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.

883 lines
25 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. LowIo.c
  5. Abstract:
  6. This module implements buffer locking and mapping; also synchronous waiting for a lowlevelIO.
  7. Author:
  8. JoeLinn [JoeLinn] 12-Oct-94
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // Local debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_LOWIO)
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, RxLockUserBuffer)
  19. #pragma alloc_text(PAGE, RxMapUserBuffer)
  20. #pragma alloc_text(PAGE, RxMapSystemBuffer)
  21. #pragma alloc_text(PAGE, RxInitializeLowIoContext)
  22. #pragma alloc_text(PAGE, RxLowIoGetBufferAddress)
  23. #pragma alloc_text(PAGE, RxLowIoSubmitRETRY)
  24. #pragma alloc_text(PAGE, RxLowIoPopulateFsctlInfo)
  25. #pragma alloc_text(PAGE, RxLowIoSubmit)
  26. #pragma alloc_text(PAGE, RxInitializeLowIoPerFcbInfo)
  27. #pragma alloc_text(PAGE, RxInitializeLowIoPerFcbInfo)
  28. #endif
  29. //
  30. // this is a crude implementation of the insertion, deletion, and coverup operations for wimp lowio
  31. // we'll just use a linked list for now.........
  32. //
  33. #define RxInsertIntoOutStandingPagingOperationsList(RxContext,Operation) { \
  34. PLIST_ENTRY WhichList = (Operation==LOWIO_OP_READ) \
  35. ?&Fcb->PagingIoReadsOutstanding \
  36. :&Fcb->PagingIoWritesOutstanding;\
  37. InsertTailList(WhichList,&RxContext->RxContextSerializationQLinks); \
  38. }
  39. #define RxRemoveFromOutStandingPagingOperationsList(RxContext) { \
  40. RemoveEntryList(&RxContext->RxContextSerializationQLinks); \
  41. RxContext->RxContextSerializationQLinks.Flink = NULL; \
  42. RxContext->RxContextSerializationQLinks.Blink = NULL; \
  43. }
  44. FAST_MUTEX RxLowIoPagingIoSyncMutex;
  45. //
  46. // here we hiding the IO access flags
  47. //
  48. INLINE
  49. NTSTATUS
  50. RxLockAndMapUserBufferForLowIo (
  51. IN PRX_CONTEXT RxContext,
  52. IN PIRP Irp,
  53. IN PLOWIO_CONTEXT LowIoContext,
  54. IN ULONG Operation
  55. )
  56. {
  57. RxLockUserBuffer( RxContext,
  58. Irp,
  59. (Operation == LOWIO_OP_READ) ? IoWriteAccess : IoReadAccess,
  60. LowIoContext->ParamsFor.ReadWrite.ByteCount );
  61. if (RxMapUserBuffer( RxContext, Irp ) == NULL) {
  62. return STATUS_INSUFFICIENT_RESOURCES;
  63. } else {
  64. LowIoContext->ParamsFor.ReadWrite.Buffer = Irp->MdlAddress;
  65. return STATUS_SUCCESS;
  66. }
  67. }
  68. //
  69. // NT specific routines
  70. //
  71. VOID
  72. RxLockUserBuffer (
  73. IN PRX_CONTEXT RxContext,
  74. IN PIRP Irp,
  75. IN LOCK_OPERATION Operation,
  76. IN ULONG BufferLength
  77. )
  78. /*++
  79. Routine Description:
  80. This routine locks the specified buffer for the specified type of
  81. access. The file system requires this routine since it does not
  82. ask the I/O system to lock its buffers for direct I/O. This routine
  83. may only be called from the Fsd while still in the user context.
  84. Arguments:
  85. RxContext - Pointer to the pointer Irp for which the buffer is to be locked.
  86. Operation - IoWriteAccess for read operations, or IoReadAccess for
  87. write operations.
  88. BufferLength - Length of user buffer.
  89. Return Value:
  90. None
  91. --*/
  92. {
  93. PMDL Mdl = NULL;
  94. PAGED_CODE();
  95. if (Irp->MdlAddress == NULL) {
  96. ASSERT( !FlagOn( Irp->Flags, IRP_INPUT_OPERATION ) );
  97. //
  98. // Allocate the Mdl, and Raise if we fail.
  99. //
  100. if (BufferLength > 0) {
  101. Mdl = IoAllocateMdl( Irp->UserBuffer,
  102. BufferLength,
  103. FALSE,
  104. FALSE,
  105. Irp );
  106. if (Mdl == NULL) {
  107. RxRaiseStatus( RxContext, STATUS_INSUFFICIENT_RESOURCES );
  108. } else {
  109. //
  110. // Now probe the buffer described by the Irp. If we get an exception,
  111. // deallocate the Mdl and return the appropriate "expected" status.
  112. //
  113. try {
  114. MmProbeAndLockPages( Mdl,
  115. Irp->RequestorMode,
  116. Operation );
  117. } except(EXCEPTION_EXECUTE_HANDLER) {
  118. NTSTATUS Status;
  119. Status = GetExceptionCode();
  120. IoFreeMdl( Mdl );
  121. Irp->MdlAddress = NULL;
  122. if (!FsRtlIsNtstatusExpected( Status )) {
  123. Status = STATUS_INVALID_USER_BUFFER;
  124. }
  125. SetFlag( RxContext->Flags, RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT );
  126. RxRaiseStatus( RxContext, Status );
  127. }
  128. }
  129. }
  130. } else {
  131. Mdl = Irp->MdlAddress;
  132. ASSERT( RxLowIoIsMdlLocked( Mdl ) );
  133. }
  134. }
  135. PVOID
  136. RxMapSystemBuffer (
  137. IN PRX_CONTEXT RxContext,
  138. IN PIRP Irp
  139. )
  140. /*++
  141. Routine Description:
  142. This routine returns the system buffer address from the irp. the way that the code is written
  143. it may also decide to get the buffer address from the mdl. that is wrong because the systembuffer is
  144. always nonpaged so no locking/mapping is needed. thus, the mdl path now contains an assert.
  145. Arguments:
  146. RxContext - Pointer to the IrpC for the request.
  147. Return Value:
  148. Mapped address
  149. --*/
  150. {
  151. PAGED_CODE();
  152. if (Irp->MdlAddress == NULL) {
  153. return Irp->AssociatedIrp.SystemBuffer;
  154. } else {
  155. ASSERT (!"there should not be an MDL in this irp!!!!!");
  156. return MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
  157. }
  158. }
  159. PVOID
  160. RxMapUserBuffer (
  161. IN PRX_CONTEXT RxContext,
  162. IN PIRP Irp
  163. )
  164. /*++
  165. Routine Description:
  166. This routine returns the address of the userbuffer. if an MDL exists then the assumption is that
  167. the mdl describes the userbuffer and the system address for the mdl is returned. otherwise, the userbuffer
  168. is returned directly.
  169. Arguments:
  170. RxContext - Pointer to the IrpC for the request.
  171. Return Value:
  172. Mapped address
  173. --*/
  174. {
  175. PAGED_CODE();
  176. if (Irp->MdlAddress == NULL) {
  177. return Irp->UserBuffer;
  178. } else {
  179. return MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
  180. }
  181. }
  182. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. //
  184. // from here down (except for fsctl buffer determination), everything is available for either wrapper. we may
  185. // decide that the fsctl stuff should be moved as well
  186. //
  187. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  188. VOID
  189. RxInitializeLowIoContext (
  190. PRX_CONTEXT RxContext,
  191. ULONG Operation,
  192. PLOWIO_CONTEXT LowIoContext
  193. )
  194. /*++
  195. Routine Description:
  196. This routine initializes the LowIO context in the RxContext.
  197. Arguments:
  198. RxContext - context of irp being processed.
  199. Return Value:
  200. none
  201. --*/
  202. {
  203. PIRP Irp = RxContext->CurrentIrp;
  204. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  205. PAGED_CODE();
  206. ASSERT( LowIoContext == &RxContext->LowIoContext );
  207. KeInitializeEvent( &RxContext->SyncEvent,
  208. NotificationEvent,
  209. FALSE );
  210. //
  211. // this ID is used to release the resource on behalf of another thread....
  212. // e.g. it is used when an async routine completes to release the thread
  213. // acquired by the first acquirer.
  214. //
  215. LowIoContext->ResourceThreadId = ExGetCurrentResourceThread();
  216. LowIoContext->Operation = (USHORT)Operation;
  217. switch (Operation) {
  218. case LOWIO_OP_READ:
  219. case LOWIO_OP_WRITE:
  220. #if DBG
  221. LowIoContext->ParamsFor.ReadWrite.ByteOffset = 0xffffffee; // no operation should start there!
  222. LowIoContext->ParamsFor.ReadWrite.ByteCount = 0xeeeeeeee; // no operation should start there!
  223. #endif
  224. ASSERT( &IrpSp->Parameters.Read.Length == &IrpSp->Parameters.Write.Length );
  225. ASSERT( &IrpSp->Parameters.Read.Key == &IrpSp->Parameters.Write.Key );
  226. LowIoContext->ParamsFor.ReadWrite.Key = IrpSp->Parameters.Read.Key;
  227. LowIoContext->ParamsFor.ReadWrite.Flags = (FlagOn( Irp->Flags, IRP_PAGING_IO ) ? LOWIO_READWRITEFLAG_PAGING_IO : 0);
  228. break;
  229. case LOWIO_OP_FSCTL:
  230. case LOWIO_OP_IOCTL:
  231. LowIoContext->ParamsFor.FsCtl.Flags = 0;
  232. LowIoContext->ParamsFor.FsCtl.InputBufferLength = 0;
  233. LowIoContext->ParamsFor.FsCtl.pInputBuffer = NULL;
  234. LowIoContext->ParamsFor.FsCtl.OutputBufferLength = 0;
  235. LowIoContext->ParamsFor.FsCtl.pOutputBuffer = NULL;
  236. LowIoContext->ParamsFor.FsCtl.MinorFunction = 0;
  237. break;
  238. case LOWIO_OP_SHAREDLOCK:
  239. case LOWIO_OP_EXCLUSIVELOCK:
  240. case LOWIO_OP_UNLOCK:
  241. case LOWIO_OP_UNLOCK_MULTIPLE:
  242. case LOWIO_OP_CLEAROUT:
  243. case LOWIO_OP_NOTIFY_CHANGE_DIRECTORY:
  244. break;
  245. default:
  246. ASSERT( FALSE );
  247. }
  248. }
  249. PVOID
  250. RxLowIoGetBufferAddress (
  251. IN PRX_CONTEXT RxContext
  252. )
  253. /*++
  254. Routine Description:
  255. This routine gets the buffer corresponding to the Mdl in the LowIoContext.
  256. Arguments:
  257. RxContext - context for the request.
  258. Return Value:
  259. Mapped address
  260. --*/
  261. {
  262. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  263. PAGED_CODE();
  264. if (LowIoContext->ParamsFor.ReadWrite.ByteCount > 0) {
  265. ASSERT( LowIoContext->ParamsFor.ReadWrite.Buffer );
  266. return MmGetSystemAddressForMdlSafe( LowIoContext->ParamsFor.ReadWrite.Buffer, NormalPagePriority );
  267. } else {
  268. return NULL;
  269. }
  270. }
  271. NTSTATUS
  272. RxLowIoSubmitRETRY (
  273. IN PRX_CONTEXT RxContext,
  274. IN PIRP Irp
  275. )
  276. /*++
  277. Routine Description:
  278. This routine just calls LowIoSubmit; the completion routine was previously
  279. stored so we just extract it and pass it in. This is called out of the Fsp
  280. dispatcher for retrying at the low level.
  281. Arguments:
  282. RxContext - the usual
  283. Return Value:
  284. whatever value supplied by the caller or RxStatus(MORE_PROCESSING_REQUIRED).
  285. --*/
  286. {
  287. PFCB Fcb = (PFCB)RxContext->pFcb;
  288. PAGED_CODE();
  289. return RxLowIoSubmit( RxContext, Irp, Fcb, RxContext->LowIoContext.CompletionRoutine );
  290. }
  291. NTSTATUS
  292. RxLowIoCompletionTail (
  293. IN PRX_CONTEXT RxContext
  294. )
  295. /*++
  296. Routine Description:
  297. This routine is called by lowio routines at the very end...i.e. after the individual completion
  298. routines are called.
  299. Arguments:
  300. RxContext - the RDBSS context
  301. Return Value:
  302. whatever value supplied by the caller.
  303. --*/
  304. {
  305. NTSTATUS Status;
  306. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  307. ULONG Operation = LowIoContext->Operation;
  308. BOOLEAN SynchronousIo = !BooleanFlagOn( RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION );
  309. RxDbgTrace( +1, Dbg, ("RxLowIoCompletionTail, Operation=%08lx\n",LowIoContext->Operation) );
  310. if ((KeGetCurrentIrql() < DISPATCH_LEVEL ) ||
  311. (FlagOn( LowIoContext->Flags, LOWIO_CONTEXT_FLAG_CAN_COMPLETE_AT_DPC_LEVEL ))) {
  312. Status = RxContext->LowIoContext.CompletionRoutine( RxContext );
  313. } else {
  314. Status = STATUS_MORE_PROCESSING_REQUIRED;
  315. }
  316. if ((Status == STATUS_MORE_PROCESSING_REQUIRED) || (Status == STATUS_RETRY)) {
  317. RxDbgTrace( -1, Dbg, ("RxLowIoCompletionTail wierdstatus, Status=%08lx\n", Status) );
  318. return Status;
  319. }
  320. switch (Operation) {
  321. case LOWIO_OP_READ:
  322. case LOWIO_OP_WRITE:
  323. if (FlagOn( LowIoContext->ParamsFor.ReadWrite.Flags, LOWIO_READWRITEFLAG_PAGING_IO )) {
  324. RxDbgTrace( 0, Dbg, ("RxLowIoCompletionTail pagingio unblock\n") );
  325. ExAcquireFastMutexUnsafe( &RxLowIoPagingIoSyncMutex );
  326. RxRemoveFromOutStandingPagingOperationsList( RxContext );
  327. ExReleaseFastMutexUnsafe( &RxLowIoPagingIoSyncMutex );
  328. RxResumeBlockedOperations_ALL( RxContext );
  329. }
  330. break;
  331. case LOWIO_OP_SHAREDLOCK:
  332. case LOWIO_OP_EXCLUSIVELOCK:
  333. case LOWIO_OP_UNLOCK:
  334. case LOWIO_OP_UNLOCK_MULTIPLE:
  335. case LOWIO_OP_CLEAROUT:
  336. break;
  337. case LOWIO_OP_FSCTL:
  338. case LOWIO_OP_IOCTL:
  339. case LOWIO_OP_NOTIFY_CHANGE_DIRECTORY:
  340. break;
  341. default:
  342. ASSERT( !"Valid Low Io Op Code" );
  343. }
  344. if (!FlagOn( LowIoContext->Flags, LOWIO_CONTEXT_FLAG_SYNCCALL )) {
  345. //
  346. // if we're being called from lowiosubmit then just get out otherwise...do the completion
  347. //
  348. RxCompleteAsynchronousRequest( RxContext, Status );
  349. }
  350. RxDbgTrace(-1, Dbg, ("RxLowIoCompletionTail, Status=%08lx\n",Status));
  351. return(Status);
  352. }
  353. NTSTATUS
  354. RxLowIoCompletion (
  355. IN PRX_CONTEXT RxContext
  356. )
  357. /*++
  358. Routine Description:
  359. This routine must be called by the MiniRdr LowIo routines when they complete,
  360. IF THEY HAVE INITIALLY RETURNED PENDING.
  361. It behaves a bit differently depending on whether it's sync or async IO.
  362. For sync, we just get back into the user's thread. For async, we first try
  363. the completion routine directly. If we get MORE_PROCESSING, then we flip to
  364. a thread and the routine will be recalled.
  365. Arguments:
  366. RxContext - the RDBSS context
  367. Return Value:
  368. Whatever value supplied by the caller or RxStatus(MORE_PROCESSING_REQUIRED).
  369. The value M_P_R is very handy if this is being called for a Irp completion.
  370. M_P_R causes the Irp completion guy to stop processing which is good since
  371. the called completion routine may complete the packet.
  372. --*/
  373. {
  374. NTSTATUS Status;
  375. BOOLEAN SynchronousIo = !BooleanFlagOn( RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION );
  376. if (SynchronousIo) {
  377. RxSignalSynchronousWaiter( RxContext );
  378. return STATUS_MORE_PROCESSING_REQUIRED;
  379. }
  380. RxDbgTrace( 0, Dbg, ("RxLowIoCompletion ASYNC\n") );
  381. ASSERT( RxLowIoIsBufferLocked( &RxContext->LowIoContext ) );
  382. Status = RxLowIoCompletionTail( RxContext );
  383. //
  384. // The called routine makes the decision as to whether it can continue. Many
  385. // will ask for a post if we're at DPC level. Some will not.
  386. //
  387. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  388. RxPostToWorkerThread( RxFileSystemDeviceObject,
  389. HyperCriticalWorkQueue,
  390. &RxContext->WorkQueueItem,
  391. RxLowIoCompletion,
  392. RxContext );
  393. } else if (Status == STATUS_RETRY) {
  394. //
  395. // I'm not too sure about this.
  396. //
  397. RxFsdPostRequestWithResume( RxContext, RxLowIoSubmitRETRY );
  398. Status = STATUS_MORE_PROCESSING_REQUIRED;
  399. }
  400. return Status;
  401. }
  402. #if DBG
  403. VOID
  404. RxAssertFsctlIsLikeIoctl ()
  405. {
  406. ASSERT(FIELD_OFFSET(IO_STACK_LOCATION,Parameters.FileSystemControl.OutputBufferLength)
  407. == FIELD_OFFSET(IO_STACK_LOCATION,Parameters.DeviceIoControl.OutputBufferLength) );
  408. ASSERT(FIELD_OFFSET(IO_STACK_LOCATION,Parameters.FileSystemControl.InputBufferLength)
  409. == FIELD_OFFSET(IO_STACK_LOCATION,Parameters.DeviceIoControl.InputBufferLength) );
  410. ASSERT(FIELD_OFFSET(IO_STACK_LOCATION,Parameters.FileSystemControl.FsControlCode)
  411. == FIELD_OFFSET(IO_STACK_LOCATION,Parameters.DeviceIoControl.IoControlCode) );
  412. ASSERT(FIELD_OFFSET(IO_STACK_LOCATION,Parameters.FileSystemControl.Type3InputBuffer)
  413. == FIELD_OFFSET(IO_STACK_LOCATION,Parameters.DeviceIoControl.Type3InputBuffer) );
  414. }
  415. #else
  416. #define RxAssertFsctlIsLikeIoctl()
  417. #endif //if DBG
  418. NTSTATUS
  419. NTAPI
  420. RxLowIoPopulateFsctlInfo (
  421. IN PRX_CONTEXT RxContext,
  422. IN PIRP Irp
  423. )
  424. {
  425. NTSTATUS Status = STATUS_SUCCESS;
  426. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  427. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  428. PAGED_CODE();
  429. RxAssertFsctlIsLikeIoctl();
  430. LowIoContext->ParamsFor.FsCtl.FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
  431. LowIoContext->ParamsFor.FsCtl.InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  432. LowIoContext->ParamsFor.FsCtl.OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
  433. LowIoContext->ParamsFor.FsCtl.MinorFunction = IrpSp->MinorFunction;
  434. switch (LowIoContext->ParamsFor.FsCtl.FsControlCode & 3) {
  435. case METHOD_BUFFERED:
  436. LowIoContext->ParamsFor.FsCtl.pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
  437. LowIoContext->ParamsFor.FsCtl.pOutputBuffer = Irp->AssociatedIrp.SystemBuffer;
  438. break;
  439. case METHOD_IN_DIRECT:
  440. case METHOD_OUT_DIRECT:
  441. LowIoContext->ParamsFor.FsCtl.pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
  442. if (Irp->MdlAddress != NULL) {
  443. LowIoContext->ParamsFor.FsCtl.pOutputBuffer = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
  444. if (LowIoContext->ParamsFor.FsCtl.pOutputBuffer == NULL) {
  445. Status = STATUS_INSUFFICIENT_RESOURCES;
  446. }
  447. } else {
  448. LowIoContext->ParamsFor.FsCtl.pOutputBuffer = NULL;
  449. }
  450. break;
  451. case METHOD_NEITHER:
  452. LowIoContext->ParamsFor.FsCtl.pInputBuffer = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
  453. LowIoContext->ParamsFor.FsCtl.pOutputBuffer = Irp->UserBuffer;
  454. break;
  455. default:
  456. ASSERT(!"Valid Method for Fs Control");
  457. break;
  458. }
  459. return Status;
  460. }
  461. NTSTATUS
  462. RxLowIoSubmit (
  463. IN PRX_CONTEXT RxContext,
  464. IN PIRP Irp,
  465. IN PFCB Fcb,
  466. PLOWIO_COMPLETION_ROUTINE CompletionRoutine
  467. )
  468. /*++
  469. Routine Description:
  470. This routine passes the request to the minirdr after setting up for completion. it then waits
  471. or pends as appropriate.
  472. Arguments:
  473. RxContext - the usual
  474. Return Value:
  475. whatever value is returned by a callout....or by LowIoCompletion.
  476. --*/
  477. {
  478. IN PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  479. IN PFILE_OBJECT FileObject = IrpSp->FileObject;
  480. NTSTATUS Status = STATUS_SUCCESS;
  481. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  482. ULONG Operation = LowIoContext->Operation;
  483. BOOLEAN SynchronousIo = !BooleanFlagOn( RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION );
  484. PAGED_CODE();
  485. LowIoContext->CompletionRoutine = CompletionRoutine;
  486. RxDbgTrace(+1, Dbg, ("RxLowIoSubmit, Operation=%08lx\n",LowIoContext->Operation));
  487. //
  488. // if fcb is shadowed and user buffer are not already locked then try fast path
  489. //
  490. if (FlagOn( Fcb->FcbState, FCB_STATE_FILE_IS_SHADOWED ) &&
  491. !FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED )) {
  492. RxContext->InformationToReturn = 0;
  493. Status = RxShadowFastLowIo( RxContext, Irp );
  494. if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
  495. return Status;
  496. }
  497. Status = STATUS_SUCCESS;
  498. }
  499. switch (Operation) {
  500. case LOWIO_OP_READ:
  501. case LOWIO_OP_WRITE:
  502. ASSERT( LowIoContext->ParamsFor.ReadWrite.ByteOffset != 0xffffffee );
  503. ASSERT (LowIoContext->ParamsFor.ReadWrite.ByteCount != 0xeeeeeeee );
  504. Status = RxLockAndMapUserBufferForLowIo( RxContext, Irp, LowIoContext, Operation);
  505. //
  506. // NT paging IO is different from WIN9X so this may be different
  507. //
  508. if (FlagOn( LowIoContext->ParamsFor.ReadWrite.Flags, LOWIO_READWRITEFLAG_PAGING_IO )) {
  509. ExAcquireFastMutexUnsafe( &RxLowIoPagingIoSyncMutex );
  510. RxContext->BlockedOpsMutex = &RxLowIoPagingIoSyncMutex;
  511. RxInsertIntoOutStandingPagingOperationsList( RxContext, Operation );
  512. ExReleaseFastMutexUnsafe( &RxLowIoPagingIoSyncMutex );
  513. }
  514. break;
  515. case LOWIO_OP_FSCTL:
  516. case LOWIO_OP_IOCTL:
  517. Status = RxLowIoPopulateFsctlInfo( RxContext, Irp );
  518. if (Status == STATUS_SUCCESS) {
  519. if ((LowIoContext->ParamsFor.FsCtl.InputBufferLength > 0) &&
  520. (LowIoContext->ParamsFor.FsCtl.pInputBuffer == NULL)) {
  521. Status = STATUS_INVALID_PARAMETER;
  522. }
  523. if ((LowIoContext->ParamsFor.FsCtl.OutputBufferLength > 0) &&
  524. (LowIoContext->ParamsFor.FsCtl.pOutputBuffer == NULL)) {
  525. Status = STATUS_INVALID_PARAMETER;
  526. }
  527. }
  528. break;
  529. case LOWIO_OP_NOTIFY_CHANGE_DIRECTORY:
  530. case LOWIO_OP_SHAREDLOCK:
  531. case LOWIO_OP_EXCLUSIVELOCK:
  532. case LOWIO_OP_UNLOCK:
  533. case LOWIO_OP_UNLOCK_MULTIPLE:
  534. case LOWIO_OP_CLEAROUT:
  535. break;
  536. default:
  537. ASSERTMSG( "Invalid Low Io Op Code", FALSE );
  538. Status = STATUS_INVALID_PARAMETER;
  539. }
  540. SetFlag( RxContext->Flags, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED );
  541. if (Status == STATUS_SUCCESS) {
  542. PMINIRDR_DISPATCH MiniRdrDispatch;
  543. if (!SynchronousIo) {
  544. //
  545. // get ready for any arbitrary finish order...assume return of pending
  546. //
  547. InterlockedIncrement( &RxContext->ReferenceCount );
  548. if (!FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP )) {
  549. IoMarkIrpPending( Irp );
  550. }
  551. RxDbgTrace( 0, Dbg, ("RxLowIoSubmit, Operation is ASYNC!\n"));
  552. }
  553. MiniRdrDispatch = RxContext->RxDeviceObject->Dispatch;
  554. if (MiniRdrDispatch != NULL) {
  555. //
  556. // Use private dispatch if lwio is enabled on this file
  557. //
  558. if (FlagOn( Fcb->FcbState, FCB_STATE_LWIO_ENABLED ) &&
  559. (Fcb->MRxDispatch != NULL)) {
  560. MiniRdrDispatch = Fcb->MRxDispatch;
  561. }
  562. do {
  563. RxContext->InformationToReturn = 0;
  564. Status = STATUS_MORE_PROCESSING_REQUIRED;
  565. //
  566. // handle shadowed fcb
  567. //
  568. if (FlagOn( Fcb->FcbState, FCB_STATE_FILE_IS_SHADOWED )) {
  569. Status = RxShadowLowIo( RxContext, Irp, Fcb );
  570. }
  571. //
  572. // call underlying mini-rdr if more processing is needed
  573. //
  574. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  575. MINIRDR_CALL( Status,
  576. RxContext,
  577. MiniRdrDispatch,
  578. MRxLowIOSubmit[LowIoContext->Operation],
  579. (RxContext) );
  580. }
  581. if (Status == STATUS_PENDING){
  582. if (!SynchronousIo) {
  583. goto FINALLY;
  584. }
  585. RxWaitSync( RxContext );
  586. Status = RxContext->StoredStatus;
  587. } else {
  588. if (!SynchronousIo && (Status != STATUS_RETRY)) {
  589. //
  590. // we were wrong about pending..so clear the bit and deref
  591. //
  592. if (!FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP )) {
  593. ClearFlag( IrpSp->Control, SL_PENDING_RETURNED );
  594. }
  595. InterlockedDecrement( &RxContext->ReferenceCount );
  596. }
  597. }
  598. } while (Status == STATUS_RETRY);
  599. } else {
  600. Status = STATUS_INVALID_PARAMETER;
  601. }
  602. }
  603. //
  604. // you do not come here for pended,async IO
  605. //
  606. RxContext->StoredStatus = Status;
  607. SetFlag( LowIoContext->Flags, LOWIO_CONTEXT_FLAG_SYNCCALL );
  608. Status = RxLowIoCompletionTail( RxContext );
  609. FINALLY:
  610. RxDbgTrace( -1, Dbg, ("RxLowIoSubmit, Status=%08lx\n",Status) );
  611. return Status;
  612. }
  613. VOID
  614. RxInitializeLowIoPerFcbInfo(
  615. PLOWIO_PER_FCB_INFO LowIoPerFcbInfo
  616. )
  617. /*++
  618. Routine Description:
  619. This routine is called in FcbInitialization to initialize the LowIo part of the structure.
  620. Arguments:
  621. LowIoPerFcbInfo - the struct to be initialized
  622. Return Value:
  623. --*/
  624. {
  625. PAGED_CODE();
  626. InitializeListHead( &LowIoPerFcbInfo->PagingIoReadsOutstanding );
  627. InitializeListHead( &LowIoPerFcbInfo->PagingIoWritesOutstanding );
  628. }