1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxWmiApi.cpp
8 
9 Abstract:
10 
11     This module implements the C interface to the WMI package
12     for the driver frameworks.
13 
14 Author:
15 
16 
17 
18 Environment:
19 
20     Kernel mode only
21 
22 Revision History:
23 
24 
25 
26 --*/
27 
28 #include "fxwmipch.hpp"
29 
30 //
31 // Extern "C" the tmh file and all external APIs
32 //
33 extern "C" {
34 #include "fxwmiapi.tmh"
35 
36 _Must_inspect_result_
37 __drv_maxIRQL(DISPATCH_LEVEL)
38 NTSTATUS
39 WDFEXPORT(WdfWmiProviderCreate)(
40     __in
41     PWDF_DRIVER_GLOBALS DriverGlobals,
42     __in
43     WDFDEVICE Device,
44     __in
45     PWDF_WMI_PROVIDER_CONFIG WmiProviderConfig,
46     __in_opt
47     PWDF_OBJECT_ATTRIBUTES ProviderAttributes,
48     __out
49     WDFWMIPROVIDER* WmiProvider
50     )
51 {
52     FxDevice* pDevice;
53     FxPowerPolicyOwnerSettings* ownerSettings;
54     FxWmiProvider* pProvider;
55 
56     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
57                          Device,
58                          FX_TYPE_DEVICE,
59                          (PVOID*) &pDevice);
60 
61     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), WmiProviderConfig);
62     FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), WmiProvider);
63 
64     //
65     // If the Device is a power policy owner then do not allow client drivers
66     // to register for GUID_POWER_DEVICE_ENABLE or GUID_POWER_DEVICE_WAKE_ENABLE
67     // if the framework has already register a provider for those guids.
68     //
69     if (pDevice->m_PkgPnp->IsPowerPolicyOwner()) {
70         ownerSettings = pDevice->m_PkgPnp->m_PowerPolicyMachine.m_Owner;
71 
72         if ((FxIsEqualGuid(&WmiProviderConfig->Guid,
73                            &GUID_POWER_DEVICE_ENABLE) &&
74              ownerSettings->m_IdleSettings.WmiInstance != NULL) ||
75 
76             (FxIsEqualGuid(&WmiProviderConfig->Guid,
77                            &GUID_POWER_DEVICE_WAKE_ENABLE) &&
78              ownerSettings->m_WakeSettings.WmiInstance != NULL)) {
79 
80             DoTraceLevelMessage(GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_ERROR,
81                                 TRACINGDEVICE, "WMI Guid already registered by "
82                                 "framework");
83             return STATUS_WMI_GUID_DISCONNECTED;
84         }
85     }
86 
87     return FxWmiProvider::_Create(GetFxDriverGlobals(DriverGlobals),
88                                   Device,
89                                   ProviderAttributes,
90                                   WmiProviderConfig,
91                                   WmiProvider,
92                                   &pProvider);
93 }
94 
95 _Must_inspect_result_
96 __drv_maxIRQL(DISPATCH_LEVEL)
97 NTSTATUS
98 WDFEXPORT(WdfWmiInstanceCreate)(
99     __in
100     PWDF_DRIVER_GLOBALS DriverGlobals,
101     __in
102     WDFDEVICE Device,
103     __in
104     PWDF_WMI_INSTANCE_CONFIG InstanceConfig,
105     __in_opt
106     PWDF_OBJECT_ATTRIBUTES InstanceAttributes,
107     __out_opt
108     WDFWMIINSTANCE* Instance
109     )
110 {
111     PFX_DRIVER_GLOBALS pFxDriverGlobals;
112     FxWmiProvider* pProvider;
113     FxWmiInstanceExternal* pInstance;
114     WDFWMIINSTANCE hInstance;
115     NTSTATUS status;
116 
117     pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
118     pInstance = NULL;
119 
120     FxPointerNotNull(pFxDriverGlobals, InstanceConfig);
121 
122     if (InstanceConfig->Size != sizeof(WDF_WMI_INSTANCE_CONFIG)) {
123         status = STATUS_INFO_LENGTH_MISMATCH;
124         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
125                             "Expected InstanceConfig Size %d, got %d, %!STATUS!",
126                             InstanceConfig->Size, sizeof(*InstanceConfig),
127                             status);
128         return status;
129     }
130 
131     if (InstanceConfig->Provider == NULL &&
132                                     InstanceConfig->ProviderConfig == NULL) {
133         status = STATUS_INVALID_PARAMETER;
134 
135         DoTraceLevelMessage(
136             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
137             "InstanceConfig %p Provider and ProviderConfig are both NULL, only "
138             "one can be, %!STATUS!", InstanceConfig, status);
139 
140         return status;
141     }
142     else if (InstanceConfig->Provider != NULL &&
143                                     InstanceConfig->ProviderConfig != NULL) {
144         status = STATUS_INVALID_PARAMETER;
145 
146         DoTraceLevelMessage(
147             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
148             "InstanceConfig %p Provider %p and ProviderConfig %p are both not "
149             "NULL, only one can be, %!STATUS!", InstanceConfig,
150             InstanceConfig->Provider, InstanceConfig->ProviderConfig, status);
151 
152         return status;
153     }
154 
155     if (InstanceConfig->Provider != NULL) {
156         FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
157                                        InstanceConfig->Provider,
158                                        FX_TYPE_WMI_PROVIDER,
159                                        (PVOID*) &pProvider,
160                                        &pFxDriverGlobals);
161     }
162     else {
163         FxDevice* pDevice;
164         FxPowerPolicyOwnerSettings* ownerSettings;
165         WDFWMIPROVIDER hProvider;
166 
167         hProvider = NULL;
168         FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
169                              Device,
170                              FX_TYPE_DEVICE,
171                              (PVOID*) &pDevice);
172 
173         //
174         // If the Device is a power policy owner then do not allow client drivers
175         // to register for GUID_POWER_DEVICE_ENABLE or GUID_POWER_DEVICE_WAKE_ENABLE
176         // if the framework has already register a provider for those guids.
177         //
178         if (pDevice->m_PkgPnp->IsPowerPolicyOwner()) {
179             ownerSettings = pDevice->m_PkgPnp->m_PowerPolicyMachine.m_Owner;
180 
181             if ((FxIsEqualGuid(&InstanceConfig->ProviderConfig->Guid,
182                                &GUID_POWER_DEVICE_ENABLE) &&
183                  ownerSettings->m_IdleSettings.WmiInstance != NULL) ||
184 
185                 (FxIsEqualGuid(&InstanceConfig->ProviderConfig->Guid,
186                                &GUID_POWER_DEVICE_WAKE_ENABLE) &&
187                  ownerSettings->m_WakeSettings.WmiInstance != NULL)) {
188 
189                 status = STATUS_WMI_GUID_DISCONNECTED;
190                 DoTraceLevelMessage(GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_ERROR,
191                                     TRACINGDEVICE, "WMI Guid already registered by "
192                                     "framework");
193                 return status;
194             }
195         }
196 
197         status = FxWmiProvider::_Create(pFxDriverGlobals,
198                                         Device,
199                                         NULL,
200                                         InstanceConfig->ProviderConfig,
201                                         &hProvider,
202                                         &pProvider);
203 
204         if (!NT_SUCCESS(status)) {
205             return status;
206         }
207 
208         //
209         // Use the object's globals and not the caller's
210         //
211         pFxDriverGlobals = pProvider->GetDriverGlobals();
212     }
213 
214     status = FxWmiInstanceExternal::_Create(pFxDriverGlobals,
215                                             pProvider,
216                                             InstanceConfig,
217                                             InstanceAttributes,
218                                             &hInstance,
219                                             &pInstance);
220 
221     if (NT_SUCCESS(status) && InstanceConfig->Register) {
222         status = pProvider->AddInstance(pInstance);
223     }
224 
225     if (NT_SUCCESS(status)) {
226         if (Instance != NULL) {
227             *Instance = hInstance;
228         }
229     }
230     else {
231         //
232         // Something went wrong, cleanup
233         //
234         if (pInstance != NULL) {
235             //
236             // This will remove the instance from the provider's list as well.
237             //
238             pInstance->DeleteFromFailedCreate();
239         }
240 
241         //
242         // Only remove the provider if we created it in this function
243         //
244         if (InstanceConfig->ProviderConfig != NULL) {
245             pProvider->DeleteFromFailedCreate();
246         }
247     }
248 
249     return status;
250 }
251 
252 WDFAPI
253 __drv_maxIRQL(DISPATCH_LEVEL)
254 WDFDEVICE
255 WDFEXPORT(WdfWmiProviderGetDevice)(
256     __in
257     PWDF_DRIVER_GLOBALS DriverGlobals,
258     __in
259     WDFWMIPROVIDER WmiProvider
260     )
261 {
262     FxWmiProvider *pProvider;
263 
264     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
265                          WmiProvider,
266                          FX_TYPE_WMI_PROVIDER,
267                          (PVOID*) &pProvider);
268 
269     return pProvider->GetDevice()->GetHandle();
270 }
271 
272 __drv_maxIRQL(DISPATCH_LEVEL)
273 BOOLEAN
274 WDFEXPORT(WdfWmiProviderIsEnabled)(
275     __in
276     PWDF_DRIVER_GLOBALS DriverGlobals,
277     __in
278     WDFWMIPROVIDER WmiProvider,
279     __in
280     WDF_WMI_PROVIDER_CONTROL ProviderControl
281     )
282 {
283     FxWmiProvider *pProvider;
284 
285     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
286                          WmiProvider,
287                          FX_TYPE_WMI_PROVIDER,
288                          (PVOID*) &pProvider);
289 
290     return pProvider->IsEnabled(ProviderControl);
291 }
292 
293 __drv_maxIRQL(DISPATCH_LEVEL)
294 ULONGLONG
295 WDFEXPORT(WdfWmiProviderGetTracingHandle)(
296     __in
297     PWDF_DRIVER_GLOBALS DriverGlobals,
298     __in
299     WDFWMIPROVIDER WmiProvider
300     )
301 {
302     FxWmiProvider *pProvider;
303 
304     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
305                          WmiProvider,
306                          FX_TYPE_WMI_PROVIDER,
307                          (PVOID*) &pProvider);
308 
309     return pProvider->GetTracingHandle();
310 }
311 
312 _Must_inspect_result_
313 __drv_maxIRQL(DISPATCH_LEVEL)
314 NTSTATUS
315 WDFEXPORT(WdfWmiInstanceRegister)(
316     __in
317     PWDF_DRIVER_GLOBALS DriverGlobals,
318     __in
319     WDFWMIINSTANCE WmiInstance
320     )
321 {
322     FxWmiInstanceExternal* pInstance;
323     FxWmiProvider* pProvider;
324 
325     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
326                          WmiInstance,
327                          FX_TYPE_WMI_INSTANCE,
328                          (PVOID*) &pInstance);
329 
330     pProvider = pInstance->GetProvider();
331 
332     return pProvider->AddInstance(pInstance);
333 }
334 
335 __drv_maxIRQL(DISPATCH_LEVEL)
336 VOID
337 WDFEXPORT(WdfWmiInstanceDeregister)(
338     __in
339     PWDF_DRIVER_GLOBALS DriverGlobals,
340     __in
341     WDFWMIINSTANCE WmiInstance
342     )
343 {
344     FxWmiInstanceExternal* pInstance;
345     FxWmiProvider* pProvider;
346 
347     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
348                          WmiInstance,
349                          FX_TYPE_WMI_INSTANCE,
350                          (PVOID*) &pInstance);
351 
352     pProvider = pInstance->GetProvider();
353     pProvider->RemoveInstance(pInstance);
354 }
355 
356 __drv_maxIRQL(DISPATCH_LEVEL)
357 WDFDEVICE
358 WDFEXPORT(WdfWmiInstanceGetDevice)(
359     __in
360     PWDF_DRIVER_GLOBALS DriverGlobals,
361     __in
362     WDFWMIINSTANCE WmiInstance
363     )
364 {
365     FxWmiInstanceExternal* pInstance;
366 
367     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
368                          WmiInstance,
369                          FX_TYPE_WMI_INSTANCE,
370                          (PVOID*) &pInstance);
371 
372     return pInstance->GetDevice()->GetHandle();
373 }
374 
375 __drv_maxIRQL(DISPATCH_LEVEL)
376 WDFWMIPROVIDER
377 WDFEXPORT(WdfWmiInstanceGetProvider)(
378     __in
379     PWDF_DRIVER_GLOBALS DriverGlobals,
380     __in
381     WDFWMIINSTANCE WmiInstance
382     )
383 {
384     FxWmiInstanceExternal *pInstance;
385 
386     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
387                          WmiInstance,
388                          FX_TYPE_WMI_INSTANCE,
389                          (PVOID*) &pInstance);
390 
391     return pInstance->GetProvider()->GetHandle();
392 }
393 
394 
395 _Must_inspect_result_
396 __drv_maxIRQL(APC_LEVEL)
397 NTSTATUS
398 WDFEXPORT(WdfWmiInstanceFireEvent)(
399     __in
400     PWDF_DRIVER_GLOBALS DriverGlobals,
401     __in
402     WDFWMIINSTANCE WmiInstance,
403     __in_opt
404     ULONG EventDataSize,
405     __in_bcount_opt(EventDataSize)
406     PVOID EventData
407     )
408 /*++
409 
410 Routine Description:
411     Fires an event based on the instance handle.
412 
413 Arguments:
414     WmiInstance - instance which the event is associated with
415     EventDataSize - size of EventData in bytes
416     EventData - buffer associated with the event
417 
418 Return Value:
419     NTSTATUS
420 
421   --*/
422 {
423     FxWmiInstanceExternal* pInstance;
424     NTSTATUS status;
425 
426     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
427                          WmiInstance,
428                          FX_TYPE_WMI_INSTANCE,
429                          (PVOID*) &pInstance);
430 
431     status = FxVerifierCheckIrqlLevel(pInstance->GetDriverGlobals(), APC_LEVEL);
432     if (!NT_SUCCESS(status)) {
433         return status;
434     }
435 
436     return pInstance->FireEvent(EventData, EventDataSize);
437 }
438 
439 } // extern "C"
440