|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
vfdevobj.c
Abstract:
This module verifies drivers properly manage device objects.
Author:
Adrian J. Oney (adriao) 09-May-1998
Environment:
Kernel mode
Revision History:
AdriaO 05/02/2000 - Seperated out from ntos\io\trackirp.c
--*/
//
// Disable W4 level warnings generated by public headers.
//
#include "vfpragma.h"
#include "..\io\iop.h" // Includes vfdef.h
#if (( defined(_X86_) ) && ( FPO ))
#pragma optimize( "y", off ) // disable FPO for consistent stack traces
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGEVRFY, VerifierIoAttachDeviceToDeviceStack)
#pragma alloc_text(PAGEVRFY, VerifierIoDetachDevice)
#pragma alloc_text(PAGEVRFY, VerifierIoDeleteDevice)
#pragma alloc_text(PAGEVRFY, VfDevObjPreAddDevice)
#pragma alloc_text(PAGEVRFY, VfDevObjPostAddDevice)
#pragma alloc_text(PAGEVRFY, VfDevObjAdjustFdoForVerifierFilters)
#endif
VOID VerifierIoAttachDeviceToDeviceStack( IN PDEVICE_OBJECT NewDevice, IN PDEVICE_OBJECT ExistingDevice ) { UNREFERENCED_PARAMETER (NewDevice);
IovUtilFlushStackCache(ExistingDevice, DATABASELOCKSTATE_HELD); }
VOID VerifierIoDetachDevice( IN PDEVICE_OBJECT LowerDevice ) { PVOID callerAddress; ULONG stackHash;
if (LowerDevice->AttachedDevice == NULL) {
if (RtlCaptureStackBackTrace(2, 1, &callerAddress, &stackHash) != 1) {
callerAddress = NULL; }
WDM_FAIL_ROUTINE(( DCERROR_DETACH_NOT_ATTACHED, DCPARAM_ROUTINE + DCPARAM_DEVOBJ, callerAddress, LowerDevice )); }
IovUtilFlushStackCache(LowerDevice, DATABASELOCKSTATE_HELD); }
VOID VerifierIoDeleteDevice( IN PDEVICE_OBJECT DeviceObject ) { PDEVICE_OBJECT deviceBelow; PVOID callerAddress; ULONG stackHash;
if (RtlCaptureStackBackTrace(2, 1, &callerAddress, &stackHash) != 1) {
callerAddress = NULL; }
//
// ADRIAO N.B. 06/16/2000 - A good thing to do here would be to send a
// second remove IRP to every deleted device object that was a member
// of a WDM device stack. Just to check.
//
if (IovUtilIsDeviceObjectMarked(DeviceObject, MARKTYPE_DELETED)) {
WDM_FAIL_ROUTINE(( DCERROR_DOUBLE_DELETION, DCPARAM_ROUTINE, callerAddress )); }
IovUtilMarkDeviceObject(DeviceObject, MARKTYPE_DELETED);
IovUtilGetLowerDeviceObject(DeviceObject, &deviceBelow); if (deviceBelow) {
WDM_FAIL_ROUTINE(( DCERROR_DELETE_WHILE_ATTACHED, DCPARAM_ROUTINE, callerAddress ));
ObDereferenceObject(deviceBelow); }
VfIrpLogDeleteDeviceLogs(DeviceObject); }
VOID VfDevObjPreAddDevice( IN PDEVICE_OBJECT PhysicalDeviceObject, IN PDRIVER_OBJECT DriverObject, IN PDRIVER_ADD_DEVICE AddDeviceFunction, IN VF_DEVOBJ_TYPE DevObjType ) /*++
Description:
This routine is called before the specified driver's AddDevice has been invoked.
Arguments:
PhysicalDeviceObject - Device object at the bottom of the PnP stack.
DriverObject - Driver object of the driver who's AddDevice has been invoked.
AddDeviceFunction - Address of the AddDevice routine.
DevObjType - Type of device object (lower device filter, FDO, etc.)
Return Value:
None.
--*/ { VF_DEVOBJ_TYPE objType;
UNREFERENCED_PARAMETER(AddDeviceFunction);
if (!MmIsDriverVerifying(DriverObject)) {
return; }
if (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_INSERT_WDM_FILTERS)) {
if (DevObjType == VF_DEVOBJ_FDO) {
//
// If we are calling AddDevice for the FDO, first attempt to attach
// a lower class filter.
//
objType = VF_DEVOBJ_LOWER_CLASS_FILTER;
} else {
objType = DevObjType; }
//
// Attach a filter, cause pain.
//
VfFilterAttach(PhysicalDeviceObject, objType); } }
VOID VfDevObjPostAddDevice( IN PDEVICE_OBJECT PhysicalDeviceObject, IN PDRIVER_OBJECT DriverObject, IN PDRIVER_ADD_DEVICE AddDeviceFunction, IN VF_DEVOBJ_TYPE DevObjType, IN NTSTATUS Result ) /*++
Description:
This routine is called after the specified driver's AddDevice has been invoked.
Arguments:
PhysicalDeviceObject - Device object at the bottom of the PnP stack.
DriverObject - Driver object of the driver who's AddDevice has been invoked.
AddDeviceFunction - Address of the AddDevice routine.
DevObjType - Type of device object (lower device filter, FDO, etc.)
Result - Result returned by the AddDevice Routine
Return Value:
None.
--*/ { PDEVICE_OBJECT deviceAbove, deviceBelow; BOOLEAN powerFailure; VF_DEVOBJ_TYPE objType;
UNREFERENCED_PARAMETER(DriverObject);
if (NT_SUCCESS(Result) && VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_INSERT_WDM_FILTERS) && MmIsDriverVerifying(DriverObject)) {
if (DevObjType == VF_DEVOBJ_FDO) {
//
// If we've just attached an FDO, try to add a upper device filter
// on top of it.
//
objType = VF_DEVOBJ_UPPER_DEVICE_FILTER;
} else {
objType = DevObjType; }
//
// Attach filter, cause pain.
//
VfFilterAttach(PhysicalDeviceObject, objType); }
if (!VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_VERIFY_DO_FLAGS)) {
return; }
//
// Take this opportunity to check the PDO.
//
if (!IovUtilIsDeviceObjectMarked(PhysicalDeviceObject, MARKTYPE_DEVICE_CHECKED)) {
if ((PhysicalDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)) == (DO_BUFFERED_IO | DO_DIRECT_IO)) {
//
// Both direct I/O and buffered I/O are set. These are mutually
// exclusive.
//
WDM_FAIL_ROUTINE(( DCERROR_INCONSISTANT_DO_FLAGS, DCPARAM_ROUTINE + DCPARAM_DEVOBJ, PhysicalDeviceObject->DriverObject->DriverExtension->AddDevice, PhysicalDeviceObject )); }
//
// No need to check DO_DEVICE_INITIALIZING as PDO's get them cleared
// automagically.
//
IovUtilMarkDeviceObject(PhysicalDeviceObject, MARKTYPE_DEVICE_CHECKED); }
powerFailure = FALSE; deviceBelow = PhysicalDeviceObject; ObReferenceObject(deviceBelow); while(1) { IovUtilGetUpperDeviceObject(deviceBelow, &deviceAbove);
if (deviceAbove == NULL) {
ObDereferenceObject(deviceBelow); break; }
if (!IovUtilIsDeviceObjectMarked(deviceAbove, MARKTYPE_DEVICE_CHECKED)) {
if ((deviceAbove->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)) == (DO_BUFFERED_IO | DO_DIRECT_IO)) {
//
// Both direct I/O and buffered I/O are set. These are mutually
// exclusive.
//
WDM_FAIL_ROUTINE(( DCERROR_INCONSISTANT_DO_FLAGS, DCPARAM_ROUTINE + DCPARAM_DEVOBJ, AddDeviceFunction, deviceAbove )); }
if (deviceAbove->Flags & DO_DEVICE_INITIALIZING) {
//
// A device didn't clear the DO_DEVICE_INITIALIZING flag during
// AddDevice. Fail it now.
//
WDM_FAIL_ROUTINE(( DCERROR_DO_INITIALIZING_NOT_CLEARED, DCPARAM_ROUTINE + DCPARAM_DEVOBJ, AddDeviceFunction, deviceAbove ));
//
// Clean up the mess.
//
deviceAbove->Flags &= ~DO_DEVICE_INITIALIZING; }
if ((deviceBelow->Flags & DO_POWER_PAGABLE) && (!(deviceAbove->Flags & DO_POWER_PAGABLE))) {
if (!powerFailure) {
//
// We have caught a driver bug. deviceAbove didn't inherit the
// DO_POWER_PAGABLE flag.
//
WDM_FAIL_ROUTINE(( DCERROR_POWER_PAGABLE_NOT_INHERITED, DCPARAM_ROUTINE + DCPARAM_DEVOBJ, AddDeviceFunction, deviceAbove ));
//
// Don't blame anyone else.
//
powerFailure = TRUE; }
deviceAbove->Flags |= DO_POWER_PAGABLE; }
if ((deviceBelow->Flags & DO_BUFFERED_IO) && (!(deviceAbove->Flags & DO_BUFFERED_IO))) {
//
// Buffered I/O flag not copied. Broken filter!
//
WDM_FAIL_ROUTINE(( DCERROR_DO_FLAG_NOT_COPIED, DCPARAM_ROUTINE + DCPARAM_DEVOBJ, AddDeviceFunction, deviceAbove )); }
if ((deviceBelow->Flags & DO_DIRECT_IO) && (!(deviceAbove->Flags & DO_DIRECT_IO))) {
//
// Direct I/O flag not copied. Broken filter!
//
WDM_FAIL_ROUTINE(( DCERROR_DO_FLAG_NOT_COPIED, DCPARAM_ROUTINE + DCPARAM_DEVOBJ, AddDeviceFunction, deviceAbove )); }
if ((deviceBelow->DeviceType != FILE_DEVICE_UNKNOWN) && (deviceAbove->DeviceType == FILE_DEVICE_UNKNOWN)) {
//
// The device type wasn't copied by a filter!
//
WDM_FAIL_ROUTINE(( DCERROR_DEVICE_TYPE_NOT_COPIED, DCPARAM_ROUTINE + DCPARAM_DEVOBJ, AddDeviceFunction, deviceAbove )); }
//
// Characteristics don't have to be checked because PnP takes care
// of propogating them appropriately.
//
}
IovUtilMarkDeviceObject(deviceAbove, MARKTYPE_DEVICE_CHECKED);
ObDereferenceObject(deviceBelow); deviceBelow = deviceAbove; } }
VOID VfDevObjAdjustFdoForVerifierFilters( IN OUT PDEVICE_OBJECT *FunctionalDeviceObject ) /*++
Description:
This routine adjusts the designated FDO to take into account any verifier filter DO's added by this file.
Arguments:
FunctionalDeviceObject - On input, contains FDO. Adjusted to point to the correct FDO if verifier added a filter.
Return Value:
None.
--*/ { PDEVICE_OBJECT fdo;
fdo = *FunctionalDeviceObject;
if (VfFilterIsVerifierFilterObject(fdo)) {
fdo = fdo->AttachedDevice; ASSERT(fdo);
*FunctionalDeviceObject = fdo; } }
|