windows-nt/Source/XPSP1/NT/base/ntos/verifier/vfwmi.c
2020-09-26 16:20:57 +08:00

321 lines
7.5 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
vfwmi.c
Abstract:
This module handles System Control Irp verification.
Author:
Adrian J. Oney (adriao) 20-Apr-1998
Environment:
Kernel mode
Revision History:
AdriaO 06/15/2000 - Seperated out from ntos\io\flunkirp.c
--*/
#include "vfdef.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, VfWmiInit)
#pragma alloc_text(PAGEVRFY, VfWmiDumpIrpStack)
#pragma alloc_text(PAGEVRFY, VfWmiVerifyNewRequest)
#pragma alloc_text(PAGEVRFY, VfWmiVerifyIrpStackDownward)
#pragma alloc_text(PAGEVRFY, VfWmiVerifyIrpStackUpward)
#pragma alloc_text(PAGEVRFY, VfWmiTestStartedPdoStack)
#endif
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg("PAGEVRFC")
#endif
const PCHAR WmiIrpNames[] = {
"IRP_MN_QUERY_ALL_DATA", // 0x00
"IRP_MN_QUERY_SINGLE_INSTANCE", // 0x01
"IRP_MN_CHANGE_SINGLE_INSTANCE", // 0x02
"IRP_MN_CHANGE_SINGLE_ITEM", // 0x03
"IRP_MN_ENABLE_EVENTS", // 0x04
"IRP_MN_DISABLE_EVENTS", // 0x05
"IRP_MN_ENABLE_COLLECTION", // 0x06
"IRP_MN_DISABLE_COLLECTION", // 0x07
"IRP_MN_REGINFO", // 0x08
"IRP_MN_EXECUTE_METHOD", // 0x09
NULL
};
#define MAX_NAMED_WMI_IRP 0x9
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg()
#endif // ALLOC_DATA_PRAGMA
VOID
VfWmiInit(
VOID
)
{
VfMajorRegisterHandlers(
IRP_MJ_SYSTEM_CONTROL,
VfWmiDumpIrpStack,
VfWmiVerifyNewRequest,
VfWmiVerifyIrpStackDownward,
VfWmiVerifyIrpStackUpward,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
VfWmiTestStartedPdoStack
);
}
VOID
FASTCALL
VfWmiVerifyNewRequest(
IN PIOV_REQUEST_PACKET IovPacket,
IN PDEVICE_OBJECT DeviceObject,
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
IN PIO_STACK_LOCATION IrpSp,
IN PIOV_STACK_LOCATION StackLocationData,
IN PVOID CallerAddress OPTIONAL
)
{
PIRP irp = IovPacket->TrackedIrp;
NTSTATUS currentStatus;
UNREFERENCED_PARAMETER (IrpSp);
UNREFERENCED_PARAMETER (IrpLastSp);
UNREFERENCED_PARAMETER (DeviceObject);
currentStatus = irp->IoStatus.Status;
//
// Verify new IRPs start out life accordingly
//
if (currentStatus!=STATUS_NOT_SUPPORTED) {
WDM_FAIL_ROUTINE((
DCERROR_WMI_IRP_BAD_INITIAL_STATUS,
DCPARAM_IRP + DCPARAM_ROUTINE,
CallerAddress,
irp
));
//
// Don't blame anyone else for this guy's mistake.
//
if (!NT_SUCCESS(currentStatus)) {
StackLocationData->Flags |= STACKFLAG_FAILURE_FORWARDED;
}
}
}
VOID
FASTCALL
VfWmiVerifyIrpStackDownward(
IN PIOV_REQUEST_PACKET IovPacket,
IN PDEVICE_OBJECT DeviceObject,
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
IN PIO_STACK_LOCATION IrpSp,
IN PIOV_STACK_LOCATION RequestHeadLocationData,
IN PIOV_STACK_LOCATION StackLocationData,
IN PVOID CallerAddress OPTIONAL
)
{
PIRP irp = IovPacket->TrackedIrp;
PDRIVER_OBJECT driverObject;
PIOV_SESSION_DATA iovSessionData;
UNREFERENCED_PARAMETER (IrpSp);
UNREFERENCED_PARAMETER (IrpLastSp);
iovSessionData = VfPacketGetCurrentSessionData(IovPacket);
//
// Verify the IRP was forwarded properly
//
if (iovSessionData->ForwardMethod == SKIPPED_A_DO) {
WDM_FAIL_ROUTINE((
DCERROR_SKIPPED_DEVICE_OBJECT,
DCPARAM_IRP + DCPARAM_ROUTINE,
CallerAddress,
irp
));
}
//
// For some IRP major's going down a stack, there *must* be a handler
//
driverObject = DeviceObject->DriverObject;
if (!IovUtilHasDispatchHandler(driverObject, IRP_MJ_SYSTEM_CONTROL)) {
RequestHeadLocationData->Flags |= STACKFLAG_BOGUS_IRP_TOUCHED;
WDM_FAIL_ROUTINE((
DCERROR_MISSING_DISPATCH_FUNCTION,
DCPARAM_IRP + DCPARAM_ROUTINE,
driverObject->DriverInit,
irp
));
StackLocationData->Flags |= STACKFLAG_NO_HANDLER;
}
}
VOID
FASTCALL
VfWmiVerifyIrpStackUpward(
IN PIOV_REQUEST_PACKET IovPacket,
IN PIO_STACK_LOCATION IrpSp,
IN PIOV_STACK_LOCATION RequestHeadLocationData,
IN PIOV_STACK_LOCATION StackLocationData,
IN BOOLEAN IsNewlyCompleted,
IN BOOLEAN RequestFinalized
)
{
PIRP irp;
BOOLEAN mustPassDown, isBogusIrp, isPdo;
PVOID routine;
UNREFERENCED_PARAMETER (RequestHeadLocationData);
UNREFERENCED_PARAMETER (RequestFinalized);
//
// Who'd we call for this one?
//
irp = IovPacket->TrackedIrp;
routine = StackLocationData->LastDispatch;
ASSERT(routine) ;
//
// If this "Request" has been "Completed", perform some checks
//
if (IsNewlyCompleted) {
//
// Remember bogosity...
//
isBogusIrp = (BOOLEAN)((IovPacket->Flags&TRACKFLAG_BOGUS)!=0);
//
// Is this a PDO?
//
isPdo = (BOOLEAN)((StackLocationData->Flags&STACKFLAG_REACHED_PDO)!=0);
//
// Was anything completed too early?
// A driver may outright fail almost anything but a bogus IRP
//
mustPassDown = (BOOLEAN)(!(StackLocationData->Flags&STACKFLAG_NO_HANDLER));
mustPassDown &= (!isPdo);
mustPassDown &= ((PDEVICE_OBJECT) IrpSp->Parameters.WMI.ProviderId != IrpSp->DeviceObject);
if (mustPassDown) {
WDM_FAIL_ROUTINE((
DCERROR_WMI_IRP_NOT_FORWARDED,
DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
routine,
irp,
IrpSp->Parameters.WMI.ProviderId
));
}
}
}
VOID
FASTCALL
VfWmiDumpIrpStack(
IN PIO_STACK_LOCATION IrpSp
)
{
DbgPrint("IRP_MJ_SYSTEM_CONTROL.");
if (IrpSp->MinorFunction <= MAX_NAMED_WMI_IRP) {
DbgPrint(WmiIrpNames[IrpSp->MinorFunction]);
} else if (IrpSp->MinorFunction == 0xFF) {
DbgPrint("IRP_MN_BOGUS");
} else {
DbgPrint("(Bogus)");
}
}
VOID
FASTCALL
VfWmiTestStartedPdoStack(
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Description:
As per the title, we are going to throw some IRPs at the stack to
see if they are handled correctly.
Returns:
Nothing
--*/
{
IO_STACK_LOCATION irpSp;
PAGED_CODE();
//
// Initialize the stack location to pass to IopSynchronousCall()
//
RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
if (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_SEND_BOGUS_WMI_IRPS)) {
//
// Send a bogus WMI IRP
//
// Note that we shouldn't be sending this IRP to any stack that doesn't
// terminate with a devnode. The WmiSystemControl export from WmiLib
// says "NotWmiIrp if it sees these. The callers should still pass down
// the IRP.
//
ASSERT(IovUtilIsPdo(PhysicalDeviceObject));
irpSp.MajorFunction = IRP_MJ_SYSTEM_CONTROL;
irpSp.MinorFunction = 0xff;
irpSp.Parameters.WMI.ProviderId = (ULONG_PTR) PhysicalDeviceObject;
VfIrpSendSynchronousIrp(
PhysicalDeviceObject,
&irpSp,
TRUE,
STATUS_NOT_SUPPORTED,
0,
NULL,
NULL
);
}
}