Leaked source code of windows server 2003
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
#ifndef __IrpQueue_h__
#define __IrpQueue_h__
extern "C" { #include <wdm.h>
}
class CTempIrpQueue { friend class CGuardedIrpQueue; public: CTempIrpQueue() { InitializeListHead(&m_QueueHead); m_fLIFO = FALSE; } ~CTempIrpQueue() { ASSERT(IsListEmpty(&m_QueueHead)); } PIRP Remove(); private: LIST_ENTRY m_QueueHead; BOOLEAN m_fLIFO; };
class CGuardedIrpQueue { public: friend void _stdcall DriverCancel(PDEVICE_OBJECT pDeviceObject, PIRP pIrp); friend class CShareIrpQueueSpinLock; typedef void (_stdcall*PFN_DEC_IRP_COUNT)(PVOID pvContext); //c'tor's and d'tors are often not called in drivers, either
//because the instance is global, or because they are a part of a
//larger structure (such as a DeviceExtension) which is allocated as
//an unstructured block of memory, so we insist that they do nothing.
//call Init and Destroy instead. (A more systematic approach to C++
//in a driver could solve this problem).
CGuardedIrpQueue(){} ~CGuardedIrpQueue(){} void Init(int iFlags, PFN_DEC_IRP_COUNT pfnDecIrpCount, PVOID pvContext); void Destroy(NTSTATUS NtStatus=STATUS_DELETE_PENDING); NTSTATUS Add(PIRP pIrp); PIRP Remove(); PIRP RemoveByPointer(PIRP pIrp); ULONG RemoveByFileObject(PFILE_OBJECT pFileObject, CTempIrpQueue *pTempIrpQueue); ULONG RemoveAll(CTempIrpQueue *pTempIrpQueue); void CancelIrp(PIRP pIrp); void CancelByFileObject(PFILE_OBJECT pFileObject); void CancelAll(NTSTATUS NtStatus = STATUS_CANCELLED); //Flags for constructor
static const int CANCEL_IRPS_ON_DELETE; //= 0x00000001;
static const int PRESERVE_QUEUE_ORDER; //= 0x00000002;
static const int LIFO_QUEUE_ORDER; //= 0x00000004;
private: //The real cancel routine
void CancelRoutine(PIRP pIrp); //Implementation sans spin locks
NTSTATUS AddImpl(PIRP pIrp, KIRQL OldIrql); PIRP RemoveImpl(); PIRP RemoveByPointerImpl(PIRP pIrp); ULONG RemoveByFileObjectImpl(PFILE_OBJECT pFileObject, CTempIrpQueue *pTempIrpQueue); ULONG RemoveAllImpl(CTempIrpQueue *pTempIrpQueue); LIST_ENTRY m_QueueHead; KSPIN_LOCK m_QueueLock; int m_iFlags; PFN_DEC_IRP_COUNT m_pfnDecIrpCount; PVOID m_pvContext; };
//
//
// @class CShareIrpQueueSpinLock | Allows sharing of SpinLock from CGuardedIrpQueue
//
// @topic Using CShareIrpQueueSpinLock |
// ** Should only be instantiated on the stack.
// ** A single instance should be used by only one thread. i.e. no static instances
// ** Inside a single function, do not CGuardedIrpQueue's accessor, rather
// ** use the interface provided by CShareIrpQueueSpinLock
//
class CShareIrpQueueSpinLock { public: CShareIrpQueueSpinLock(CGuardedIrpQueue *pIrpQueue) : m_pIrpQueue(pIrpQueue), m_fIsHeld(FALSE) #if (DBG==1)
,m_debug_ThreadContext(KeGetCurrentThread()) #endif
{} ~CShareIrpQueueSpinLock() { ASSERT(!m_fIsHeld && "You must release (or AddAndRelease) the spin lock before this instance goes of scope!"); ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack" ); } //Functions to access mutex
void Acquire() { ASSERT(!m_fIsHeld && "An attempt to acquire a spin lock twice in the same thread!"); ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!"); m_fIsHeld = TRUE; KeAcquireSpinLock(&m_pIrpQueue->m_QueueLock, &m_OldIrql); } void Release() { ASSERT(m_fIsHeld && "An attempt to release a spin lock that had not been acquired, (reminder: AddAndRelease also Releases)!"); ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!"); m_fIsHeld = FALSE; KeReleaseSpinLock(&m_pIrpQueue->m_QueueLock, m_OldIrql); } //Functions to access IrpQueue
NTSTATUS AddAndRelease(PIRP pIrp) { ASSERT(m_fIsHeld && "Use CGuardedIrpQueue if you do not need to share the SpinLock!"); ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!"); m_fIsHeld=FALSE; return m_pIrpQueue->AddImpl(pIrp, m_OldIrql); } PIRP Remove() { ASSERT(m_fIsHeld && "Use CGuardedIrpQueue if you do not need to share the SpinLock!"); ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!"); return m_pIrpQueue->RemoveImpl(); } PIRP RemoveByPointer(PIRP pIrp) { ASSERT(m_fIsHeld && "Use CGuardedIrpQueue if you do not need to share the SpinLock!"); ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!"); return m_pIrpQueue->RemoveByPointerImpl(pIrp); } ULONG RemoveByFileObject(PFILE_OBJECT pFileObject, CTempIrpQueue *pTempIrpQueue) { ASSERT(m_fIsHeld && "Use CGuardedIrpQueue if you do not need to share the SpinLock!"); ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!"); return m_pIrpQueue->RemoveByFileObjectImpl(pFileObject,pTempIrpQueue); } ULONG RemoveAll(CTempIrpQueue *pTempIrpQueue) { ASSERT(m_fIsHeld && "Use CGuardedIrpQueue if you do not need to share the SpinLock!"); ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!"); return m_pIrpQueue->RemoveAllImpl(pTempIrpQueue); } private: CGuardedIrpQueue *m_pIrpQueue; BOOLEAN m_fIsHeld; KIRQL m_OldIrql; #if (DBG==1)
PKTHREAD m_debug_ThreadContext; #endif
}; #endif //__IrpQueue_h__
|