Windows2000/private/ntos/io/trackirp.h

601 lines
19 KiB
C

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
trackirp.h
Abstract:
The module associated with the header asserts Irps are handled correctly by drivers.
No IRP-major specific testing is done; such code is done in flunkirp.*
Author:
Adrian J. Oney (adriao) 20-Apr-1998
*/
#ifndef _TRACKIRP_H_
#define _TRACKIRP_H_
#define ASSERTFLAG_TRACKIRPS 0x00000001
#define ASSERTFLAG_MONITOR_ALLOCS 0x00000002
#define ASSERTFLAG_POLICEIRPS 0x00000004
#define ASSERTFLAG_MONITORMAJORS 0x00000008
#define ASSERTFLAG_SURROGATE 0x00000010
#define ASSERTFLAG_SMASH_SRBS 0x00000020
#define ASSERTFLAG_CONSUME_ALWAYS 0x00000040
#define ASSERTFLAG_FORCEPENDING 0x00000080
#define ASSERTFLAG_COMPLETEATDPC 0x00000100
#define ASSERTFLAG_COMPLETEATPASSIVE 0x00000200
#define ASSERTFLAG_DEFERCOMPLETION 0x00000800
#define ASSERTFLAG_ROTATE_STATUS 0x00001000
#define ASSERTMASK_COMPLETESTYLE 0x00000F80
#define ASSERTFLAG_SEEDSTACK 0x00010000
// Disabling HACKHACKS_ENABLED will remove support for all hack code. The
// hack code allows the machine to fully boot in checked builds. Note that
// those hacks can be individually disabled by setting the IovpHackFlags
// variable at boot time.
#define HACKHACKS_ENABLED
#define HACKFLAG_FOR_MUP 0x00000001
#define HACKFLAG_FOR_SCSIPORT 0x00000002
#define HACKFLAG_FOR_ACPI 0x00000004
#define HACKFLAG_FOR_BOGUSIRPS 0x00000008
extern ULONG IovpHackFlags ;
extern ULONG IovpTrackingFlags ;
// Currently, ntddk.h uses up to 0x2000 for Irp->Flags
#define IRPFLAG_EXAMINE_MASK 0xC0000000
#define IRPFLAG_EXAMINE_NOT_TRACKED 0x80000000
#define IRPFLAG_EXAMINE_TRACKED 0x40000000
#define IRPFLAG_EXAMINE_UNMARKED 0x00000000
#define IRP_DIAG_HAS_SURROGATE 0x02000000
#define IRP_DIAG_IS_SURROGATE 0x01000000
#define TRACKFLAG_ACTIVE 0x00000001
#define TRACKFLAG_SURROGATE 0x00000002
#define TRACKFLAG_HAS_SURROGATE 0x00000004
#define TRACKFLAG_PROTECTEDIRP 0x00000008
#define TRACKFLAG_QUEUED_INTERNALLY 0x00000010
#define TRACKFLAG_BOGUS 0x00000020
#define TRACKFLAG_RELEASED 0x00000040
#define TRACKFLAG_SRB_MUNGED 0x00000080
#define TRACKFLAG_SWAPPED_BACK 0x00000100
#define TRACKFLAG_WATERMARKED 0x00100000
#define TRACKFLAG_IO_ALLOCATED 0x00200000
#define TRACKFLAG_UNWOUND_BADLY 0x00400000
#define TRACKFLAG_PASSED_FAILURE 0x01000000
#define TRACKFLAG_PASSED_AT_BAD_IRQL 0x02000000
#define TRACKFLAG_IN_TRANSIT 0x40000000
#define TRACKFLAG_REMOVED_FROM_TABLE 0x80000000
#define DOE_DESIGNATED_FDO 0x80000000
#define DOE_BOTTOM_OF_FDO_STACK 0x40000000
#define DOE_RAW_FDO 0x20000000
#define DOE_EXAMINED 0x10000000
#define DOE_TRACKED 0x08000000
#define STACKFLAG_NO_HANDLER 0x80000000
#define STACKFLAG_REQUEST_COMPLETED 0x40000000
#define STACKFLAG_CHECK_FOR_REFERENCE 0x20000000
#define STACKFLAG_REACHED_PDO 0x10000000
#define STACKFLAG_FIRST_REQUEST 0x08000000
#define CALLFLAG_COMPLETED 0x80000000
#define CALLFLAG_IS_REMOVE_IRP 0x40000000
#define CALLFLAG_REMOVING_FDO_STACK_DO 0x20000000
#define CALLFLAG_OVERRIDE_STATUS 0x10000000
#define CALLFLAG_TOPMOST_IN_SLOT 0x08000000
#define ALLOCFLAG_PROTECTEDIRP 0x00000001
#define SESSIONFLAG_UNWOUND_INCONSISTANT 0x00000001
#define IRP_SYSTEM_RESTRICTED 0x00000001
#define IRP_BOGUS 0x00000002
#define SL_NOTCOPIED 0x10
#define IRP_ALLOCATION_MONITORED 0x80
#define STARTED_TOP_OF_STACK 1
#define FORWARDED_TO_NEXT_DO 2
#define SKIPPED_A_DO 3
#define STARTED_INSIDE_STACK 4
#define CHANGED_STACKS_AT_BOTTOM 5
#define CHANGED_STACKS_MID_STACK 6
#define IRP_ALLOC_COUNT 5
typedef enum {
DEFERACTION_QUEUE_WORKITEM,
DEFERACTION_QUEUE_PASSIVE_TIMER,
DEFERACTION_QUEUE_DISPATCH_TIMER,
DEFERACTION_NORMAL
} DEFER_ACTION;
struct _IOFCALLDRIVER_STACKDATA;
struct _IOV_STACK_LOCATION;
struct _IOV_REQUEST_PACKET;
typedef struct _IOFCALLDRIVER_STACKDATA *PIOFCALLDRIVER_STACKDATA;
typedef struct _IOV_STACK_LOCATION *PIOV_STACK_LOCATION;
typedef struct _IOV_REQUEST_PACKET *PIOV_REQUEST_PACKET;
typedef struct _IOV_SESSION_DATA *PIOV_SESSION_DATA;
typedef struct _IOFCALLDRIVER_STACKDATA {
PIOV_SESSION_DATA IovSessionData;
PIOV_STACK_LOCATION IovStackLocation; // For internal consistency checks only...
ULONG Flags;
LIST_ENTRY SharedLocationList;
NTSTATUS ExpectedStatus;
NTSTATUS NewStatus;
PDEVICE_OBJECT RemovePdo;
} IOFCALLDRIVER_STACKDATA;
typedef struct _IOV_STACK_LOCATION {
BOOLEAN InUse;
ULONG Flags;
PIOV_STACK_LOCATION RequestsFirstStackLocation;
LIST_ENTRY CallStackData;
PIO_STACK_LOCATION IrpSp;
PVOID LastDispatch;
LARGE_INTEGER PerfDispatchStart;
LARGE_INTEGER PerfStackLocationStart;
PDEVICE_OBJECT ReferencingObject;
LONG ReferencingCount;
IO_STATUS_BLOCK InitialStatusBlock;
IO_STATUS_BLOCK LastStatusBlock;
PETHREAD ThreadDispatchedTo;
} IOV_STACK_LOCATION;
typedef struct _IOV_SESSION_DATA {
PIOV_REQUEST_PACKET IovRequestPacket;
LONG SessionRefCount;
LIST_ENTRY SessionLink;
ULONG SessionFlags;
ULONG AssertFlags;
PETHREAD OriginatorThread;
PDEVICE_OBJECT DeviceLastCalled; // Last device called
ULONG ForwardMethod;
PIRP BestVisibleIrp;
IOV_STACK_LOCATION StackData[ANYSIZE_ARRAY];
} IOV_SESSION_DATA;
typedef struct _IOV_REQUEST_PACKET {
PIRP TrackedIrp; // Tracked IRP (could be surrogate)
KSPIN_LOCK IrpLock; // Spinlock on data structure
KIRQL CallerIrql; // IRQL taken at.
LONG ReferenceCount; // # of reasons to keep this packet
LONG PointerCount; // # of reasons to track by irp addr
ULONG Flags;
LIST_ENTRY HashLink; // Link in hash table.
LIST_ENTRY SurrogateLink; // Head is at HeadPacket
LIST_ENTRY SessionHead; // List of all sessions.
PIOV_REQUEST_PACKET HeadPacket; // First non-surrogate packet.
CCHAR StackCount; // StackCount of tracked IRP.
ULONG AssertFlags;
PIO_COMPLETION_ROUTINE RealIrpCompletionRoutine;
UCHAR RealIrpControl;
PVOID RealIrpContext;
PVOID AllocatorStack[IRP_ALLOC_COUNT];
// The following information is for the assertion routines to read.
UCHAR TopStackLocation;
CCHAR PriorityBoost; // Boost from IofCompleteRequest
UCHAR LastLocation; // Last location from IofCallDriver
ULONG RefTrackingCount;
PVOID RestoreHandle;
PIOV_SESSION_DATA pIovSessionData;
} IOV_REQUEST_PACKET;
typedef struct _DEFERRAL_CONTEXT {
PIOV_REQUEST_PACKET IovRequestPacket;
PIO_COMPLETION_ROUTINE OriginalCompletionRoutine;
PVOID OriginalContext;
PIRP OriginalIrp;
CCHAR OriginalPriorityBoost;
PDEVICE_OBJECT DeviceObject;
PIO_STACK_LOCATION IrpSpNext;
WORK_QUEUE_ITEM WorkQueueItem;
KDPC DpcItem;
KTIMER DeferralTimer;
DEFER_ACTION DeferAction;
} DEFERRAL_CONTEXT, *PDEFERRAL_CONTEXT;
typedef struct _IOFCOMPLETEREQUEST_STACKDATA {
PIOV_SESSION_DATA IovSessionData;
PIOV_REQUEST_PACKET IovRequestPacket;
BOOLEAN IsRemoveIrp ;
LONG LocationsAdvanced ;
ULONG RaisedCount ;
KIRQL PreviousIrql ;
PVOID CompletionRoutine ;
} IOFCOMPLETEREQUEST_STACKDATA, *PIOFCOMPLETEREQUEST_STACKDATA ;
#ifdef NO_SPECIAL_IRP
#define SPECIALIRP_MARK_NON_TRACKABLE(Irp)
#define SPECIALIRP_IOF_CALL_1(pIrp, DeviceObject, st1)
#define SPECIALIRP_IOF_CALL_2(Irp, DeviceObject, Routine, FinalStatus, st1)
#define SPECIALIRP_IOF_COMPLETE_1(Irp, PriorityBoost, CompletionPacket)
#define SPECIALIRP_IOF_COMPLETE_2(Irp, CompletionPacket)
#define SPECIALIRP_IOF_COMPLETE_3(Irp, Routine, CompletionPacket)
#define SPECIALIRP_IOF_COMPLETE_4(Irp, ReturnedStatus, CompletionPacket)
#define SPECIALIRP_IOF_COMPLETE_5(Irp, CompletionPacket)
#define SPECIALIRP_IOP_COMPLETE_REQUEST(Irp, StackPointer)
#define SPECIALIRP_IO_CANCEL_IRP(Irp, CancelHandled, ReturnValue) DbgBreakPoint() ;
#define SPECIALIRP_IO_FREE_IRP(Irp, FreeHandled) DbgBreakPoint() ;
#define SPECIALIRP_IO_ALLOCATE_IRP_1(StackSize, Quota, pIrp) DbgBreakPoint() ;
#define SPECIALIRP_IO_ALLOCATE_IRP_2(Irp)
#define SPECIALIRP_IO_INITIALIZE_IRP(Irp, PacketSize, StackSize, InitHandled) \
DbgBreakPoint() ;
#define SPECIALIRP_IO_ATTACH_DEVICE_TO_DEVICE_STACK(NewDevice, ExistingDevice)
#define SPECIALIRP_IO_DETACH_DEVICE(TargetDevice)
#define SPECIALIRP_IO_DELETE_DEVICE(TargetDevice)
#define SPECIALIRP_WATERMARK_IRP(Irp, Flags)
#define IOP_DIAG_THROW_CHAFF_AT_STARTED_PDO_STACK(DeviceObject)
#else // NO_SPECIAL_IRP
// These are in trackirp.c
BOOLEAN
FASTCALL
IovpInitIrpTracking(
IN ULONG Level,
IN ULONG Flags
);
VOID
FASTCALL
IovpCallDriver1(
IN OUT PIRP *IrpPointer,
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIOFCALLDRIVER_STACKDATA IofCallDriverStackData
);
VOID
FASTCALL
IovpCallDriver2(
IN PIRP Irp,
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Routine,
IN OUT NTSTATUS *FinalStatus,
IN PIOFCALLDRIVER_STACKDATA IofCallDriverStackData
);
VOID
FASTCALL
IovpCompleteRequest1(
IN PIRP Irp,
IN CCHAR PriorityBoost,
IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket
);
VOID
FASTCALL
IovpCompleteRequest2(
IN PIRP Irp,
IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket
);
VOID
FASTCALL
IovpCompleteRequest3(
IN PIRP Irp,
IN PVOID Routine,
IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket
);
VOID
FASTCALL
IovpCompleteRequest4(
IN PIRP Irp,
IN NTSTATUS ReturnedStatus,
IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket
);
VOID
FASTCALL
IovpCompleteRequest5(
IN PIRP Irp,
IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket
);
VOID
FASTCALL
IovpCompleteRequestApc(
IN PIRP Irp,
IN PVOID BestStackOffset
);
VOID
FASTCALL
IovpCancelIrp(
IN PIRP Irp,
IN OUT PBOOLEAN CancelHandled,
IN OUT PBOOLEAN ReturnValue
);
VOID
FASTCALL
IovpFreeIrp(
IN PIRP Irp,
IN OUT PBOOLEAN FreeHandled
);
VOID
FASTCALL
IovpAllocateIrp1(
IN CCHAR StackSize,
IN BOOLEAN ChargeQuota,
IN OUT PIRP *IrpPointer
);
VOID
FASTCALL
IovpAllocateIrp2(
IN PIRP Irp
);
VOID
FASTCALL
IovpInitializeIrp(
IN OUT PIRP Irp,
IN USHORT PacketSize,
IN CCHAR StackSize,
IN OUT PBOOLEAN InitializeHandled
);
VOID
IovpExamineIrpStackForwarding(
IN OUT PIOV_REQUEST_PACKET IovPacket,
IN BOOLEAN IsNewSession,
IN ULONG ForwardMethod,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN OUT PIO_STACK_LOCATION *IoCurrentStackLocation,
OUT PIO_STACK_LOCATION *IoLastStackLocation,
OUT ULONG *StackLocationsAdvanced
);
NTSTATUS
IovpSwapSurrogateIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
VOID
FASTCALL
IovpExamineDevObjForwarding(
IN PDEVICE_OBJECT DeviceBeingCalled,
IN PDEVICE_OBJECT DeviceLastCalled,
OUT PULONG ForwardingTechnique
);
VOID
FASTCALL
IovpFinalizeIrpSettings(
IN OUT PIOV_REQUEST_PACKET IrpTrackingData,
IN BOOLEAN SurrogateIrpSwapped
);
PDEVICE_OBJECT FASTCALL IovpGetDeviceAttachedTo(IN PDEVICE_OBJECT DeviceObject);
NTSTATUS IovpInternalCompletionTrap(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
NTSTATUS IovpInternalDeferredCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
PDEVICE_OBJECT FASTCALL IovpGetLowestDevice(IN PDEVICE_OBJECT DeviceObject);
VOID FASTCALL IovpAssertNonLegacyDevice(IN PDEVICE_OBJECT DeviceObject, IN ULONG StackFramesToSkip, IN PUCHAR FailureTxt);
BOOLEAN FASTCALL IovpIsInFdoStack(IN PDEVICE_OBJECT DeviceObject);
BOOLEAN FASTCALL IovpDoAssertIrps(VOID);
VOID FASTCALL IovpSeedStack(VOID);
VOID FASTCALL IovpSeedOnePage(VOID);
VOID FASTCALL IovpSeedTwoPages(VOID);
VOID FASTCALL IovpSeedThreePages(VOID);
VOID IovpInternalCompleteAfterWait(IN PVOID Context);
VOID IovpInternalCompleteAtDPC(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
VOID IovpAttachDeviceToDeviceStack(IN PDEVICE_OBJECT NewDevice, IN PDEVICE_OBJECT ExistingDevice);
VOID IovpDetachDevice(IN PDEVICE_OBJECT LowerDevice);
VOID IovpDeleteDevice(IN PDEVICE_OBJECT Device);
BOOLEAN IovpIsInterestingStack(IN PDEVICE_OBJECT DeviceObject);
BOOLEAN IovpIsInterestingDriver(IN PDRIVER_OBJECT DriverObject);
VOID IovpReexamineAllStacks(VOID);
BOOLEAN
IovpEnumDevObjCallback(
IN PVOID Object,
IN PUNICODE_STRING ObjectName,
IN ULONG HandleCount,
IN ULONG PointerCount,
IN PVOID Context
);
BOOLEAN
IovpAdvanceStackDownwards(
IN PIOV_STACK_LOCATION StackDataArray,
IN CCHAR CurrentLocation,
IN PIO_STACK_LOCATION IrpSp,
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
IN ULONG LocationsAdvanced,
IN BOOLEAN IsNewRequest,
IN BOOLEAN MarkAsTaken,
OUT PIOV_STACK_LOCATION *StackLocationInfo
);
#define SPECIALIRP_MARK_NON_TRACKABLE(Irp) { \
(Irp)->Flags |= IRPFLAG_EXAMINE_NOT_TRACKED; \
}
#define SPECIALIRP_IOF_CALL_1(pIrp, DeviceObject, st1) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpCallDriver1((pIrp), (DeviceObject), (st1));\
IovpSeedStack() ; \
} else { \
(st1)->IovSessionData = NULL ; \
SPECIALIRP_MARK_NON_TRACKABLE(*pIrp); \
} \
}
#define SPECIALIRP_IOF_CALL_2(Irp, DeviceObject, Routine, FinalStatus, st1) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpCallDriver2((Irp), (DeviceObject), (Routine), (FinalStatus), (st1));\
} \
}
#define SPECIALIRP_IOF_COMPLETE_1(Irp, PriorityBoost, CompletionPacket) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpCompleteRequest1((Irp), (PriorityBoost), (CompletionPacket));\
} else { \
(CompletionPacket)->IovSessionData = NULL ; \
} \
}
#define SPECIALIRP_IOF_COMPLETE_2(Irp, CompletionPacket) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpCompleteRequest2((Irp), (CompletionPacket));\
} \
}
#define SPECIALIRP_IOF_COMPLETE_3(Irp, Routine, CompletionPacket) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpCompleteRequest3((Irp), (Routine), (CompletionPacket));\
} \
}
#define SPECIALIRP_IOF_COMPLETE_4(Irp, ReturnedStatus, CompletionPacket) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpCompleteRequest4((Irp), (ReturnedStatus), (CompletionPacket));\
} \
}
#define SPECIALIRP_IOF_COMPLETE_5(Irp, CompletionPacket) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpCompleteRequest5((Irp), (CompletionPacket));\
} \
}
#define SPECIALIRP_IO_CANCEL_IRP(Irp, CancelHandled, ReturnValue) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpCancelIrp((Irp), (CancelHandled), (ReturnValue));\
} else { \
*(CancelHandled) = FALSE ; \
} \
}
#define IOP_DIAG_THROW_CHAFF_AT_STARTED_PDO_STACK(DeviceObject) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpThrowChaffAtStartedPdoStack(DeviceObject);\
}\
}
#define SPECIALIRP_IO_FREE_IRP(Irp, FreeHandled) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpFreeIrp((Irp), (FreeHandled));\
} else { \
*(FreeHandled) = FALSE ; \
} \
}
#define SPECIALIRP_IO_ALLOCATE_IRP_1(StackSize, Quota, IrpPointer) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpAllocateIrp1((StackSize), (Quota), (IrpPointer));\
} else { \
*(IrpPointer) = NULL ; \
} \
}
#define SPECIALIRP_IO_ALLOCATE_IRP_2(Irp) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpAllocateIrp2(Irp);\
}\
}
#define SPECIALIRP_IO_INITIALIZE_IRP(Irp, PacketSize, StackSize, InitHandled) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpInitializeIrp((Irp), (PacketSize), (StackSize), (InitHandled));\
} else { \
*(InitHandled) = FALSE ; \
}\
}
#define SPECIALIRP_IO_DELETE_DEVICE(Device) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpDeleteDevice(Device);\
}\
}
#define SPECIALIRP_IO_ATTACH_DEVICE_TO_DEVICE_STACK(NewDevice, ExistingDevice) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpAttachDeviceToDeviceStack(NewDevice, ExistingDevice);\
}\
}
#define SPECIALIRP_IO_DETACH_DEVICE(TargetDevice) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpDetachDevice(TargetDevice);\
}\
}
#define SPECIALIRP_WATERMARK_IRP(Irp, Flags) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpWatermarkIrp(Irp, Flags);\
}\
}
#define SPECIALIRP_IOP_COMPLETE_REQUEST(Irp, StackPointer) \
{\
if (IovpTrackingFlags && IovpDoAssertIrps()) { \
IovpCompleteRequestApc(Irp, StackPointer);\
}\
}
#if DBG
#define TRACKIRP_DBGPRINT(txt,level) \
{ \
if (IovpIrpTrackingSpewLevel>(level)) { \
DbgPrint##txt ; \
}\
}
#else
#define TRACKIRP_DBGPRINT(txt,level)
#endif
#endif // NO_SPECIAL_IRP
#endif // _TRACKIRP_H_