iohandle.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. iohandle.c
  5. Abstract:
  6. This module implements support for managing I/O handles.
  7. Author:
  8. Evan Green 25-Apr-2013
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/kernel.h>
  16. #include "iop.h"
  17. //
  18. // ---------------------------------------------------------------- Definitions
  19. //
  20. #define IO_HANDLE_ALLOCATION_TAG 0x61486F49 // 'aHoI'
  21. #define IO_HANDLE_MAX_REFERENCE_COUNT 0x10000000
  22. //
  23. // ------------------------------------------------------ Data Type Definitions
  24. //
  25. //
  26. // ----------------------------------------------- Internal Function Prototypes
  27. //
  28. //
  29. // -------------------------------------------------------------------- Globals
  30. //
  31. //
  32. // ------------------------------------------------------------------ Functions
  33. //
  34. KERNEL_API
  35. ULONG
  36. IoGetIoHandleAccessPermissions (
  37. PIO_HANDLE IoHandle
  38. )
  39. /*++
  40. Routine Description:
  41. This routine returns the access permissions for the given I/O handle.
  42. Arguments:
  43. IoHandle - Supplies a pointer to an I/O handle.
  44. Return Value:
  45. Returns the access permissions for the given I/O handle.
  46. --*/
  47. {
  48. return IoHandle->Access;
  49. }
  50. KERNEL_API
  51. ULONG
  52. IoGetIoHandleOpenFlags (
  53. PIO_HANDLE IoHandle
  54. )
  55. /*++
  56. Routine Description:
  57. This routine returns the current open flags for a given I/O handle. Some
  58. of these flags can change.
  59. Arguments:
  60. IoHandle - Supplies a pointer to an I/O handle.
  61. Return Value:
  62. Returns the current open flags for the I/O handle.
  63. --*/
  64. {
  65. return IoHandle->OpenFlags;
  66. }
  67. VOID
  68. IoIoHandleAddReference (
  69. PIO_HANDLE IoHandle
  70. )
  71. /*++
  72. Routine Description:
  73. This routine increments the reference count on an I/O handle.
  74. Arguments:
  75. IoHandle - Supplies a pointer to the I/O handle.
  76. Return Value:
  77. None.
  78. --*/
  79. {
  80. ULONG OldValue;
  81. OldValue = RtlAtomicAdd32(&(IoHandle->ReferenceCount), 1);
  82. ASSERT((OldValue != 0) && (OldValue < IO_HANDLE_MAX_REFERENCE_COUNT));
  83. return;
  84. }
  85. KSTATUS
  86. IoIoHandleReleaseReference (
  87. PIO_HANDLE IoHandle
  88. )
  89. /*++
  90. Routine Description:
  91. This routine decrements the reference count on an I/O handle. If the
  92. reference count becomes zero, the I/O handle will be destroyed.
  93. Arguments:
  94. IoHandle - Supplies a pointer to the I/O handle.
  95. Return Value:
  96. None.
  97. --*/
  98. {
  99. ULONG OldValue;
  100. KSTATUS Status;
  101. Status = STATUS_SUCCESS;
  102. OldValue = RtlAtomicAdd32(&(IoHandle->ReferenceCount), -1);
  103. ASSERT((OldValue != 0) && (OldValue < IO_HANDLE_MAX_REFERENCE_COUNT));
  104. if (OldValue == 1) {
  105. Status = IopClose(IoHandle);
  106. if (!KSUCCESS(Status)) {
  107. //
  108. // Restore the reference to the I/O handle.
  109. //
  110. RtlAtomicAdd32(&(IoHandle->ReferenceCount), 1);
  111. return Status;
  112. }
  113. MmFreePagedPool(IoHandle);
  114. }
  115. return Status;
  116. }
  117. PIMAGE_SECTION_LIST
  118. IoGetImageSectionListFromIoHandle (
  119. PIO_HANDLE IoHandle
  120. )
  121. /*++
  122. Routine Description:
  123. This routine gets the image section list for the given I/O handle.
  124. Arguments:
  125. IoHandle - Supplies a pointer to an I/O handle.
  126. Return Value:
  127. Returns a pointer to the I/O handles image section list or NULL on failure.
  128. --*/
  129. {
  130. PFILE_OBJECT FileObject;
  131. FileObject = IoHandle->FileObject;
  132. return IopGetImageSectionListFromFileObject(FileObject);
  133. }
  134. BOOL
  135. IoIoHandleIsCacheable (
  136. PIO_HANDLE IoHandle
  137. )
  138. /*++
  139. Routine Description:
  140. This routine determines whether or not data for the I/O object specified by
  141. the given handle is cached in the page cache.
  142. Arguments:
  143. IoHandle - Supplies a pointer to an I/O handle.
  144. Return Value:
  145. Returns TRUE if the I/O handle's object is cached or FALSE otherwise.
  146. --*/
  147. {
  148. PFILE_OBJECT FileObject;
  149. //
  150. // The I/O handle is deemed cacheable if the file object is cacheable.
  151. //
  152. FileObject = IoHandle->FileObject;
  153. if (IO_IS_FILE_OBJECT_CACHEABLE(FileObject) != FALSE) {
  154. return TRUE;
  155. }
  156. return FALSE;
  157. }
  158. KSTATUS
  159. IopCreateIoHandle (
  160. PIO_HANDLE *Handle
  161. )
  162. /*++
  163. Routine Description:
  164. This routine creates a new I/O handle with a reference count of one.
  165. Arguments:
  166. Handle - Supplies a pointer where a pointer to the new I/O handle will be
  167. returned on success.
  168. Return Value:
  169. Status code.
  170. --*/
  171. {
  172. PIO_HANDLE NewHandle;
  173. KSTATUS Status;
  174. //
  175. // Create the I/O handle structure.
  176. //
  177. NewHandle = MmAllocatePagedPool(sizeof(IO_HANDLE),
  178. IO_HANDLE_ALLOCATION_TAG);
  179. if (NewHandle == NULL) {
  180. Status = STATUS_INSUFFICIENT_RESOURCES;
  181. goto CreateIoHandleEnd;
  182. }
  183. RtlZeroMemory(NewHandle, sizeof(IO_HANDLE));
  184. NewHandle->HandleType = IoHandleTypeDefault;
  185. NewHandle->ReferenceCount = 1;
  186. ASSERT(NewHandle->DeviceContext == NULL);
  187. Status = STATUS_SUCCESS;
  188. CreateIoHandleEnd:
  189. if (!KSUCCESS(Status)) {
  190. if (NewHandle != NULL) {
  191. MmFreePagedPool(NewHandle);
  192. NewHandle = NULL;
  193. }
  194. }
  195. *Handle = NewHandle;
  196. return Status;
  197. }
  198. VOID
  199. IopOverwriteIoHandle (
  200. PIO_HANDLE Destination,
  201. PIO_HANDLE IoSource
  202. )
  203. /*++
  204. Routine Description:
  205. This routine takes the contents of the given source handle and overwrites
  206. the destination handle with it. I/O actions performed on the destination
  207. handle appear as if they were done to the I/O object of the source handle.
  208. This replacement does not replace any information about the original path
  209. opened in the destination. It also does not modify the access and open
  210. flags in the destination. This routine is not thread safe.
  211. Arguments:
  212. Destination - Supplies a pointer to the I/O handle that should magically
  213. redirect elsewhere.
  214. IoSource - Supplies a pointer to the I/O handle that contains the
  215. underlying I/O object the destination should interact with.
  216. Return Value:
  217. None.
  218. --*/
  219. {
  220. PFILE_OBJECT OldFileObject;
  221. //
  222. // The destination I/O handle really shouldn't be handed to anyone yet,
  223. // since I/O might get wonky during the switch.
  224. //
  225. ASSERT(Destination->ReferenceCount == 1);
  226. OldFileObject = Destination->FileObject;
  227. Destination->FileObject = IoSource->FileObject;
  228. if (OldFileObject != Destination->PathPoint.PathEntry->FileObject) {
  229. IopFileObjectReleaseReference(OldFileObject);
  230. }
  231. IopFileObjectAddReference(IoSource->FileObject);
  232. return;
  233. }
  234. //
  235. // --------------------------------------------------------- Internal Functions
  236. //