过滤驱动 代码例子来源: Win驱动9]Windows分层驱动_windows分层驱动程序 数据-CSDN博客
过滤驱动是一种独立的驱动程序,直接插入内核驱动栈中,拦截并处理驱动程序之间的数据传输。它可以拦截底层的I/O请求,并在不改变原始请求的情况下,修改、延迟或直接处理这些请求。
过滤驱动 :位于设备驱动程序堆栈的上层,负责拦截、修改和处理 I/O 请求或响应,并可能将其转发给目标驱动。
目标驱动 :位于设备驱动程序堆栈的下层,直接与硬件交互,处理实际的 I/O 操作。
和注册回调的区别: 过滤驱动运行在内核模式下的驱动栈中,拦截并处理I/O请求;回调函数则在某些事件发生时被内核或应用调用,可能在用户模式或内核模式下运行。 过滤驱动可以拦截设备级的I/O请求(如文件读写、网络包),而回调函数通常处理系统事件(如进程创建、线程创建、加载模块等)。 过滤驱动适合用于文件系统、网络、设备的深度控制和拦截;回调函数则用于监控和响应特定的系统事件,例如进程管理、内存分配等。
最重要的是:这玩意贼稳定,受微软支持的,想附加就附加
当请求完成的时候,会调用完成例程函数,用以下函数可以添加,可以从里面获取到键盘扫描码….吗?
但是我们还是会使用原来的键盘回调,等于又把完成例程函数修改回去了,所以这个方法并不可行
完成例程函数 通过IoSetCompletionRoutine
设置的完成例程函数 (Completion Routine)在 Windows 驱动开发中主要用于在 I/O 请求(IRP)完成后执行一些额外的操作。
1 2 3 4 5 NTSTATUS CompletionRoutine ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) ;
调用时机:
当一个IRP请求调用了IoCompleteRequest
,促使古I/O管理器就会检查IRP是否已经设置好了完成例程函数,如果设置了执行IoSetCompletionRoutine
关联的完成例程。
DPC例程 DPC例程(Deferred Procedure Call,延迟过程调用) 是 Windows 内核中的一种机制,允许高优先级的任务将某些工作推迟到稍后执行,通常在一个相对较低的中断请求级别(IRQL)。这有助于优化系统性能,避免在高优先级的中断上下文中执行过多的工作。
在这里的应用场景是,当驱动程序在处理异步 I/O 请求时,会利用 DPC 来处理请求的完成例程。
例如 键盘驱动程序会在用户按下某个键时生成一个扫描码 。此时,键盘驱动会将扫描码存入 IRP
的缓冲区,并调用 IoCompleteRequest
。 所以我们就可以通过DPC例程,等待一段时间后,自己注册一个完成例程函数,然后从完成例程函数里面读出来扫描码
注意注意,调用CreateFile一定在驱动程序用注册Create的IRP例程!
实战目标驱动,过滤驱动 目标驱动代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 #include "header.h" typedef struct _DEVICE_EXTENSION { UNICODE_STRING ustrDevName; UNICODE_STRING ustrSymName; PDEVICE_OBJECT pDevice; PIRP pCurrentIrp; KDPC Dpc; KTIMER Timer; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; NTSTATUS DispatchRoutine (PDEVICE_OBJECT pDev, PIRP pIrp) { pDev; pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0 ; IoCompleteRequest (pIrp, IO_NO_INCREMENT); return (STATUS_SUCCESS); } NTSTATUS WriteRoutine (PDEVICE_OBJECT pDev, PIRP pIrp) { pDev; KdPrint (("进入WriteRoutine\n" )); pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0 ; IoCompleteRequest (pIrp, IO_NO_INCREMENT); KdPrint (("离开WriteRoutine\n" )); return (STATUS_SUCCESS); } NTSTATUS ReadRoutine (PDEVICE_OBJECT pDev, PIRP pIrp) { KdPrint (("DriverA: 进入ReadRoutine\n" )); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDev->DeviceExtension; IoMarkIrpPending (pIrp); pdx->pCurrentIrp = pIrp; LARGE_INTEGER timeout; timeout.QuadPart = -30 * 1000 * 1000 ; KeSetTimer (&pdx->Timer, timeout, &pdx->Dpc); KdPrint (("DriverA: 离开ReadRoutine\n" )); return (STATUS_PENDING); } void DPCRoutine (PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) { Dpc; SystemArgument1; SystemArgument2; KdPrint (("DPC例程: 进入了DPC例程\n" )); PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)DeferredContext; PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; PIRP pIrp = pDevExt->pCurrentIrp; pIrp->IoStatus.Information = 0 ; pIrp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest (pIrp, IO_NO_INCREMENT); KdPrint (("DPC例程完成了挂起的IRP请求\n" )); KdPrint (("DPC例程: 离开了DPC例程\n" )); } NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER (RegistryPath); KdPrint (("Create!" )); KdBreakPoint (); DriverObject->DriverUnload = DriverUnloadRoutine; for (int i = 0 ; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) DriverObject->MajorFunction[i] = DispatchRoutine; DriverObject->MajorFunction[IRP_MJ_READ] = ReadRoutine; NTSTATUS status; PDEVICE_OBJECT DeviceObject = NULL ; UNICODE_STRING DeviceName; RtlInitUnicodeString (&DeviceName, L"\\Device\\HelloDDKA" ); status = IoCreateDevice ( DriverObject, sizeof (DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_UNKNOWN, 0 , FALSE, &DeviceObject ); if (!NT_SUCCESS (status)) { KdPrint (("Failed to create device: %X\n" , status)); return status; } KdPrint (("Device created successfully\n" )); UNICODE_STRING symbolicLink = RTL_CONSTANT_STRING (L"\\??\\HelloDDKA" ); status = IoCreateSymbolicLink (&symbolicLink, &DeviceName); if (!NT_SUCCESS (status)) { KdPrint (("Failed to create device: %X\n" , status)); return status; } KdPrint (("Device created successfully\n" )); PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; pDevExt->pDevice = DeviceObject; pDevExt->ustrDevName = DeviceName; KeInitializeTimer (&pDevExt->Timer); KeInitializeDpc (&pDevExt->Dpc, DPCRoutine, DeviceObject); RtlInitUnicodeString (&pDevExt->ustrSymName, L"\\??\\HelloDDKA" ); return STATUS_SUCCESS; } VOID DriverUnloadRoutine (IN PDRIVER_OBJECT DriverObject) { PDEVICE_OBJECT pNextDev = DriverObject->DeviceObject; while (pNextDev) { PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextDev->DeviceExtension; KdPrint (("符号链接名: %wZ\n" , pDevExt->ustrSymName)); IoDeleteSymbolicLink (&pDevExt->ustrSymName); IoDeleteDevice (pDevExt->pDevice); pNextDev = pNextDev->NextDevice; } DbgPrint ("Driver unloaded\n" ); }
过滤驱动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 #include "header.h" typedef struct _DEVICE_EXTENSION { UNICODE_STRING ustrDevName; PDEVICE_OBJECT pDevice; PDEVICE_OBJECT pTargetDev; } DEVICE_EXTENSION, * PDEVICE_EXTENSION; NTSTATUS ReadRoutine (PDEVICE_OBJECT pDev, PIRP pIrp) { KdPrint (("DriverB: 进入ReadRoutine\n" )); PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDev->DeviceExtension; IoSkipCurrentIrpStackLocation (pIrp); NTSTATUS status = IoCallDriver (pDevExt->pTargetDev, pIrp); KdPrint (("DriverB: 离开ReadRoutine\n" )); return (status); } NTSTATUS CloseRoutine (IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint (("DriverB:Enter B CloseRoutine\n" )); NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; IoSkipCurrentIrpStackLocation (pIrp); ntStatus = IoCallDriver (pdx->pTargetDev, pIrp); KdPrint (("DriverB:Leave B CloseRoutine\n" )); return ntStatus; } NTSTATUS CreateRoutine (IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint (("DriverB:Enter B CreateRoutine\n" )); NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; IoSkipCurrentIrpStackLocation (pIrp); ntStatus = IoCallDriver (pdx->pTargetDev, pIrp); KdPrint (("DriverB:Leave B CreateRoutine\n" )); return ntStatus; } NTSTATUS DispatchRoutine (PDEVICE_OBJECT pDev, PIRP pIrp) { pDev; pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0 ; IoCompleteRequest (pIrp, IO_NO_INCREMENT); return (STATUS_SUCCESS); } NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER (RegistryPath); KdPrint (("Create!" )); KdBreakPoint (); DriverObject->DriverUnload = DriverUnloadRoutine; for (int i = 0 ; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) DriverObject->MajorFunction[i] = DispatchRoutine; DriverObject->MajorFunction[IRP_MJ_READ] = ReadRoutine; DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateRoutine; DriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseRoutine; UNICODE_STRING DeviceName; NTSTATUS status = NULL ; PDEVICE_OBJECT pDevObj; RtlInitUnicodeString (&DeviceName, L"\\Device\\HelloDDKB" ); status = IoCreateDevice (DriverObject, sizeof (DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_UNKNOWN, 0 , TRUE, &pDevObj); if (!NT_SUCCESS (status)) { KdPrint (("IoCreateDevice %08X\n" , status)); return (status); } pDevObj->Flags |= DO_BUFFERED_IO; PDEVICE_OBJECT pFilterDevObj = pDevObj; UNICODE_STRING ustrTargetDevName; PFILE_OBJECT pFileObj; PDEVICE_OBJECT pTargetDevObj, pTarget; RtlInitUnicodeString (&ustrTargetDevName, L"\\Device\\HelloDDKA" ); status = IoGetDeviceObjectPointer (&ustrTargetDevName, FILE_ALL_ACCESS, &pFileObj, &pTargetDevObj); if (!NT_SUCCESS (status)) { KdPrint (("IoGetDeviceObjectPointer %08X\n" , status)); return (status); } pTarget = IoAttachDeviceToDeviceStack (pFilterDevObj, pTargetDevObj); if (pTarget==NULL ) { ObDereferenceObject (pFileObj); IoDeleteDevice (pFilterDevObj); KdPrint (("附加失败!\n" )); return (STATUS_UNSUCCESSFUL); } PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pFilterDevObj->DeviceExtension; pDevExt->pTargetDev = pTarget; pFilterDevObj->Flags |= (pTarget->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO)); pFilterDevObj->Flags &= ~DO_DEVICE_INITIALIZING; pFilterDevObj->Characteristics = pTarget->Characteristics; pFilterDevObj->DeviceType = pTarget->DeviceType; ObDereferenceObject (pFileObj); return STATUS_SUCCESS; } VOID DriverUnloadRoutine (IN PDRIVER_OBJECT DriverObject) { PDEVICE_OBJECT pDevObj = DriverObject->DeviceObject; while (pDevObj) { PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; IoDetachDevice (pDevExt->pTargetDev); IoDeleteDevice (pDevExt->pDevice); pDevObj = pDevObj->NextDevice; } DbgPrint ("Driver unloaded\n" ); }
应用程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <windows.h> #include <stdio.h> int main () { const WCHAR* psz = L"\\\\.\\HelloDDKA" ; HANDLE hDev = CreateFile (psz, GENERIC_READ | GENERIC_WRITE, 0 , NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hDev==INVALID_HANDLE_VALUE) { printf ("无效句柄\n" ); system ("pause" ); return (-1 ); } DWORD dwRead = 0 ; ReadFile (hDev, NULL , 0 , &dwRead, NULL ); CloseHandle (hDev); system ("pause" ); return (0 ); }
运行起来结果如下:
我们捋一下流程,选取Read_MJ_IRP来举例:
首先应用程序调用了ReadFile函数,ReadFile会调用NTDLL里的NtReadFile
NTDLL中的NtReadFile会调用系统调用中的NtReadFile
系统调用的NtReadFile会发送IRP_MJ_READ类型的IRP请求给对应的驱动设备(这里是目标驱动设备,也就是HelloDDKA)
我们附加的是HelloDDKB,附加在HelloDDKA上面,因为IRP都是从设备栈的栈顶开始自顶而下传递的,所以HelloDDKB首先截获IRP
HelloDDKB截获,所以先根据IRP类型进入了HelloDDKB的ReadRoutine里面
根据过滤驱动写的代码,ReadRoutine什么也不做,将其转发给了目标驱动HelloDDKA,并保留当前的IO环境,并阻塞在IoCallDriver上
HelloDDKA就接收到了IRP请求,并根据类型派遣到HelloDDKA的处理函数ReadRoutine
ReadRoutine将其挂起,并设置了DPC例程后直接返回挂起状态
但是此时因为HelloDDKB的IRP_MJ_READ还没有被结束, IRP_MJ_READ
请求 的处理通常需要等待调用 IoCompleteRequest(pIrp, IO_NO_INCREMENT)
后才算正式结束,完成例程函数也是在 IoCompleteRequest
调用后被触发。
3秒后DPC例程被触发,被挂起的IRP请求完成
此时IRP会沿着设备栈向上返回,解除HelloDDKB中IoCallDriver的阻塞状态并继续执行
经过一步步网上返回后最终会将运行结果返回应用层的ReadFile函数
用过滤驱动拿到键盘扫描码 查阅资料可以知道这玩意是键盘的驱动,我们通过附加这个驱动,获取到键盘的扫描码
ObReferenceObjectByName
:可以根据名字拿到驱动对象,是一个导出函数,需要声明一下才能用,注意要用C语言的符号导出,cpp会额外加一些奇奇怪怪的符号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 extern "C" { NTSTATUS ObReferenceObjectByName ( __in PUNICODE_STRING ObjectName, __in ULONG Attributes, __in_opt PACCESS_STATE AccessState, __in_opt ACCESS_MASK DesiredAccess, __in POBJECT_TYPE ObjectType, __in KPROCESSOR_MODE AccessMode, __inout_opt PVOID ParseContext, __out PVOID* Object ) ;} status = ObReferenceObjectByName ( &driverName, OBJ_CASE_INSENSITIVE, NULL , KernelMode, *IoDriverObjectType, KernelMode, NULL , (PVOID*)&KbdDriver)
键盘扫描码通常是在键盘类驱动(kbdclass.sys
)的完成例程 中被处理并返回的
因为中断处理要求的是快,我们不能在读IRP分发函数做一些耗时的工作(比如获取、替换键值等操作),那样的话会导致系统变卡,所以我们只在ReadDispatch中做一个关键操作,设置IRP完成回调函数,意思是指读IRP完成后,再由系统来调用操作键值的函数,那样就不会耽误IRP的传递了。
IRP请求只有一个,可以被传递
完成例程函数 是在**IoCompleteRequest
** 执行后立即调用的。完成例程是一个回调函数,它会在驱动程序调用 IoCompleteRequest
标记 IRP 为完成时触发执行。
IoCallDriver是否立即返回,得看目标驱动的例程函数是啥,如果是同步,则会阻塞,如果是异步,那么就会立即返回,过滤驱动继续完成例程函数代码
同步的情况:
1 2 3 4 5 6 7 8 9 10 11 NTSTATUS TargetDriverReadRoutine (PDEVICE_OBJECT DeviceObject, PIRP Irp) { KdPrint (("Target driver processing IRP synchronously\n" )); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0 ; IoCompleteRequest (Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; }
异步的情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 NTSTATUS TargetDriverReadRoutine (PDEVICE_OBJECT DeviceObject, PIRP Irp) { KdPrint (("Target driver processing IRP asynchronously\n" )); IoMarkIrpPending (Irp); return STATUS_PENDING; } VOID CompleteIrpLater (PIRP Irp) { Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest (Irp, IO_NO_INCREMENT); }
为什么我们能拿到键盘扫描码呢?过滤驱动和目标驱动的IRP堆栈的内容不是不共享吗? 答:IRP堆栈不共享,但是SystemBuffer是共享的,我们从SystemBuffer里拿键盘扫描码
键盘驱动在注册的时候,已经提前发了一个IRP_MJ_READ请求,并挂起(于键盘驱动挂起,等待用户按下)
在执行完例程函数后,IRP(I/O请求数据包)请求并不一定就结束了,有些操作是异步的,执行完例程函数后,可能还需要等待其他硬件或驱动程序的响应。挂起可以确保在收到响应之前不释放IRP。
所以在过滤驱动中,我们需要加这一句,确保不出错
1 2 3 4 5 if (Irp->PendingReturned){ IoMarkIrpPending (Irp); } return Irp->IoStatus.Status;
过滤驱动完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 #pragma once extern "C" { #include <ntifs.h> #include <ntddk.h> #include <ntddkbd.h> NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) ; VOID DriverUnloadRoutine (IN PDRIVER_OBJECT DriverObject) ; NTSTATUS ObReferenceObjectByName ( __in PUNICODE_STRING ObjectName, __in ULONG Attributes, __in_opt PACCESS_STATE AccessState, __in_opt ACCESS_MASK DesiredAccess, __in POBJECT_TYPE ObjectType, __in KPROCESSOR_MODE AccessMode, __inout_opt PVOID ParseContext, __out PVOID* Object ) ; extern POBJECT_TYPE* IoDriverObjectType; } #include "header.h" typedef struct _DEVICE_EXTENSION { UNICODE_STRING ustrDevName; PDEVICE_OBJECT pDevice; PDEVICE_OBJECT pTargetDev; } DEVICE_EXTENSION, * PDEVICE_EXTENSION; NTSTATUS DispatchRoutine (PDEVICE_OBJECT pDev, PIRP pIrp) { pDev; pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0 ; IoCompleteRequest (pIrp, IO_NO_INCREMENT); return (STATUS_SUCCESS); } NTSTATUS FilterReadCompletionRoutine ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { Context; DeviceObject; if (NT_SUCCESS (Irp->IoStatus.Status)) { PKEYBOARD_INPUT_DATA myData; ULONG KeyNumber = NULL ; myData = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer; KeyNumber = ((ULONG)(Irp->IoStatus.Information) / sizeof (PKEYBOARD_INPUT_DATA)); for (ULONG i = 0 ; i < KeyNumber; i++) { KdPrint (("number:%u\n" , KeyNumber)); KdPrint (("scancode:%x\n" , myData->MakeCode)); } } if (Irp->PendingReturned) { IoMarkIrpPending (Irp); } return Irp->IoStatus.Status; } NTSTATUS ReadRoutine (PDEVICE_OBJECT pDev, PIRP pIrp) { KdPrint (("DriverB: 进入ReadRoutine\n" )); PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDev->DeviceExtension; PIO_STACK_LOCATION stack; stack = IoGetCurrentIrpStackLocation (pIrp); IoCopyCurrentIrpStackLocationToNext (pIrp); IoSetCompletionRoutine (pIrp, FilterReadCompletionRoutine, NULL , TRUE, TRUE, TRUE); NTSTATUS status = IoCallDriver (pDevExt->pTargetDev, pIrp); return status; } NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER (RegistryPath); KdPrint (("Create!" )); KdBreakPoint (); DriverObject->DriverUnload = DriverUnloadRoutine; for (int i = 0 ; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) DriverObject->MajorFunction[i] = DispatchRoutine; DriverObject->MajorFunction[IRP_MJ_READ] = ReadRoutine; NTSTATUS status; PDEVICE_OBJECT DeviceObject = NULL ; UNICODE_STRING DeviceName; RtlInitUnicodeString (&DeviceName, L"\\Device\\MyDevice" ); status = IoCreateDevice ( DriverObject, sizeof (DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_UNKNOWN, 0 , FALSE, &DeviceObject ); if (!NT_SUCCESS (status)) { KdPrint (("Failed to create device: %X\n" , status)); return status; } KdPrint (("Device created successfully\n" )); PDEVICE_OBJECT pTarget = nullptr ; PDEVICE_OBJECT KbdDevice = nullptr ; UNICODE_STRING driverName; OBJECT_ATTRIBUTES objectAttributes; PDRIVER_OBJECT KbdDriver = nullptr ; RtlInitUnicodeString (&driverName, L"\\Driver\\kbdclass" ); InitializeObjectAttributes ( &objectAttributes, &driverName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL , NULL ); if (IoDriverObjectType == NULL ) { KdPrint (("IoDriverObjectType is NULL.\n" )); return STATUS_UNSUCCESSFUL; } status = ObReferenceObjectByName ( &driverName, OBJ_CASE_INSENSITIVE, NULL , KernelMode, *IoDriverObjectType, KernelMode, NULL , (PVOID*)&KbdDriver ); if (!NT_SUCCESS (status)) { KdPrint (("驱动对象失败\n" )); return (status); } KbdDevice = KbdDriver->DeviceObject; KbdDevice = KbdDevice->NextDevice; pTarget = IoAttachDeviceToDeviceStack (DeviceObject, KbdDevice); if (pTarget == NULL ) { IoDeleteDevice (DeviceObject); KdPrint (("附加失败!\n" )); return (STATUS_UNSUCCESSFUL); } PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; pDevExt->pTargetDev = pTarget; DeviceObject->Flags |= (pTarget->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO)); DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; DeviceObject->Characteristics = pTarget->Characteristics; DeviceObject->DeviceType = pTarget->DeviceType; return STATUS_SUCCESS; } VOID DriverUnloadRoutine (IN PDRIVER_OBJECT DriverObject) { PDEVICE_OBJECT pDeviceObject = DriverObject->DeviceObject; while (pDeviceObject != NULL ) { PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension; if (pDevExt->pTargetDev != NULL ) { IoDetachDevice (pDevExt->pTargetDev); } PDEVICE_OBJECT pNextDevice = pDeviceObject->NextDevice; IoDeleteDevice (pDeviceObject); pDeviceObject = pNextDevice; } DbgPrint ("Driver unloaded and detached successfully\n" ); }
效果如下