RegistryPath) //入口函数
{
PDRIVER_OBJECT kbdDriverObject;
UNICODE_STRING uniNtNameString;
NTSTATUS status=NULL;
NTSTATUS ObReferenceObjectByName(PUNICODESTRING ObjectName,
//这个函数文档里没有,但申明一下就可以直接使用
ULONG Attributes,
PACCESS_STATE AccessState,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
PVOID ParseContext,
PVOID *Object);
RtlInitUnicodeString(&uniNtNameString,KBD_DRIVER_NAME);
//初始化为0
status=ObReferenceObjectByName(
//得到并打开设备
&uniNtNameString,
OBJ_CASE_INSENSITIVE,
NULL,
0,
IoDriverObjectType,
KernelMode,
NULL,
&kbdDriverObject);
if(!NT_SUCCESS(status))
{
DbgPrint("cannot get the kbd object\n");
return STATUS_UNSUCCESSFUL;
}
else
{
ULONG i;
//PDRIVER_DISPATCH OldDispatchFunctions[IRP_MJ_MAXIMUM_FUNCTION+1];
OldDispatchRead = kbdDriverObject->MajorFunction[IRP_MJ_READ];// 保存原
IRP_MJ_READ函数的入口地址
InterlockedExchangePointer(&kbdDriverObject->MajorFunction[IRP_MJ_READ],New
DispatchRead);//替换为自定义的新分发函数的地址
ObDereferenceObject(kbdDriverObject); //不要忘记解除调用
}
DriverObject->DriverUnload=DriverUnload;
return STATUS_SUCCESS;
}
然后我们来写我们自己的分发函数,在这个分发函数中,我们要定义一个完成函数,以
便请求完成的时候,能够调用我们的完成函数。
NTSTATUS NewDispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp) //
新的分发函数
{
PIO_STACK_LOCATION irpSp; //以
下的内容都是新分发函数的新增内容
irpSp = IoGetCurrentIrpStackLocation(Irp);
irpSp->Control =
SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR|SL_INVOKE_ON_CANCEL;
//保留原来的完成函数,如果有的话
irpSp->Context = irpSp->CompletionRoutine;
irpSp->CompletionRoutine = (PIO_COMPLETION_ROUTINE)OnReadCompletion; //
这个是完成函数
return OldDispatchRead(pDeviceObject,Irp); //调用原来的分
发函数,完成应该有的内容
}
最后我们就要为我们的完成函数写自己的代码了,这里我只做简单的打印,打印出的是
读取键盘输入,但要注意的是键盘按下和弹起都有扫描码,打印其中之一就行。
NTSTATUS OnReadCompletion(IN PDRIVER_OBJECT DriverObject,
IN PIRP Irp,
IN PVOID Context
) //完成函数
{
PIO_STACK_LOCATION IrpSp;
PUCHAR buf=NULL;
IrpSp=IoGetCurrentIrpStackLocation(Irp); |