3 Copyright (C) Microsoft Corporation, 1991 - 1999
11 SCSI class driver routines
29 IN PDEVICE_OBJECT DeviceObject
,
35 PGUIDREGINFO GuidList
,
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"
47 // What can be paged ???
49 #pragma alloc_text(PAGE, ClassSystemControl)
50 #pragma alloc_text(PAGE, ClassFindGuid)
54 /*++////////////////////////////////////////////////////////////////////////////
60 This routine will search the list of guids registered and return
61 the index for the one that was registered.
65 GuidList is the list of guids to search
67 GuidCount is the count of guids in the list
69 Guid is the guid being searched for
71 *GuidIndex returns the index to the guid
75 TRUE if guid is found else FALSE
80 PGUIDREGINFO GuidList
,
90 for (i
= 0; i
< GuidCount
; i
++)
92 if (IsEqualGUID(Guid
, &GuidList
[i
].Guid
))
100 } // end ClassFindGuid()
102 /*++////////////////////////////////////////////////////////////////////////////
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.
115 DeviceObject - Supplies a pointer to the device object for this request.
117 Irp - Supplies the Irp making the request.
127 IN PDEVICE_OBJECT DeviceObject
,
131 PCOMMON_DEVICE_EXTENSION commonExtension
= DeviceObject
->DeviceExtension
;
132 PCLASS_DRIVER_EXTENSION driverExtension
;
133 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
140 PCLASS_WMI_INFO classWmiInfo
;
145 // Make sure device has not been removed
146 isRemoved
= ClassAcquireRemoveLock(DeviceObject
, Irp
);
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
;
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
)))
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
));
171 buffer
= (PUCHAR
)irpStack
->Parameters
.WMI
.Buffer
;
172 bufferSize
= irpStack
->Parameters
.WMI
.BufferSize
;
174 if (minorFunction
!= IRP_MN_REGINFO
)
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
180 if (ClassFindGuid(commonExtension
->GuidRegInfo
,
181 commonExtension
->GuidCount
,
182 (LPGUID
)irpStack
->Parameters
.WMI
.DataPath
,
185 status
= STATUS_SUCCESS
;
187 status
= STATUS_WMI_GUID_NOT_FOUND
;
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
)))
196 if ( (((PWNODE_HEADER
)buffer
)->Flags
) &
197 WNODE_FLAG_STATIC_INSTANCE_NAMES
)
199 if ( ((PWNODE_SINGLE_INSTANCE
)buffer
)->InstanceIndex
!= 0 )
201 status
= STATUS_WMI_INSTANCE_NOT_FOUND
;
204 status
= STATUS_WMI_INSTANCE_NOT_FOUND
;
208 if (! NT_SUCCESS(status
))
210 Irp
->IoStatus
.Status
= status
;
211 ClassReleaseRemoveLock(DeviceObject
, Irp
);
212 ClassCompleteRequest(DeviceObject
, Irp
, IO_NO_INCREMENT
);
217 driverExtension
= commonExtension
->DriverExtension
;
219 classWmiInfo
= commonExtension
->IsFdo
?
220 &driverExtension
->InitData
.FdoData
.ClassWmiInfo
:
221 &driverExtension
->InitData
.PdoData
.ClassWmiInfo
;
222 switch(minorFunction
)
227 PGUIDREGINFO guidList
;
228 PWMIREGINFOW wmiRegInfo
;
229 PWMIREGGUIDW wmiRegGuid
;
230 //PDEVICE_OBJECT pdo;
231 PUNICODE_STRING regPath
;
234 ULONG registryPathOffset
;
235 ULONG mofResourceOffset
;
239 ULONG nameSize
, nameOffset
, nameFlags
;
240 UNICODE_STRING name
, mofName
;
241 PCLASS_QUERY_WMI_REGINFO_EX ClassQueryWmiRegInfoEx
;
245 name
.MaximumLength
= 0;
248 ClassQueryWmiRegInfoEx
= commonExtension
->IsFdo
?
249 driverExtension
->ClassFdoQueryWmiRegInfoEx
:
250 driverExtension
->ClassPdoQueryWmiRegInfoEx
;
252 if (ClassQueryWmiRegInfoEx
== NULL
)
254 status
= classWmiInfo
->ClassQueryWmiRegInfo(
259 RtlInitUnicodeString(&mofName
, MOFRESOURCENAME
);
261 RtlInitUnicodeString(&mofName
, L
"");
262 status
= (*ClassQueryWmiRegInfoEx
)(
269 if (NT_SUCCESS(status
) &&
270 (! (nameFlags
& WMIREG_FLAG_INSTANCE_PDO
) &&
271 (name
.Buffer
== NULL
)))
274 // if PDO flag not specified then an instance name must be
275 status
= STATUS_INVALID_DEVICE_REQUEST
;
278 if (NT_SUCCESS(status
))
280 guidList
= classWmiInfo
->GuidRegInfo
;
281 guidCount
= classWmiInfo
->GuidCount
;
283 nameOffset
= sizeof(WMIREGINFO
) +
284 guidCount
* sizeof(WMIREGGUIDW
);
286 if (nameFlags
& WMIREG_FLAG_INSTANCE_PDO
)
289 nameInfo
= commonExtension
->IsFdo
?
290 (ULONG_PTR
)((PFUNCTIONAL_DEVICE_EXTENSION
)commonExtension
)->LowerPdo
:
291 (ULONG_PTR
)DeviceObject
;
293 nameFlags
|= WMIREG_FLAG_INSTANCE_LIST
;
294 nameSize
= name
.Length
+ sizeof(USHORT
);
295 nameInfo
= nameOffset
;
298 mofResourceOffset
= nameOffset
+ nameSize
;
300 registryPathOffset
= mofResourceOffset
+
301 mofName
.Length
+ sizeof(USHORT
);
303 regPath
= &driverExtension
->RegistryPath
;
304 bufferNeeded
= registryPathOffset
+
305 regPath
->Length
+ sizeof(USHORT
);
307 if (bufferNeeded
<= bufferSize
)
309 retSize
= bufferNeeded
;
311 commonExtension
->GuidCount
= guidCount
;
312 commonExtension
->GuidRegInfo
= guidList
;
314 wmiRegInfo
= (PWMIREGINFO
)buffer
;
315 wmiRegInfo
->BufferSize
= bufferNeeded
;
316 wmiRegInfo
->NextWmiRegInfo
= 0;
317 wmiRegInfo
->MofResourceName
= mofResourceOffset
;
318 wmiRegInfo
->RegistryPath
= registryPathOffset
;
319 wmiRegInfo
->GuidCount
= guidCount
;
321 for (i
= 0; i
< guidCount
; i
++)
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;
330 if ( nameFlags
& WMIREG_FLAG_INSTANCE_LIST
)
332 stringPtr
= (PWCHAR
)((PUCHAR
)buffer
+ nameOffset
);
333 *stringPtr
++ = name
.Length
;
334 RtlCopyMemory(stringPtr
,
339 stringPtr
= (PWCHAR
)((PUCHAR
)buffer
+ mofResourceOffset
);
340 *stringPtr
++ = mofName
.Length
;
341 RtlCopyMemory(stringPtr
,
345 stringPtr
= (PWCHAR
)((PUCHAR
)buffer
+ registryPathOffset
);
346 *stringPtr
++ = regPath
->Length
;
347 RtlCopyMemory(stringPtr
,
351 *((PULONG
)buffer
) = bufferNeeded
;
352 retSize
= sizeof(ULONG
);
358 if (name
.Buffer
!= NULL
)
360 ExFreePool(name
.Buffer
);
363 Irp
->IoStatus
.Status
= status
;
364 Irp
->IoStatus
.Information
= retSize
;
365 ClassReleaseRemoveLock(DeviceObject
, Irp
);
366 ClassCompleteRequest(DeviceObject
, Irp
, IO_NO_INCREMENT
);
370 case IRP_MN_QUERY_ALL_DATA
:
372 PWNODE_ALL_DATA wnode
;
375 wnode
= (PWNODE_ALL_DATA
)buffer
;
377 if (bufferSize
< sizeof(WNODE_ALL_DATA
))
381 bufferAvail
= bufferSize
- sizeof(WNODE_ALL_DATA
);
384 wnode
->DataBlockOffset
= sizeof(WNODE_ALL_DATA
);
386 status
= classWmiInfo
->ClassQueryWmiDataBlock(
391 buffer
+ sizeof(WNODE_ALL_DATA
));
396 case IRP_MN_QUERY_SINGLE_INSTANCE
:
398 PWNODE_SINGLE_INSTANCE wnode
;
399 ULONG dataBlockOffset
;
401 wnode
= (PWNODE_SINGLE_INSTANCE
)buffer
;
403 dataBlockOffset
= wnode
->DataBlockOffset
;
405 status
= classWmiInfo
->ClassQueryWmiDataBlock(
409 bufferSize
- dataBlockOffset
,
410 (PUCHAR
)wnode
+ dataBlockOffset
);
415 case IRP_MN_CHANGE_SINGLE_INSTANCE
:
417 PWNODE_SINGLE_INSTANCE wnode
;
419 wnode
= (PWNODE_SINGLE_INSTANCE
)buffer
;
421 status
= classWmiInfo
->ClassSetWmiDataBlock(
425 wnode
->SizeDataBlock
,
426 (PUCHAR
)wnode
+ wnode
->DataBlockOffset
);
431 case IRP_MN_CHANGE_SINGLE_ITEM
:
433 PWNODE_SINGLE_ITEM wnode
;
435 wnode
= (PWNODE_SINGLE_ITEM
)buffer
;
437 status
= classWmiInfo
->ClassSetWmiDataItem(
443 (PUCHAR
)wnode
+ wnode
->DataBlockOffset
);
448 case IRP_MN_EXECUTE_METHOD
:
450 PWNODE_METHOD_ITEM wnode
;
452 wnode
= (PWNODE_METHOD_ITEM
)buffer
;
454 status
= classWmiInfo
->ClassExecuteWmiMethod(
459 wnode
->SizeDataBlock
,
460 bufferSize
- wnode
->DataBlockOffset
,
461 buffer
+ wnode
->DataBlockOffset
);
467 case IRP_MN_ENABLE_EVENTS
:
469 status
= classWmiInfo
->ClassWmiFunctionControl(
478 case IRP_MN_DISABLE_EVENTS
:
480 status
= classWmiInfo
->ClassWmiFunctionControl(
489 case IRP_MN_ENABLE_COLLECTION
:
491 status
= classWmiInfo
->ClassWmiFunctionControl(
500 case IRP_MN_DISABLE_COLLECTION
:
502 status
= classWmiInfo
->ClassWmiFunctionControl(
513 status
= STATUS_INVALID_DEVICE_REQUEST
;
520 } // end ClassSystemControl()
522 /*++////////////////////////////////////////////////////////////////////////////
524 ClassWmiCompleteRequest()
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.
532 NOTE: This routine assumes that the ClassRemoveLock is held and it will
537 DeviceObject - Supplies a pointer to the device object for this request.
539 Irp - Supplies the Irp making the request.
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.
544 BufferUsed - number of bytes of actual data to return (not including WMI
547 PriorityBoost - priority boost to pass to ClassCompleteRequest
557 ClassWmiCompleteRequest(
558 IN PDEVICE_OBJECT DeviceObject
,
562 IN CCHAR PriorityBoost
565 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
566 //UCHAR MinorFunction;
571 minorFunction
= irpStack
->MinorFunction
;
572 buffer
= (PUCHAR
)irpStack
->Parameters
.WMI
.Buffer
;
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
720 IN PDEVICE_OBJECT DeviceObject
,
722 IN ULONG InstanceIndex
,
723 IN ULONG EventDataSize
,
729 PWNODE_SINGLE_INSTANCE event
;
732 if (EventData
== NULL
)
737 sizeNeeded
= sizeof(WNODE_SINGLE_INSTANCE
) + EventDataSize
;
739 event
= ExAllocatePoolWithTag(NonPagedPool
, sizeNeeded
, CLASS_TAG_WMI
);
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
);
750 event
->InstanceIndex
= InstanceIndex
;
751 event
->SizeDataBlock
= EventDataSize
;
752 event
->DataBlockOffset
= sizeof(WNODE_SINGLE_INSTANCE
);
753 if (EventData
!= NULL
)
755 RtlCopyMemory( &event
->VariableData
, EventData
, EventDataSize
);
758 status
= IoWMIWriteEvent(event
);
759 if (! NT_SUCCESS(status
))
764 status
= STATUS_INSUFFICIENT_RESOURCES
;
768 } // end ClassWmiFireEvent()