问题描述
我想向连接到我的电脑的PC / SC读卡器发送一个IOCTL命令(win7 64位)。
为了发送IOCTL命令我需要一个设备句柄,这我无法建立。
该设备被列为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}
我的问题:我不能创建一个有效的句柄这个具有CreateFile函数的设备:
我在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& 1#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
\GLOBAL ?? \USB#VID_076B&放大器; PID_1021#5和291f6990&放大器; 0&放大器; 1#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
代码示例:
#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<<手柄< std :: endl;
}
注意:
- 返回的句柄始终无效
- 始终以管理员身份运行,这样的特权不应该是一个问题
编辑:
解决方案:
$ b
- PC / SC服务对设备具有独占所有权,因此任何调用CreateFile的尝试都将失败。
- 解决方案是一个内核空间驱动程序,这允许您将IRP传递给驱动程序。 (我是能够实现KMDF筛选器驱动程序来改变发送/接收数据到/从设备)
试试我的方式。我使用Setup API来枚举系统中的所有USB活动设备,并获取路径。这样你可以知道是否是路径或其他参数 CreateFile
不喜欢。
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>接口;
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);
}
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)
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);
}
这篇关于将IOCTL发送到Windows设备驱动程序 - CreateFile失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!