779695f153e2a8094584c8b3908c8685c6f3f05e
[reactos.git] / reactos / ntoskrnl / wmi / wmidrv.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/wmidrv.c
5 * PURPOSE: I/O Windows Management Instrumentation (WMI) Support
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntoskrnl.h>
12 #include <wmistr.h>
13 #include <wmiioctl.h>
14 #include "wmip.h"
15
16 #define NDEBUG
17 #include <debug.h>
18
19 // FIXME: these should go to a shared header
20 typedef struct _WMIP_REGISTER_GUIDS
21 {
22 POBJECT_ATTRIBUTES ObjectAttributes;
23 ULONG Unknown04;
24 ULONG Unknown08;
25 ULONG Unknown0C;
26 ULONG Unknown10;
27 ULONG Unknown14;
28
29 WMIREGINFOW RegInfo;
30 } WMIP_REGISTER_GUIDS, *PWMIP_REGISTER_GUIDS;
31
32 typedef struct _WMIP_RESULT
33 {
34 HANDLE Handle;
35 ULONG Unknown04;
36 TRACEHANDLE TraceHandle;
37 BOOLEAN Unknown10;
38 } WMIP_RESULT, *PWMIP_RESULT;
39
40 typedef struct _WMI_UNREGISTER_GUID
41 {
42 GUID Guid;
43 ULONG Unknown10;
44 ULONG Unknown14;
45 ULONG Unknown18;
46 ULONG Unknown1C;
47 } WMI_UNREGISTER_GUID, *PWMI_UNREGISTER_GUID;
48
49 typedef struct _WMI_GUID_OBJECT_ENTRY
50 {
51 HANDLE Handle;
52 ULONG Unknown04;
53 } WMI_GUID_OBJECT_ENTRY, *PWMI_GUID_OBJECT_ENTRY;
54
55 typedef struct _WMI_NOTIFICATION
56 {
57 ULONG NumberOfGuidObjects;
58 ULONG Unknown04;
59 ULONG Unknown08;
60 ULONG Unknown0C;
61 ULONG Unknown10;
62 ULONG Unknown14;
63 WMI_GUID_OBJECT_ENTRY GuidObjects[0];
64 } WMI_NOTIFICATION, *PWMI_NOTIFICATION;
65
66 typedef struct _WMI_SET_MARK
67 {
68 ULONG Flags;
69 WCHAR Mark[1];
70 } WMI_SET_MARK, *PWMI_SET_MARK;
71
72 PDEVICE_OBJECT WmipServiceDeviceObject;
73 PDEVICE_OBJECT WmipAdminDeviceObject;
74 FAST_IO_DISPATCH WmipFastIoDispatch;
75
76
77 /* FUNCTIONS *****************************************************************/
78
79 DRIVER_DISPATCH WmipOpenCloseCleanup;
80 DRIVER_DISPATCH WmipIoControl;
81 DRIVER_DISPATCH WmipSystemControl;
82 DRIVER_DISPATCH WmipShutdown;
83
84 NTSTATUS
85 NTAPI
86 WmipOpenCloseCleanup(
87 _In_ PDEVICE_OBJECT DeviceObject,
88 _Inout_ PIRP Irp)
89 {
90 PAGED_CODE();
91
92 /* No work to do, just return success */
93 Irp->IoStatus.Status = STATUS_SUCCESS;
94 Irp->IoStatus.Information = 0;
95 IoCompleteRequest(Irp, IO_NO_INCREMENT);
96 return STATUS_SUCCESS;
97 }
98
99 static
100 NTSTATUS
101 WmiTraceEvent(
102 PVOID InputBuffer,
103 KPROCESSOR_MODE PreviousMode)
104 {
105 UNIMPLEMENTED_DBGBREAK();
106 return STATUS_SUCCESS;
107 }
108
109 static
110 NTSTATUS
111 WmiTraceUserMessage(
112 PVOID InputBuffer,
113 ULONG InputBufferLength)
114 {
115 UNIMPLEMENTED_DBGBREAK();
116 return STATUS_SUCCESS;
117 }
118
119 static
120 NTSTATUS
121 WmipCaptureGuidObjectAttributes(
122 _In_ POBJECT_ATTRIBUTES GuidObjectAttributes,
123 _Out_ POBJECT_ATTRIBUTES CapuredObjectAttributes,
124 _Out_ PUNICODE_STRING CapturedObjectName,
125 _Out_ PWSTR ObjectNameBuffer,
126 _In_ KPROCESSOR_MODE AccessMode)
127 {
128 ASSERT(AccessMode != KernelMode);
129
130 _SEH2_TRY
131 {
132 /* Probe and copy the object attributes structure */
133 ProbeForRead(GuidObjectAttributes,
134 sizeof(OBJECT_ATTRIBUTES),
135 sizeof(PVOID));
136 *CapuredObjectAttributes = *GuidObjectAttributes;
137
138 /* Probe and copy the object name UNICODE_STRING */
139 ProbeForRead(CapuredObjectAttributes->ObjectName,
140 sizeof(UNICODE_STRING),
141 sizeof(PVOID));
142 *CapturedObjectName = *CapuredObjectAttributes->ObjectName;
143
144 /* Check if the object name has the expected length */
145 if (CapturedObjectName->Length != 45 * sizeof(WCHAR))
146 {
147 return STATUS_INVALID_PARAMETER;
148 }
149
150 /* Probe and copy the object name buffer */
151 ProbeForRead(CapturedObjectName->Buffer,
152 CapturedObjectName->Length,
153 sizeof(WCHAR));
154 RtlCopyMemory(ObjectNameBuffer,
155 CapturedObjectName->Buffer,
156 CapturedObjectName->Length);
157
158 /* Fix pointers */
159 CapturedObjectName->Buffer = ObjectNameBuffer;
160 GuidObjectAttributes->ObjectName = CapturedObjectName;
161 }
162 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
163 {
164 DPRINT1("Got exception!\n");
165 return _SEH2_GetExceptionCode();
166 }
167 _SEH2_END;
168
169 return STATUS_SUCCESS;
170 }
171
172 static
173 NTSTATUS
174 WmipRegisterGuids(
175 _In_ PDEVICE_OBJECT DeviceObject,
176 _In_ PVOID Buffer,
177 _In_ ULONG InputLength,
178 _Inout_ PULONG OutputLength)
179 {
180 PWMIP_REGISTER_GUIDS RegisterGuids = (PWMIP_REGISTER_GUIDS)Buffer;
181 PWMIP_RESULT Result = (PWMIP_RESULT)Buffer;
182 OBJECT_ATTRIBUTES LocalObjectAttributes;
183 UNICODE_STRING LocalObjectName;
184 WCHAR LocalObjectNameBuffer[45 + 1];
185 KPROCESSOR_MODE PreviousMode;
186 HANDLE GuidObjectHandle;
187 PVOID GuidObject;
188 NTSTATUS Status;
189
190 /* Make sure the input buffer is large enough */
191 if ((InputLength < sizeof(WMIP_REGISTER_GUIDS)) ||
192 (RegisterGuids->RegInfo.BufferSize >
193 (InputLength - FIELD_OFFSET(WMIP_REGISTER_GUIDS, RegInfo))))
194 {
195 return STATUS_UNSUCCESSFUL;
196 }
197
198 /* Make sure we have a resonable GUID count */
199 if ((RegisterGuids->RegInfo.GuidCount == 0) ||
200 (RegisterGuids->RegInfo.GuidCount > 0x10000))
201 {
202 return STATUS_UNSUCCESSFUL;
203 }
204
205 /* Capture object attributes */
206 PreviousMode = ExGetPreviousMode();
207 Status = WmipCaptureGuidObjectAttributes(RegisterGuids->ObjectAttributes,
208 &LocalObjectAttributes,
209 &LocalObjectName,
210 LocalObjectNameBuffer,
211 PreviousMode);
212 if (!NT_SUCCESS(Status))
213 {
214 DPRINT1("WmipCaptureGuidObjectAttributes failed: 0x%lx\n", Status);
215 return Status;
216 }
217
218 /* Open a new GUID object */
219 Status = WmipOpenGuidObjectByName(&LocalObjectAttributes,
220 SPECIFIC_RIGHTS_ALL,
221 PreviousMode,
222 &GuidObjectHandle,
223 &GuidObject);
224 if (!NT_SUCCESS(Status))
225 {
226 DPRINT1("WmipOpenGuidObjectByName failed: 0x%lx\n", Status);
227 return Status;
228 }
229
230 /* Dereference the GUID object */
231 ObDereferenceObject(GuidObject);
232
233 /* Return the handle (user mode will close it) */
234 Result->Handle = GuidObjectHandle;
235 Result->TraceHandle = 0;
236 *OutputLength = 24;
237
238 return STATUS_SUCCESS;
239 }
240
241
242 static
243 NTSTATUS
244 WmipUnregisterGuids(
245 _In_ PVOID Buffer,
246 _In_ ULONG InputLength,
247 _Inout_ PULONG OutputLength)
248 {
249 /* For now we have nothing to do */
250 return STATUS_SUCCESS;
251 }
252
253 VOID
254 NTAPI
255 WmipClearIrpObjectList(
256 _In_ PIRP Irp)
257 {
258 PWMIP_IRP_CONTEXT IrpContext;
259 PLIST_ENTRY ListEntry;
260 PWMIP_GUID_OBJECT GuidObject;
261
262 /* Get the IRP context */
263 IrpContext = (PWMIP_IRP_CONTEXT)Irp->Tail.Overlay.DriverContext;
264
265 /* Loop all GUID objects attached to this IRP */
266 for (ListEntry = IrpContext->GuidObjectListHead.Flink;
267 ListEntry != &IrpContext->GuidObjectListHead;
268 ListEntry = ListEntry->Flink)
269 {
270 /* Get the GUID object */
271 GuidObject = CONTAINING_RECORD(ListEntry, WMIP_GUID_OBJECT, IrpLink);
272
273 /* Make sure the IRP matches and clear it */
274 ASSERT(GuidObject->Irp == Irp);
275 GuidObject->Irp = NULL;
276
277 /* Remove the entry */
278 RemoveEntryList(ListEntry);
279 }
280 }
281
282 VOID
283 NTAPI
284 WmipNotificationIrpCancel(
285 _In_ PDEVICE_OBJECT DeviceObject,
286 _Inout_ PIRP Irp)
287 {
288 /* Clear the list */
289 WmipClearIrpObjectList(Irp);
290
291 /* Release the cancel spin lock */
292 IoReleaseCancelSpinLock(Irp->CancelIrql);
293
294 /* Set the status to cancelled and complete the IRP */
295 Irp->IoStatus.Status = STATUS_CANCELLED;
296 Irp->IoStatus.Information = 0;
297 IoCompleteRequest(Irp, IO_NO_INCREMENT);
298 }
299
300 static
301 VOID
302 WmipInitializeIrpContext(
303 PWMIP_IRP_CONTEXT IrpContext)
304 {
305 /* Initialize the list head for GUID objects */
306 InitializeListHead(&IrpContext->GuidObjectListHead);
307 }
308
309 static
310 NTSTATUS
311 WmipReceiveNotifications(
312 _Inout_ PIRP Irp,
313 _In_ PVOID Buffer,
314 _In_ ULONG InputLength,
315 _Inout_ PULONG OutputLength)
316 {
317 PWMI_NOTIFICATION Notification;
318 PWMIP_IRP_CONTEXT IrpContext;
319 NTSTATUS Status;
320
321 //__debugbreak();
322 if ((InputLength < sizeof(WMI_NOTIFICATION)) || (*OutputLength < 0x38))
323 {
324 return STATUS_INVALID_DEVICE_REQUEST;
325 }
326
327 /// FIXME: For now we don't do any actual work, but simply pretend we are
328 /// waiting for notifications. We won't ever deliver any though.
329 Notification = (PWMI_NOTIFICATION)Buffer;
330 DBG_UNREFERENCED_LOCAL_VARIABLE(Notification);
331
332 // loop all objects
333 // reference the object
334 // on failure, fail the whole request
335
336 // loop all objects
337 // update the irp (synchronization!)
338 // if we had one before complete the old irp with an error
339
340 /* Get the IRP context and initialize it */
341 IrpContext = (PWMIP_IRP_CONTEXT)Irp->Tail.Overlay.DriverContext;
342 WmipInitializeIrpContext(IrpContext);
343
344 // loop all objects
345 // insert the objects into the IRP list
346
347 /* Set our cancel routine for cleanup */
348 IoSetCancelRoutine(Irp, WmipNotificationIrpCancel);
349
350 /* Check if the IRP is already being cancelled */
351 if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
352 {
353 Status = STATUS_CANCELLED;
354 }
355 else
356 {
357 /* Mark the IRP as pending */
358 IoMarkIrpPending(Irp);
359 Status = STATUS_PENDING;
360 }
361
362 return Status;
363 }
364
365 typedef struct _WMI_OPEN_GUID_FOR_EVENTS
366 {
367 POBJECT_ATTRIBUTES ObjectAttributes;
368 ACCESS_MASK DesiredAccess;
369 ULONG Unknown08;
370 ULONG Unknown0C;
371 } WMI_OPEN_GUID_FOR_EVENTS, *PWMI_OPEN_GUID_FOR_EVENTS;
372
373 typedef struct _WMIP_RESULT2
374 {
375 ULONG Unknown00;
376 ULONG Unknown04;
377 HANDLE Handle;
378 ULONG Unknown0C;
379 } WMIP_RESULT2, *PWMIP_RESULT2;
380
381 static
382 NTSTATUS
383 WmipOpenGuidForEvents(
384 PVOID Buffer,
385 ULONG InputLength,
386 PULONG OutputLength)
387 {
388 PWMI_OPEN_GUID_FOR_EVENTS OpenGuidForEvents = Buffer;
389 PWMIP_RESULT2 Result = (PWMIP_RESULT2)Buffer;
390 OBJECT_ATTRIBUTES LocalObjectAttributes;
391 UNICODE_STRING LocalObjectName;
392 WCHAR LocalObjectNameBuffer[45 + 1];
393 KPROCESSOR_MODE PreviousMode;
394 HANDLE GuidObjectHandle;
395 PVOID GuidObject;
396 NTSTATUS Status;
397
398 if ((InputLength != sizeof(WMI_OPEN_GUID_FOR_EVENTS)) ||
399 (*OutputLength != sizeof(WMIP_RESULT2)))
400 {
401 return STATUS_UNSUCCESSFUL;
402 }
403
404 /* Capture object attributes */
405 PreviousMode = ExGetPreviousMode();
406 Status = WmipCaptureGuidObjectAttributes(OpenGuidForEvents->ObjectAttributes,
407 &LocalObjectAttributes,
408 &LocalObjectName,
409 LocalObjectNameBuffer,
410 PreviousMode);
411 if (!NT_SUCCESS(Status))
412 {
413 DPRINT1("ProbeAndCaptureGuidObjectAttributes failed: 0x%lx\n", Status);
414 return Status;
415 }
416
417 /* Open a new GUID object */
418 Status = WmipOpenGuidObjectByName(&LocalObjectAttributes,
419 OpenGuidForEvents->DesiredAccess,
420 PreviousMode,
421 &GuidObjectHandle,
422 &GuidObject);
423 if (!NT_SUCCESS(Status))
424 {
425 DPRINT1("WmipOpenGuidObjectByName failed: 0x%lx\n", Status);
426 return Status;
427 }
428
429 Result->Handle = GuidObjectHandle;
430
431 ObDereferenceObject(GuidObject);
432
433 return STATUS_SUCCESS;
434 }
435
436 static
437 NTSTATUS
438 WmiSetMark(
439 PWMI_SET_MARK Buffer,
440 ULONG Length)
441 {
442 UNIMPLEMENTED_DBGBREAK();
443 return STATUS_SUCCESS;
444 }
445
446 NTSTATUS
447 NTAPI
448 WmipIoControl(
449 _In_ PDEVICE_OBJECT DeviceObject,
450 _Inout_ PIRP Irp)
451 {
452 PIO_STACK_LOCATION IoStackLocation;
453 ULONG IoControlCode;
454 PVOID Buffer;
455 ULONG InputLength, OutputLength;
456 NTSTATUS Status;
457 PAGED_CODE();
458
459 /* Get the current stack location */
460 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
461
462 /* Get the io control parameters */
463 IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
464 Buffer = Irp->AssociatedIrp.SystemBuffer;
465 InputLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
466 OutputLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
467
468 switch (IoControlCode)
469 {
470
471 case IOCTL_WMI_REGISTER_GUIDS:
472 {
473 Status = WmipRegisterGuids(DeviceObject,
474 Buffer,
475 InputLength,
476 &OutputLength);
477 break;
478 }
479
480 case IOCTL_WMI_UNREGISTER_GUIDS:
481 {
482 Status = WmipUnregisterGuids(Buffer,
483 InputLength,
484 &OutputLength);
485 break;
486 }
487
488 case IOCTL_WMI_RECEIVE_NOTIFICATIONS:
489 {
490 Status = WmipReceiveNotifications(Irp,
491 Buffer,
492 InputLength,
493 &OutputLength);
494 break;
495 }
496
497 case 0x228168:
498 {
499 DPRINT1("IOCTL 0x228168 is unimplemented, ignoring\n");
500 Status = STATUS_SUCCESS;
501 break;
502 }
503
504 case IOCTL_WMI_OPEN_GUID_FOR_EVENTS:
505 {
506 Status = WmipOpenGuidForEvents(Buffer, InputLength, &OutputLength);
507 break;
508 }
509
510 case IOCTL_WMI_SET_MARK:
511 {
512 if (InputLength < FIELD_OFFSET(WMI_SET_MARK, Mark))
513 {
514 Status = STATUS_UNSUCCESSFUL;
515 break;
516 }
517
518 Status = WmiSetMark(Buffer, InputLength);
519 break;
520 }
521
522 default:
523 DPRINT1("Unsupported yet IOCTL: 0x%lx\n", IoControlCode);
524 Status = STATUS_INVALID_DEVICE_REQUEST;
525 __debugbreak();
526 break;
527 }
528
529 if (Status == STATUS_PENDING)
530 return Status;
531
532 Irp->IoStatus.Status = Status;
533 Irp->IoStatus.Information = NT_SUCCESS(Status) ? OutputLength : 0;
534
535 IoCompleteRequest(Irp, IO_NO_INCREMENT);
536 return Status;
537 }
538
539 NTSTATUS
540 NTAPI
541 WmipSystemControl(
542 _Inout_ PDEVICE_OBJECT DeviceObject,
543 _Inout_ PIRP Irp)
544 {
545 UNIMPLEMENTED_DBGBREAK();
546 return STATUS_NOT_IMPLEMENTED;
547 }
548
549 NTSTATUS
550 NTAPI
551 WmipShutdown(
552 _Inout_ PDEVICE_OBJECT DeviceObject,
553 _Inout_ PIRP Irp)
554 {
555 UNIMPLEMENTED;
556 return STATUS_NOT_IMPLEMENTED;
557 }
558
559 _Function_class_(FAST_IO_DEVICE_CONTROL)
560 _IRQL_requires_same_
561 BOOLEAN
562 NTAPI
563 WmipFastIoDeviceControl(
564 _In_ PFILE_OBJECT FileObject,
565 _In_ BOOLEAN Wait,
566 _In_opt_ PVOID InputBuffer,
567 _In_ ULONG InputBufferLength,
568 _Out_opt_ PVOID OutputBuffer,
569 _In_ ULONG OutputBufferLength,
570 _In_ ULONG IoControlCode,
571 _Out_ PIO_STATUS_BLOCK IoStatus,
572 _In_ PDEVICE_OBJECT DeviceObject)
573 {
574 PAGED_CODE();
575
576 if (IoControlCode == IOCTL_WMI_TRACE_EVENT)
577 {
578 if (InputBufferLength < 0x30)
579 {
580 DPRINT1("Buffer too small\n");
581 return FALSE;
582 }
583
584 IoStatus->Status = WmiTraceEvent(InputBuffer, ExGetPreviousMode());
585 return TRUE;
586 }
587 else if (IoControlCode == IOCTL_WMI_TRACE_USER_MESSAGE)
588 {
589 if (InputBufferLength < 0x30)
590 {
591 DPRINT1("Buffer too small\n");
592 return FALSE;
593 }
594
595 IoStatus->Status = WmiTraceUserMessage(InputBuffer, InputBufferLength);
596 return TRUE;
597 }
598
599 DPRINT1("Invalid io control code for fast dispatch: 0x%lx\n", IoControlCode);
600 return FALSE;
601 }
602
603 NTSTATUS
604 NTAPI
605 WmipDockUndockEventCallback(
606 _In_ PVOID NotificationStructure,
607 _Inout_opt_ PVOID Context)
608 {
609 UNIMPLEMENTED_DBGBREAK();
610 return STATUS_NOT_IMPLEMENTED;
611 }
612
613 _Function_class_(DRIVER_INITIALIZE)
614 _IRQL_requires_same_
615 NTSTATUS
616 NTAPI
617 WmipDriverEntry(
618 _In_ PDRIVER_OBJECT DriverObject,
619 _In_ PUNICODE_STRING RegistryPath)
620 {
621 static UNICODE_STRING ServiceDeviceName = RTL_CONSTANT_STRING(L"\\Device\\WMIDataDevice");
622 static UNICODE_STRING ServiceDosDeviceName = RTL_CONSTANT_STRING(L"\\DosDevices\\WMIDataDevice");
623 static UNICODE_STRING AdminDeviceName = RTL_CONSTANT_STRING(L"\\Device\\WMIAdminDevice");
624 static UNICODE_STRING AdminDosDeviceName = RTL_CONSTANT_STRING(L"\\DosDevices\\WMIAdminDevice");
625 NTSTATUS Status;
626 PAGED_CODE();
627
628 /* Create the service device object */
629 Status = IoCreateDevice(DriverObject,
630 0,
631 &ServiceDeviceName,
632 FILE_DEVICE_UNKNOWN,
633 FILE_DEVICE_SECURE_OPEN,
634 0,
635 &WmipServiceDeviceObject);
636 if (!NT_SUCCESS(Status))
637 {
638 DPRINT1("Failed to create service device: 0x%lx\n", Status);
639 return Status;
640 }
641
642 /* Create a symbolic link for the service device */
643 Status = IoCreateSymbolicLink(&ServiceDosDeviceName, &ServiceDeviceName);
644 if (!NT_SUCCESS(Status))
645 {
646 DPRINT1("IoCreateSymbolicLink() failed: 0x%lx\n", Status);
647 IoDeleteDevice(WmipServiceDeviceObject);
648 return Status;
649 }
650
651 /* Create the admin device object */
652 Status = IoCreateDevice(DriverObject,
653 0,
654 &AdminDeviceName,
655 FILE_DEVICE_UNKNOWN,
656 FILE_DEVICE_SECURE_OPEN,
657 0,
658 &WmipAdminDeviceObject);
659 if (!NT_SUCCESS(Status))
660 {
661 DPRINT1("Failed to create admin device: 0x%lx\n", Status);
662 IoDeleteDevice(WmipServiceDeviceObject);
663 IoDeleteSymbolicLink(&ServiceDosDeviceName);
664 return Status;
665 }
666
667 /* Create a symbolic link for the admin device */
668 Status = IoCreateSymbolicLink(&AdminDosDeviceName, &AdminDeviceName);
669 if (!NT_SUCCESS(Status))
670 {
671 DPRINT1("IoCreateSymbolicLink() failed: 0x%lx\n", Status);
672 IoDeleteSymbolicLink(&ServiceDosDeviceName);
673 IoDeleteDevice(WmipServiceDeviceObject);
674 IoDeleteDevice(WmipAdminDeviceObject);
675 return Status;
676 }
677
678 /* Initialize dispatch routines */
679 DriverObject->MajorFunction[IRP_MJ_CREATE] = WmipOpenCloseCleanup;
680 DriverObject->MajorFunction[IRP_MJ_CLOSE] = WmipOpenCloseCleanup;
681 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WmipIoControl;
682 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = WmipOpenCloseCleanup;
683 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = WmipSystemControl;
684 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = WmipShutdown;
685
686 /* Initialize fast dispatch */
687 RtlZeroMemory(&WmipFastIoDispatch, sizeof(WmipFastIoDispatch));
688 WmipFastIoDispatch.SizeOfFastIoDispatch = sizeof(WmipFastIoDispatch);
689 WmipFastIoDispatch.FastIoDeviceControl = WmipFastIoDeviceControl;
690 DriverObject->FastIoDispatch = &WmipFastIoDispatch;
691
692 /* Register the WMI service device */
693 IoWMIRegistrationControl(WmipServiceDeviceObject, WMIREG_ACTION_REGISTER);
694
695 /* Register a shutdown notification */
696 IoRegisterShutdownNotification(WmipServiceDeviceObject);
697
698 /* Initialization is done */
699 WmipServiceDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
700 WmipAdminDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
701
702 return STATUS_SUCCESS;
703 }
704
705