You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:55:08