unit U_USB; interface uses Windows, SysUtils, Variants, Classes, ShellApi, Forms, ioctl; const MAX_PATH = 260; ANYSIZE_ARRAY = 1; SetupApiModuleName = 'SetupApi.dll'; setupapi = 'SetupApi.dll'; DIGCF_PRESENT = $00000002; DIGCF_DEVICEINTERFACE = $00000010; GUID_CLASS_USBHUB:TGUID='{f18a0e88-c30c-11d0-8815-00a0c906bed8}'; GUID_CLASS_USB_DEVICE:TGUID='{A5DCBF10-6530-11D2-901F-00C04FB951ED}'; GUID_CLASS_USB_HOST_CONTROLLER:TGUID='{3ABF6F2D-71C4-462a-8A92-1E6861E6AF27}'; GUID_DEVINTERFACE_VOLUME:TGUID='{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}'; GUID_DEVINTERFACE_DISK:TGUID='{53f56307-b6bf-11d0-94f2-00a0c91efb8b}'; GUID_DEVCLASS_DISKDRIVE: TGUID = (D1: $4D36E967; D2: $E325; D3: $11CE; D4: ($BF, $C1, $08, $00, $2B, $E1, $03, $18)); SPDRP_DEVICEDESC = $00000000; // DeviceDesc (R/W) {$EXTERNALSYM SPDRP_DEVICEDESC} SPDRP_HARDWAREID = $00000001; // HardwareID (R/W) {$EXTERNALSYM SPDRP_HARDWAREID} SPDRP_COMPATIBLEIDS = $00000002; // CompatibleIDs (R/W) {$EXTERNALSYM SPDRP_COMPATIBLEIDS} SPDRP_UNUSED0 = $00000003; // unused {$EXTERNALSYM SPDRP_UNUSED0} SPDRP_SERVICE = $00000004; // Service (R/W) {$EXTERNALSYM SPDRP_SERVICE} SPDRP_UNUSED1 = $00000005; // unused {$EXTERNALSYM SPDRP_UNUSED1} SPDRP_UNUSED2 = $00000006; // unused {$EXTERNALSYM SPDRP_UNUSED2} SPDRP_CLASS = $00000007; // Class (R--tied to ClassGUID) {$EXTERNALSYM SPDRP_CLASS} SPDRP_CLASSGUID = $00000008; // ClassGUID (R/W) {$EXTERNALSYM SPDRP_CLASSGUID} SPDRP_DRIVER = $00000009; // Driver (R/W) {$EXTERNALSYM SPDRP_DRIVER} SPDRP_CONFIGFLAGS = $0000000A; // ConfigFlags (R/W) {$EXTERNALSYM SPDRP_CONFIGFLAGS} SPDRP_MFG = $0000000B; // Mfg (R/W) {$EXTERNALSYM SPDRP_MFG} SPDRP_FRIENDLYNAME = $0000000C; // FriendlyName (R/W) {$EXTERNALSYM SPDRP_FRIENDLYNAME} SPDRP_LOCATION_INFORMATION = $0000000D; // LocationInformation (R/W) {$EXTERNALSYM SPDRP_LOCATION_INFORMATION} SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = $0000000E; // PhysicalDeviceObjectName (R) {$EXTERNALSYM SPDRP_PHYSICAL_DEVICE_OBJECT_NAME} SPDRP_CAPABILITIES = $0000000F; // Capabilities (R) {$EXTERNALSYM SPDRP_CAPABILITIES} SPDRP_UI_NUMBER = $00000010; // UiNumber (R) {$EXTERNALSYM SPDRP_UI_NUMBER} SPDRP_UPPERFILTERS = $00000011; // UpperFilters (R/W) {$EXTERNALSYM SPDRP_UPPERFILTERS} SPDRP_LOWERFILTERS = $00000012; // LowerFilters (R/W) {$EXTERNALSYM SPDRP_LOWERFILTERS} SPDRP_BUSTYPEGUID = $00000013; // BusTypeGUID (R) {$EXTERNALSYM SPDRP_BUSTYPEGUID} SPDRP_LEGACYBUSTYPE = $00000014; // LegacyBusType (R) {$EXTERNALSYM SPDRP_LEGACYBUSTYPE} SPDRP_BUSNUMBER = $00000015; // BusNumber (R) {$EXTERNALSYM SPDRP_BUSNUMBER} SPDRP_ENUMERATOR_NAME = $00000016; // Enumerator Name (R) {$EXTERNALSYM SPDRP_ENUMERATOR_NAME} SPDRP_SECURITY = $00000017; // Security (R/W, binary form) {$EXTERNALSYM SPDRP_SECURITY} SPDRP_SECURITY_SDS = $00000018; // Security (W, SDS form) {$EXTERNALSYM SPDRP_SECURITY_SDS} SPDRP_DEVTYPE = $00000019; // Device Type (R/W) {$EXTERNALSYM SPDRP_DEVTYPE} SPDRP_EXCLUSIVE = $0000001A; // Device is exclusive-access (R/W) {$EXTERNALSYM SPDRP_EXCLUSIVE} SPDRP_CHARACTERISTICS = $0000001B; // Device Characteristics (R/W) {$EXTERNALSYM SPDRP_CHARACTERISTICS} SPDRP_ADDRESS = $0000001C; // Device Address (R) {$EXTERNALSYM SPDRP_ADDRESS} {$IFDEF WINXP_UP} SPDRP_UI_NUMBER_DESC_FORMAT = $0000001D; // UiNumberDescFormat (R/W) {$EXTERNALSYM SPDRP_UI_NUMBER_DESC_FORMAT} SPDRP_DEVICE_POWER_DATA = $0000001E; // Device Power Data (R) {$EXTERNALSYM SPDRP_DEVICE_POWER_DATA} SPDRP_REMOVAL_POLICY = $0000001F; // Removal Policy (R) {$EXTERNALSYM SPDRP_REMOVAL_POLICY} SPDRP_REMOVAL_POLICY_HW_DEFAULT = $00000020; // Hardware Removal Policy (R) {$EXTERNALSYM SPDRP_REMOVAL_POLICY_HW_DEFAULT} SPDRP_REMOVAL_POLICY_OVERRIDE = $00000021; // Removal Policy Override (RW) {$EXTERNALSYM SPDRP_REMOVAL_POLICY_OVERRIDE} SPDRP_INSTALL_STATE = $00000022; // Device Install State (R) {$EXTERNALSYM SPDRP_INSTALL_STATE} SPDRP_MAXIMUM_PROPERTY = $00000023; // Upper bound on ordinals {$EXTERNALSYM SPDRP_MAXIMUM_PROPERTY} {$ELSE} SPDRP_UI_NUMBER_DESC_FORMAT = $0000001E; // UiNumberDescFormat (R/W) {$EXTERNALSYM SPDRP_UI_NUMBER_DESC_FORMAT} SPDRP_MAXIMUM_PROPERTY = $0000001F; // Upper bound on ordinals {$EXTERNALSYM SPDRP_MAXIMUM_PROPERTY} {$ENDIF WINXP_UP} SPCRP_SECURITY = $00000017; // Security (R/W, binary form) {$EXTERNALSYM SPCRP_SECURITY} SPCRP_SECURITY_SDS = $00000018; // Security (W, SDS form) {$EXTERNALSYM SPCRP_SECURITY_SDS} SPCRP_DEVTYPE = $00000019; // Device Type (R/W) {$EXTERNALSYM SPCRP_DEVTYPE} SPCRP_EXCLUSIVE = $0000001A; // Device is exclusive-access (R/W) {$EXTERNALSYM SPCRP_EXCLUSIVE} SPCRP_CHARACTERISTICS = $0000001B; // Device Characteristics (R/W) {$EXTERNALSYM SPCRP_CHARACTERISTICS} SPCRP_MAXIMUM_PROPERTY = $0000001C; // Upper bound on ordinals {$EXTERNALSYM SPCRP_MAXIMUM_PROPERTY} type HDEVINFO = Pointer; PSP_DEVINFO_DATA = ^SP_DEVINFO_DATA; PSPDevInfoData = ^TSPDevInfoData; SP_DEVINFO_DATA = packed record cbSize: DWORD; ClassGuid: TGUID; DevInst: DWORD; Reserved: DWORD; end; TSPDevInfoData = SP_DEVINFO_DATA; PSTORAGE_DEVICE_NUMBER = ^STORAGE_DEVICE_NUMBER; STORAGE_DEVICE_NUMBER = packed record DeviceType: DWORD; DeviceNumber: Longint; PartitionNumber: Longint; end; TSTORAGE_DEVICE_NUMBER = STORAGE_DEVICE_NUMBER; type PSPDeviceInterfaceData = ^TSPDeviceInterfaceData; SP_DEVICE_INTERFACE_DATA = packed record cbSize: DWORD; InterfaceClassGuid: TGUID; Flags: DWORD; Reserved: DWORD; end; TSPDeviceInterfaceData = SP_DEVICE_INTERFACE_DATA; type PSPDeviceInterfaceDetailData = ^TSPDeviceInterfaceDetailData; SP_DEVICE_INTERFACE_DETAIL_DATA_A = packed record cbSize: DWORD; DevicePath: array [0..ANYSIZE_ARRAY - 1] of AnsiChar; end; TSPDeviceInterfaceDetailData = SP_DEVICE_INTERFACE_DETAIL_DATA_A; TUSBDev = class(TObject) private public FDeviceID: DWORD; FDevicePath: string; FCapabilities: DWORD; FClassDescr: string; FClassGUID: string; FCompatibleIDs: TStringList; FConfigFlags: DWORD; FDeviceDescr: string; FDriver: string; FFriendlyName: string; FHardwareID: TStringList; FLowerFilters: TStringList; FMfg: string; FUpperFilters: TStringList; FAddress: string; FBusNumber: DWORD; FBusType: string; FCharacteristics: string; FDevType: DWORD; FEnumeratorName: string; FExclusive: DWORD; FLegacyBusType: DWORD; FLocationInfo: string; FPhysDevObjName: string; FSecuritySDS: string; FService: string; FUINumber: DWORD; FUINumberFormat: string; FDevData: TSPDevInfoData; FPnPHandle: HDEVINFO; constructor Create; procedure GetInfoForDev(APnPHandle: HDEVINFO; ADevData: TSPDevInfoData; ADevicePath: PChar); function GetRegistryPropertyDWord(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): DWORD; function GetRegistryPropertyString(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): string; function GetRegistryPropertyStringList(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): TStringList; end; function GetTempDir: string; function GetDevNum(aPath: string): LongInt; function USBDeviceFind(GUID:TGUID; aPhysDevObjName: string): TUSBDev; function GetDEVID(aDevPath: string): string; function IsRemoveable(aDevPath: string): Boolean; procedure EjectDrive(aDrive: string); procedure SelfRemoteEject; implementation function SetupDiGetDeviceRegistryProperty(DeviceInfoSet: HDEVINFO; const DeviceInfoData: TSPDevInfoData; Property_: DWORD; var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSize: DWORD; var RequiredSize: DWORD): LongBool; stdcall; external SetupApiModuleName name 'SetupDiGetDeviceRegistryPropertyA'; function SetupDiGetClassDevs(ClassGuid: PGUID; const Enumerator: PAnsiChar; hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall; external SetupApiModuleName name 'SetupDiGetClassDevsA'; function SetupDiEnumDeviceInfo(DeviceInfoSet: HDEVINFO; MemberIndex: DWORD; var DeviceInfoData: TSPDevInfoData): LongBool; stdcall; external SetupApiModuleName name 'SetupDiEnumDeviceInfo'; function SetupDiEnumDeviceInterfaces(DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData; const InterfaceClassGuid: TGUID; MemberIndex: DWORD; var DeviceInterfaceData: TSPDeviceInterfaceData): LongBool; stdcall; external SetupApiModuleName name 'SetupDiEnumDeviceInterfaces'; function SetupDiGetDeviceInterfaceDetail(DeviceInfoSet: HDEVINFO; DeviceInterfaceData: PSPDeviceInterfaceData; DeviceInterfaceDetailData: PSPDeviceInterfaceDetailData; DeviceInterfaceDetailDataSize: DWORD; var RequiredSize: DWORD; Device: PSPDevInfoData): LongBool; stdcall; external SetupApiModuleName name 'SetupDiGetDeviceInterfaceDetailA'; //function GetVolumeNameForVolumeMountPoint(volumeName: string; // uniqueVolumeName: PChar; // uniqueNameBufferCapacity: integer): LongBool; stdcall; external 'kernel32.dll' name 'GetVolumeNameForVolumeMountPointA'; function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): LongBool; stdcall; external SetupApiModuleName name 'SetupDiDestroyDeviceInfoList'; function GetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint: LPCSTR; lpszVolumeName: LPSTR; cchBufferLength: DWORD): BOOL; stdcall; external 'kernel32.dll' name 'GetVolumeNameForVolumeMountPointA'; function CM_Get_Parent(pdnDevInst: PDWORD; dnDevInst: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi; function CM_Get_Device_ID_Size(pulLen: PDWORD; dnDevInst: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi; function CM_Get_Device_IDA(dnDevInst: DWORD; Buffer: PChar; BufferLen: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi; function CM_Locate_DevNodeA(pdnDevInst: PDWORD; pDeviceID: PChar; ulFlags: DWORD): DWORD; stdcall; external setupapi; function CM_Request_Device_EjectA(dnDevInst: DWORD; pVetoType: Pointer; pszVetoName: PChar; ulNameLength: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi; function CM_Query_And_Remove_SubTree(dnDevInst: DWORD; pVetoType: Pointer; pszVetoName: PChar; ulNameLength: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi name 'CM_Query_And_Remove_SubTreeA'; { TUSBDev } constructor TUSBDev.Create; begin inherited; end; procedure TUSBDev.GetInfoForDev(APnPHandle: HDEVINFO; ADevData: TSPDevInfoData; ADevicePath: PChar); begin FDeviceID := ADevData.DevInst; FDevicePath := ADevicePath; FDevData := ADevData; FPnPHandle := APnPHandle; // primary information FCapabilities := GetRegistryPropertyDWord(APnPHandle, ADevData, SPDRP_CAPABILITIES); FClassDescr := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_CLASS); FClassGUID := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_CLASSGUID); FCompatibleIDs := GetRegistryPropertyStringList(APnPHandle, ADevData, SPDRP_COMPATIBLEIDS); FConfigFlags := GetRegistryPropertyDWord(APnPHandle, ADevData, SPDRP_CONFIGFLAGS); FDeviceDescr := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_DEVICEDESC); FDriver := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_DRIVER); FFriendlyName := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_FRIENDLYNAME); FHardwareID := GetRegistryPropertyStringList(APnPHandle, ADevData, SPDRP_HARDWAREID); FLowerFilters := GetRegistryPropertyStringList(APnPHandle, ADevData, SPDRP_LOWERFILTERS); FMfg := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_MFG); FUpperFilters := GetRegistryPropertyStringList(APnPHandle, ADevData, SPDRP_UPPERFILTERS); FService := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_SERVICE); // secondary information not all likely to exist for a HID device FAddress := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_ADDRESS); FBusNumber := GetRegistryPropertyDWord(APnPHandle, ADevData, SPDRP_BUSNUMBER); FBusType := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_BUSTYPEGUID); FCharacteristics := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_CHARACTERISTICS); FDevType := GetRegistryPropertyDWord(APnPHandle, ADevData, SPDRP_DEVTYPE); FEnumeratorName := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_ENUMERATOR_NAME); FExclusive := GetRegistryPropertyDWord(APnPHandle, ADevData, SPDRP_EXCLUSIVE); FLegacyBusType := GetRegistryPropertyDWord(APnPHandle, ADevData, SPDRP_LEGACYBUSTYPE); FLocationInfo := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_LOCATION_INFORMATION); FPhysDevObjName := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME); FSecuritySDS := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_SECURITY_SDS); FUINumber := GetRegistryPropertyDWord(APnPHandle, ADevData, SPDRP_UI_NUMBER); FUINumberFormat := GetRegistryPropertyString(APnPHandle, ADevData, SPDRP_UI_NUMBER_DESC_FORMAT); end; function TUSBDev.GetRegistryPropertyDWord(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): DWORD; var BytesReturned: DWORD; RegDataType: DWORD; begin BytesReturned := 0; RegDataType := 0; Result := 0; SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, Prop, RegDataType, PBYTE(@Result), SizeOf(Result), BytesReturned); end; function TUSBDev.GetRegistryPropertyString(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): string; var BytesReturned: DWORD; RegDataType: DWORD; Buffer: array [0..1023] of Char; begin BytesReturned := 0; RegDataType := 0; Buffer[0] := #0; SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, Prop, RegDataType, PByte(@Buffer[0]), SizeOf(Buffer), BytesReturned); Result := Buffer; end; function TUSBDev.GetRegistryPropertyStringList(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData; Prop: DWORD): TStringList; var BytesReturned: DWORD; RegDataType: DWORD; Buffer: array [0..16383] of Char; P: PChar; begin BytesReturned := 0; RegDataType := 0; Buffer[0] := #0; SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, Prop, RegDataType, PBYTE(@Buffer[0]), SizeOf(Buffer), BytesReturned); Result := TStringList.Create; P := @Buffer[0]; while P[0] <> #0 do begin Result.Add(P); P := P + StrLen(P) + 1; end; end; function GetTempDir: string; var buff: pchar; s: string; begin getmem(buff, 1255); s := ''; if (GetEnvironmentVariable('tmp', buff, 1254) > 0) and (DirectoryExists(buff)) then begin s := buff; end else if (GetEnvironmentVariable('temp',buff, 1254) >0) and (DirectoryExists(buff)) then begin s := buff; end else s := 'c:\'; freemem(buff); result := s; end; function USBDeviceFind(GUID:TGUID; aPhysDevObjName: string): TUSBDev; var PnPHandle: HDEVINFO; DevData: TSPDevInfoData; DeviceInterfaceData: TSPDeviceInterfaceData; FunctionClassDeviceData: PSPDeviceInterfaceDetailData; Success: LongBool; Devn: Integer; BytesReturned: DWORD; aUSBDev: TUSBDev; begin try Result := nil; PnPHandle:= SetupDiGetClassDevs(@Guid, nil, 0,DIGCF_PRESENT or DIGCF_DEVICEINTERFACE); if PnPHandle = Pointer(INVALID_HANDLE_VALUE) then Exit; try Devn := 0; repeat DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData); Success := SetupDiEnumDeviceInterfaces(PnPHandle, nil, Guid, Devn, DeviceInterfaceData); if Success then begin DevData.cbSize := SizeOf(SP_DEVINFO_DATA); DeviceInterfaceData.cbSize := SizeOf(SP_DEVICE_INTERFACE_DATA); BytesReturned := 0; SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, nil, 0, BytesReturned, @DevData); if (BytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then begin FunctionClassDeviceData := AllocMem(BytesReturned); try FunctionClassDeviceData.cbSize := 5; if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, FunctionClassDeviceData, BytesReturned, BytesReturned, @DevData) then begin aUSBDev := TUSBDev.Create; aUSBDev.GetInfoForDev(PnPHandle, DevData, @FunctionClassDeviceData.DevicePath); if aPhysDevObjName = aUSBDev.FPhysDevObjName then begin result := aUSBDev; break; end else aUSBDev.Free; end; Inc(Devn); finally FreeMem(FunctionClassDeviceData); end; end; end; until not Success; finally if result = nil then SetupDiDestroyDeviceInfoList(PnPHandle); end; finally end; end; function USBDeviceEject(GUID:TGUID; aPhysDevNumber: LongInt): Boolean; var PnPHandle: HDEVINFO; DevData: TSPDevInfoData; DeviceInterfaceData: TSPDeviceInterfaceData; FunctionClassDeviceData: PSPDeviceInterfaceDetailData; Success: LongBool; Devn: Integer; BytesReturned: DWORD; i: integer; aUSBDev: TUSBDev; Parent: DWORD; VetoName: PChar; begin try Result := False; PnPHandle:= SetupDiGetClassDevs(@Guid, nil, 0,DIGCF_PRESENT or DIGCF_DEVICEINTERFACE); if PnPHandle = Pointer(INVALID_HANDLE_VALUE) then Exit; try Devn := 0; repeat DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData); Success := SetupDiEnumDeviceInterfaces(PnPHandle, nil, Guid, Devn, DeviceInterfaceData); if Success then begin DevData.cbSize := SizeOf(SP_DEVINFO_DATA); DeviceInterfaceData.cbSize := SizeOf(SP_DEVICE_INTERFACE_DATA); BytesReturned := 0; SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, nil, 0, BytesReturned, @DevData); if (BytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then begin FunctionClassDeviceData := AllocMem(BytesReturned); try FunctionClassDeviceData.cbSize := 5; if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, FunctionClassDeviceData, BytesReturned, BytesReturned, @DevData) then begin aUSBDev := TUSBDev.Create; aUSBDev.GetInfoForDev(PnPHandle, DevData, @FunctionClassDeviceData.DevicePath); if aPhysDevNumber = GetDevNum(aUSBDev.FDevicePath) then begin if CM_Get_Parent(@Parent, aUSBDev.FDevData.DevInst, 0) = 0 then begin sleep(200); VetoName := GetMemory(260); // if (CM_Request_Device_EjectA(aUSBDev.FDevData.DevInst, nil, VetoName, 260, 0) <> 0) then // if (CM_Query_And_Remove_SubTree(aUSBDev.FDevData.DevInst, nil, VetoName, 260, 0) <> 0) then // if (CM_Query_And_Remove_SubTree(Parent, nil, VetoName, 260, 0) <> 0) then if (CM_Request_Device_EjectA(Parent, nil, VetoName, 260, 0) <> 0) then begin if (CM_Locate_DevNodeA(@Parent, VetoName, 0) <> 0) then begin FreeMemory(VetoName); exit; end; FreeMemory(VetoName); if (CM_Request_Device_EjectA(Parent, nil, nil, 0, 0) <> 0) then exit else result := True; end else result := True; FreeMemory(VetoName); end; aUSBDev.Free; break; end else aUSBDev.Free; end; Inc(Devn); finally FreeMem(FunctionClassDeviceData); end; end; end; until not Success; finally end; finally SetupDiDestroyDeviceInfoList(PnPHandle); end; end; function GetDevNum(aPath: string): LongInt; var hFile: THandle; DevNum: TSTORAGE_DEVICE_NUMBER; tmp: Dword; begin result := 0; hFile := CreateFile(PChar(aPath), $C0, 4, nil, 3, FILE_ATTRIBUTE_NORMAL, 0); if hFile > 0 then begin DeviceIoControl(hFile, IOCTL_STORAGE_GET_DEVICE_NUMBER, nil, 0, @DevNum, sizeof(DevNum), Tmp, nil); Result := DevNum.DeviceNumber; end; CloseHandle(hFile); end; function GetDEVID(aDevPath: string): string; var TempStr: string; ResDosDev : Array [1..MAX_PATH] of Char; aUSBDev: TUSBDev; DevNumber: LongInt; begin result := ''; try If (QueryDosDevice(PChar(aDevPath), @ResDosDev, MAX_PATH) <> 0) then begin TempStr := StrPas(@ResDosDev); aUSBDev := USBDeviceFind(GUID_DEVINTERFACE_VOLUME, TempStr); if assigned(aUSBDev) then begin if Pos('removablemedia', AnsiLowerCase(aUSBDev.FDevicePath)) > 0 then begin DevNumber := GetDevNum(aUSBDev.FDevicePath); end; result := aUSBDev.FDevicePath; SetupDiDestroyDeviceInfoList(aUSBDev.FPnPHandle); aUSBDev.Free; end; end; except end; end; function IsRemoveable(aDevPath: string): Boolean; var TempStr: string; ResDosDev : Array [1..MAX_PATH] of Char; aUSBDev: TUSBDev; DevNumber: LongInt; begin try result := False; If (QueryDosDevice(PChar(aDevPath), @ResDosDev, MAX_PATH) <> 0) then begin TempStr := StrPas(@ResDosDev); aUSBDev := USBDeviceFind(GUID_DEVINTERFACE_VOLUME, TempStr); if assigned(aUSBDev) then begin if Pos('removablemedia', AnsiLowerCase(aUSBDev.FDevicePath)) > 0 then begin Result := True; end; SetupDiDestroyDeviceInfoList(aUSBDev.FPnPHandle); aUSBDev.Free; end; end; except end; end; procedure EjectDrive(aDrive: string); var aUSBDev: TUSBDev; DevNumber: LongInt; ResDosDev : Array [1..MAX_PATH] of Char; TempStr: string; begin try If (QueryDosDevice(PChar(aDrive), @ResDosDev, MAX_PATH) <> 0) then begin sleep(500); TempStr := StrPas(@ResDosDev); aUSBDev := USBDeviceFind(GUID_DEVINTERFACE_VOLUME, TempStr); if assigned(aUSBDev) then begin if Pos('removablemedia', AnsiLowerCase(aUSBDev.FDevicePath)) > 0 then begin DevNumber := GetDevNum(aUSBDev.FDevicePath); USBDeviceEject(GUID_DEVINTERFACE_DISK, DevNumber); end; SetupDiDestroyDeviceInfoList(aUSBDev.FPnPHandle); aUSBDev.Free; end; end; except end; end; procedure SelfRemoteEject; var TempStr1: string; Handle: THandle; begin try TempStr1 := ExtractFileDir(Application.ExeName); if Not FileExists(GetTempDir + '\EjectUSB.exe') then CopyFile(PChar(TempStr1 + '\EjectUSB.exe'), PChar(GetTempDir + '\EjectUSB.exe'), False); TempStr1 := copy(TempStr1, 1, 2); Handle := GetDesktopWindow; ShellExecute(Handle, PChar('open'), PChar(GetTempDir + '\EjectUSB.exe'), PChar(TempStr1), PChar(GetTempDir), SW_HIDE); except end; end; end.