首页 > 代码库 > 一个简单的截取键盘按键的驱动
一个简单的截取键盘按键的驱动
近来在学驱动开发,自己写了一个简单地驱动程序,截取键盘按键,另外写的应用程序会显示按键。下面是驱动部分的关键代码,完整代码点击:猛戳这里
/**************************************************************/ #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); //继续下一个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\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 = http://www.mamicode.com/CONTAINING_RECORD(pEntry,MYDATASTRUCT,ListEntry);>应用程序部分代码: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); } }
完整代码请访问:猛戳这里
学驱动不久,有不妥之处还望大家指正。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。