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