Send IOCTL to Windows device driver - CreateFile fails
Solution 1
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);
}
Solution 2
Just try with CreateFile(L"\\\\.\\{GUID}",etc..
.
Related videos on Youtube
bmotmans
Updated on June 04, 2022Comments
-
bmotmans almost 2 years
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)
-
Alexey Frunze over 12 yearsSome 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.
-
bmotmans over 12 yearsThis 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. -
Violet Giraffe over 12 years@bmotmans: try
GENERIC_READ
orGENERIC_READ | GENERIC_WRITE
as the second parameter toCreateFile
, leave all other flags '0'. -
bmotmans over 12 yearsThis causes the error "The parameter is incorrect". Apparently the 'dwCreationDisposition' parameter must always be set (OPEN_EXISTING)
-
Violet Giraffe over 12 years@bmotmans: Of course, sorry, forgot that one. And what happens when you set it to OPEN_EXISTING?
-
bmotmans over 12 yearssame thing when only using the OPEN_EXISTING parameter. (all other parameters with value 0)
-
Violet Giraffe over 12 years@bmotmans: I meant
GENERIC_READ
orGENERIC_READ | GENERIC_WRITE
andOPEN_EXISTING
, with all other flags being 0. That's the combination I am only able to open USB device with. -
bmotmans over 12 yearsSame thing, "Access is denied". I'm starting to believe that another process has exclusive ownership over the driver/device, blocking my CreateFile attempts.
-
Violet Giraffe over 12 years@bmotmans: I'm afraid I've shared all the experience I have. I have no idea how to fix
ACCESS_DENIED
. -
serup almost 6 yearshow is this different from what he is already doing - you need to provide a more clear answer