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