WINAPI获取USB存储信息失败:错误码50(请求不支持)
问题分析与解决方案
错误码50(请求不支持)的核心原因是:你当前打开的是USB设备的通用接口句柄,而IOCTL_DISK_GET_DRIVE_GEOMETRY_EX是针对磁盘存储设备的控制指令,USB设备接口本身不支持这类磁盘操作指令。
解决思路
需要枚举系统中的磁盘设备(而非USB设备),通过磁盘设备关联的硬件ID提取VID/PID进行匹配,获取正确的磁盘设备句柄后再执行磁盘信息查询。
修改后的完整代码
#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <initguid.h> #include <setupapi.h> #include <devguid.h> #include <ntdddisk.h> HANDLE getDiskHandleByVidPid(DWORD targetVid, DWORD targetPid) { HANDLE diskHandle = NULL; // 枚举磁盘设备接口 HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (hDevInfo == INVALID_HANDLE_VALUE) { printf("Failed to get disk device info set. Error: %d\n", GetLastError()); return NULL; } SP_DEVICE_INTERFACE_DATA ifaceData = {0}; ifaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); DWORD index = 0; while (SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_DISK, index++, &ifaceData)) { DWORD detailSize = 0; // 先获取所需缓冲区大小 SetupDiGetDeviceInterfaceDetail(hDevInfo, &ifaceData, NULL, 0, &detailSize, NULL); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { printf("Failed to get detail size. Error: %d\n", GetLastError()); continue; } SP_DEVICE_INTERFACE_DETAIL_DATA* pDetail = (SP_DEVICE_INTERFACE_DETAIL_DATA*)malloc(detailSize); if (!pDetail) { printf("Malloc failed\n"); continue; } pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); SP_DEVINFO_DATA devInfoData = {0}; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &ifaceData, pDetail, detailSize, NULL, &devInfoData)) { printf("Failed to get device detail. Error: %d\n", GetLastError()); free(pDetail); continue; } // 获取硬件ID,提取VID和PID char hardwareId[256]; if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_HARDWAREID, NULL, (PBYTE)hardwareId, sizeof(hardwareId), NULL)) { free(pDetail); continue; } DWORD vid, pid; // 从硬件ID中解析VID/PID(格式如USB\VID_XXXX&PID_XXXX) if (sscanf_s(hardwareId, "USB\\VID_%04X&PID_%04X", &vid, &pid) == 2) { if (vid == targetVid && pid == targetPid) { // 打开磁盘设备句柄,仅需GENERIC_READ权限即可获取磁盘信息 diskHandle = CreateFile(pDetail->DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (diskHandle != INVALID_HANDLE_VALUE) { free(pDetail); break; } else { printf("CreateFile failed. Error: %d\n", GetLastError()); } } } free(pDetail); } SetupDiDestroyDeviceInfoList(hDevInfo); return diskHandle; } int main() { DWORD targetVid = 0x090C; DWORD targetPid = 0x1000; HANDLE diskHandle = getDiskHandleByVidPid(targetVid, targetPid); if (!diskHandle || diskHandle == INVALID_HANDLE_VALUE) { printf("Failed to get valid disk handle\n"); return 1; } DISK_GEOMETRY_EX diskGeometry; DWORD bytesReturned = 0; BOOL result = DeviceIoControl( diskHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &diskGeometry, sizeof(diskGeometry), &bytesReturned, NULL ); if (result) { printf("Bytes returned: %d\n", bytesReturned); printf("Total storage size: %llu bytes\n", diskGeometry.DiskSize.QuadPart); } else { printf("DeviceIoControl failed. Error: %d\n", GetLastError()); printf("Bytes returned: %d\n", bytesReturned); } CloseHandle(diskHandle); return 0; }
关键修改点说明
- 替换枚举的设备GUID:使用
GUID_DEVINTERFACE_DISK枚举磁盘设备,而非GUID_DEVINTERFACE_USB_DEVICE。 - 提取硬件ID匹配VID/PID:通过
SetupDiGetDeviceRegistryProperty获取磁盘设备关联的硬件ID,从中解析出VID和PID进行匹配。 - 调整权限:打开磁盘设备时仅需
GENERIC_READ权限,无需GENERIC_WRITE,减少权限要求。
编译命令
gcc main.c -o main.exe -lsetupapi
内容的提问来源于stack exchange,提问作者work work
相关产品推荐
相关产品推荐

