當裝置路徑未知時,可透過裝置介面 GUID 列舉系統現有儲存裝置。本文示範 SetupAPI 列舉裝置路徑、以 IOCTL_STORAGE_QUERY_PROPERTY 取得廠商 ID、產品 ID、序號、總線類型等詳細屬性,解決「不知路徑如何開啟裝置」的核心問題。
DEFINE_GUID(GUID_DEVINTERFACE_DISK, 0x53f56307L, 0xb6bf, 0x11d0,
0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
int GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath) {
HDEVINFO hDevInfo = SetupDiGetClassDevs(lpGuid, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SP_DEVICE_INTERFACE_DATA ifData = {sizeof(SP_DEVICE_INTERFACE_DATA)};
PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
GlobalAlloc(LMEM_ZEROINIT, 1024);
pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
int nCount = 0; BOOL bResult = TRUE;
while (bResult) {
bResult = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, lpGuid,
nCount, &ifData);
if (bResult) {
bResult = SetupDiGetInterfaceDeviceDetail(hDevInfo, &ifData,
pDetail, 1024, NULL, NULL);
if (bResult) {
strcpy(pszDevicePath[nCount], pDetail->DevicePath);
nCount++;
}
}
}
GlobalFree(pDetail);
SetupDiDestroyDeviceInfoList(hDevInfo);
return nCount;
}
需連結 setupapi.lib,包含 initguid.h, setupapi.h。
路徑格式範例:
\\?\ide#diskmaxtor_2f040j0__________________________vam51jj0#3146563447534558202020202020202020202020#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
編碼包含:匯流排類型 (IDE/SCSI/USB)、產品型號、韌體版本、序號、GUID。無標準解析規則,僅供人工識別。
typedef enum _STORAGE_BUS_TYPE { BusTypeUnknown=0, BusTypeScsi, BusTypeAtapi,
BusTypeAta, BusType1394, BusTypeSsa, BusTypeFibre, BusTypeUsb, BusTypeRAID } STORAGE_BUS_TYPE;
typedef struct _STORAGE_PROPERTY_QUERY {
STORAGE_PROPERTY_ID PropertyId; // StorageDeviceProperty / StorageAdapterProperty
STORAGE_QUERY_TYPE QueryType; // PropertyStandardQuery / PropertyExistsQuery ...
UCHAR AdditionalParameters[1];
} STORAGE_PROPERTY_QUERY;
typedef struct _STORAGE_DEVICE_DESCRIPTOR {
ULONG Version, Size;
UCHAR DeviceType, DeviceTypeModifier;
BOOLEAN RemovableMedia, CommandQueueing;
ULONG VendorIdOffset, ProductIdOffset, ProductRevisionOffset, SerialNumberOffset;
STORAGE_BUS_TYPE BusType;
ULONG RawPropertiesLength;
UCHAR RawDeviceProperties[1]; // 緊接著 VendorId/ProductId/Revision/SerialNumber 字串
} STORAGE_DEVICE_DESCRIPTOR;
BOOL GetDriveProperty(HANDLE hDevice, PSTORAGE_DEVICE_DESCRIPTOR pDesc) {
STORAGE_PROPERTY_QUERY q = {StorageDeviceProperty, PropertyStandardQuery};
DWORD dwOut;
return DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&q, sizeof(q), pDesc, pDesc->Size, &dwOut, NULL);
}
呼叫後需根據 Offset 從 RawDeviceProperties 解析字串 (ANSI/Unicode 視驅動而定)。
31465634475345582020...),非原始 ASCII — 可能為驅動轉換格式。歡迎專家補充驅動層面的解釋。