program usbkey;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows,
SetupApi,
Cfg,
CfgMgr32;
// From WDK/DDK (ntddstor.h, winioctl.h)
const GUID_DEVINTERFACE_DISK: TGUID = '
{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}';
const props :
array[0..12]
of DWORD = (
SPDRP_CLASS,
SPDRP_CLASSGUID,
SPDRP_DEVICEDESC,
SPDRP_DRIVER,
SPDRP_ENUMERATOR_NAME,
SPDRP_FRIENDLYNAME,
SPDRP_LOCATION_INFORMATION,
SPDRP_MFG,
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
SPDRP_SECURITY_SDS,
SPDRP_SERVICE,
SPDRP_UI_NUMBER_DESC_FORMAT,
SPDRP_UI_NUMBER
);
function GetDeviceRegProperty(hDevInfo: THandle;
const spdevid : TSPDevInfoData; dwProperty: DWORD):
String;
var
dwTemp, dwRequired : DWORD;
begin
case dwProperty
of
// REG_DWORD
SPDRP_ADDRESS,
SPDRP_BUSNUMBER,
SPDRP_CAPABILITIES,
SPDRP_CHARACTERISTICS,
SPDRP_CONFIGFLAGS,
SPDRP_DEVTYPE,
SPDRP_INSTALL_STATE,
SPDRP_UI_NUMBER:
begin
if(SetupDiGetDeviceRegistryProperty(hDevInfo, spdevid, dwProperty, PDWORD(
nil)^, @dwTemp, sizeof(dwTemp), dwRequired))
then
begin
Result := Format('
%u (0x%8.8X)', [dwTemp, dwTemp]);
exit;
end;
end;
// REG_SZ
SPDRP_CLASS,
SPDRP_CLASSGUID,
SPDRP_DEVICEDESC,
SPDRP_DRIVER,
SPDRP_ENUMERATOR_NAME,
SPDRP_FRIENDLYNAME,
SPDRP_LOCATION_INFORMATION,
SPDRP_MFG,
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
SPDRP_SECURITY_SDS,
SPDRP_SERVICE,
SPDRP_UI_NUMBER_DESC_FORMAT:
begin
// We expect this call to fail
if(
not SetupDiGetDeviceRegistryProperty(hDevInfo, spdevid, dwProperty, PDWORD(
nil)^,
nil, 0, dwRequired))
then
begin
if(ERROR_INSUFFICIENT_BUFFER = GetLastError())
then
begin
SetLength(Result, (dwRequired + 1)
div sizeof(Char));
if(SetupDiGetDeviceRegistryProperty(hDevInfo, spdevid, dwProperty, PDWORD(
nil)^, PByte(@Result[1]), dwRequired, dwRequired))
then
begin
// Result now contains the property string
exit;
end;
end;
end;
end
else
Result := Format('
<unsupported property %u>', [dwProperty]);
exit;
end;
if(ERROR_INVALID_DATA = GetLastError())
then
Result := '
'
else
Result := Format('
<Win32 error: %u>', [GetLastError()]);
end;
procedure GetDetailedData(hDevInfo : THandle ; dwIdx : DWORD;
const spdevid : TSPDevInfoData);
var
cmret : CONFIGRET;
ulStatus, ulProblem : DWORD;
str :
String;
i: Integer;
begin
cmret := CM_Get_DevNode_Status(ulStatus, ulProblem, spdevid.DevInst, 0);
// Something went wrong
if(CR_SUCCESS <> cmret)
then
begin
// Aaah, it's just that the device isn't plugged in (or otherwise present)
if(CR_NO_SUCH_DEVNODE <> cmret)
then // shut up about non-present devices
WriteLn('
CM_Get_DevNode_Status returned error: ', cmret);
exit;
end;
if(DN_STARTED = (DN_STARTED
and ulStatus))
then
begin
WriteLn(dwIdx, '
started:');
for i := Low(props)
to High(props)
do
begin
str := GetDeviceRegProperty(hDevInfo, spdevid, props[i]);
if(str <> '
')
then
WriteLn(Format('
%8.8X', [props[i]]), '
: ', str);
end;
end
end;
procedure ListUsbDisks();
var
hDevInfo : THandle;
iErr : Integer;
spdevid: TSPDevInfoData;
dwIdx: DWORD;
begin
hDevInfo := SetupDiGetClassDevs(@GUID_DEVINTERFACE_DISK,
nil, 0, DIGCF_DEVICEINTERFACE);
if(INVALID_HANDLE_VALUE <> hDevInfo)
then
try
dwIdx := 0;
iErr := ERROR_SUCCESS;
repeat
spdevid.cbSize := sizeof(spdevid);
if(
not SetupDiEnumDeviceInfo(hDevInfo, dwIdx, spdevid))
then
begin
iErr := GetLastError();
if(ERROR_NO_MORE_ITEMS <> iErr)
then
begin
WriteLn('
Error from SetupDiEnumDeviceInterfaces: ', iErr);
break;
end;
end;
GetDetailedData(hDevInfo, dwIdx, spdevid);
Inc(dwIdx);
until (iErr = ERROR_NO_MORE_ITEMS);
finally
if(
not SetupDiDestroyDeviceInfoList(hDevInfo))
then
WriteLn('
Could not destroy device list: ', GetLastError());
end
else
WriteLn('
Could not retrieve list for devices of GUID_DEVINTERFACE_DISK class: ', GetLastError());
end;
begin
try
ListUsbDisks();
except
on E:
Exception do
Writeln(E.Classname, '
: ', E.
Message);
end;
end.