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 PCOMMON_DEVICE_EXTENSION commonExtension
= DeviceObject
->DeviceExtension
;
566 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
567 //UCHAR MinorFunction;
573 minorFunction
= irpStack
->MinorFunction
;
574 buffer
= (PUCHAR
)irpStack
->Parameters
.WMI
.Buffer
;
575 bufferSize
= irpStack
->Parameters
.WMI
.BufferSize
;
577 switch(minorFunction
)
579 case IRP_MN_QUERY_ALL_DATA
:
581 PWNODE_ALL_DATA wnode
;
582 PWNODE_TOO_SMALL wnodeTooSmall
;
585 wnode
= (PWNODE_ALL_DATA
)buffer
;
587 bufferNeeded
= sizeof(WNODE_ALL_DATA
) + BufferUsed
;
589 if (NT_SUCCESS(Status
))
591 retSize
= bufferNeeded
;
592 wnode
->WnodeHeader
.BufferSize
= bufferNeeded
;
593 KeQuerySystemTime(&wnode
->WnodeHeader
.TimeStamp
);
594 wnode
->WnodeHeader
.Flags
|= WNODE_FLAG_FIXED_INSTANCE_SIZE
;
595 wnode
->FixedInstanceSize
= BufferUsed
;
596 wnode
->InstanceCount
= 1;
598 } else if (Status
== STATUS_BUFFER_TOO_SMALL
) {
599 wnodeTooSmall
= (PWNODE_TOO_SMALL
)wnode
;
601 wnodeTooSmall
->WnodeHeader
.BufferSize
= sizeof(WNODE_TOO_SMALL
);
602 wnodeTooSmall
->WnodeHeader
.Flags
= WNODE_FLAG_TOO_SMALL
;
603 wnodeTooSmall
->SizeNeeded
= sizeof(WNODE_ALL_DATA
) + BufferUsed
;
604 retSize
= sizeof(WNODE_TOO_SMALL
);
605 Status
= STATUS_SUCCESS
;
612 case IRP_MN_QUERY_SINGLE_INSTANCE
:
614 PWNODE_SINGLE_INSTANCE wnode
;
615 PWNODE_TOO_SMALL wnodeTooSmall
;
618 wnode
= (PWNODE_SINGLE_INSTANCE
)buffer
;
620 bufferNeeded
= wnode
->DataBlockOffset
+ BufferUsed
;
622 if (NT_SUCCESS(Status
))
624 retSize
= bufferNeeded
;
625 wnode
->WnodeHeader
.BufferSize
= bufferNeeded
;
626 KeQuerySystemTime(&wnode
->WnodeHeader
.TimeStamp
);
627 wnode
->SizeDataBlock
= BufferUsed
;
629 } else if (Status
== STATUS_BUFFER_TOO_SMALL
) {
630 wnodeTooSmall
= (PWNODE_TOO_SMALL
)wnode
;
632 wnodeTooSmall
->WnodeHeader
.BufferSize
= sizeof(WNODE_TOO_SMALL
);
633 wnodeTooSmall
->WnodeHeader
.Flags
= WNODE_FLAG_TOO_SMALL
;
634 wnodeTooSmall
->SizeNeeded
= bufferNeeded
;
635 retSize
= sizeof(WNODE_TOO_SMALL
);
636 Status
= STATUS_SUCCESS
;
643 case IRP_MN_EXECUTE_METHOD
:
645 PWNODE_METHOD_ITEM wnode
;
646 PWNODE_TOO_SMALL wnodeTooSmall
;
649 wnode
= (PWNODE_METHOD_ITEM
)buffer
;
651 bufferNeeded
= wnode
->DataBlockOffset
+ BufferUsed
;
653 if (NT_SUCCESS(Status
))
655 retSize
= bufferNeeded
;
656 wnode
->WnodeHeader
.BufferSize
= bufferNeeded
;
657 KeQuerySystemTime(&wnode
->WnodeHeader
.TimeStamp
);
658 wnode
->SizeDataBlock
= BufferUsed
;
660 } else if (Status
== STATUS_BUFFER_TOO_SMALL
) {
661 wnodeTooSmall
= (PWNODE_TOO_SMALL
)wnode
;
663 wnodeTooSmall
->WnodeHeader
.BufferSize
= sizeof(WNODE_TOO_SMALL
);
664 wnodeTooSmall
->WnodeHeader
.Flags
= WNODE_FLAG_TOO_SMALL
;
665 wnodeTooSmall
->SizeNeeded
= bufferNeeded
;
666 retSize
= sizeof(WNODE_TOO_SMALL
);
667 Status
= STATUS_SUCCESS
;
677 // All other requests don't return any data
684 Irp
->IoStatus
.Status
= Status
;
685 Irp
->IoStatus
.Information
= retSize
;
686 ClassReleaseRemoveLock(DeviceObject
, Irp
);
687 ClassCompleteRequest(DeviceObject
, Irp
, PriorityBoost
);
689 } // end ClassWmiCompleteRequest()
691 /*++////////////////////////////////////////////////////////////////////////////
697 This routine will fire a WMI event using the data buffer passed. This
698 routine may be called at or below DPC level
702 DeviceObject - Supplies a pointer to the device object for this event
704 Guid is pointer to the GUID that represents the event
706 InstanceIndex is the index of the instance of the event
708 EventDataSize is the number of bytes of data that is being fired with
711 EventData is the data that is fired with the events. This may be NULL
712 if there is no data associated with the event
723 IN PDEVICE_OBJECT DeviceObject
,
725 IN ULONG InstanceIndex
,
726 IN ULONG EventDataSize
,
732 PWNODE_SINGLE_INSTANCE event
;
735 if (EventData
== NULL
)
740 sizeNeeded
= sizeof(WNODE_SINGLE_INSTANCE
) + EventDataSize
;
742 event
= ExAllocatePoolWithTag(NonPagedPool
, sizeNeeded
, CLASS_TAG_WMI
);
745 event
->WnodeHeader
.Guid
= *Guid
;
746 event
->WnodeHeader
.ProviderId
= IoWMIDeviceObjectToProviderId(DeviceObject
);
747 event
->WnodeHeader
.BufferSize
= sizeNeeded
;
748 event
->WnodeHeader
.Flags
= WNODE_FLAG_SINGLE_INSTANCE
|
749 WNODE_FLAG_EVENT_ITEM
|
750 WNODE_FLAG_STATIC_INSTANCE_NAMES
;
751 KeQuerySystemTime(&event
->WnodeHeader
.TimeStamp
);
753 event
->InstanceIndex
= InstanceIndex
;
754 event
->SizeDataBlock
= EventDataSize
;
755 event
->DataBlockOffset
= sizeof(WNODE_SINGLE_INSTANCE
);
756 if (EventData
!= NULL
)
758 RtlCopyMemory( &event
->VariableData
, EventData
, EventDataSize
);
761 status
= IoWMIWriteEvent(event
);
762 if (! NT_SUCCESS(status
))
767 status
= STATUS_INSUFFICIENT_RESOURCES
;
771 } // end ClassWmiFireEvent()