驱动开发之 一个简单的截取键盘按键的驱动

news/2025/1/8 23:25:01/

近来在学驱动开发,自己写了一个简单地驱动程序,截取键盘按键,另外写的应用程序会显示按键。下面是驱动部分的关键代码,完整代码点击:猛戳这里

/**************************************************************/
#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\n"));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\n"));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\n"));//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\n",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\n",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\n"));return STATUS_SUCCESS;
}
#pragma PAGEDCODE
void KeyFilterCancelIRP(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{KdPrint(("Enter HelloWDMOnCancelIRP\n"));if (Irp == fdo->CurrentIrp){KIRQL oldirql = Irp->CancelIrql;//释放cancel自旋锁IoReleaseCancelSpinLock(Irp->CancelIrql);//继续下一个IRPIoStartNextPacket(fdo, TRUE);//降低IRQLKeLowerIrql(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\n"));
}
//************************************
// 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\n"));switch (code){case IOCTL_SHOWKEYFILTER:KdPrint(("IOCTL_SHOWKEYFILTER KeyFilterDeviceIoCtlStartio\n"));if (IsListEmpty(&pDevExt->linkListHead))//队列为空,完成irp{KdPrint(("list is empty.\n"));Irp->IoStatus.Status = STATUS_SUCCESS;Irp->IoStatus.Information = 0;IoCompleteRequest(Irp, IO_NO_INCREMENT);}else//队列中有数据,取出数据{KdPrint(("list have data\n"));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\n"));//取出链表中数据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\n"));KdPrint(("+++++++++ list count is %d\n",index/2));//将取出的数据写入输出bufferRtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,(void *)buffer,sizeof(USHORT)*index);ExFreePool(pData);//完成irpIrp->IoStatus.Status = STATUS_SUCCESS;Irp->IoStatus.Information = index*sizeof(USHORT);IoCompleteRequest(Irp, IO_NO_INCREMENT);}break;default:KeyFilterDispatchRoutine(fdo,Irp);}KdPrint(("++++++leave KeyFilterDeviceIoCtlStartio\n"));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\n"));//自旋锁会将当前运行级别提高到DISPATCH_LEVEL,驱动程序如果想调用IoSetCancelRoutine,那么就得先获取这个lock,具体参考//http://msdn.microsoft.com/en-us/library/windows/hardware/ff548196(v=vs.85).aspxIoAcquireCancelSpinLock(&oldirql);//fdo->CurrentIrp就是驱动当前正在处理的IRP。if (Irp != fdo->CurrentIrp || Irp->Cancel){//如果Irp不是当前处理的IRP,或者这个Irp是想取消的,那么直接返回,啥也不做。IoReleaseCancelSpinLock(oldirql);KdPrint(("Do nothing\n"));return;}else{//正在处理该IRPKdPrint(("Forbit to use CancelRoutine\n"));IoSetCancelRoutine(Irp, NULL);//不允许调用取消例程IoReleaseCancelSpinLock(oldirql);}//可以根据需要处理IRPPIO_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\n", 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\n"));IoStartPacket(fdo, Irp, 0, KeyFilterCancelIRP);KdPrint(("end call IoStartPacket, IRP\n"));return status;
}
#pragma LOCKEDCODE//************************************// Method:    KeyFilterReadCompletion// Qualifier: 读完成回调函数//************************************NTSTATUS KeyFilterReadCompletion(PDEVICE_OBJECT fdo,PIRP Irp,PVOID Context){KdPrint(("enter KeyFilterReadCompletion\n"));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 \n",KeyData[i].Flags ? "Up":"Down"));PMYDATASTRUCT pData;pData = (PMYDATASTRUCT)ExAllocatePool(NonPagedPool,sizeof(MYDATASTRUCT));pData->ScanCode = KeyData[i].MakeCode;pData->Flags = KeyData[i].Flags;//得到 spinlockKeAcquireSpinLock(&pDeviceExtension->ListSpinLock,&oldIrql);KdPrint(("********>> ReadCompletion spinlock\n"));InsertHeadList(&pDeviceExtension->linkListHead,&pData->ListEntry);//释放 end spinlockKeReleaseSpinLock(&pDeviceExtension->ListSpinLock,oldIrql);KdPrint(("<<******** ReadCompletion spinlock\n"));}}if (Irp->PendingReturned){IoMarkIrpPending(Irp);}KdPrint(("leave KeyFilterReadCompletion\n"));return Irp->IoStatus.Status;}//************************************
// Method:    KeyFilterReadStartio
// Qualifier: 处理读请求
//************************************
NTSTATUS KeyFilterReadStartio(PDEVICE_OBJECT fdo,PIRP Irp/*,PVOID Context*/)
{PDEVICE_EXTENSION DeviceExtension;KdPrint(("enter KeyFilterReadStartio\n"));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\n", 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\n", Irp));break;default:break;}return status;
}
NTSTATUS KeyFilterUnHandleIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{KdPrint(("Irp: %d\n", 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\n"));IoSkipCurrentIrpStackLocation(Irp);KdPrint(("Leave DefaultPnpHandler\n"));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\n"));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\n"));//取出链表中数据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\n"));return status;
}/************************************************************************
* 函数名称:KeyFilterPnp
* 功能描述:对即插即用IRP进行处理
* 参数列表:fdo:功能设备对象Irp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS KeyFilterPnp(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{PAGED_CODE();KdPrint(("Enter KeyFilterPnp\n"));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_DEVICEDefaultPnpHandler,		// IRP_MN_QUERY_REMOVE_DEVICEHandleRemoveDevice,		// IRP_MN_REMOVE_DEVICEDefaultPnpHandler,		// IRP_MN_CANCEL_REMOVE_DEVICEDefaultPnpHandler,		// IRP_MN_STOP_DEVICEDefaultPnpHandler,		// IRP_MN_QUERY_STOP_DEVICEDefaultPnpHandler,		// IRP_MN_CANCEL_STOP_DEVICEDefaultPnpHandler,		// IRP_MN_QUERY_DEVICE_RELATIONSDefaultPnpHandler,		// IRP_MN_QUERY_INTERFACEDefaultPnpHandler,		// IRP_MN_QUERY_CAPABILITIESDefaultPnpHandler,		// IRP_MN_QUERY_RESOURCESDefaultPnpHandler,		// IRP_MN_QUERY_RESOURCE_REQUIREMENTSDefaultPnpHandler,		// IRP_MN_QUERY_DEVICE_TEXTDefaultPnpHandler,		// IRP_MN_FILTER_RESOURCE_REQUIREMENTSDefaultPnpHandler,		// DefaultPnpHandler,		// IRP_MN_READ_CONFIGDefaultPnpHandler,		// IRP_MN_WRITE_CONFIGDefaultPnpHandler,		// IRP_MN_EJECTDefaultPnpHandler,		// IRP_MN_SET_LOCKDefaultPnpHandler,		// IRP_MN_QUERY_IDDefaultPnpHandler,		// IRP_MN_QUERY_PNP_DEVICE_STATEDefaultPnpHandler,		// IRP_MN_QUERY_BUS_INFORMATIONDefaultPnpHandler,		// IRP_MN_DEVICE_USAGE_NOTIFICATIONDefaultPnpHandler,		// IRP_MN_SURPRISE_REMOVAL};ULONG fcn = stack->MinorFunction;if (fcn >= arraysize(fcntab)){						// 未知的子功能代码status = DefaultPnpHandler(pdx, Irp); // some function we don't know aboutreturn status;}						#if DBGstatic 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)\n", fcnname[fcn]));
#endif // DBGstatus = (*fcntab[fcn])(pdx, Irp);KdPrint(("Leave KeyFilterPnp\n"));return status;
}/************************************************************************
* 函数名称:KeyFilterDispatchRoutine
* 功能描述:对缺省IRP进行处理
* 参数列表:fdo:功能设备对象Irp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS KeyFilterDispatchRoutine(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{//PAGED_CODE();KdPrint(("Enter KeyFilterDispatchRoutine\n"));Irp->IoStatus.Status = STATUS_SUCCESS;Irp->IoStatus.Information = 0;	// no bytes xferedIoCompleteRequest( Irp, IO_NO_INCREMENT );KdPrint(("Leave KeyFilterDispatchRoutine\n"));return STATUS_SUCCESS;
}/************************************************************************
* 函数名称:KeyFilterUnload
* 功能描述:负责驱动程序的卸载操作
* 参数列表:DriverObject:驱动对象
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
void KeyFilterUnload(IN PDRIVER_OBJECT DriverObject)
{PAGED_CODE();KdPrint(("Enter KeyFilterUnload\n"));KdPrint(("Leave KeyFilterUnload\n"));
}
应用程序部分代码:

void CShowInputKeyDlg::OnBnClickedStart()
{// TODO: Add your control notification handler code hereCString ldebug;do {mParamStruct.mHdevice = CreateFile(L"\\\\.\\KeyFilterSymLinkName0",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,		// share mode noneNULL,	// no securityOPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL );		// no templateif (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 classUSHORT 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);}}

完整代码请访问: 猛戳这里


学驱动不久,有不妥之处还望大家指正。




http://www.ppmy.cn/news/456230.html

相关文章

独立按键和矩阵键盘驱动原理

博主福利&#xff1a;100G电子设计学习资源包&#xff01; http://mp.weixin.qq.com/mp/homepage?__bizMzU3OTczMzk5Mg&hid7&snad5d5d0f15df84f4a92ebf72f88d4ee8&scene18#wechat_redirect -------------------------------------------------------------------…

基于N32G45的按键驱动

基于N32G45的按键驱动 1.N32G45简介 N32G45系列集成了最新一代嵌入式ARM Cortex™-M4F处理器&#xff0c;在Cortex™-M3内核的基础上强化了运算能力、新增加了浮点运算处理单元&#xff08;FPU&#xff09;、DSP和并行计算指令&#xff0c;提供1.25DMIPS/MHz的优异性能。同时其…

开发操作系统(2)键盘驱动

做一个操作系统&#xff0c;不可能只在屏幕上打印字符&#xff0c;不让用户操作吧。 int 16h键盘驱动&#xff0c;详细ah功能号如下 ah0 读取键盘并等待键盘发出反应。 输出&#xff1a; ah属性&#xff08;应该是在键盘上的位置&#xff09; al字符 ah1 读取键盘但不等…

驱动中实现模拟键盘按键

分享一下我老师大神的人工智能教程&#xff01;零基础&#xff0c;通俗易懂&#xff01;http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章。分享知识&#xff0c;造福人民&#xff0c;实现我们中华民族伟大复兴&#xff01; 标 题: 驱动中实现模拟键盘按键 作 者: lu…

天行数据土味情话API接口调用接口

天行数据土味情话API接口调用 注册天行数据账号申请"土味情话"接口下载微信开发工具创建一个空项目将下面的key填到是链接上即可请求成功 https://apis.tianapi.com/topnews/index?keyKEY // pages/index/index.js Page({/*** 页面的初始数据*/data: {// 渲染到视…

ESP8266通过HTTPClient获取天行数据平台数据

ESP8266通过HTTPClient获取天行数据平台数据 📌天行数据平台:https://www.tianapi.com/,提供丰富的API接口数据。🌿通过Httpclient获取获取古诗词📋开发板:Nodemcu1.0🔖支持库版本:2.7.4📝实例代码 #include <ESP8266WiFi.h> #include <ESP8266HTTPClie…

iphone版 天行skyline_‎App Store 上的“Pergola SKYLINE”

Aplikace SKYLINE umožňuje zobrazit bioklimatickou pergolu SKYLINE u jakkoliv budovy nebo v prostoru. SKYLINE je hlinkov pergola zastřešen motorizovanm slunolamem, kter funguje jako protislunečn a protidešťov ochrana, a zroveň v horkm ltě umožňuj…

【jQuery】基于天行数据接口的天气预报

一、准备工作 1、注册天行数据账号 2、申请接口 3、在天行数据搜索天气预报&#xff0c;点击进去后申请 4、申请之后点击导航栏上的控制台&#xff0c;进入之后再数据管理 这个key调接口需要的&#xff0c;每个人不一样的&#xff0c;注意隐私&#xff01; 5、熟悉接口文档 1…