1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxWmiInstance.cpp
8 
9 Abstract:
10 
11     This module implements the FxWmiInstance object and its derivations
12 
13 Author:
14 
15 
16 
17 Revision History:
18 
19 
20 --*/
21 
22 #include "fxwmipch.hpp"
23 
24 extern "C" {
25 // #include "FxWmiInstance.tmh"
26 }
27 
FxWmiInstance(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in USHORT ObjectSize,__in FxWmiProvider * Provider)28 FxWmiInstance::FxWmiInstance(
29     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
30     __in USHORT ObjectSize,
31     __in FxWmiProvider* Provider
32     ) :
33     FxNonPagedObject(FX_TYPE_WMI_INSTANCE, ObjectSize, FxDriverGlobals)
34 {
35     InitializeListHead(&m_ListEntry);
36     m_Provider = Provider;
37     m_Provider->ADDREF(this);
38     MarkDisposeOverride(ObjectDoNotLock);
39 }
40 
~FxWmiInstance()41 FxWmiInstance::~FxWmiInstance()
42 {
43     ASSERT(IsListEmpty(&m_ListEntry));
44 }
45 
46 BOOLEAN
Dispose(VOID)47 FxWmiInstance::Dispose(
48     VOID
49     )
50 {
51     m_Provider->RemoveInstance(this);
52     m_Provider->RELEASE(this);
53 
54     //
55     // Object is being deleted, remove this object from the provider's list
56     // of instances.  If we don't do this, the provider will have a list which
57     // contains entries which have been freed.
58     //
59     return FxNonPagedObject::Dispose(); // __super call
60 }
61 
62 _Must_inspect_result_
63 NTSTATUS
FireEvent(__in_bcount_opt (EventBufferSize)PVOID EventBuffer,__inout ULONG EventBufferSize)64 FxWmiInstance::FireEvent(
65     __in_bcount_opt(EventBufferSize) PVOID EventBuffer,
66     __inout ULONG EventBufferSize
67     )
68 {
69     ULONG sizeNeeded;
70     PWNODE_SINGLE_INSTANCE pNode;
71     NTSTATUS status;
72 
73     if (EventBuffer == NULL) {
74         EventBufferSize = 0;
75     }
76 
77     sizeNeeded = sizeof(WNODE_SINGLE_INSTANCE) + EventBufferSize;
78 
79     //
80     // IoWMIWriteEvent will free the memory by calling ExFreePool. This means
81     // we cannot use a framework allocate function.
82     //
83     pNode = (PWNODE_SINGLE_INSTANCE)
84         ExAllocatePoolWithTag(NonPagedPool, sizeNeeded, GetDriverGlobals()->Tag);
85 
86     if (pNode != NULL) {
87         RtlCopyMemory(&pNode->WnodeHeader.Guid,
88                       m_Provider->GetGUID(),
89                       sizeof(GUID));
90 
91         pNode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(
92             GetDevice()->GetDeviceObject());
93         pNode->WnodeHeader.BufferSize = sizeNeeded;
94         pNode->WnodeHeader.Flags =  WNODE_FLAG_SINGLE_INSTANCE |
95                                     WNODE_FLAG_EVENT_ITEM |
96                                     WNODE_FLAG_STATIC_INSTANCE_NAMES;
97         KeQuerySystemTime(&pNode->WnodeHeader.TimeStamp);
98 
99         pNode->InstanceIndex = m_Provider->GetInstanceIndex(this);
100         pNode->SizeDataBlock = EventBufferSize;
101         pNode->DataBlockOffset = sizeof(WNODE_SINGLE_INSTANCE);
102 
103         if (EventBuffer != NULL) {
104             RtlCopyMemory(&pNode->VariableData, EventBuffer, EventBufferSize);
105         }
106 
107         //
108         // Upon success, IoWMIWriteEvent will free pNode.
109         //
110         status = IoWMIWriteEvent(pNode);
111 
112         if (!NT_SUCCESS(status)) {
113             ExFreePool(pNode);
114         }
115     }
116     else {
117         status = STATUS_INSUFFICIENT_RESOURCES;
118 
119         DoTraceLevelMessage(
120             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
121             "WDFWMIINSTANCE %p insufficient resources to fire event,%!STATUS!",
122             GetHandle(), status);
123     }
124 
125     return status;
126 }
127 
FxWmiInstanceExternal(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in PWDF_WMI_INSTANCE_CONFIG Config,__in FxWmiProvider * Provider)128 FxWmiInstanceExternal::FxWmiInstanceExternal(
129     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
130     __in PWDF_WMI_INSTANCE_CONFIG Config,
131     __in FxWmiProvider* Provider
132     ) :
133     FxWmiInstance(FxDriverGlobals, sizeof(FxWmiInstanceExternal), Provider),
134     m_QueryInstanceCallback(FxDriverGlobals),
135     m_SetInstanceCallback(FxDriverGlobals),
136     m_SetItemCallback(FxDriverGlobals),
137     m_ExecuteMethodCallback(FxDriverGlobals)
138 {
139     m_ContextLength = 0;
140     m_UseContextForQuery = Config->UseContextForQuery;
141 
142     if (m_UseContextForQuery == FALSE) {
143         m_QueryInstanceCallback.m_Method = Config->EvtWmiInstanceQueryInstance;
144     }
145     m_SetInstanceCallback.m_Method = Config->EvtWmiInstanceSetInstance;
146     m_SetItemCallback.m_Method = Config->EvtWmiInstanceSetItem;
147 
148     m_ExecuteMethodCallback.m_Method = Config->EvtWmiInstanceExecuteMethod;
149 }
150 
151 _Must_inspect_result_
152 NTSTATUS
_Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in FxWmiProvider * Provider,__in PWDF_WMI_INSTANCE_CONFIG WmiInstanceConfig,__in_opt PWDF_OBJECT_ATTRIBUTES InstanceAttributes,__out WDFWMIINSTANCE * WmiInstance,__out FxWmiInstanceExternal ** Instance)153 FxWmiInstanceExternal::_Create(
154     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
155     __in FxWmiProvider* Provider,
156     __in PWDF_WMI_INSTANCE_CONFIG WmiInstanceConfig,
157     __in_opt PWDF_OBJECT_ATTRIBUTES InstanceAttributes,
158     __out WDFWMIINSTANCE* WmiInstance,
159     __out FxWmiInstanceExternal** Instance
160     )
161 {
162     FxWmiInstanceExternal* pInstance;
163     WDFWMIINSTANCE hInstance;
164     NTSTATUS status;
165     size_t contextSize;
166 
167     contextSize = 0;
168     *Instance = 0;
169 
170     *WmiInstance = NULL;
171 
172     //
173     // For event only providers, you cannot specify any callbacks or context
174     // usage.
175     //
176     if (Provider->IsEventOnly() &&
177         (WmiInstanceConfig->UseContextForQuery ||
178          WmiInstanceConfig->EvtWmiInstanceQueryInstance != NULL ||
179          WmiInstanceConfig->EvtWmiInstanceSetInstance != NULL ||
180          WmiInstanceConfig->EvtWmiInstanceSetItem != NULL ||
181          WmiInstanceConfig->EvtWmiInstanceExecuteMethod != NULL)) {
182 
183         status = STATUS_INVALID_PARAMETER;
184 
185         DoTraceLevelMessage(
186             FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
187             "WDFWMIPROVIDER %p is event only and UseContextForQuery (%d) is TRUE,"
188             " or a callback (query instance %p, set instance %p, set item %p, "
189             "executue method %p) is not NULL, %!STATUS!",
190             Provider->GetHandle(), WmiInstanceConfig->UseContextForQuery,
191             WmiInstanceConfig->EvtWmiInstanceQueryInstance,
192             WmiInstanceConfig->EvtWmiInstanceSetInstance,
193             WmiInstanceConfig->EvtWmiInstanceSetItem,
194             WmiInstanceConfig->EvtWmiInstanceExecuteMethod, status);
195 
196         return status;
197     }
198 
199     status = FxValidateObjectAttributes(FxDriverGlobals,
200                                         InstanceAttributes,
201                                         FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
202     if (!NT_SUCCESS(status)) {
203         return status;
204     }
205 
206     if (WmiInstanceConfig->UseContextForQuery) {
207         //
208         // UseContextForQuery only supported for read only instances.
209         // ExecuteMethod has undefined side affects, so we allow it.
210         //
211         if (WmiInstanceConfig->EvtWmiInstanceSetInstance != NULL ||
212             WmiInstanceConfig->EvtWmiInstanceSetItem != NULL) {
213             status = STATUS_INVALID_PARAMETER;
214 
215             DoTraceLevelMessage(
216                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
217                 "UseContextForQuery set, i.e. a read only instance, but "
218                 "EvtWmiInstanceSetInstance %p or EvtWmiInstanceSetItem %p is "
219                 "set, %!STATUS!",
220                 WmiInstanceConfig->EvtWmiInstanceSetInstance,
221                 WmiInstanceConfig->EvtWmiInstanceSetItem, status);
222 
223             return status;
224         }
225 
226         //
227         // We must have a context to use for the query
228         //
229         if (InstanceAttributes == NULL ||
230             InstanceAttributes->ContextTypeInfo == NULL) {
231             status = STATUS_INVALID_PARAMETER;
232 
233             DoTraceLevelMessage(
234                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
235                 "UseContextForQuery set, but InstanceAttributes %p is null or "
236                 "there is no associated type, %!STATUS!",
237                 InstanceAttributes, status);
238 
239             return status;
240         }
241 
242         contextSize = InstanceAttributes->ContextTypeInfo->ContextSize;
243 
244         if (InstanceAttributes->ContextSizeOverride != 0) {
245             status = RtlSizeTAdd(contextSize,
246                                  InstanceAttributes->ContextSizeOverride,
247                                  &contextSize);
248             if (!NT_SUCCESS(status)) {
249                 DoTraceLevelMessage(
250                     FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
251                     "Overlfow adding contextSize %I64d with size override %I64d, "
252                     "%!STATUS!", contextSize,
253                     InstanceAttributes->ContextSizeOverride, status);
254 
255                 return status;
256             }
257         }
258 
259         if (contextSize > ULONG_MAX) {
260             //
261             // Since we are casting to a ULONG below, detect loss of data here
262             // (only really applicable on 64 bit machines where sizeof(size_t) !=
263             // sizeof(ULONG)
264             //
265             status = STATUS_INTEGER_OVERFLOW;
266 
267             DoTraceLevelMessage(
268                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
269                 "context size %I64d can be %d large, %!STATUS!",
270                 contextSize, ULONG_MAX, status);
271 
272             return status;
273         }
274 
275         //
276         // Make sure the context is the minimum the buffer size.
277         //
278         if (contextSize < Provider->GetMinInstanceBufferSize()) {
279             status = STATUS_BUFFER_TOO_SMALL;
280 
281             DoTraceLevelMessage(
282                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
283                 "context size %I64d is less then the WDFWMIPROVIDER %p min size "
284                 "of %d, %!STATUS!",
285                 contextSize, Provider->GetHandle(),
286                 Provider->GetMinInstanceBufferSize(), status);
287 
288             return status;
289         }
290     }
291 
292     pInstance = new(FxDriverGlobals, InstanceAttributes)
293         FxWmiInstanceExternal(FxDriverGlobals, WmiInstanceConfig, Provider);
294 
295     if (pInstance == NULL) {
296         status = STATUS_INSUFFICIENT_RESOURCES;
297 
298         DoTraceLevelMessage(
299             FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
300             "could not allocate memory for WDFWMIINSTANCE, %!STATUS!",
301             status);
302 
303         return status;
304     }
305 
306     if (contextSize > 0) {
307         pInstance->SetContextForQueryLength((ULONG) contextSize);
308     }
309 
310     if (NT_SUCCESS(status)) {
311         status = pInstance->Commit(
312             InstanceAttributes, (PWDFOBJECT) &hInstance, Provider);
313 
314         if (NT_SUCCESS(status)) {
315             //
316             // Assign the handle back to the caller.
317             //
318             *WmiInstance = hInstance;
319         }
320         else {
321             //
322             // On failure, DeleteFromFailedCreate will delete the object and
323             // the Dispose callback will remove the instance from the provider's
324             // list.
325             //
326             DO_NOTHING();
327         }
328     }
329 
330     if (NT_SUCCESS(status)) {
331         *Instance = pInstance;
332     }
333     else {
334         pInstance->DeleteFromFailedCreate();
335     }
336 
337     return status;
338 }
339 
340 BOOLEAN
IsQueryInstanceSupported(VOID)341 FxWmiInstanceExternal::IsQueryInstanceSupported(
342     VOID
343     )
344 {
345     //
346     // If we have a function pointer to call or we are using the context
347     // as the buffer, query instance is supported.
348     //
349     // Also, if neither of the first 2 are true, we need to support query
350     // instance if the device has an execute method callback b/c WMI will
351     // send a query instance to this instance which much succeed for the
352     // execute method irp to be sent.
353     //
354     return (m_UseContextForQuery ||
355             m_QueryInstanceCallback.m_Method != NULL ||
356             m_ExecuteMethodCallback.m_Method != NULL) ? TRUE
357                                                       : FALSE;
358 }
359 
360 _Must_inspect_result_
361 __drv_sameIRQL
__drv_maxIRQL(PASSIVE_LEVEL)362 __drv_maxIRQL(PASSIVE_LEVEL)
363 NTSTATUS
364 FxWmiInstanceExternal::QueryInstance(
365     __inout ULONG OutBufferSize,
366     __out_bcount(OutBufferSize) PVOID OutBuffer,
367     __out PULONG BufferUsed
368     )
369 {
370     NTSTATUS status;
371 
372     if (m_UseContextForQuery) {
373         //
374         // No matter what, we are reporting the length of the context.  If the
375         // buffer is too small, it is used to report the desired buffer length.
376         // Otherwise, it is the amount of data we copied to the query buffer.
377         //
378         *BufferUsed = m_ContextLength;
379 
380         if (OutBufferSize < m_ContextLength) {
381             status = STATUS_BUFFER_TOO_SMALL;
382 
383             DoTraceLevelMessage(
384                 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
385                 "WDFWMIINSTANCE %p query instance using context for query, "
386                 "query buffer length %d, context length %d, %!STATUS!",
387                 GetHandle(), OutBufferSize, m_ContextLength, status);
388         }
389         else {
390             status = STATUS_SUCCESS;
391 
392             RtlCopyMemory(OutBuffer,
393                           &GetContextHeader()->Context[0],
394                           m_ContextLength);
395         }
396     }
397     else if (m_QueryInstanceCallback.m_Method != NULL) {
398         BYTE dummy;
399 
400         if (OutBufferSize == 0) {
401             ASSERT(m_Provider->GetMinInstanceBufferSize() == 0);
402             OutBuffer = (PVOID) &dummy;
403             OutBufferSize = sizeof(dummy);
404         }
405 
406         status = m_QueryInstanceCallback.Invoke(
407             GetDevice()->GetHandle(),
408             GetHandle(),
409             OutBufferSize,
410             OutBuffer,
411             BufferUsed
412             );
413 
414         if (status == STATUS_PENDING) {
415             DoTraceLevelMessage(
416                 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
417                 "WDFWMIINSTANCE %p was queried and returned %!STATUS!, which is "
418                 "not an allowed return value", GetHandle(), status);
419 
420             FxVerifierDbgBreakPoint(GetDriverGlobals());
421 
422             status = STATUS_UNSUCCESSFUL;
423             *BufferUsed = 0;
424         }
425         else if (NT_SUCCESS(status)) {
426             if (*BufferUsed > OutBufferSize) {
427                 //
428                 // Caller error, they returned more bytes in *BufferUsed then
429                 // was passed in via OutBufferSize, yet returned NT_SUCCESS
430                 //
431                 DoTraceLevelMessage(
432                     GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
433                     "WDFWMIINSTANCE %p was queried with buffer size %d, "
434                     " but returned %d bytes and %!STATUS!, should return "
435                     "!NT_SUCCESS in this case",
436                     GetHandle(), OutBufferSize, *BufferUsed, status);
437 
438                 FxVerifierDbgBreakPoint(GetDriverGlobals());
439 
440                 status = STATUS_UNSUCCESSFUL;
441                 *BufferUsed = 0;
442             }
443             else if (OutBuffer == &dummy && *BufferUsed > 0) {
444                 //
445                 // Convert success back to an error where we can report the
446                 // required size back to the caller.
447                 //
448                 status = STATUS_BUFFER_TOO_SMALL;
449             }
450         }
451         else if (status == STATUS_BUFFER_TOO_SMALL) {
452             if (m_Provider->GetMinInstanceBufferSize()) {
453                 DoTraceLevelMessage(
454                     GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
455                     "WDFWMIINSTANCE %p returned %!STATUS!, but it specified "
456                     "a minimum instance size %d in its WDFWMIPROVIDER %p",
457                     GetHandle(), status, m_Provider->GetMinInstanceBufferSize(),
458                     m_Provider->GetHandle());
459                 DoTraceLevelMessage(
460                     GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
461                     "This is a break in the contract.  Minimum instance size "
462                     "should only be used for fixed sized instances");
463 
464                 FxVerifierDbgBreakPoint(GetDriverGlobals());
465             }
466         }
467     }
468     else {
469         ASSERT(m_ExecuteMethodCallback.m_Method != NULL);
470 
471         DoTraceLevelMessage(
472             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
473             "WDFWMIINSTANCE %p was queried with no query callback and supports "
474             "execute method (%p), zero bytes returned", GetHandle(),
475             m_ExecuteMethodCallback.m_Method);
476 
477         status = STATUS_SUCCESS;
478         *BufferUsed = 0;
479     }
480 
481     return status;
482 }
483 
484 BOOLEAN
IsSetInstanceSupported(VOID)485 FxWmiInstanceExternal::IsSetInstanceSupported(
486     VOID
487     )
488 {
489     return m_SetInstanceCallback.m_Method != NULL ? TRUE : FALSE;
490 }
491 
492 _Must_inspect_result_
493 __drv_sameIRQL
__drv_maxIRQL(PASSIVE_LEVEL)494 __drv_maxIRQL(PASSIVE_LEVEL)
495 NTSTATUS
496 FxWmiInstanceExternal::SetInstance(
497     __in ULONG InBufferSize,
498     __in_bcount(InBufferSize) PVOID InBuffer
499     )
500 {
501     return m_SetInstanceCallback.Invoke(
502         GetDevice()->GetHandle(),
503         GetHandle(),
504         InBufferSize,
505         InBuffer
506         );
507 }
508 
509 BOOLEAN
IsSetItemSupported(VOID)510 FxWmiInstanceExternal::IsSetItemSupported(
511     VOID
512     )
513 {
514     return m_SetItemCallback.m_Method != NULL ? TRUE : FALSE;
515 }
516 
517 _Must_inspect_result_
518 __drv_sameIRQL
__drv_maxIRQL(PASSIVE_LEVEL)519 __drv_maxIRQL(PASSIVE_LEVEL)
520 NTSTATUS
521 FxWmiInstanceExternal::SetItem(
522     __in ULONG DataItemId,
523     __in ULONG InBufferSize,
524     __in_bcount(InBufferSize) PVOID InBuffer
525     )
526 {
527     return m_SetItemCallback.Invoke(
528         GetDevice()->GetHandle(),
529         GetHandle(),
530         DataItemId,
531         InBufferSize,
532         InBuffer
533         );
534 }
535 
536 BOOLEAN
IsExecuteMethodSupported(VOID)537 FxWmiInstanceExternal::IsExecuteMethodSupported(
538     VOID
539     )
540 {
541     return m_ExecuteMethodCallback.m_Method != NULL ? TRUE : FALSE;
542 }
543 
544 _Must_inspect_result_
545 __drv_sameIRQL
__drv_maxIRQL(PASSIVE_LEVEL)546 __drv_maxIRQL(PASSIVE_LEVEL)
547 NTSTATUS
548 FxWmiInstanceExternal::ExecuteMethod(
549     __in ULONG MethodId,
550     __in ULONG InBufferSize,
551     __inout ULONG OutBufferSize,
552     __drv_when(InBufferSize >= OutBufferSize, __inout_bcount(InBufferSize))
553     __drv_when(InBufferSize < OutBufferSize, __inout_bcount(OutBufferSize))
554         PVOID Buffer,
555     __out PULONG BufferUsed
556     )
557 {
558     return m_ExecuteMethodCallback.Invoke(
559         GetDevice()->GetHandle(),
560         GetHandle(),
561         MethodId,
562         InBufferSize,
563         OutBufferSize,
564         Buffer,
565         BufferUsed
566         );
567 }
568 
FxWmiInstanceInternal(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in FxWmiInstanceInternalCallbacks * Callbacks,__in FxWmiProvider * Provider)569 FxWmiInstanceInternal::FxWmiInstanceInternal(
570     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
571     __in FxWmiInstanceInternalCallbacks* Callbacks,
572     __in FxWmiProvider* Provider
573     ) : FxWmiInstance(FxDriverGlobals, sizeof(FxWmiInstanceInternal), Provider)
574 {
575     m_QueryInstance = Callbacks->QueryInstance;
576     m_SetInstance = Callbacks->SetInstance;
577     m_SetItem = Callbacks->SetItem;
578     m_ExecuteMethod = Callbacks->ExecuteMethod;
579 }
580 
581 BOOLEAN
IsQueryInstanceSupported(VOID)582 FxWmiInstanceInternal::IsQueryInstanceSupported(
583     VOID
584     )
585 {
586     return m_QueryInstance != NULL ? TRUE : FALSE;
587 }
588 
589 _Must_inspect_result_
590 __drv_sameIRQL
__drv_maxIRQL(PASSIVE_LEVEL)591 __drv_maxIRQL(PASSIVE_LEVEL)
592 NTSTATUS
593 FxWmiInstanceInternal::QueryInstance(
594     __inout ULONG OutBufferSize,
595     __out_bcount(OutBufferSize) PVOID OutBuffer,
596     __out PULONG BufferUsed
597     )
598 {
599     return m_QueryInstance(GetDevice(),
600                            this,
601                            OutBufferSize,
602                            OutBuffer,
603                            BufferUsed);
604 }
605 
606 BOOLEAN
IsSetInstanceSupported(VOID)607 FxWmiInstanceInternal::IsSetInstanceSupported(
608     VOID
609     )
610 {
611     return m_SetInstance != NULL ? TRUE : FALSE;
612 }
613 
614 _Must_inspect_result_
615 __drv_sameIRQL
__drv_maxIRQL(PASSIVE_LEVEL)616 __drv_maxIRQL(PASSIVE_LEVEL)
617 NTSTATUS
618 FxWmiInstanceInternal::SetInstance(
619     __in ULONG InBufferSize,
620     __in_bcount(InBufferSize) PVOID InBuffer
621     )
622 {
623     return m_SetInstance(GetDevice(),
624                          this,
625                          InBufferSize,
626                          InBuffer);
627 }
628 
629 BOOLEAN
IsSetItemSupported(VOID)630 FxWmiInstanceInternal::IsSetItemSupported(
631     VOID
632     )
633 {
634     return m_SetItem != NULL ? TRUE : FALSE;
635 }
636 
637 _Must_inspect_result_
638 __drv_sameIRQL
__drv_maxIRQL(PASSIVE_LEVEL)639 __drv_maxIRQL(PASSIVE_LEVEL)
640 NTSTATUS
641 FxWmiInstanceInternal::SetItem(
642     __in ULONG DataItemId,
643     __in ULONG InBufferSize,
644     __in_bcount(InBufferSize) PVOID InBuffer
645     )
646 {
647     return m_SetItem(GetDevice(),
648                      this,
649                      DataItemId,
650                      InBufferSize,
651                      InBuffer);
652 }
653 
654 BOOLEAN
IsExecuteMethodSupported(VOID)655 FxWmiInstanceInternal::IsExecuteMethodSupported(
656     VOID
657     )
658 
659 {
660     return m_ExecuteMethod != NULL ? TRUE : FALSE;
661 }
662 
663 _Must_inspect_result_
664 __drv_sameIRQL
__drv_maxIRQL(PASSIVE_LEVEL)665 __drv_maxIRQL(PASSIVE_LEVEL)
666 NTSTATUS
667 FxWmiInstanceInternal::ExecuteMethod(
668     __in ULONG MethodId,
669     __in ULONG InBufferSize,
670     __inout ULONG OutBufferSize,
671     __drv_when(InBufferSize >= OutBufferSize, __inout_bcount(InBufferSize))
672     __drv_when(InBufferSize < OutBufferSize, __inout_bcount(OutBufferSize))
673         PVOID Buffer,
674     __out PULONG BufferUsed
675     )
676 {
677     return m_ExecuteMethod(GetDevice(),
678                            this,
679                            MethodId,
680                            InBufferSize,
681                            OutBufferSize,
682                            Buffer,
683                            BufferUsed);
684 }
685