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


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

    /**************************************************************/
    #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
    "));
    
    	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
    "));
    	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
    "));
    	//
    	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
    ",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
    ",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
    "));
    	return STATUS_SUCCESS;
    }
    #pragma PAGEDCODE
    void KeyFilterCancelIRP(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
    {
    	KdPrint(("Enter HelloWDMOnCancelIRP
    "));
    
    	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
    "));
    }
    //************************************
    // 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
    "));
    	switch (code)
    	{
    	case IOCTL_SHOWKEYFILTER:
    		KdPrint(("IOCTL_SHOWKEYFILTER KeyFilterDeviceIoCtlStartio
    "));
    		if (IsListEmpty(&pDevExt->linkListHead))//队列为空,完毕irp
    		{
    			KdPrint(("list is empty.
    "));
    			Irp->IoStatus.Status = STATUS_SUCCESS;
    			Irp->IoStatus.Information = 0;
    			IoCompleteRequest(Irp, IO_NO_INCREMENT);
    		}
    		else//队列中有数据,取出数据
    		{
    			KdPrint(("list have data
    "));
    			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
    "));
    			//取出链表中数据
    			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
    "));
    			KdPrint(("+++++++++ list count is %d
    ",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
    "));
    
    	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
    "));
    	//自旋锁会将当前执行级别提高到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
    "));
    		return;
    	}
    	else
    	{//正在处理该IRP
    		KdPrint(("Forbit to use CancelRoutine
    "));
    		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
    ", 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
    "));
    	IoStartPacket(fdo, Irp, 0, KeyFilterCancelIRP);
    	KdPrint(("end call IoStartPacket, IRP
    "));
    	return status;
    }
    #pragma LOCKEDCODE
     //************************************
     // Method:    KeyFilterReadCompletion
     // Qualifier: 读完毕回调函数
     //************************************
     NTSTATUS KeyFilterReadCompletion(PDEVICE_OBJECT fdo,PIRP Irp,PVOID Context)
     {
     	KdPrint(("enter KeyFilterReadCompletion
    "));
     	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 
    ",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
    "));
    			InsertHeadList(&pDeviceExtension->linkListHead,&pData->ListEntry);
    			//释放 end spinlock
    			KeReleaseSpinLock(&pDeviceExtension->ListSpinLock,oldIrql);
    			KdPrint(("<<******** ReadCompletion spinlock
    "));
     		}
    
     	}
     	if (Irp->PendingReturned)
     	{
     		IoMarkIrpPending(Irp);
     	}
     	KdPrint(("leave KeyFilterReadCompletion
    "));
     	return Irp->IoStatus.Status;
     }
    
    //************************************
    // Method:    KeyFilterReadStartio
    // Qualifier: 处理读请求
    //************************************
    NTSTATUS KeyFilterReadStartio(PDEVICE_OBJECT fdo,PIRP Irp/*,PVOID Context*/)
    {
    	PDEVICE_EXTENSION DeviceExtension;
    	KdPrint(("enter KeyFilterReadStartio
    "));
    	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
    ", 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
    ", Irp));
    		break;
    	default:
    		break;
    	}
    	return status;
    }
    NTSTATUS KeyFilterUnHandleIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    
    	KdPrint(("Irp: %d
    ", 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
    "));
    	IoSkipCurrentIrpStackLocation(Irp);
    	KdPrint(("Leave DefaultPnpHandler
    "));
    	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
    "));
    
    	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
    "));
    	//取出链表中数据
    	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
    "));
    	return status;
    }
    
    /************************************************************************
    * 函数名称:KeyFilterPnp
    * 功能描写叙述:对即插即用IRP进行处理
    * 參数列表:
          fdo:功能设备对象
          Irp:从IO请求包
    * 返回 值:返回状态
    *************************************************************************/
    #pragma PAGEDCODE
    NTSTATUS KeyFilterPnp(IN PDEVICE_OBJECT fdo,
                            IN PIRP Irp)
    {
    	PAGED_CODE();
    
    	KdPrint(("Enter KeyFilterPnp
    "));
    	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)
    ", fcnname[fcn]));
    #endif // DBG
    
    	status = (*fcntab[fcn])(pdx, Irp);
    	KdPrint(("Leave KeyFilterPnp
    "));
    	return status;
    }
    
    /************************************************************************
    * 函数名称:KeyFilterDispatchRoutine
    * 功能描写叙述:对缺省IRP进行处理
    * 參数列表:
          fdo:功能设备对象
          Irp:从IO请求包
    * 返回 值:返回状态
    *************************************************************************/
    #pragma PAGEDCODE
    NTSTATUS KeyFilterDispatchRoutine(IN PDEVICE_OBJECT fdo,
    								 IN PIRP Irp)
    {
    	//PAGED_CODE();
    	KdPrint(("Enter KeyFilterDispatchRoutine
    "));
    	Irp->IoStatus.Status = STATUS_SUCCESS;
    	Irp->IoStatus.Information = 0;	// no bytes xfered
    	IoCompleteRequest( Irp, IO_NO_INCREMENT );
    	KdPrint(("Leave KeyFilterDispatchRoutine
    "));
    	return STATUS_SUCCESS;
    }
    
    /************************************************************************
    * 函数名称:KeyFilterUnload
    * 功能描写叙述:负责驱动程序的卸载操作
    * 參数列表:
          DriverObject:驱动对象
    * 返回 值:返回状态
    *************************************************************************/
    #pragma PAGEDCODE
    void KeyFilterUnload(IN PDRIVER_OBJECT DriverObject)
    {
    	PAGED_CODE();
    	KdPrint(("Enter KeyFilterUnload
    "));
    	KdPrint(("Leave KeyFilterUnload
    "));
    }
    应用程序部分代码:

    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);
    	}
    	
    }

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


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





  • 相关阅读:
    app测试的一些较为重要的测试点
    adb工作常用命令
    vue中$attrs $listeners你会用吗?
    Vue中组件通信的常用方式
    Vue中watch 的用法
    VUE中使用 async await 将 axios 异步请求同步化处理
    安装spyder记录
    树莓CM3开机连接WIFI
    树莓派搭建seafile服务器备忘
    关于JAVA数据结构_线性表(通过单向链表实现)的学习
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5303393.html
Copyright © 2020-2023  润新知