expertcad/SRC/Protection/U_USB1.pas
2025-05-12 10:07:51 +03:00

632 lines
24 KiB
ObjectPascal

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.