Sync with trunk revision 64099.
[reactos.git] / drivers / storage / classpnp / classwmi.c
1 /*++
2
3 Copyright (C) Microsoft Corporation, 1991 - 1999
4
5 Module Name:
6
7 classwmi.c
8
9 Abstract:
10
11 SCSI class driver routines
12
13 Environment:
14
15 kernel mode only
16
17 Notes:
18
19
20 Revision History:
21
22 --*/
23
24 #include "classp.h"
25
26 #include <wmistr.h>
27
28 NTSTATUS
29 NTAPI
30 ClassSystemControl(
31 IN PDEVICE_OBJECT DeviceObject,
32 IN PIRP Irp
33 );
34
35 BOOLEAN
36 ClassFindGuid(
37 PGUIDREGINFO GuidList,
38 ULONG GuidCount,
39 LPGUID Guid,
40 PULONG GuidIndex
41 );
42
43 //
44 // This is the name for the MOF resource that must be part of all drivers that
45 // register via this interface.
46 #define MOFRESOURCENAME L"MofResourceName"
47
48 //
49 // What can be paged ???
50 #ifdef ALLOC_PRAGMA
51 #pragma alloc_text(PAGE, ClassSystemControl)
52 #pragma alloc_text(PAGE, ClassFindGuid)
53 #endif
54
55 \f
56 /*++////////////////////////////////////////////////////////////////////////////
57
58 ClassFindGuid()
59
60 Routine Description:
61
62 This routine will search the list of guids registered and return
63 the index for the one that was registered.
64
65 Arguments:
66
67 GuidList is the list of guids to search
68
69 GuidCount is the count of guids in the list
70
71 Guid is the guid being searched for
72
73 *GuidIndex returns the index to the guid
74
75 Return Value:
76
77 TRUE if guid is found else FALSE
78
79 --*/
80 BOOLEAN
81 ClassFindGuid(
82 PGUIDREGINFO GuidList,
83 ULONG GuidCount,
84 LPGUID Guid,
85 PULONG GuidIndex
86 )
87 {
88 ULONG i;
89
90 PAGED_CODE();
91
92 for (i = 0; i < GuidCount; i++)
93 {
94 if (IsEqualGUID(Guid, &GuidList[i].Guid))
95 {
96 *GuidIndex = i;
97 return(TRUE);
98 }
99 }
100
101 return(FALSE);
102 } // end ClassFindGuid()
103 \f
104 /*++////////////////////////////////////////////////////////////////////////////
105
106 ClassSystemControl()
107
108 Routine Description:
109
110 Dispatch routine for IRP_MJ_SYSTEM_CONTROL. This routine will process
111 all wmi requests received, forwarding them if they are not for this
112 driver or determining if the guid is valid and if so passing it to
113 the driver specific function for handing wmi requests.
114
115 Arguments:
116
117 DeviceObject - Supplies a pointer to the device object for this request.
118
119 Irp - Supplies the Irp making the request.
120
121 Return Value:
122
123 status
124
125 --*/
126 NTSTATUS
127 NTAPI
128 ClassSystemControl(
129 IN PDEVICE_OBJECT DeviceObject,
130 IN PIRP Irp
131 )
132 {
133 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
134 PCLASS_DRIVER_EXTENSION driverExtension;
135 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
136 ULONG isRemoved;
137 ULONG bufferSize;
138 PUCHAR buffer;
139 NTSTATUS status;
140 UCHAR minorFunction;
141 ULONG guidIndex;
142 PCLASS_WMI_INFO classWmiInfo;
143
144 PAGED_CODE();
145
146 //
147 // Make sure device has not been removed
148 isRemoved = ClassAcquireRemoveLock(DeviceObject, Irp);
149 if(isRemoved)
150 {
151 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
152 ClassReleaseRemoveLock(DeviceObject, Irp);
153 ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
154 return STATUS_DEVICE_DOES_NOT_EXIST;
155 }
156
157 //
158 // If the irp is not a WMI irp or it is not targetted at this device
159 // or this device has not regstered with WMI then just forward it on.
160 minorFunction = irpStack->MinorFunction;
161 if ((minorFunction > IRP_MN_EXECUTE_METHOD) ||
162 (irpStack->Parameters.WMI.ProviderId != (ULONG_PTR)DeviceObject) ||
163 ((minorFunction != IRP_MN_REGINFO) &&
164 (commonExtension->GuidRegInfo == NULL)))
165 {
166 //
167 // CONSIDER: Do I need to hang onto lock until IoCallDriver returns ?
168 IoSkipCurrentIrpStackLocation(Irp);
169 ClassReleaseRemoveLock(DeviceObject, Irp);
170 return(IoCallDriver(commonExtension->LowerDeviceObject, Irp));
171 }
172
173 buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
174 bufferSize = irpStack->Parameters.WMI.BufferSize;
175
176 if (minorFunction != IRP_MN_REGINFO)
177 {
178 //
179 // For all requests other than query registration info we are passed
180 // a guid. Determine if the guid is one that is supported by the
181 // device.
182 if (ClassFindGuid(commonExtension->GuidRegInfo,
183 commonExtension->GuidCount,
184 (LPGUID)irpStack->Parameters.WMI.DataPath,
185 &guidIndex))
186 {
187 status = STATUS_SUCCESS;
188 } else {
189 status = STATUS_WMI_GUID_NOT_FOUND;
190 }
191
192 if (NT_SUCCESS(status) &&
193 ((minorFunction == IRP_MN_QUERY_SINGLE_INSTANCE) ||
194 (minorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE) ||
195 (minorFunction == IRP_MN_CHANGE_SINGLE_ITEM) ||
196 (minorFunction == IRP_MN_EXECUTE_METHOD)))
197 {
198 if ( (((PWNODE_HEADER)buffer)->Flags) &
199 WNODE_FLAG_STATIC_INSTANCE_NAMES)
200 {
201 if ( ((PWNODE_SINGLE_INSTANCE)buffer)->InstanceIndex != 0 )
202 {
203 status = STATUS_WMI_INSTANCE_NOT_FOUND;
204 }
205 } else {
206 status = STATUS_WMI_INSTANCE_NOT_FOUND;
207 }
208 }
209
210 if (! NT_SUCCESS(status))
211 {
212 Irp->IoStatus.Status = status;
213 ClassReleaseRemoveLock(DeviceObject, Irp);
214 ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
215 return(status);
216 }
217 }
218
219 driverExtension = commonExtension->DriverExtension;
220
221 classWmiInfo = commonExtension->IsFdo ?
222 &driverExtension->InitData.FdoData.ClassWmiInfo :
223 &driverExtension->InitData.PdoData.ClassWmiInfo;
224 switch(minorFunction)
225 {
226 case IRP_MN_REGINFO:
227 {
228 ULONG guidCount;
229 PGUIDREGINFO guidList;
230 PWMIREGINFOW wmiRegInfo;
231 PWMIREGGUIDW wmiRegGuid;
232 //PDEVICE_OBJECT pdo;
233 PUNICODE_STRING regPath;
234 PWCHAR stringPtr;
235 ULONG retSize;
236 ULONG registryPathOffset;
237 ULONG mofResourceOffset;
238 ULONG bufferNeeded;
239 ULONG i;
240 ULONG_PTR nameInfo;
241 ULONG nameSize, nameOffset, nameFlags;
242 UNICODE_STRING name, mofName;
243 PCLASS_QUERY_WMI_REGINFO_EX ClassQueryWmiRegInfoEx;
244
245 name.Buffer = NULL;
246 name.Length = 0;
247 name.MaximumLength = 0;
248 nameFlags = 0;
249
250 ClassQueryWmiRegInfoEx = commonExtension->IsFdo ?
251 driverExtension->ClassFdoQueryWmiRegInfoEx :
252 driverExtension->ClassPdoQueryWmiRegInfoEx;
253
254 if (ClassQueryWmiRegInfoEx == NULL)
255 {
256 status = classWmiInfo->ClassQueryWmiRegInfo(
257 DeviceObject,
258 &nameFlags,
259 &name);
260
261 RtlInitUnicodeString(&mofName, MOFRESOURCENAME);
262 } else {
263 RtlInitUnicodeString(&mofName, L"");
264 status = (*ClassQueryWmiRegInfoEx)(
265 DeviceObject,
266 &nameFlags,
267 &name,
268 &mofName);
269 }
270
271 if (NT_SUCCESS(status) &&
272 (! (nameFlags & WMIREG_FLAG_INSTANCE_PDO) &&
273 (name.Buffer == NULL)))
274 {
275 //
276 // if PDO flag not specified then an instance name must be
277 status = STATUS_INVALID_DEVICE_REQUEST;
278 }
279
280 if (NT_SUCCESS(status))
281 {
282 guidList = classWmiInfo->GuidRegInfo;
283 guidCount = classWmiInfo->GuidCount;
284
285 nameOffset = sizeof(WMIREGINFO) +
286 guidCount * sizeof(WMIREGGUIDW);
287
288 if (nameFlags & WMIREG_FLAG_INSTANCE_PDO)
289 {
290 nameSize = 0;
291 nameInfo = commonExtension->IsFdo ?
292 (ULONG_PTR)((PFUNCTIONAL_DEVICE_EXTENSION)commonExtension)->LowerPdo :
293 (ULONG_PTR)DeviceObject;
294 } else {
295 nameFlags |= WMIREG_FLAG_INSTANCE_LIST;
296 nameSize = name.Length + sizeof(USHORT);
297 nameInfo = nameOffset;
298 }
299
300 mofResourceOffset = nameOffset + nameSize;
301
302 registryPathOffset = mofResourceOffset +
303 mofName.Length + sizeof(USHORT);
304
305 regPath = &driverExtension->RegistryPath;
306 bufferNeeded = registryPathOffset +
307 regPath->Length + sizeof(USHORT);
308
309 if (bufferNeeded <= bufferSize)
310 {
311 retSize = bufferNeeded;
312
313 commonExtension->GuidCount = guidCount;
314 commonExtension->GuidRegInfo = guidList;
315
316 wmiRegInfo = (PWMIREGINFO)buffer;
317 wmiRegInfo->BufferSize = bufferNeeded;
318 wmiRegInfo->NextWmiRegInfo = 0;
319 wmiRegInfo->MofResourceName = mofResourceOffset;
320 wmiRegInfo->RegistryPath = registryPathOffset;
321 wmiRegInfo->GuidCount = guidCount;
322
323 for (i = 0; i < guidCount; i++)
324 {
325 wmiRegGuid = &wmiRegInfo->WmiRegGuid[i];
326 wmiRegGuid->Guid = guidList[i].Guid;
327 wmiRegGuid->Flags = guidList[i].Flags | nameFlags;
328 wmiRegGuid->InstanceInfo = nameInfo;
329 wmiRegGuid->InstanceCount = 1;
330 }
331
332 if ( nameFlags & WMIREG_FLAG_INSTANCE_LIST)
333 {
334 stringPtr = (PWCHAR)((PUCHAR)buffer + nameOffset);
335 *stringPtr++ = name.Length;
336 RtlCopyMemory(stringPtr,
337 name.Buffer,
338 name.Length);
339 }
340
341 stringPtr = (PWCHAR)((PUCHAR)buffer + mofResourceOffset);
342 *stringPtr++ = mofName.Length;
343 RtlCopyMemory(stringPtr,
344 mofName.Buffer,
345 mofName.Length);
346
347 stringPtr = (PWCHAR)((PUCHAR)buffer + registryPathOffset);
348 *stringPtr++ = regPath->Length;
349 RtlCopyMemory(stringPtr,
350 regPath->Buffer,
351 regPath->Length);
352 } else {
353 *((PULONG)buffer) = bufferNeeded;
354 retSize = sizeof(ULONG);
355 }
356 } else {
357 retSize = 0;
358 }
359
360 if (name.Buffer != NULL)
361 {
362 ExFreePool(name.Buffer);
363 }
364
365 Irp->IoStatus.Status = status;
366 Irp->IoStatus.Information = retSize;
367 ClassReleaseRemoveLock(DeviceObject, Irp);
368 ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
369 return(status);
370 }
371
372 case IRP_MN_QUERY_ALL_DATA:
373 {
374 PWNODE_ALL_DATA wnode;
375 ULONG bufferAvail;
376
377 wnode = (PWNODE_ALL_DATA)buffer;
378
379 if (bufferSize < sizeof(WNODE_ALL_DATA))
380 {
381 bufferAvail = 0;
382 } else {
383 bufferAvail = bufferSize - sizeof(WNODE_ALL_DATA);
384 }
385
386 wnode->DataBlockOffset = sizeof(WNODE_ALL_DATA);
387
388 status = classWmiInfo->ClassQueryWmiDataBlock(
389 DeviceObject,
390 Irp,
391 guidIndex,
392 bufferAvail,
393 buffer + sizeof(WNODE_ALL_DATA));
394
395 break;
396 }
397
398 case IRP_MN_QUERY_SINGLE_INSTANCE:
399 {
400 PWNODE_SINGLE_INSTANCE wnode;
401 ULONG dataBlockOffset;
402
403 wnode = (PWNODE_SINGLE_INSTANCE)buffer;
404
405 dataBlockOffset = wnode->DataBlockOffset;
406
407 status = classWmiInfo->ClassQueryWmiDataBlock(
408 DeviceObject,
409 Irp,
410 guidIndex,
411 bufferSize - dataBlockOffset,
412 (PUCHAR)wnode + dataBlockOffset);
413
414 break;
415 }
416
417 case IRP_MN_CHANGE_SINGLE_INSTANCE:
418 {
419 PWNODE_SINGLE_INSTANCE wnode;
420
421 wnode = (PWNODE_SINGLE_INSTANCE)buffer;
422
423 status = classWmiInfo->ClassSetWmiDataBlock(
424 DeviceObject,
425 Irp,
426 guidIndex,
427 wnode->SizeDataBlock,
428 (PUCHAR)wnode + wnode->DataBlockOffset);
429
430 break;
431 }
432
433 case IRP_MN_CHANGE_SINGLE_ITEM:
434 {
435 PWNODE_SINGLE_ITEM wnode;
436
437 wnode = (PWNODE_SINGLE_ITEM)buffer;
438
439 status = classWmiInfo->ClassSetWmiDataItem(
440 DeviceObject,
441 Irp,
442 guidIndex,
443 wnode->ItemId,
444 wnode->SizeDataItem,
445 (PUCHAR)wnode + wnode->DataBlockOffset);
446
447 break;
448 }
449
450 case IRP_MN_EXECUTE_METHOD:
451 {
452 PWNODE_METHOD_ITEM wnode;
453
454 wnode = (PWNODE_METHOD_ITEM)buffer;
455
456 status = classWmiInfo->ClassExecuteWmiMethod(
457 DeviceObject,
458 Irp,
459 guidIndex,
460 wnode->MethodId,
461 wnode->SizeDataBlock,
462 bufferSize - wnode->DataBlockOffset,
463 buffer + wnode->DataBlockOffset);
464
465
466 break;
467 }
468
469 case IRP_MN_ENABLE_EVENTS:
470 {
471 status = classWmiInfo->ClassWmiFunctionControl(
472 DeviceObject,
473 Irp,
474 guidIndex,
475 EventGeneration,
476 TRUE);
477 break;
478 }
479
480 case IRP_MN_DISABLE_EVENTS:
481 {
482 status = classWmiInfo->ClassWmiFunctionControl(
483 DeviceObject,
484 Irp,
485 guidIndex,
486 EventGeneration,
487 FALSE);
488 break;
489 }
490
491 case IRP_MN_ENABLE_COLLECTION:
492 {
493 status = classWmiInfo->ClassWmiFunctionControl(
494 DeviceObject,
495 Irp,
496 guidIndex,
497 DataBlockCollection,
498 TRUE);
499 break;
500 }
501
502 case IRP_MN_DISABLE_COLLECTION:
503 {
504 status = classWmiInfo->ClassWmiFunctionControl(
505 DeviceObject,
506 Irp,
507 guidIndex,
508 DataBlockCollection,
509 FALSE);
510 break;
511 }
512
513 default:
514 {
515 status = STATUS_INVALID_DEVICE_REQUEST;
516 break;
517 }
518
519 }
520
521 return(status);
522 } // end ClassSystemControl()
523 \f
524 /*++////////////////////////////////////////////////////////////////////////////
525
526 ClassWmiCompleteRequest()
527
528 Routine Description:
529
530
531 This routine will do the work of completing a WMI irp. Depending upon the
532 the WMI request this routine will fixup the returned WNODE appropriately.
533
534 NOTE: This routine assumes that the ClassRemoveLock is held and it will
535 release it.
536
537 Arguments:
538
539 DeviceObject - Supplies a pointer to the device object for this request.
540
541 Irp - Supplies the Irp making the request.
542
543 Status - Status to complete the irp with. STATUS_BUFFER_TOO_SMALL is used
544 to indicate that more buffer is required for the data requested.
545
546 BufferUsed - number of bytes of actual data to return (not including WMI
547 specific structures)
548
549 PriorityBoost - priority boost to pass to ClassCompleteRequest
550
551 Return Value:
552
553 status
554
555 --*/
556 SCSIPORTAPI
557 NTSTATUS
558 NTAPI
559 ClassWmiCompleteRequest(
560 IN PDEVICE_OBJECT DeviceObject,
561 IN PIRP Irp,
562 IN NTSTATUS Status,
563 IN ULONG BufferUsed,
564 IN CCHAR PriorityBoost
565 )
566 {
567 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
568 //UCHAR MinorFunction;
569 PUCHAR buffer;
570 ULONG retSize;
571 UCHAR minorFunction;
572
573 minorFunction = irpStack->MinorFunction;
574 buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
575
576 switch(minorFunction)
577 {
578 case IRP_MN_QUERY_ALL_DATA:
579 {
580 PWNODE_ALL_DATA wnode;
581 PWNODE_TOO_SMALL wnodeTooSmall;
582 ULONG bufferNeeded;
583
584 wnode = (PWNODE_ALL_DATA)buffer;
585
586 bufferNeeded = sizeof(WNODE_ALL_DATA) + BufferUsed;
587
588 if (NT_SUCCESS(Status))
589 {
590 retSize = bufferNeeded;
591 wnode->WnodeHeader.BufferSize = bufferNeeded;
592 KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
593 wnode->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE;
594 wnode->FixedInstanceSize = BufferUsed;
595 wnode->InstanceCount = 1;
596
597 } else if (Status == STATUS_BUFFER_TOO_SMALL) {
598 wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
599
600 wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
601 wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
602 wnodeTooSmall->SizeNeeded = sizeof(WNODE_ALL_DATA) + BufferUsed;
603 retSize = sizeof(WNODE_TOO_SMALL);
604 Status = STATUS_SUCCESS;
605 } else {
606 retSize = 0;
607 }
608 break;
609 }
610
611 case IRP_MN_QUERY_SINGLE_INSTANCE:
612 {
613 PWNODE_SINGLE_INSTANCE wnode;
614 PWNODE_TOO_SMALL wnodeTooSmall;
615 ULONG bufferNeeded;
616
617 wnode = (PWNODE_SINGLE_INSTANCE)buffer;
618
619 bufferNeeded = wnode->DataBlockOffset + BufferUsed;
620
621 if (NT_SUCCESS(Status))
622 {
623 retSize = bufferNeeded;
624 wnode->WnodeHeader.BufferSize = bufferNeeded;
625 KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
626 wnode->SizeDataBlock = BufferUsed;
627
628 } else if (Status == STATUS_BUFFER_TOO_SMALL) {
629 wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
630
631 wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
632 wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
633 wnodeTooSmall->SizeNeeded = bufferNeeded;
634 retSize = sizeof(WNODE_TOO_SMALL);
635 Status = STATUS_SUCCESS;
636 } else {
637 retSize = 0;
638 }
639 break;
640 }
641
642 case IRP_MN_EXECUTE_METHOD:
643 {
644 PWNODE_METHOD_ITEM wnode;
645 PWNODE_TOO_SMALL wnodeTooSmall;
646 ULONG bufferNeeded;
647
648 wnode = (PWNODE_METHOD_ITEM)buffer;
649
650 bufferNeeded = wnode->DataBlockOffset + BufferUsed;
651
652 if (NT_SUCCESS(Status))
653 {
654 retSize = bufferNeeded;
655 wnode->WnodeHeader.BufferSize = bufferNeeded;
656 KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
657 wnode->SizeDataBlock = BufferUsed;
658
659 } else if (Status == STATUS_BUFFER_TOO_SMALL) {
660 wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
661
662 wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
663 wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
664 wnodeTooSmall->SizeNeeded = bufferNeeded;
665 retSize = sizeof(WNODE_TOO_SMALL);
666 Status = STATUS_SUCCESS;
667 } else {
668 retSize = 0;
669 }
670 break;
671 }
672
673 default:
674 {
675 //
676 // All other requests don't return any data
677 retSize = 0;
678 break;
679 }
680
681 }
682
683 Irp->IoStatus.Status = Status;
684 Irp->IoStatus.Information = retSize;
685 ClassReleaseRemoveLock(DeviceObject, Irp);
686 ClassCompleteRequest(DeviceObject, Irp, PriorityBoost);
687 return(Status);
688 } // end ClassWmiCompleteRequest()
689 \f
690 /*++////////////////////////////////////////////////////////////////////////////
691
692 ClassWmiFireEvent()
693
694 Routine Description:
695
696 This routine will fire a WMI event using the data buffer passed. This
697 routine may be called at or below DPC level
698
699 Arguments:
700
701 DeviceObject - Supplies a pointer to the device object for this event
702
703 Guid is pointer to the GUID that represents the event
704
705 InstanceIndex is the index of the instance of the event
706
707 EventDataSize is the number of bytes of data that is being fired with
708 with the event
709
710 EventData is the data that is fired with the events. This may be NULL
711 if there is no data associated with the event
712
713
714 Return Value:
715
716 status
717
718 --*/
719 NTSTATUS
720 NTAPI
721 ClassWmiFireEvent(
722 IN PDEVICE_OBJECT DeviceObject,
723 IN LPGUID Guid,
724 IN ULONG InstanceIndex,
725 IN ULONG EventDataSize,
726 IN PVOID EventData
727 )
728 {
729
730 ULONG sizeNeeded;
731 PWNODE_SINGLE_INSTANCE event;
732 NTSTATUS status;
733
734 if (EventData == NULL)
735 {
736 EventDataSize = 0;
737 }
738
739 sizeNeeded = sizeof(WNODE_SINGLE_INSTANCE) + EventDataSize;
740
741 event = ExAllocatePoolWithTag(NonPagedPool, sizeNeeded, CLASS_TAG_WMI);
742 if (event != NULL)
743 {
744 event->WnodeHeader.Guid = *Guid;
745 event->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(DeviceObject);
746 event->WnodeHeader.BufferSize = sizeNeeded;
747 event->WnodeHeader.Flags = WNODE_FLAG_SINGLE_INSTANCE |
748 WNODE_FLAG_EVENT_ITEM |
749 WNODE_FLAG_STATIC_INSTANCE_NAMES;
750 KeQuerySystemTime(&event->WnodeHeader.TimeStamp);
751
752 event->InstanceIndex = InstanceIndex;
753 event->SizeDataBlock = EventDataSize;
754 event->DataBlockOffset = sizeof(WNODE_SINGLE_INSTANCE);
755 if (EventData != NULL)
756 {
757 RtlCopyMemory( &event->VariableData, EventData, EventDataSize);
758 }
759
760 status = IoWMIWriteEvent(event);
761 if (! NT_SUCCESS(status))
762 {
763 ExFreePool(event);
764 }
765 } else {
766 status = STATUS_INSUFFICIENT_RESOURCES;
767 }
768
769 return(status);
770 } // end ClassWmiFireEvent()
771