Source code of Windows XP (NT5)
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.

385 lines
8.2 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. fscontrl.c
  5. Abstract:
  6. This module implements the file file system control routines for MSFS
  7. called by the dispatch driver.
  8. Author:
  9. Manny Weiser (mannyw) 25-Jan-1991
  10. Revision History:
  11. --*/
  12. #include "mailslot.h"
  13. //
  14. // The debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_FSCONTROL)
  17. //
  18. // local procedure prototypes
  19. //
  20. NTSTATUS
  21. MsCommonFsControl (
  22. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  23. IN PIRP Irp
  24. );
  25. NTSTATUS
  26. MsPeek (
  27. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  28. IN PIRP Irp
  29. );
  30. #ifdef ALLOC_PRAGMA
  31. #pragma alloc_text( PAGE, MsCommonFsControl )
  32. #pragma alloc_text( PAGE, MsFsdFsControl )
  33. #pragma alloc_text( PAGE, MsPeek )
  34. #endif
  35. NTSTATUS
  36. MsFsdFsControl (
  37. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  38. IN PIRP Irp
  39. )
  40. /*++
  41. Routine Description:
  42. This routine implements the FSD part of the NtFsControlFile API calls.
  43. Arguments:
  44. MsfsDeviceObject - Supplies the device object to use.
  45. Irp - Supplies the Irp being processed
  46. Return Value:
  47. NTSTATUS - The Fsd status for the Irp
  48. --*/
  49. {
  50. NTSTATUS status;
  51. PAGED_CODE();
  52. DebugTrace(+1, Dbg, "MsFsdFsControl\n", 0);
  53. //
  54. // Call the common file system control function.
  55. //
  56. status = MsCommonFsControl( MsfsDeviceObject, Irp );
  57. //
  58. // Return to the caller.
  59. //
  60. DebugTrace(-1, Dbg, "MsFsdFsControl -> %08lx\n", status );
  61. return status;
  62. }
  63. NTSTATUS
  64. MsCommonFsControl (
  65. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  66. IN PIRP Irp
  67. )
  68. /*++
  69. Routine Description:
  70. This is the common routine for handling a file system control call.
  71. Arguments:
  72. MsfsDeviceObject - A pointer to the mailslot file system device object.
  73. Irp - Supplies the Irp to process
  74. Return Value:
  75. NTSTATUS - the return status for the operation
  76. --*/
  77. {
  78. NTSTATUS status;
  79. PIO_STACK_LOCATION irpSp;
  80. PAGED_CODE();
  81. //
  82. // Reference our input parameters to make things easier
  83. //
  84. irpSp = IoGetCurrentIrpStackLocation( Irp );
  85. DebugTrace(+1, Dbg, "MsCommonFileSystemControl\n", 0);
  86. DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp);
  87. DebugTrace( 0, Dbg, "OutputBufferLength = %08lx\n", irpSp->Parameters.FileSystemControl.OutputBufferLength);
  88. DebugTrace( 0, Dbg, "InputBufferLength = %08lx\n", irpSp->Parameters.FileSystemControl.InputBufferLength);
  89. DebugTrace( 0, Dbg, "FsControlCode = %08lx\n", irpSp->Parameters.FileSystemControl.FsControlCode);
  90. //
  91. // Decide how to handle this IRP. Call the appropriate worker function.
  92. //
  93. switch (irpSp->Parameters.FileSystemControl.FsControlCode) {
  94. case FSCTL_MAILSLOT_PEEK:
  95. FsRtlEnterFileSystem();
  96. status = MsPeek( MsfsDeviceObject, Irp );
  97. FsRtlExitFileSystem();
  98. break;
  99. default:
  100. MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
  101. status = STATUS_INVALID_PARAMETER;
  102. }
  103. //
  104. // Return to the caller.
  105. //
  106. DebugTrace(-1, Dbg, "MsCommonFsControl -> %08lx\n", status);
  107. return status;
  108. }
  109. NTSTATUS
  110. MsPeek (
  111. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  112. IN PIRP Irp
  113. )
  114. /*++
  115. Routine Description:
  116. This function handles a mailslot peek call.
  117. Arguments:
  118. MsfsDeviceObject - A pointer to the mailslot file system device object.
  119. Irp - Supplies the Irp to process
  120. Return Value:
  121. NTSTATUS - the return status for the operation
  122. --*/
  123. {
  124. NTSTATUS status;
  125. PIO_STACK_LOCATION irpSp;
  126. NODE_TYPE_CODE nodeTypeCode;
  127. PFCB fcb;
  128. PVOID fsContext2;
  129. PFILE_MAILSLOT_PEEK_BUFFER peekParamBuffer;
  130. ULONG peekParamLength;
  131. PVOID peekDataBuffer;
  132. ULONG peekDataLength;
  133. PDATA_QUEUE dataQueue;
  134. ULONG MessageLength;
  135. PAGED_CODE();
  136. irpSp = IoGetCurrentIrpStackLocation( Irp );
  137. DebugTrace(+1, Dbg, "MsPeek\n", 0);
  138. //
  139. // Make local copies of the input parameters to make things easier.
  140. //
  141. peekParamBuffer = irpSp->Parameters.FileSystemControl.Type3InputBuffer;
  142. peekParamLength = irpSp->Parameters.FileSystemControl.InputBufferLength;
  143. peekDataBuffer = Irp->UserBuffer;
  144. peekDataLength = irpSp->Parameters.FileSystemControl.OutputBufferLength;
  145. //
  146. // Ensure that the supplied buffer is large enough for the peek
  147. // parameters.
  148. //
  149. if (peekParamLength < sizeof( FILE_MAILSLOT_PEEK_BUFFER ) ) {
  150. DebugTrace(0, Dbg, "Output buffer is too small\n", 0);
  151. MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
  152. status = STATUS_INVALID_PARAMETER;
  153. DebugTrace(-1, Dbg, "MsPeek -> %08lx\n", status );
  154. return status;
  155. }
  156. //
  157. // If the requestor mode is user mode we need to probe the buffers.
  158. // We do not need to have an exception handler here because our top
  159. // level caller already has one that will complete the Irp with
  160. // the appropriate status if we access violate.
  161. //
  162. if (Irp->RequestorMode != KernelMode) {
  163. try {
  164. ProbeForWrite( peekParamBuffer, peekParamLength, sizeof(UCHAR) );
  165. ProbeForWrite( peekDataBuffer, peekDataLength, sizeof(UCHAR) );
  166. peekParamBuffer->ReadDataAvailable = 0;
  167. peekParamBuffer->NumberOfMessages = 0;
  168. peekParamBuffer->MessageLength = 0;
  169. } except(EXCEPTION_EXECUTE_HANDLER) {
  170. status = GetExceptionCode ();
  171. MsCompleteRequest( Irp, status );
  172. return status;
  173. }
  174. }
  175. //
  176. // Decode the fil1e object. If it returns NTC_UNDEFINED, then the
  177. // node is closing. Otherwise we obtain a referenced pointer to
  178. // an FCB.
  179. //
  180. if ((nodeTypeCode = MsDecodeFileObject( irpSp->FileObject,
  181. (PVOID *)&fcb,
  182. &fsContext2 )) == NTC_UNDEFINED) {
  183. DebugTrace(0, Dbg, "Mailslot is disconnected from us\n", 0);
  184. MsCompleteRequest( Irp, STATUS_FILE_FORCED_CLOSED );
  185. status = STATUS_FILE_FORCED_CLOSED;
  186. DebugTrace(-1, Dbg, "MsPeek -> %08lx\n", status );
  187. return status;
  188. }
  189. //
  190. // Allow a peek operation only if this is a server side handle to
  191. // a mailslot file (i.e. the node type is FCB).
  192. //
  193. if (nodeTypeCode != MSFS_NTC_FCB) {
  194. DebugTrace(0, Dbg, "FileObject is not the correct type\n", 0);
  195. MsDereferenceNode( &fcb->Header );
  196. MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
  197. status = STATUS_INVALID_PARAMETER;
  198. DebugTrace(-1, Dbg, "MsPeek -> %08lx\n", status );
  199. return status;
  200. }
  201. //
  202. // Acquire exclusive access to the FCB.
  203. //
  204. MsAcquireExclusiveFcb( fcb );
  205. //
  206. // Ensure that this FCB still belongs to an active open mailslot.
  207. //
  208. status = MsVerifyFcb( fcb );
  209. if (NT_SUCCESS (status)) {
  210. //
  211. // Look for write data in the mailslot.
  212. //
  213. dataQueue = &fcb->DataQueue;
  214. if (!MsIsDataQueueWriters( dataQueue )) {
  215. //
  216. // There are no outstanding writes so leave all the zeros in there.
  217. //
  218. } else {
  219. //
  220. // There is write data for the peek. Fill in the peek output
  221. // buffer.
  222. //
  223. Irp->IoStatus = MsReadDataQueue(
  224. dataQueue,
  225. Peek,
  226. peekDataBuffer,
  227. peekDataLength,
  228. &MessageLength
  229. );
  230. status = Irp->IoStatus.Status;
  231. if (NT_SUCCESS (status)) {
  232. try {
  233. peekParamBuffer->ReadDataAvailable = dataQueue->BytesInQueue;
  234. peekParamBuffer->NumberOfMessages = dataQueue->EntriesInQueue;
  235. peekParamBuffer->MessageLength = MessageLength;
  236. } except (EXCEPTION_EXECUTE_HANDLER) {
  237. status = GetExceptionCode ();
  238. }
  239. }
  240. }
  241. }
  242. MsReleaseFcb( fcb );
  243. //
  244. // Release the reference to the FCB.
  245. //
  246. MsDereferenceFcb( fcb );
  247. //
  248. // Finish up the fs control IRP.
  249. //
  250. MsCompleteRequest( Irp, status );
  251. DebugTrace(-1, Dbg, "MsPeek -> %08lx\n", status);
  252. return status;
  253. }