Here is the code for Windows 7 x86.
It's different from the previous code, so be careful when you use a different version of Windows.
feature of Windows before running. Otherwise, when enabling the disabled device again and ejecting it, it will not be ejected, saying that the device is in use.
This is because an explorer window related to the AutoPlay is opened.
Alternatively, there is a way to prevent the AutoPlay using the "QueryCancelAutoPlay" window message, so try searching.
A foreground window is essential to process the message.
Since the "USB Root Hub" device is manipulated when reconnecting, it may affect other associated devices.
There is something missing in the code.
When disabling a device, enumerate the child "storage" devices of the device to see if there is any device you want to disable.
Code: Select all
#CR_SUCCESS = 0
#CR_NO_SUCH_DEVNODE = $0d
#CR_NO_SUCH_DEVINST = #CR_NO_SUCH_DEVNODE
#DN_HAS_PROBLEM = $00000400
#DN_DRIVER_LOADED = $00000002 ;Has Register_Device_Driver
#DN_STARTED = $00000008 ;Is currently configured
#CM_PROB_DISABLED = $00000016 ;devinst is disabled
#CM_PROB_HELD_FOR_EJECT = $0000002F ;The device is offline awaiting removal
#CM_LOCATE_DEVNODE_NORMAL = 0
#MAX_CLASS_NAME_LEN = 32
#MAX_DEV_NAME_LEN = 512
#SPDRP_HARDWAREID = 1
#SPDRP_SERVICE = 4
#SPDRP_FRIENDLYNAME = $0C
#SPDRP_ENUMERATOR_NAME = $16
#SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = $0E
#APPLICATION_ERROR_MASK = $20000000
#ERROR_SEVERITY_ERROR = $C0000000
#ERROR_IN_WOW64 = #APPLICATION_ERROR_MASK | #ERROR_SEVERITY_ERROR | $235 ;$E0000235
#ERROR_NO_SUCH_DEVINST = #APPLICATION_ERROR_MASK | #ERROR_SEVERITY_ERROR | $20B ;$E000020B
#CM_REENUMERATE_NORMAL = 0
#CM_REENUMERATE_SYNCHRONOUS = 1
#CM_REENUMERATE_RETRY_INSTALLATION = 2
#CM_REENUMERATE_ASYNCHRONOUS = 4
#CM_SETUP_DEVNODE_READY = 0 ;Reenable problem devinst
#CM_SETUP_DEVNODE_RESET = 4 ;Reset problem devinst without starting
#CM_DISABLE_POLITE = 0 ;Ask the driver
#CM_DISABLE_ABSOLUTE = 1 ;Don't ask the driver
#CM_DISABLE_HARDWARE = 2 ;Don't ask the driver, and won't be restarteable
#CM_DISABLE_UI_NOT_OK = 4 ;Don't popup any veto API
#CM_DISABLE_PERSIST = 8 ;Persists through restart by setting CONFIGFLAG_DISABLED in the registry
#DICS_ENABLE = 1
#DICS_DISABLE = 2
#DICS_PROPCHANGE = 3
#DICS_START = 4
#DICS_STOP = 5
#DICS_FLAG_GLOBAL = 1 ;// make change in all hardware profiles
#DICS_FLAG_CONFIGSPECIFIC = 2 ;// make change in specified profile only
#DICS_FLAG_CONFIGGENERAL = 4 ;// 1 or more hardware profile-specific changes to follow.
#DIF_PROPERTYCHANGE = $12
Structure SP_CLASSINSTALL_HEADER
cbSize.l
InstallFunction.l
EndStructure
Structure SP_PROPCHANGE_PARAMS
ClassInstallHeader.SP_CLASSINSTALL_HEADER
StateChange.l
Scope.l
HwProfile.l
EndStructure
Structure SP_DEVICE_INTERFACE_DETAIL_DATA
cbSize.l
DevicePath.s{512}
EndStructure
Structure SP_DEVINFO_DATA
cbSize.l
ClassGuid.GUID
DevInst.l
*reserved
EndStructure
Prototype ptCM_Get_Device_IDW(DevInst.l, *DeviceIdString, BufferLen.l, Flags.l)
Prototype ptCM_Get_Parent(*DevInst, DevInst.l, Flags)
Prototype ptCM_Locate_DevNodeW(*DevInst, *pDeviceID, ulFlags.l)
Prototype ptCM_Get_Child(*DevInst, DevInst, ulFlags.l)
Prototype ptCM_Request_Device_Eject_ExW(DevInst.l, *VetoType, VetoName.s, NameLength.l, Flags.l, hMachine)
Prototype ptCM_Get_DevNode_Status(*Status, *ProblemNumber, dnDevInst.l, ulFlags.l)
Prototype ptSetupDiSetClassInstallParamsW(DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize.l)
Prototype ptSetupDiCallClassInstaller(InstallFunction, DeviceInfoSet, DeviceInfoData)
Prototype ptCM_Disable_DevNode(DevInst, ulFlags.l)
Prototype ptCM_Enable_DevNode(DevInst, ulFlags.l)
Prototype ptCM_Reenumerate_DevNode(DevInst, ulFlags.l)
Prototype ptCM_Get_Sibling(*DevInst, DevInst, ulFlags.l)
Global CM_Get_Sibling.ptCM_Get_Sibling
Global CM_Get_Child.ptCM_Get_Child
Global SetupDiCallClassInstaller.ptSetupDiCallClassInstaller
Global SetupDiSetClassInstallParams.ptSetupDiSetClassInstallParamsW
Global CM_Reenumerate_DevNode.ptCM_Reenumerate_DevNode
Global CM_Disable_DevNode.ptCM_Disable_DevNode
Global CM_Enable_DevNode.ptCM_Enable_DevNode
Global CM_Get_DevNode_Status.ptCM_Get_DevNode_Status
Global CM_Request_Device_Eject.ptCM_Request_Device_Eject_ExW
Global CM_Locate_DevNode.ptCM_Locate_DevNodeW
Global CM_Get_Parent.ptCM_Get_Parent
Global CM_Get_Device_ID.ptCM_Get_Device_IDW
Define setupapi
setupapi = OpenLibrary(#PB_Any, "setupapi.dll")
If setupapi
CM_Get_Device_ID = GetFunction(setupapi, "CM_Get_Device_IDW")
CM_Get_Parent = GetFunction(setupapi, "CM_Get_Parent")
CM_Get_Child = GetFunction(setupapi, "CM_Get_Child")
CM_Get_Sibling = GetFunction(setupapi, "CM_Get_Sibling")
CM_Locate_DevNode = GetFunction(setupapi, "CM_Locate_DevNodeW")
CM_Request_Device_Eject = GetFunction(setupapi, "CM_Request_Device_Eject_ExW")
CM_Get_DevNode_Status = GetFunction(setupapi, "CM_Get_DevNode_Status")
SetupDiSetClassInstallParams = GetFunction(setupapi, "SetupDiSetClassInstallParamsW")
SetupDiCallClassInstaller = GetFunction(setupapi, "SetupDiCallClassInstaller")
CM_Enable_DevNode = GetFunction(setupapi, "CM_Enable_DevNode")
CM_Disable_DevNode = GetFunction(setupapi, "CM_Disable_DevNode")
CM_Reenumerate_DevNode = GetFunction(setupapi, "CM_Reenumerate_DevNode")
Else
MessageRequester("Error", "Can't open library setupapi.dll")
End
EndIf
Define Index, ChildIndex, cbRequired
Define spdid.SP_DEVICE_INTERFACE_DATA
Define spdidChild.SP_DEVICE_INTERFACE_DATA
Define spdidd.SP_DEVICE_INTERFACE_DETAIL_DATA
Define spdiddChild.SP_DEVICE_INTERFACE_DETAIL_DATA
Define spdd.SP_DEVINFO_DATA
Define spddChild.SP_DEVINFO_DATA
Define sppp.SP_PROPCHANGE_PARAMS
Define hDevInfo, hChildDevInfo
Define *pGUID = ?GUID_DEVINTERFACE_USB_DEVICE
Define Buffer.s{512}
Define ParentDeviceInstID.s{512}
Define sdn.STORAGE_DEVICE_NUMBER
Define Status, StatusParent
;- Flags for test
Enumeration
#Test_Mode___Disable_USB
#Test_Mode___Enable_and_Eject_USB
#Test_Mode___Reconnect_USB
EndEnumeration
;- Set a flag !
#Test_Mode = #Test_Mode___Disable_USB
CompilerSelect #Test_Mode
CompilerCase #Test_Mode___Disable_USB
hDevInfo = SetupDiGetClassDevs_(*pGUID, #Null, #Null, #DIGCF_PRESENT | #DIGCF_DEVICEINTERFACE)
CompilerCase #Test_Mode___Enable_and_Eject_USB
hDevInfo = SetupDiGetClassDevs_(*pGUID, #Null, #Null, #DIGCF_DEVICEINTERFACE)
CompilerCase #Test_Mode___Reconnect_USB
hDevInfo = SetupDiGetClassDevs_(*pGUID, #Null, #Null, #DIGCF_DEVICEINTERFACE)
CompilerDefault
End
CompilerEndSelect
If hDevInfo = #INVALID_HANDLE_VALUE
MessageRequester("Error", "Inavlid handle value")
End
EndIf
spdid\cbSize = SizeOf(SP_DEVICE_INTERFACE_DATA)
While SetupDiEnumDeviceInterfaces_(hDevInfo, 0, *pGUID, Index, @spdid)
SetupDiGetDeviceInterfaceDetail_(hDevInfo, @spdid, 0, 0, @cbRequired, 0)
If cbRequired > 0 And cbRequired < 511
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
spdidd\cbSize = 8 ; x86(Unicode=6, ASCII=5), x64=8
CompilerElse
spdidd\cbSize = 4 + SizeOf(Character) ; x86(Unicode=6, ASCII=5), x64=8
CompilerEndIf
spdd\cbSize = SizeOf(SP_DEVINFO_DATA)
If SetupDiGetDeviceInterfaceDetail_(hDevInfo, @spdid, @spdidd, cbRequired, 0, @spdd)
Debug "DevicePath: " + spdidd\DevicePath
Debug "DevInst: " + spdd\DevInst
If FindString(spdidd\DevicePath, "USB", 1, #PB_String_NoCase)
If CM_Get_Parent(@DevInstParent, spdd\DevInst, 0) = #CR_SUCCESS
Debug "Parent DevInst: " + DevInstParent
EndIf
If CM_Get_Device_ID(DevInstParent, @ParentDeviceInstID, 511, 0) = #CR_SUCCESS
Debug "Parent Device instance ID: " + ParentDeviceInstID
EndIf
If CM_Get_Child(@DevInstChild, spdd\DevInst, 0) = #CR_SUCCESS
Debug "Child DevInst: " + DevInstChild
EndIf
If CM_Get_Device_ID(DevInstChild, @Buffer, 511, 0) = #CR_SUCCESS
Debug "Child Device instance ID: " + Buffer
EndIf
If CM_Get_DevNode_Status(@StatusParent, @ProblemNumber, DevInstParent, 0) = #CR_SUCCESS
Debug " DN_STARTED: " + Bool(StatusParent & #DN_STARTED)
Debug " DN_DRIVER_LOADED: " + Bool(StatusParent & #DN_DRIVER_LOADED)
Debug "*** Child ***"
Debug "DevicePath: " + spdidd\DevicePath
Debug "DevInst: " + spdd\DevInst
If CM_Get_DevNode_Status(@Status, @ProblemNumber, spdd\DevInst, 0) = #CR_SUCCESS
Debug " DN_STARTED: " + Bool(Status & #DN_STARTED)
Debug " DN_DRIVER_LOADED: " + Bool(Status & #DN_DRIVER_LOADED)
EndIf
CM_Get_Device_ID(spdd\DevInst, @Buffer, 511, 0)
Debug "Device instance ID: " + Buffer
CM_Locate_DevNode(@id, @Buffer, #CM_LOCATE_DEVNODE_NORMAL)
Debug "DevInst: " + id
SetupDiGetDeviceRegistryProperty_(hDevInfo, @spdd, #SPDRP_FRIENDLYNAME, 0, @Buffer, 1024, 0)
Debug "Friendly name: " + Buffer
SetupDiGetDeviceRegistryProperty_(hDevInfo, @spdd, #SPDRP_ENUMERATOR_NAME, 0, @Buffer, 1024, 0)
Debug "SPDRP_ENUMERATOR_NAME: " + Buffer
SetupDiGetDeviceRegistryProperty_(hDevInfo, @spdd, #SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, 0, @Buffer, 1024, 0)
Debug "SPDRP_PHYSICAL_DEVICE_OBJECT_NAME: " + Buffer
SetupDiGetDeviceRegistryProperty_(hDevInfo, @spdd, #SPDRP_HARDWAREID, 0, @Buffer, 1024, 0)
Debug "SPDRP_HARDWAREID: "
Debug Buffer
StrLength = StringByteLength(Buffer)
*p = @Buffer + StrLength + 2
While PeekC(*p)
s.s = PeekS(*p)
Debug s
StrLength = StringByteLength(s)
*p + StrLength + 2
Wend
Debug ""
CompilerSelect #Test_Mode
CompilerCase #Test_Mode___Disable_USB
Debug "****** Disable USB"
Found = 0
If CM_Get_Child(@DevInstChild, spdd\DevInst, 0) = #CR_SUCCESS
Debug "Child DevInst: " + DevInstChild
If CM_Get_Device_ID(DevInstChild, @Buffer, 511, 0) = #CR_SUCCESS
Debug "Child Device instance ID: " + Buffer
Found = 1
While Not (FindString(Buffer, "USBSTOR", 1, #PB_String_NoCase) And FindString(Buffer, "DISK", 1, #PB_String_NoCase))
If CM_Get_Sibling(@DevInstChild, DevInstChild, 0) = #CR_SUCCESS
Debug "Sibling DevInst: " + DevInstChild
If CM_Get_Device_ID(DevInstChild, @Buffer, 511, 0) = #CR_SUCCESS
Debug "Sibling Device instance ID: " + Buffer
EndIf
Else
Debug " *** No storage devices were found."
Found = 0
Break
EndIf
Wend
EndIf
EndIf
If Found
If CM_Disable_DevNode(spdd\DevInst, #CM_DISABLE_UI_NOT_OK) = #CR_SUCCESS
Debug " The device is disabled."
Break
EndIf
EndIf
CompilerCase #Test_Mode___Enable_and_Eject_USB
Debug "****** Enable and Eject USB"
If Status & #DN_HAS_PROBLEM And ProblemNumber = #CM_PROB_DISABLED
Debug " The device is currently disabled."
If CM_Enable_DevNode(spdd\DevInst, 0) = #CR_SUCCESS
CM_Reenumerate_DevNode(spdd\DevInst, #CM_REENUMERATE_SYNCHRONOUS | #CM_REENUMERATE_RETRY_INSTALLATION)
Debug " The device is enabled."
Delay(1500)
EndIf
EndIf
If CM_Get_Child(@DevInstChild, spdd\DevInst, 0) = #CR_SUCCESS
Debug "Child DevInst: " + DevInstChild
If CM_Get_Device_ID(DevInstChild, @Buffer, 511, 0) = #CR_SUCCESS
Debug "Child Device instance ID: " + Buffer
Found = 1
While Not (FindString(Buffer, "USBSTOR", 1, #PB_String_NoCase) And FindString(Buffer, "DISK", 1, #PB_String_NoCase))
If CM_Get_Sibling(@DevInstChild, DevInstChild, 0) = #CR_SUCCESS
Debug "Sibling DevInst: " + DevInstChild
If CM_Get_Device_ID(DevInstChild, @Buffer, 511, 0) = #CR_SUCCESS
Debug "Sibling Device instance ID: " + Buffer
EndIf
Else
Found = 0
Break
EndIf
Wend
If Found
hChildDevInfo = SetupDiGetClassDevs_(?GUID_DEVINTERFACE_DISK, @Buffer, #Null, #DIGCF_PRESENT | #DIGCF_DEVICEINTERFACE)
If hChildDevInfo <> #INVALID_HANDLE_VALUE
spdidChild\cbSize = SizeOf(SP_DEVICE_INTERFACE_DATA)
While SetupDiEnumDeviceInterfaces_(hChildDevInfo, 0, ?GUID_DEVINTERFACE_DISK, ChildIndex, @spdidChild)
SetupDiGetDeviceInterfaceDetail_(hChildDevInfo, @spdidChild, 0, 0, @cbRequired, 0)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
spdiddChild\cbSize = 8 ; x86(Unicode=6, ASCII=5), x64=8
CompilerElse
spdiddChild\cbSize = 4 + SizeOf(Character) ; x86(Unicode=6, ASCII=5), x64=8
CompilerEndIf
spddChild\cbSize = SizeOf(SP_DEVINFO_DATA)
If cbRequired > 0 And cbRequired < 511
If SetupDiGetDeviceInterfaceDetail_(hChildDevInfo, @spdidChild, @spdiddChild, cbRequired, 0, @spddChild)
hUSB = CreateFile_(@spdiddChild\DevicePath, 0, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, 0, #Null)
If hUSB <> #INVALID_HANDLE_VALUE
If DeviceIoControl_(hUSB, #IOCTL_STORAGE_GET_DEVICE_NUMBER, 0, 0, @sdn, SizeOf(STORAGE_DEVICE_NUMBER), @BytesReturned, 0)
If sdn\DeviceNumber ;= DeviceNumber
CloseHandle_(hUSB)
CM_Request_Device_Eject(spdd\DevInst, #Null, #Null$, #Null, #Null, #Null)
Debug " Eject done."
Break
EndIf
EndIf
CloseHandle_(hUSB)
EndIf
EndIf
EndIf
ChildIndex + 1
Wend
SetupDiDestroyDeviceInfoList_(hChildDevInfo)
EndIf
EndIf
EndIf
EndIf
CompilerCase #Test_Mode___Reconnect_USB
Debug "****** Reconnect USB"
If Status & #DN_HAS_PROBLEM And ProblemNumber = #CM_PROB_HELD_FOR_EJECT
Debug " The device is not physically removed."
If FindString(ParentDeviceInstID, "HUB", 1, #PB_String_NoCase)
If CM_Disable_DevNode(DevInstParent, #CM_DISABLE_UI_NOT_OK) = #CR_SUCCESS
If CM_Enable_DevNode(DevInstParent, 0) = #CR_SUCCESS
CM_Reenumerate_DevNode(DevInstParent, #CM_REENUMERATE_SYNCHRONOUS | #CM_REENUMERATE_RETRY_INSTALLATION)
Debug " The device reconnected."
Break
EndIf
EndIf
EndIf
EndIf
CompilerEndSelect
EndIf
Debug "----------------------------------------------------------------------------------"
EndIf
EndIf
EndIf
Index + 1
Wend
SetupDiDestroyDeviceInfoList_(hDevInfo)
CloseLibrary(setupapi)
DataSection
GUID_DEVINTERFACE_USB_DEVICE:
Data.l $A5DCBF10
Data.w $6530, $11D2
Data.b $90, $1F, $00, $C0, $4F, $B9, $51, $ED
GUID_DEVINTERFACE_DISK:
Data.l $53f56307
Data.w $b6bf, $11d0
Data.b $94, $f2, $00, $a0, $c9, $1e, $fb, $8b
EndDataSection