3 Copyright (C) Microsoft Corporation, 1991 - 1999
11 SCSI class driver routines
28 IN PDEVICE_OBJECT DeviceObject
,
34 PGUIDREGINFO GuidList
,
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"
46 // What can be paged ???
48 #pragma alloc_text(PAGE, ClassSystemControl)
49 #pragma alloc_text(PAGE, ClassFindGuid)
53 /*++////////////////////////////////////////////////////////////////////////////
59 This routine will search the list of guids registered and return
60 the index for the one that was registered.
64 GuidList is the list of guids to search
66 GuidCount is the count of guids in the list
68 Guid is the guid being searched for
70 *GuidIndex returns the index to the guid
74 TRUE if guid is found else FALSE
79 PGUIDREGINFO GuidList
,
89 for (i
= 0; i
< GuidCount
; i
++)
91 if (IsEqualGUID(Guid
, &GuidList
[i
].Guid
))
99 } // end ClassFindGuid()
101 /*++////////////////////////////////////////////////////////////////////////////
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.
114 DeviceObject - Supplies a pointer to the device object for this request.
116 Irp - Supplies the Irp making the request.
125 IN PDEVICE_OBJECT DeviceObject
,
129 PCOMMON_DEVICE_EXTENSION commonExtension
= DeviceObject
->DeviceExtension
;
130 PCLASS_DRIVER_EXTENSION driverExtension
;
131 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
138 PCLASS_WMI_INFO classWmiInfo
;
143 // Make sure device has not been removed
144 isRemoved
= ClassAcquireRemoveLock(DeviceObject
, Irp
);
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
;
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
)))
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
));
169 buffer
= (PUCHAR
)irpStack
->Parameters
.WMI
.Buffer
;
170 bufferSize
= irpStack
->Parameters
.WMI
.BufferSize
;
172 if (minorFunction
!= IRP_MN_REGINFO
)
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
178 if (ClassFindGuid(commonExtension
->GuidRegInfo
,
179 commonExtension
->GuidCount
,
180 (LPGUID
)irpStack
->Parameters
.WMI
.DataPath
,
183 status
= STATUS_SUCCESS
;
185 status
= STATUS_WMI_GUID_NOT_FOUND
;
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
)))
194 if ( (((PWNODE_HEADER
)buffer
)->Flags
) &
195 WNODE_FLAG_STATIC_INSTANCE_NAMES
)
197 if ( ((PWNODE_SINGLE_INSTANCE
)buffer
)->InstanceIndex
!= 0 )
199 status
= STATUS_WMI_INSTANCE_NOT_FOUND
;
202 status
= STATUS_WMI_INSTANCE_NOT_FOUND
;
206 if (! NT_SUCCESS(status
))
208 Irp
->IoStatus
.Status
= status
;
209 ClassReleaseRemoveLock(DeviceObject
, Irp
);
210 ClassCompleteRequest(DeviceObject
, Irp
, IO_NO_INCREMENT
);
215 driverExtension
= commonExtension
->DriverExtension
;
217 classWmiInfo
= commonExtension
->IsFdo
?
218 &driverExtension
->InitData
.FdoData
.ClassWmiInfo
:
219 &driverExtension
->InitData
.PdoData
.ClassWmiInfo
;
220 switch(minorFunction
)
225 PGUIDREGINFO guidList
;
226 PWMIREGINFOW wmiRegInfo
;
227 PWMIREGGUIDW wmiRegGuid
;
229 PUNICODE_STRING regPath
;
232 ULONG registryPathOffset
;
233 ULONG mofResourceOffset
;
237 ULONG nameSize
, nameOffset
, nameFlags
;
238 UNICODE_STRING name
, mofName
;
239 PCLASS_QUERY_WMI_REGINFO_EX ClassQueryWmiRegInfoEx
;
243 name
.MaximumLength
= 0;
246 ClassQueryWmiRegInfoEx
= commonExtension
->IsFdo
?
247 driverExtension
->ClassFdoQueryWmiRegInfoEx
:
248 driverExtension
->ClassPdoQueryWmiRegInfoEx
;
250 if (ClassQueryWmiRegInfoEx
== NULL
)
252 status
= classWmiInfo
->ClassQueryWmiRegInfo(
257 RtlInitUnicodeString(&mofName
, MOFRESOURCENAME
);
259 RtlInitUnicodeString(&mofName
, L
"");
260 status
= (*ClassQueryWmiRegInfoEx
)(
267 if (NT_SUCCESS(status
) &&
268 (! (nameFlags
& WMIREG_FLAG_INSTANCE_PDO
) &&
269 (name
.Buffer
== NULL
)))
272 // if PDO flag not specified then an instance name must be
273 status
= STATUS_INVALID_DEVICE_REQUEST
;
276 if (NT_SUCCESS(status
))
278 guidList
= classWmiInfo
->GuidRegInfo
;
279 guidCount
= classWmiInfo
->GuidCount
;
281 nameOffset
= sizeof(WMIREGINFO
) +
282 guidCount
* sizeof(WMIREGGUIDW
);
284 if (nameFlags
& WMIREG_FLAG_INSTANCE_PDO
)
287 nameInfo
= commonExtension
->IsFdo
?
288 (ULONG_PTR
)((PFUNCTIONAL_DEVICE_EXTENSION
)commonExtension
)->LowerPdo
:
289 (ULONG_PTR
)DeviceObject
;
291 nameFlags
|= WMIREG_FLAG_INSTANCE_LIST
;
292 nameSize
= name
.Length
+ sizeof(USHORT
);
293 nameInfo
= nameOffset
;
296 mofResourceOffset
= nameOffset
+ nameSize
;
298 registryPathOffset
= mofResourceOffset
+
299 mofName
.Length
+ sizeof(USHORT
);
301 regPath
= &driverExtension
->RegistryPath
;
302 bufferNeeded
= registryPathOffset
+
303 regPath
->Length
+ sizeof(USHORT
);
305 if (bufferNeeded
<= bufferSize
)
307 retSize
= bufferNeeded
;
309 commonExtension
->GuidCount
= guidCount
;
310 commonExtension
->GuidRegInfo
= guidList
;
312 wmiRegInfo
= (PWMIREGINFO
)buffer
;
313 wmiRegInfo
->BufferSize
= bufferNeeded
;
314 wmiRegInfo
->NextWmiRegInfo
= 0;
315 wmiRegInfo
->MofResourceName
= mofResourceOffset
;
316 wmiRegInfo
->RegistryPath
= registryPathOffset
;
317 wmiRegInfo
->GuidCount
= guidCount
;
319 for (i
= 0; i
< guidCount
; i
++)
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;
328 if ( nameFlags
& WMIREG_FLAG_INSTANCE_LIST
)
330 stringPtr
= (PWCHAR
)((PUCHAR
)buffer
+ nameOffset
);
331 *stringPtr
++ = name
.Length
;
332 RtlCopyMemory(stringPtr
,
337 stringPtr
= (PWCHAR
)((PUCHAR
)buffer
+ mofResourceOffset
);
338 *stringPtr
++ = mofName
.Length
;
339 RtlCopyMemory(stringPtr
,
343 stringPtr
= (PWCHAR
)((PUCHAR
)buffer
+ registryPathOffset
);
344 *stringPtr
++ = regPath
->Length
;
345 RtlCopyMemory(stringPtr
,
349 *((PULONG
)buffer
) = bufferNeeded
;
350 retSize
= sizeof(ULONG
);
356 if (name
.Buffer
!= NULL
)
358 ExFreePool(name
.Buffer
);
361 Irp
->IoStatus
.Status
= status
;
362 Irp
->IoStatus
.Information
= retSize
;
363 ClassReleaseRemoveLock(DeviceObject
, Irp
);
364 ClassCompleteRequest(DeviceObject
, Irp
, IO_NO_INCREMENT
);
368 case IRP_MN_QUERY_ALL_DATA
:
370 PWNODE_ALL_DATA wnode
;
373 wnode
= (PWNODE_ALL_DATA
)buffer
;
375 if (bufferSize
< sizeof(WNODE_ALL_DATA
))
379 bufferAvail
= bufferSize
- sizeof(WNODE_ALL_DATA
);
382 wnode
->DataBlockOffset
= sizeof(WNODE_ALL_DATA
);
384 status
= classWmiInfo
->ClassQueryWmiDataBlock(
389 buffer
+ sizeof(WNODE_ALL_DATA
));
394 case IRP_MN_QUERY_SINGLE_INSTANCE
:
396 PWNODE_SINGLE_INSTANCE wnode
;
397 ULONG dataBlockOffset
;
399 wnode
= (PWNODE_SINGLE_INSTANCE
)buffer
;
401 dataBlockOffset
= wnode
->DataBlockOffset
;
403 status
= classWmiInfo
->ClassQueryWmiDataBlock(
407 bufferSize
- dataBlockOffset
,
408 (PUCHAR
)wnode
+ dataBlockOffset
);
413 case IRP_MN_CHANGE_SINGLE_INSTANCE
:
415 PWNODE_SINGLE_INSTANCE wnode
;
417 wnode
= (PWNODE_SINGLE_INSTANCE
)buffer
;
419 status
= classWmiInfo
->ClassSetWmiDataBlock(
423 wnode
->SizeDataBlock
,
424 (PUCHAR
)wnode
+ wnode
->DataBlockOffset
);
429 case IRP_MN_CHANGE_SINGLE_ITEM
:
431 PWNODE_SINGLE_ITEM wnode
;
433 wnode
= (PWNODE_SINGLE_ITEM
)buffer
;
435 status
= classWmiInfo
->ClassSetWmiDataItem(
441 (PUCHAR
)wnode
+ wnode
->DataBlockOffset
);
446 case IRP_MN_EXECUTE_METHOD
:
448 PWNODE_METHOD_ITEM wnode
;
450 wnode
= (PWNODE_METHOD_ITEM
)buffer
;
452 status
= classWmiInfo
->ClassExecuteWmiMethod(
457 wnode
->SizeDataBlock
,
458 bufferSize
- wnode
->DataBlockOffset
,
459 buffer
+ wnode
->DataBlockOffset
);
465 case IRP_MN_ENABLE_EVENTS
:
467 status
= classWmiInfo
->ClassWmiFunctionControl(
476 case IRP_MN_DISABLE_EVENTS
:
478 status
= classWmiInfo
->ClassWmiFunctionControl(
487 case IRP_MN_ENABLE_COLLECTION
:
489 status
= classWmiInfo
->ClassWmiFunctionControl(
498 case IRP_MN_DISABLE_COLLECTION
:
500 status
= classWmiInfo
->ClassWmiFunctionControl(
511 status
= STATUS_INVALID_DEVICE_REQUEST
;
518 } // end ClassSystemControl()
520 /*++////////////////////////////////////////////////////////////////////////////
522 ClassWmiCompleteRequest()
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.
530 NOTE: This routine assumes that the ClassRemoveLock is held and it will
535 DeviceObject - Supplies a pointer to the device object for this request.
537 Irp - Supplies the Irp making the request.
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.
542 BufferUsed - number of bytes of actual data to return (not including WMI
545 PriorityBoost - priority boost to pass to ClassCompleteRequest
554 ClassWmiCompleteRequest(
555 IN PDEVICE_OBJECT DeviceObject
,
559 IN CCHAR PriorityBoost
562 PCOMMON_DEVICE_EXTENSION commonExtension
= DeviceObject
->DeviceExtension
;
563 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
570 minorFunction
= irpStack
->MinorFunction
;
571 buffer
= (PUCHAR
)irpStack
->Parameters
.WMI
.Buffer
;
572 bufferSize
= irpStack
->Parameters
.WMI
.BufferSize
;
574 switch(minorFunction
)
576 case IRP_MN_QUERY_ALL_DATA
:
578 PWNODE_ALL_DATA wnode
;
579 PWNODE_TOO_SMALL wnodeTooSmall
;
582 wnode
= (PWNODE_ALL_DATA
)buffer
;
584 bufferNeeded
= sizeof(WNODE_ALL_DATA
) + BufferUsed
;
586 if (NT_SUCCESS(Status
))
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;
595 } else if (Status
== STATUS_BUFFER_TOO_SMALL
) {
596 wnodeTooSmall
= (PWNODE_TOO_SMALL
)wnode
;
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
;
609 case IRP_MN_QUERY_SINGLE_INSTANCE
:
611 PWNODE_SINGLE_INSTANCE wnode
;
612 PWNODE_TOO_SMALL wnodeTooSmall
;
615 wnode
= (PWNODE_SINGLE_INSTANCE
)buffer
;
617 bufferNeeded
= wnode
->DataBlockOffset
+ BufferUsed
;
619 if (NT_SUCCESS(Status
))
621 retSize
= bufferNeeded
;
622 wnode
->WnodeHeader
.BufferSize
= bufferNeeded
;
623 KeQuerySystemTime(&wnode
->WnodeHeader
.TimeStamp
);
624 wnode
->SizeDataBlock
= BufferUsed
;
626 } else if (Status
== STATUS_BUFFER_TOO_SMALL
) {
627 wnodeTooSmall
= (PWNODE_TOO_SMALL
)wnode
;
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
;
640 case IRP_MN_EXECUTE_METHOD
:
642 PWNODE_METHOD_ITEM wnode
;
643 PWNODE_TOO_SMALL wnodeTooSmall
;
646 wnode
= (PWNODE_METHOD_ITEM
)buffer
;
648 bufferNeeded
= wnode
->DataBlockOffset
+ BufferUsed
;
650 if (NT_SUCCESS(Status
))
652 retSize
= bufferNeeded
;
653 wnode
->WnodeHeader
.BufferSize
= bufferNeeded
;
654 KeQuerySystemTime(&wnode
->WnodeHeader
.TimeStamp
);
655 wnode
->SizeDataBlock
= BufferUsed
;
657 } else if (Status
== STATUS_BUFFER_TOO_SMALL
) {
658 wnodeTooSmall
= (PWNODE_TOO_SMALL
)wnode
;
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
;
674 // All other requests don't return any data
681 Irp
->IoStatus
.Status
= Status
;
682 Irp
->IoStatus
.Information
= retSize
;
683 ClassReleaseRemoveLock(DeviceObject
, Irp
);
684 ClassCompleteRequest(DeviceObject
, Irp
, PriorityBoost
);
686 } // end ClassWmiCompleteRequest()
688 /*++////////////////////////////////////////////////////////////////////////////
694 This routine will fire a WMI event using the data buffer passed. This
695 routine may be called at or below DPC level
699 DeviceObject - Supplies a pointer to the device object for this event
701 Guid is pointer to the GUID that represents the event
703 InstanceIndex is the index of the instance of the event
705 EventDataSize is the number of bytes of data that is being fired with
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
719 IN PDEVICE_OBJECT DeviceObject
,
721 IN ULONG InstanceIndex
,
722 IN ULONG EventDataSize
,
728 PWNODE_SINGLE_INSTANCE event
;
731 if (EventData
== NULL
)
736 sizeNeeded
= sizeof(WNODE_SINGLE_INSTANCE
) + EventDataSize
;
738 event
= ExAllocatePoolWithTag(NonPagedPool
, sizeNeeded
, CLASS_TAG_WMI
);
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
);
749 event
->InstanceIndex
= InstanceIndex
;
750 event
->SizeDataBlock
= EventDataSize
;
751 event
->DataBlockOffset
= sizeof(WNODE_SINGLE_INSTANCE
);
752 if (EventData
!= NULL
)
754 RtlCopyMemory( &event
->VariableData
, EventData
, EventDataSize
);
757 status
= IoWMIWriteEvent(event
);
758 if (! NT_SUCCESS(status
))
763 status
= STATUS_INSUFFICIENT_RESOURCES
;
767 } // end ClassWmiFireEvent()