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