ReactOS  0.4.15-dev-2701-g34593d9
fxwmiprovider.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  FxWmiProvider.cpp
8 
9 Abstract:
10 
11  This module implements the FxWmiProvider object
12 
13 Author:
14 
15 
16 
17 Revision History:
18 
19 
20 --*/
21 
22 #include "fxwmipch.hpp"
23 
24 extern "C" {
25 // #include "FxWmiProvider.tmh"
26 }
27 
29  __in PFX_DRIVER_GLOBALS FxDriverGlobals,
32  ) :
35  FxDriverGlobals),
36  m_FunctionControl(FxDriverGlobals)
37 {
40  m_NumInstances = 0;
41 
42  m_Parent = Device->m_PkgWmi;
43 
47 
48  m_TracingHandle = 0;
49 
50  m_Flags = Config->Flags;
51  m_MinInstanceBufferSize = Config->MinInstanceBufferSize;
52  RtlCopyMemory(&m_Guid, &Config->Guid, sizeof(GUID));
53 
54  if (Config->EvtWmiProviderFunctionControl != NULL) {
55  m_FunctionControl.m_Method = Config->EvtWmiProviderFunctionControl;
56  }
57 
58  //
59  // Driver cannot call WdfObjectDelete on this handle
60  //
62 
64 }
65 
67 {
69 }
70 
71 BOOLEAN
73  VOID
74  )
75 {
76  //
77  // Object is being deleted, remove this object from the irp handler's list
78  // of providers. If we don't do this, the irp handler will have a list
79  // which contains entries which have been freed.
80  //
81  m_Parent->RemoveProvider(this);
82 
83  return FxNonPagedObject::Dispose(); // __super call
84 }
85 
89  __in PFX_DRIVER_GLOBALS CallersGlobals,
90  __in WDFDEVICE Device,
93  __out WDFWMIPROVIDER* WmiProvider,
95  )
96 {
102  GUID zeroGuid;
103  BOOLEAN update;
104 
105  FxObjectHandleGetPtrAndGlobals(CallersGlobals,
106  Device,
108  (PVOID*) &pDevice,
110 
111  *Provider = NULL;
112  update = FALSE;
113 
114  *WmiProvider = NULL;
115 
119  if (!NT_SUCCESS(status)) {
120  return status;
121  }
122 
123  if (WmiProviderConfig->Size != sizeof(WDF_WMI_PROVIDER_CONFIG)) {
125 
128  "WmiProviderConfig Size 0x%x, expected size 0x%x, %!STATUS!",
130  status);
131 
132  return status;
133  }
134 
135  if ((WmiProviderConfig->Flags & ~WdfWmiProviderValidFlags) != 0) {
139  "Invalid flag(s) set, Flags 0x%x, valid mask 0x%x, %!STATUS!",
141  status);
142  return status;
143  }
144 
145  if ((WmiProviderConfig->Flags & WdfWmiProviderTracing) &&
148 
151  "WdfWmiProviderTracing must be the only flag set, %!STATUS!",
152  status);
153 
154  return status;
155  }
156 
157  //
158  // Function control makes sense if it is expensive. Otherwise you will
159  // not be called back on it.
160  //
161  // The opposite, marking yourself as expensive but providing no callback is
162  // OK b/c the provider marks the enabled state and the driver can retrieve
163  // it at runtime.
164  //
165  // Function control also applies to tracing GUIDs since the tracing subsystem
166  // will call enable/disable events to start/stop tracing.
167  //
168  if (WmiProviderConfig->EvtWmiProviderFunctionControl != NULL &&
171 
174  "EvtWmiProviderFunctionControl can only be set if Flags 0x%x has "
175  "WdfWmiProviderTracing (%d) or WdfWmiProviderExpensive (%d) bit "
176  "values set, %!STATUS!",
179 
180  return status;
181  }
182 
183  RtlZeroMemory(&zeroGuid, sizeof(zeroGuid));
184 
186  &zeroGuid,
187  sizeof(GUID)) == sizeof(GUID)) {
189 
192  "WmiProvider Guid filed is all zeros, %!STATUS!",
193  status);
194 
195  return status;
196  }
197 
198  pProvider = NULL;
199 
202 
203  if (pProvider == NULL) {
205 
208  "Could not allocate memory for a WDFWMIPROVIDER, %!STATUS!",
209  status);
210 
211  return status;
212  }
213 
215 
216  if (NT_SUCCESS(status)) {
218 
219  if (!NT_SUCCESS(status)) {
221  }
222  else {
223  //
224  // NT_SUCCES(status) case
225  //
226  *WmiProvider = (WDFWMIPROVIDER) hProvider;
227  }
228  }
229 
230  if (NT_SUCCESS(status)) {
231  *Provider = pProvider;
232 
233  if (update) {
235  }
236  }
237  else {
238  //
239  // AddProvider incremented update count on success however since we
240  // are not going to update registration due to this failure, decrement
241  // the count.
242  //
243  if (update) {
245  }
246 
248  }
249 
250  return status;
251 }
252 
254 NTSTATUS
257  __in BOOLEAN NoErrorIfPresent,
260  )
261 {
263 
264  *Update = FALSE;
265 
266  if (!IsListEmpty(&Instance->m_ListEntry)) {
267  if (NoErrorIfPresent) {
268  return STATUS_SUCCESS;
269  }
270  else {
271  //
272  // Entry is already on a list, bad caller!
273  //
275 
278  "WDFWMIINSTANCE %p already added, %!STATUS!",
279  Instance->GetHandle(), status);
280 
281  return status;
282  }
283  }
284 
285  //
286  // Check to see if we are in the process of
287  //
288  switch (m_Parent->m_RegisteredState) {
290  //
291  // The GUID will be reported when we do the initial registration
292  //
293  break;
294 
296  //
297  // Either the GUID will be reported when we do the re-registration or
298  // we will clean it up when we goto the cleanup state.
299  //
300  break;
301 
303  //
304  // Since we already registered we need to tell WMI the change in the
305  // number of instances on this provider.
306  //
307  *Update = TRUE;
308  break;
309 
311  //
312  // Device is going away, registration is not allowed for the device
313  // anymore.
314  //
316 
319  "WMI is being cleanedup, WDFWMIINSTANCE %p add failing, %!STATUS!",
320  Instance->GetHandle(), status);
321 
322  return status;
323 
324  default:
325  ASSERT(FALSE);
326  break;
327  }
328 
329  if (Action == AddInstanceToTail) {
330  InsertTailList(&m_InstanceListHead, &Instance->m_ListEntry);
331  }
332  else {
333  InsertHeadList(&m_InstanceListHead, &Instance->m_ListEntry);
334  }
335 
336  //
337  // Since the count is increasing to at least one, we are not going to
338  // need to report this GUID as missing. We could check the
339  // m_Parent->m_RegisteredState and only set it when we are registered, but
340  // it does us no harm to always clear this value regardless of state.
341  //
343 
344  m_NumInstances++;
346 
347  return status;
348 }
349 
351 NTSTATUS
354  __in BOOLEAN NoErrorIfPresent
355  )
356 {
358  KIRQL irql;
359  BOOLEAN update;
360 
363 
366  "WDFWMIINSTANCE %p cannot be added to tracing WDFWMIPROVIDER %p, "
367  "%!STATUS!", Instance->GetHandle(), GetHandle(), status);
368 
369  return status;
370  }
371 
372  m_Parent->Lock(&irql);
373  status = AddInstanceLocked(Instance, NoErrorIfPresent, &update);
374 
375  if (update) {
376  update = m_Parent->DeferUpdateLocked(irql);
377  }
378  m_Parent->Unlock(irql);
379 
380  if (update) {
382  }
383 
384  return status;
385 }
386 
387 VOID
390  )
391 {
392  KIRQL irql;
393  BOOLEAN update;
394 
395  update = FALSE;
396 
397  m_Parent->Lock(&irql);
398 
399  if (!IsListEmpty(&Instance->m_ListEntry)) {
400  //
401  // Instance is in the list of instances on this provider. Remove it.
402  //
403  RemoveEntryList(&Instance->m_ListEntry);
404  InitializeListHead(&Instance->m_ListEntry);
405  m_NumInstances--;
406 
408  update = TRUE;
409 
410  //
411  // When the count goes to zero, inform WMI that the GUID should be
412  // removed when we get requeried. We only need to do this once we have
413  // been registered. In all other states, we ignore this value.
414  //
415  if (m_NumInstances == 0 &&
416  (m_Flags & WdfWmiProviderExpensive) == 0) {
417  m_RemoveGuid = TRUE;
418  }
419  }
420  }
421  else {
422  //
423  // The instance was explicitly removed and now the instance is trying
424  // to remove itself during dispose. Nothing to do.
425  //
426  DO_NOTHING();
427  }
428 
429  if (update) {
430  update = m_Parent->DeferUpdateLocked(irql);
431  }
432 
433  m_Parent->Unlock(irql);
434 
435  if (update) {
437  }
438 }
439 
440 ULONG
443  )
444 {
446  ULONG index;
447  KIRQL irql;
448 
449  m_Parent->Lock(&irql);
450  for (index = 0, ple = m_InstanceListHead.Flink;
452  index++, ple = ple->Flink) {
454  break;
455  }
456  }
457  m_Parent->Unlock(irql);
458 
459  return index;
460 }
461 
465  __in ULONG Index,
466  __in PVOID Tag
467  )
468 {
470  KIRQL irql;
471 
472  m_Parent->Lock(&irql);
474  m_Parent->Unlock(irql);
475 
476  return pInstance;
477 }
478 
482  __in ULONG Index,
483  __in PVOID Tag
484  )
485 {
486  FxWmiInstance* pFound;
488  ULONG i;
489 
490  pFound = NULL;
491 
492  for (i = 0, ple = m_InstanceListHead.Flink;
493  i < m_NumInstances;
494  ple = ple->Flink, i++) {
495 
496  if (i == Index) {
498  pFound->ADDREF(Tag);
499  break;
500  }
501  }
502 
503  return pFound;
504 }
505 
507 NTSTATUS
511  )
512 {
514  GetHandle(),
515  Control,
516  Enable);
517 }
518 
519 ULONG
521  VOID
522  )
523 {
524  ULONG flags;
525 
528 
529  //
530  // Once tracing GUID is registered, we do not allow it to be unregistered
531  //
533  }
534  else {
536 
539  }
540 
543  }
544  }
545 
546  if (m_RemoveGuid) {
547  //
548  // We have gone down to zero instances of this provider, report it as
549  // gone to WMI.
550  //
551  ASSERT(m_NumInstances == 0);
553 
554  //
555  // Once reported as removed, we do not have not have to report ourselves
556  // as removed again.
557  //
559  }
560 
561  return flags;
562 }
563 
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_WMI_PROVIDER_CONFIG WmiProviderConfig
Definition: wdfwmi.h:356
#define _Must_inspect_result_
Definition: no_sal2.h:62
__inline CfxDevice * GetDevice(VOID)
Definition: fxpackage.hpp:46
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
_Must_inspect_result_ NTSTATUS Commit(__in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __out_opt WDFOBJECT *ObjectHandle, __in_opt FxObject *Parent=NULL, __in BOOLEAN AssignDriverAsDefaultParent=TRUE)
Definition: fxobject.cpp:904
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
WmiRegisteredState m_RegisteredState
#define __in_opt
Definition: dbghelp.h:38
#define TRUE
Definition: types.h:120
FxWmiProvider * pProvider
Definition: fxwmiapi.cpp:54
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
WDF_EXTERN_C_START enum _WDF_WMI_PROVIDER_CONTROL WDF_WMI_PROVIDER_CONTROL
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LONG NTSTATUS
Definition: precomp.h:26
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:140
#define WMIREG_FLAG_EVENT_ONLY_GUID
Definition: wmistr.h:75
WDFWMIPROVIDER hProvider
Definition: fxwmiapi.cpp:165
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
KIRQL irql
Definition: wave.h:1
ULONG GetRegistrationFlagsLocked(VOID)
#define InsertTailList(ListHead, Entry)
FxWmiProviderFunctionControlCallback m_FunctionControl
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
BOOLEAN m_DataBlockControlEnabled
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
PSINGLE_LIST_ENTRY ple
_Must_inspect_result_ NTSTATUS AddProvider(__in FxWmiProvider *Provider, __out_opt PBOOLEAN Update=NULL)
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
FxWmiIrpHandler * m_PkgWmi
Definition: fxdevice.hpp:672
PFN_WDF_WMI_PROVIDER_FUNCTION_CONTROL m_Method
#define FALSE
Definition: types.h:117
VOID MarkDisposeOverride(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1101
#define __out
Definition: dbghelp.h:62
_Must_inspect_result_ FxWmiInstance * GetInstanceReferenced(__in ULONG Index, __in PVOID Tag)
_Must_inspect_result_ NTSTATUS AddInstanceLocked(__in FxWmiInstance *Instance, __in BOOLEAN NoErrorIfPresent, __out PBOOLEAN Update, __in AddInstanceAction Action=AddInstanceToTail)
unsigned char BOOLEAN
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
ULONG GetInstanceIndex(__in FxWmiInstance *Instance)
ULONG m_MinInstanceBufferSize
#define WMIREG_FLAG_INSTANCE_PDO
Definition: wmistr.h:69
GLuint index
Definition: glext.h:6031
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_WMI_PROVIDER_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWMIPROVIDER * WmiProvider
Definition: wdfwmi.h:356
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
VOID RemoveInstance(__in FxWmiInstance *Instance)
FxDevice * pDevice
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY m_InstanceListHead
#define TRACINGDEVICE
Definition: dbgtrace.h:58
PFX_DRIVER_GLOBALS pFxDriverGlobals
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define WMIREG_FLAG_REMOVE_GUID
Definition: wmistr.h:70
_In_ WDFCOLLECTION _In_ ULONG Index
BOOLEAN m_EventControlEnabled
BOOLEAN m_RemoveGuid
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_WMI_PROVIDER_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES ProviderAttributes
Definition: wdfwmi.h:356
GLbitfield flags
Definition: glext.h:7161
_Must_inspect_result_ FxWmiInstance * GetInstanceReferencedLocked(__in ULONG Index, __in PVOID Tag)
VOID UpdateGuids(VOID)
char * PBOOLEAN
Definition: retypes.h:11
virtual BOOLEAN Dispose(VOID)
#define index(s, c)
Definition: various.h:29
_Must_inspect_result_ NTSTATUS FxValidateObjectAttributes(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in ULONG Flags=FX_VALIDATE_OPTION_NONE_SPECIFIED)
VOID MarkNoDeleteDDI(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1118
Definition: typedefs.h:119
FxWmiProvider(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_WMI_PROVIDER_CONFIG Config, __in CfxDevice *Device)
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4061
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_CHILD_LIST_CONFIG Config
Definition: wdfchildlist.h:474
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACINGPNP
Definition: dbgtrace.h:67
FxWmiInstanceExternal * pInstance
Definition: fxwmiapi.cpp:113
BOOLEAN DeferUpdateLocked(__in KIRQL OldIrql)
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Must_inspect_result_ NTSTATUS FunctionControl(__in WDF_WMI_PROVIDER_CONTROL Control, __in BOOLEAN Enable)
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:506
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
#define NULL
Definition: types.h:112
_Must_inspect_result_ NTSTATUS Invoke(__in WDFDEVICE Device, __in WDFWMIPROVIDER WmiProvider, __in WDF_WMI_PROVIDER_CONTROL Control, __in BOOLEAN Enable)
#define WMIREG_FLAG_TRACED_GUID
Definition: wmistr.h:73
VOID DeleteFromFailedCreate(VOID)
Definition: fxobject.cpp:391
LIST_ENTRY m_ListEntry
FxWmiIrpHandler * m_Parent
unsigned int ULONG
Definition: retypes.h:1
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE,(PVOID *)&pDevice, &pFxDriverGlobals)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS CallersGlobals, __in WDFDEVICE Device, __in_opt PWDF_OBJECT_ATTRIBUTES ProviderAttributes, __in PWDF_WMI_PROVIDER_CONFIG WmiProviderConfig, __out WDFWMIPROVIDER *WmiProvider, __out FxWmiProvider **Provider)
virtual BOOLEAN Dispose(VOID)
WDFWMIPROVIDER GetHandle(VOID)
_Must_inspect_result_ NTSTATUS AddInstance(__in FxWmiInstance *Instance, __in BOOLEAN NoErrorIfPresent=FALSE)
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
ULONGLONG m_TracingHandle
#define WMIREG_FLAG_EXPENSIVE
Definition: wmistr.h:66
IN PVOID Instance
Definition: pci.h:361
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define WMIREG_FLAG_TRACE_CONTROL_GUID
Definition: wmistr.h:74
#define DO_NOTHING()
Definition: mxgeneral.h:32
VOID RemoveProvider(__in FxWmiProvider *Provider)
Definition: ps.c:97