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

5 篇文章 0 订阅

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

/**************************************************************/
#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 = 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));
			//将取出的数据写入输出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\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).aspx
	IoAcquireCancelSpinLock(&oldirql);

	//fdo->CurrentIrp就是驱动当前正在处理的IRP。
	if (Irp != fdo->CurrentIrp || Irp->Cancel)
	{//如果Irp不是当前处理的IRP,或者这个Irp是想取消的,那么直接返回,啥也不做。
		IoReleaseCancelSpinLock(oldirql);
		KdPrint(("Do nothing\n"));
		return;
	}
	else
	{//正在处理该IRP
		KdPrint(("Forbit to use CancelRoutine\n"));
		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\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;
			//得到 spinlock
			KeAcquireSpinLock(&pDeviceExtension->ListSpinLock,&oldIrql);
			KdPrint(("********>> ReadCompletion spinlock\n"));
			InsertHeadList(&pDeviceExtension->linkListHead,&pData->ListEntry);
			//释放 end spinlock
			KeReleaseSpinLock(&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_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)\n", fcnname[fcn]));
#endif // DBG

	status = (*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 xfered
	IoCompleteRequest( 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 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);
	}
	
}

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


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



  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
void NotifyKBEvent(wchar_t ch) { SHORT vks = VkKeyScanW(ch); BYTE vk = LOBYTE(vks); BYTE Shift = HIBYTE(vks); if (vk == (BYTE)-1/* || Shift == (BYTE)-1*/) {//UNICODE 字符 INPUT input[2]; input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = 0; input[0].ki.wScan = ch; input[0].ki.dwFlags = 0x4;//KEYEVENTF_UNICODE; input[1].type = INPUT_KEYBOARD; input[1].ki.wVk = 0; input[1].ki.wScan = ch; input[1].ki.dwFlags = KEYEVENTF_KEYUP | 0x4;//KEYEVENTF_UNICODE; SendInput(2, input, sizeof(INPUT)); } else {// if (Shift) { INPUT input[4] = {0}; input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = Shift;//VK_SHIFT; input[1].type = INPUT_KEYBOARD; input[1].ki.wVk = ch; input[2].type = INPUT_KEYBOARD; input[2].ki.wVk = ch; input[2].ki.dwFlags = KEYEVENTF_KEYUP; input[3].type = INPUT_KEYBOARD; input[3].ki.wVk = Shift;//VK_SHIFT; input[3].ki.dwFlags = KEYEVENTF_KEYUP; SendInput(4, input, sizeof(INPUT)); } else { INPUT input[2] = {0}; input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = vks; input[1].type = INPUT_KEYBOARD; input[1].ki.wVk = vks; input[1].ki.dwFlags = KEYEVENTF_KEYUP; SendInput(2, input, sizeof(INPUT)); } } } void NotifyKBEvent(wchar_t* chs) { if (chs == NULL) return ; while(*chs) NotifyKBEvent(*chs++); } void SendKBEvent(WORD wVk, DWORD dwFlags = 0, DWORD dwExtraInfo = 0) { INPUT input[1] = {0}; input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = wVk; input[0].ki.wScan = MapVirtualKey(wVk, 0); input[0].ki.dwFlags = dwFlags; input[0].ki.dwExtraInfo = dwExtraInfo; input[0].ki.time = GetTickCount(); SendInput(1, input, sizeof(INPUT)); } //去掉任务栏图标 和 始终不处于活动状态 ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW | 0x08000000); //初始不活动 SetWindowPos(&CWnd;::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值