930 lines
21 KiB
C
930 lines
21 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
iovutil.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module implements various utilities required to do driver verification.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Adrian J. Oney (adriao) 20-Apr-1998
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Kernel mode
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
AdriaO 02/10/2000 - Seperated out from ntos\io\trackirp.c
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "iop.h"
|
||
|
#include "pnpi.h"
|
||
|
#include "arbiter.h"
|
||
|
#include "dockintf.h"
|
||
|
#include "pnprlist.h"
|
||
|
#include "pnpiop.h"
|
||
|
#include "iovputil.h"
|
||
|
|
||
|
#ifdef ALLOC_PRAGMA
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilInit)
|
||
|
//#pragma alloc_text(PAGEVRFY, IovUtilMarkDeviceObject)
|
||
|
//#pragma alloc_text(PAGEVRFY, IovUtilMarkStack)
|
||
|
//#pragma alloc_text(PAGEVRFY, IovUtilWatermarkIrp)
|
||
|
|
||
|
#ifndef NO_VERIFIER
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilGetLowerDeviceObject)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilGetBottomDeviceObject)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilGetUpperDeviceObject)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilIsVerifiedDeviceStack)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilFlushStackCache)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilFlushVerifierDriverListCache)
|
||
|
#pragma alloc_text(PAGEVRFY, IovpUtilFlushListCallback)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilIsPdo)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilIsWdmStack)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilHasDispatchHandler)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilIsInFdoStack)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilIsRawPdo)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilIsDesignatedFdo)
|
||
|
#pragma alloc_text(PAGEVRFY, IovUtilIsDeviceObjectMarked)
|
||
|
#endif // NO_VERIFIER
|
||
|
|
||
|
#endif // ALLOC_PRAGMA
|
||
|
|
||
|
//
|
||
|
// This entire implementation is specific to the verifier
|
||
|
//
|
||
|
#ifndef NO_VERIFIER
|
||
|
|
||
|
BOOLEAN IovUtilVerifierEnabled = FALSE;
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilInit(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
IovUtilVerifierEnabled = TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilGetLowerDeviceObject(
|
||
|
IN PDEVICE_OBJECT UpperDeviceObject,
|
||
|
OUT PDEVICE_OBJECT *LowerDeviceObject
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine returns the device object below the passed in parameter. In
|
||
|
other words, it is the inverse of DeviceObject->AttachedDevice. Note that
|
||
|
the returned device object is referenced by this routine.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
UpperDeviceObject - Device object to look beneath.
|
||
|
LowerDeviceObject - Receives device object beneath UpperDeviceObject, or
|
||
|
NULL if none.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDEVOBJ_EXTENSION deviceExtension;
|
||
|
PDEVICE_OBJECT deviceAttachedTo;
|
||
|
KIRQL irql;
|
||
|
|
||
|
irql = KeAcquireQueuedSpinLock( LockQueueIoDatabaseLock );
|
||
|
|
||
|
deviceExtension = UpperDeviceObject->DeviceObjectExtension;
|
||
|
deviceAttachedTo = deviceExtension->AttachedTo;
|
||
|
|
||
|
if (deviceAttachedTo) {
|
||
|
|
||
|
ObReferenceObject(deviceAttachedTo);
|
||
|
}
|
||
|
|
||
|
KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
|
||
|
|
||
|
*LowerDeviceObject = deviceAttachedTo;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilGetBottomDeviceObject(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
OUT PDEVICE_OBJECT *BottomDeviceObject
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine returns the device object at the bottom of the stack in which
|
||
|
the passed in parameter is a member. In other words, it is the inverse of
|
||
|
IoGetAttachedDeviceReference. Note that the returned device object is
|
||
|
referenced by this routine.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject - Device object to examine.
|
||
|
BottomDeviceObject - Receives device object at the bottom of DeviceObject's
|
||
|
stack, NULL if none.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDEVOBJ_EXTENSION deviceExtension;
|
||
|
PDEVICE_OBJECT lowerDeviceObject, deviceAttachedTo;
|
||
|
KIRQL irql;
|
||
|
|
||
|
deviceAttachedTo = DeviceObject;
|
||
|
|
||
|
irql = KeAcquireQueuedSpinLock( LockQueueIoDatabaseLock );
|
||
|
|
||
|
do {
|
||
|
lowerDeviceObject = deviceAttachedTo;
|
||
|
deviceExtension = lowerDeviceObject->DeviceObjectExtension;
|
||
|
deviceAttachedTo = deviceExtension->AttachedTo;
|
||
|
|
||
|
} while ( deviceAttachedTo );
|
||
|
|
||
|
ObReferenceObject(lowerDeviceObject);
|
||
|
|
||
|
KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
|
||
|
|
||
|
*BottomDeviceObject = lowerDeviceObject;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilGetUpperDeviceObject(
|
||
|
IN PDEVICE_OBJECT LowerDeviceObject,
|
||
|
OUT PDEVICE_OBJECT *UpperDeviceObject
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine returns the device object above the passed in parameter. In
|
||
|
other words, it retrieves DeviceObject->AttachedDevice under the database
|
||
|
lock.. Note that the returned device object is referenced by this routine.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
LowerDeviceObject - Device object to look above.
|
||
|
UpperDeviceObject - Receives device object above LowerDeviceObject, or
|
||
|
NULL if none.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDEVICE_OBJECT deviceAbove;
|
||
|
KIRQL irql;
|
||
|
|
||
|
irql = KeAcquireQueuedSpinLock( LockQueueIoDatabaseLock );
|
||
|
|
||
|
deviceAbove = LowerDeviceObject->AttachedDevice;
|
||
|
if (deviceAbove) {
|
||
|
|
||
|
ObReferenceObject(deviceAbove);
|
||
|
}
|
||
|
|
||
|
KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
|
||
|
|
||
|
*UpperDeviceObject = deviceAbove;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
FASTCALL
|
||
|
IovUtilIsVerifiedDeviceStack(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine determines whether a device object in the stack is marked for
|
||
|
verification.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject - Device object to examine.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if at least one device object in the stack is marked for verification,
|
||
|
FALSE otherwise.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDEVOBJ_EXTENSION deviceExtension;
|
||
|
PDEVICE_OBJECT currentDevObj, deviceAttachedTo;
|
||
|
BOOLEAN stackIsInteresting;
|
||
|
KIRQL irql;
|
||
|
|
||
|
//
|
||
|
// Quickly check the cached result stored on the device object...
|
||
|
//
|
||
|
if (DeviceObject->DeviceObjectExtension->ExtensionFlags & DOV_EXAMINED) {
|
||
|
|
||
|
stackIsInteresting =
|
||
|
((DeviceObject->DeviceObjectExtension->ExtensionFlags & DOV_TRACKED) != 0);
|
||
|
|
||
|
return stackIsInteresting;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Walk the entire stack and update everything appropriately.
|
||
|
//
|
||
|
irql = KeAcquireQueuedSpinLock( LockQueueIoDatabaseLock );
|
||
|
|
||
|
stackIsInteresting = FALSE;
|
||
|
deviceAttachedTo = DeviceObject;
|
||
|
do {
|
||
|
currentDevObj = deviceAttachedTo;
|
||
|
deviceExtension = currentDevObj->DeviceObjectExtension;
|
||
|
deviceAttachedTo = deviceExtension->AttachedTo;
|
||
|
|
||
|
//
|
||
|
// Remember this...
|
||
|
//
|
||
|
if (MmIsDriverVerifying(currentDevObj->DriverObject)) {
|
||
|
|
||
|
stackIsInteresting = TRUE;
|
||
|
}
|
||
|
|
||
|
} while (deviceAttachedTo &&
|
||
|
(!(deviceAttachedTo->DeviceObjectExtension->ExtensionFlags & DOV_EXAMINED))
|
||
|
);
|
||
|
|
||
|
if (deviceAttachedTo &&
|
||
|
(deviceAttachedTo->DeviceObjectExtension->ExtensionFlags & DOV_TRACKED)) {
|
||
|
|
||
|
//
|
||
|
// Propogate upwards the "interesting-ness" of the last examined device
|
||
|
// in the stack...
|
||
|
//
|
||
|
stackIsInteresting = TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Walk upwards, marking everything examined and appropriately tracked.
|
||
|
//
|
||
|
do {
|
||
|
deviceExtension = currentDevObj->DeviceObjectExtension;
|
||
|
|
||
|
if (stackIsInteresting) {
|
||
|
|
||
|
deviceExtension->ExtensionFlags |= DOV_TRACKED;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
deviceExtension->ExtensionFlags &=~ DOV_TRACKED;
|
||
|
}
|
||
|
|
||
|
deviceExtension->ExtensionFlags |= DOV_EXAMINED;
|
||
|
|
||
|
currentDevObj = currentDevObj->AttachedDevice;
|
||
|
|
||
|
} while (currentDevObj);
|
||
|
|
||
|
KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
|
||
|
|
||
|
return stackIsInteresting;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilFlushStackCache(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN DATABASELOCKSTATE DatabaseLockState
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine causes the verifier to reexamine the stack of which the given
|
||
|
device object is a member. This needs to be done whenever the attachment
|
||
|
chain is updated.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject - Device that is a member of the stack requiring
|
||
|
reexamination.
|
||
|
DatabaseLockState - Indicates current state of Database lock, either
|
||
|
DATABASELOCKSTATE_HELD or DATABASELOCKSTATE_NOT_HELD.
|
||
|
If the lock is not held, this routine will acquire and
|
||
|
release it.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDEVICE_OBJECT pBottomDeviceObject, pCurrentDeviceObject;
|
||
|
PDEVOBJ_EXTENSION deviceExtension;
|
||
|
KIRQL irql;
|
||
|
|
||
|
if (DatabaseLockState == DATABASELOCKSTATE_NOT_HELD) {
|
||
|
|
||
|
irql = KeAcquireQueuedSpinLock( LockQueueIoDatabaseLock );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Walk to the bottom of the stack
|
||
|
//
|
||
|
pCurrentDeviceObject = DeviceObject;
|
||
|
do {
|
||
|
pBottomDeviceObject = pCurrentDeviceObject;
|
||
|
deviceExtension = pBottomDeviceObject->DeviceObjectExtension;
|
||
|
pCurrentDeviceObject = deviceExtension->AttachedTo;
|
||
|
|
||
|
} while ( pCurrentDeviceObject );
|
||
|
|
||
|
//
|
||
|
// Walk back up clearing the appropriate flags.
|
||
|
//
|
||
|
pCurrentDeviceObject = pBottomDeviceObject;
|
||
|
while(pCurrentDeviceObject) {
|
||
|
|
||
|
deviceExtension = pCurrentDeviceObject->DeviceObjectExtension;
|
||
|
deviceExtension->ExtensionFlags &= ~(DOV_EXAMINED | DOV_TRACKED);
|
||
|
pCurrentDeviceObject = pCurrentDeviceObject->AttachedDevice;
|
||
|
}
|
||
|
|
||
|
if (DatabaseLockState == DATABASELOCKSTATE_NOT_HELD) {
|
||
|
|
||
|
KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilFlushVerifierDriverListCache(
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine causes the verifier to reexamine all previously examined
|
||
|
stacks. This is a prerequisite for updating the list of verified drivers.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
//
|
||
|
// We must be called at PASSIVE_LEVEL!
|
||
|
//
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ObEnumerateObjectsByType(
|
||
|
IoDeviceObjectType,
|
||
|
IovpUtilFlushListCallback,
|
||
|
NULL
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
IovpUtilFlushListCallback(
|
||
|
IN PVOID Object,
|
||
|
IN PUNICODE_STRING ObjectName,
|
||
|
IN ULONG HandleCount,
|
||
|
IN ULONG PointerCount,
|
||
|
IN PVOID Context
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is a worker routine for IovUtilFlushVerifierDriverListCache. It is
|
||
|
called on each device object in the system.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Object - Device Object enumerated by ObEnumerateObjectsByType.
|
||
|
ObjectName - Name of the object
|
||
|
HandleCount - Handle count of the object
|
||
|
PointerCount - Pointer count of the object
|
||
|
Context - Context supplied to ObEnumerateObjectsByType (not used)
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
BOOLEAN that indicates whether the enumeration should continue.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDEVICE_OBJECT deviceObject;
|
||
|
PDEVOBJ_EXTENSION deviceExtension;
|
||
|
|
||
|
deviceObject = (PDEVICE_OBJECT) Object;
|
||
|
deviceExtension = deviceObject->DeviceObjectExtension;
|
||
|
|
||
|
if (PointerCount || HandleCount) {
|
||
|
|
||
|
deviceExtension->ExtensionFlags &= ~(DOV_EXAMINED | DOV_TRACKED);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
IovUtilRelateDeviceObjects(
|
||
|
IN PDEVICE_OBJECT FirstDeviceObject,
|
||
|
IN PDEVICE_OBJECT SecondDeviceObject,
|
||
|
OUT DEVOBJ_RELATION *DeviceObjectRelation
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine determines the relationship between two device objects,
|
||
|
relative to their stacks.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
FirstDeviceObject - First device object
|
||
|
|
||
|
SecondDeviceObject - Second device object
|
||
|
|
||
|
DeviceObjectRelation - Receives stack relationship of device objects:
|
||
|
|
||
|
DEVOBJ_RELATION_IDENTICAL -
|
||
|
The two device objects are identical.
|
||
|
|
||
|
DEVOBJ_RELATION_FIRST_IMMEDIATELY_ABOVE_SECOND -
|
||
|
The first device object is immediately above the second device
|
||
|
object in the same stack.
|
||
|
|
||
|
DEVOBJ_RELATION_FIRST_ABOVE_SECOND -
|
||
|
The first device object is above the second device object in the
|
||
|
same stack, but not immediately above.
|
||
|
|
||
|
DEVOBJ_RELATION_FIRST_IMMEDIATELY_BELOW_SECOND -
|
||
|
The first device object is immediately below the second device
|
||
|
object in the same stack.
|
||
|
|
||
|
DEVOBJ_RELATION_FIRST_BELOW_SECOND -
|
||
|
The first device object is below the second device object in the
|
||
|
same stack, but not immediately above.
|
||
|
|
||
|
DEVOBJ_RELATION_NOT_IN_SAME_STACK -
|
||
|
The device objects do not belong to the same stack.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDEVOBJ_EXTENSION deviceExtension;
|
||
|
PDEVICE_OBJECT upperDevobj, lowerDeviceObject, deviceAttachedTo;
|
||
|
ULONG result;
|
||
|
KIRQL irql;
|
||
|
|
||
|
//
|
||
|
// Try the easiest early out
|
||
|
//
|
||
|
if (FirstDeviceObject == SecondDeviceObject) {
|
||
|
|
||
|
*DeviceObjectRelation = DEVOBJ_RELATION_IDENTICAL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
irql = KeAcquireQueuedSpinLock( LockQueueIoDatabaseLock );
|
||
|
|
||
|
//
|
||
|
// Try the most common early out
|
||
|
//
|
||
|
if (FirstDeviceObject == SecondDeviceObject->AttachedDevice){
|
||
|
|
||
|
*DeviceObjectRelation = DEVOBJ_RELATION_FIRST_IMMEDIATELY_ABOVE_SECOND;
|
||
|
KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
|
||
|
return;
|
||
|
|
||
|
} else if (FirstDeviceObject->AttachedDevice == SecondDeviceObject) {
|
||
|
|
||
|
*DeviceObjectRelation = DEVOBJ_RELATION_FIRST_IMMEDIATELY_BELOW_SECOND;
|
||
|
KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We'll have to walk a stack. Start by getting the bottom of the first
|
||
|
// device object.
|
||
|
//
|
||
|
deviceAttachedTo = FirstDeviceObject;
|
||
|
do {
|
||
|
if (deviceAttachedTo == SecondDeviceObject) {
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
lowerDeviceObject = deviceAttachedTo;
|
||
|
deviceExtension = lowerDeviceObject->DeviceObjectExtension;
|
||
|
deviceAttachedTo = deviceExtension->AttachedTo;
|
||
|
|
||
|
} while ( deviceAttachedTo );
|
||
|
|
||
|
//
|
||
|
// If deviceAttachedTo isn't NULL, then we walked down from
|
||
|
// FirstDeviceObject and found SecondDeviceObject.
|
||
|
//
|
||
|
if (deviceAttachedTo) {
|
||
|
|
||
|
*DeviceObjectRelation = DEVOBJ_RELATION_FIRST_ABOVE_SECOND;
|
||
|
KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now try walking *up* FirstDeviceObject and see if we find
|
||
|
// SecondDeviceObject.
|
||
|
//
|
||
|
upperDevobj = FirstDeviceObject->AttachedDevice;
|
||
|
while(upperDevobj && (upperDevobj != SecondDeviceObject)) {
|
||
|
|
||
|
upperDevobj = upperDevobj->AttachedDevice;
|
||
|
}
|
||
|
|
||
|
if (upperDevobj == NULL) {
|
||
|
|
||
|
*DeviceObjectRelation = DEVOBJ_RELATION_NOT_IN_SAME_STACK;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
*DeviceObjectRelation = DEVOBJ_RELATION_FIRST_BELOW_SECOND;
|
||
|
}
|
||
|
|
||
|
KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
IovUtilIsPdo(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
)
|
||
|
{
|
||
|
PDEVICE_NODE deviceNode;
|
||
|
PDEVICE_OBJECT possiblePdo;
|
||
|
BOOLEAN isPdo;
|
||
|
|
||
|
IovUtilGetBottomDeviceObject(DeviceObject, &possiblePdo);
|
||
|
if (possiblePdo != DeviceObject) {
|
||
|
|
||
|
ObDereferenceObject(possiblePdo);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
deviceNode = possiblePdo->DeviceObjectExtension->DeviceNode;
|
||
|
|
||
|
isPdo =
|
||
|
(deviceNode && (!(deviceNode->Flags & DNF_LEGACY_RESOURCE_DEVICENODE)));
|
||
|
|
||
|
//
|
||
|
// Free our reference.
|
||
|
//
|
||
|
ObDereferenceObject(possiblePdo);
|
||
|
|
||
|
return isPdo;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
IovUtilIsWdmStack(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
)
|
||
|
{
|
||
|
PDEVICE_NODE deviceNode;
|
||
|
PDEVICE_OBJECT possiblePdo;
|
||
|
BOOLEAN isWdmStack;
|
||
|
|
||
|
IovUtilGetBottomDeviceObject(DeviceObject, &possiblePdo);
|
||
|
|
||
|
deviceNode = possiblePdo->DeviceObjectExtension->DeviceNode;
|
||
|
|
||
|
isWdmStack =
|
||
|
(deviceNode && (!(deviceNode->Flags & DNF_LEGACY_RESOURCE_DEVICENODE)));
|
||
|
|
||
|
//
|
||
|
// Free our reference.
|
||
|
//
|
||
|
ObDereferenceObject(possiblePdo);
|
||
|
|
||
|
return isWdmStack;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
FASTCALL
|
||
|
IovUtilHasDispatchHandler(
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN UCHAR MajorFunction
|
||
|
)
|
||
|
{
|
||
|
return (DriverObject->MajorFunction[MajorFunction] != IopInvalidDeviceRequest);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
FASTCALL
|
||
|
IovUtilIsInFdoStack(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
)
|
||
|
{
|
||
|
PDEVOBJ_EXTENSION deviceExtension;
|
||
|
PDEVICE_OBJECT deviceAttachedTo, lowerDevobj;
|
||
|
KIRQL irql;
|
||
|
|
||
|
deviceAttachedTo = DeviceObject;
|
||
|
|
||
|
irql = KeAcquireQueuedSpinLock( LockQueueIoDatabaseLock );
|
||
|
|
||
|
do {
|
||
|
|
||
|
if (IovUtilIsDeviceObjectMarked(DeviceObject, MARKTYPE_BOTTOM_OF_FDO_STACK)) {
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
deviceAttachedTo = deviceAttachedTo->DeviceObjectExtension->AttachedTo;
|
||
|
|
||
|
} while ( deviceAttachedTo );
|
||
|
|
||
|
KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
|
||
|
return (deviceAttachedTo != NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
FASTCALL
|
||
|
IovUtilIsRawPdo(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
)
|
||
|
{
|
||
|
return IovUtilIsDeviceObjectMarked(DeviceObject, MARKTYPE_RAW_PDO);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
FASTCALL
|
||
|
IovUtilIsDesignatedFdo(
|
||
|
IN PDEVICE_OBJECT DeviceObject
|
||
|
)
|
||
|
{
|
||
|
return IovUtilIsDeviceObjectMarked(DeviceObject, MARKTYPE_DESIGNATED_FDO);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilMarkDeviceObject(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN MARK_TYPE MarkType
|
||
|
)
|
||
|
{
|
||
|
PULONG extensionFlags;
|
||
|
|
||
|
if (!IovUtilVerifierEnabled) {
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
extensionFlags = &DeviceObject->DeviceObjectExtension->ExtensionFlags;
|
||
|
|
||
|
switch(MarkType) {
|
||
|
|
||
|
case MARKTYPE_DELETED:
|
||
|
*extensionFlags |= DOV_DELETED;
|
||
|
break;
|
||
|
|
||
|
case MARKTYPE_BOTTOM_OF_FDO_STACK:
|
||
|
*extensionFlags |= DOV_BOTTOM_OF_FDO_STACK;
|
||
|
break;
|
||
|
|
||
|
case MARKTYPE_DESIGNATED_FDO:
|
||
|
*extensionFlags |= DOV_DESIGNATED_FDO;
|
||
|
break;
|
||
|
|
||
|
case MARKTYPE_RAW_PDO:
|
||
|
*extensionFlags |= DOV_RAW_PDO;
|
||
|
break;
|
||
|
|
||
|
case MARKTYPE_DEVICE_CHECKED:
|
||
|
*extensionFlags |= DOV_FLAGS_CHECKED;
|
||
|
break;
|
||
|
|
||
|
case MARKTYPE_RELATION_PDO_EXAMINED:
|
||
|
*extensionFlags |= DOV_FLAGS_RELATION_EXAMINED;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(0);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
FASTCALL
|
||
|
IovUtilIsDeviceObjectMarked(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN MARK_TYPE MarkType
|
||
|
)
|
||
|
{
|
||
|
ULONG extensionFlags;
|
||
|
|
||
|
extensionFlags = DeviceObject->DeviceObjectExtension->ExtensionFlags;
|
||
|
|
||
|
switch(MarkType) {
|
||
|
|
||
|
case MARKTYPE_DELETED:
|
||
|
return ((extensionFlags & DOV_DELETED) != 0);
|
||
|
|
||
|
case MARKTYPE_BOTTOM_OF_FDO_STACK:
|
||
|
return ((extensionFlags & DOV_BOTTOM_OF_FDO_STACK) != 0);
|
||
|
|
||
|
case MARKTYPE_DESIGNATED_FDO:
|
||
|
return ((extensionFlags & DOV_DESIGNATED_FDO) != 0);
|
||
|
|
||
|
case MARKTYPE_RAW_PDO:
|
||
|
return ((extensionFlags & DOV_RAW_PDO) != 0);
|
||
|
|
||
|
case MARKTYPE_DEVICE_CHECKED:
|
||
|
return ((extensionFlags & DOV_FLAGS_CHECKED) != 0);
|
||
|
|
||
|
case MARKTYPE_RELATION_PDO_EXAMINED:
|
||
|
return ((extensionFlags & DOV_FLAGS_RELATION_EXAMINED) != 0);
|
||
|
|
||
|
default:
|
||
|
ASSERT(0);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilMarkStack(
|
||
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||
|
IN PDEVICE_OBJECT BottomOfFdoStack OPTIONAL,
|
||
|
IN PDEVICE_OBJECT FunctionalDeviceObject OPTIONAL,
|
||
|
IN BOOLEAN RawStack
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Description:
|
||
|
|
||
|
This routine marks device objects in a PnP stack appropriately. It is
|
||
|
called by AddDevice once the stack is properly constructed.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
PhysicalDeviceObject - Device object at the bottom of the PnP stack.
|
||
|
|
||
|
BottomOfFdoStack - First device object added during AddDevice. Below this
|
||
|
device object is either a bus filter or the PDO itself.
|
||
|
|
||
|
FunctionalDeviceObject - Specifies the device object as identified in the
|
||
|
service branch. This should be NULL if the devnode
|
||
|
is raw and no overriding service was specified.
|
||
|
|
||
|
RawStack - True if stack was marked raw.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PDEVICE_OBJECT trueFunctionalDeviceObject;
|
||
|
|
||
|
if (BottomOfFdoStack) {
|
||
|
|
||
|
IovUtilMarkDeviceObject(BottomOfFdoStack, MARKTYPE_BOTTOM_OF_FDO_STACK);
|
||
|
}
|
||
|
|
||
|
if (FunctionalDeviceObject) {
|
||
|
|
||
|
trueFunctionalDeviceObject = FunctionalDeviceObject;
|
||
|
|
||
|
if (IovUtilVerifierEnabled) {
|
||
|
|
||
|
VfDevObjAdjustFdoForVerifierFilters(&trueFunctionalDeviceObject);
|
||
|
}
|
||
|
|
||
|
IovUtilMarkDeviceObject(trueFunctionalDeviceObject, MARKTYPE_DESIGNATED_FDO);
|
||
|
|
||
|
} else if (RawStack) {
|
||
|
|
||
|
IovUtilMarkDeviceObject(PhysicalDeviceObject, MARKTYPE_DESIGNATED_FDO);
|
||
|
IovUtilMarkDeviceObject(PhysicalDeviceObject, MARKTYPE_RAW_PDO);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilWatermarkIrp(
|
||
|
IN PIRP Irp,
|
||
|
IN ULONG Flags
|
||
|
)
|
||
|
{
|
||
|
if (IovUtilVerifierEnabled) {
|
||
|
|
||
|
VfIrpWatermark(Irp, Flags);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#else // NO_VERIFIER
|
||
|
|
||
|
//
|
||
|
// The code below should be built into a future stub that deadens out IO
|
||
|
// support for the verifier.
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilInit(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilMarkDeviceObject(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN MARK_TYPE MarkType
|
||
|
)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(DeviceObject);
|
||
|
UNREFERENCED_PARAMETER(MarkType);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilMarkStack(
|
||
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||
|
IN PDEVICE_OBJECT BottomOfFdoStack OPTIONAL,
|
||
|
IN PDEVICE_OBJECT FunctionalDeviceObject OPTIONAL,
|
||
|
IN BOOLEAN RawStack
|
||
|
)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(PhysicalDeviceObject);
|
||
|
UNREFERENCED_PARAMETER(BottomOfFdoStack);
|
||
|
UNREFERENCED_PARAMETER(FunctionalDeviceObject);
|
||
|
UNREFERENCED_PARAMETER(RawStack);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FASTCALL
|
||
|
IovUtilWatermarkIrp(
|
||
|
IN PIRP Irp,
|
||
|
IN ULONG Flags
|
||
|
)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(Irp);
|
||
|
UNREFERENCED_PARAMETER(Flags);
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif // NO_VERIFIER
|
||
|
|