321 lines
7.5 KiB
C
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
|
|
);
|
|
}
|
|
}
|
|
|
|
|