Send IOCTL to Windows device driver - CreateFile fails
Asked Answered
M

2

9

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.

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}

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

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:

\\?\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)
Muscadine answered 24/11, 2011 at 23:19 Comment(7)
Did you try sending an access control? E.g. GENERIC_READ instead of 0?Mealtime
It was suggested somewhere on MSDN to use 0 when using CreateFile in combination with a device driver. However, I tried GENERIC_READ, GENERIC_READ | GENERIC_WRITE and 0 without result.Muscadine
What is the error code? Access denied? File not found?Watermark
depending on the format of the device string, I get 3 different errors: The system cannot find the file specified, The filename, directory name, or volume label syntax is incorrect or The network path was not foundMuscadine
Some device drivers accept only names that have extra known-only-to-them stuff in the names after "device name\". There may be other special ways for opening as well. I wonder if you can find out more using the kernel debugger (WinDbg), setting breakpoints here and there and looking at what's being passed to/from the driver.Nobby
Alex : this was indeed the case, together with the solution of @Violet-giraffe I figured out that \\slot0 must be appended at the end of the device string. However, now I get the error Access is denied (as admin)Muscadine
I tried to use this solution but it's not working: #17465538Patentor
E
9

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 CreateFile doesn't like.

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);
    }
Evaporimeter answered 28/11, 2011 at 14:40 Comment(8)
This pointed me to the correct string to use for my device, namely: L"\\\\?\\usb#vid_076b&pid_1021#6&3225591f&0&1#{50dd5230-ba8a-11d1-bf5d-0000f805f530}\\slot0" , I will accept this comment as the solution when I can find the cause of the "Access is denied" error that I now receive.Muscadine
@bmotmans: try GENERIC_READ or GENERIC_READ | GENERIC_WRITE as the second parameter to CreateFile, leave all other flags '0'.Evaporimeter
This causes the error "The parameter is incorrect". Apparently the 'dwCreationDisposition' parameter must always be set (OPEN_EXISTING)Muscadine
@bmotmans: Of course, sorry, forgot that one. And what happens when you set it to OPEN_EXISTING?Evaporimeter
same thing when only using the OPEN_EXISTING parameter. (all other parameters with value 0)Muscadine
@bmotmans: I meant GENERIC_READ or GENERIC_READ | GENERIC_WRITE and OPEN_EXISTING, with all other flags being 0. That's the combination I am only able to open USB device with.Evaporimeter
Same thing, "Access is denied". I'm starting to believe that another process has exclusive ownership over the driver/device, blocking my CreateFile attempts.Muscadine
@bmotmans: I'm afraid I've shared all the experience I have. I have no idea how to fix ACCESS_DENIED.Evaporimeter
E
1

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

Everhart answered 29/5, 2017 at 7:26 Comment(1)
how is this different from what he is already doing - you need to provide a more clear answerLegislate

© 2022 - 2024 — McMap. All rights reserved.