我对驱动程序开发很新,并试图编写一个简单的过滤器驱动程序来启用或禁用键盘或鼠标设备.如果我可以使它工作,我想用它来插入鼠标插入我的笔记本电脑上的触摸板.我意识到可能有软件已经做到这一点,但我真的对设备驱动程序感兴趣,并希望自己学习如何做到这一点.
我正在使用随WDK一起提供的kbfiltr和moufiltr示例,作为上层过滤器驱动程序安装.kbfiltr示例创建一个pdo,可以通过usermode程序枚举和连接.这允许我将IOCTL发送到由KbFilter_EvtIoDeviceControlForRawPdo处理的PDO .但是,当我尝试做任何与过滤器驱动程序相关的事情时,比如调用KbFilter_EvtIoInternalDeviceControl所以我可以做类似的事情
VOID
KbFilter_EvtIoInternalDeviceControl(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength,
IN ULONG IoControlCode
)
...
hDevice = WdfIoQueueGetDevice(Queue);
devExt = FilterGetData(hDevice);
switch (IoControlCode) {
...
case IOCTL_INTERNAL_KEYBOARD_DISCONNECT:
//
// Clear the connection parameters in the device extension.
//
devExt->UpperConnectData.ClassService = NULL;
break;
...
}
Run Code Online (Sandbox Code Playgroud)
我得到了一个BSOD.它不是上面的代码,在vanilla示例中,set to null被注释掉,只是调用Kbfilter会导致BSOD.我试图直接在PDO中设置设备扩展,但这也会导致BSOD,可能是因为它是PDO devExt,而不是kbfiltr?
(相关:什么是从BSOD获取堆栈跟踪的好方法?我使用Virtual PC作为我的测试环境和未经检查的XPSP3版本)
我不能直接向驱动程序堆栈发送IOCTL_INTERNAL_KEYBOARD_DISCONNECT(我知道输入设备一次只接受一个连接?)因此需要原始PDO.我真的只需要发送两个IOCTL(启用和禁用),我想我会使用键盘断开连接,因为这些已经定义.
如果我对这些假设有任何错误,请告诉我,我知道我真的是一个菜鸟,但我没有找到很多关于通过PDO进行此类通信的文档.
我试图将C++结构转换为C但仍然获得"未声明的标识符"?C++是否有不同的语法来引用结构?
struct KEY_STATE
{
bool kSHIFT; //if the shift key is pressed
bool kCAPSLOCK; //if the caps lock key is pressed down
bool kCTRL; //if the control key is pressed down
bool kALT; //if the alt key is pressed down
};
Run Code Online (Sandbox Code Playgroud)
我在另一个结构中使用KEY_STATE类型的变量:
typedef struct _DEVICE_EXTENSION
{
WDFDEVICE WdfDevice;
KEY_STATE kState;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
Run Code Online (Sandbox Code Playgroud)
导致 错误C2061:语法错误:标识符'KEY_STATE'
...在KEY_STATE kState线上; 我正在使用WDK编译器构建,如果这有任何区别.这当然是在头文件中.我正在将C++ WDM驱动程序移植到WDF和C.
初始化器可以用括号括起来.要避免此问题,请将声明符括在括号中或使其成为typedef.
当编译器将表达式检测为类模板参数时,也可能导致此错误; 使用typename告诉编译器它是一个类型.
将KEY_STATE更改为typedef结构仍会导致此错误,实际上会导致更多错误.没有免费的括号或太多括号中的东西,这是文章建议的另一件事.
在Windows上,我的平台是x86和x86-64.
中断优先级系统的要点是让最高优先级的中断超过其他中断.为了强制执行此操作,我猜测Windows将完全禁用所有较低级别的中断,直到更高级别中断的ISR完成为止.
但如果CPU没有收听中断,会发生什么?他们只是默默地消失了吗?或者他们是否在硬件中排队,等待中断再次启用?如果存放,在哪里?有多少人可以排队?如果有太多中断没有被处理,会发生什么?如果存在中断处理积压的罕见情况,检测问题的工具是什么?
有没有人知道部分或完全自动化驱动程序测试安装的方法?
我是驱动程序开发的新手,并且习惯于在更高级别的语言中使用更多的测试驱动方法,因此转向我无法轻松测试的环境对我来说是一个进步.我在我的测试环境中使用Virtual PC,目前必须重置它,打开设备管理器,选择设备,点击一堆" 你真的确定你不会安装其中一个系统驱动程序 "类型的对话框,然后在测试环境启动时,最终重启测试环境,同时在主机中重启WinDbg ... argh.
在重复这个过程很多次之后,肯定必须有更好的方法来做到这一点?商业驱动程序开发人员在测试环境中使用哪些工具/方法/技巧来运行其驱动程序?
注意,这不是关于单元测试驱动程序,我还没有达到那个阶段或者知道它是否可能.这只是为了启动附加WinDbg的测试环境,以确保我可能做的一些小改变正在做我期望的事情.
我叫AcquireCredentialsHandle在内核驱动程序,传递SCHANNEL_CRED与dwCredFormat
设置为SCH_CRED_FORMAT_CERT_HASH
.它失败了SEC_E_NO_CREDENTIALS
.这是我的代码:
BYTE certHashBytes[20] = { 0x6d,0x64,0xed,0x56,0xd2,0x94,0x15,0xf4,0x49,0x08,0xaf,0x18,0xf1,0xca,0xf5,0xa2,0xc8,0x01,0x20,0x96 };
CredHandle credHandle;
RtlZeroMemory(&credHandle, sizeof(CredHandle));
SCHANNEL_CRED schannelCred;
RtlZeroMemory(&schannelCred, sizeof(SCHANNEL_CRED));
schannelCred.dwVersion = 4;
schannelCred.cCreds = 1;
schannelCred.paCred = certHashBytes;
schannelCred.dwCredFormat = 1;
UNICODE_STRING unispName;
RtlUnicodeStringInit(&unispName, L"Microsoft Unified Security Protocol Provider");
TimeStamp ts;
SECURITY_STATUS res = AcquireCredentialsHandle(NULL, &unispName, SECPKG_CRED_INBOUND, NULL, &schannelCred, NULL, NULL, &credHandle, &ts);
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, "AcquireCredentialsHandle %x\n", res);
Run Code Online (Sandbox Code Playgroud)
我的证书哈希肯定是正确的,并且在MY商店中正确安装,用于用户帐户和本地计算机.我知道这是因为它在用户模式下工作正常,如下所示:
HCERTSTORE certStore = CertOpenSystemStore(NULL, L"MY");
BYTE certHashBytes[20] = { 0x6d,0x64,0xed,0x56,0xd2,0x94,0x15,0xf4,0x49,0x08,0xaf,0x18,0xf1,0xca,0xf5,0xa2,0xc8,0x01,0x20,0x96 };
CERT_NAME_BLOB certHash { 20, …
Run Code Online (Sandbox Code Playgroud) 我在WDK中使用KbFilter示例,尝试在由KbFilter_ServiceCallback调用的函数中发送IOCTL,因此在DISPATCH_LEVEL处执行.该函数只需发送一个IOCTL并返回,不等待输出缓冲区被填充,因此它可以是异步,触发和忘记.
我目前正在使用WDF函数WdfIoTargetFormatRequestForIoctl和WdfRequestSend尝试在DISPATCH_LEVEL发送并且什么都没得到.对WdfRequestSend的调用是成功的,但似乎没有收到IOCTL.
使用WdfIoTargetSendIoctlSynchronously或WDM模式IoBuildDeviceIoControlRequest()和IoCallDriver()需要PASSIVE_LEVEL,我知道在PASSIVE_LEVEL调用它们的唯一方法是创建一个在PASSIVE_LEVEL上运行的单独线程,并通过缓冲区或队列传递指令,同步用螺旋锁和信号量.
有人能告诉我是否有更简单的方法将IOCTL传递给我的过滤器下面的驱动程序,或者当你需要在更高的IRQL上做事时,线程/队列是否接近正常模式?在什么情况下我可以使用KeRaiseIrql,这是我应该使用的吗?谢谢.
当我尝试从Visual Studio 2013调试我的KMDF驱动程序时,出现以下错误
Visual Studio的Windows调试扩展
无法启动调试会话,错误8004005:未指定错误
在我收到错误之前,它会在目标计算机上安装驱动程序.有没有我可以看到更多信息的日志文件?
编辑1:
主机是Windows 7,目标是在VMWare ESXi中安装的Windows 8.1
编辑2:
我现在已经使用WINDBG进行了测试,并得到以下日志输出:
使用NET进行调试
打开WinSock 2.0
无法初始化套接字.错误On-2147467259
内核调试器初始化失败,HRESULT 0x80004005
"未指定的错误"
我还得到以下消息框:
无法启动内核调试
net:port = 50230,key = XXXXXXXXXXXXXXX参数,HRESULT 0x80004005
我正在编写一个KMDF驱动程序,它需要在传递给ioQueue之前拦截每个IRP.
我有一个注册PreprocessIrpCallback的回调函数,并希望将它挂钩到这样的框架中
status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit
, PreprocessIrpCallback
, ?
, ?);
Run Code Online (Sandbox Code Playgroud)
但问题是,如果我想拦截每一个IRP?
在我的 Windows 7 计算机上,我同时拥有 Windows SDK(10.0.14393.795) 和 WDK(10.0.14393.0) 版本,但是,当我在 Visual Studio 2015 中构建项目时,它一直说
MSB8036 找不到 Windows SDK 版本 10.0.14393.0。安装所需版本的 Windows SDK 或在项目属性页中更改 SDK 版本,或者右键单击解决方案并选择“重新定位解决方案”。
当我重新定位解决方案时,我拥有的选项是 10.0.10240 和 8.1,但不是 10.0.14393。
我怎样才能建立这种正确性?