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)
bmotmans
  • 15,650
  • 5
  • 20
  • 14
  • Did you try sending an access control? E.g. GENERIC_READ instead of 0? – Billy ONeal Nov 24 '11 at 23:33
  • 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. – bmotmans Nov 24 '11 at 23:52
  • What is the error code? Access denied? File not found? – Luke Nov 25 '11 at 01:54
  • 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 found – bmotmans Nov 25 '11 at 12:55
  • 1
    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. – Alexey Frunze Nov 28 '11 at 12:17
  • 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) – bmotmans Nov 28 '11 at 16:22
  • I tried to use this solution but it's not working: http://stackoverflow.com/questions/17465038/error-in-setupdigetdeviceinterfacedetail – Bosskardo Jul 04 '13 at 08:10

2 Answers2

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);
    }
Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
  • 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. – bmotmans Nov 28 '11 at 16:25
  • @bmotmans: try `GENERIC_READ` or `GENERIC_READ | GENERIC_WRITE` as the second parameter to `CreateFile`, leave all other flags '0'. – Violet Giraffe Nov 28 '11 at 16:42
  • This causes the error "The parameter is incorrect". Apparently the 'dwCreationDisposition' parameter must always be set (OPEN_EXISTING) – bmotmans Nov 28 '11 at 16:53
  • @bmotmans: Of course, sorry, forgot that one. And what happens when you set it to OPEN_EXISTING? – Violet Giraffe Nov 28 '11 at 16:58
  • same thing when only using the OPEN_EXISTING parameter. (all other parameters with value 0) – bmotmans Nov 28 '11 at 19:35
  • @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. – Violet Giraffe Nov 28 '11 at 19:39
  • Same thing, "Access is denied". I'm starting to believe that another process has exclusive ownership over the driver/device, blocking my CreateFile attempts. – bmotmans Nov 29 '11 at 07:21
  • @bmotmans: I'm afraid I've shared all the experience I have. I have no idea how to fix `ACCESS_DENIED`. – Violet Giraffe Nov 29 '11 at 14:46
1

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

user2986042
  • 1,098
  • 2
  • 16
  • 37
  • how is this different from what he is already doing - you need to provide a more clear answer – serup Apr 18 '18 at 07:33