使用IOCTL_CHANGER_GET_PRODUCT_DATA

时间:2017-01-22 19:26:05

标签: c++ windows winapi

我有一项任务是将VendorId和ProductId设备作为磁盘挂载。代码看起来像这样:

int main() {
    HANDLE hDevice;
    char cDisk = 'c';   // Get metadata about the C:\ disk

                        // Build the logical drive path and get the drive device handle
    std::wstring logicalDrive = L"\\\\.\\";
    wchar_t drive[3];
    drive[0] = cDisk;
    drive[1] = L':';
    drive[2] = L'\0';
    logicalDrive.append(drive);

    hDevice = CreateFile(
        logicalDrive.c_str(),
        FILE_READ_ATTRIBUTES,
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

    _tprintf(_T("%s\n"), logicalDrive.c_str());

    if (hDevice == INVALID_HANDLE_VALUE)
    {
        std::cerr << "CreateFile error #" << GetLastError() << std::endl;
        system("pause");
        return -1;
    }

    // Now that we have the device handle for the disk, let us get disk's metadata  

    CHANGER_PRODUCT_DATA dg = { 0 };
    DWORD ioctlJnk;

    if (!DeviceIoControl(hDevice,
        IOCTL_CHANGER_GET_PRODUCT_DATA,
        NULL,
        0,
        &dg,
        sizeof(dg),
        &ioctlJnk,
        NULL)
        )
    {
        std::cerr << "DeviceIoControl error #" << GetLastError() << std::endl;
        CloseHandle(hDevice);
        system("pause");
        return -1;
    }

    // Success, now print the device manufacturer's name
    std::cout << dg.VendorId << std::endl;
    CloseHandle(hDevice);
}

问题是DeviceIoControl函数失败,GetLastError返回ERROR_ACCESS_DENIED。它发生在任何磁盘上。

如何使此代码正常工作?任何其他想法如何获得VID&amp; PID通过挂载设备的特性?

提前致谢!

2 个答案:

答案 0 :(得分:2)

您可能需要打开具有足够访问权限和/或具有足够权限才能使用该I / O控制功能的设备,但您的​​根本问题是您使用的设备类型错误。 IOCTL_CHANGER_*函数仅适用于更换器设备,这些设备的文件名格式为\\.\Changer#。来自MSDN上的CreateFile文档:

  

更换设备

     

DeviceIoControl的 IOCTL_CHANGER _ * 控制代码接受更换器设备的句柄。要打开更换器设备,请使用以下格式的文件名:“\\。\ Changerx”其中x是一个数字,指示要打开的设备,从零开始。要在使用C或C ++编写的应用程序中打开更换器设备零,请使用以下文件名:“\\\\。\\ Changer0”。

请注意,您不是第一个犯这个错误的人。 Juan Pablo reported on the MinGW mailing list使用类似代码获得相同的错误。 Luke Dunstan指出,在该线程中修复使用GENERIC_READ的代码会将失败更改为ERROR_INVALID_FUNCTION。

最后,我还要注意,您使用的文件名\\.\C:不是物理磁盘的名称。它是物理磁盘上卷的名称。物理磁盘上可以有多个卷,卷可以跨多个物理磁盘。

答案 1 :(得分:0)

寻找IOCTL_CHANGER_GET_PRODUCT_DATA定义:

#define IOCTL_CHANGER_GET_PRODUCT_DATA       CTL_CODE(IOCTL_CHANGER_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS)

注意FILE_READ_ACCESS所以文件句柄必须有FILE_READ_DATA,但是你如何打开文件?

hDevice = CreateFile(
        logicalDrive.c_str(),
        0,
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

更改为

hDevice = CreateFile(
    logicalDrive.c_str(),
    FILE_GENERIC_READ,
    0,
    NULL,
    OPEN_EXISTING,
    0,
    NULL);

之后你又出现了另一个错误 - ERROR_NOT_SUPPORTED,因为你选择了不正确的设备来请求