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.

375 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. read.c
  5. Abstract:
  6. This module implements the file read routine for MSFS called by the
  7. dispatch driver.
  8. Author:
  9. Manny Weiser (mannyw) 15-Jan-1991
  10. Revision History:
  11. --*/
  12. #include "mailslot.h"
  13. //
  14. // The debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_READ)
  17. //
  18. // local procedure prototypes
  19. //
  20. NTSTATUS
  21. MsCommonRead (
  22. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  23. IN PIRP Irp
  24. );
  25. NTSTATUS
  26. MsCreateWorkContext (
  27. PDEVICE_OBJECT DeviceObject,
  28. PLARGE_INTEGER Timeout,
  29. PFCB Fcb,
  30. PIRP Irp,
  31. PWORK_CONTEXT *ppWorkContext
  32. );
  33. #ifdef ALLOC_PRAGMA
  34. #pragma alloc_text( PAGE, MsCommonRead )
  35. #pragma alloc_text( PAGE, MsFsdRead )
  36. #pragma alloc_text( PAGE, MsCreateWorkContext )
  37. #endif
  38. NTSTATUS
  39. MsFsdRead (
  40. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  41. IN PIRP Irp
  42. )
  43. /*++
  44. Routine Description:
  45. This routine implements the FSD part of the NtReadFile API calls.
  46. Arguments:
  47. MsfsDeviceObject - Supplies the device object to use.
  48. Irp - Supplies the Irp being processed
  49. Return Value:
  50. NTSTATUS - The Fsd status for the Irp
  51. --*/
  52. {
  53. NTSTATUS status;
  54. PAGED_CODE();
  55. DebugTrace(+1, Dbg, "MsFsdRead\n", 0);
  56. FsRtlEnterFileSystem();
  57. status = MsCommonRead( MsfsDeviceObject, Irp );
  58. FsRtlExitFileSystem();
  59. //
  60. // Return to the caller.
  61. //
  62. DebugTrace(-1, Dbg, "MsFsdRead -> %08lx\n", status );
  63. return status;
  64. }
  65. NTSTATUS
  66. MsCreateWorkContext (
  67. PDEVICE_OBJECT DeviceObject,
  68. PLARGE_INTEGER Timeout,
  69. PFCB Fcb,
  70. PIRP Irp,
  71. PWORK_CONTEXT *ppWorkContext
  72. )
  73. /*++
  74. Routine Description:
  75. This routine build a timeout work context.
  76. Arguments:
  77. Return Value:
  78. NTSTATUS - Status associated with the call
  79. --*/
  80. {
  81. PKTIMER Timer;
  82. PKDPC Dpc;
  83. PWORK_CONTEXT WorkContext;
  84. //
  85. // Allocate memory for the work context.
  86. //
  87. *ppWorkContext = NULL;
  88. WorkContext = MsAllocateNonPagedPoolWithQuota( sizeof(WORK_CONTEXT),
  89. 'wFsM' );
  90. if (WorkContext == NULL) {
  91. return STATUS_INSUFFICIENT_RESOURCES;
  92. }
  93. Timer = &WorkContext->Timer;
  94. Dpc = &WorkContext->Dpc;
  95. //
  96. // Fill in the work context structure.
  97. //
  98. WorkContext->Irp = Irp;
  99. WorkContext->Fcb = Fcb;
  100. WorkContext->WorkItem = IoAllocateWorkItem (DeviceObject);
  101. if (WorkContext->WorkItem == NULL) {
  102. MsFreePool (WorkContext);
  103. return STATUS_INSUFFICIENT_RESOURCES;
  104. }
  105. //
  106. // Now set up a DPC and set the timer to the user specified
  107. // timeout.
  108. //
  109. KeInitializeTimer( Timer );
  110. KeInitializeDpc( Dpc, MsReadTimeoutHandler, WorkContext );
  111. MsAcquireGlobalLock();
  112. MsReferenceNode( &Fcb->Header );
  113. MsReleaseGlobalLock();
  114. *ppWorkContext = WorkContext;
  115. return STATUS_SUCCESS;
  116. }
  117. NTSTATUS
  118. MsCommonRead (
  119. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  120. IN PIRP Irp
  121. )
  122. /*++
  123. Routine Description:
  124. This is the common routine for reading a file.
  125. Arguments:
  126. Irp - Supplies the Irp to process
  127. Return Value:
  128. NTSTATUS - the return status for the operation
  129. --*/
  130. {
  131. NTSTATUS status;
  132. PIO_STACK_LOCATION irpSp;
  133. NODE_TYPE_CODE nodeTypeCode;
  134. PFCB fcb;
  135. PVOID fsContext2;
  136. PIRP readIrp;
  137. PUCHAR readBuffer;
  138. ULONG readLength;
  139. ULONG readRemaining;
  140. PDATA_QUEUE readQueue;
  141. ULONG messageLength;
  142. LARGE_INTEGER timeout;
  143. PWORK_CONTEXT workContext = NULL;
  144. PAGED_CODE();
  145. irpSp = IoGetCurrentIrpStackLocation( Irp );
  146. DebugTrace(+1, Dbg, "MsCommonRead\n", 0);
  147. DebugTrace( 0, Dbg, "MsfsDeviceObject = %08lx\n", (ULONG)MsfsDeviceObject);
  148. DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp);
  149. DebugTrace( 0, Dbg, "FileObject = %08lx\n", (ULONG)irpSp->FileObject);
  150. //
  151. // Get the FCB and make sure that the file isn't closing.
  152. //
  153. if ((nodeTypeCode = MsDecodeFileObject( irpSp->FileObject,
  154. (PVOID *)&fcb,
  155. &fsContext2 )) == NTC_UNDEFINED) {
  156. DebugTrace(0, Dbg, "Mailslot is disconnected from us\n", 0);
  157. MsCompleteRequest( Irp, STATUS_FILE_FORCED_CLOSED );
  158. status = STATUS_FILE_FORCED_CLOSED;
  159. DebugTrace(-1, Dbg, "MsCommonRead -> %08lx\n", status );
  160. return status;
  161. }
  162. //
  163. // Allow read operations only if this is a server side handle to
  164. // a mailslot file.
  165. //
  166. if (nodeTypeCode != MSFS_NTC_FCB) {
  167. DebugTrace(0, Dbg, "FileObject is not the correct type\n", 0);
  168. MsDereferenceNode( (PNODE_HEADER)fcb );
  169. MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
  170. status = STATUS_INVALID_PARAMETER;
  171. DebugTrace(-1, Dbg, "MsCommonRead -> %08lx\n", status );
  172. return status;
  173. }
  174. //
  175. // Make local copies of the input parameters to make things easier, and
  176. // initialize the main variables that describe the read command.
  177. //
  178. readIrp = Irp;
  179. readBuffer = Irp->UserBuffer;
  180. readLength = irpSp->Parameters.Read.Length;
  181. readRemaining = readLength;
  182. readQueue = &fcb->DataQueue;
  183. //
  184. // Acquire exclusive access to the FCB.
  185. //
  186. MsAcquireExclusiveFcb( fcb );
  187. //
  188. // Ensure that this FCB still belongs to an active open mailslot.
  189. //
  190. status = MsVerifyFcb( fcb );
  191. if (NT_SUCCESS (status)) {
  192. //
  193. // If the read queue does not contain any write entries
  194. // then we either need to queue this operation or
  195. // fail immediately.
  196. //
  197. if (!MsIsDataQueueWriters( readQueue )) {
  198. //
  199. // There are no outstanding writes. If the read timeout is
  200. // non-zero queue the read IRP, otherwise fail it.
  201. //
  202. timeout = fcb->Specific.Fcb.ReadTimeout;
  203. if (timeout.HighPart == 0 && timeout.LowPart == 0) {
  204. DebugTrace(0, Dbg, "Failing read with 0 timeout\n", 0);
  205. status = STATUS_IO_TIMEOUT;
  206. DebugTrace(-1, Dbg, "MsCommonRead -> %08lx\n", status );
  207. } else {
  208. //
  209. // Create a timer block to time the request if we need to.
  210. //
  211. if ( timeout.QuadPart != -1 ) {
  212. status = MsCreateWorkContext (&MsfsDeviceObject->DeviceObject,
  213. &timeout,
  214. fcb,
  215. readIrp,
  216. &workContext);
  217. }
  218. if (NT_SUCCESS (status)) {
  219. status = MsAddDataQueueEntry( readQueue,
  220. ReadEntries,
  221. readLength,
  222. readIrp,
  223. workContext );
  224. }
  225. }
  226. } else {
  227. //
  228. // Otherwise we have a data on a queue that contains
  229. // one or more write entries. Read the data and complete
  230. // the read IRP.
  231. //
  232. readIrp->IoStatus = MsReadDataQueue( readQueue,
  233. Read,
  234. readBuffer,
  235. readLength,
  236. &messageLength
  237. );
  238. status = readIrp->IoStatus.Status;
  239. //
  240. // Update the file last access time and finish up the read IRP.
  241. //
  242. if ( NT_SUCCESS( status ) ) {
  243. KeQuerySystemTime( &fcb->Specific.Fcb.LastAccessTime );
  244. }
  245. }
  246. }
  247. MsReleaseFcb( fcb );
  248. MsDereferenceFcb( fcb );
  249. if (status != STATUS_PENDING) {
  250. if (workContext) {
  251. MsDereferenceFcb ( fcb );
  252. IoFreeWorkItem (workContext->WorkItem);
  253. ExFreePool (workContext);
  254. }
  255. MsCompleteRequest( readIrp, status );
  256. }
  257. DebugTrace(-1, Dbg, "MsCommonRead -> %08lx\n", status);
  258. return status;
  259. }