|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
vfpnp.c
Abstract:
This module handles Pnp 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"
#include "vipnp.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, VfPnpInit)
#pragma alloc_text(PAGEVRFY, VfPnpDumpIrpStack)
#pragma alloc_text(PAGEVRFY, VfPnpVerifyNewRequest)
#pragma alloc_text(PAGEVRFY, VfPnpVerifyIrpStackDownward)
#pragma alloc_text(PAGEVRFY, VfPnpVerifyIrpStackUpward)
#pragma alloc_text(PAGEVRFY, VfPnpIsSystemRestrictedIrp)
#pragma alloc_text(PAGEVRFY, VfPnpAdvanceIrpStatus)
#pragma alloc_text(PAGEVRFY, VfPnpTestStartedPdoStack)
#endif
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg("PAGEVRFC")
#endif
const PCHAR PnPIrpNames[] = { "IRP_MN_START_DEVICE", // 0x00
"IRP_MN_QUERY_REMOVE_DEVICE", // 0x01
"IRP_MN_REMOVE_DEVICE - ", // 0x02
"IRP_MN_CANCEL_REMOVE_DEVICE", // 0x03
"IRP_MN_STOP_DEVICE", // 0x04
"IRP_MN_QUERY_STOP_DEVICE", // 0x05
"IRP_MN_CANCEL_STOP_DEVICE", // 0x06
"IRP_MN_QUERY_DEVICE_RELATIONS", // 0x07
"IRP_MN_QUERY_INTERFACE", // 0x08
"IRP_MN_QUERY_CAPABILITIES", // 0x09
"IRP_MN_QUERY_RESOURCES", // 0x0A
"IRP_MN_QUERY_RESOURCE_REQUIREMENTS", // 0x0B
"IRP_MN_QUERY_DEVICE_TEXT", // 0x0C
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS", // 0x0D
"INVALID_IRP_CODE", //
"IRP_MN_READ_CONFIG", // 0x0F
"IRP_MN_WRITE_CONFIG", // 0x10
"IRP_MN_EJECT", // 0x11
"IRP_MN_SET_LOCK", // 0x12
"IRP_MN_QUERY_ID", // 0x13
"IRP_MN_QUERY_PNP_DEVICE_STATE", // 0x14
"IRP_MN_QUERY_BUS_INFORMATION", // 0x15
"IRP_MN_DEVICE_USAGE_NOTIFICATION", // 0x16
"IRP_MN_SURPRISE_REMOVAL", // 0x17
"IRP_MN_QUERY_LEGACY_BUS_INFORMATION", // 0x18
NULL };
#define MAX_NAMED_PNP_IRP 0x18
#include <initguid.h>
DEFINE_GUID( GUID_BOGUS_INTERFACE, 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg()
#endif // ALLOC_DATA_PRAGMA
VOID VfPnpInit( VOID ) { VfMajorRegisterHandlers( IRP_MJ_PNP, VfPnpDumpIrpStack, VfPnpVerifyNewRequest, VfPnpVerifyIrpStackDownward, VfPnpVerifyIrpStackUpward, VfPnpIsSystemRestrictedIrp, VfPnpAdvanceIrpStatus, NULL, NULL, NULL, NULL, VfPnpTestStartedPdoStack ); }
VOID FASTCALL VfPnpVerifyNewRequest( 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; NTSTATUS currentStatus; PDEVICE_OBJECT possiblePdo; PDEVICE_CAPABILITIES deviceCapabilities;
UNREFERENCED_PARAMETER (IrpLastSp);
irp = IovPacket->TrackedIrp; currentStatus = irp->IoStatus.Status;
//
// Verify new IRPs start out life accordingly
//
if (currentStatus!=STATUS_NOT_SUPPORTED) {
//
// This is a special WDM (9x) compatibility hack.
//
if ((IrpSp->MinorFunction != IRP_MN_FILTER_RESOURCE_REQUIREMENTS) && (!(IovPacket->Flags & TRACKFLAG_BOGUS))) {
WDM_FAIL_ROUTINE(( DCERROR_PNP_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; } }
if (IrpSp->MinorFunction == IRP_MN_QUERY_CAPABILITIES) {
deviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
if (VfUtilIsMemoryRangeReadable(deviceCapabilities, sizeof(DEVICE_CAPABILITIES), VFMP_INSTANT_NONPAGED)) {
//
// Verify fields are initialized correctly
//
if (deviceCapabilities->Version < 1) {
//
// Whoops, it didn't initialize the version correctly!
//
WDM_FAIL_ROUTINE(( DCERROR_PNP_QUERY_CAP_BAD_VERSION, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, irp )); }
if (deviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES)) {
//
// Whoops, it didn't initialize the size field correctly!
//
WDM_FAIL_ROUTINE(( DCERROR_PNP_QUERY_CAP_BAD_SIZE, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, irp )); }
if (deviceCapabilities->Address != (ULONG) -1) {
//
// Whoops, it didn't initialize the address field correctly!
//
WDM_FAIL_ROUTINE(( DCERROR_PNP_QUERY_CAP_BAD_ADDRESS, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, irp )); }
if (deviceCapabilities->UINumber != (ULONG) -1) {
//
// Whoops, it didn't initialize the UI number field correctly!
//
WDM_FAIL_ROUTINE(( DCERROR_PNP_QUERY_CAP_BAD_UI_NUM, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, irp )); } } }
//
// If this is a target device relation IRP, verify the appropriate
// object will be referenced.
//
if (!VfSettingsIsOptionEnabled(IovPacket->VerifierSettings, VERIFIER_OPTION_TEST_TARGET_REFCOUNT)) {
return; }
if ((IrpSp->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS)&& (IrpSp->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)) {
IovUtilGetBottomDeviceObject(DeviceObject, &possiblePdo);
if (IovUtilIsPdo(possiblePdo)) {
if (StackLocationData->ReferencingObject == NULL) {
//
// Got'm!
//
StackLocationData->Flags |= STACKFLAG_CHECK_FOR_REFERENCE; StackLocationData->ReferencingObject = possiblePdo; StackLocationData->ReferencingCount = ObvUtilStartObRefMonitoring(possiblePdo); IovPacket->RefTrackingCount++; } }
//
// Free our reference (we will have one if we are snapshotting anyway)
//
ObDereferenceObject(possiblePdo); } }
VOID FASTCALL VfPnpVerifyIrpStackDownward( 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; NTSTATUS currentStatus, lastStatus; BOOLEAN statusChanged; PDRIVER_OBJECT driverObject; PIOV_SESSION_DATA iovSessionData; HOW_PROCESSED howProcessed; VF_DEVOBJ_TYPE devObjType;
UNREFERENCED_PARAMETER (StackLocationData);
if (!IovUtilIsWdmStack(DeviceObject)) {
return; }
irp = IovPacket->TrackedIrp; currentStatus = irp->IoStatus.Status; lastStatus = RequestHeadLocationData->LastStatusBlock.Status; statusChanged = (BOOLEAN)(currentStatus != lastStatus); iovSessionData = VfPacketGetCurrentSessionData(IovPacket);
//
// Verify the IRP was forwarded properly
//
switch(iovSessionData->ForwardMethod) {
case SKIPPED_A_DO:
WDM_FAIL_ROUTINE(( DCERROR_SKIPPED_DEVICE_OBJECT, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, irp ));
break;
case STARTED_TOP_OF_STACK: case FORWARDED_TO_NEXT_DO:
//
// Perfectly normal
//
break;
case STARTED_INSIDE_STACK: //
// Probably an Internal irp (query cap's, etc)
//
break;
case CHANGED_STACKS_MID_STACK: case CHANGED_STACKS_AT_BOTTOM:
//
// ADRIAO N.B. - Ensure drivers aren't rerouting certain IRPs off
// PnP stacks.
//
#if 0
ASSERT(0); #endif
break ; }
//
// For some IRP major's going down a stack, there *must* be a handler
//
driverObject = DeviceObject->DriverObject;
if (!IovUtilHasDispatchHandler(driverObject, IRP_MJ_PNP)) {
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; }
//
// The following is only executed if we are not a new IRP...
//
if (IrpLastSp == NULL) { return; }
//
// The only legit failure code to pass down is STATUS_NOT_SUPPORTED
//
if ((!NT_SUCCESS(currentStatus)) && (currentStatus != STATUS_NOT_SUPPORTED) && (!(RequestHeadLocationData->Flags & STACKFLAG_FAILURE_FORWARDED))) {
WDM_FAIL_ROUTINE(( DCERROR_PNP_FAILURE_FORWARDED, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, irp ));
//
// Don't blame anyone else for this driver's mistakes...
//
RequestHeadLocationData->Flags |= STACKFLAG_FAILURE_FORWARDED; }
//
// Status of a PnP IRP may not be converted to
// STATUS_NOT_SUPPORTED on the way down
//
if ((currentStatus == STATUS_NOT_SUPPORTED)&&statusChanged&& (!(RequestHeadLocationData->Flags & STACKFLAG_FAILURE_FORWARDED))) {
WDM_FAIL_ROUTINE(( DCERROR_PNP_IRP_STATUS_RESET, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, irp ));
//
// Don't blame anyone else for this driver's mistakes...
//
RequestHeadLocationData->Flags |= STACKFLAG_FAILURE_FORWARDED; }
//
// Some IRPs FDO's are required to handle before passing down. And some
// IRPs should not be touched by the FDO. Assert it is so...
//
if ((!iovSessionData->DeviceLastCalled) || (!IovUtilIsDesignatedFdo(iovSessionData->DeviceLastCalled))) {
return; }
if (currentStatus != STATUS_NOT_SUPPORTED) {
howProcessed = DEFINITELY_PROCESSED;
} else if (IrpSp->CompletionRoutine == NULL) {
howProcessed = NOT_PROCESSED;
} else {
howProcessed = POSSIBLY_PROCESSED; }
//
// How could a Raw FDO (aka a PDO) get here? Well, a PDO could forward
// to another stack if he's purposely reserved enough stack locations
// for that eventuality.
//
devObjType = IovUtilIsRawPdo(iovSessionData->DeviceLastCalled) ? VF_DEVOBJ_PDO : VF_DEVOBJ_FDO;
ViPnpVerifyMinorWasProcessedProperly( irp, IrpSp, devObjType, iovSessionData->VerifierSettings, howProcessed, CallerAddress ); }
VOID FASTCALL VfPnpVerifyIrpStackUpward( 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; NTSTATUS currentStatus; BOOLEAN mustPassDown, isBogusIrp, isPdo, touchable; PVOID routine; LONG referencesTaken; PDEVICE_RELATIONS deviceRelations; PIOV_SESSION_DATA iovSessionData; ULONG index, swapIndex; PDEVICE_OBJECT swapObject, lowerDevObj; HOW_PROCESSED howProcessed;
UNREFERENCED_PARAMETER (RequestFinalized);
if (!IovUtilIsWdmStack(IrpSp->DeviceObject)) {
return; }
isPdo = FALSE;
irp = IovPacket->TrackedIrp; currentStatus = irp->IoStatus.Status; iovSessionData = VfPacketGetCurrentSessionData(IovPacket);
//
// Who'd we call for this one?
//
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 &= (isBogusIrp || NT_SUCCESS(currentStatus) || (currentStatus == STATUS_NOT_SUPPORTED)); if (mustPassDown) {
//
// Print appropriate error message
//
if (IovPacket->Flags&TRACKFLAG_BOGUS) {
WDM_FAIL_ROUTINE(( DCERROR_BOGUS_PNP_IRP_COMPLETED, DCPARAM_IRP + DCPARAM_ROUTINE, routine, irp ));
} else if (NT_SUCCESS(currentStatus)) {
WDM_FAIL_ROUTINE(( DCERROR_SUCCESSFUL_PNP_IRP_NOT_FORWARDED, DCPARAM_IRP + DCPARAM_ROUTINE, routine, irp ));
} else if (currentStatus == STATUS_NOT_SUPPORTED) {
WDM_FAIL_ROUTINE(( DCERROR_UNTOUCHED_PNP_IRP_NOT_FORWARDED, DCPARAM_IRP + DCPARAM_ROUTINE, routine, irp )); } } }
//
// Did the PDO respond to it's required set of IRPs?
//
if (IsNewlyCompleted && isPdo) {
if (currentStatus != STATUS_NOT_SUPPORTED) {
howProcessed = DEFINITELY_PROCESSED;
} else {
howProcessed = POSSIBLY_PROCESSED; }
ViPnpVerifyMinorWasProcessedProperly( irp, IrpSp, VF_DEVOBJ_PDO, iovSessionData->VerifierSettings, howProcessed, routine ); }
//
// Was TargetDeviceRelation implemented correctly?
//
if (IsNewlyCompleted && (RequestHeadLocationData->Flags&STACKFLAG_CHECK_FOR_REFERENCE)) {
ASSERT ((IrpSp->MajorFunction == IRP_MJ_PNP)&& (IrpSp->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS)&& (IrpSp->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation));
ASSERT(RequestHeadLocationData->ReferencingObject); ASSERT(IovPacket->RefTrackingCount);
referencesTaken = ObvUtilStopObRefMonitoring( RequestHeadLocationData->ReferencingObject, RequestHeadLocationData->ReferencingCount );
IovPacket->RefTrackingCount--; RequestHeadLocationData->ReferencingObject = NULL;
RequestHeadLocationData->Flags &= ~STACKFLAG_CHECK_FOR_REFERENCE;
if (NT_SUCCESS(currentStatus)&&(!referencesTaken)) {
WDM_FAIL_ROUTINE(( DCERROR_TARGET_RELATION_NEEDS_REF, DCPARAM_IRP + DCPARAM_ROUTINE, routine, irp )); } }
//
// Did anyone stomp the status erroneously?
//
if ((currentStatus == STATUS_NOT_SUPPORTED) && (!(RequestHeadLocationData->Flags & STACKFLAG_FAILURE_FORWARDED)) && (currentStatus != RequestHeadLocationData->LastStatusBlock.Status)) {
//
// Status of a PnP or Power IRP may not be converted from success to
// STATUS_NOT_SUPPORTED on the way down.
//
WDM_FAIL_ROUTINE(( DCERROR_PNP_IRP_STATUS_RESET, DCPARAM_IRP + DCPARAM_ROUTINE, routine, irp ));
//
// Don't blame anyone else for this driver's mistakes...
//
RequestHeadLocationData->Flags |= STACKFLAG_FAILURE_FORWARDED; }
switch(IrpSp->MinorFunction) {
case IRP_MN_QUERY_DEVICE_RELATIONS: //
// Rotate device relations if so ordered.
//
if ((RequestHeadLocationData == StackLocationData) && ((IrpSp->Parameters.QueryDeviceRelations.Type == BusRelations) || (IrpSp->Parameters.QueryDeviceRelations.Type == RemovalRelations) || (IrpSp->Parameters.QueryDeviceRelations.Type == EjectionRelations)) && VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_SCRAMBLE_RELATIONS)) {
if (NT_SUCCESS(currentStatus) && irp->IoStatus.Information) {
deviceRelations = (PDEVICE_RELATIONS) irp->IoStatus.Information;
touchable = VfUtilIsMemoryRangeReadable( deviceRelations, (sizeof(DEVICE_RELATIONS)-sizeof(PVOID)), VFMP_INSTANT_NONPAGED );
if (!touchable) {
break; }
touchable = VfUtilIsMemoryRangeReadable( deviceRelations, (sizeof(DEVICE_RELATIONS)-(deviceRelations->Count-1)*sizeof(PVOID)), VFMP_INSTANT_NONPAGED );
if (!touchable) {
break; }
if (deviceRelations->Count > 1) {
//
// Scramble the relation list by random swapping.
//
for(index = 0; index < (deviceRelations->Count+1)/2; index++) {
swapIndex = VfRandomGetNumber(1, deviceRelations->Count-1);
swapObject = deviceRelations->Objects[0]; deviceRelations->Objects[0] = deviceRelations->Objects[swapIndex]; deviceRelations->Objects[swapIndex] = swapObject; } } } }
break;
case IRP_MN_SURPRISE_REMOVAL: if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_MONITOR_REMOVES)) {
//
// Verify driver didn't do an IoDetachDevice upon recieving the
// SURPRISE_REMOVAL IRP.
//
IovUtilGetLowerDeviceObject(IrpSp->DeviceObject, &lowerDevObj);
if (lowerDevObj) {
ObDereferenceObject(lowerDevObj);
} else if (!IovUtilIsPdo(IrpSp->DeviceObject)) {
WDM_FAIL_ROUTINE(( DCERROR_DETACHED_IN_SURPRISE_REMOVAL, DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ, routine, iovSessionData->BestVisibleIrp, IrpSp->DeviceObject )); }
//
// Verify driver didn't do an IoDeleteDevice upon recieving the
// SURPRISE_REMOVAL IRP.
//
if (IovUtilIsDeviceObjectMarked(IrpSp->DeviceObject, MARKTYPE_DELETED)) {
WDM_FAIL_ROUTINE(( DCERROR_DELETED_IN_SURPRISE_REMOVAL, DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ, routine, iovSessionData->BestVisibleIrp, IrpSp->DeviceObject )); } }
break;
default: break; } }
VOID FASTCALL VfPnpDumpIrpStack( IN PIO_STACK_LOCATION IrpSp ) { DbgPrint("IRP_MJ_PNP.");
if (IrpSp->MinorFunction<=MAX_NAMED_PNP_IRP) {
DbgPrint(PnPIrpNames[IrpSp->MinorFunction]); } else if (IrpSp->MinorFunction==0xFF) {
DbgPrint("IRP_MN_BOGUS"); } else {
DbgPrint("(Bogus)"); }
switch(IrpSp->MinorFunction) { case IRP_MN_QUERY_DEVICE_RELATIONS:
switch(IrpSp->Parameters.QueryDeviceRelations.Type) { case BusRelations: DbgPrint("(BusRelations)"); break; case EjectionRelations: DbgPrint("(EjectionRelations)"); break; case PowerRelations: DbgPrint("(PowerRelations)"); break; case RemovalRelations: DbgPrint("(RemovalRelations)"); break; case TargetDeviceRelation: DbgPrint("(TargetDeviceRelation)"); break; default: DbgPrint("(Bogus)"); break; } break; case IRP_MN_QUERY_INTERFACE: break; case IRP_MN_QUERY_DEVICE_TEXT: switch(IrpSp->Parameters.QueryId.IdType) { case DeviceTextDescription: DbgPrint("(DeviceTextDescription)"); break; case DeviceTextLocationInformation: DbgPrint("(DeviceTextLocationInformation)"); break; default: DbgPrint("(Bogus)"); break; } break; case IRP_MN_WRITE_CONFIG: case IRP_MN_READ_CONFIG: DbgPrint("(WhichSpace=%x, Buffer=%x, Offset=%x, Length=%x)", IrpSp->Parameters.ReadWriteConfig.WhichSpace, IrpSp->Parameters.ReadWriteConfig.Buffer, IrpSp->Parameters.ReadWriteConfig.Offset, IrpSp->Parameters.ReadWriteConfig.Length ); break; case IRP_MN_SET_LOCK: if (IrpSp->Parameters.SetLock.Lock) DbgPrint("(True)"); else DbgPrint("(False)"); break; case IRP_MN_QUERY_ID: switch(IrpSp->Parameters.QueryId.IdType) { case BusQueryDeviceID: DbgPrint("(BusQueryDeviceID)"); break; case BusQueryHardwareIDs: DbgPrint("(BusQueryHardwareIDs)"); break; case BusQueryCompatibleIDs: DbgPrint("(BusQueryCompatibleIDs)"); break; case BusQueryInstanceID: DbgPrint("(BusQueryInstanceID)"); break; default: DbgPrint("(Bogus)"); break; } break; case IRP_MN_QUERY_BUS_INFORMATION: break; case IRP_MN_DEVICE_USAGE_NOTIFICATION: switch(IrpSp->Parameters.UsageNotification.Type) { case DeviceUsageTypeUndefined: DbgPrint("(DeviceUsageTypeUndefined"); break; case DeviceUsageTypePaging: DbgPrint("(DeviceUsageTypePaging"); break; case DeviceUsageTypeHibernation: DbgPrint("(DeviceUsageTypeHibernation"); break; case DeviceUsageTypeDumpFile: DbgPrint("(DeviceUsageTypeDumpFile"); break; default: DbgPrint("(Bogus)"); break; } if (IrpSp->Parameters.UsageNotification.InPath) { DbgPrint(", InPath=TRUE)"); } else { DbgPrint(", InPath=FALSE)"); } break; case IRP_MN_QUERY_LEGACY_BUS_INFORMATION: break; default: break; } }
BOOLEAN FASTCALL VfPnpIsSystemRestrictedIrp( IN PIO_STACK_LOCATION IrpSp ) { switch(IrpSp->MinorFunction) { case IRP_MN_START_DEVICE: case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_REMOVE_DEVICE: case IRP_MN_CANCEL_REMOVE_DEVICE: case IRP_MN_STOP_DEVICE: case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE: case IRP_MN_SURPRISE_REMOVAL: return TRUE;
case IRP_MN_QUERY_DEVICE_RELATIONS: switch(IrpSp->Parameters.QueryDeviceRelations.Type) { case BusRelations: case PowerRelations: return TRUE; case RemovalRelations: case EjectionRelations: case TargetDeviceRelation: return FALSE; default: break; } break; case IRP_MN_QUERY_INTERFACE: case IRP_MN_QUERY_CAPABILITIES: return FALSE; case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: case IRP_MN_QUERY_DEVICE_TEXT: return TRUE; case IRP_MN_READ_CONFIG: case IRP_MN_WRITE_CONFIG: return FALSE; case IRP_MN_EJECT: case IRP_MN_SET_LOCK: case IRP_MN_QUERY_RESOURCES: case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: case IRP_MN_QUERY_LEGACY_BUS_INFORMATION: return TRUE; case IRP_MN_QUERY_ID: switch(IrpSp->Parameters.QueryId.IdType) {
case BusQueryHardwareIDs: case BusQueryCompatibleIDs: return TRUE; case BusQueryDeviceID: case BusQueryInstanceID: return FALSE; default: break; } break; case IRP_MN_QUERY_PNP_DEVICE_STATE: case IRP_MN_QUERY_BUS_INFORMATION: return TRUE; case IRP_MN_DEVICE_USAGE_NOTIFICATION: return FALSE; default: break; }
return TRUE; }
BOOLEAN FASTCALL VfPnpAdvanceIrpStatus( IN PIO_STACK_LOCATION IrpSp, IN NTSTATUS OriginalStatus, IN OUT NTSTATUS *StatusToAdvance ) /*++
Description:
Given an IRP stack pointer, is it legal to change the status for debug-ability? If so, this function determines what the new status should be. Note that for each stack location, this function is iterated over n times where n is equal to the number of drivers who IoSkip'd this location.
Arguments:
IrpSp - Current stack right after complete for the given stack location, but before the completion routine for the stack location above has been called.
OriginalStatus - The status of the IRP at the time listed above. Does not change over iteration per skipping driver.
StatusToAdvance - Pointer to the current status that should be updated.
Return Value:
TRUE if the status has been adjusted, FALSE otherwise (in this case StatusToAdvance is untouched).
--*/ { UNREFERENCED_PARAMETER (IrpSp);
if (((ULONG) OriginalStatus) >= 256) {
return FALSE; }
(*StatusToAdvance)++; if ((*StatusToAdvance) == STATUS_PENDING) { (*StatusToAdvance)++; }
return TRUE; }
VOID FASTCALL VfPnpTestStartedPdoStack( 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; PDEVICE_RELATIONS targetDeviceRelationList; INTERFACE interface; NTSTATUS status;
PAGED_CODE();
//
// Initialize the stack location to pass to IopSynchronousCall()
//
RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
//
// send lots of bogus PNP IRPs
//
irpSp.MajorFunction = IRP_MJ_PNP; irpSp.MinorFunction = 0xff; VfIrpSendSynchronousIrp( PhysicalDeviceObject, &irpSp, TRUE, STATUS_NOT_SUPPORTED, 0, NULL, NULL );
irpSp.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS; irpSp.Parameters.QueryDeviceRelations.Type = (DEVICE_RELATION_TYPE) -1; VfIrpSendSynchronousIrp( PhysicalDeviceObject, &irpSp, TRUE, STATUS_NOT_SUPPORTED, 0, NULL, NULL );
if (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_RELATION_IGNORANCE_TEST)) {
irpSp.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS; irpSp.Parameters.QueryDeviceRelations.Type = (DEVICE_RELATION_TYPE) -1; VfIrpSendSynchronousIrp( PhysicalDeviceObject, &irpSp, TRUE, STATUS_NOT_SUPPORTED, (ULONG_PTR) -1, NULL, NULL ); }
irpSp.MinorFunction = IRP_MN_QUERY_DEVICE_TEXT; irpSp.Parameters.QueryDeviceText.DeviceTextType = (DEVICE_TEXT_TYPE) -1; VfIrpSendSynchronousIrp( PhysicalDeviceObject, &irpSp, TRUE, STATUS_NOT_SUPPORTED, 0, NULL, NULL );
irpSp.MinorFunction = IRP_MN_QUERY_ID; irpSp.Parameters.QueryId.IdType = (BUS_QUERY_ID_TYPE) -1; VfIrpSendSynchronousIrp( PhysicalDeviceObject, &irpSp, TRUE, STATUS_NOT_SUPPORTED, 0, NULL, NULL ); /*
irpSp.MinorFunction = IRP_MN_QUERY_ID; irpSp.Parameters.QueryId.IdType = (BUS_QUERY_ID_TYPE) -1; VfIrpSendSynchronousIrp( PhysicalDeviceObject, &irpSp, TRUE, STATUS_SUCCESS, (ULONG_PTR) -1, NULL, NULL ); */ //
// Target device relation test...
//
irpSp.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS; irpSp.Parameters.QueryDeviceRelations.Type = TargetDeviceRelation; targetDeviceRelationList = NULL; if (VfIrpSendSynchronousIrp( PhysicalDeviceObject, &irpSp, FALSE, STATUS_NOT_SUPPORTED, 0, (ULONG_PTR *) &targetDeviceRelationList, &status )) {
if (NT_SUCCESS(status)) {
ASSERT(targetDeviceRelationList); ASSERT(targetDeviceRelationList->Count == 1); ASSERT(targetDeviceRelationList->Objects[0]); ObDereferenceObject(targetDeviceRelationList->Objects[0]); ExFreePool(targetDeviceRelationList);
} else {
//
// IRP was asserted in other code. We need to do nothing here...
//
} }
RtlZeroMemory(&interface, sizeof(INTERFACE)); irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE; irpSp.Parameters.QueryInterface.Size = (USHORT)-1; irpSp.Parameters.QueryInterface.Version = 1; irpSp.Parameters.QueryInterface.InterfaceType = &GUID_BOGUS_INTERFACE; irpSp.Parameters.QueryInterface.Interface = &interface; irpSp.Parameters.QueryInterface.InterfaceSpecificData = (PVOID) -1; VfIrpSendSynchronousIrp( PhysicalDeviceObject, &irpSp, TRUE, STATUS_NOT_SUPPORTED, 0, NULL, NULL );
RtlZeroMemory(&interface, sizeof(INTERFACE)); irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE; irpSp.Parameters.QueryInterface.Size = (USHORT)-1; irpSp.Parameters.QueryInterface.Version = 1; irpSp.Parameters.QueryInterface.InterfaceType = &GUID_BOGUS_INTERFACE; irpSp.Parameters.QueryInterface.Interface = &interface; irpSp.Parameters.QueryInterface.InterfaceSpecificData = (PVOID) -1; VfIrpSendSynchronousIrp( PhysicalDeviceObject, &irpSp, TRUE, STATUS_SUCCESS, 0, NULL, NULL );
//
// We could do more chaff here. For example, bogus device usage
// notifications, etc...
//
}
VOID ViPnpVerifyMinorWasProcessedProperly( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp, IN VF_DEVOBJ_TYPE DevObjType, IN PVERIFIER_SETTINGS_SNAPSHOT VerifierSnapshot, IN HOW_PROCESSED HowProcessed, IN PVOID CallerAddress ) { PDEVICE_OBJECT relationObject, relationPdo; PDEVICE_RELATIONS deviceRelations; BOOLEAN touchable; ULONG index;
switch(IrpSp->MinorFunction) {
case IRP_MN_SURPRISE_REMOVAL:
if ((HowProcessed != NOT_PROCESSED) || (!VfSettingsIsOptionEnabled(VerifierSnapshot, VERIFIER_OPTION_EXTENDED_REQUIRED_IRPS))) {
break; }
WDM_FAIL_ROUTINE(( DCERROR_PNP_IRP_NEEDS_HANDLING, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, Irp ));
break;
case IRP_MN_START_DEVICE: case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_REMOVE_DEVICE: case IRP_MN_STOP_DEVICE: case IRP_MN_QUERY_STOP_DEVICE:
//
// The driver must set the status as appropriate.
//
if (HowProcessed != NOT_PROCESSED) {
break; }
WDM_FAIL_ROUTINE(( DCERROR_PNP_IRP_NEEDS_HANDLING, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, Irp ));
break;
case IRP_MN_CANCEL_REMOVE_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE:
//
// The driver must set the status of these IRPs to something
// successful!
//
if (HowProcessed == NOT_PROCESSED) {
WDM_FAIL_ROUTINE(( DCERROR_PNP_IRP_NEEDS_HANDLING, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, Irp ));
} else if ((HowProcessed == DEFINITELY_PROCESSED) && (!NT_SUCCESS(Irp->IoStatus.Status)) && (VfSettingsIsOptionEnabled(VerifierSnapshot, VERIFIER_OPTION_EXTENDED_REQUIRED_IRPS))) {
WDM_FAIL_ROUTINE(( DCERROR_NON_FAILABLE_IRP, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, Irp )); }
break;
case IRP_MN_QUERY_DEVICE_RELATIONS: switch(IrpSp->Parameters.QueryDeviceRelations.Type) { case TargetDeviceRelation:
if (DevObjType != VF_DEVOBJ_PDO) {
if (HowProcessed != DEFINITELY_PROCESSED) {
break; }
WDM_FAIL_ROUTINE(( DCERROR_PNP_IRP_HANDS_OFF, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, Irp ));
} else {
if (HowProcessed == NOT_PROCESSED) {
WDM_FAIL_ROUTINE(( DCERROR_PNP_IRP_NEEDS_PDO_HANDLING, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, Irp ));
} else if (NT_SUCCESS(Irp->IoStatus.Status)) {
if (Irp->IoStatus.Information == (ULONG_PTR) NULL) {
WDM_FAIL_ROUTINE(( DCERROR_TARGET_RELATION_LIST_EMPTY, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, Irp )); }
//
// ADRIAO N.B. - I could also assert the Information
// matches DeviceObject.
//
} }
break;
case BusRelations: case PowerRelations: case RemovalRelations:
case EjectionRelations:
//
// Ejection relations are usually a bad idea for
// FDO's - As stopping a device implies powerdown,
// RemovalRelations are usually the proper response
// for an FDO. One exception is ISAPNP, as PCI-to-ISA
// bridges can never be powered down.
//
default: break; }
//
// Verify we got back PDO's.
//
if (!VfSettingsIsOptionEnabled( VerifierSnapshot, VERIFIER_OPTION_EXAMINE_RELATION_PDOS)) {
break; }
if ((!NT_SUCCESS(Irp->IoStatus.Status)) || (((PVOID) Irp->IoStatus.Information) == NULL)) {
break; }
switch(IrpSp->Parameters.QueryDeviceRelations.Type) { case TargetDeviceRelation: case BusRelations: case PowerRelations: case RemovalRelations: case EjectionRelations:
deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
touchable = VfUtilIsMemoryRangeReadable( deviceRelations, (sizeof(DEVICE_RELATIONS)-sizeof(PVOID)), VFMP_INSTANT_NONPAGED );
if (!touchable) {
break; }
touchable = VfUtilIsMemoryRangeReadable( deviceRelations, (sizeof(DEVICE_RELATIONS)-(deviceRelations->Count-1)*sizeof(PVOID)), VFMP_INSTANT_NONPAGED );
if (!touchable) {
break; }
for(index = 0; index < deviceRelations->Count; index++) {
relationObject = deviceRelations->Objects[index];
if (IovUtilIsDeviceObjectMarked(relationObject, MARKTYPE_RELATION_PDO_EXAMINED)) {
continue; }
IovUtilGetBottomDeviceObject(relationObject, &relationPdo);
if (relationPdo != relationObject) {
//
// Fail the appropriate driver.
//
WDM_FAIL_ROUTINE(( DCERROR_NON_PDO_RETURNED_IN_RELATION, DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ, CallerAddress, Irp, relationObject )); }
//
// Don't blame the next driver that handles the IRP.
//
IovUtilMarkDeviceObject( relationObject, MARKTYPE_RELATION_PDO_EXAMINED );
//
// Drop ref
//
ObDereferenceObject(relationPdo); }
break; }
break; case IRP_MN_QUERY_INTERFACE: case IRP_MN_QUERY_CAPABILITIES: case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: break; case IRP_MN_QUERY_DEVICE_TEXT: case IRP_MN_READ_CONFIG: case IRP_MN_WRITE_CONFIG: case IRP_MN_EJECT: case IRP_MN_SET_LOCK: case IRP_MN_QUERY_RESOURCES: case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: case IRP_MN_QUERY_BUS_INFORMATION:
if ((DevObjType == VF_DEVOBJ_PDO) || (HowProcessed != DEFINITELY_PROCESSED)) {
break; }
WDM_FAIL_ROUTINE(( DCERROR_PNP_IRP_HANDS_OFF, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, Irp ));
break;
case IRP_MN_QUERY_ID: switch(IrpSp->Parameters.QueryId.IdType) {
case BusQueryDeviceID: case BusQueryHardwareIDs: case BusQueryCompatibleIDs: case BusQueryInstanceID:
if ((DevObjType == VF_DEVOBJ_PDO) || (HowProcessed != DEFINITELY_PROCESSED)) {
break; }
WDM_FAIL_ROUTINE(( DCERROR_PNP_IRP_HANDS_OFF, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, Irp ));
break; default: break; } break; case IRP_MN_QUERY_PNP_DEVICE_STATE: case IRP_MN_QUERY_LEGACY_BUS_INFORMATION: break; case IRP_MN_DEVICE_USAGE_NOTIFICATION:
if ((HowProcessed != NOT_PROCESSED) || (!VfSettingsIsOptionEnabled(VerifierSnapshot, VERIFIER_OPTION_EXTENDED_REQUIRED_IRPS))) {
break; }
WDM_FAIL_ROUTINE(( DCERROR_PNP_IRP_NEEDS_HANDLING, DCPARAM_IRP + DCPARAM_ROUTINE, CallerAddress, Irp ));
break;
default: break; }
}
|