8.2.1 找到所有的键盘设备
先打开驱动对象KbdClass,然后绑定它下面的所有设备
//声明个全局变量 IoDeriverObjectType
extern POBJECT_TYPE IoDriverObjectType;
//KbdClass驱动的名字
#define KBD_DRIVER_NAME L"\\Driver\\kbdclass"
//这个函数是存在的,通过名字获取对象的指针,文档中没公开,声明下就可以用了
NTSTATUS
ObReferenceObjectByName(
PUNICODE_STRING ObjectNmae,
ULONG Attributes;
PACCESS_STATE AccessState,
ACCESS_MASK DesiredAccess;
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
PVOID ParseContext,
PVOID *Object
//这个函数经过改造能打开KbdClass驱动对象,然后绑定她下面的所有设备
NTSTATUS
c2pAttachDevices(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = 0;
UNICODE_STRING uniNtNameString;
PC2P_DEV_EXT devExt;
PDEVICE_OBJECT pFilterDeviceObject =NULL;
PDEVICE_OBJECT pTargetDeviceObject = NULL;
PDEVICE_OBJECT pLowerDeviceObject = NULL;
PDEVICE_OBJECT kbDriverObject =NULL;
kfPrint(("MyAttach\n"));
//初始化一个字符串,就是KbdClass驱动的名字
RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME);
//打开驱动对象
status = ObReferenceObjectByName(
&uniNtNameString,
OBJ_CASE_INSENSITIVE,
NULL,
0,
IoDriverObjectType,
KernelMode,
NULL,
&KbdDriverObject
);
//如果失败就直接返回
if(!NT_SUCCESS(status))
{
KdPrint(("MyAttach: Couldnot get the MyTest Device Object\n"));
return(status);
}
else
{
//调用ObRenferenceObjectByName会导致对驱动对象的引用计数增加必须相应的调用ObDerefenrenceObject函数解除引用
ObDereferenceObject(DriverObject);
}
//这是设备链里面的第一个设备
pTargetDeviceObject = KbdDriverObject->DeviceObject;
//现在开始遍历这个设备链
while(pTargetDeviceObject )
{
//生成过滤设备,IN宏和OUT宏都是空宏,只有标志意义,表明参数是输入或者输出
status = IoCreateDevice(
IN DriverObject,
IN sizeof(C2P_DEV_EXT),
IN NULL,
IN pTargetDeviceObject ->DeviceType,
IN pTargetDeviceObject ->Characteristics,
IN FALSE,
OUT &pFilterDeviceObject
);
//如果失败了退出
if(!NT_SUCCESS(status))
{
KdPrint(("MyAttach:couldn't create the MyFilter Filter Device Object
\n"));
return (status);
}
//绑定.pLowerDeviceObject是绑定之后得到的下一个设备
//也就是前面常说的真实设备
pLowerDeviceObject = IoAttachToDeviceStack(pFilterDeviceObject,pTargetDeviceObject);
//如果绑定失败了,放弃之前的操作,退出
if(!pLowerDeviceObject )
{
KdPrint(("MyAttach:couldn't attach to MyTest Device Object\n"));
IoDeleteDevice(pFilterDeviceObject);
pFilterDeviceObject = NULL;
return( status );
}
//设备扩展
devExt = (PC2P_DEV_EXT)(pFilterDeviceObject ->DeviceExtension);
c2pDeviceExtInit(
devExt,
pFilterDeviceObject,
pTargetDeviceObject,
pLowerDeviceObject
);
//拷贝标志位,和过滤串口的操作差不多
pFilterDeviceObject->DeviceType=pLowerDeviceObject->DeviceType;
pFilterDeviceObject->Characteristics=pLowerDeviceObject->Characteristics;
pFilterDeviceObject->StachSize=pLowerDeviceObject->StachSize+1;
pFilterDeviceObject->Flags |=pLowerDeviceObject->Flag &(DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGEBLE);
//移动到下一设备继续遍历
pTagrgetDeviceObject = pTargetDeviceObject->NextDevice;
}
return status;
}