近来在学驱动开发,自己写了一个简单地驱动程序,截取键盘按键。另外写的应用程序会显示按键。以下是驱动部分的关键代码。完整代码点击:猛戳这里
/**************************************************************/ #include "KeyFilter.h" /************************************************************************ * 函数名称:DriverEntry * 功能描写叙述:初始化驱动程序。定位和申请硬件资源。创建内核对象 * 參数列表: pDriverObject:从I/O管理器中传进来的驱动对象 pRegistryPath:驱动程序在注冊表的中的路径 * 返回 值:返回初始化驱动状态 *************************************************************************/ #pragma INITCODE extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath) { KdPrint(("Enter DriverEntry ")); pDriverObject->DriverExtension->AddDevice = KeyFilterAddDevice; pDriverObject->MajorFunction[IRP_MJ_PNP] = KeyFilterPnp; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KeyFilterDeviceIoCtl; pDriverObject->MajorFunction[IRP_MJ_CREATE] = KeyFilterDispatchRoutine; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = KeyFilterDispatchRoutine; pDriverObject->MajorFunction[IRP_MJ_READ] = KeyFilterRead; pDriverObject->MajorFunction[IRP_MJ_WRITE] = KeyFilterDispatchRoutine; pDriverObject->DriverUnload = KeyFilterUnload; pDriverObject->DriverStartIo = KeyFilterStartIO; KdPrint(("Leave DriverEntry ")); return STATUS_SUCCESS; } /************************************************************************ * 函数名称:KeyFilterAddDevice * 功能描写叙述:加入新设备 * 參数列表: DriverObject:从I/O管理器中传进来的驱动对象 PhysicalDeviceObject:从I/O管理器中传进来的物理设备对象 * 返回 值:返回加入新设备状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS KeyFilterAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { PAGED_CODE(); _asm int 3; NTSTATUS status; PDEVICE_OBJECT PDeviceObject; UNICODE_STRING strnum; UNICODE_STRING devName; UNICODE_STRING kbdclassname; UNICODE_STRING symLinkName; //PDRIVER_OBJECT kbdDriver; PDEVICE_OBJECT kbdDevice; int index = 0; PDEVICE_EXTENSION pdx; WCHAR DevnameBase[100] = L"\Device\KeyFilterDevice"; KdPrint(("Enter KeyFilterAddDevice ")); // PFILE_OBJECT FileObject = NULL; RtlInitUnicodeString(&kbdclassname,L"\Device\KeyboardClass0"); //通过classname得到设备对象 status = IoGetDeviceObjectPointer(&kbdclassname,FILE_ALL_ACCESS,&FileObject,&kbdDevice); if (!NT_SUCCESS(status)) { KdPrint(("ObReferenceObjectByName error,0x%x ",status)); return status; } do{ RtlInitUnicodeString(&strnum,L"strnum"); RtlIntegerToUnicodeString(index,10,&strnum); RtlInitUnicodeString(&devName,DevnameBase); RtlAppendUnicodeStringToString(&devName,&strnum); //创建设备 status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), &devName, kbdDevice->DeviceType, kbdDevice->Characteristics, FALSE, &PDeviceObject); if( !NT_SUCCESS(status)) break; pdx = (PDEVICE_EXTENSION)PDeviceObject->DeviceExtension; pdx->NextStackDevice = IoAttachDeviceToDeviceStack(PDeviceObject, kbdDevice); if (pdx->NextStackDevice == NULL) { KdPrint(("IoAttachDeviceToDeviceStack failed,error = %x ",status)); IoDeleteDevice( PDeviceObject ); break; } pdx->PDeviceObject = PDeviceObject; //创建符号链接 RtlInitUnicodeString(&symLinkName,L"\??\KeyFilterSymLinkName"); RtlAppendUnicodeStringToString(&symLinkName,&strnum); status = IoCreateSymbolicLink(&symLinkName,&devName); if( !NT_SUCCESS(status)) { IoDeleteSymbolicLink(&pdx->ustrSymLinkName); break; } //保存设备名和符号链接名 RtlCopyUnicodeString(&pdx->ustrDeviceName,&devName); RtlCopyUnicodeString(&pdx->ustrSymLinkName,&symLinkName); PDeviceObject->Flags |= kbdDevice->Flags & (DO_BUFFERED_IO | DO_POWER_PAGABLE); PDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;//将Flag上的DO_DEVICE_INITIALIZING位清零,保证设备初始化完毕,必须的。 }while(FALSE); ObDereferenceObject(FileObject); ObDereferenceObject(kbdDevice); //初始化自旋锁 KeInitializeSpinLock(&pdx->ListSpinLock); //初始化链表 InitializeListHead(&pdx->linkListHead); KdPrint(("Leave KeyFilterAddDevice ")); return STATUS_SUCCESS; } #pragma PAGEDCODE void KeyFilterCancelIRP(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { KdPrint(("Enter HelloWDMOnCancelIRP ")); if (Irp == fdo->CurrentIrp) { KIRQL oldirql = Irp->CancelIrql; //释放cancel自旋锁 IoReleaseCancelSpinLock(Irp->CancelIrql); //继续下一个IRP IoStartNextPacket(fdo, TRUE); //减少IRQL KeLowerIrql(oldirql); } else {//还没有被执行,还在队列中 KeRemoveEntryDeviceQueue(&fdo->DeviceQueue, &Irp->Tail.Overlay.DeviceQueueEntry); //释放cancel自旋锁 IoReleaseCancelSpinLock(Irp->CancelIrql); } Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); KdPrint(("Leave HelloWDMOnCancelIRP ")); } //************************************ // Method: KeyFilterDeviceIoCtlStartio // Qualifier: IRP_MJ_DEVICE_CONTROL 处理函数 //************************************ NTSTATUS KeyFilterDeviceIoCtlStartio(IN PDEVICE_OBJECT fdo,IN PIRP Irp) { PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); NTSTATUS status = STATUS_SUCCESS; ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; ULONG readLen = stack->Parameters.Read.Length; PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)fdo->DeviceExtension; KdPrint(("++++++enter KeyFilterDeviceIoCtlStartio ")); switch (code) { case IOCTL_SHOWKEYFILTER: KdPrint(("IOCTL_SHOWKEYFILTER KeyFilterDeviceIoCtlStartio ")); if (IsListEmpty(&pDevExt->linkListHead))//队列为空,完毕irp { KdPrint(("list is empty. ")); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); } else//队列中有数据,取出数据 { KdPrint(("list have data ")); PLIST_ENTRY pEntry; PMYDATASTRUCT pData; memset(Irp->AssociatedIrp.SystemBuffer,0,readLen); int index = 0; USHORT buffer[MAX_KEY_COUNT*2] = {0}; //获取自旋锁 KIRQL oldIrql; KeAcquireSpinLock(&pDevExt->ListSpinLock,&oldIrql); KdPrint(("******>> DeviceIoCtlStartio spinlock ")); //取出链表中数据 while(!IsListEmpty(&pDevExt->linkListHead)) { pEntry = RemoveTailList(&pDevExt->linkListHead); pData = CONTAINING_RECORD(pEntry,MYDATASTRUCT,ListEntry); buffer[index] = pData->ScanCode; buffer[index+1] = pData->Flags; index += 2; } KeReleaseSpinLock(&pDevExt->ListSpinLock,oldIrql); KdPrint(("<<****** DeviceIoCtlStartio spinlock ")); KdPrint(("+++++++++ list count is %d ",index/2)); //将取出的数据写入输出buffer RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,(void *)buffer,sizeof(USHORT)*index); ExFreePool(pData); //完毕irp Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = index*sizeof(USHORT); IoCompleteRequest(Irp, IO_NO_INCREMENT); } break; default: KeyFilterDispatchRoutine(fdo,Irp); } KdPrint(("++++++leave KeyFilterDeviceIoCtlStartio ")); return Irp->IoStatus.Status; } #pragma LOCKEDCODE //************************************ // Method: KeyFilterStartIO // Qualifier: startio函数 //************************************ void KeyFilterStartIO(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { KIRQL oldirql; KdPrint(("++++++Enter KeyFilterStartIO, IRP address ")); //自旋锁会将当前执行级别提高到DISPATCH_LEVEL,驱动程序假设想调用IoSetCancelRoutine,那么就得先获取这个lock。详细參考 //http://msdn.microsoft.com/en-us/library/windows/hardware/ff548196(v=vs.85).aspx IoAcquireCancelSpinLock(&oldirql); //fdo->CurrentIrp就是驱动当前正在处理的IRP。 if (Irp != fdo->CurrentIrp || Irp->Cancel) {//假设Irp不是当前处理的IRP,或者这个Irp是想取消的,那么直接返回。啥也不做。 IoReleaseCancelSpinLock(oldirql); KdPrint(("Do nothing ")); return; } else {//正在处理该IRP KdPrint(("Forbit to use CancelRoutine ")); IoSetCancelRoutine(Irp, NULL);//不同意调用取消例程 IoReleaseCancelSpinLock(oldirql); } //能够依据须要处理IRP PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); if (stack->MajorFunction == IRP_MJ_READ)//读请求 { KeyFilterReadStartio(fdo,Irp); } else if (stack->MajorFunction == IRP_MJ_DEVICE_CONTROL )//DEVICE_CONTROL { KeyFilterDeviceIoCtlStartio(fdo,Irp); } else//其它请求 { KeyFilterDispatchRoutine(fdo,Irp); } //在队列中读取下一个IRP,而且进行StartIO. IoStartNextPacket(fdo, TRUE); KdPrint(("++++++Leave KeyFilterStartIO, IRP address: 0x%x ", Irp)); } //************************************ // Method: KeyFilterRead // Qualifier: 读派遣函数 // Parameter: IN PDEVICE_OBJECT fdo 设备对象 // Parameter: IN PIRP Irp IO请求包 //************************************ NTSTATUS KeyFilterRead(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { NTSTATUS status = STATUS_PENDING; Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoMarkIrpPending(Irp);//将IRP设置为挂起状态(异步IRP) KdPrint(("start to call IoStartPacket, IRP ")); IoStartPacket(fdo, Irp, 0, KeyFilterCancelIRP); KdPrint(("end call IoStartPacket, IRP ")); return status; } #pragma LOCKEDCODE //************************************ // Method: KeyFilterReadCompletion // Qualifier: 读完毕回调函数 //************************************ NTSTATUS KeyFilterReadCompletion(PDEVICE_OBJECT fdo,PIRP Irp,PVOID Context) { KdPrint(("enter KeyFilterReadCompletion ")); PKEYBOARD_INPUT_DATA KeyData; int KeyNum; //得到设备扩展 PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION)fdo->DeviceExtension; //得到当前堆栈 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); //得到须要读设备的字节数 ULONG ReadLen = stack->Parameters.Read.Length; if (NT_SUCCESS(Irp->IoStatus.Status)) { //得到按键信息 KeyData = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer; //按键个数 KeyNum = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA); KIRQL oldIrql; for (int i = 0; i < KeyNum;i++) { KdPrint(("Scancode : %x ",KeyData[i].MakeCode)); KdPrint(("%s ",KeyData[i].Flags ? "Up":"Down")); PMYDATASTRUCT pData; pData = (PMYDATASTRUCT)ExAllocatePool(NonPagedPool,sizeof(MYDATASTRUCT)); pData->ScanCode = KeyData[i].MakeCode; pData->Flags = KeyData[i].Flags; //得到 spinlock KeAcquireSpinLock(&pDeviceExtension->ListSpinLock,&oldIrql); KdPrint(("********>> ReadCompletion spinlock ")); InsertHeadList(&pDeviceExtension->linkListHead,&pData->ListEntry); //释放 end spinlock KeReleaseSpinLock(&pDeviceExtension->ListSpinLock,oldIrql); KdPrint(("<<******** ReadCompletion spinlock ")); } } if (Irp->PendingReturned) { IoMarkIrpPending(Irp); } KdPrint(("leave KeyFilterReadCompletion ")); return Irp->IoStatus.Status; } //************************************ // Method: KeyFilterReadStartio // Qualifier: 处理读请求 //************************************ NTSTATUS KeyFilterReadStartio(PDEVICE_OBJECT fdo,PIRP Irp/*,PVOID Context*/) { PDEVICE_EXTENSION DeviceExtension; KdPrint(("enter KeyFilterReadStartio ")); DeviceExtension = (PDEVICE_EXTENSION)fdo->DeviceExtension; IoCopyCurrentIrpStackLocationToNext(Irp); //设置回调函数 IoSetCompletionRoutine(Irp, KeyFilterReadCompletion, NULL, TRUE, TRUE, TRUE); return IoCallDriver(DeviceExtension->NextStackDevice,Irp); } //************************************ // Method: KeyFilterDeviceIoCtl // Qualifier: DeviceIOControl 派遣函数 // Parameter: PDEVICE_OBJECT fdo 功能设备对象 // Parameter: PIRP Irp 从IO请求包 // Parameter: PVOID Context 上下文传过来的參数 //************************************ NTSTATUS KeyFilterDeviceIoCtl(PDEVICE_OBJECT fdo,PIRP Irp) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION DeviceExt = (PDEVICE_EXTENSION)fdo->DeviceExtension; ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; switch(code) { case IOCTL_SHOWKEYFILTER://应用程序发过来的得到按键消息的请求 KdPrint(("enter KeyFilterDeviceIoCtl: 0x%x ", Irp)); status = STATUS_PENDING; Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoMarkIrpPending(Irp);//将IRP设置为挂起状态(异步IRP) IoStartPacket(fdo, Irp, 0, KeyFilterCancelIRP); KdPrint(("leave KeyFilterDeviceIoCtl: 0x%x ", Irp)); break; default: break; } return status; } NTSTATUS KeyFilterUnHandleIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp) { KdPrint(("Irp: %d ", IoGetCurrentIrpStackLocation(Irp)->MajorFunction)); IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->NextStackDevice, Irp); } /************************************************************************ * 函数名称:DefaultPnpHandler * 功能描写叙述:对PNP IRP进行缺省处理 * 參数列表: pdx:设备对象的扩展 Irp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp) { PAGED_CODE(); KdPrint(("Enter DefaultPnpHandler ")); IoSkipCurrentIrpStackLocation(Irp); KdPrint(("Leave DefaultPnpHandler ")); return IoCallDriver(pdx->NextStackDevice, Irp); } /************************************************************************ * 函数名称:HandleRemoveDevice * 功能描写叙述:对IRP_MN_REMOVE_DEVICE IRP进行处理 * 參数列表: fdo:功能设备对象 Irp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp) { PAGED_CODE(); KdPrint(("Enter HandleRemoveDevice ")); Irp->IoStatus.Status = STATUS_SUCCESS; NTSTATUS status = DefaultPnpHandler(pdx, Irp); IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName); PLIST_ENTRY pEntry; PMYDATASTRUCT pData; //获取自旋锁 KIRQL oldIrql; KeAcquireSpinLock(&pdx->ListSpinLock,&oldIrql); KdPrint(("******>> DeviceIoCtlStartio spinlock ")); //取出链表中数据 while(!IsListEmpty(&pdx->linkListHead)) { pEntry = RemoveTailList(&pdx->linkListHead); pData = CONTAINING_RECORD(pEntry,MYDATASTRUCT,ListEntry); } KeReleaseSpinLock(&pdx->ListSpinLock,oldIrql); ExFreePool(pData); //调用IoDetachDevice()把fdo从设备栈中脱开: if (pdx->NextStackDevice) IoDetachDevice(pdx->NextStackDevice); //删除fdo: IoDeleteDevice(pdx->PDeviceObject); KdPrint(("Leave HandleRemoveDevice ")); return status; } /************************************************************************ * 函数名称:KeyFilterPnp * 功能描写叙述:对即插即用IRP进行处理 * 參数列表: fdo:功能设备对象 Irp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS KeyFilterPnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { PAGED_CODE(); KdPrint(("Enter KeyFilterPnp ")); NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) = { DefaultPnpHandler, // IRP_MN_START_DEVICE DefaultPnpHandler, // IRP_MN_QUERY_REMOVE_DEVICE HandleRemoveDevice, // IRP_MN_REMOVE_DEVICE DefaultPnpHandler, // IRP_MN_CANCEL_REMOVE_DEVICE DefaultPnpHandler, // IRP_MN_STOP_DEVICE DefaultPnpHandler, // IRP_MN_QUERY_STOP_DEVICE DefaultPnpHandler, // IRP_MN_CANCEL_STOP_DEVICE DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_RELATIONS DefaultPnpHandler, // IRP_MN_QUERY_INTERFACE DefaultPnpHandler, // IRP_MN_QUERY_CAPABILITIES DefaultPnpHandler, // IRP_MN_QUERY_RESOURCES DefaultPnpHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_TEXT DefaultPnpHandler, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS DefaultPnpHandler, // DefaultPnpHandler, // IRP_MN_READ_CONFIG DefaultPnpHandler, // IRP_MN_WRITE_CONFIG DefaultPnpHandler, // IRP_MN_EJECT DefaultPnpHandler, // IRP_MN_SET_LOCK DefaultPnpHandler, // IRP_MN_QUERY_ID DefaultPnpHandler, // IRP_MN_QUERY_PNP_DEVICE_STATE DefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION DefaultPnpHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION DefaultPnpHandler, // IRP_MN_SURPRISE_REMOVAL }; ULONG fcn = stack->MinorFunction; if (fcn >= arraysize(fcntab)) { // 未知的子功能代码 status = DefaultPnpHandler(pdx, Irp); // some function we don't know about return status; } #if DBG static char* fcnname[] = { "IRP_MN_START_DEVICE", "IRP_MN_QUERY_REMOVE_DEVICE", "IRP_MN_REMOVE_DEVICE", "IRP_MN_CANCEL_REMOVE_DEVICE", "IRP_MN_STOP_DEVICE", "IRP_MN_QUERY_STOP_DEVICE", "IRP_MN_CANCEL_STOP_DEVICE", "IRP_MN_QUERY_DEVICE_RELATIONS", "IRP_MN_QUERY_INTERFACE", "IRP_MN_QUERY_CAPABILITIES", "IRP_MN_QUERY_RESOURCES", "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", "IRP_MN_QUERY_DEVICE_TEXT", "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", "", "IRP_MN_READ_CONFIG", "IRP_MN_WRITE_CONFIG", "IRP_MN_EJECT", "IRP_MN_SET_LOCK", "IRP_MN_QUERY_ID", "IRP_MN_QUERY_PNP_DEVICE_STATE", "IRP_MN_QUERY_BUS_INFORMATION", "IRP_MN_DEVICE_USAGE_NOTIFICATION", "IRP_MN_SURPRISE_REMOVAL", }; KdPrint(("PNP Request (%s) ", fcnname[fcn])); #endif // DBG status = (*fcntab[fcn])(pdx, Irp); KdPrint(("Leave KeyFilterPnp ")); return status; } /************************************************************************ * 函数名称:KeyFilterDispatchRoutine * 功能描写叙述:对缺省IRP进行处理 * 參数列表: fdo:功能设备对象 Irp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS KeyFilterDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { //PAGED_CODE(); KdPrint(("Enter KeyFilterDispatchRoutine ")); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; // no bytes xfered IoCompleteRequest( Irp, IO_NO_INCREMENT ); KdPrint(("Leave KeyFilterDispatchRoutine ")); return STATUS_SUCCESS; } /************************************************************************ * 函数名称:KeyFilterUnload * 功能描写叙述:负责驱动程序的卸载操作 * 參数列表: DriverObject:驱动对象 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE void KeyFilterUnload(IN PDRIVER_OBJECT DriverObject) { PAGED_CODE(); KdPrint(("Enter KeyFilterUnload ")); KdPrint(("Leave KeyFilterUnload ")); }应用程序部分代码:
void CShowInputKeyDlg::OnBnClickedStart() { // TODO: Add your control notification handler code here CString ldebug; do { mParamStruct.mHdevice = CreateFile(L"\\.\KeyFilterSymLinkName0", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, // share mode none NULL, // no security OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); // no template if (mParamStruct.mHdevice == INVALID_HANDLE_VALUE) { CString ldebug; ldebug.Format(_T("--------------Failed to obtain file handle to device error : %d"),GetLastError()); OutputDebugString(ldebug); break; } mParamStruct.mHwndMain = GetSafeHwnd(); mThreadHandle = (HANDLE)_beginthreadex(NULL,0,ReadThread,(void*)&mParamStruct,0,NULL); } while (FALSE); }新建的线程函数为:
UINT CALLBACK ReadThread(LPVOID para) { PPARAM_STRUCT lParamStruct = (PPARAM_STRUCT)para; BOOL lbRet = TRUE; DWORD ReturnLen = 0; USHORT readBuffer[MAX_KEY_COUNT*2] = {0}; CString ldebug; do { HANDLE lhDevice = lParamStruct->mHdevice; HWND lHwnd = lParamStruct->mHwndMain; if (lhDevice == NULL || lHwnd == NULL) { break; } OutputDebugString(L"---------->ReadThread"); while(TRUE) { lbRet = DeviceIoControl(lhDevice,IOCTL_SHOWKEYFILTER,NULL,0,readBuffer, sizeof(readBuffer),&ReturnLen,NULL); if (lbRet == FALSE) { ldebug.Format(_T("DeviceIoControl error :0x%x."),GetLastError()); OutputDebugString(ldebug); break; } ldebug.Format(_T("----------- DeviceIoControl returnlen : %d"),ReturnLen); OutputDebugString(ldebug); if (ReturnLen == 0) { continue; } PostMessage(lHwnd,WM_INSERT_ITEM_MESSAGE,(WPARAM)readBuffer,(LPARAM)&ReturnLen); ldebug.Format(_T("----------- DeviceIoControl insert list end ")); OutputDebugString(ldebug); } } while (FALSE); OutputDebugString(L"<----------ReadThread"); _endthreadex( 0 ); return 0; }消息处理,界面显示:
BOOL CShowInputKeyDlg::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class USHORT Scancode; USHORT Flag; CString ldebug; if (pMsg->message == WM_INSERT_ITEM_MESSAGE) { OutputDebugString(L"WM_INSERT_ITEM_MESSAGE"); USHORT * readBuffer = (USHORT *)pMsg->wParam; PDWORD PReturnLen = (PDWORD)pMsg->lParam; CString lstrAction = NULL; for (DWORD index = 0;index < *PReturnLen/sizeof(USHORT);index += 2) { Scancode = readBuffer[index]; Flag = readBuffer[index+1]; lstrAction.Format(_T("%d"),mList.GetItemCount()+1); mList.InsertItem(mList.GetItemCount(),lstrAction); lstrAction.Format(_T("0x%x"),Scancode); mList.SetItemText(mList.GetItemCount()-1,1,lstrAction); UINT VkKey = MapVirtualKey(Scancode,MAPVK_VSC_TO_VK); if (VkKey != 0) { lstrAction.Format(_T("0x%x"),VkKey); mList.SetItemText(mList.GetItemCount()-1,2,lstrAction); } lstrAction.Format(_T("%ws"),Flag? L"Up" : L"Down"); mList.SetItemText(mList.GetItemCount()-1,3,lstrAction); //确保List Control最后一行可见 mList.EnsureVisible(mList.GetItemCount()-1,FALSE); } return TRUE;//直接返回true }else { return CDialogEx::PreTranslateMessage(pMsg); } }
完整代码请訪问:猛戳这里
学驱动不久。有不妥之处还望大家指正。