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.

300 lines
8.1 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. csq.h
  5. Abstract:
  6. This header exposes the cancel safe queue DDIs for use on Win2K at later.
  7. Drivers that use this header should link to csq.lib. If a driver only needs
  8. to work on XP or later, neither this header or the lib are required (the
  9. XP kernel supports the cancel safe queue DDIs natively.)
  10. Author:
  11. Nar Ganapathy (narg) 1-Jan-1999
  12. Revision History:
  13. --*/
  14. // Cancel SAFE DDI set start
  15. //
  16. // The following DDIs are to help ease the pain of writing queue packages that
  17. // handle the cancellation race well. The idea of this set of DDIs is to not
  18. // force a single queue data structure but allow the cancel logic to be hidden
  19. // from the drivers. A driver implements a queue and as part of its header
  20. // includes the IO_CSQ structure. In its initialization routine it calls
  21. // IoInitializeCsq. Then in the dispatch routine when the driver wants to
  22. // insert an IRP into the queue it calls IoCsqInsertIrp. When the driver wants
  23. // to remove something from the queue it calls IoCsqRemoveIrp. Note that Insert
  24. // can fail if the IRP was cancelled in the meantime. Remove can also fail if
  25. // the IRP was already cancelled.
  26. //
  27. // There are typically two modes where drivers queue IRPs. These two modes are
  28. // covered by the cancel safe queue DDI set.
  29. //
  30. // Mode 1:
  31. // One is where the driver queues the IRP and at some later
  32. // point in time dequeues an IRP and issues the IO request.
  33. // For this mode the driver should use IoCsqInsertIrp and IoCsqRemoveNextIrp.
  34. // The driver in this case is expected to pass NULL to the irp context
  35. // parameter in IoInsertIrp.
  36. //
  37. // Mode 2:
  38. // In this the driver queues theIRP, issues the IO request (like issuing a DMA
  39. // request or writing to a register) and when the IO request completes (either
  40. // using a DPC or timer) the driver dequeues the IRP and completes it. For this
  41. // mode the driver should use IoCsqInsertIrp and IoCsqRemoveIrp. In this case
  42. // the driver should allocate an IRP context and pass it in to IoCsqInsertIrp.
  43. // The cancel DDI code creates an association between the IRP and the context
  44. // and thus ensures that when the time comes to remove the IRP it can ascertain
  45. // correctly.
  46. //
  47. // Note that the cancel DDI set assumes that the field DriverContext[3] is
  48. // always available for use and that the driver does not use it.
  49. //
  50. #ifndef _CSQ_H_
  51. #define _CSQ_H_
  52. #pragma once
  53. #ifdef __cplusplus
  54. extern "C" {
  55. #endif
  56. //
  57. // If the wdm.h/ntddk.h we're including already defines cancel safe DDIs, we
  58. // can skip the structure definitions. Otherwise, we do the rest here:
  59. //
  60. #ifndef IO_TYPE_CSQ_IRP_CONTEXT
  61. //
  62. // Bookkeeping structure. This should be opaque to drivers.
  63. // Drivers typically include this as part of their queue headers.
  64. // Given a CSQ pointer the driver should be able to get its
  65. // queue header using CONTAINING_RECORD macro
  66. //
  67. typedef struct _IO_CSQ IO_CSQ, *PIO_CSQ;
  68. #define IO_TYPE_CSQ_IRP_CONTEXT 1
  69. #define IO_TYPE_CSQ 2
  70. //
  71. // IRP context structure. This structure is necessary if the driver is using
  72. // the second mode.
  73. //
  74. typedef struct _IO_CSQ_IRP_CONTEXT {
  75. ULONG Type;
  76. PIRP Irp;
  77. PIO_CSQ Csq;
  78. } IO_CSQ_IRP_CONTEXT, *PIO_CSQ_IRP_CONTEXT;
  79. //
  80. // Routines that insert/remove IRP
  81. //
  82. typedef VOID
  83. (*PIO_CSQ_INSERT_IRP)(
  84. IN struct _IO_CSQ *Csq,
  85. IN PIRP Irp
  86. );
  87. typedef VOID
  88. (*PIO_CSQ_REMOVE_IRP)(
  89. IN PIO_CSQ Csq,
  90. IN PIRP Irp
  91. );
  92. //
  93. // Retrieves next entry after Irp from the queue.
  94. // Returns NULL if there are no entries in the queue.
  95. // If Irp is NUL, returns the entry in the head of the queue.
  96. // This routine does not remove the IRP from the queue.
  97. //
  98. typedef PIRP
  99. (*PIO_CSQ_PEEK_NEXT_IRP)(
  100. IN PIO_CSQ Csq,
  101. IN PIRP Irp,
  102. IN PVOID PeekContext
  103. );
  104. //
  105. // Lock routine that protects the cancel safe queue.
  106. //
  107. typedef VOID
  108. (*PIO_CSQ_ACQUIRE_LOCK)(
  109. IN PIO_CSQ Csq,
  110. OUT PKIRQL Irql
  111. );
  112. typedef VOID
  113. (*PIO_CSQ_RELEASE_LOCK)(
  114. IN PIO_CSQ Csq,
  115. IN KIRQL Irql
  116. );
  117. //
  118. // Completes the IRP with STATUS_CANCELLED. IRP is guaranteed to be valid
  119. // In most cases this routine just calls IoCompleteRequest(Irp, STATUS_CANCELLED);
  120. //
  121. typedef VOID
  122. (*PIO_CSQ_COMPLETE_CANCELED_IRP)(
  123. IN PIO_CSQ Csq,
  124. IN PIRP Irp
  125. );
  126. //
  127. // Bookkeeping structure. This should be opaque to drivers.
  128. // Drivers typically include this as part of their queue headers.
  129. // Given a CSQ pointer the driver should be able to get its
  130. // queue header using CONTAINING_RECORD macro
  131. //
  132. typedef struct _IO_CSQ {
  133. ULONG Type;
  134. PIO_CSQ_INSERT_IRP CsqInsertIrp;
  135. PIO_CSQ_REMOVE_IRP CsqRemoveIrp;
  136. PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp;
  137. PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock;
  138. PIO_CSQ_RELEASE_LOCK CsqReleaseLock;
  139. PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp;
  140. PVOID ReservePointer; // Future expansion
  141. } IO_CSQ, *PIO_CSQ;
  142. #endif // IO_TYPE_CSQ_IRP_CONTEXT
  143. //
  144. // Add in new extensions to the csq.h library.
  145. //
  146. #ifndef IO_TYPE_CSQ_EX
  147. #define IO_TYPE_CSQ_EX 3
  148. typedef NTSTATUS
  149. (*PIO_CSQ_INSERT_IRP_EX)(
  150. IN struct _IO_CSQ *Csq,
  151. IN PIRP Irp,
  152. IN PVOID InsertContext
  153. );
  154. #endif // IO_TYPE_CSQ_EX
  155. //
  156. // These defines ensure the backward compatible CSQ library can be used within
  157. // the XP build environment in which the kernel supports the functions natively.
  158. //
  159. #define CSQLIB_DDI(x) Wdmlib##x
  160. //
  161. // Initializes the cancel queue structure.
  162. //
  163. #undef IoCsqInitialize
  164. #define IoCsqInitialize WdmlibIoCsqInitialize
  165. NTSTATUS
  166. CSQLIB_DDI(IoCsqInitialize)(
  167. IN PIO_CSQ Csq,
  168. IN PIO_CSQ_INSERT_IRP CsqInsertIrp,
  169. IN PIO_CSQ_REMOVE_IRP CsqRemoveIrp,
  170. IN PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp,
  171. IN PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock,
  172. IN PIO_CSQ_RELEASE_LOCK CsqReleaseLock,
  173. IN PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp
  174. );
  175. #undef IoCsqInitializeEx
  176. #define IoCsqInitializeEx WdmlibIoCsqInitializeEx
  177. NTSTATUS
  178. CSQLIB_DDI(IoCsqInitializeEx)(
  179. IN PIO_CSQ Csq,
  180. IN PIO_CSQ_INSERT_IRP_EX CsqInsertIrp,
  181. IN PIO_CSQ_REMOVE_IRP CsqRemoveIrp,
  182. IN PIO_CSQ_PEEK_NEXT_IRP CsqPeekNextIrp,
  183. IN PIO_CSQ_ACQUIRE_LOCK CsqAcquireLock,
  184. IN PIO_CSQ_RELEASE_LOCK CsqReleaseLock,
  185. IN PIO_CSQ_COMPLETE_CANCELED_IRP CsqCompleteCanceledIrp
  186. );
  187. //
  188. // The caller calls this routine to insert the IRP and return STATUS_PENDING.
  189. //
  190. #undef IoCsqInsertIrp
  191. #define IoCsqInsertIrp WdmlibIoCsqInsertIrp
  192. VOID
  193. CSQLIB_DDI(IoCsqInsertIrp)(
  194. IN PIO_CSQ Csq,
  195. IN PIRP Irp,
  196. IN PIO_CSQ_IRP_CONTEXT Context
  197. );
  198. #undef IoCsqInsertIrpEx
  199. #define IoCsqInsertIrpEx WdmlibIoCsqInsertIrpEx
  200. NTSTATUS
  201. CSQLIB_DDI(IoCsqInsertIrpEx)(
  202. IN PIO_CSQ Csq,
  203. IN PIRP Irp,
  204. IN PIO_CSQ_IRP_CONTEXT Context,
  205. IN PVOID InsertContext
  206. );
  207. //
  208. // Returns an IRP if one can be found. NULL otherwise.
  209. //
  210. #undef IoCsqRemoveNextIrp
  211. #define IoCsqRemoveNextIrp WdmlibIoCsqRemoveNextIrp
  212. PIRP
  213. CSQLIB_DDI(IoCsqRemoveNextIrp)(
  214. IN PIO_CSQ Csq,
  215. IN PVOID PeekContext
  216. );
  217. //
  218. // This routine is called from timeout or DPCs.
  219. // The context is presumably part of the DPC or timer context.
  220. // If succesfull returns the IRP associated with context.
  221. //
  222. #undef IoCsqRemoveIrp
  223. #define IoCsqRemoveIrp WdmlibIoCsqRemoveIrp
  224. PIRP
  225. CSQLIB_DDI(IoCsqRemoveIrp)(
  226. IN PIO_CSQ Csq,
  227. IN PIO_CSQ_IRP_CONTEXT Context
  228. );
  229. #ifdef __cplusplus
  230. } // extern "C"
  231. #endif
  232. #endif // _CSQ_H_
  233. // Cancel SAFE DDI set end