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