【发布时间】:2010-10-15 17:08:26
【问题描述】:
我对与 Windows 设备驱动程序进行通信非常陌生。
A) 我需要与第三方驱动程序通信。我看到CreateFile() 接受设备名称(例如\\\\.\\DeviceName),我也可以调用完整的文件名(例如\\\\.\\C:\\MyPath\\DriverName.sys)。什么是最好的选择?为什么?两者的工作方式相同?
B) 我看到很多设备驱动都有两个名字,例如:
SymbolicLink "\GLOBAL??\VirtualSerial"
Destination "\Device\VrSerialrs232"
如果我尝试打开例如打开VrSerialrs232 和CreateFile(),它会失败。那么,如果我总是必须调用SymbolicLink(VirtualSerial),为什么还要使用VrSerialrs232?
C) 我安装了一个DeviceIOControl 监视器来检查我的代码为什么会出现Error 50 失败(不支持该请求),但我不知道为什么。
DeviceIOControl 监视器的输出是here
来自test.exe 的是我的代码,另一个(受保护的)是调用同一设备的原始应用程序。
我的代码是这样的:
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <strsafe.h>
void ErrorExit(LPTSTR lpszFunction){
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
BOOL OpenDevice(PWSTR DriverName, HANDLE *lphDevice){
WCHAR DeviceName[MAX_PATH]; HANDLE hDevice;
if ((GetVersion() & 0xFF) >= 5) {
wcscpy(DeviceName, L"\\\\.\\Global\\");
} else {
wcscpy(DeviceName, L"\\\\.\\"); }
wcscat(DeviceName, DriverName); printf("Opening.. %S\n", DeviceName);
hDevice = CreateFileW(DeviceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("CreateFile() ERROR %d\n", GetLastError()); return FALSE;
}
*lphDevice = hDevice; return TRUE;
}
int _tmain(int argc, _TCHAR* argv[]){
HANDLE hDevice = NULL;
DWORD cb = 0;
int ret = 0;
char tcode[] = "\x8a\xb3\x39\x9d"; /* Copied from original request seen on Monitor) */
if(!OpenDevice(L"MyDeviceName",&hDevice)) {
printf("Error: Error opening device\n");
return(0);
} else {
printf("Device succesfully opened!\n");
}
char *Buff = (char *)VirtualAlloc(NULL, 0x330, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (Buff){
ret = DeviceIoControl(hDevice, 0xa028442f, tcode, 0x04, 0, NULL, &cb, (LPOVERLAPPED)NULL);
if (ret == 0) {
printf("Error: Bytes returned %#x\n",cb);
ErrorExit(TEXT("DeviceIoControl: "));
}
}
CloseHandle(hDevice);
return(0);
}
我总是收到这个错误:
C:>Test.exe
Opening.. \\.\Global\MyDeviceName
Device succesfully opened!
Error: Bytes returned 0
DeviceIOControl: Error 50 - The request is not supported
为什么?
我不知道 IOCTL 命令的名称,但我知道编号。有没有办法将 IOCTL 编号转换为名称?
这是我使用 IOCTL 监视器捕获的有效且真实的请求。
Log started...
'C:\PathToApplication\OriginalAppName.exe' (PID: 2896)
'\Device\VSFilterbpd' (0x86b83c40) [\??\C:\LocalPath\DeviceDriverName.sys]
SymbolicLink "\GLOBAL??\VSFFilter"
IOCTL Code: 0xa028442f, Method: METHOD_NEITHER
InBuff: 0x004883a4, InSize: 0x00000004
--------------------------------------------------------------------
9c 84 e2 86 | ....
OutBuff: 0x004b4f68, OutSize: 0x00001b20
--------------------------------------------------------------------
03 00 00 00 1c 03 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 e4 0c 00 00 00 00 00 00 00 00 00 00 | ................
A lot of data.
从我自己的应用程序复制/克隆/复制完全相同的消息到同一个驱动程序缺少什么?
谢谢
【问题讨论】:
-
嗯,控制码错误,驱动不识别。看起来确实很奇怪,缓冲区传递方法代码是3,METHOD_NEITHER。
标签: winapi device-driver device