将 IOCTL 发送到 Windows 设备驱动程序 - CreateFile 失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8263380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:31:34  来源:igfitidea点击:

Send IOCTL to Windows device driver - CreateFile fails

c++windowsdriverdeviceioctl

提问by bmotmans

I want to send an IOCTL command to a PC/SC reader connected to my computer (win7 64 bit). In order to send an IOCTL command I need a HANDLE to the device, which I'm unable to create.

我想向连接到我的计算机(win7 64 位)的 PC/SC 阅读器发送 IOCTL 命令。为了发送 IOCTL 命令,我需要一个到设备的 HANDLE,我无法创建它。

The device is listed as "OMNIKEY 1021" in the device manager, the physical device object name is "\Device\USBPDO-15". Using the "WinObj" tool, I can detect 2 symlinks: USB#VID_076B&PID_1021#5&291f6990&0&1#{50dd5230-ba8a-11d1-bf5d-0000f805f530} USB#VID_076B&PID_1021#5&291f6990&0&1#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

该设备在设备管理器中列为“OMNIKEY 1021”,物理设备对象名称为“\Device\USBPDO-15”。使用 “的WinObj” 的工具,我可以检测2个符号链接:USB#VID_076B&PID_1021#5&291f6990&0&1#{50dd5230-ba8a-11D1-bf5d-0000f805f530} USB#VID_076B&PID_1021#5&291f6990&0&1#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

My problem: I cannot create a valid handle to this device with the CreateFile function:

我的问题:我无法使用 CreateFile 函数创建此设备的有效句柄:

I found several possible formats on MSDN/Google to use as the lpFileName param of the CreateFile function, but none of them seem to work:

我在 MSDN/Google 上发现了几种可能的格式用作 CreateFile 函数的 lpFileName 参数,但它们似乎都不起作用:

\?\Device\USBPDO-15
\.\Device\USBPDO-15
\GLOBAL??\Device\USBPDO-15
\GLOBAL??\Device\USBPDO-15
\.\USBPDO-15
\?\USB#VID_076B&PID_1021#5&291f6990&0&1#{50dd5230-ba8a-11d1-bf5d-0000f805f530}
\.\USB#VID_076B&PID_1021#5&291f6990&0&1#{50dd5230-ba8a-11d1-bf5d-0000f805f530}
\GLOBAL??\USB#VID_076B&PID_1021#5&291f6990&0&1#{50dd5230-ba8a-11d1-bf5d-0000f805f530}
\GLOBAL??\USB#VID_076B&PID_1021#5&291f6990&0&1#{50dd5230-ba8a-11d1-bf5d-0000f805f530}
\?\USB#VID_076B&PID_1021#5&291f6990&0&1#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
\.\USB#VID_076B&PID_1021#5&291f6990&0&1#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
\GLOBAL??\USB#VID_076B&PID_1021#5&291f6990&0&1#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
\GLOBAL??\USB#VID_076B&PID_1021#5&291f6990&0&1#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

Code sample:

代码示例

#include <iostream>
#include <Windows.h>

int main (int argc, char* argv[])
{
    HANDLE handle = CreateFile (
        L"\\.\Device\USBPDO-15",
        0,
        FILE_SHARE_READ, //FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0, //FILE_FLAG_OVERLAPPED,
        NULL
    );

    if (handle == INVALID_HANDLE_VALUE)
        std::cout << "INVALID HANDLE" << std::endl;
    else
        std::cout << "HANDLE: " << std::hex << handle << std::endl;
}

Notes:

笔记:

  • The returned handle is always invalid
  • Always running as Administrator, so the privileges should not be a problem
  • 返回的句柄总是无效的
  • 始终以管理员身份运行,所以权限应该不是问题

edit:

编辑:

Solution:

解决方案:

  • The PC/SC service takes exclusive ownership of the devices, so any attempt to call 'CreateFile' will always fail.
  • The solution is a kernel space driver, this allows you to pass IRP's to the driver. (I was able to implement a KMDF filter driver to alter data sent/received to/from the device)
  • PC/SC 服务拥有设备的独占所有权,因此任何调用“CreateFile”的尝试都将失败。
  • 解决方案是内核空间驱动程序,这允许您将 IRP 传递给驱动程序。(我能够实现 KMDF 过滤器驱动程序来更改发送/接收到/从设备的数据)

采纳答案by Violet Giraffe

Try it my way. I'm using Setup API to enumerate all USB active devices in the system and get paths. That way you can find out whether it's the path or other arguments that CreateFiledoesn't like.

试试我的方法。我正在使用 Setup API 枚举系统中的所有 USB 活动设备并获取路径。这样你就可以找出是路径还是其他CreateFile不喜欢的参数。

I'll add some comments a bit later, if anyone's interested.

如果有人感兴趣,我稍后会添加一些评论。

HDEVINFO hDevInfo = SetupDiGetClassDevs( &_DEVINTERFACE_USB_DEVICE, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
    if(hDevInfo == INVALID_HANDLE_VALUE)
    {
        return ERR_FAIL;
    }

    std::vector<SP_INTERFACE_DEVICE_DATA> interfaces;

    for (DWORD i = 0; true; ++i)
    {
        SP_DEVINFO_DATA devInfo;
        devInfo.cbSize = sizeof(SP_DEVINFO_DATA);
        BOOL succ = SetupDiEnumDeviceInfo(hDevInfo, i, &devInfo);
        if (GetLastError() == ERROR_NO_MORE_ITEMS)
            break;
        if (!succ) continue;

        SP_INTERFACE_DEVICE_DATA ifInfo;
        ifInfo.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
        if (TRUE != SetupDiEnumDeviceInterfaces(hDevInfo, &devInfo,  &(_DEVINTERFACE_USB_DEVICE), 0, &ifInfo))
        {
            if (GetLastError() != ERROR_NO_MORE_ITEMS)
                break;
        }
        interfaces.push_back(ifInfo);
    }

    std::vector<SP_INTERFACE_DEVICE_DETAIL_DATA*> devicePaths;
    for (size_t i = 0; i < interfaces.size(); ++i)
    {
        DWORD requiredSize = 0;
        SetupDiGetDeviceInterfaceDetail(hDevInfo, &(interfaces.at(i)), NULL, NULL, &requiredSize, NULL);
        SP_INTERFACE_DEVICE_DETAIL_DATA* data = (SP_INTERFACE_DEVICE_DETAIL_DATA*) malloc(requiredSize);
        assert (data);
        data->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

        if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &(interfaces.at(i)), data, requiredSize, NULL, NULL))
        {
            continue;
        }
        devicePaths.push_back(data);
    }

回答by user2986042

Just try with CreateFile(L"\\\\.\\{GUID}",etc...

试试吧CreateFile(L"\\\\.\\{GUID}",etc..