3 Copyright (C) Microsoft Corporation, 1991 - 1999
11 SCSI class driver routines
31 IN PDEVICE_OBJECT DeviceObject
,
37 PGUIDREGINFO GuidList
,
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"
49 // What can be paged ???
51 #pragma alloc_text(PAGE, ClassSystemControl)
52 #pragma alloc_text(PAGE, ClassFindGuid)
56 /*++////////////////////////////////////////////////////////////////////////////
62 This routine will search the list of guids registered and return
63 the index for the one that was registered.
67 GuidList is the list of guids to search
69 GuidCount is the count of guids in the list
71 Guid is the guid being searched for
73 *GuidIndex returns the index to the guid
77 TRUE if guid is found else FALSE
82 PGUIDREGINFO GuidList
,
92 for (i
= 0; i
< GuidCount
; i
++)
94 if (IsEqualGUID(Guid
, &GuidList
[i
].Guid
))
102 } // end ClassFindGuid()
104 /*++////////////////////////////////////////////////////////////////////////////
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.
117 DeviceObject - Supplies a pointer to the device object for this request.
119 Irp - Supplies the Irp making the request.
129 IN PDEVICE_OBJECT DeviceObject
,
133 PCOMMON_DEVICE_EXTENSION commonExtension
= DeviceObject
->DeviceExtension
;
134 PCLASS_DRIVER_EXTENSION driverExtension
;
135 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
142 PCLASS_WMI_INFO classWmiInfo
;
147 // Make sure device has not been removed
148 isRemoved
= ClassAcquireRemoveLock(DeviceObject
, Irp
);
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
;
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
)))
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
));
173 buffer
= (PUCHAR
)irpStack
->Parameters
.WMI
.Buffer
;
174 bufferSize
= irpStack
->Parameters
.WMI
.BufferSize
;
176 if (minorFunction
!= IRP_MN_REGINFO
)
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
182 if (ClassFindGuid(commonExtension
->GuidRegInfo
,
183 commonExtension
->GuidCount
,
184 (LPGUID
)irpStack
->Parameters
.WMI
.DataPath
,
187 status
= STATUS_SUCCESS
;
189 status
= STATUS_WMI_GUID_NOT_FOUND
;
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
)))
198 if ( (((PWNODE_HEADER
)buffer
)->Flags
) &
199 WNODE_FLAG_STATIC_INSTANCE_NAMES
)
201 if ( ((PWNODE_SINGLE_INSTANCE
)buffer
)->InstanceIndex
!= 0 )
203 status
= STATUS_WMI_INSTANCE_NOT_FOUND
;
206 status
= STATUS_WMI_INSTANCE_NOT_FOUND
;
210 if (! NT_SUCCESS(status
))
212 Irp
->IoStatus
.Status
= status
;
213 ClassReleaseRemoveLock(DeviceObject
, Irp
);
214 ClassCompleteRequest(DeviceObject
, Irp
, IO_NO_INCREMENT
);
219 driverExtension
= commonExtension
->DriverExtension
;
221 classWmiInfo
= commonExtension
->IsFdo
?
222 &driverExtension
->InitData
.FdoData
.ClassWmiInfo
:
223 &driverExtension
->InitData
.PdoData
.ClassWmiInfo
;
224 switch(minorFunction
)
229 PGUIDREGINFO guidList
;
230 PWMIREGINFOW wmiRegInfo
;
231 PWMIREGGUIDW wmiRegGuid
;
232 //PDEVICE_OBJECT pdo;
233 PUNICODE_STRING regPath
;
236 ULONG registryPathOffset
;
237 ULONG mofResourceOffset
;
241 ULONG nameSize
, nameOffset
, nameFlags
;
242 UNICODE_STRING name
, mofName
;
243 PCLASS_QUERY_WMI_REGINFO_EX ClassQueryWmiRegInfoEx
;
247 name
.MaximumLength
= 0;
250 ClassQueryWmiRegInfoEx
= commonExtension
->IsFdo
?
251 driverExtension
->ClassFdoQueryWmiRegInfoEx
:
252 driverExtension
->ClassPdoQueryWmiRegInfoEx
;
254 if (ClassQueryWmiRegInfoEx
== NULL
)
256 status
= classWmiInfo
->ClassQueryWmiRegInfo(
261 RtlInitUnicodeString(&mofName
, MOFRESOURCENAME
);
263 RtlInitUnicodeString(&mofName
, L
"");
264 status
= (*ClassQueryWmiRegInfoEx
)(
271 if (NT_SUCCESS(status
) &&
272 (! (nameFlags
& WMIREG_FLAG_INSTANCE_PDO
) &&
273 (name
.Buffer
== NULL
)))
276 // if PDO flag not specified then an instance name must be
277 status
= STATUS_INVALID_DEVICE_REQUEST
;
280 if (NT_SUCCESS(status
))
282 guidList
= classWmiInfo
->GuidRegInfo
;
283 guidCount
= classWmiInfo
->GuidCount
;
285 nameOffset
= sizeof(WMIREGINFO
) +
286 guidCount
* sizeof(WMIREGGUIDW
);
288 if (nameFlags
& WMIREG_FLAG_INSTANCE_PDO
)
291 nameInfo
= commonExtension
->IsFdo
?
292 (ULONG_PTR
)((PFUNCTIONAL_DEVICE_EXTENSION
)commonExtension
)->LowerPdo
:
293 (ULONG_PTR
)DeviceObject
;
295 nameFlags
|= WMIREG_FLAG_INSTANCE_LIST
;
296 nameSize
= name
.Length
+ sizeof(USHORT
);
297 nameInfo
= nameOffset
;
300 mofResourceOffset
= nameOffset
+ nameSize
;
302 registryPathOffset
= mofResourceOffset
+
303 mofName
.Length
+ sizeof(USHORT
);
305 regPath
= &driverExtension
->RegistryPath
;
306 bufferNeeded
= registryPathOffset
+
307 regPath
->Length
+ sizeof(USHORT
);
309 if (bufferNeeded
<= bufferSize
)
311 retSize
= bufferNeeded
;
313 commonExtension
->GuidCount
= guidCount
;
314 commonExtension
->GuidRegInfo
= guidList
;
316 wmiRegInfo
= (PWMIREGINFO
)buffer
;
317 wmiRegInfo
->BufferSize
= bufferNeeded
;
318 wmiRegInfo
->NextWmiRegInfo
= 0;
319 wmiRegInfo
->MofResourceName
= mofResourceOffset
;
320 wmiRegInfo
->RegistryPath
= registryPathOffset
;
321 wmiRegInfo
->GuidCount
= guidCount
;
323 for (i
= 0; i
< guidCount
; i
++)
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;
332 if ( nameFlags
& WMIREG_FLAG_INSTANCE_LIST
)
334 stringPtr
= (PWCHAR
)((PUCHAR
)buffer
+ nameOffset
);
335 *stringPtr
++ = name
.Length
;
336 RtlCopyMemory(stringPtr
,
341 stringPtr
= (PWCHAR
)((PUCHAR
)buffer
+ mofResourceOffset
);
342 *stringPtr
++ = mofName
.Length
;
343 RtlCopyMemory(stringPtr
,
347 stringPtr
= (PWCHAR
)((PUCHAR
)buffer
+ registryPathOffset
);
348 *stringPtr
++ = regPath
->Length
;
349 RtlCopyMemory(stringPtr
,
353 *((PULONG
)buffer
) = bufferNeeded
;
354 retSize
= sizeof(ULONG
);
360 if (name
.Buffer
!= NULL
)
362 ExFreePool(name
.Buffer
);
365 Irp
->IoStatus
.Status
= status
;
366 Irp
->IoStatus
.Information
= retSize
;
367 ClassReleaseRemoveLock(DeviceObject
, Irp
);
368 ClassCompleteRequest(DeviceObject
, Irp
, IO_NO_INCREMENT
);
372 case IRP_MN_QUERY_ALL_DATA
:
374 PWNODE_ALL_DATA wnode
;
377 wnode
= (PWNODE_ALL_DATA
)buffer
;
379 if (bufferSize
< sizeof(WNODE_ALL_DATA
))
383 bufferAvail
= bufferSize
- sizeof(WNODE_ALL_DATA
);
386 wnode
->DataBlockOffset
= sizeof(WNODE_ALL_DATA
);
388 status
= classWmiInfo
->ClassQueryWmiDataBlock(
393 buffer
+ sizeof(WNODE_ALL_DATA
));
398 case IRP_MN_QUERY_SINGLE_INSTANCE
:
400 PWNODE_SINGLE_INSTANCE wnode
;
401 ULONG dataBlockOffset
;
403 wnode
= (PWNODE_SINGLE_INSTANCE
)buffer
;
405 dataBlockOffset
= wnode
->DataBlockOffset
;
407 status
= classWmiInfo
->ClassQueryWmiDataBlock(
411 bufferSize
- dataBlockOffset
,
412 (PUCHAR
)wnode
+ dataBlockOffset
);
417 case IRP_MN_CHANGE_SINGLE_INSTANCE
:
419 PWNODE_SINGLE_INSTANCE wnode
;
421 wnode
= (PWNODE_SINGLE_INSTANCE
)buffer
;
423 status
= classWmiInfo
->ClassSetWmiDataBlock(
427 wnode
->SizeDataBlock
,
428 (PUCHAR
)wnode
+ wnode
->DataBlockOffset
);
433 case IRP_MN_CHANGE_SINGLE_ITEM
:
435 PWNODE_SINGLE_ITEM wnode
;
437 wnode
= (PWNODE_SINGLE_ITEM
)buffer
;
439 status
= classWmiInfo
->ClassSetWmiDataItem(
445 (PUCHAR
)wnode
+ wnode
->DataBlockOffset
);
450 case IRP_MN_EXECUTE_METHOD
:
452 PWNODE_METHOD_ITEM wnode
;
454 wnode
= (PWNODE_METHOD_ITEM
)buffer
;
456 status
= classWmiInfo
->ClassExecuteWmiMethod(
461 wnode
->SizeDataBlock
,
462 bufferSize
- wnode
->DataBlockOffset
,
463 buffer
+ wnode
->DataBlockOffset
);
469 case IRP_MN_ENABLE_EVENTS
:
471 status
= classWmiInfo
->ClassWmiFunctionControl(
480 case IRP_MN_DISABLE_EVENTS
:
482 status
= classWmiInfo
->ClassWmiFunctionControl(
491 case IRP_MN_ENABLE_COLLECTION
:
493 status
= classWmiInfo
->ClassWmiFunctionControl(
502 case IRP_MN_DISABLE_COLLECTION
:
504 status
= classWmiInfo
->ClassWmiFunctionControl(
515 status
= STATUS_INVALID_DEVICE_REQUEST
;
522 } // end ClassSystemControl()
524 /*++////////////////////////////////////////////////////////////////////////////
526 ClassWmiCompleteRequest()
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.
534 NOTE: This routine assumes that the ClassRemoveLock is held and it will
539 DeviceObject - Supplies a pointer to the device object for this request.
541 Irp - Supplies the Irp making the request.
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.
546 BufferUsed - number of bytes of actual data to return (not including WMI
549 PriorityBoost - priority boost to pass to ClassCompleteRequest
559 ClassWmiCompleteRequest(
560 IN PDEVICE_OBJECT DeviceObject
,
564 IN CCHAR PriorityBoost
567 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
568 //UCHAR MinorFunction;
573 minorFunction
= irpStack
->MinorFunction
;
574 buffer
= (PUCHAR
)irpStack
->Parameters
.WMI
.Buffer
;
576 switch(minorFunction
)
578 case IRP_MN_QUERY_ALL_DATA
:
580 PWNODE_ALL_DATA wnode
;
581 PWNODE_TOO_SMALL wnodeTooSmall
;
584 wnode
= (PWNODE_ALL_DATA
)buffer
;
586 bufferNeeded
= sizeof(WNODE_ALL_DATA
) + BufferUsed
;
588 if (NT_SUCCESS(Status
))
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;
597 } else if (Status
== STATUS_BUFFER_TOO_SMALL
) {
598 wnodeTooSmall
= (PWNODE_TOO_SMALL
)wnode
;
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
;
611 case IRP_MN_QUERY_SINGLE_INSTANCE
:
613 PWNODE_SINGLE_INSTANCE wnode
;
614 PWNODE_TOO_SMALL wnodeTooSmall
;
617 wnode
= (PWNODE_SINGLE_INSTANCE
)buffer
;
619 bufferNeeded
= wnode
->DataBlockOffset
+ BufferUsed
;
621 if (NT_SUCCESS(Status
))
623 retSize
= bufferNeeded
;
624 wnode
->WnodeHeader
.BufferSize
= bufferNeeded
;
625 KeQuerySystemTime(&wnode
->WnodeHeader
.TimeStamp
);
626 wnode
->SizeDataBlock
= BufferUsed
;
628 } else if (Status
== STATUS_BUFFER_TOO_SMALL
) {
629 wnodeTooSmall
= (PWNODE_TOO_SMALL
)wnode
;
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
;
642 case IRP_MN_EXECUTE_METHOD
:
644 PWNODE_METHOD_ITEM wnode
;
645 PWNODE_TOO_SMALL wnodeTooSmall
;
648 wnode
= (PWNODE_METHOD_ITEM
)buffer
;
650 bufferNeeded
= wnode
->DataBlockOffset
+ BufferUsed
;
652 if (NT_SUCCESS(Status
))
654 retSize
= bufferNeeded
;
655 wnode
->WnodeHeader
.BufferSize
= bufferNeeded
;
656 KeQuerySystemTime(&wnode
->WnodeHeader
.TimeStamp
);
657 wnode
->SizeDataBlock
= BufferUsed
;
659 } else if (Status
== STATUS_BUFFER_TOO_SMALL
) {
660 wnodeTooSmall
= (PWNODE_TOO_SMALL
)wnode
;
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
;
676 // All other requests don't return any data
683 Irp
->IoStatus
.Status
= Status
;
684 Irp
->IoStatus
.Information
= retSize
;
685 ClassReleaseRemoveLock(DeviceObject
, Irp
);
686 ClassCompleteRequest(DeviceObject
, Irp
, PriorityBoost
);
688 } // end ClassWmiCompleteRequest()
690 /*++////////////////////////////////////////////////////////////////////////////
696 This routine will fire a WMI event using the data buffer passed. This
697 routine may be called at or below DPC level
701 DeviceObject - Supplies a pointer to the device object for this event
703 Guid is pointer to the GUID that represents the event
705 InstanceIndex is the index of the instance of the event
707 EventDataSize is the number of bytes of data that is being fired with
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
722 IN PDEVICE_OBJECT DeviceObject
,
724 IN ULONG InstanceIndex
,
725 IN ULONG EventDataSize
,
731 PWNODE_SINGLE_INSTANCE event
;
734 if (EventData
== NULL
)
739 sizeNeeded
= sizeof(WNODE_SINGLE_INSTANCE
) + EventDataSize
;
741 event
= ExAllocatePoolWithTag(NonPagedPool
, sizeNeeded
, CLASS_TAG_WMI
);
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
);
752 event
->InstanceIndex
= InstanceIndex
;
753 event
->SizeDataBlock
= EventDataSize
;
754 event
->DataBlockOffset
= sizeof(WNODE_SINGLE_INSTANCE
);
755 if (EventData
!= NULL
)
757 RtlCopyMemory( &event
->VariableData
, EventData
, EventDataSize
);
760 status
= IoWMIWriteEvent(event
);
761 if (! NT_SUCCESS(status
))
766 status
= STATUS_INSUFFICIENT_RESOURCES
;
770 } // end ClassWmiFireEvent()