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.

968 lines
25 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. shadow.c
  5. Abstract:
  6. This module contains the code that implements local read/write operations for shadow
  7. FCB
  8. Author:
  9. Ahmed Mohamed (ahmedm) 15-Dec-2001
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. //
  17. // define this so that rdbsstrace flag works, just use the lowio one since shadow is part of it
  18. //
  19. #define Dbg (DEBUG_TRACE_LOWIO)
  20. #define RxGetShadowSrvOpenContext(SrvOpen) ((PMRXSHADOW_SRV_OPEN) (SrvOpen)->ShadowContext)
  21. #define RxShadowLockKeyLock(LowIoContext, ShadowCtx) (LowIoContext->ParamsFor.Locks.Key)
  22. #define RxShadowLockKey(LowIoContext, ShadowCtx) (LowIoContext->ParamsFor.ReadWrite.Key)
  23. typedef struct {
  24. PIRP Irp;
  25. BOOLEAN Cancelable;
  26. LONG Refcnt;
  27. } RX_SHADOW_CONTEXT, *PRX_SHADOW_CONTEXT;
  28. extern PETHREAD RxSpinUpRequestsThread;
  29. NTSTATUS
  30. RxShadowVerifyIoParameters(
  31. PDEVICE_OBJECT DeviceObject,
  32. PFILE_OBJECT FileObject,
  33. PVOID Buffer,
  34. ULONG Length,
  35. PLARGE_INTEGER FileOffset
  36. )
  37. {
  38. if (!FlagOn( FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING )) {
  39. return STATUS_SUCCESS;
  40. }
  41. //
  42. // The file was opened without intermediate buffering enabled.
  43. // Check that the Buffer is properly aligned, and that the
  44. // length is an integral number of the block size.
  45. //
  46. if ((DeviceObject->SectorSize &&
  47. (Length & (DeviceObject->SectorSize - 1))) ||
  48. ((ULONG_PTR)Buffer & DeviceObject->AlignmentRequirement)) {
  49. //
  50. // Check for sector sizes that are not a power of two.
  51. //
  52. if ((DeviceObject->SectorSize && (Length % DeviceObject->SectorSize)) ||
  53. ((ULONG_PTR)Buffer & DeviceObject->AlignmentRequirement)) {
  54. return STATUS_INVALID_PARAMETER;
  55. }
  56. }
  57. //
  58. // If a ByteOffset parameter was specified, ensure that it is
  59. // is of the proper type.
  60. //
  61. if ((FileOffset->LowPart == FILE_WRITE_TO_END_OF_FILE) &&
  62. (FileOffset->HighPart == -1)) {
  63. NOTHING;
  64. } else if ((FileOffset->LowPart == FILE_USE_FILE_POINTER_POSITION) &&
  65. (FileOffset->HighPart == -1) &&
  66. FlagOn( FileObject->Flags, FO_SYNCHRONOUS_IO )) {
  67. NOTHING;
  68. } else if (DeviceObject->SectorSize &&
  69. (FileOffset->LowPart & (DeviceObject->SectorSize - 1))) {
  70. return STATUS_INVALID_PARAMETER;
  71. }
  72. return STATUS_SUCCESS;
  73. }
  74. NTSTATUS
  75. RxShadowBuildAsynchronousRequest (
  76. IN PIRP OriginalIrp,
  77. IN PDEVICE_OBJECT DeviceObject,
  78. IN PFILE_OBJECT FileObject,
  79. IN PFCB Fcb,
  80. IN PRX_CONTEXT RxContext,
  81. IN PMRXSHADOW_SRV_OPEN LocalSrvOpen,
  82. IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,
  83. IN PVOID Arg,
  84. OUT PIRP *Irp
  85. )
  86. /*++
  87. Routine Description:
  88. This routine builds an I/O Request Packet (IRP) suitable for a File System
  89. Driver (FSD) to use in requesting an I/O operation from a device driver.
  90. The request (RxContext->MajorFunction) must be one of the following request
  91. codes:
  92. IRP_MJ_READ
  93. IRP_MJ_WRITE
  94. IRP_MJ_DIRECTORY_CONTROL
  95. IRP_MJ_FLUSH_BUFFERS
  96. IRP_MJ_SHUTDOWN (not yet implemented)
  97. Arguments:
  98. RxContext - The RDBSS context.
  99. CompletionRoutine - The Irp CompletionRoutine.
  100. Return Value:
  101. The return status of the operation.
  102. --*/
  103. {
  104. PIRP NewIrp;
  105. PIO_STACK_LOCATION IrpSp;
  106. ULONG MajorFunction = RxContext->MajorFunction;
  107. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  108. LONG Length;
  109. *Irp = NULL;
  110. if ((MajorFunction != IRP_MJ_READ) &&
  111. (MajorFunction != IRP_MJ_WRITE) &&
  112. (MajorFunction != IRP_MJ_LOCK_CONTROL)) {
  113. return STATUS_NOT_SUPPORTED;
  114. }
  115. IF_DEBUG {
  116. PFOBX Fobx = (PFOBX)RxContext->pFobx;
  117. ASSERT( Fobx != NULL );
  118. ASSERT( Fobx->pSrvOpen == RxContext->pRelevantSrvOpen );
  119. }
  120. NewIrp = IoAllocateIrp( DeviceObject->StackSize, FALSE );
  121. if (!NewIrp) {
  122. return STATUS_INSUFFICIENT_RESOURCES;
  123. }
  124. //
  125. // Set current thread for IoSetHardErrorOrVerifyDevice.
  126. //
  127. NewIrp->Tail.Overlay.Thread = RxSpinUpRequestsThread; //PsGetCurrentThread();
  128. NewIrp->Tail.Overlay.OriginalFileObject = FileObject;
  129. NewIrp->RequestorMode = KernelMode;
  130. NewIrp->AssociatedIrp.SystemBuffer = (PVOID)NULL;
  131. //
  132. // Get a pointer to the stack location of the first driver which will be
  133. // invoked. This is where the function codes and the parameters are set.
  134. //
  135. IrpSp = IoGetNextIrpStackLocation( NewIrp );
  136. IrpSp->MajorFunction = (UCHAR) MajorFunction;
  137. IrpSp->MinorFunction = 0;
  138. IrpSp->FileObject = FileObject;
  139. IrpSp->DeviceObject = DeviceObject;
  140. if (CompletionRoutine != NULL) {
  141. IoSetCompletionRoutine( NewIrp,
  142. CompletionRoutine,
  143. Arg,
  144. TRUE,
  145. TRUE,
  146. TRUE );
  147. }
  148. NewIrp->Flags = 0;
  149. SetFlag( NewIrp->Flags, FlagOn( OriginalIrp->Flags, IRP_SYNCHRONOUS_API | IRP_NOCACHE ) );
  150. if (MajorFunction == IRP_MJ_LOCK_CONTROL) {
  151. //
  152. // We need to tag the lock flag
  153. //
  154. FileObject->LockOperation = TRUE;
  155. IrpSp->MinorFunction = RxContext->MinorFunction;
  156. IrpSp->Flags = (UCHAR)LowIoContext->ParamsFor.Locks.Flags;
  157. IrpSp->Parameters.LockControl.Length = (PLARGE_INTEGER)&LowIoContext->ParamsFor.Locks.Length;
  158. IrpSp->Parameters.LockControl.Key = RxShadowLockKeyLock( LowIoContext, LocalSrvOpen );
  159. IrpSp->Parameters.LockControl.ByteOffset.QuadPart = LowIoContext->ParamsFor.Locks.ByteOffset;
  160. NewIrp->Tail.Overlay.AuxiliaryBuffer = OriginalIrp->Tail.Overlay.AuxiliaryBuffer;
  161. *Irp = NewIrp;
  162. return STATUS_SUCCESS;
  163. }
  164. //
  165. // if file is opened with no intermediate bufffering then set no cache flag
  166. //
  167. if (FlagOn( FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING )) {
  168. SetFlag( NewIrp->Flags, IRP_NOCACHE );
  169. }
  170. Length = LowIoContext->ParamsFor.ReadWrite.ByteCount;
  171. if (MajorFunction == IRP_MJ_WRITE) {
  172. if (FlagOn( FileObject->Flags, FO_WRITE_THROUGH )) {
  173. IrpSp->Flags = SL_WRITE_THROUGH;
  174. }
  175. IrpSp->Parameters.Write.ByteOffset.QuadPart = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
  176. IrpSp->Parameters.Write.Length = Length;
  177. IrpSp->Parameters.Write.Key = RxShadowLockKey( LowIoContext, LocalSrvOpen );
  178. } else {
  179. IrpSp->Parameters.Read.ByteOffset.QuadPart = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
  180. IrpSp->Parameters.Read.Length = Length;
  181. IrpSp->Parameters.Read.Key = RxShadowLockKey( LowIoContext, LocalSrvOpen );
  182. }
  183. NewIrp->UserBuffer = OriginalIrp->UserBuffer;
  184. NewIrp->MdlAddress = RxContext->LowIoContext.ParamsFor.ReadWrite.Buffer;
  185. if (NewIrp->MdlAddress != NULL) {
  186. NewIrp->UserBuffer = MmGetMdlVirtualAddress( NewIrp->MdlAddress );
  187. if (FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP )) {
  188. //
  189. // we must map the mdl into system address space and use the system address instead
  190. //
  191. NewIrp->UserBuffer = MmGetSystemAddressForMdlSafe( NewIrp->MdlAddress, NormalPagePriority );
  192. //
  193. // we need to zap out the mdl address, otherwise the filesystem complains that the
  194. // userbuffer and the mdl startva are not the same
  195. //
  196. NewIrp->MdlAddress = NULL;
  197. }
  198. }
  199. //
  200. // Finally, return a pointer to the IRP.
  201. //
  202. *Irp = NewIrp;
  203. return STATUS_SUCCESS;
  204. }
  205. NTSTATUS
  206. RxShadowCommonCompletion (
  207. PRX_CONTEXT RxContext,
  208. PIRP Irp,
  209. NTSTATUS Status,
  210. ULONG_PTR Information
  211. )
  212. {
  213. PRX_SHADOW_CONTEXT Context;
  214. BOOLEAN SynchronousIo = !BooleanFlagOn( RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION );
  215. //
  216. // Clear the MDL address from the IRP if it is a re-use of our own. Do this before completion
  217. // so we can successfully read the Buffer MDL from the LOWIO_CONTEXT
  218. //
  219. if ( (Irp->MdlAddress == RxContext->LowIoContext.ParamsFor.ReadWrite.Buffer) &&
  220. ( (RxContext->MajorFunction == IRP_MJ_READ) ||
  221. (RxContext->MajorFunction == IRP_MJ_WRITE) ) ) {
  222. Irp->MdlAddress = NULL;
  223. }
  224. //
  225. // we need to synch with cancel
  226. //
  227. Context = (PRX_SHADOW_CONTEXT)RxContext->MRxContext;
  228. if (Context->Cancelable) {
  229. KIRQL SavedIrql;
  230. KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
  231. Irp = Context->Irp;
  232. if (!FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_CANCELLED )) {
  233. RxContext->MRxCancelRoutine = NULL;
  234. Context->Irp = NULL;
  235. } else {
  236. LONG x;
  237. //
  238. // cancel thread must have a reference on the Irp so we don't free it now but
  239. // on the actual cancel call
  240. //
  241. x = InterlockedDecrement( &Context->Refcnt );
  242. if (x > 0) {
  243. Irp = NULL;
  244. } else {
  245. //
  246. // we could have already got cancelled and we need to let the others we are done
  247. //
  248. Context->Irp = NULL;
  249. }
  250. }
  251. KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
  252. }
  253. RxContext->StoredStatus = Status;
  254. RxContext->InformationToReturn += Information;
  255. if (SynchronousIo) {
  256. //
  257. // Signal the thread that is waiting after queuing the workitem on the
  258. // KQueue.
  259. //
  260. RxSignalSynchronousWaiter( RxContext );
  261. } else {
  262. RxLowIoCompletion( RxContext );
  263. }
  264. if (Irp != NULL) {
  265. if (Irp->MdlAddress) {
  266. PMDL mdl,nextMdl;
  267. for (mdl = Irp->MdlAddress; mdl != NULL; mdl = nextMdl) {
  268. nextMdl = mdl->Next;
  269. MmUnlockPages( mdl );
  270. }
  271. for (mdl = Irp->MdlAddress; mdl != NULL; mdl = nextMdl) {
  272. nextMdl = mdl->Next;
  273. IoFreeMdl( mdl );
  274. }
  275. Irp->MdlAddress = NULL;
  276. }
  277. //
  278. // We are done with this Irp, so free it.
  279. //
  280. IoFreeIrp( Irp );
  281. }
  282. return STATUS_MORE_PROCESSING_REQUIRED;
  283. }
  284. NTSTATUS
  285. RxShadowIrpCompletion (
  286. IN PDEVICE_OBJECT DeviceObject,
  287. IN PIRP CalldownIrp OPTIONAL,
  288. IN PVOID Context
  289. )
  290. /*++
  291. Routine Description:
  292. This routine is called when the calldownIrp is completed.
  293. Arguments:
  294. DeviceObject - The device object in play.
  295. CalldownIrp -
  296. Context -
  297. Return Value:
  298. RXSTATUS - STATUS_MORE_PROCESSING_REQUIRED
  299. --*/
  300. {
  301. PRX_CONTEXT RxContext = (PRX_CONTEXT)Context;
  302. RxShadowCommonCompletion( RxContext,
  303. CalldownIrp,
  304. CalldownIrp->IoStatus.Status,
  305. CalldownIrp->IoStatus.Information );
  306. return STATUS_MORE_PROCESSING_REQUIRED;
  307. }
  308. NTSTATUS
  309. RxShadowCancelRoutine(
  310. PRX_CONTEXT RxContext
  311. )
  312. {
  313. KIRQL SavedIrql;
  314. PIRP Irp;
  315. LONG x;
  316. PRX_SHADOW_CONTEXT Context;
  317. Irp = NULL;
  318. KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
  319. Context = (RX_SHADOW_CONTEXT *) RxContext->MRxContext;
  320. Irp = Context->Irp;
  321. if (Irp != NULL) {
  322. //
  323. // io hasn't completed yet
  324. //
  325. InterlockedIncrement( &Context->Refcnt );
  326. //
  327. // need to clear the Irp field
  328. //
  329. Context->Irp = NULL;
  330. }
  331. KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
  332. if (Irp != NULL) {
  333. IoCancelIrp(Irp);
  334. x = InterlockedDecrement( &Context->Refcnt );
  335. if (x == 0) {
  336. if (Irp->MdlAddress) {
  337. PMDL mdl,nextMdl;
  338. for (mdl = Irp->MdlAddress; mdl != NULL; mdl = nextMdl) {
  339. nextMdl = mdl->Next;
  340. MmUnlockPages( mdl );
  341. }
  342. for (mdl = Irp->MdlAddress; mdl != NULL; mdl = nextMdl) {
  343. nextMdl = mdl->Next;
  344. IoFreeMdl( mdl );
  345. }
  346. Irp->MdlAddress = NULL;
  347. }
  348. IoFreeIrp( Irp );
  349. }
  350. }
  351. return STATUS_SUCCESS;
  352. }
  353. NTSTATUS
  354. RxShadowIoHandler (
  355. IN PRX_CONTEXT RxContext,
  356. IN PIRP Irp,
  357. IN PFCB Fcb,
  358. IN BOOLEAN Cancelable
  359. )
  360. /*++
  361. Routine Description:
  362. This routine is common to guys who use the async context engine. It has the
  363. responsibility for getting a context, initing, starting and finalizing it,
  364. but the internal guts of the procesing is via the continuation routine
  365. that is passed in.
  366. Arguments:
  367. RxContext - The RDBSS context.
  368. Irp - The original irp
  369. Fcb - The fcb io is being done on
  370. Cancelable - Can the irp be cancelled
  371. Return Value:
  372. RXSTATUS - The return status for the operation
  373. --*/
  374. {
  375. NTSTATUS Status = STATUS_SUCCESS;
  376. PMRXSHADOW_SRV_OPEN LocalSrvOpen;
  377. PLOWIO_CONTEXT LowIoContext = &(RxContext->LowIoContext);
  378. PIRP TopIrp = NULL;
  379. BOOLEAN SynchronousIo;
  380. PIRP ShadowIrp = NULL;
  381. LocalSrvOpen = RxGetShadowSrvOpenContext( RxContext->pRelevantSrvOpen );
  382. //
  383. // We are in, issue the I/O
  384. //
  385. SynchronousIo = !BooleanFlagOn( RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION );
  386. if (LocalSrvOpen->UnderlyingFileObject != NULL) {
  387. PDEVICE_OBJECT DeviceObject;
  388. PFILE_OBJECT FileObject;
  389. DeviceObject = LocalSrvOpen->UnderlyingDeviceObject;
  390. FileObject = LocalSrvOpen->UnderlyingFileObject;
  391. if (SynchronousIo) {
  392. KeInitializeEvent( &RxContext->SyncEvent, NotificationEvent, FALSE );
  393. }
  394. Status = RxShadowBuildAsynchronousRequest( Irp,
  395. DeviceObject,
  396. FileObject,
  397. Fcb,
  398. RxContext,
  399. LocalSrvOpen,
  400. RxShadowIrpCompletion,
  401. (PVOID) RxContext,
  402. &ShadowIrp );
  403. if (Status == STATUS_SUCCESS) {
  404. PRX_SHADOW_CONTEXT Context;
  405. Context = (PRX_SHADOW_CONTEXT)RxContext->MRxContext;
  406. ASSERT( sizeof( *Context ) <= sizeof( RxContext->MRxContext ));
  407. //
  408. // save new Irp if we want to resume later
  409. //
  410. Context->Irp = ShadowIrp;
  411. Context->Cancelable = Cancelable;
  412. Context->Refcnt = 1;
  413. try {
  414. //
  415. // Save the TopLevel Irp.
  416. //
  417. TopIrp = IoGetTopLevelIrp();
  418. //
  419. // Tell the underlying guy he's all clear.
  420. //
  421. IoSetTopLevelIrp( NULL );
  422. Status = IoCallDriver( DeviceObject, ShadowIrp );
  423. } finally {
  424. //
  425. // Restore my context for unwind.
  426. //
  427. IoSetTopLevelIrp( TopIrp );
  428. }
  429. if (Cancelable == TRUE) {
  430. KIRQL SavedIrql;
  431. TopIrp = NULL;
  432. KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
  433. if ((Context->Irp != NULL) &&
  434. !FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_CANCELLED )) {
  435. //
  436. // io is still pending and hasn't been cancelled
  437. //
  438. RxContext->MRxCancelRoutine = RxShadowCancelRoutine;
  439. } else if (Context->Irp != NULL) {
  440. //
  441. // io is already cancelled
  442. //
  443. TopIrp = Context->Irp;
  444. //
  445. // we need to clear the Irp field
  446. //
  447. Context->Irp = NULL;
  448. //
  449. // we need to take an extra reference
  450. //
  451. InterlockedIncrement( &Context->Refcnt );
  452. }
  453. KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
  454. if (TopIrp != NULL) {
  455. LONG x;
  456. IoCancelIrp( TopIrp );
  457. x = InterlockedDecrement( &Context->Refcnt );
  458. if (x == 0) {
  459. if (TopIrp->MdlAddress) {
  460. TopIrp->MdlAddress = NULL;
  461. }
  462. IoFreeIrp( TopIrp );
  463. }
  464. }
  465. }
  466. if (SynchronousIo) {
  467. RxWaitSync( RxContext );
  468. Status = RxContext->StoredStatus;
  469. } else {
  470. Status = STATUS_PENDING;
  471. }
  472. }
  473. } else {
  474. Status = STATUS_VOLUME_DISMOUNTED;
  475. }
  476. return Status;
  477. }
  478. NTSTATUS
  479. RxShadowFastLowIo (
  480. IN PRX_CONTEXT RxContext,
  481. IN PIRP Irp
  482. )
  483. /*++
  484. Routine Description:
  485. This routine handles network read requests.
  486. Arguments:
  487. RxContext - the RDBSS context
  488. Return Value:
  489. RXSTATUS - The return status for the operation
  490. --*/
  491. {
  492. NTSTATUS Status = STATUS_MORE_PROCESSING_REQUIRED;
  493. PMRXSHADOW_SRV_OPEN MrxShadowSrvOpen;
  494. PLOWIO_CONTEXT LowIoContext = &(RxContext->LowIoContext);
  495. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  496. LARGE_INTEGER Offset;
  497. BOOLEAN Wait, PagingIo;
  498. IO_STATUS_BLOCK Ios;
  499. PVOID Buffer;
  500. PIRP TopIrp;
  501. //
  502. // we only support read and write
  503. //
  504. if ((LowIoContext->Operation != LOWIO_OP_READ) && (LowIoContext->Operation != LOWIO_OP_WRITE)) {
  505. return Status;
  506. }
  507. //
  508. // don't deal with name pipes
  509. //
  510. if (FlagOn( RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_OPERATION )) {
  511. return Status;
  512. }
  513. //
  514. // check for locks and take default path
  515. //
  516. if (IrpSp->FileObject && IrpSp->FileObject->LockOperation) {
  517. return Status;
  518. }
  519. PagingIo = BooleanFlagOn( LowIoContext->ParamsFor.ReadWrite.Flags, LOWIO_READWRITEFLAG_PAGING_IO );
  520. MrxShadowSrvOpen = RxGetShadowSrvOpenContext( RxContext->pRelevantSrvOpen );
  521. //
  522. // The only time we can get PagingIo write on a loopback file is if the
  523. // file has been memory mapped.
  524. //
  525. //
  526. // We don't handle PagingIo read and no-buffering handles through fast
  527. // path. PagingIo write is tried through the fast path and if it does
  528. // not succeed then we return STATUS_MORE_PROCESSING_REQUIRED.
  529. //
  530. if ((PagingIo && LowIoContext->Operation == LOWIO_OP_READ) ||
  531. (MrxShadowSrvOpen == NULL) ||
  532. (MrxShadowSrvOpen->UnderlyingFileObject == NULL ) ||
  533. (IrpSp->FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING)) {
  534. return Status;
  535. }
  536. Offset.QuadPart = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
  537. //
  538. // get user buffer
  539. //
  540. if (!FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP )) {
  541. Buffer = Irp->UserBuffer;
  542. } else {
  543. ASSERT( LowIoContext->ParamsFor.ReadWrite.Buffer != NULL );
  544. Buffer = RxLowIoGetBufferAddress( RxContext );
  545. }
  546. //
  547. // Check shadow state and io params.
  548. //
  549. if (RxShadowVerifyIoParameters( MrxShadowSrvOpen->UnderlyingDeviceObject,
  550. IrpSp->FileObject,
  551. Buffer,
  552. LowIoContext->ParamsFor.ReadWrite.ByteCount,
  553. &Offset) != STATUS_SUCCESS) {
  554. return Status;
  555. }
  556. Wait = !BooleanFlagOn( RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION );
  557. if (PagingIo) {
  558. ASSERT(LowIoContext->Operation == LOWIO_OP_WRITE);
  559. Wait = FALSE;
  560. }
  561. //
  562. // Save the TopLevel Irp.
  563. //
  564. TopIrp = IoGetTopLevelIrp();
  565. //
  566. // Tell the underlying guy he's all clear.
  567. //
  568. IoSetTopLevelIrp( NULL );
  569. try {
  570. if ((LowIoContext->Operation == LOWIO_OP_READ) &&
  571. (MrxShadowSrvOpen->FastIoRead != NULL) &&
  572. MrxShadowSrvOpen->FastIoRead(MrxShadowSrvOpen->UnderlyingFileObject,
  573. &Offset,
  574. LowIoContext->ParamsFor.ReadWrite.ByteCount,
  575. Wait,
  576. RxShadowLockKey( LowIoContext, MrxShadowSrvOpen ),
  577. Buffer,
  578. &Ios,
  579. MrxShadowSrvOpen->UnderlyingDeviceObject )) {
  580. //
  581. // the fast io path worked
  582. //
  583. Irp->IoStatus = Ios;
  584. RxContext->StoredStatus = Ios.Status;
  585. RxContext->InformationToReturn += Ios.Information;
  586. Status = Ios.Status;
  587. } else if ((LowIoContext->Operation == LOWIO_OP_WRITE) &&
  588. (MrxShadowSrvOpen->FastIoWrite != NULL) &&
  589. MrxShadowSrvOpen->FastIoWrite(MrxShadowSrvOpen->UnderlyingFileObject,
  590. &Offset,
  591. LowIoContext->ParamsFor.ReadWrite.ByteCount,
  592. Wait,
  593. RxShadowLockKey(LowIoContext, MrxShadowSrvOpen),
  594. Buffer,
  595. &Ios,
  596. MrxShadowSrvOpen->UnderlyingDeviceObject )) {
  597. //
  598. // The fast io path worked.
  599. //
  600. Irp->IoStatus = Ios;
  601. RxContext->StoredStatus = Ios.Status;
  602. RxContext->InformationToReturn += Ios.Information;
  603. Status = Ios.Status;
  604. }
  605. } except( EXCEPTION_EXECUTE_HANDLER ) {
  606. //
  607. // TODO: Should we fall through to the slow path on an exception?
  608. //
  609. Status = GetExceptionCode();
  610. }
  611. if (Status != STATUS_SUCCESS && PagingIo) {
  612. ASSERT(LowIoContext->Operation == LOWIO_OP_WRITE);
  613. Status = STATUS_MORE_PROCESSING_REQUIRED;
  614. }
  615. //
  616. // Restore my context for unwind.
  617. //
  618. IoSetTopLevelIrp( TopIrp );
  619. return Status;
  620. }
  621. NTSTATUS
  622. RxShadowLowIo (
  623. IN PRX_CONTEXT RxContext,
  624. IN PIRP Irp,
  625. IN PFCB Fcb
  626. )
  627. /*++
  628. Routine Description:
  629. This routine handles network read requests.
  630. Arguments:
  631. RxContext - the RDBSS context
  632. Return Value:
  633. RXSTATUS - The return status for the operation
  634. --*/
  635. {
  636. NTSTATUS Status = STATUS_MORE_PROCESSING_REQUIRED;
  637. PMRXSHADOW_SRV_OPEN MrxShadowSrvOpen;
  638. PLOWIO_CONTEXT LowIoContext = &(RxContext->LowIoContext);
  639. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  640. LARGE_INTEGER Offset;
  641. PVOID Buffer;
  642. //
  643. // we only support read and write and lock
  644. //
  645. if ((LowIoContext->Operation != LOWIO_OP_READ) &&
  646. (LowIoContext->Operation != LOWIO_OP_WRITE) &&
  647. (RxContext->MajorFunction != IRP_MJ_LOCK_CONTROL)) {
  648. return Status;
  649. }
  650. //
  651. // don't deal with name pipes
  652. //
  653. if (FlagOn( RxContext->FlagsForLowIo, RXCONTEXT_FLAG4LOWIO_PIPE_OPERATION )) {
  654. return Status;
  655. }
  656. MrxShadowSrvOpen = RxGetShadowSrvOpenContext( RxContext->pRelevantSrvOpen );
  657. if ((MrxShadowSrvOpen == NULL) ||
  658. (MrxShadowSrvOpen->UnderlyingFileObject == NULL)) {
  659. return Status;
  660. }
  661. //
  662. // if min-rdr wants to handle shadow io then pass call down
  663. //
  664. if (MrxShadowSrvOpen->DispatchRoutine) {
  665. return MrxShadowSrvOpen->DispatchRoutine( RxContext );
  666. }
  667. if ((LowIoContext->Operation == LOWIO_OP_READ) ||
  668. (LowIoContext->Operation == LOWIO_OP_WRITE)) {
  669. Offset.QuadPart = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
  670. //
  671. // if we have no mdl then use the user buffer directly
  672. //
  673. if (!LowIoContext->ParamsFor.ReadWrite.Buffer) {
  674. Buffer = Irp->UserBuffer;
  675. } else {
  676. Buffer = RxLowIoGetBufferAddress( RxContext );
  677. }
  678. //
  679. // check shadow state and io params
  680. //
  681. Status = RxShadowVerifyIoParameters( MrxShadowSrvOpen->UnderlyingDeviceObject,
  682. IrpSp->FileObject,
  683. Buffer,
  684. LowIoContext->ParamsFor.ReadWrite.ByteCount,
  685. &Offset );
  686. if (Status != STATUS_SUCCESS) {
  687. //
  688. // don't return status more processing required here in order to enforce proper
  689. // alignment. Note, if the user has the file locked the server can't help it anyway.
  690. //
  691. return Status;
  692. }
  693. }
  694. Status = RxShadowIoHandler( RxContext, Irp, Fcb, RxContext->MajorFunction == IRP_MJ_LOCK_CONTROL ? TRUE : FALSE );
  695. return Status;
  696. }