Skip to content

Instantly share code, notes, and snippets.

@emabrey
Created November 16, 2024 00:49
Show Gist options
  • Save emabrey/60ced7bd66e6bc3f44a83abba7bb46a9 to your computer and use it in GitHub Desktop.
Save emabrey/60ced7bd66e6bc3f44a83abba7bb46a9 to your computer and use it in GitHub Desktop.
Script to remove TP-Link Wireless USB Device from Eject Hardware Menu
param([switch]$Elevated)
function Test-Admin {
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
$currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
function Log-Info ($msg, $color = "Blue") {
if($host.UI.RawUI.ForegroundColor -ne $null) {
Write-Host "`n[$([datetime]::Now.ToLongTimeString())] $msg" -ForegroundColor $color -BackgroundColor "Gray"
} else {
#Write-Output "`r`n[$([datetime]::Now.ToLongTimeString())] $msg"
}
}
if ((Test-Admin) -eq $false) {
if ($elevated) {
# tried to elevate, did not work, aborting
} else {
Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -noninteractive -windowstyle Hidden -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))
}
exit
}
If ($True) {
#
# Disable the 'Safely Remove Hardware and Eject Media' capability for target Plug and Play (PnP) devices
#
# Set the class/friendlyname of devices to update
$PnP_Class = "Net";
$PnP_FriendlyName = "TP-Link Wireless USB Adapter";
# Set the list of capabilities to remove (additional "capabilities bits" listed at the bottom of this script)
$RemoveCapabilities = @()
$RemoveCapabilities += 0x00000002; # CM_DEVCAP_EJECTSUPPORTED (flags the device as ejectable)
$RemoveCapabilities += 0x00000004; # CM_DEVCAP_REMOVABLE (flags the device as removable)
# Get the list of devices to remove capabilities from
Get-PnpDevice -Class "${PnP_Class}" -FriendlyName "${PnP_FriendlyName}" -Status 'OK' -EA:0 | ForEach-Object {
$InstanceId = (${_}.InstanceId);
$RegEdit = @{
Path="Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\${InstanceId}";
Name="Capabilities";
Type="DWord";
Description="Defines the capabilities for a given device. Citation [ https://github.com/tpn/winsdk-10/blob/master/Include/10.0.10240.0/um/cfgmgr32.h#L1067-L1076 ]";
};
# ------------------------------
# Parse each device in question
Write-Host "------------------------------------------------------------";
If ((Test-Path -Path (${RegEdit}.Path)) -Eq $True) {
$GetEachItemProp = (Get-ItemPropertyValue -LiteralPath (${RegEdit}.Path) -Name (${RegEdit}.Name) -ErrorAction ("Stop"));
${RegEdit}.Value = $GetEachItemProp;
# Bitwise slice off any instances of the Capability to-remove
${RemoveCapabilities} | ForEach-Object {
# Note that the bitwise AND will be zero if the value doesn't include the value to remove - it will only modify values which require an update.
${RegEdit}.Value = ((${RegEdit}.Value) - ((${RegEdit}.Value) -band ${_}));
}
If ((${GetEachItemProp}) -Eq (${RegEdit}.Value)) {
Log-Info "`nInfo: (Skipped) Registry key `"$(${RegEdit}.Path)`"'s property `"$(${RegEdit}.Name)`" is already set to value `"$(${RegEdit}.Value)`"`n";
} Else {
Log-Info "`nInfo: Setting Registry key `"$(${RegEdit}.Path)`"'s property `"$(${RegEdit}.Name)`" to value `"$(${RegEdit}.Value)`"...`n";
Set-ItemProperty -LiteralPath (${RegEdit}.Path) -Name (${RegEdit}.Name) -Value (${RegEdit}.Value);
}
Log-Info "`nInfo: Confirming value for Registry key `"$(${RegEdit}.Path)`"'s property `"$(${RegEdit}.Name)`"...";
Get-ItemProperty -LiteralPath (${RegEdit}.Path) -Name (${RegEdit}.Name);
# ------------------------------
# Repeat this process for the parent device
Write-Host "------------------------------------------------------------";
$ParentInstanceId = (Get-PnpDeviceProperty -KeyName 'DEVPKEY_Device_Parent' -InstanceId "${InstanceId}" | Select-Object -ExpandProperty "Data" -EA:0);
$RegEditParent = @{
Path="Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\${ParentInstanceId}";
Name="Capabilities";
Type="DWord";
Description="Defines the capabilities for a given device. Citation [ https://github.com/tpn/winsdk-10/blob/master/Include/10.0.10240.0/um/cfgmgr32.h#L1067-L1076 ]";
};
If ((Test-Path -Path (${RegEditParent}.Path)) -Eq $True) {
$GetEachParentItemProp = (Get-ItemPropertyValue -LiteralPath (${RegEditParent}.Path) -Name (${RegEditParent}.Name) -ErrorAction ("Stop"));
${RegEditParent}.Value = $GetEachItemProp;
# Bitwise slice off any instances of the Capability to-remove
${RemoveCapabilities} | ForEach-Object {
# Note that the bitwise AND will be zero if the value doesn't include the value to remove - it will only modify values which require an update.
${RegEditParent}.Value = ((${RegEditParent}.Value) - ((${RegEditParent}.Value) -band ${_}));
}
If ((${GetEachParentItemProp}) -Eq (${RegEditParent}.Value)) {
Log-Info "`nInfo: (Skipped) Registry key `"$(${RegEditParent}.Path)`"'s property `"$(${RegEditParent}.Name)`" is already set to value `"$(${RegEditParent}.Value)`"`n";
} Else {
Log-Info "`nInfo: Setting Registry key `"$(${RegEditParent}.Path)`"'s property `"$(${RegEditParent}.Name)`" to value `"$(${RegEditParent}.Value)`"...`n";
Set-ItemProperty -LiteralPath (${RegEditParent}.Path) -Name (${RegEditParent}.Name) -Value (${RegEditParent}.Value);
}
Log-Info "`nInfo: Confirming value for Registry key `"$(${RegEditParent}.Path)`"'s property `"$(${RegEditParent}.Name)`"...";
Get-ItemProperty -LiteralPath (${RegEditParent}.Path) -Name (${RegEditParent}.Name);
} Else {
Log-Info "`nInfo: (Skipped) Registry key `"$(${RegEditParent}.Path)`" not found to exist`n";
}
# End of parent device handling
# ------------------------------
} Else {
Log-Info "`nInfo: (Skipped) Registry key `"$(${RegEdit}.Path)`" not found to exist`n";
}
}
}
#Restart explorer
$class = [wmiclass]"\root\cimv2:win32_process"
Get-WmiObject -Class Win32_Process -Filter "Name='explorer.exe'" -OutVariable Process |
Where-Object { $_.GetOwner().User -ne 'Administrator' } |
Foreach-Object { $_.Terminate()}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment