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.

158 lines
5.5 KiB

  1. #ifndef __IrpQueue_h__
  2. #define __IrpQueue_h__
  3. extern "C"
  4. {
  5. #include <wdm.h>
  6. }
  7. class CTempIrpQueue
  8. {
  9. friend class CGuardedIrpQueue;
  10. public:
  11. CTempIrpQueue()
  12. {
  13. InitializeListHead(&m_QueueHead);
  14. m_fLIFO = FALSE;
  15. }
  16. ~CTempIrpQueue()
  17. {
  18. ASSERT(IsListEmpty(&m_QueueHead));
  19. }
  20. PIRP Remove();
  21. private:
  22. LIST_ENTRY m_QueueHead;
  23. BOOLEAN m_fLIFO;
  24. };
  25. class CGuardedIrpQueue
  26. {
  27. public:
  28. friend void _stdcall DriverCancel(PDEVICE_OBJECT pDeviceObject, PIRP pIrp);
  29. friend class CShareIrpQueueSpinLock;
  30. typedef void (_stdcall*PFN_DEC_IRP_COUNT)(PVOID pvContext);
  31. //c'tor's and d'tors are often not called in drivers, either
  32. //because the instance is global, or because they are a part of a
  33. //larger structure (such as a DeviceExtension) which is allocated as
  34. //an unstructured block of memory, so we insist that they do nothing.
  35. //call Init and Destroy instead. (A more systematic approach to C++
  36. //in a driver could solve this problem).
  37. CGuardedIrpQueue(){}
  38. ~CGuardedIrpQueue(){}
  39. void Init(int iFlags, PFN_DEC_IRP_COUNT pfnDecIrpCount, PVOID pvContext);
  40. void Destroy(NTSTATUS NtStatus=STATUS_DELETE_PENDING);
  41. NTSTATUS Add(PIRP pIrp);
  42. PIRP Remove();
  43. PIRP RemoveByPointer(PIRP pIrp);
  44. ULONG RemoveByFileObject(PFILE_OBJECT pFileObject, CTempIrpQueue *pTempIrpQueue);
  45. ULONG RemoveAll(CTempIrpQueue *pTempIrpQueue);
  46. void CancelIrp(PIRP pIrp);
  47. void CancelByFileObject(PFILE_OBJECT pFileObject);
  48. void CancelAll(NTSTATUS NtStatus = STATUS_CANCELLED);
  49. //Flags for constructor
  50. static const int CANCEL_IRPS_ON_DELETE; //= 0x00000001;
  51. static const int PRESERVE_QUEUE_ORDER; //= 0x00000002;
  52. static const int LIFO_QUEUE_ORDER; //= 0x00000004;
  53. private:
  54. //The real cancel routine
  55. void CancelRoutine(PIRP pIrp);
  56. //Implementation sans spin locks
  57. NTSTATUS AddImpl(PIRP pIrp, KIRQL OldIrql);
  58. PIRP RemoveImpl();
  59. PIRP RemoveByPointerImpl(PIRP pIrp);
  60. ULONG RemoveByFileObjectImpl(PFILE_OBJECT pFileObject, CTempIrpQueue *pTempIrpQueue);
  61. ULONG RemoveAllImpl(CTempIrpQueue *pTempIrpQueue);
  62. LIST_ENTRY m_QueueHead;
  63. KSPIN_LOCK m_QueueLock;
  64. int m_iFlags;
  65. PFN_DEC_IRP_COUNT m_pfnDecIrpCount;
  66. PVOID m_pvContext;
  67. };
  68. //
  69. //
  70. // @class CShareIrpQueueSpinLock | Allows sharing of SpinLock from CGuardedIrpQueue
  71. //
  72. // @topic Using CShareIrpQueueSpinLock |
  73. // ** Should only be instantiated on the stack.
  74. // ** A single instance should be used by only one thread. i.e. no static instances
  75. // ** Inside a single function, do not CGuardedIrpQueue's accessor, rather
  76. // ** use the interface provided by CShareIrpQueueSpinLock
  77. //
  78. class CShareIrpQueueSpinLock
  79. {
  80. public:
  81. CShareIrpQueueSpinLock(CGuardedIrpQueue *pIrpQueue) :
  82. m_pIrpQueue(pIrpQueue),
  83. m_fIsHeld(FALSE)
  84. #if (DBG==1)
  85. ,m_debug_ThreadContext(KeGetCurrentThread())
  86. #endif
  87. {}
  88. ~CShareIrpQueueSpinLock()
  89. {
  90. ASSERT(!m_fIsHeld && "You must release (or AddAndRelease) the spin lock before this instance goes of scope!");
  91. ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack" );
  92. }
  93. //Functions to access mutex
  94. void Acquire()
  95. {
  96. ASSERT(!m_fIsHeld && "An attempt to acquire a spin lock twice in the same thread!");
  97. ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!");
  98. m_fIsHeld = TRUE;
  99. KeAcquireSpinLock(&m_pIrpQueue->m_QueueLock, &m_OldIrql);
  100. }
  101. void Release()
  102. {
  103. ASSERT(m_fIsHeld && "An attempt to release a spin lock that had not been acquired, (reminder: AddAndRelease also Releases)!");
  104. ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!");
  105. m_fIsHeld = FALSE;
  106. KeReleaseSpinLock(&m_pIrpQueue->m_QueueLock, m_OldIrql);
  107. }
  108. //Functions to access IrpQueue
  109. NTSTATUS AddAndRelease(PIRP pIrp)
  110. {
  111. ASSERT(m_fIsHeld && "Use CGuardedIrpQueue if you do not need to share the SpinLock!");
  112. ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!");
  113. m_fIsHeld=FALSE;
  114. return m_pIrpQueue->AddImpl(pIrp, m_OldIrql);
  115. }
  116. PIRP Remove()
  117. {
  118. ASSERT(m_fIsHeld && "Use CGuardedIrpQueue if you do not need to share the SpinLock!");
  119. ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!");
  120. return m_pIrpQueue->RemoveImpl();
  121. }
  122. PIRP RemoveByPointer(PIRP pIrp)
  123. {
  124. ASSERT(m_fIsHeld && "Use CGuardedIrpQueue if you do not need to share the SpinLock!");
  125. ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!");
  126. return m_pIrpQueue->RemoveByPointerImpl(pIrp);
  127. }
  128. ULONG RemoveByFileObject(PFILE_OBJECT pFileObject, CTempIrpQueue *pTempIrpQueue)
  129. {
  130. ASSERT(m_fIsHeld && "Use CGuardedIrpQueue if you do not need to share the SpinLock!");
  131. ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!");
  132. return m_pIrpQueue->RemoveByFileObjectImpl(pFileObject,pTempIrpQueue);
  133. }
  134. ULONG RemoveAll(CTempIrpQueue *pTempIrpQueue)
  135. {
  136. ASSERT(m_fIsHeld && "Use CGuardedIrpQueue if you do not need to share the SpinLock!");
  137. ASSERT(m_debug_ThreadContext==KeGetCurrentThread() && "class instance should be on local stack!");
  138. return m_pIrpQueue->RemoveAllImpl(pTempIrpQueue);
  139. }
  140. private:
  141. CGuardedIrpQueue *m_pIrpQueue;
  142. BOOLEAN m_fIsHeld;
  143. KIRQL m_OldIrql;
  144. #if (DBG==1)
  145. PKTHREAD m_debug_ThreadContext;
  146. #endif
  147. };
  148. #endif //__IrpQueue_h__