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