Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1126 lines
30 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
vfddi.c
Abstract:
This module contains the list of device driver interfaces exported by the
driver verifier and the kernel. Note that thunked exports are *not* placed
here.
All the exports are concentrated in one file because
1) There are relatively few driver verifier exports
2) The function naming convention differs from that used elsewhere in
the driver verifier.
Author:
Adrian J. Oney (adriao) 26-Apr-2001
Environment:
Kernel mode
Revision History:
--*/
#include "vfdef.h"
#include "viddi.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, VfDdiInit)
#pragma alloc_text(PAGEVRFY, VfDdiExposeWmiObjects)
//#pragma alloc_text(NONPAGED, VfFailDeviceNode)
//#pragma alloc_text(NONPAGED, VfFailSystemBIOS)
//#pragma alloc_text(NONPAGED, VfFailDriver)
//#pragma alloc_text(NONPAGED, VfIsVerificationEnabled)
#pragma alloc_text(PAGEVRFY, ViDdiThrowException)
#pragma alloc_text(PAGEVRFY, ViDdiDriverEntry)
#pragma alloc_text(PAGEVRFY, ViDdiDispatchWmi)
#pragma alloc_text(PAGEVRFY, ViDdiDispatchWmiRegInfoEx)
#pragma alloc_text(PAGEVRFY, ViDdiBuildWmiRegInfoData)
#pragma alloc_text(PAGEVRFY, ViDdiDispatchWmiQueryAllData)
#endif // ALLOC_PRAGMA
LOGICAL ViDdiInitialized = FALSE;
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg("PAGEVRFD")
#endif
UNICODE_STRING ViDdiWmiMofKey;
UNICODE_STRING ViDdiWmiMofResourceName;
PDEVICE_OBJECT *ViDdiDeviceObjectArray = NULL;
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg("PAGEVRFC")
#endif
//
// These are the general "classifications" of device errors, along with the
// default flags that will be applied the first time this is hit.
//
const VFMESSAGE_CLASS ViDdiClassFailDeviceInField = {
VFM_FLAG_BEEP | VFM_LOGO_FAILURE | VFM_DEPLOYMENT_FAILURE,
"DEVICE FAILURE"
};
// VFM_DEPLOYMENT_FAILURE is set here because we don't yet have a "logo" mode
const VFMESSAGE_CLASS ViDdiClassFailDeviceLogo = {
VFM_FLAG_BEEP | VFM_LOGO_FAILURE | VFM_DEPLOYMENT_FAILURE,
"DEVICE FAILURE"
};
const VFMESSAGE_CLASS ViDdiClassFailDeviceUnderDebugger = {
VFM_FLAG_BEEP,
"DEVICE FAILURE"
};
WCHAR VerifierDdiDriverName[] = L"\\DRIVER\\VERIFIER_DDI";
#include <initguid.h>
// Define the verifier WMI GUID (1E2C2980-F7DB-46AA-820E-8734FCC21F4C)
DEFINE_GUID( GUID_VERIFIER_WMI_INTERFACE, 0x1E2C2980L, 0xF7DB, 0x46AA,
0x82, 0x0E, 0x87, 0x34, 0xFC, 0xC2, 0x1F, 0x4C);
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg()
#endif // ALLOC_DATA_PRAGMA
#define POOLTAG_DDI_WMIDO_ARRAY 'aDfV'
VOID
VfDdiInit(
VOID
)
/*++
Routine Description:
This routine initializes the Device Driver Interface support.
Arguments:
None.
Return Value:
None.
--*/
{
ViDdiInitialized = TRUE;
}
VOID
VfDdiExposeWmiObjects(
VOID
)
/*++
Routine Description:
This routine exposes verifier WMI objects.
Arguments:
None.
Return Value:
None.
--*/
{
UNICODE_STRING driverString;
// L"\\Machine\\Registry\\System\\CurrentControlSet\\Services\\Verifier");
RtlInitUnicodeString(&ViDdiWmiMofKey, L"");
// L"VerifierMof"
RtlInitUnicodeString(&ViDdiWmiMofResourceName, L"");
RtlInitUnicodeString(&driverString, VerifierDdiDriverName);
IoCreateDriver(&driverString, ViDdiDriverEntry);
}
VOID
VfFailDeviceNode(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN ULONG BugCheckMajorCode,
IN ULONG BugCheckMinorCode,
IN VF_FAILURE_CLASS FailureClass,
IN OUT PULONG AssertionControl,
IN PSTR DebuggerMessageText,
IN PSTR ParameterFormatString,
...
)
/*++
Routine Description:
This routine fails a Pnp enumerated hardware or virtual device if
verification is enabled against it.
Arguments:
PhysicalDeviceObject - Bottom of the stack that identifies the PnP
device.
BugCheckMajorCode - BugCheck Major Code
BugCheckMinorCode - BugCheck Minor Code
Note - Zero is reserved!!!
FailureClass - Either VFFAILURE_FAIL_IN_FIELD,
VFFAILURE_FAIL_LOGO, or
VFFAILURE_FAIL_UNDER_DEBUGGER
AssertionControl - Points to a ULONG associated with the failure,
used to store information across multiple calls.
Must be statically preinitialized to zero.
DebuggerMessageText - Text to be displayed in the debugger. Note that
the text may reference parameters such as:
%Routine - passed in Routine
%Irp - passed in Irp
%DevObj - passed in DevObj
%Status - passed in Status
%Ulong - passed in ULONG
%Ulong1 - first passed in ULONG
%Ulong3 - third passed in ULONG (max 3, any param)
%Pvoid2 - second passed in PVOID
etc
(note, capitalization matters)
ParameterFormatString - Contains ordered list of parameters referenced by
above debugger text. For instance,
(..., "%Status1%Status2%Ulong1%Ulong2", Status1, Status2, Ulong1, Ulong2);
Note - If %Routine/%Routine1 is supplied as a param,
the driver at %Routine must also be under verification.
... - Actual parameters
Return Value:
None.
Note - this function may return if the device is not currently being
verified.
--*/
{
va_list arglist;
if (!VfIsVerificationEnabled(VFOBJTYPE_DEVICE, (PVOID) PhysicalDeviceObject)) {
return;
}
va_start(arglist, ParameterFormatString);
ViDdiThrowException(
BugCheckMajorCode,
BugCheckMinorCode,
FailureClass,
AssertionControl,
DebuggerMessageText,
ParameterFormatString,
&arglist
);
va_end(arglist);
}
VOID
VfFailSystemBIOS(
IN ULONG BugCheckMajorCode,
IN ULONG BugCheckMinorCode,
IN VF_FAILURE_CLASS FailureClass,
IN OUT PULONG AssertionControl,
IN PSTR DebuggerMessageText,
IN PSTR ParameterFormatString,
...
)
/*++
Routine Description:
This routine fails the system BIOS if verification is enabled against it.
Arguments:
BugCheckMajorCode - BugCheck Major Code
BugCheckMinorCode - BugCheck Minor Code
Note - Zero is reserved!!!
FailureClass - Either VFFAILURE_FAIL_IN_FIELD,
VFFAILURE_FAIL_LOGO, or
VFFAILURE_FAIL_UNDER_DEBUGGER
AssertionControl - Points to a ULONG associated with the failure,
used to store information across multiple calls.
Must be statically preinitialized to zero.
DebuggerMessageText - Text to be displayed in the debugger. Note that
the text may reference parameters such as:
%Routine - passed in Routine
%Irp - passed in Irp
%DevObj - passed in DevObj
%Status - passed in Status
%Ulong - passed in ULONG
%Ulong1 - first passed in ULONG
%Ulong3 - third passed in ULONG (max 3, any param)
%Pvoid2 - second passed in PVOID
etc
(note, capitalization matters)
ParameterFormatString - Contains ordered list of parameters referenced by
above debugger text. For instance,
(..., "%Status1%Status2%Ulong1%Ulong2", Status1, Status2, Ulong1, Ulong2);
Note - If %Routine/%Routine1 is supplied as a param,
the driver at %Routine must also be under verification.
... - Actual parameters
Return Value:
None.
Note - this function may return if the device is not currently being
verified.
--*/
{
va_list arglist;
if (!VfIsVerificationEnabled(VFOBJTYPE_SYSTEM_BIOS, NULL)) {
return;
}
va_start(arglist, ParameterFormatString);
ViDdiThrowException(
BugCheckMajorCode,
BugCheckMinorCode,
FailureClass,
AssertionControl,
DebuggerMessageText,
ParameterFormatString,
&arglist
);
va_end(arglist);
}
VOID
VfFailDriver(
IN ULONG BugCheckMajorCode,
IN ULONG BugCheckMinorCode,
IN VF_FAILURE_CLASS FailureClass,
IN OUT PULONG AssertionControl,
IN PSTR DebuggerMessageText,
IN PSTR ParameterFormatString,
...
)
/*++
Routine Description:
This routine fails a driver if verification is enabled against it.
Arguments:
BugCheckMajorCode - BugCheck Major Code
BugCheckMinorCode - BugCheck Minor Code
Note - Zero is reserved!!!
FailureClass - Either VFFAILURE_FAIL_IN_FIELD,
VFFAILURE_FAIL_LOGO, or
VFFAILURE_FAIL_UNDER_DEBUGGER
AssertionControl - Points to a ULONG associated with the failure.
Must be preinitialized to zero!!!
DebuggerMessageText - Text to be displayed in the debugger. Note that
the text may reference parameters such as:
%Routine - passed in Routine
%Irp - passed in Irp
%DevObj - passed in DevObj
%Status - passed in Status
%Ulong - passed in ULONG
%Ulong1 - first passed in ULONG
%Ulong3 - third passed in ULONG (max 3, any param)
%Pvoid2 - second passed in PVOID
etc
(note, capitalization matters)
ParameterFormatString - Contains ordered list of parameters referenced by
above debugger text. For instance,
(..., "%Status1%Status2%Ulong1%Ulong2", Status1, Status2, Ulong1, Ulong2);
One of these parameters should be %Routine. This will
be what the OS uses to identify the driver.
static minorFlags = 0;
VfFailDriver(
major,
minor,
VFFAILURE_FAIL_LOGO,
&minorFlags,
"Driver at %Routine returned %Ulong",
"%Ulong%Routine",
value,
routine
);
Return Value:
None.
Note - this function may return if the driver is not currently being
verified.
--*/
{
va_list arglist;
if (!ViDdiInitialized) {
return;
}
va_start(arglist, ParameterFormatString);
ViDdiThrowException(
BugCheckMajorCode,
BugCheckMinorCode,
FailureClass,
AssertionControl,
DebuggerMessageText,
ParameterFormatString,
&arglist
);
va_end(arglist);
}
VOID
ViDdiThrowException(
IN ULONG BugCheckMajorCode,
IN ULONG BugCheckMinorCode,
IN VF_FAILURE_CLASS FailureClass,
IN OUT PULONG AssertionControl,
IN PSTR DebuggerMessageText,
IN PSTR ParameterFormatString,
IN va_list * MessageParameters
)
/*++
Routine Description:
This routine fails either a devnode or a driver.
Arguments:
BugCheckMajorCode - BugCheck Major Code
BugCheckMinorCode - BugCheck Minor Code
Note - Zero is reserved!!!
FailureClass - Either VFFAILURE_FAIL_IN_FIELD,
VFFAILURE_FAIL_LOGO, or
VFFAILURE_FAIL_UNDER_DEBUGGER
AssertionControl - Points to a ULONG associated with the failure.
Must be preinitialized to zero.
DebuggerMessageText - Text to be displayed in the debugger. Note that
the text may reference parameters such as:
%Routine - passed in Routine
%Irp - passed in Irp
%DevObj - passed in DevObj
%Status - passed in Status
%Ulong - passed in ULONG
%Ulong1 - first passed in ULONG
%Ulong3 - third passed in ULONG (max 3, any param)
%Pvoid2 - second passed in PVOID
etc
(note, capitalization matters)
ParameterFormatString - Contains ordered list of parameters referenced by
above debugger text. For instance,
(..., "%Status1%Status2%Ulong1%Ulong2", Status1, Status2, Ulong1, Ulong2);
MessageParameters - arg list of parameters matching
ParameterFormatString
Return Value:
None.
Note - this function may return if the device is not currently being
verified.
--*/
{
PCVFMESSAGE_CLASS messageClass;
VFMESSAGE_TEMPLATE messageTemplates[2];
VFMESSAGE_TEMPLATE_TABLE messageTable;
NTSTATUS status;
ASSERT(BugCheckMinorCode != 0);
switch(FailureClass) {
case VFFAILURE_FAIL_IN_FIELD:
messageClass = &ViDdiClassFailDeviceInField;
break;
case VFFAILURE_FAIL_LOGO:
messageClass = &ViDdiClassFailDeviceLogo;
break;
case VFFAILURE_FAIL_UNDER_DEBUGGER:
messageClass = &ViDdiClassFailDeviceUnderDebugger;
break;
default:
ASSERT(0);
messageClass = NULL;
break;
}
//
// Program the template.
//
RtlZeroMemory(messageTemplates, sizeof(messageTemplates));
messageTemplates[0].MessageID = BugCheckMinorCode-1;
messageTemplates[1].MessageID = BugCheckMinorCode;
messageTemplates[1].MessageClass = messageClass;
messageTemplates[1].Flags = *AssertionControl;
messageTemplates[1].ParamString = ParameterFormatString;
messageTemplates[1].MessageText = DebuggerMessageText;
//
// Fill out the message table.
//
messageTable.TableID = 0;
messageTable.BugCheckMajor = BugCheckMajorCode;
messageTable.TemplateArray = messageTemplates;
messageTable.TemplateCount = ARRAY_COUNT(messageTemplates);
messageTable.OverrideArray = NULL;
messageTable.OverrideCount = 0;
status = VfBugcheckThrowException(
&messageTable,
BugCheckMinorCode,
ParameterFormatString,
MessageParameters
);
//
// Write back the assertion control.
//
*AssertionControl = messageTemplates[1].Flags;
}
BOOLEAN
VfIsVerificationEnabled(
IN VF_OBJECT_TYPE VfObjectType,
IN PVOID Object
)
{
if (!ViDdiInitialized) {
return FALSE;
}
switch(VfObjectType) {
case VFOBJTYPE_DRIVER:
return (BOOLEAN) MmIsDriverVerifying((PDRIVER_OBJECT) Object);
case VFOBJTYPE_DEVICE:
if (!VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_HARDWARE_VERIFICATION)) {
return FALSE;
}
return PpvUtilIsHardwareBeingVerified((PDEVICE_OBJECT) Object);
case VFOBJTYPE_SYSTEM_BIOS:
return VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_SYSTEM_BIOS_VERIFICATION);
}
return FALSE;
}
NTSTATUS
ViDdiDriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This is the callback function when we call IoCreateDriver to create a
Verifier Ddi Object.
Arguments:
DriverObject - Pointer to the driver object created by the system.
RegistryPath - is NULL.
Return Value:
STATUS_SUCCESS
--*/
{
PDEVICE_OBJECT deviceObject;
ULONG siloCount;
NTSTATUS status;
ULONG i;
UNREFERENCED_PARAMETER(RegistryPath);
//
// This driver exposes a WMI interface, and that's it.
//
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = ViDdiDispatchWmi;
siloCount = VfIrpLogGetIrpDatabaseSiloCount();
ViDdiDeviceObjectArray = (PDEVICE_OBJECT *) ExAllocatePoolWithTag(
NonPagedPool,
sizeof(PDEVICE_OBJECT) * siloCount,
POOLTAG_DDI_WMIDO_ARRAY
);
if (ViDdiDeviceObjectArray == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Create device objects that will expose IRP history via WMI. We expose
// multiple as WMI has a maximum of 64K data per transfer.
//
for(i=0; i < siloCount; i++) {
status = IoCreateDevice(
DriverObject,
sizeof(VFWMI_DEVICE_EXTENSION),
NULL, // The name will be autogenerated
FILE_DEVICE_UNKNOWN,
FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObject
);
if (!NT_SUCCESS(status)) {
while(i) {
IoDeleteDevice(ViDdiDeviceObjectArray[--i]);
}
return status;
}
ViDdiDeviceObjectArray[i] = deviceObject;
((PVFWMI_DEVICE_EXTENSION) deviceObject->DeviceExtension)->SiloNumber = i;
}
for(i=0; i < siloCount; i++) {
deviceObject = ViDdiDeviceObjectArray[i];
//
// Let the operating system know this device object is now online (we
// can now receive IRPs, such as WMI).
//
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
//
// Tell WMI to query our device object for WMI information.
//
status = IoWMIRegistrationControl(deviceObject, WMIREG_ACTION_REGISTER);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(deviceObject);
while(i) {
IoDeleteDevice(ViDdiDeviceObjectArray[--i]);
}
return status;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
ViDdiDispatchWmi(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Verifier Ddi dispatch handler for WMI IRPs.
Arguments:
DeviceObject - Pointer to the verifier device object.
Irp - Pointer to the incoming IRP.
Return Value:
NTSTATUS
--*/
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status;
irpSp = IoGetCurrentIrpStackLocation(Irp);
switch(irpSp->MinorFunction) {
case IRP_MN_REGINFO_EX:
status = ViDdiDispatchWmiRegInfoEx(DeviceObject, Irp);
break;
case IRP_MN_QUERY_ALL_DATA:
status = ViDdiDispatchWmiQueryAllData(DeviceObject, Irp);
break;
default:
status = STATUS_NOT_SUPPORTED;
break;
}
if (status == STATUS_NOT_SUPPORTED) {
status = Irp->IoStatus.Status;
} else {
Irp->IoStatus.Status = status;
}
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
ViDdiDispatchWmiRegInfoEx(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Verifier Ddi dispatch handler for the WMI IRP_MN_REGINFO_EX IRP.
Arguments:
DeviceObject - Pointer to the verifier device object.
Irp - Pointer to the incoming IRP.
Return Value:
NTSTATUS
--*/
{
PIO_STACK_LOCATION irpSp;
PWMIREGINFO wmiRegInfo;
ULONG sizeSupplied;
ULONG sizeRequired;
irpSp = IoGetCurrentIrpStackLocation(Irp);
if ((PDEVICE_OBJECT) irpSp->Parameters.WMI.ProviderId != DeviceObject) {
//
// Huh? This is a single device object legacy stack!
//
ASSERT(0);
return STATUS_NOT_SUPPORTED;
}
wmiRegInfo = (PWMIREGINFO) irpSp->Parameters.WMI.Buffer;
sizeSupplied = irpSp->Parameters.WMI.BufferSize;
sizeRequired = ViDdiBuildWmiRegInfoData((ULONG) (ULONG_PTR) irpSp->Parameters.WMI.DataPath, NULL);
if (sizeRequired > sizeSupplied) {
//
// Not large enough, indicate the required size and fail the IRP.
//
if (sizeSupplied < sizeof(ULONG)) {
//
// WMI must give us at least a ULONG!
//
ASSERT(0);
return STATUS_NOT_SUPPORTED;
}
//
// Per spec, write to only the first ULONG in the supplied buffer.
//
wmiRegInfo->BufferSize = sizeRequired;
Irp->IoStatus.Information = sizeof(ULONG);
return STATUS_BUFFER_TOO_SMALL;
}
ViDdiBuildWmiRegInfoData((ULONG) (ULONG_PTR) irpSp->Parameters.WMI.DataPath, wmiRegInfo);
Irp->IoStatus.Information = sizeRequired;
return STATUS_SUCCESS;
}
ULONG
ViDdiBuildWmiRegInfoData(
IN ULONG Datapath,
OUT PWMIREGINFOW WmiRegInfo OPTIONAL
)
/*++
Routine Description:
This function calculates and optionally builds the data block to return
back to WMI in response to IRP_MN_REGINFO_EX.
Arguments:
Datapath - Either WMIREGISTER or WMIUPDATE.
WmiRegInfo - Buffer supplied by OS to optionally fill in.
Return Value:
Size in bytes of buffer (required or written)
--*/
{
PUNICODE_STRING unicodeDestString;
PUNICODE_STRING unicodeSrcString;
PWMIREGGUIDW wmiRegGuid;
ULONG bufferSize;
ULONG guidCount;
//
// Start with the basic WMI structure size.
//
bufferSize = sizeof(WMIREGINFO);
//
// Add our one interface GUID structure. We are using dynamic instance
// names for this interface, so we'll provide them in response to a query.
// Consequently, we don't have any trailing static instance info.
//
guidCount = 1;
if (ARGUMENT_PRESENT(WmiRegInfo)) {
WmiRegInfo->GuidCount = guidCount;
wmiRegGuid = &WmiRegInfo->WmiRegGuid[0];
wmiRegGuid->Guid = GUID_VERIFIER_WMI_INTERFACE;
wmiRegGuid->Flags = 0;
//
// These fields don't need to be zeroed, but we make them consistant
// just in case a bug exists somewhere downstream.
//
wmiRegGuid->InstanceCount = 0;
wmiRegGuid->InstanceInfo = 0;
}
bufferSize += guidCount * sizeof(WMIREGGUIDW);
if (Datapath == WMIREGISTER) {
//
// The registry path begins here. Adjust bufferSize to point to the
// next field.
//
bufferSize = ALIGN_UP_ULONG(bufferSize, 2);
unicodeSrcString = &ViDdiWmiMofKey;
if (ARGUMENT_PRESENT(WmiRegInfo)) {
WmiRegInfo->RegistryPath = bufferSize;
unicodeDestString = (PUNICODE_STRING) (((PUCHAR) WmiRegInfo) + bufferSize);
unicodeDestString->Length = unicodeSrcString->Length;
unicodeDestString->MaximumLength = unicodeSrcString->Length;
unicodeDestString->Buffer = (PWCHAR) (unicodeDestString+1);
RtlCopyMemory(unicodeDestString->Buffer,
unicodeSrcString->Buffer,
unicodeSrcString->Length);
}
bufferSize += sizeof(UNICODE_STRING) + unicodeSrcString->Length;
//
// The Mof resource name begins here. Adjust buffersize to point to the
// next field.
//
bufferSize = ALIGN_UP_ULONG(bufferSize, 2);
unicodeSrcString = &ViDdiWmiMofResourceName;
if (ARGUMENT_PRESENT(WmiRegInfo)) {
WmiRegInfo->MofResourceName = bufferSize;
unicodeDestString = (PUNICODE_STRING) (((PUCHAR) WmiRegInfo) + bufferSize);
unicodeDestString->Length = unicodeSrcString->Length;
unicodeDestString->MaximumLength = unicodeSrcString->Length;
unicodeDestString->Buffer = (PWCHAR) (unicodeDestString+1);
RtlCopyMemory(unicodeDestString->Buffer,
unicodeSrcString->Buffer,
unicodeSrcString->Length);
}
bufferSize += sizeof(UNICODE_STRING) + unicodeSrcString->Length;
}
//
// That's it, close up the structures.
//
if (ARGUMENT_PRESENT(WmiRegInfo)) {
WmiRegInfo->NextWmiRegInfo = 0;
WmiRegInfo->BufferSize = bufferSize;
}
return bufferSize;
}
NTSTATUS
ViDdiDispatchWmiQueryAllData(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Verifier Ddi dispatch handler for the WMI IRP_MN_QUERY_ALL_DATA
IRP.
Arguments:
DeviceObject - Pointer to the verifier device object.
Irp - Pointer to the incoming IRP.
Return Value:
NTSTATUS
--*/
{
PVFWMI_DEVICE_EXTENSION wmiDeviceExtension;
PIO_STACK_LOCATION irpSp;
PWNODE_HEADER wnodeHeader;
PWNODE_ALL_DATA wmiAllData;
PWNODE_TOO_SMALL tooSmall;
ULONG sizeSupplied;
ULONG offsetInstanceNameOffsets;
ULONG instanceCount;
ULONG dataBlockOffset;
ULONG totalRequiredSize;
NTSTATUS status;
irpSp = IoGetCurrentIrpStackLocation(Irp);
if ((PDEVICE_OBJECT) irpSp->Parameters.WMI.ProviderId != DeviceObject) {
//
// Huh? This is a single device object legacy stack!
//
ASSERT(0);
return STATUS_NOT_SUPPORTED;
}
if (!IS_EQUAL_GUID(irpSp->Parameters.WMI.DataPath, &GUID_VERIFIER_WMI_INTERFACE)) {
//
// We only support one Guid. WMI shouldn't be able to come up with
// another...
//
ASSERT(0);
return STATUS_WMI_GUID_NOT_FOUND;
}
wmiDeviceExtension = (PVFWMI_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
sizeSupplied = irpSp->Parameters.WMI.BufferSize;
//
// Not large enough, indicate the required size and fail the IRP.
//
if (sizeSupplied < sizeof(WNODE_TOO_SMALL)) {
//
// WMI must give us at least a WNODE_TOO_SMALL structure!
//
ASSERT(0);
return STATUS_BUFFER_TOO_SMALL;
}
wmiAllData = (PWNODE_ALL_DATA) irpSp->Parameters.WMI.Buffer;
wnodeHeader = &wmiAllData->WnodeHeader;
//
// These fields should already be populated by WMI...
//
ASSERT(wnodeHeader->Flags & WNODE_FLAG_ALL_DATA);
ASSERT(IS_EQUAL_GUID(&wnodeHeader->Guid, &GUID_VERIFIER_WMI_INTERFACE));
//
// Fill in the time stamp before we lock the Irp log database.
//
KeQuerySystemTime(&wnodeHeader->TimeStamp);
//
// Lock the Irp Log Database so that we can query entries from it.
//
status = VfIrpLogLockDatabase(wmiDeviceExtension->SiloNumber);
if (!NT_SUCCESS(status)) {
return status;
}
status = VfIrpLogRetrieveWmiData(
wmiDeviceExtension->SiloNumber,
NULL,
&offsetInstanceNameOffsets,
&instanceCount,
&dataBlockOffset,
&totalRequiredSize
);
if (!NT_SUCCESS(status)) {
VfIrpLogUnlockDatabase(wmiDeviceExtension->SiloNumber);
return status;
}
totalRequiredSize += sizeof(WNODE_ALL_DATA);
if (totalRequiredSize > sizeSupplied) {
VfIrpLogUnlockDatabase(wmiDeviceExtension->SiloNumber);
//
// Per spec, write to a WNODE_TOO_SMALL structure into the buffer.
// Note that the structure does *not* follow wmiAllData! Rather,
// the same structure is interpretted two
//
//
wnodeHeader->Flags |= WNODE_FLAG_TOO_SMALL;
tooSmall = (PWNODE_TOO_SMALL) wmiAllData;
tooSmall->SizeNeeded = totalRequiredSize;
Irp->IoStatus.Information = sizeof(WNODE_TOO_SMALL);
//
// Yes, STATUS_SUCCESS is returned here. This is very asymetric when
// compared to IRP_MN_QUERY_REGINFO_EX.
//
return STATUS_SUCCESS;
} else if (instanceCount) {
status = VfIrpLogRetrieveWmiData(
wmiDeviceExtension->SiloNumber,
(PUCHAR) wmiAllData,
&offsetInstanceNameOffsets,
&instanceCount,
&dataBlockOffset,
&totalRequiredSize
);
}
VfIrpLogUnlockDatabase(wmiDeviceExtension->SiloNumber);
if (!NT_SUCCESS(status)) {
return status;
}
if (instanceCount) {
wnodeHeader->Flags |= WNODE_FLAG_ALL_DATA;
wnodeHeader->Flags &= ~WNODE_FLAG_FIXED_INSTANCE_SIZE;
wnodeHeader->BufferSize = totalRequiredSize;
wmiAllData->InstanceCount = instanceCount;
wmiAllData->DataBlockOffset = dataBlockOffset;
wmiAllData->OffsetInstanceNameOffsets = offsetInstanceNameOffsets;
} else {
totalRequiredSize = sizeof(WNODE_ALL_DATA);
wnodeHeader->BufferSize = totalRequiredSize;
wmiAllData->InstanceCount = 0;
wmiAllData->FixedInstanceSize = 0;
wmiAllData->DataBlockOffset = 0;
wmiAllData->OffsetInstanceNameOffsets = 0;
}
Irp->IoStatus.Information = totalRequiredSize;
return STATUS_SUCCESS;
}