1 #include "stdafx.h"
2 #include
3 #include
4 #include
5 using namespace std;
6
7 #define CTL_KEINJECTAPC \
8 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x830, METHOD_BUFFERED, FILE_ANY_ACCESS)
9
10 typedef struct _INJECT_INFO
11 {
12 ULONG ProcessId;
13 wchar_t DllName[1024];
14 }INJECT_INFO, *PINJECT_INFO;
15
16 int _tmain(int argc, _TCHAR* argv[])
17 {
18 HANDLE hFile;
19 INJECT_INFO InjectInfo;
20 hFile = CreateFile(L"\\\\.\\DriverLink",
21 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
22 NULL, OPEN_EXISTING, 0, NULL);
23
24 if (hFile == INVALID_HANDLE_VALUE)
25 {
26 printf("\nError: Unable to connect to the driver (%d)\n", GetLastError());
27 return -1;
28 }
29 memset(&InjectInfo, 0, sizeof(INJECT_INFO));
30 scanf("%d", &(InjectInfo.ProcessId));
31 wscanf(L"%s", InjectInfo.DllName);
32 DWORD dwReturnSize = 0;
33 DWORD dwRet = 0;
34 dwRet = DeviceIoControl(hFile, CTL_KEINJECTAPC, //
35 &InjectInfo,
36 sizeof(INJECT_INFO),
37 NULL,
38 NULL,
39 &dwReturnSize,
40 NULL);
41
42 CloseHandle(hFile);
43 return 0;
44 }
45
46 #include
47 #include
48 #include
49
50 #endif
51
52 #define DEVICE_NAME L"\\Device\\DriverDevice"
53 #define LINK_NAME L"\\DosDevices\\DriverLink"
54
55 #define CTL_KEINJECTAPC \
56 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x830, METHOD_BUFFERED, FILE_ANY_ACCESS)
57
58 typedef struct _SYSTEM_THREAD_INFORMATION
59 {
60 LARGE_INTEGER KernelTime;
61 LARGE_INTEGER UserTime;
62 LARGE_INTEGER CreateTime;
63 ULONG WaitTime;
64 PVOID StartAddress;
65 CLIENT_ID ClientId;
66 KPRIORITY Priority;
67 LONG BasePriority;
68 ULONG ContextSwitches;
69 ULONG ThreadState;
70 KWAIT_REASON WaitReason;
71 }SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;
72
73 typedef struct _SYSTEM_PROCESS_INFO
74 {
75 ULONG NextEntryOffset;
76 ULONG NumberOfThreads;
77 LARGE_INTEGER WorkingSetPrivateSize;
78 ULONG HardFaultCount;
79 ULONG NumberOfThreadsHighWatermark;
80 ULONGLONG CycleTime;
81 LARGE_INTEGER CreateTime;
82 LARGE_INTEGER UserTime;
83 LARGE_INTEGER KernelTime;
84 UNICODE_STRING ImageName;
85 KPRIORITY BasePriority;
86 HANDLE UniqueProcessId;
87 HANDLE InheritedFromUniqueProcessId;
88 ULONG HandleCount;
89 ULONG SessionId;
90 ULONG_PTR UniqueProcessKey;
91 SIZE_T PeakVirtualSize;
92 SIZE_T VirtualSize;
93 ULONG PageFaultCount;
94 SIZE_T PeakWorkingSetSize;
95 SIZE_T WorkingSetSize;
96 SIZE_T QuotaPeakPagedPoolUsage;
97 SIZE_T QuotaPagedPoolUsage;
98 SIZE_T QuotaPeakNonPagedPoolUsage;
99 SIZE_T QuotaNonPagedPoolUsage;
100 SIZE_T PagefileUsage;
101 SIZE_T PeakPagefileUsage;
102 SIZE_T PrivatePageCount;
103 LARGE_INTEGER ReadOperationCount;
104 LARGE_INTEGER WriteOperationCount;
105 LARGE_INTEGER OtherOperationCount;
106 LARGE_INTEGER ReadTransferCount;
107 LARGE_INTEGER WriteTransferCount;
108 LARGE_INTEGER OtherTransferCount;
109 SYSTEM_THREAD_INFORMATION Threads[1];
110 }SYSTEM_PROCESS_INFO, *PSYSTEM_PROCESS_INFO;
111
112 typedef struct _LDR_DATA_TABLE_ENTRY
113 {
114 LIST_ENTRY InLoadOrderLinks;
115 LIST_ENTRY InMemoryOrderLinks;
116 LIST_ENTRY InInitializationOrderLinks;
117 PVOID DllBase;
118 PVOID EntryPoint;
119 ULONG SizeOfImage;
120 UNICODE_STRING FullDllName;
121 UNICODE_STRING BaseDllName;
122 ULONG Flags;
123 USHORT LoadCount;
124 USHORT TlsIndex;
125
126 union
127 {
128 LIST_ENTRY HashLinks;
129 struct
130 {
131 PVOID SectionPointer;
132 ULONG CheckSum;
133 };
134 };
135
136 union
137 {
138 ULONG TimeDateStamp;
139 PVOID LoadedImports;
140 };
141
142 struct _ACTIVATION_CONTEXT * EntryPointActivationContext;
143 PVOID PatchInformation;
144 LIST_ENTRY ForwarderLinks;
145 LIST_ENTRY ServiceTagLinks;
146 LIST_ENTRY StaticLinks;
147 }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
148
149 typedef struct _INJECT_INFO
150 {
151 ULONG ProcessId;
152 wchar_t DllName[1024];
153 }INJECT_INFO, *PINJECT_INFO;
154
155 typedef NTSTATUS(*PLDR_LOAD_DLL)(PWSTR, PULONG, PUNICODE_STRING, PVOID*);
156
157 typedef struct _KINJECT
158 {
159 UNICODE_STRING DllName;
160 wchar_t Buffer[1024];
161 PLDR_LOAD_DLL LdrLoadDll;
162 PVOID DllBase;
163 ULONG Executed;
164 }KINJECT, *PKINJECT;
165
166 typedef enum _KAPC_ENVIRONMENT
167 {
168 OriginalApcEnvironment,
169 AttachedApcEnvironment,
170 CurrentApcEnvironment,
171 InsertApcEnvironment
172 }KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT;
173
174 typedef VOID(NTAPI *PKNORMAL_ROUTINE)(
175 PVOID NormalContext,
176 PVOID SystemArgument1,
177 PVOID SystemArgument2
178 );
179
180 typedef VOID KKERNEL_ROUTINE(
181 PRKAPC Apc,
182 PKNORMAL_ROUTINE *NormalRoutine,
183 PVOID *NormalContext,
184 PVOID *SystemArgument1,
185 PVOID *SystemArgument2
186 );
187
188 typedef KKERNEL_ROUTINE(NTAPI *PKKERNEL_ROUTINE);
189
190 typedef VOID(NTAPI *PKRUNDOWN_ROUTINE)(
191 PRKAPC Apc
192 );
193
194 void KeInitializeApc(
195 PRKAPC Apc,
196 PRKTHREAD Thread,
197 KAPC_ENVIRONMENT Environment,
198 PKKERNEL_ROUTINE KernelRoutine,
199 PKRUNDOWN_ROUTINE RundownRoutine,
200 PKNORMAL_ROUTINE NormalRoutine,
201 KPROCESSOR_MODE ProcessorMode,
202 PVOID NormalContext
203 );
204
205 BOOLEAN KeInsertQueueApc(
206 PRKAPC Apc,
207 PVOID SystemArgument1,
208 PVOID SystemArgument2,
209 KPRIORITY Increment
210 );
211
212
213 NTSTATUS ZwQuerySystemInformation(ULONG InfoClass, PVOID Buffer, ULONG Length, PULONG ReturnLength);
214 LPSTR PsGetProcessImageFileName(PEPROCESS Process);
215
216 NTSTATUS DefaultPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp);
217 void UnloadDriver(PDRIVER_OBJECT DriverObject);
218 NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp);
219
220 ULONG ApcStateOffset;
221 PLDR_LOAD_DLL LdrLoadDll;
222
223 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING pRegistryPath)
224 {
225 NTSTATUS Status;
226 PDEVICE_OBJECT DeviceObject;
227 PEPROCESS Process;
228 PETHREAD Thread;
229 PKAPC_STATE ApcState;
230 PVOID KdVersionBlock, NtdllBase;
231 PULONG ptr, Functions, Names;
232 PUSHORT Ordinals;
233 PLDR_DATA_TABLE_ENTRY MmLoadedUserImageList, ModuleEntry;
234 ULONG i;
235 PIMAGE_DOS_HEADER pIDH;
236 PIMAGE_NT_HEADERS pINH;
237 PIMAGE_EXPORT_DIRECTORY pIED;
238 UNICODE_STRING uniDeviceName;
239 UNICODE_STRING uniLinkName;
240 RtlInitUnicodeString(&uniDeviceName, DEVICE_NAME);
241 RtlInitUnicodeString(&uniLinkName, LINK_NAME);
242 for (i = 0; i
245 }
246 DriverObject->DriverUnload = UnloadDriver;
247 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverDispatch;
248 //创建设备对象
249 Status = IoCreateDevice(DriverObject, 0, &uniDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
250 if (!NT_SUCCESS(Status))
251 {
252 return Status;
253 }
254 Status = IoCreateSymbolicLink(&uniLinkName, &uniDeviceName);
255 if (!NT_SUCCESS(Status))
256 {
257 IoDeleteDevice(DeviceObject);
258 return Status;
259 }
260
261 //使当前线程运行在第一个处理器上
262 KeSetSystemAffinityThread(1);
263 KdVersionBlock = (PVOID)__readfsdword(0x34); //得到KdVersionBlock
264 KeRevertToUserAffinityThread();//恢复线程运行的处理器
265 MmLoadedUserImageList = *(PLDR_DATA_TABLE_ENTRY*)((PUCHAR)KdVersionBlock + 0x228); // Get the MmLoadUserImageList
266
267 /*
268 kd> !pcr
269 KPCR for Processor 0 at 83f3ec00:
270
271 kd> dt _kpcr 83f3ec00
272 +0x034 KdVersionBlock : 0x83f3dc00 Void
273
274 kd> dd 0x83f3dc00+0x228
275 83f3de28 83f5de38 00000000 83e5dfa8 00000000
276 83f3de38 00000000 00000000 83f7d8c0 00000000
277 83f3de48 83f7d560 00000000 83f5d84c 00000000
278
279 kd> dd 83f5de38
280 83f5de38 8706b1e8 877cb660 00000000 00000000
281 83f5de48 00000000 00000000 00040107 00000000
282 83f5de58 865d0690 865d0690 c0403188 0007ff7e
283
284 kd> dt _LDR_DATA_TABLE_ENTRY 8706b1e8
285 nt!_LDR_DATA_TABLE_ENTRY
286 +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x8713b4e0 - 0x83f5de38 ]
287 +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
288 +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
289 +0x018 DllBase : 0x77ce0000 Void
290 +0x01c EntryPoint : (null)
291 +0x020 SizeOfImage : 0x13c000
292 +0x024 FullDllName : _UNICODE_STRING "\Windows\System32\ntdll.dll"
293 +0x02c BaseDllName : _UNICODE_STRING ""
294 +0x034 Flags : 0
295 +0x038 LoadCount : 1
296 +0x03a TlsIndex : 0
297 +0x03c HashLinks : _LIST_ENTRY [ 0x0 - 0x1490d9 ]
298 +0x03c SectionPointer : (null)
299 +0x040 CheckSum : 0x1490d9
300 +0x044 TimeDateStamp : 0
301 +0x044 LoadedImports : (null)
302 +0x048 EntryPointActivationContext : (null)
303 +0x04c PatchInformation : (null)
304 +0x050 ForwarderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
305 +0x058 ServiceTagLinks : _LIST_ENTRY [ 0x0 - 0x57005c ]
306 +0x060 StaticLinks : _LIST_ENTRY [ 0x6e0069 - 0x6f0064 ]
307 +0x068 ContextInformation : 0x00730077 Void
308 +0x06c OriginalBase : 0x53005c
309 +0x070 LoadTime : _LARGE_INTEGER 0x650074`00730079
310 */
311 DbgPrint("KdVersionBlock address: %#x", KdVersionBlock);
312 DbgPrint("MmLoadedUserImageList address: %#x", MmLoadedUserImageList);
313
314 ModuleEntry = (PLDR_DATA_TABLE_ENTRY)MmLoadedUserImageList->InLoadOrderLinks.Flink; //第一模块
315 NtdllBase = ModuleEntry->DllBase; //ntdll基地址
316
317 DbgPrint("ntdll base address: %#x", NtdllBase);
318
319 pIDH = (PIMAGE_DOS_HEADER)NtdllBase;
320 pINH = (PIMAGE_NT_HEADERS)((PUCHAR)NtdllBase + pIDH->e_lfanew);
321 pIED = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)NtdllBase + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
322
323 Functions = (PULONG)((PUCHAR)NtdllBase + pIED->AddressOfFunctions);
324 Names = (PULONG)((PUCHAR)NtdllBase + pIED->AddressOfNames);
325
326 Ordinals = (PUSHORT)((PUCHAR)NtdllBase + pIED->AddressOfNameOrdinals);
327
328 //搜索LdrLoadDll
329 for (i = 0; i
330 {
331 if (!strcmp((char*)NtdllBase + Names[i], "LdrLoadDll"))
332 {
333 LdrLoadDll = (PLDR_LOAD_DLL)((PUCHAR)NtdllBase + Functions[Ordinals[i]]);
334 break;
335 }
336 }
337
338 DbgPrint("LdrLoadDll address: %#x", LdrLoadDll);
339 Process = PsGetCurrentProcess();
340 Thread = PsGetCurrentThread();
341 ptr = (PULONG)Thread;
342 //确定ApcState在EThread中的偏移
343 for (i = 0; i<512; i++)
344 {
345 if (ptr[i] == (ULONG)Process)
346 {
347 ApcState = CONTAINING_RECORD(&ptr[i], KAPC_STATE, Process);
348 ApcStateOffset = (ULONG)ApcState - (ULONG)Thread;
349 break;
350 }
351 }
352 DbgPrint("ApcState offset: %#x", ApcStateOffset);
353 DbgPrint("DLL injection driver loaded.");
354 return STATUS_SUCCESS;
355 }
356
357 NTSTATUS DefaultPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp)
358 {
359 Irp->IoStatus.Information = 0;
360 Irp->IoStatus.Status = STATUS_SUCCESS;
361 IoCompleteRequest(Irp, IO_NO_INCREMENT);
362 return STATUS_SUCCESS;
363 }
364
365 void UnloadDriver(PDRIVER_OBJECT DriverObject)
366 {
367 UNICODE_STRING uniLinkName;
368 PDEVICE_OBJECT CurrentDeviceObject;
369 PDEVICE_OBJECT NextDeviceObject;
370 RtlInitUnicodeString(&uniLinkName, LINK_NAME);
371 IoDeleteSymbolicLink(&uniLinkName);
372 if (DriverObject->DeviceObject != NULL)
373 {
374 CurrentDeviceObject = DriverObject->DeviceObject;
375 while (CurrentDeviceObject != NULL)
376 {
377 NextDeviceObject = CurrentDeviceObject->NextDevice;
378 IoDeleteDevice(CurrentDeviceObject);
379 CurrentDeviceObject = NextDeviceObject;
380 }
381 }
382 DbgPrint("UnloadDriver\r\n");
383 }
384
385 void NTAPI InjectDllApc(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
386 {
387 PKINJECT inject = (PKINJECT)NormalContext;
388 inject->LdrLoadDll(NULL, NULL, &inject->DllName, &inject->DllBase);
389 inject->Executed = TRUE;
390 }
391
392 void NTAPI KernelRoutine(PKAPC apc, PKNORMAL_ROUTINE* NormalRoutine, PVOID* NormalContext, \
393 PVOID* SystemArgument1, PVOID* SystemArgument2)
394 {
395 ExFreePool(apc);
396 }
397
398 BOOLEAN InjectDll(PINJECT_INFO InjectInfo)
399 {
400 PEPROCESS Process;
401 PETHREAD Thread;
402 PKINJECT mem;
403 ULONG size;
404 PKAPC_STATE ApcState;
405 PKAPC apc;
406 PVOID buffer;
407 PSYSTEM_PROCESS_INFO pSpi;
408 LARGE_INTEGER delay;
409 buffer = ExAllocatePool(NonPagedPool, 1024 * 1024);
410 if (!buffer)
411 {
412 DbgPrint("Error: Unable to allocate memory for the process thread list.");
413 return FALSE;
414 }
415
416 //5 SystemProcessInformation,
417 if (!NT_SUCCESS(ZwQuerySystemInformation(5, buffer, 1024 * 1024, NULL)))
418 {
419 DbgPrint("Error: Unable to query process thread list.");
420 ExFreePool(buffer);
421 return FALSE;
422 }
423
424 pSpi = (PSYSTEM_PROCESS_INFO)buffer;
425
426 //找到目标进程
427 while (pSpi->NextEntryOffset)
428 {
429 if (pSpi->UniqueProcessId == InjectInfo->ProcessId)
430 {
431 DbgPrint("Target thread found. TID: %d", pSpi->Threads[0].ClientId.UniqueThread);
432 break;
433 }
434 pSpi = (PSYSTEM_PROCESS_INFO)((PUCHAR)pSpi + pSpi->NextEntryOffset);
435 }
436
437 // 引用目标进程EProcess,
438 if (!NT_SUCCESS(PsLookupProcessByProcessId(InjectInfo->ProcessId, &Process)))
439 {
440 DbgPrint("Error: Unable to reference the target process.");
441 ExFreePool(buffer);
442 return FALSE;
443 }
444
445 DbgPrint("Process name: %s", PsGetProcessImageFileName(Process));
446 DbgPrint("EPROCESS address: %#x", Process);
447
448 //目标进程主线程
449 if (!NT_SUCCESS(PsLookupThreadByThreadId(pSpi->Threads[0].ClientId.UniqueThread, &Thread)))
450 {
451 DbgPrint("Error: Unable to reference the target thread.");
452 ObDereferenceObject(Process);
453 ExFreePool(buffer);
454 return FALSE;
455 }
456
457 DbgPrint("ETHREAD address: %#x", Thread);
458
459 ExFreePool(buffer);
460 //切入到目标进程
461 KeAttachProcess(Process);
462
463 mem = NULL;
464 size = 4096;
465
466 //在目标进程申请内存
467 if (!NT_SUCCESS(ZwAllocateVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)))
468 {
469 DbgPrint("Error: Unable to allocate memory in the target process.");
470 KeDetachProcess();
471 ObDereferenceObject(Process);
472 ObDereferenceObject(Thread);
473 return FALSE;
474 }
475
476 DbgPrint("Memory allocated at %#x", mem);
477 mem->LdrLoadDll = LdrLoadDll;
478 wcscpy(mem->Buffer, InjectInfo->DllName);
479 RtlInitUnicodeString(&mem->DllName, mem->Buffer);
480 ApcState = (PKAPC_STATE)((PUCHAR)Thread + ApcStateOffset);
481 ApcState->UserApcPending = TRUE;
482 memcpy((PKINJECT)(mem + 1), InjectDllApc, (ULONG)KernelRoutine - (ULONG)InjectDllApc);
483 DbgPrint("APC code address: %#x", (PKINJECT)(mem + 1));
484
485 //申请apc对象
486 apc = (PKAPC)ExAllocatePool(NonPagedPool, sizeof(KAPC));
487
488 if (!apc)
489 {
490 DbgPrint("Error: Unable to allocate the APC object.");
491 size = 0;
492 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, &size, MEM_RELEASE);
493 KeDetachProcess();
494 ObDereferenceObject(Process);
495 ObDereferenceObject(Thread);
496 return FALSE;
497 }
498
499 KeInitializeApc(apc,
500 Thread, //目标进程主线程
501 OriginalApcEnvironment, //目标apcz状态
502 KernelRoutine, //内核apc总入口
503 NULL, //Rundown Rounine=NULL
504 (PKNORMAL_ROUTINE)((PKINJECT)mem + 1), //用户空间的总apc
505 UserMode, //插入到用户apc队列
506 mem); // 自己的apc队列
507
508 DbgPrint("Inserting APC to target thread");
509
510 // 插入apc队列
511 if (!KeInsertQueueApc(apc, NULL, NULL, IO_NO_INCREMENT))
512 {
513 DbgPrint("Error: Unable to insert APC to target thread.");
514 size = 0;
515 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, &size, MEM_RELEASE);
516 KeDetachProcess();
517 ObDereferenceObject(Process);
518 ObDereferenceObject(Thread);
519 ExFreePool(apc);
520 return FALSE;
521 }
522
523 delay.QuadPart = -100 * 10000;
524 while (!mem->Executed)
525 {
526 KeDelayExecutionThread(KernelMode, FALSE, &delay); //等待apc执行
527 }
528 if (!mem->DllBase)
529 {
530 DbgPrint("Error: Unable to inject DLL into target process.");
531 size = 0;
532 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, &size, MEM_RELEASE);
533 KeDetachProcess();
534 ObDereferenceObject(Process);
535 ObDereferenceObject(Thread);
536 return FALSE;
537 }
538
539 DbgPrint("DLL injected at %#x", mem->DllBase);
540 size = 0;
541 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, &size, MEM_RELEASE);
542 ObDereferenceObject(Process);
543 ObDereferenceObject(Thread);
544 return TRUE;
545 }
546
547 NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
548 {
549 PIO_STACK_LOCATION io;
550 PINJECT_INFO InjectInfo;
551 NTSTATUS Status = STATUS_SUCCESS;
552 PIO_STACK_LOCATION IrpSp;
553 PVOID InputBuffer = NULL;
554 PVOID OutputBuffer = NULL;
555 ULONG_PTR InputSize = 0;
556 ULONG_PTR OutputSize = 0;
557 ULONG_PTR IoControlCode = 0;
558
559 IrpSp = IoGetCurrentIrpStackLocation(Irp);
560 InputBuffer = OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
561 InputSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
562 OutputSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
563 IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
564
565 switch (IoControlCode)
566 {
567 case CTL_KEINJECTAPC:
568
569 InjectInfo = (PINJECT_INFO)InputBuffer;
570
571 if (!InjectInfo)
572 {
573 Status = STATUS_INSUFFICIENT_RESOURCES;
574 break;
575 }
576
577 if (!InjectDll(InjectInfo))
578 {
579 Status = STATUS_UNSUCCESSFUL;
580 break;
581 }
582 Status = STATUS_SUCCESS;
583 Irp->IoStatus.Information = 0;
584 break;
585 default:
586 Status = STATUS_INVALID_DEVICE_REQUEST;
587 break;
588 }
589 Irp->IoStatus.Status = Status;
590 IoCompleteRequest(Irp, IO_NO_INCREMENT);
591 return Status;
592 }
手机扫一扫
移动阅读更方便
你可能感兴趣的文章