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.

1268 lines
32 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. NtFastIo.c
  5. Abstract:
  6. This module implements NT fastio routines.
  7. Author:
  8. Joe Linn [JoeLinn] 9-Nov-1994
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // The local debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_NTFASTIO)
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, RxFastIoRead)
  19. #pragma alloc_text(PAGE, RxFastIoWrite)
  20. #pragma alloc_text(PAGE, RxFastLock)
  21. #pragma alloc_text(PAGE, RxFastUnlockAll)
  22. #pragma alloc_text(PAGE, RxFastUnlockAllByKey)
  23. #pragma alloc_text(PAGE, RxFastUnlockSingle)
  24. #pragma alloc_text(PAGE, RxFastIoCheckIfPossible)
  25. #pragma alloc_text(PAGE, RxFastQueryBasicInfo)
  26. #pragma alloc_text(PAGE, RxFastQueryStdInfo)
  27. #endif
  28. //these declarations would be copied to fsrtl.h
  29. BOOLEAN
  30. FsRtlCopyRead2 (
  31. IN PFILE_OBJECT FileObject,
  32. IN PLARGE_INTEGER FileOffset,
  33. IN ULONG Length,
  34. IN BOOLEAN Wait,
  35. IN ULONG LockKey,
  36. OUT PVOID Buffer,
  37. OUT PIO_STATUS_BLOCK IoStatus,
  38. IN PDEVICE_OBJECT DeviceObject,
  39. IN ULONG_PTR TopLevelIrpValue
  40. );
  41. BOOLEAN
  42. FsRtlCopyWrite2 (
  43. IN PFILE_OBJECT FileObject,
  44. IN PLARGE_INTEGER FileOffset,
  45. IN ULONG Length,
  46. IN BOOLEAN Wait,
  47. IN ULONG LockKey,
  48. IN PVOID Buffer,
  49. OUT PIO_STATUS_BLOCK IoStatus,
  50. IN PDEVICE_OBJECT DeviceObject,
  51. IN ULONG_PTR TopLevelIrpValue
  52. );
  53. BOOLEAN
  54. RxFastIoRead (
  55. IN PFILE_OBJECT FileObject,
  56. IN PLARGE_INTEGER FileOffset,
  57. IN ULONG Length,
  58. IN BOOLEAN Wait,
  59. IN ULONG LockKey,
  60. OUT PVOID Buffer,
  61. OUT PIO_STATUS_BLOCK IoStatus,
  62. IN PDEVICE_OBJECT DeviceObject
  63. )
  64. {
  65. BOOLEAN ReturnValue;
  66. RX_TOPLEVELIRP_CONTEXT TopLevelContext;
  67. PAGED_CODE();
  68. RxDbgTrace(+1, Dbg, ("RxFastIoRead\n"));
  69. RxLog(("FastRead %lx:%lx:%lx",FileObject,FileObject->FsContext,FileObject->FsContext2));
  70. RxLog(("------>> %lx@%lx %lx",Length,FileOffset->LowPart,FileOffset->HighPart));
  71. RxWmiLog(LOG,
  72. RxFastIoRead_1,
  73. LOGPTR(FileObject)
  74. LOGPTR(FileObject->FsContext)
  75. LOGPTR(FileObject->FsContext2)
  76. LOGULONG(Length)
  77. LOGULONG(FileOffset->LowPart)
  78. LOGULONG(FileOffset->HighPart));
  79. ASSERT(RxIsThisTheTopLevelIrp(NULL));
  80. RxInitializeTopLevelIrpContext(
  81. &TopLevelContext,
  82. ((PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP),
  83. (PRDBSS_DEVICE_OBJECT)DeviceObject);
  84. ReturnValue = FsRtlCopyRead2 (
  85. FileObject,
  86. FileOffset,
  87. Length,
  88. Wait,
  89. LockKey,
  90. Buffer,
  91. IoStatus,
  92. DeviceObject,
  93. (ULONG_PTR)(&TopLevelContext)
  94. );
  95. RxDbgTrace(-1, Dbg, ("RxFastIoRead ReturnValue=%x\n", ReturnValue));
  96. if (ReturnValue) {
  97. RxLog(
  98. ("FastReadYes %lx ret %lx:%lx",
  99. FileObject->FsContext2,IoStatus->Status,IoStatus->Information));
  100. RxWmiLog(LOG,
  101. RxFastIoRead_2,
  102. LOGPTR(FileObject->FsContext2)
  103. LOGULONG(IoStatus->Status)
  104. LOGPTR(IoStatus->Information));
  105. } else {
  106. RxLog(("FastReadNo %lx",FileObject->FsContext2));
  107. RxWmiLog(LOG,
  108. RxFastIoRead_3,
  109. LOGPTR(FileObject->FsContext2));
  110. }
  111. return ReturnValue;
  112. }
  113. BOOLEAN
  114. RxFastIoWrite (
  115. IN PFILE_OBJECT FileObject,
  116. IN PLARGE_INTEGER FileOffset,
  117. IN ULONG Length,
  118. IN BOOLEAN Wait,
  119. IN ULONG LockKey,
  120. IN PVOID Buffer,
  121. OUT PIO_STATUS_BLOCK IoStatus,
  122. IN PDEVICE_OBJECT DeviceObject
  123. )
  124. {
  125. BOOLEAN ReturnValue;
  126. RX_TOPLEVELIRP_CONTEXT TopLevelContext;
  127. PSRV_OPEN SrvOpen;
  128. PAGED_CODE();
  129. RxDbgTrace(+1, Dbg, ("RxFastIoWrite\n"));
  130. SrvOpen = ((PFOBX)(FileObject->FsContext2))->SrvOpen;
  131. if (FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_DONTUSE_WRITE_CACHEING)) {
  132. //if this flag is set, we have to treat this as an unbuffered Io....sigh.
  133. RxDbgTrace(-1, Dbg, ("RxFastIoWrite DONTUSE_WRITE_CACHEING...failing\n"));
  134. return FALSE;
  135. }
  136. ASSERT(RxIsThisTheTopLevelIrp(NULL));
  137. RxInitializeTopLevelIrpContext(
  138. &TopLevelContext,
  139. ((PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP),
  140. (PRDBSS_DEVICE_OBJECT)DeviceObject);
  141. ReturnValue = FsRtlCopyWrite2 (
  142. FileObject,
  143. FileOffset,
  144. Length,
  145. Wait,
  146. LockKey,
  147. Buffer,
  148. IoStatus,
  149. DeviceObject,
  150. (ULONG_PTR)(&TopLevelContext)
  151. );
  152. RxDbgTrace(-1, Dbg, ("RxFastIoWrite ReturnValue=%x\n", ReturnValue));
  153. if (ReturnValue) {
  154. RxLog(
  155. ("FWY %lx OLP: %lx SLP: %lx IOSB %lx:%lx",
  156. FileObject->FsContext2,
  157. FileOffset->LowPart,
  158. SrvOpen->pFcb->Header.FileSize.LowPart,
  159. IoStatus->Status,
  160. IoStatus->Information));
  161. RxWmiLog(LOG,
  162. RxFastIoWrite_1,
  163. LOGPTR(FileObject->FsContext2)
  164. LOGULONG(FileOffset->LowPart)
  165. LOGULONG(SrvOpen->pFcb->Header.FileSize.LowPart)
  166. LOGULONG(IoStatus->Status)
  167. LOGPTR(IoStatus->Information));
  168. } else {
  169. RxLog(("FastWriteNo %lx",FileObject->FsContext2));
  170. RxWmiLog(LOG,
  171. RxFastIoWrite_2,
  172. LOGPTR(FileObject->FsContext2));
  173. }
  174. return ReturnValue;
  175. }
  176. BOOLEAN
  177. RxFastLock (
  178. IN PFILE_OBJECT FileObject,
  179. IN PLARGE_INTEGER FileOffset,
  180. IN PLARGE_INTEGER Length,
  181. PEPROCESS ProcessId,
  182. ULONG Key,
  183. BOOLEAN FailImmediately,
  184. BOOLEAN ExclusiveLock,
  185. OUT PIO_STATUS_BLOCK IoStatus,
  186. IN PDEVICE_OBJECT DeviceObject
  187. )
  188. /*++
  189. Routine Description:
  190. This is a call back routine for doing the fast lock call.
  191. Arguments:
  192. FileObject - Supplies the file object used in this operation
  193. FileOffset - Supplies the file offset used in this operation
  194. Length - Supplies the length used in this operation
  195. ProcessId - Supplies the process ID used in this operation
  196. Key - Supplies the key used in this operation
  197. FailImmediately - Indicates if the request should fail immediately
  198. if the lock cannot be granted.
  199. ExclusiveLock - Indicates if this is a request for an exclusive or
  200. shared lock
  201. IoStatus - Receives the Status if this operation is successful
  202. Return Value:
  203. BOOLEAN - TRUE if this operation completed and FALSE if caller
  204. needs to take the long route.
  205. --*/
  206. {
  207. BOOLEAN Results;
  208. PFCB Fcb = (PFCB)(FileObject->FsContext); //need a macro
  209. PAGED_CODE();
  210. RxDbgTrace(+1, Dbg, ("RxFastLock\n", 0));
  211. //
  212. // Decode the type of file object we're being asked to process and make
  213. // sure it is only a user file open.
  214. //
  215. if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
  216. IoStatus->Status = STATUS_INVALID_PARAMETER;
  217. IoStatus->Information = 0;
  218. RxDbgTrace(-1, Dbg, ("RxFastLock -> TRUE (RxStatus(INVALID_PARAMETER))\n", 0));
  219. return TRUE;
  220. }
  221. RxDbgTrace(-1, Dbg, ("RxFastLock -> FALSE (fastlocks not yet implemented)\n", 0));
  222. return FALSE; //stuff past here has been massaged but not tested
  223. //
  224. // Acquire exclusive access to the Fcb this operation can always wait; you need
  225. // the resource to synchronize with oplock breaks
  226. //
  227. FsRtlEnterFileSystem();
  228. ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
  229. try {
  230. //
  231. // We check whether we can proceed
  232. // based on the state of the file oplocks.
  233. //
  234. if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
  235. try_return( Results = FALSE );
  236. }
  237. //
  238. // Now call the FsRtl routine to do the actual processing of the
  239. // Lock request
  240. //
  241. if (Results = FsRtlFastLock(
  242. &Fcb->Specific.Fcb.FileLock,
  243. FileObject,
  244. FileOffset,
  245. Length,
  246. ProcessId,
  247. Key,
  248. FailImmediately,
  249. ExclusiveLock,
  250. IoStatus,
  251. NULL,
  252. FALSE )) {
  253. //
  254. // Set the flag indicating if Fast I/O is possible
  255. //
  256. //Fcb->Header.IsFastIoPossible = RxIsFastIoPossible( Fcb );
  257. }
  258. try_exit: NOTHING;
  259. } finally {
  260. DebugUnwind( RxFastLock );
  261. //
  262. // Release the Fcb, and return to our caller
  263. //
  264. ExReleaseResourceLite( (Fcb)->Header.Resource );
  265. FsRtlExitFileSystem();
  266. RxDbgTrace(-1, Dbg, ("RxFastLock -> %08lx\n", Results));
  267. }
  268. return Results;
  269. }
  270. BOOLEAN
  271. RxFastUnlockSingle (
  272. IN PFILE_OBJECT FileObject,
  273. IN PLARGE_INTEGER FileOffset,
  274. IN PLARGE_INTEGER Length,
  275. PEPROCESS ProcessId,
  276. ULONG Key,
  277. OUT PIO_STATUS_BLOCK IoStatus,
  278. IN PDEVICE_OBJECT DeviceObject
  279. )
  280. /*++
  281. Routine Description:
  282. This is a call back routine for doing the fast unlock single call.
  283. Arguments:
  284. FileObject - Supplies the file object used in this operation
  285. FileOffset - Supplies the file offset used in this operation
  286. Length - Supplies the length used in this operation
  287. ProcessId - Supplies the process ID used in this operation
  288. Key - Supplies the key used in this operation
  289. Status - Receives the Status if this operation is successful
  290. Return Value:
  291. BOOLEAN - TRUE if this operation completed and FALSE if caller
  292. needs to take the long route.
  293. --*/
  294. {
  295. BOOLEAN Results;
  296. PFCB Fcb = (PFCB)(FileObject->FsContext); //need macro
  297. PAGED_CODE();
  298. RxDbgTrace(+1, Dbg, ("RxFastUnlockSingle\n", 0));
  299. IoStatus->Information = 0;
  300. //
  301. // Decode the type of file object we're being asked to process and make sure
  302. // it is only a user file open
  303. //
  304. if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
  305. IoStatus->Status = STATUS_INVALID_PARAMETER;
  306. RxDbgTrace(-1, Dbg, ("RxFastUnlockSingle -> TRUE (RxStatus(INVALID_PARAMETER))\n", 0));
  307. return TRUE;
  308. }
  309. RxDbgTrace(-1, Dbg, ("RxFastUnlockSingle -> FALSE (fastlocks not yet implemented)\n", 0));
  310. return FALSE; //stuff past here has been massaged but not tested
  311. //
  312. // Acquire exclusive access to the Fcb this operation can always wait
  313. //
  314. FsRtlEnterFileSystem();
  315. ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
  316. try {
  317. //
  318. // We check whether we can proceed based on the state of the file oplocks.
  319. //
  320. if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
  321. try_return( Results = FALSE );
  322. }
  323. //
  324. // Now call the FsRtl routine to do the actual processing of the
  325. // Lock request. The call will always succeed.
  326. //
  327. Results = TRUE;
  328. IoStatus->Status = FsRtlFastUnlockSingle(
  329. &Fcb->Specific.Fcb.FileLock,
  330. FileObject,
  331. FileOffset,
  332. Length,
  333. ProcessId,
  334. Key,
  335. NULL,
  336. FALSE );
  337. //
  338. // Set the flag indicating if Fast I/O is possible
  339. //
  340. //Fcb->Header.IsFastIoPossible = RxIsFastIoPossible( Fcb );
  341. try_exit: NOTHING;
  342. } finally {
  343. DebugUnwind( RxFastUnlockSingle );
  344. //
  345. // Release the Fcb, and return to our caller
  346. //
  347. ExReleaseResourceLite( (Fcb)->Header.Resource );
  348. FsRtlExitFileSystem();
  349. RxDbgTrace(-1, Dbg, ("RxFastUnlockSingle -> %08lx\n", Results));
  350. }
  351. return Results;
  352. }
  353. BOOLEAN
  354. RxFastUnlockAll (
  355. IN PFILE_OBJECT FileObject,
  356. PEPROCESS ProcessId,
  357. OUT PIO_STATUS_BLOCK IoStatus,
  358. IN PDEVICE_OBJECT DeviceObject
  359. )
  360. /*++
  361. Routine Description:
  362. This is a call back routine for doing the fast unlock all call.
  363. Arguments:
  364. FileObject - Supplies the file object used in this operation
  365. ProcessId - Supplies the process ID used in this operation
  366. Status - Receives the Status if this operation is successful
  367. Return Value:
  368. BOOLEAN - TRUE if this operation completed and FALSE if caller
  369. needs to take the long route.
  370. --*/
  371. {
  372. BOOLEAN Results;
  373. PFCB Fcb = (PFCB)(FileObject->FsContext); //need macro
  374. PAGED_CODE();
  375. RxDbgTrace(+1, Dbg, ("RxFastUnlockAll\n", 0));
  376. IoStatus->Information = 0;
  377. //
  378. // Decode the type of file object we're being asked to process and make sure
  379. // it is only a user file open.
  380. //
  381. if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
  382. IoStatus->Status = STATUS_INVALID_PARAMETER;
  383. RxDbgTrace(-1, Dbg, ("RxFastUnlockAll -> TRUE (RxStatus(INVALID_PARAMETER))\n", 0));
  384. return TRUE;
  385. }
  386. RxDbgTrace(-1, Dbg, ("RxFastUnlockAll -> FALSE (fastlocks not yet implemented)\n", 0));
  387. return FALSE; //stuff past here has been massaged but not tested
  388. //
  389. // Acquire exclusive access to the Fcb this operation can always wait
  390. //
  391. FsRtlEnterFileSystem();
  392. (VOID) ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
  393. try {
  394. //
  395. // We check whether we can proceed based on the state of the file oplocks.
  396. //
  397. if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
  398. try_return( Results = FALSE );
  399. }
  400. //
  401. // Now call the FsRtl routine to do the actual processing of the
  402. // Lock request. The call will always succeed.
  403. //
  404. Results = TRUE;
  405. IoStatus->Status = FsRtlFastUnlockAll(
  406. &Fcb->Specific.Fcb.FileLock,
  407. FileObject,
  408. ProcessId,
  409. NULL );
  410. //
  411. // Set the flag indicating if Fast I/O is possible
  412. //
  413. //Fcb->Header.IsFastIoPossible = RxIsFastIoPossible( Fcb );
  414. try_exit: NOTHING;
  415. } finally {
  416. DebugUnwind( RxFastUnlockAll );
  417. //
  418. // Release the Fcb, and return to our caller
  419. //
  420. ExReleaseResourceLite( (Fcb)->Header.Resource );
  421. FsRtlExitFileSystem();
  422. RxDbgTrace(-1, Dbg, ("RxFastUnlockAll -> %08lx\n", Results));
  423. }
  424. return Results;
  425. }
  426. BOOLEAN
  427. RxFastUnlockAllByKey (
  428. IN PFILE_OBJECT FileObject,
  429. PVOID ProcessId,
  430. ULONG Key,
  431. OUT PIO_STATUS_BLOCK IoStatus,
  432. IN PDEVICE_OBJECT DeviceObject
  433. )
  434. /*++
  435. Routine Description:
  436. This is a call back routine for doing the fast unlock all by key call.
  437. Arguments:
  438. FileObject - Supplies the file object used in this operation
  439. ProcessId - Supplies the process ID used in this operation
  440. Key - Supplies the key used in this operation
  441. Status - Receives the Status if this operation is successful
  442. Return Value:
  443. BOOLEAN - TRUE if this operation completed and FALSE if caller
  444. needs to take the long route.
  445. --*/
  446. {
  447. BOOLEAN Results;
  448. PFCB Fcb = (PFCB)(FileObject->FsContext); //need macro
  449. PAGED_CODE();
  450. RxDbgTrace(+1, Dbg, ("RxFastUnlockAllByKey\n", 0));
  451. IoStatus->Information = 0;
  452. //
  453. // Decode the type of file object we're being asked to process and make sure
  454. // it is only a user file open.
  455. //
  456. if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
  457. IoStatus->Status = STATUS_INVALID_PARAMETER;
  458. RxDbgTrace(-1, Dbg, ("RxFastUnlockAll -> TRUE (RxStatus(INVALID_PARAMETER))\n", 0));
  459. return TRUE;
  460. }
  461. RxDbgTrace(-1, Dbg, ("RxFastUnlockAll -> FALSE (fastlocks not yet implemented)\n", 0));
  462. return FALSE; //stuff past here has been massaged but not tested
  463. //
  464. // Acquire exclusive access to the Fcb this operation can always wait
  465. //
  466. FsRtlEnterFileSystem();
  467. (VOID) ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
  468. try {
  469. //
  470. // We check whether we can proceed based on the state of the file oplocks.
  471. //
  472. if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
  473. try_return( Results = FALSE );
  474. }
  475. //
  476. // Now call the FsRtl routine to do the actual processing of the
  477. // Lock request. The call will always succeed.
  478. //
  479. Results = TRUE;
  480. IoStatus->Status = FsRtlFastUnlockAllByKey(
  481. &Fcb->Specific.Fcb.FileLock,
  482. FileObject,
  483. ProcessId,
  484. Key,
  485. NULL );
  486. //
  487. // Set the flag indicating if Fast I/O is possible
  488. //
  489. //Fcb->Header.IsFastIoPossible = RxIsFastIoPossible( Fcb );
  490. try_exit: NOTHING;
  491. } finally {
  492. DebugUnwind( RxFastUnlockAllByKey );
  493. //
  494. // Release the Fcb, and return to our caller
  495. //
  496. ExReleaseResourceLite( (Fcb)->Header.Resource );
  497. FsRtlExitFileSystem();
  498. RxDbgTrace(-1, Dbg, ("RxFastUnlockAllByKey -> %08lx\n", Results));
  499. }
  500. return Results;
  501. }
  502. #define RxLogAndReturnFalse(x) { \
  503. RxLog(("CheckFast fail %lx %s",FileObject,x)); \
  504. RxWmiLog(LOG, \
  505. RxFastIoCheckIfPossible, \
  506. LOGPTR(FileObject) \
  507. LOGARSTR(x)); \
  508. return FALSE; \
  509. }
  510. BOOLEAN
  511. RxFastIoCheckIfPossible (
  512. IN PFILE_OBJECT FileObject,
  513. IN PLARGE_INTEGER FileOffset,
  514. IN ULONG Length,
  515. IN BOOLEAN Wait,
  516. IN ULONG LockKey,
  517. IN BOOLEAN CheckForReadOperation,
  518. OUT PIO_STATUS_BLOCK IoStatus,
  519. IN PDEVICE_OBJECT DeviceObject
  520. )
  521. /*++
  522. Routine Description:
  523. This routine checks if fast i/o is possible for a read/write operation
  524. Arguments:
  525. FileObject - Supplies the file object used in the query
  526. FileOffset - Supplies the starting byte offset for the read/write operation
  527. Length - Supplies the length, in bytes, of the read/write operation
  528. Wait - Indicates if we can wait
  529. LockKey - Supplies the lock key
  530. CheckForReadOperation - Indicates if this is a check for a read or write
  531. operation
  532. IoStatus - Receives the status of the operation if our return value is
  533. FastIoReturnError
  534. Return Value:
  535. BOOLEAN - TRUE if fast I/O is possible and FALSE if the caller needs
  536. to take the long route.
  537. --*/
  538. {
  539. PFCB Fcb = (PFCB)(FileObject->FsContext);
  540. PFOBX Fobx = (PFOBX)(FileObject->FsContext2);
  541. PSRV_OPEN pSrvOpen = Fobx->SrvOpen;
  542. LARGE_INTEGER LargeLength;
  543. PAGED_CODE();
  544. if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
  545. RxLogAndReturnFalse("notfile");
  546. }
  547. if (!FsRtlOplockIsFastIoPossible( &Fcb->Specific.Fcb.Oplock )) {
  548. RxLogAndReturnFalse("cnd/oplock");
  549. }
  550. if (FileObject->DeletePending) {
  551. RxLogAndReturnFalse("delpend");
  552. }
  553. if (Fcb->NonPaged->OutstandingAsyncWrites != 0) {
  554. RxLogAndReturnFalse("asynW");
  555. }
  556. if (FlagOn(pSrvOpen->Flags,SRVOPEN_FLAG_ORPHANED)) {
  557. RxLogAndReturnFalse("srvopen orphaned");
  558. }
  559. if (FlagOn(Fcb->FcbState,FCB_STATE_ORPHANED)) {
  560. RxLogAndReturnFalse("orphaned");
  561. }
  562. if (BooleanFlagOn(
  563. pSrvOpen->Flags,
  564. SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING)) {
  565. RxLogAndReturnFalse("buf state change");
  566. }
  567. if (FlagOn(pSrvOpen->Flags,SRVOPEN_FLAG_FILE_RENAMED) ||
  568. FlagOn(pSrvOpen->Flags,SRVOPEN_FLAG_FILE_DELETED)) {
  569. RxLogAndReturnFalse("ren/del");
  570. }
  571. // Ensure that all pending buffering state change requests are processed
  572. // before letting the operation through.
  573. FsRtlEnterFileSystem();
  574. RxProcessChangeBufferingStateRequestsForSrvOpen(pSrvOpen);
  575. FsRtlExitFileSystem();
  576. LargeLength.QuadPart = Length;
  577. //
  578. // Based on whether this is a read or write operation we call
  579. // fsrtl check for read/write
  580. //
  581. if (CheckForReadOperation) {
  582. if (!FlagOn(Fcb->FcbState,FCB_STATE_READCACHEING_ENABLED)) {
  583. RxLogAndReturnFalse("notreadC");
  584. }
  585. if (!FsRtlFastCheckLockForRead(
  586. &Fcb->Specific.Fcb.FileLock,
  587. FileOffset,
  588. &LargeLength,
  589. LockKey,
  590. FileObject,
  591. PsGetCurrentProcess() )) {
  592. RxLogAndReturnFalse("readlock");
  593. }
  594. } else {
  595. if (!FlagOn(Fcb->FcbState,FCB_STATE_WRITECACHEING_ENABLED)) {
  596. RxLogAndReturnFalse("notwriteC");
  597. }
  598. //
  599. // Also check for a write-protected volume here.
  600. //
  601. if (!FsRtlFastCheckLockForWrite(
  602. &Fcb->Specific.Fcb.FileLock,
  603. FileOffset,
  604. &LargeLength,
  605. LockKey,
  606. FileObject,
  607. PsGetCurrentProcess() )) {
  608. RxLogAndReturnFalse("writelock");
  609. }
  610. }
  611. // RxLog(("IoPossible %lx",FileObject));
  612. return TRUE;
  613. }
  614. BOOLEAN
  615. RxFastIoDeviceControl(
  616. IN struct _FILE_OBJECT *FileObject,
  617. IN BOOLEAN Wait,
  618. IN PVOID InputBuffer OPTIONAL,
  619. IN ULONG InputBufferLength,
  620. OUT PVOID OutputBuffer OPTIONAL,
  621. IN ULONG OutputBufferLength,
  622. IN ULONG IoControlCode,
  623. OUT PIO_STATUS_BLOCK IoStatus,
  624. IN struct _DEVICE_OBJECT *DeviceObject
  625. )
  626. /*++
  627. Routine Description:
  628. This routine is for the fast device control call.
  629. Arguments:
  630. FileObject - Supplies the file object used in this operation
  631. Wait - Indicates if we are allowed to wait for the information
  632. InputBuffer - Supplies the input buffer
  633. InputBufferLength - the length of the input buffer
  634. OutputBuffer - the output buffer
  635. OutputBufferLength - the length of the output buffer
  636. IoControlCode - the IO control code
  637. IoStatus - Receives the final status of the operation
  638. DeviceObject - the associated device object
  639. Return Value:
  640. BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
  641. needs to take the long route.
  642. Notes:
  643. The following IO control requests are handled in the first path
  644. IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER
  645. InputBuffer - pointer to the other file object
  646. InputBufferLength - length in bytes of a pointer.
  647. OutputBuffer - not used
  648. OutputBufferLength - not used
  649. IoStatus --
  650. IoStatus.Status set to STATUS_SUCCESS if both the file objects are
  651. on the same server, otherwise set to STATUS_NOT_SAME_DEVICE
  652. This is a kernel mode interface only.
  653. --*/
  654. {
  655. BOOLEAN FastIoSucceeded;
  656. switch (IoControlCode) {
  657. case IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER :
  658. {
  659. FastIoSucceeded = TRUE;
  660. try {
  661. if (InputBufferLength == sizeof(HANDLE)) {
  662. PFCB pFcb1,pFcb2;
  663. HANDLE hFile;
  664. PFILE_OBJECT pFileObject2;
  665. NTSTATUS Status;
  666. pFcb1 = (PFCB)FileObject->FsContext;
  667. RtlCopyMemory(
  668. &hFile,
  669. InputBuffer,
  670. sizeof(HANDLE));
  671. Status = ObReferenceObjectByHandle(
  672. hFile,
  673. FILE_ANY_ACCESS,
  674. *IoFileObjectType,
  675. UserMode,
  676. &pFileObject2,
  677. NULL);
  678. if ((Status == STATUS_SUCCESS)) {
  679. if(pFileObject2->DeviceObject == DeviceObject) {
  680. pFcb2 = (PFCB)pFileObject2->FsContext;
  681. if ((pFcb2 != NULL) &&
  682. (NodeTypeIsFcb(pFcb2))) {
  683. if (pFcb1->pNetRoot->pSrvCall == pFcb2->pNetRoot->pSrvCall) {
  684. IoStatus->Status = STATUS_SUCCESS;
  685. } else {
  686. IoStatus->Status = STATUS_NOT_SAME_DEVICE;
  687. }
  688. } else {
  689. Status = STATUS_INVALID_PARAMETER;
  690. }
  691. } else {
  692. Status = STATUS_INVALID_PARAMETER;
  693. }
  694. ObDereferenceObject(pFileObject2);
  695. } else {
  696. IoStatus->Status = STATUS_INVALID_PARAMETER;
  697. }
  698. } else {
  699. IoStatus->Status = STATUS_INVALID_PARAMETER;
  700. }
  701. } except( EXCEPTION_EXECUTE_HANDLER ) {
  702. // The I/O request was not handled successfully, abort the I/O request with
  703. // the error status that we get back from the execption code
  704. IoStatus->Status = STATUS_INVALID_PARAMETER;
  705. FastIoSucceeded = TRUE;
  706. }
  707. }
  708. break;
  709. default:
  710. {
  711. FastIoSucceeded = FALSE;
  712. }
  713. }
  714. return FastIoSucceeded;
  715. }
  716. BOOLEAN
  717. RxFastQueryBasicInfo (
  718. IN PFILE_OBJECT FileObject,
  719. IN BOOLEAN Wait,
  720. IN OUT PFILE_BASIC_INFORMATION Buffer,
  721. OUT PIO_STATUS_BLOCK IoStatus,
  722. IN PDEVICE_OBJECT DeviceObject
  723. )
  724. /*++
  725. Routine Description:
  726. This routine is for the fast query call for basic file information.
  727. Arguments:
  728. FileObject - Supplies the file object used in this operation
  729. Wait - Indicates if we are allowed to wait for the information
  730. Buffer - Supplies the output buffer to receive the basic information
  731. IoStatus - Receives the final status of the operation
  732. Return Value:
  733. BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
  734. needs to take the long route.
  735. --*/
  736. {
  737. BOOLEAN Results = FALSE;
  738. PFCB Fcb = (PFCB)(FileObject->FsContext);
  739. PFOBX Fobx = (PFOBX)(FileObject->FsContext2);
  740. NODE_TYPE_CODE TypeOfOpen = NodeType(Fcb);
  741. BOOLEAN FcbAcquired = FALSE;
  742. PAGED_CODE();
  743. //
  744. // Determine the type of open for the input file object and only accept
  745. // the user file or directory open
  746. //
  747. if ((TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE) &&
  748. (TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)) {
  749. return Results;
  750. }
  751. FsRtlEnterFileSystem();
  752. //
  753. // Get access to the Fcb but only if it is not the paging file
  754. //
  755. if (!FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
  756. if (!ExAcquireResourceSharedLite( Fcb->Header.Resource, Wait )) {
  757. FsRtlExitFileSystem();
  758. return Results;
  759. }
  760. FcbAcquired = TRUE;
  761. }
  762. try {
  763. //
  764. // Set it to indicate that the query is a normal file.
  765. // Later we might overwrite the attribute.
  766. //
  767. Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
  768. //
  769. // If the fcb is not the root dcb then we will fill in the
  770. // buffer otherwise it is all setup for us.
  771. //
  772. if (NodeType(Fcb) != RDBSS_NTC_ROOT_DCB) {
  773. //
  774. // Extract the data and fill in the non zero fields of the output
  775. // buffer
  776. //
  777. Buffer->LastWriteTime = Fcb->LastWriteTime;
  778. Buffer->ChangeTime = Fcb->LastChangeTime;
  779. Buffer->CreationTime = Fcb->CreationTime;
  780. Buffer->LastAccessTime = Fcb->LastAccessTime;
  781. //
  782. // Zero out the field we don't support.
  783. //
  784. Buffer->ChangeTime = RxLargeZero;
  785. if (Fcb->Attributes != 0) {
  786. Buffer->FileAttributes = Fcb->Attributes;
  787. } else {
  788. Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
  789. }
  790. } else {
  791. Buffer->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
  792. }
  793. //
  794. // If the temporary flag is set, then set it in the buffer.
  795. //
  796. if (FlagOn( Fcb->FcbState, FCB_STATE_TEMPORARY )) {
  797. SetFlag( Buffer->FileAttributes, FILE_ATTRIBUTE_TEMPORARY );
  798. }
  799. IoStatus->Status = STATUS_SUCCESS;
  800. IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
  801. Results = TRUE;
  802. } finally {
  803. if (FcbAcquired) { ExReleaseResourceLite( Fcb->Header.Resource ); }
  804. FsRtlExitFileSystem();
  805. }
  806. //
  807. // And return to our caller
  808. //
  809. return Results;
  810. }
  811. BOOLEAN
  812. RxFastQueryStdInfo (
  813. IN PFILE_OBJECT FileObject,
  814. IN BOOLEAN Wait,
  815. IN OUT PFILE_STANDARD_INFORMATION Buffer,
  816. OUT PIO_STATUS_BLOCK IoStatus,
  817. IN PDEVICE_OBJECT DeviceObject
  818. )
  819. /*++
  820. Routine Description:
  821. This routine is for the fast query call for standard file information.
  822. Arguments:
  823. FileObject - Supplies the file object used in this operation
  824. Wait - Indicates if we are allowed to wait for the information
  825. Buffer - Supplies the output buffer to receive the basic information
  826. IoStatus - Receives the final status of the operation
  827. Return Value:
  828. BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
  829. needs to take the long route.
  830. --*/
  831. {
  832. BOOLEAN Results = FALSE;
  833. PFCB Fcb = (PFCB)(FileObject->FsContext);
  834. PFOBX Fobx = (PFOBX)(FileObject->FsContext2);
  835. NODE_TYPE_CODE TypeOfOpen = NodeType(Fcb);
  836. BOOLEAN FcbAcquired = FALSE;
  837. PAGED_CODE();
  838. //
  839. // Determine the type of open for the input file object and only accept
  840. // the user file or directory open
  841. //
  842. if ((TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE) &&
  843. (TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)) {
  844. return Results;
  845. }
  846. //
  847. // Get access to the Fcb but only if it is not the paging file
  848. //
  849. FsRtlEnterFileSystem();
  850. if (!FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
  851. if (!ExAcquireResourceSharedLite( Fcb->Header.Resource, Wait )) {
  852. FsRtlExitFileSystem();
  853. return Results;
  854. }
  855. FcbAcquired = TRUE;
  856. }
  857. try {
  858. Buffer->NumberOfLinks = 1;
  859. Buffer->DeletePending = BooleanFlagOn( Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE );
  860. //
  861. // Case on whether this is a file or a directory, and extract
  862. // the information and fill in the fcb/dcb specific parts
  863. // of the output buffer.
  864. //
  865. if (NodeType(Fcb) == RDBSS_NTC_FCB) {
  866. //
  867. // If we don't alread know the allocation size, we cannot look
  868. // it up in the fast path.
  869. //
  870. if (Fcb->Header.AllocationSize.LowPart == 0xffffffff) {
  871. try_return( Results );
  872. }
  873. Buffer->AllocationSize = Fcb->Header.AllocationSize;
  874. Buffer->EndOfFile = Fcb->Header.FileSize;
  875. Buffer->Directory = FALSE;
  876. } else {
  877. Buffer->AllocationSize = RxLargeZero;
  878. Buffer->EndOfFile = RxLargeZero;
  879. Buffer->Directory = TRUE;
  880. }
  881. IoStatus->Status = STATUS_SUCCESS;
  882. IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
  883. Results = TRUE;
  884. try_exit: NOTHING;
  885. } finally {
  886. if (FcbAcquired) { ExReleaseResourceLite( Fcb->Header.Resource ); }
  887. FsRtlExitFileSystem();
  888. }
  889. //
  890. // And return to our caller
  891. //
  892. return Results;
  893. }