text: /*++
  
  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_PTR        HandleCount,
      IN ULONG_PTR        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
  
  