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.

2819 lines
80 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. FileInfo.c
  5. Abstract:
  6. This module implements the File Information routines for Rx called by
  7. the dispatch driver.
  8. Author:
  9. Joe Linn [JoeLinn] 5-oct-94
  10. Revision History:
  11. Balan Sethu Raman 15-May-95 -- reworked to fit in pipe FSCTL's
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // The local debug trace level
  17. //
  18. #define Dbg (DEBUG_TRACE_FILEINFO)
  19. NTSTATUS
  20. RxQueryBasicInfo (
  21. IN PRX_CONTEXT RxContext,
  22. IN PIRP Irp,
  23. IN PFCB Fcb,
  24. IN OUT PFILE_BASIC_INFORMATION Buffer
  25. );
  26. NTSTATUS
  27. RxQueryStandardInfo (
  28. IN PRX_CONTEXT RxContext,
  29. IN PIRP Irp,
  30. IN PFCB Fcb,
  31. IN PFOBX Fobx,
  32. IN OUT PFILE_STANDARD_INFORMATION Buffer
  33. );
  34. NTSTATUS
  35. RxQueryInternalInfo (
  36. IN PRX_CONTEXT RxContext,
  37. IN PIRP Irp,
  38. IN PFCB Fcb,
  39. IN OUT PFILE_INTERNAL_INFORMATION Buffer
  40. );
  41. NTSTATUS
  42. RxQueryEaInfo (
  43. IN PRX_CONTEXT RxContext,
  44. IN PIRP Irp,
  45. IN PFCB Fcb,
  46. IN OUT PFILE_EA_INFORMATION Buffer
  47. );
  48. NTSTATUS
  49. RxQueryPositionInfo (
  50. IN PRX_CONTEXT RxContext,
  51. IN PIRP Irp,
  52. IN PFCB Fcb,
  53. IN OUT PFILE_POSITION_INFORMATION Buffer
  54. );
  55. NTSTATUS
  56. RxQueryNameInfo (
  57. IN PRX_CONTEXT RxContext,
  58. IN PIRP Irp,
  59. IN PFCB Fcb,
  60. IN PFOBX Fobx,
  61. IN OUT PFILE_NAME_INFORMATION Buffer
  62. );
  63. NTSTATUS
  64. RxQueryAlternateNameInfo (
  65. IN PRX_CONTEXT RxContext,
  66. IN PIRP Irp,
  67. IN PFCB Fcb,
  68. IN OUT PFILE_NAME_INFORMATION Buffer
  69. );
  70. NTSTATUS
  71. RxQueryCompressedInfo (
  72. IN PRX_CONTEXT RxContext,
  73. IN PIRP Irp,
  74. IN PFCB Fcb,
  75. IN OUT PFILE_COMPRESSION_INFORMATION Buffer
  76. );
  77. NTSTATUS
  78. RxQueryPipeInfo (
  79. IN PRX_CONTEXT RxContext,
  80. IN PIRP Irp,
  81. IN PFCB Fcb,
  82. IN PFOBX Fobx,
  83. IN OUT PVOID PipeInformation
  84. );
  85. NTSTATUS
  86. RxSetBasicInfo (
  87. IN PRX_CONTEXT RxContext,
  88. IN PIRP Irp,
  89. IN PFCB Fcb,
  90. IN PFOBX Fobx
  91. );
  92. NTSTATUS
  93. RxSetDispositionInfo (
  94. IN PRX_CONTEXT RxContext,
  95. IN PIRP Irp,
  96. IN PFCB Fcb
  97. );
  98. NTSTATUS
  99. RxSetRenameInfo (
  100. IN PRX_CONTEXT RxContext,
  101. IN PIRP Irp,
  102. IN PFCB Fcb,
  103. IN PFOBX Fobx
  104. );
  105. NTSTATUS
  106. RxSetPositionInfo (
  107. IN PRX_CONTEXT RxContext,
  108. IN PIRP Irp,
  109. IN PFCB Fcb,
  110. IN PFOBX Fobx
  111. );
  112. NTSTATUS
  113. RxSetAllocationInfo (
  114. IN PRX_CONTEXT RxContext,
  115. IN PIRP Irp,
  116. IN PFCB Fcb,
  117. IN PFOBX Fobx
  118. );
  119. NTSTATUS
  120. RxSetEndOfFileInfo (
  121. IN PRX_CONTEXT RxContext,
  122. IN PIRP Irp,
  123. IN PFCB Fcb,
  124. IN PFOBX Fobx
  125. );
  126. NTSTATUS
  127. RxSetPipeInfo(
  128. IN PRX_CONTEXT RxContext,
  129. IN PIRP Irp,
  130. IN PFCB Fcb,
  131. IN PFOBX Fobx
  132. );
  133. NTSTATUS
  134. RxSetSimpleInfo(
  135. IN PRX_CONTEXT RxContext,
  136. IN PIRP Irp,
  137. IN PFCB Fcb
  138. );
  139. #ifdef ALLOC_PRAGMA
  140. #pragma alloc_text(PAGE, RxCommonQueryInformation)
  141. #pragma alloc_text(PAGE, RxCommonSetInformation)
  142. #pragma alloc_text(PAGE, RxSetAllocationInfo)
  143. #pragma alloc_text(PAGE, RxQueryBasicInfo)
  144. #pragma alloc_text(PAGE, RxQueryEaInfo)
  145. #pragma alloc_text(PAGE, RxQueryInternalInfo)
  146. #pragma alloc_text(PAGE, RxQueryNameInfo)
  147. #pragma alloc_text(PAGE, RxQueryAlternateNameInfo)
  148. #pragma alloc_text(PAGE, RxQueryPositionInfo)
  149. #pragma alloc_text(PAGE, RxQueryStandardInfo)
  150. #pragma alloc_text(PAGE, RxQueryPipeInfo)
  151. #pragma alloc_text(PAGE, RxSetBasicInfo)
  152. #pragma alloc_text(PAGE, RxSetDispositionInfo)
  153. #pragma alloc_text(PAGE, RxSetEndOfFileInfo)
  154. #pragma alloc_text(PAGE, RxSetPositionInfo)
  155. #pragma alloc_text(PAGE, RxSetRenameInfo)
  156. #pragma alloc_text(PAGE, RxSetPipeInfo)
  157. #pragma alloc_text(PAGE, RxSetSimpleInfo)
  158. #pragma alloc_text(PAGE, RxConjureOriginalName)
  159. #pragma alloc_text(PAGE, RxQueryCompressedInfo)
  160. #endif
  161. NTSTATUS
  162. RxpSetInfoMiniRdr (
  163. PRX_CONTEXT RxContext,
  164. PIRP Irp,
  165. PFCB Fcb,
  166. FILE_INFORMATION_CLASS FileInformationClass
  167. )
  168. {
  169. NTSTATUS Status;
  170. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  171. RxContext->Info.FileInformationClass = FileInformationClass;
  172. RxContext->Info.Buffer = Irp->AssociatedIrp.SystemBuffer;
  173. RxContext->Info.Length = IrpSp->Parameters.SetFile.Length;
  174. MINIRDR_CALL( Status,
  175. RxContext,
  176. Fcb->MRxDispatch,
  177. MRxSetFileInfo,
  178. (RxContext) );
  179. return Status;
  180. }
  181. NTSTATUS
  182. RxpQueryInfoMiniRdr (
  183. PRX_CONTEXT RxContext,
  184. PFCB Fcb,
  185. FILE_INFORMATION_CLASS InformationClass,
  186. PVOID Buffer)
  187. {
  188. NTSTATUS Status;
  189. RxContext->Info.FileInformationClass = InformationClass;
  190. RxContext->Info.Buffer = Buffer;
  191. MINIRDR_CALL(
  192. Status,
  193. RxContext,
  194. Fcb->MRxDispatch,
  195. MRxQueryFileInfo,
  196. (RxContext));
  197. return Status;
  198. }
  199. NTSTATUS
  200. RxCommonQueryInformation (
  201. IN PRX_CONTEXT RxContext,
  202. IN PIRP Irp
  203. )
  204. /*++
  205. Routine Description:
  206. This is the common routine for querying file information called by both
  207. the fsd and fsp threads.
  208. Arguments:
  209. Irp - Supplies the Irp being processed
  210. Return Value:
  211. RXSTATUS - The return status for the operation
  212. --*/
  213. {
  214. NTSTATUS Status = STATUS_SUCCESS;
  215. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  216. PFILE_OBJECT FileObject = IrpSp->FileObject;
  217. PFCB Fcb;
  218. PFOBX Fobx;
  219. NODE_TYPE_CODE TypeOfOpen;
  220. PVOID Buffer = NULL;
  221. FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
  222. BOOLEAN FcbAcquired = FALSE;
  223. BOOLEAN PostIrp = FALSE;
  224. PFILE_ALL_INFORMATION AllInfo;
  225. PAGED_CODE();
  226. TypeOfOpen = RxDecodeFileObject( FileObject, &Fcb, &Fobx );
  227. RxDbgTrace( +1, Dbg, ("RxCommonQueryInformation...IrpC %08lx, Fobx %08lx, Fcb %08lx\n",
  228. RxContext, Fobx, Fcb) );
  229. RxDbgTrace( 0, Dbg, (" Buffer %08lx Length %08lx FileInfoClass %08lx\n",
  230. Irp->AssociatedIrp.SystemBuffer,
  231. IrpSp->Parameters.QueryFile.Length,
  232. IrpSp->Parameters.QueryFile.FileInformationClass
  233. ) );
  234. RxLog(( "QueryFileInfo %lx %lx %lx\n", RxContext, Fcb, Fobx ));
  235. RxWmiLog( LOG,
  236. RxCommonQueryInformation_1,
  237. LOGPTR( RxContext )
  238. LOGPTR( Fcb )
  239. LOGPTR( Fobx ) );
  240. RxLog(( " alsoqfi %lx %lx %ld\n",
  241. Irp->AssociatedIrp.SystemBuffer,
  242. IrpSp->Parameters.QueryFile.Length,
  243. IrpSp->Parameters.QueryFile.FileInformationClass ));
  244. RxWmiLog( LOG,
  245. RxCommonQueryInformation_2,
  246. LOGPTR( Irp->AssociatedIrp.SystemBuffer )
  247. LOGULONG( IrpSp->Parameters.QueryFile.Length )
  248. LOGULONG( IrpSp->Parameters.QueryFile.FileInformationClass ) );
  249. RxContext->Info.LengthRemaining = (LONG)IrpSp->Parameters.QueryFile.Length;
  250. try {
  251. //
  252. // Obtain the Request packet's(user's) buffer
  253. //
  254. Buffer = RxMapSystemBuffer( RxContext, Irp );
  255. if (Buffer == NULL) {
  256. Status = STATUS_INSUFFICIENT_RESOURCES;
  257. try_return( Status );
  258. }
  259. //
  260. // Zero the buffer
  261. //
  262. RtlZeroMemory( Buffer, RxContext->Info.LengthRemaining );
  263. //
  264. // Case on the type of open we're dealing with
  265. //
  266. switch (TypeOfOpen) {
  267. case RDBSS_NTC_STORAGE_TYPE_FILE:
  268. case RDBSS_NTC_STORAGE_TYPE_UNKNOWN:
  269. case RDBSS_NTC_STORAGE_TYPE_DIRECTORY:
  270. //
  271. // Acquire shared access to the fcb, except for a paging file
  272. // in order to avoid deadlocks with Mm.
  273. //
  274. if (!FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
  275. if (FileInformationClass != FileNameInformation) {
  276. //
  277. // If this is FileCompressedFileSize, we need the Fcb
  278. // exclusive.
  279. //
  280. if (FileInformationClass != FileCompressionInformation) {
  281. Status = RxAcquireSharedFcb( RxContext, Fcb );
  282. } else {
  283. Status = RxAcquireExclusiveFcb( RxContext, Fcb );
  284. }
  285. if (Status == STATUS_LOCK_NOT_GRANTED) {
  286. RxDbgTrace(0, Dbg, ("Cannot acquire Fcb\n", 0));
  287. try_return( PostIrp = TRUE );
  288. } else if (Status != STATUS_SUCCESS) {
  289. try_return( PostIrp = FALSE );
  290. }
  291. FcbAcquired = TRUE;
  292. }
  293. }
  294. //
  295. // Based on the information class, call down to the minirdr
  296. // we either complete or we post
  297. //
  298. switch (FileInformationClass) {
  299. case FileAllInformation:
  300. //
  301. // For the all information class we'll typecast a local
  302. // pointer to the output buffer and then call the
  303. // individual routines to fill in the buffer.
  304. //
  305. AllInfo = Buffer;
  306. //
  307. // can't rely on QueryXXInfo functions to calculate LengthRemaining due to
  308. // possible allignment issues
  309. //
  310. RxContext->Info.LengthRemaining = (LONG)IrpSp->Parameters.QueryFile.Length - FIELD_OFFSET( FILE_ALL_INFORMATION, BasicInformation );
  311. Status = RxQueryBasicInfo( RxContext, Irp, Fcb, &AllInfo->BasicInformation );
  312. if (Status != STATUS_SUCCESS) break;
  313. RxContext->Info.LengthRemaining = (LONG)IrpSp->Parameters.QueryFile.Length - FIELD_OFFSET( FILE_ALL_INFORMATION, StandardInformation );
  314. Status = RxQueryStandardInfo( RxContext, Irp, Fcb, Fobx, &AllInfo->StandardInformation );
  315. if (Status != STATUS_SUCCESS) break;
  316. RxContext->Info.LengthRemaining = (LONG)IrpSp->Parameters.QueryFile.Length - FIELD_OFFSET( FILE_ALL_INFORMATION, InternalInformation );
  317. Status = RxQueryInternalInfo( RxContext, Irp, Fcb, &AllInfo->InternalInformation );
  318. if (Status != STATUS_SUCCESS) break;
  319. RxContext->Info.LengthRemaining = (LONG)IrpSp->Parameters.QueryFile.Length - FIELD_OFFSET( FILE_ALL_INFORMATION, EaInformation );
  320. Status = RxQueryEaInfo( RxContext, Irp, Fcb, &AllInfo->EaInformation );
  321. if (Status != STATUS_SUCCESS) break;
  322. RxContext->Info.LengthRemaining = (LONG)IrpSp->Parameters.QueryFile.Length - FIELD_OFFSET( FILE_ALL_INFORMATION, PositionInformation );
  323. Status = RxQueryPositionInfo( RxContext, Irp, Fcb, &AllInfo->PositionInformation );
  324. if (Status != STATUS_SUCCESS) break;
  325. RxContext->Info.LengthRemaining = (LONG)IrpSp->Parameters.QueryFile.Length - FIELD_OFFSET( FILE_ALL_INFORMATION, NameInformation );
  326. //
  327. // QueryNameInfo could return buffer-overflow!!!
  328. //
  329. Status = RxQueryNameInfo( RxContext, Irp, Fcb, Fobx, &AllInfo->NameInformation );
  330. break;
  331. case FileBasicInformation:
  332. Status = RxQueryBasicInfo( RxContext, Irp, Fcb, Buffer );
  333. break;
  334. case FileStandardInformation:
  335. Status = RxQueryStandardInfo( RxContext, Irp, Fcb, Fobx, Buffer );
  336. break;
  337. case FileInternalInformation:
  338. Status = RxQueryInternalInfo( RxContext, Irp, Fcb, Buffer );
  339. break;
  340. case FileEaInformation:
  341. Status = RxQueryEaInfo( RxContext, Irp, Fcb, Buffer );
  342. break;
  343. case FilePositionInformation:
  344. Status = RxQueryPositionInfo( RxContext, Irp, Fcb, Buffer );
  345. break;
  346. case FileNameInformation:
  347. Status = RxQueryNameInfo( RxContext, Irp, Fcb, Fobx, Buffer );
  348. break;
  349. case FileAlternateNameInformation:
  350. Status = RxQueryAlternateNameInfo( RxContext, Irp, Fcb, Buffer );
  351. break;
  352. case FileCompressionInformation:
  353. Status = RxQueryCompressedInfo( RxContext, Irp, Fcb, Buffer );
  354. break;
  355. case FilePipeInformation:
  356. case FilePipeLocalInformation:
  357. case FilePipeRemoteInformation:
  358. Status = RxQueryPipeInfo( RxContext, Irp, Fcb, Fobx, Buffer );
  359. break;
  360. default:
  361. //
  362. // anything that we don't understand, we just remote
  363. //
  364. RxContext->StoredStatus = RxpQueryInfoMiniRdr( RxContext,
  365. Fcb,
  366. FileInformationClass,
  367. Buffer );
  368. Status = RxContext->StoredStatus;
  369. break;
  370. }
  371. //
  372. // If we overflowed the buffer, set the length to 0 and change the
  373. // status to RxStatus(BUFFER_OVERFLOW).
  374. //
  375. if (RxContext->Info.LengthRemaining < 0) {
  376. Status = STATUS_BUFFER_OVERFLOW;
  377. RxContext->Info.LengthRemaining = IrpSp->Parameters.QueryFile.Length;
  378. }
  379. //
  380. // Set the information field to the number of bytes actually filled in
  381. // and then complete the request LARRY DOES THIS UNDER "!NT_ERROR"
  382. //
  383. Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - RxContext->Info.LengthRemaining;
  384. break;
  385. case RDBSS_NTC_MAILSLOT:
  386. Status = STATUS_NOT_IMPLEMENTED;
  387. break;
  388. default:
  389. RxDbgTrace( 0, Dbg, ("RxCommonQueryInformation: Illegal Type of Open = %08lx\n", TypeOfOpen) );
  390. Status = STATUS_INVALID_PARAMETER;
  391. break;
  392. }
  393. try_exit:
  394. if ((Status == STATUS_SUCCESS) &&
  395. (PostIrp || RxContext->PostRequest)) {
  396. Status = RxFsdPostRequest( RxContext );
  397. }
  398. } finally {
  399. DebugUnwind( RxCommonQueryInformation );
  400. if (FcbAcquired) {
  401. RxReleaseFcb( RxContext, Fcb );
  402. }
  403. RxDbgTrace( -1, Dbg, ("RxCommonQueryInformation -> %08lx\n", Status) );
  404. }
  405. return Status;
  406. }
  407. NTSTATUS
  408. RxCommonSetInformation (
  409. IN PRX_CONTEXT RxContext,
  410. IN PIRP Irp
  411. )
  412. /*++
  413. Routine Description:
  414. This is the common routine for setting file information called by both
  415. the fsd and fsp threads.
  416. Arguments:
  417. Irp - Supplies the Irp being processed
  418. Return Value:
  419. RXSTATUS - The return status for the operation
  420. --*/
  421. {
  422. NTSTATUS Status = STATUS_SUCCESS;
  423. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  424. NODE_TYPE_CODE TypeOfOpen;
  425. PFCB Fcb;
  426. PFOBX Fobx;
  427. PNET_ROOT NetRoot;
  428. FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
  429. PFCB TempFcb;
  430. PFILE_DISPOSITION_INFORMATION Buffer;
  431. BOOLEAN Wait = BooleanFlagOn( RxContext->Flags, RX_CONTEXT_FLAG_WAIT );
  432. BOOLEAN FcbAcquired = FALSE;
  433. BOOLEAN NetRootTableLockAcquired = FALSE;
  434. PAGED_CODE();
  435. TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx );
  436. NetRoot = Fcb->NetRoot;
  437. RxDbgTrace( +1, Dbg, ("RxCommonSetInformation...IrpC %08lx, Fobx %08lx, Fcb %08lx\n",
  438. RxContext, Fobx, Fcb) );
  439. RxDbgTrace( 0, Dbg, (" Buffer %08lx Length %08lx FileInfoClass %08lx Replace %08lx\n",
  440. Irp->AssociatedIrp.SystemBuffer,
  441. IrpSp->Parameters.QueryFile.Length,
  442. IrpSp->Parameters.QueryFile.FileInformationClass,
  443. IrpSp->Parameters.SetFile.ReplaceIfExists
  444. ) );
  445. RxLog(( "SetFileInfo %lx %lx %lx\n", RxContext, Fcb, Fobx ));
  446. RxWmiLog( LOG,
  447. RxCommonSetInformation_1,
  448. LOGPTR( RxContext )
  449. LOGPTR( Fcb )
  450. LOGPTR( Fobx ) );
  451. RxLog((" alsosfi %lx %lx %ld %lx\n",
  452. Irp->AssociatedIrp.SystemBuffer,
  453. IrpSp->Parameters.QueryFile.Length,
  454. IrpSp->Parameters.QueryFile.FileInformationClass,
  455. IrpSp->Parameters.SetFile.ReplaceIfExists ));
  456. RxWmiLog( LOG,
  457. RxCommonSetInformation_2,
  458. LOGPTR(Irp->AssociatedIrp.SystemBuffer)
  459. LOGULONG( IrpSp->Parameters.QueryFile.Length )
  460. LOGULONG( IrpSp->Parameters.QueryFile.FileInformationClass )
  461. LOGUCHAR( IrpSp->Parameters.SetFile.ReplaceIfExists ) );
  462. FcbAcquired = FALSE;
  463. Status = STATUS_SUCCESS;
  464. try {
  465. //
  466. // Case on the type of open we're dealing with
  467. //
  468. switch (TypeOfOpen) {
  469. case RDBSS_NTC_STORAGE_TYPE_FILE:
  470. case RDBSS_NTC_STORAGE_TYPE_DIRECTORY:
  471. case RDBSS_NTC_STORAGE_TYPE_UNKNOWN:
  472. case RDBSS_NTC_SPOOLFILE:
  473. break;
  474. case RDBSS_NTC_MAILSLOT:
  475. try_return( Status = STATUS_NOT_IMPLEMENTED );
  476. break;
  477. default:
  478. DbgPrint ("SetFile, Illegal TypeOfOpen = %08lx\n", TypeOfOpen);
  479. try_return( Status = STATUS_INVALID_PARAMETER );
  480. }
  481. //
  482. // If the FileInformationClass is FileEndOfFileInformation and the
  483. // AdvanceOnly field in IrpSp->Parameters is TRUE then we don't need
  484. // to proceed any further. Only local file systems care about this
  485. // call. This is the AdvanceOnly callback � all FAT does with this is
  486. // use it as a hint of a good time to punch out the directory entry.
  487. // NTFS is much the same way. This is pure PagingIo (dovetailing with
  488. // lazy writer sync) to metadata streams and can�t block behind other
  489. // user file cached IO.
  490. //
  491. if ((FileInformationClass == FileEndOfFileInformation) &&
  492. (IrpSp->Parameters.SetFile.AdvanceOnly)) {
  493. RxDbgTrace( -1, Dbg, ("RxCommonSetInfo (no advance) -> %08lx\n", RxContext) );
  494. RxLog(( "RxCommonSetInfo SetEofAdvance-NOT! %lx\n", RxContext ));
  495. RxWmiLog( LOG,
  496. RxSetEndOfFileInfo_2,
  497. LOGPTR( RxContext ) );
  498. try_return( Status = STATUS_SUCCESS );
  499. }
  500. //
  501. // In the following two cases, we cannot have creates occuring
  502. // while we are here, so acquire the exclusive lock on netroot prefix table.
  503. //
  504. if ((FileInformationClass == FileDispositionInformation) ||
  505. (FileInformationClass == FileRenameInformation)) {
  506. //
  507. // For directory renames, all files under that directory need to be closed.
  508. // So, we purge all files on the netroot (share) in case this is a directory.
  509. //
  510. if ( NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_DIRECTORY ) {
  511. TempFcb = NULL;
  512. } else {
  513. TempFcb = Fcb;
  514. }
  515. RxPurgeRelatedFobxs( NetRoot,
  516. RxContext,
  517. ATTEMPT_FINALIZE_ON_PURGE,
  518. TempFcb );
  519. RxScavengeFobxsForNetRoot( NetRoot, TempFcb );
  520. if (!RxAcquireFcbTableLockExclusive( &NetRoot->FcbTable, Wait )) {
  521. RxDbgTrace( 0, Dbg, ("Cannot acquire NetRootTableLock\n", 0) );
  522. Status = STATUS_PENDING;
  523. RxContext->PostRequest = TRUE;
  524. try_return( Status );
  525. }
  526. NetRootTableLockAcquired = TRUE;
  527. }
  528. //
  529. // Acquire exclusive access to the Fcb, We use exclusive
  530. // because it is probable that the subroutines
  531. // that we call will need to monkey with file allocation,
  532. // create/delete extra fcbs. So we're willing to pay the
  533. // cost of exclusive Fcb access.
  534. //
  535. // Note that we do not acquire the resource for paging file
  536. // operations in order to avoid deadlock with Mm.
  537. //
  538. if (!FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
  539. Status = RxAcquireExclusiveFcb( RxContext, Fcb );
  540. if (Status == STATUS_LOCK_NOT_GRANTED) {
  541. RxDbgTrace( 0, Dbg, ("Cannot acquire Fcb\n", 0) );
  542. Status = STATUS_SUCCESS;
  543. RxContext->PostRequest = TRUE;
  544. try_return( Status );
  545. } else if (Status != STATUS_SUCCESS) {
  546. try_return( Status );
  547. }
  548. FcbAcquired = TRUE;
  549. }
  550. Status = STATUS_SUCCESS;
  551. //
  552. // Based on the information class we'll do different
  553. // actions. Each of the procedures that we're calling will either
  554. // complete the request of send the request off to the fsp
  555. // to do the work.
  556. //
  557. switch (FileInformationClass) {
  558. case FileBasicInformation:
  559. Status = RxSetBasicInfo( RxContext, Irp, Fcb, Fobx );
  560. break;
  561. case FileDispositionInformation:
  562. Buffer = Irp->AssociatedIrp.SystemBuffer;
  563. //
  564. // Check if the user wants to delete the file; if so,
  565. // check for situations where we cannot delete.
  566. //
  567. if (Buffer->DeleteFile) {
  568. //
  569. // Make sure there is no process mapping this file as an image.
  570. //
  571. if (!MmFlushImageSection( &Fcb->NonPaged->SectionObjectPointers, MmFlushForDelete )) {
  572. RxDbgTrace( -1, Dbg, ("Cannot delete user mapped image\n", 0) );
  573. Status = STATUS_CANNOT_DELETE;
  574. }
  575. if (Status == STATUS_SUCCESS) {
  576. //
  577. // In the case of disposition information this name is being
  578. // deleted. In such cases the collapsing of new create requests
  579. // onto this FCB should be prohibited. This can be accomplished
  580. // by removing the FCB name from the FCB table. Subsequently the
  581. // FCB table lock can be dropped.
  582. //
  583. ASSERT( FcbAcquired && NetRootTableLockAcquired );
  584. RxRemoveNameNetFcb( Fcb );
  585. RxReleaseFcbTableLock( &NetRoot->FcbTable );
  586. NetRootTableLockAcquired = FALSE;
  587. }
  588. }
  589. if (Status == STATUS_SUCCESS) {
  590. Status = RxSetDispositionInfo( RxContext, Irp, Fcb );
  591. }
  592. break;
  593. case FileMoveClusterInformation:
  594. case FileLinkInformation:
  595. case FileRenameInformation:
  596. //
  597. // We proceed with this operation only if we can wait
  598. //
  599. if (!Wait) {
  600. Status = RxFsdPostRequest( RxContext );
  601. } else {
  602. ClearFlag( Fcb->FcbState, FCB_STATE_COLLAPSING_ENABLED );
  603. Status = RxSetRenameInfo( RxContext, Irp, Fcb, Fobx );
  604. if ((Status == STATUS_SUCCESS) &&
  605. (FileInformationClass == FileRenameInformation)) {
  606. ASSERT( FcbAcquired && NetRootTableLockAcquired );
  607. RxRemoveNameNetFcb( Fcb );
  608. }
  609. }
  610. break;
  611. case FilePositionInformation:
  612. Status = RxSetPositionInfo( RxContext, Irp, Fcb, Fobx );
  613. break;
  614. case FileAllocationInformation:
  615. Status = RxSetAllocationInfo( RxContext, Irp, Fcb, Fobx );
  616. break;
  617. case FileEndOfFileInformation:
  618. Status = RxSetEndOfFileInfo( RxContext, Irp, Fcb, Fobx );
  619. break;
  620. case FilePipeInformation:
  621. case FilePipeLocalInformation:
  622. case FilePipeRemoteInformation:
  623. Status = RxSetPipeInfo( RxContext, Irp, Fcb, Fobx );
  624. break;
  625. case FileValidDataLengthInformation:
  626. if(!MmCanFileBeTruncated( &Fcb->NonPaged->SectionObjectPointers, NULL )) {
  627. Status = STATUS_USER_MAPPED_FILE;
  628. break;
  629. }
  630. Status = RxSetSimpleInfo( RxContext, Irp, Fcb );
  631. break;
  632. case FileShortNameInformation:
  633. Status = RxSetSimpleInfo( RxContext, Irp, Fcb );
  634. break;
  635. default:
  636. Status = STATUS_INVALID_PARAMETER;
  637. break;
  638. }
  639. try_exit:
  640. if ((Status == STATUS_SUCCESS) &&
  641. RxContext->PostRequest) {
  642. Status = RxFsdPostRequest( RxContext );
  643. }
  644. } finally {
  645. DebugUnwind( RxCommonSetInformation );
  646. if (FcbAcquired) {
  647. RxReleaseFcb( RxContext, Fcb );
  648. }
  649. if (NetRootTableLockAcquired) {
  650. RxReleaseFcbTableLock( &NetRoot->FcbTable );
  651. }
  652. RxDbgTrace(-1, Dbg, ("RxCommonSetInformation -> %08lx\n", Status));
  653. }
  654. return Status;
  655. }
  656. NTSTATUS
  657. RxSetBasicInfo (
  658. IN PRX_CONTEXT RxContext,
  659. IN PIRP Irp,
  660. IN PFCB Fcb,
  661. IN PFOBX Fobx
  662. )
  663. /*++
  664. Routine Description:
  665. (Interal Support Routine)
  666. This routine performs the set basic information for rx. It either
  667. completes the request or enqueues it off to the fsp.
  668. Arguments:
  669. RxContext - Supplies the irp being processed
  670. Return Value:
  671. RXSTATUS - The result of this operation if it completes without
  672. an exception.
  673. --*/
  674. {
  675. NTSTATUS Status;
  676. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  677. PFILE_OBJECT FileObject = IrpSp->FileObject;
  678. PFILE_BASIC_INFORMATION Buffer;
  679. BOOLEAN ModifyCreation = FALSE;
  680. BOOLEAN ModifyLastAccess = FALSE;
  681. BOOLEAN ModifyLastWrite = FALSE;
  682. BOOLEAN ModifyLastChange = FALSE;
  683. PAGED_CODE();
  684. RxDbgTrace( +1, Dbg, ("RxSetBasicInfo...\n", 0) );
  685. RxLog(( "RxSetBasicInfo\n" ));
  686. RxWmiLog( LOG,
  687. RxSetBasicInfo,
  688. LOGPTR( RxContext ) );
  689. //
  690. // call down. if we're successful, then fixup all the fcb data.
  691. //
  692. Status = RxpSetInfoMiniRdr( RxContext, Irp, Fcb, FileBasicInformation );
  693. if (!NT_SUCCESS(Status)) {
  694. RxDbgTrace( -1, Dbg, ("RxSetBasicInfo -> %08lx\n", Status) );
  695. return Status;
  696. }
  697. //
  698. // now we have to update the info in the fcb, both the absolute info AND whether changes were made
  699. //
  700. Buffer = Irp->AssociatedIrp.SystemBuffer;
  701. try {
  702. //
  703. // Check if the user specified a non-zero creation time
  704. //
  705. if (Buffer->CreationTime.QuadPart != 0 ) {
  706. ModifyCreation = TRUE;
  707. }
  708. //
  709. // Check if the user specified a non-zero last access time
  710. //
  711. if (Buffer->LastAccessTime.QuadPart != 0 ) {
  712. ModifyLastAccess = TRUE;
  713. }
  714. //
  715. // Check if the user specified a non-zero last write time
  716. //
  717. if (Buffer->LastWriteTime.QuadPart != 0 ) {
  718. ModifyLastWrite = TRUE;
  719. }
  720. if (Buffer->ChangeTime.QuadPart != 0 ) {
  721. ModifyLastChange = TRUE;
  722. }
  723. //
  724. // Check if the user specified a non zero file attributes byte
  725. //
  726. if (Buffer->FileAttributes != 0) {
  727. USHORT Attributes;
  728. //
  729. // Remove the normal attribute flag
  730. //
  731. Attributes = (USHORT)FlagOn( Buffer->FileAttributes, ~FILE_ATTRIBUTE_NORMAL );
  732. //
  733. // Make sure that for a file the directory bit is not set
  734. // and for a directory that the bit is set
  735. //
  736. if (NodeType( Fcb ) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY) {
  737. ClearFlag( Attributes, FILE_ATTRIBUTE_DIRECTORY );
  738. } else {
  739. SetFlag( Attributes, FILE_ATTRIBUTE_DIRECTORY );
  740. }
  741. //
  742. // Mark the FcbState temporary flag correctly.
  743. //
  744. if (FlagOn( Buffer->FileAttributes, FILE_ATTRIBUTE_TEMPORARY )) {
  745. SetFlag( Fcb->FcbState, FCB_STATE_TEMPORARY );
  746. SetFlag( FileObject->Flags, FO_TEMPORARY_FILE );
  747. } else {
  748. ClearFlag( Fcb->FcbState, FCB_STATE_TEMPORARY );
  749. ClearFlag( FileObject->Flags, FO_TEMPORARY_FILE );
  750. }
  751. //
  752. // Set the new attributes byte, and mark the bcb dirty
  753. //
  754. Fcb->Attributes = Attributes;
  755. }
  756. if (ModifyCreation) {
  757. //
  758. // Set the new last write time in the dirent, and mark
  759. // the bcb dirty
  760. //
  761. Fcb->CreationTime = Buffer->CreationTime;
  762. //
  763. // Now because the user just set the creation time we
  764. // better not set the creation time on close
  765. //
  766. SetFlag( Fobx->Flags, FOBX_FLAG_USER_SET_CREATION );
  767. }
  768. if (ModifyLastAccess) {
  769. //
  770. // Set the new last write time in the dirent, and mark
  771. // the bcb dirty
  772. //
  773. Fcb->LastAccessTime = Buffer->LastAccessTime;
  774. //
  775. // Now because the user just set the last access time we
  776. // better not set the last access time on close
  777. //
  778. SetFlag( Fobx->Flags, FOBX_FLAG_USER_SET_LAST_ACCESS );
  779. }
  780. if (ModifyLastWrite) {
  781. //
  782. // Set the new last write time in the dirent, and mark
  783. // the bcb dirty
  784. //
  785. Fcb->LastWriteTime = Buffer->LastWriteTime;
  786. //
  787. // Now because the user just set the last write time we
  788. // better not set the last write time on close
  789. //
  790. SetFlag( Fobx->Flags, FOBX_FLAG_USER_SET_LAST_WRITE );
  791. }
  792. if (ModifyLastChange) {
  793. //
  794. // Set the new last write time in the dirent, and mark
  795. // the bcb dirty
  796. //
  797. Fcb->LastChangeTime = Buffer->ChangeTime;
  798. //
  799. // Now because the user just set the last write time we
  800. // better not set the last write time on close
  801. //
  802. SetFlag( Fobx->Flags, FOBX_FLAG_USER_SET_LAST_CHANGE );
  803. }
  804. } finally {
  805. DebugUnwind( RxSetBasicInfo );
  806. RxDbgTrace( -1, Dbg, ("RxSetBasicInfo -> %08lx\n", Status) );
  807. }
  808. return Status;
  809. }
  810. NTSTATUS
  811. RxSetDispositionInfo (
  812. IN PRX_CONTEXT RxContext,
  813. IN PIRP Irp,
  814. IN PFCB Fcb
  815. )
  816. /*++
  817. Routine Description:
  818. (Internal Support Routine)
  819. This routine performs the set disposition information for rx. It either
  820. completes the request or enqueues it off to the fsp.
  821. Arguments:
  822. RxContext - Supplies the irp being processed
  823. Return Value:
  824. RXSTATUS - The result of this operation if it completes without
  825. an exception.
  826. --*/
  827. {
  828. NTSTATUS Status;
  829. PFILE_OBJECT FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
  830. PFILE_DISPOSITION_INFORMATION Buffer;
  831. PAGED_CODE();
  832. RxDbgTrace( +1, Dbg, ("RxSetDispositionInfo...\n", 0) );
  833. RxLog(( "RxSetDispositionInfo\n" ));
  834. RxWmiLog( LOG,
  835. RxSetDispositionInfo,
  836. LOGPTR( RxContext ) );
  837. Buffer = Irp->AssociatedIrp.SystemBuffer;
  838. //
  839. // call down and check for success
  840. //
  841. Status = RxpSetInfoMiniRdr( RxContext, Irp, Fcb, FileDispositionInformation );
  842. if (!NT_SUCCESS( Status )) {
  843. RxDbgTrace( -1, Dbg, ("RxSetDispositionInfo -> %08lx\n", Status) );
  844. return Status;
  845. }
  846. //
  847. // if successful, record the correct state in the fcb
  848. //
  849. if (Buffer->DeleteFile) {
  850. SetFlag( Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE );
  851. FileObject->DeletePending = TRUE;
  852. } else {
  853. //
  854. // The user doesn't want to delete the file so clear
  855. // the delete on close bit
  856. //
  857. RxDbgTrace(0, Dbg, ("User want to not delete file\n", 0));
  858. ClearFlag(Fcb->FcbState, ~FCB_STATE_DELETE_ON_CLOSE );
  859. FileObject->DeletePending = FALSE;
  860. }
  861. RxDbgTrace(-1, Dbg, ("RxSetDispositionInfo -> RxStatus(SUCCESS)\n", 0));
  862. return STATUS_SUCCESS;
  863. }
  864. NTSTATUS
  865. RxSetRenameInfo (
  866. IN PRX_CONTEXT RxContext,
  867. IN PIRP Irp,
  868. IN PFCB Fcb,
  869. IN PFOBX Fobx
  870. )
  871. /*++
  872. Routine Description:
  873. (Internal Support Routine)
  874. This routine performs the set name information for rx. It either
  875. completes the request or enqueues it off to the fsp.
  876. Arguments:
  877. Irp - Supplies the irp being processed
  878. Return Value:
  879. RXSTATUS - The result of this operation if it completes without
  880. an exception.
  881. --*/
  882. {
  883. NTSTATUS Status;
  884. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  885. PAGED_CODE();
  886. RxDbgTrace( +1, Dbg, ("RxSetRenameInfo ......FileObj = %08lx\n",
  887. IrpSp->Parameters.SetFile.FileObject) );
  888. RxLog(("RxSetRenameInfo %lx %lx\n",
  889. IrpSp->Parameters.SetFile.FileObject,
  890. IrpSp->Parameters.SetFile.ReplaceIfExists ));
  891. RxWmiLog(LOG,
  892. RxSetRenameInfo,
  893. LOGPTR(IrpSp->Parameters.SetFile.FileObject)
  894. LOGUCHAR(IrpSp->Parameters.SetFile.ReplaceIfExists));
  895. RxContext->Info.ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
  896. if (IrpSp->Parameters.SetFile.FileObject){
  897. // here we have to translate the name. the fcb of the fileobject has the
  898. // translation already....all we have to do is to allocate a buffer, copy
  899. // and calldown
  900. PFILE_OBJECT RenameFileObject = IrpSp->Parameters.SetFile.FileObject;
  901. PFCB RenameFcb = (PFCB)(RenameFileObject->FsContext);
  902. PFILE_RENAME_INFORMATION RenameInformation;
  903. ULONG allocate_size;
  904. ASSERT (NodeType(RenameFcb)==RDBSS_NTC_OPENTARGETDIR_FCB);
  905. RxDbgTrace(0, Dbg, ("-->RenameTarget is %wZ,over=%08lx\n",
  906. &(RenameFcb->FcbTableEntry.Path),
  907. Fcb->NetRoot->DiskParameters.RenameInfoOverallocationSize));
  908. if (RenameFcb->NetRoot != Fcb->NetRoot) {
  909. RxDbgTrace(-1, Dbg, ("RxSetRenameInfo -> %s\n", "NOT SAME DEVICE!!!!!!"));
  910. return(STATUS_NOT_SAME_DEVICE);
  911. }
  912. allocate_size = FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName[0])
  913. + RenameFcb->FcbTableEntry.Path.Length
  914. + Fcb->NetRoot->DiskParameters.RenameInfoOverallocationSize;
  915. RxDbgTrace(0, Dbg, ("-->AllocSize is %08lx\n", allocate_size));
  916. RenameInformation = RxAllocatePool( PagedPool, allocate_size );
  917. if (RenameInformation != NULL) {
  918. try {
  919. *RenameInformation = *((PFILE_RENAME_INFORMATION)(Irp->AssociatedIrp.SystemBuffer));
  920. RenameInformation->FileNameLength = RenameFcb->FcbTableEntry.Path.Length;
  921. RtlMoveMemory(
  922. &RenameInformation->FileName[0],
  923. RenameFcb->FcbTableEntry.Path.Buffer,
  924. RenameFcb->FcbTableEntry.Path.Length);
  925. RxContext->Info.FileInformationClass = (IrpSp->Parameters.SetFile.FileInformationClass);
  926. RxContext->Info.Buffer = RenameInformation;
  927. RxContext->Info.Length = allocate_size;
  928. MINIRDR_CALL(Status,RxContext,Fcb->MRxDispatch,MRxSetFileInfo,(RxContext));
  929. //we don't change the name in the fcb? a la rdr1
  930. } finally {
  931. RxFreePool(RenameInformation);
  932. }
  933. } else {
  934. Status = STATUS_INSUFFICIENT_RESOURCES;
  935. }
  936. } else {
  937. Status = RxpSetInfoMiniRdr( RxContext,
  938. Irp,
  939. Fcb,
  940. IrpSp->Parameters.SetFile.FileInformationClass );
  941. }
  942. RxDbgTrace(-1, Dbg, ("RxSetRenameInfo -> %08lx\n", Status));
  943. return Status;
  944. }
  945. NTSTATUS
  946. RxSetPositionInfo (
  947. IN PRX_CONTEXT RxContext,
  948. IN PIRP Irp,
  949. IN PFCB Fcb,
  950. IN PFOBX Fobx
  951. )
  952. /*++
  953. Routine Description:
  954. (Internal Support Routine)
  955. This routine performs the set position information for rx. It either
  956. completes the request or enqueues it off to the fsp.
  957. Arguments:
  958. RxContext - Supplies the irp being processed
  959. Return Value:
  960. RXSTATUS - The result of this operation if it completes without
  961. an exception.
  962. --*/
  963. {
  964. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  965. PFILE_OBJECT FileObject = IrpSp->FileObject;
  966. PFILE_POSITION_INFORMATION Buffer;
  967. PAGED_CODE();
  968. RxDbgTrace(+1, Dbg, ("RxSetPositionInfo...\n", 0));
  969. RxLog(("RxSetPositionInfo\n"));
  970. RxWmiLog(LOG,
  971. RxSetPositionInfo,
  972. LOGPTR(RxContext));
  973. //
  974. // This does NOT call down to the minirdrs .........
  975. //
  976. Buffer = Irp->AssociatedIrp.SystemBuffer;
  977. //
  978. // Check if the file does not use intermediate buffering. If it
  979. // does not use intermediate buffering then the new position we're
  980. // supplied must be aligned properly for the device
  981. //
  982. if (FlagOn( FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING )) {
  983. PDEVICE_OBJECT DeviceObject;
  984. DeviceObject = IrpSp->DeviceObject;
  985. if ((Buffer->CurrentByteOffset.LowPart & DeviceObject->AlignmentRequirement) != 0) {
  986. RxDbgTrace(0, Dbg, ("Cannot set position due to aligment conflict\n", 0));
  987. RxDbgTrace(-1, Dbg, ("RxSetPositionInfo -> %08lx\n", STATUS_INVALID_PARAMETER));
  988. return STATUS_INVALID_PARAMETER;
  989. }
  990. }
  991. //
  992. // The input parameter is fine so set the current byte offset and
  993. // complete the request
  994. //
  995. RxDbgTrace(0, Dbg, ("Set the new position to %08lx\n", Buffer->CurrentByteOffset));
  996. FileObject->CurrentByteOffset = Buffer->CurrentByteOffset;
  997. RxDbgTrace(-1, Dbg, ("RxSetPositionInfo -> %08lx\n", STATUS_SUCCESS));
  998. return STATUS_SUCCESS;
  999. }
  1000. NTSTATUS
  1001. RxSetAllocationInfo (
  1002. IN PRX_CONTEXT RxContext,
  1003. IN PIRP Irp,
  1004. IN PFCB Fcb,
  1005. IN PFOBX Fobx
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. (Internal Support Routine)
  1010. This routine performs the set Allocation information for rx. It either
  1011. completes the request or enqueues it off to the fsp.
  1012. Arguments:
  1013. RxContext - Supplies the irp being processed
  1014. Return Value:
  1015. RXSTATUS - The result of this operation if it completes without
  1016. an exception.
  1017. --*/
  1018. {
  1019. NTSTATUS Status = STATUS_SUCCESS;
  1020. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1021. PFILE_OBJECT FileObject = IrpSp->FileObject;
  1022. PFILE_ALLOCATION_INFORMATION Buffer;
  1023. LONGLONG NewAllocationSize;
  1024. BOOLEAN CacheMapInitialized = FALSE;
  1025. LARGE_INTEGER OriginalFileSize;
  1026. LARGE_INTEGER OriginalAllocationSize;
  1027. PAGED_CODE();
  1028. Buffer = Irp->AssociatedIrp.SystemBuffer;
  1029. NewAllocationSize = Buffer->AllocationSize.QuadPart;
  1030. RxDbgTrace( +1, Dbg, ("RxSetAllocationInfo.. to %08lx\n", NewAllocationSize) );
  1031. RxLog(( "SetAlloc %lx %lx %lx\n", Fcb->Header.FileSize.LowPart,
  1032. (ULONG)NewAllocationSize, Fcb->Header.AllocationSize.LowPart ));
  1033. RxWmiLog( LOG,
  1034. RxSetAllocationInfo_1,
  1035. LOGULONG( Fcb->Header.FileSize.LowPart )
  1036. LOGULONG( (ULONG)NewAllocationSize )
  1037. LOGULONG( Fcb->Header.AllocationSize.LowPart ) );
  1038. //
  1039. // This is kinda gross, but if the file is not cached, but there is
  1040. // a data section, we have to cache the file to avoid a bunch of
  1041. // extra work.
  1042. //
  1043. if ((FileObject->SectionObjectPointer->DataSectionObject != NULL) &&
  1044. (FileObject->SectionObjectPointer->SharedCacheMap == NULL) &&
  1045. (Irp->RequestorMode != KernelMode)) {
  1046. if (FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE )) {
  1047. return STATUS_FILE_CLOSED;
  1048. }
  1049. RxAdjustAllocationSizeforCC( Fcb );
  1050. //
  1051. // Now initialize the cache map.
  1052. //
  1053. CcInitializeCacheMap( FileObject,
  1054. (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
  1055. FALSE,
  1056. &RxData.CacheManagerCallbacks,
  1057. Fcb );
  1058. CacheMapInitialized = TRUE;
  1059. }
  1060. //
  1061. // Now mark that the time on the dirent needs to be updated on close.
  1062. //
  1063. SetFlag( FileObject->Flags, FO_FILE_MODIFIED );
  1064. try {
  1065. //
  1066. // Check here if we will be decreasing file size and synchonize with
  1067. // paging IO.
  1068. //
  1069. RxGetFileSizeWithLock( Fcb, &OriginalFileSize.QuadPart );
  1070. if (OriginalFileSize.QuadPart > Buffer->AllocationSize.QuadPart) {
  1071. //
  1072. // Before we actually truncate, check to see if the purge
  1073. // is going to fail.
  1074. //
  1075. if (!MmCanFileBeTruncated( FileObject->SectionObjectPointer,
  1076. &Buffer->AllocationSize )) {
  1077. try_return( Status = STATUS_USER_MAPPED_FILE );
  1078. }
  1079. RxAcquirePagingIoResource( RxContext, Fcb );
  1080. RxSetFileSizeWithLock( Fcb, &NewAllocationSize );
  1081. //
  1082. // If we reduced the file size to less than the ValidDataLength,
  1083. // adjust the VDL.
  1084. //
  1085. if (Fcb->Header.ValidDataLength.QuadPart > NewAllocationSize) {
  1086. Fcb->Header.ValidDataLength.QuadPart = NewAllocationSize;
  1087. }
  1088. RxReleasePagingIoResource( RxContext, Fcb );
  1089. }
  1090. OriginalAllocationSize.QuadPart = Fcb->Header.AllocationSize.QuadPart;
  1091. Fcb->Header.AllocationSize.QuadPart = NewAllocationSize;
  1092. Status = RxpSetInfoMiniRdr( RxContext,
  1093. Irp,
  1094. Fcb,
  1095. FileAllocationInformation );
  1096. if (!NT_SUCCESS( Status )) {
  1097. Fcb->Header.AllocationSize.QuadPart = OriginalAllocationSize.QuadPart;
  1098. RxDbgTrace( -1, Dbg, ("RxSetAllocationInfo -> %08lx\n", Status) );
  1099. try_return( Status );
  1100. }
  1101. //
  1102. // Now check if we needed to change the file size accordingly.
  1103. //
  1104. if( OriginalAllocationSize.QuadPart != NewAllocationSize ) {
  1105. //
  1106. // Tell the cache manager we reduced the file size or increased the allocationsize
  1107. // The call is unconditional, because MM always wants to know.
  1108. //
  1109. try {
  1110. CcSetFileSizes( FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
  1111. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1112. Status = GetExceptionCode();
  1113. //
  1114. // Cache manager was not able to extend the file. Restore the file to
  1115. // its previous state.
  1116. //
  1117. // NOTE: If this call to the mini-RDR fails, there is nothing we can do.
  1118. //
  1119. Fcb->Header.AllocationSize.QuadPart = OriginalAllocationSize.QuadPart;
  1120. RxpSetInfoMiniRdr( RxContext,
  1121. Irp,
  1122. Fcb,
  1123. FileAllocationInformation );
  1124. try_return( Status );
  1125. }
  1126. }
  1127. try_exit: NOTHING;
  1128. } finally {
  1129. if (CacheMapInitialized) {
  1130. CcUninitializeCacheMap( FileObject, NULL, NULL );
  1131. }
  1132. }
  1133. RxLog(( "SetAllocExit %lx %lx\n",
  1134. Fcb->Header.FileSize.LowPart,
  1135. Fcb->Header.AllocationSize.LowPart ));
  1136. RxWmiLog( LOG,
  1137. RxSetAllocationInfo_2,
  1138. LOGULONG( Fcb->Header.FileSize.LowPart )
  1139. LOGULONG( Fcb->Header.AllocationSize.LowPart) );
  1140. RxDbgTrace( -1, Dbg, ("RxSetAllocationInfo -> %08lx\n", STATUS_SUCCESS) );
  1141. return Status;
  1142. }
  1143. NTSTATUS
  1144. RxSetEndOfFileInfo (
  1145. IN PRX_CONTEXT RxContext,
  1146. IN PIRP Irp,
  1147. IN PFCB Fcb,
  1148. IN PFOBX Fobx
  1149. )
  1150. /*++
  1151. Routine Description:
  1152. (Internal Support Routine)
  1153. This routine performs the set End of File information for rx. It either
  1154. completes the request or enqueues it off to the fsp.
  1155. Arguments:
  1156. RxContext - The rxcontext for the request
  1157. Irp - irp to proccess
  1158. Fcb - the fcb to work on
  1159. Fobx - The fobx for the open
  1160. Return Value:
  1161. RXSTATUS - The result of this operation if it completes without
  1162. an exception.
  1163. --*/
  1164. {
  1165. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  1166. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1167. PFILE_OBJECT FileObject = IrpSp->FileObject;
  1168. PFILE_END_OF_FILE_INFORMATION Buffer;
  1169. LONGLONG NewFileSize;
  1170. LONGLONG OriginalFileSize;
  1171. LONGLONG OriginalAllocationSize;
  1172. LONGLONG OriginalValidDataLength;
  1173. BOOLEAN CacheMapInitialized = FALSE;
  1174. BOOLEAN PagingIoResourceAcquired = FALSE;
  1175. PAGED_CODE();
  1176. Buffer = Irp->AssociatedIrp.SystemBuffer;
  1177. NewFileSize = Buffer->EndOfFile.QuadPart;
  1178. RxDbgTrace( +1, Dbg, ("RxSetEndOfFileInfo...Old,New,Alloc %08lx,%08lx,%08lx\n",
  1179. Fcb->Header.FileSize.LowPart,
  1180. (ULONG)NewFileSize,
  1181. Fcb->Header.AllocationSize.LowPart) );
  1182. RxLog(( "SetEof %lx %lx %lx %lx\n", RxContext, Fcb->Header.FileSize.LowPart, (ULONG)NewFileSize, Fcb->Header.AllocationSize.LowPart ));
  1183. RxWmiLog( LOG,
  1184. RxSetEndOfFileInfo_1,
  1185. LOGPTR(RxContext)
  1186. LOGULONG( Fcb->Header.FileSize.LowPart )
  1187. LOGULONG( (ULONG)NewFileSize )
  1188. LOGULONG( Fcb->Header.AllocationSize.LowPart ) );
  1189. //
  1190. // File Size changes are only allowed on a file and not a directory
  1191. //
  1192. if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
  1193. RxDbgTrace( 0, Dbg, ("Cannot change size of a directory\n", 0) );
  1194. return STATUS_INVALID_DEVICE_REQUEST;
  1195. }
  1196. try {
  1197. //
  1198. // remember everything
  1199. //
  1200. OriginalFileSize = Fcb->Header.FileSize.QuadPart;
  1201. OriginalAllocationSize = Fcb->Header.AllocationSize.QuadPart;
  1202. OriginalValidDataLength = Fcb->Header.ValidDataLength.QuadPart;
  1203. //
  1204. // This is kinda gross, but if the file is not cached, but there is
  1205. // a data section, we have to cache the file to avoid a bunch of
  1206. // extra work.
  1207. //
  1208. if ((FileObject->SectionObjectPointer->DataSectionObject != NULL) &&
  1209. (FileObject->SectionObjectPointer->SharedCacheMap == NULL) &&
  1210. (Irp->RequestorMode != KernelMode)) {
  1211. if ( FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE ) ) {
  1212. try_return( STATUS_FILE_CLOSED );
  1213. }
  1214. RxAdjustAllocationSizeforCC( Fcb );
  1215. //
  1216. // Now initialize the cache map.
  1217. //
  1218. CcInitializeCacheMap( FileObject,
  1219. (PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
  1220. FALSE,
  1221. &RxData.CacheManagerCallbacks,
  1222. Fcb );
  1223. CacheMapInitialized = TRUE;
  1224. }
  1225. //
  1226. // RDR doesn't handle the lazy write of file sizes. See abovein RxCommonSetInformation
  1227. //
  1228. ASSERTMSG( "Unhandled advance only EOF\n", !IrpSp->Parameters.SetFile.AdvanceOnly );
  1229. //
  1230. // Check if we are really changing the file size
  1231. //
  1232. if (Fcb->Header.FileSize.QuadPart != NewFileSize) {
  1233. if (NewFileSize < Fcb->Header.FileSize.QuadPart) {
  1234. //
  1235. // Before we actually truncate, check to see if the purge
  1236. // is going to fail.
  1237. //
  1238. if (!MmCanFileBeTruncated( FileObject->SectionObjectPointer,
  1239. &Buffer->EndOfFile )) {
  1240. try_return( Status = STATUS_USER_MAPPED_FILE );
  1241. }
  1242. }
  1243. //
  1244. // MM always wants to know if the filesize is changing;
  1245. // serialize here with paging io since we are truncating the file size.
  1246. //
  1247. PagingIoResourceAcquired = RxAcquirePagingIoResource( RxContext, Fcb );
  1248. //
  1249. // Set the new file size
  1250. //
  1251. Fcb->Header.FileSize.QuadPart = NewFileSize;
  1252. //
  1253. // If we reduced the file size to less than the ValidDataLength,
  1254. // adjust the VDL.
  1255. //
  1256. if (Fcb->Header.ValidDataLength.QuadPart > NewFileSize) {
  1257. Fcb->Header.ValidDataLength.QuadPart = NewFileSize;
  1258. }
  1259. //
  1260. // Change the file allocation size as well
  1261. //
  1262. Fcb->Header.AllocationSize.QuadPart = NewFileSize;
  1263. Status = RxpSetInfoMiniRdr( RxContext,
  1264. Irp,
  1265. Fcb,
  1266. FileEndOfFileInformation );
  1267. if (Status == STATUS_SUCCESS) {
  1268. if (PagingIoResourceAcquired) {
  1269. RxReleasePagingIoResource( RxContext, Fcb );
  1270. PagingIoResourceAcquired = FALSE;
  1271. }
  1272. //
  1273. // We must now update the cache mapping (benign if not cached).
  1274. //
  1275. try {
  1276. CcSetFileSizes( FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
  1277. } except (EXCEPTION_EXECUTE_HANDLER) {
  1278. Status = GetExceptionCode();
  1279. }
  1280. if (Status != STATUS_SUCCESS) {
  1281. try_return( Status );
  1282. }
  1283. }
  1284. } else {
  1285. //
  1286. // Set our return status to success
  1287. //
  1288. Status = STATUS_SUCCESS;
  1289. }
  1290. //
  1291. // Set this handle as having modified the file
  1292. //
  1293. SetFlag( FileObject->Flags, FO_FILE_MODIFIED );
  1294. try_exit: NOTHING;
  1295. } finally {
  1296. DebugUnwind( RxSetEndOfFileInfo );
  1297. if ((AbnormalTermination() || !NT_SUCCESS( Status ))) {
  1298. RxDbgTrace( -1, Dbg, ("RxSetEndOfFileInfo2 status -> %08lx\n", Status) );
  1299. Fcb->Header.FileSize.QuadPart = OriginalFileSize;
  1300. Fcb->Header.AllocationSize.QuadPart = OriginalAllocationSize;
  1301. Fcb->Header.ValidDataLength.QuadPart = OriginalValidDataLength;
  1302. if (FileObject->SectionObjectPointer->SharedCacheMap != NULL) {
  1303. *CcGetFileSizePointer(FileObject) = Fcb->Header.FileSize;
  1304. }
  1305. RxLog(("SetEofabnormalorbadstatus %lx %lx", RxContext,Status));
  1306. RxWmiLog( LOG,
  1307. RxSetEndOfFileInfo_3,
  1308. LOGPTR( RxContext )
  1309. LOGULONG( Status ) );
  1310. }
  1311. if (PagingIoResourceAcquired) {
  1312. RxReleasePagingIoResource( RxContext, Fcb );
  1313. }
  1314. if (CacheMapInitialized) {
  1315. CcUninitializeCacheMap( FileObject, NULL, NULL );
  1316. }
  1317. RxDbgTrace(-1, Dbg, ("RxSetEndOfFileInfo -> %08lx\n", Status));
  1318. }
  1319. if (Status == STATUS_SUCCESS) {
  1320. RxLog(( "SetEofexit %lx %lx %lx\n",
  1321. Fcb->Header.FileSize.LowPart,
  1322. (ULONG)NewFileSize,
  1323. Fcb->Header.AllocationSize.LowPart ));
  1324. RxWmiLog( LOG,
  1325. RxSetEndOfFileInfo_4,
  1326. LOGPTR( RxContext )
  1327. LOGULONG( Fcb->Header.FileSize.LowPart )
  1328. LOGULONG( (ULONG)NewFileSize )
  1329. LOGULONG( Fcb->Header.AllocationSize.LowPart ) );
  1330. }
  1331. return Status;
  1332. }
  1333. BOOLEAN RxForceQFIPassThrough = FALSE;
  1334. NTSTATUS
  1335. RxQueryBasicInfo (
  1336. IN PRX_CONTEXT RxContext,
  1337. IN PIRP Irp,
  1338. IN PFCB Fcb,
  1339. IN OUT PFILE_BASIC_INFORMATION Buffer
  1340. )
  1341. /*++
  1342. Description:
  1343. (Internal Support Routine)
  1344. This routine performs the query basic information function for fat.
  1345. Arguments:
  1346. RxContext -
  1347. Irp -
  1348. Fcb -
  1349. Buffer - Supplies a pointer to the buffer where the information is to
  1350. be returned
  1351. Return Value:
  1352. STATUS_SUCCESS if the call was successful, otherwise the appropriate error code
  1353. --*/
  1354. {
  1355. NTSTATUS Status = STATUS_SUCCESS;
  1356. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1357. PAGED_CODE();
  1358. RxDbgTrace( +1, Dbg, ("RxQueryBasicInfo...\n", 0) );
  1359. RxLog(( "RxQueryBasicInfo\n" ));
  1360. RxWmiLog( LOG,
  1361. RxQueryBasicInfo,
  1362. LOGPTR( RxContext ) );
  1363. //
  1364. // Zero out the output buffer, and set it to indicate that
  1365. // the query is a normal file. Later we might overwrite the
  1366. // attribute.
  1367. //
  1368. RtlZeroMemory( Buffer, sizeof( FILE_BASIC_INFORMATION ) );
  1369. Status = RxpQueryInfoMiniRdr( RxContext,
  1370. Fcb,
  1371. FileBasicInformation,
  1372. Buffer );
  1373. return Status;
  1374. }
  1375. NTSTATUS
  1376. RxQueryStandardInfo (
  1377. IN PRX_CONTEXT RxContext,
  1378. IN PIRP Irp,
  1379. IN PFCB Fcb,
  1380. IN PFOBX Fobx,
  1381. IN OUT PFILE_STANDARD_INFORMATION Buffer
  1382. )
  1383. /*++
  1384. Routine Description:
  1385. This routine performs the query standard information function for fat.
  1386. Arguments:
  1387. RxContext -
  1388. Irp -
  1389. Fcb -
  1390. Fobx -
  1391. Buffer - Supplies a pointer to the buffer where the information is to
  1392. be returned
  1393. Return Value:
  1394. STATUS_SUCCESS/STATUS_PENDING or an appropriate error code
  1395. --*/
  1396. {
  1397. NTSTATUS Status = STATUS_SUCCESS;
  1398. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1399. PMRX_SRV_OPEN SrvOpen;
  1400. PAGED_CODE();
  1401. RxDbgTrace( +1, Dbg, ("RxQueryStandardInfo...\n", 0) );
  1402. RxLog(( "RxQueryStandardInfo\n" ));
  1403. RxWmiLog( LOG,
  1404. RxQueryStandardInfo,
  1405. LOGPTR( RxContext ));
  1406. //
  1407. // Zero out the output buffer, and fill in the number of links
  1408. // and the delete pending flag.
  1409. //
  1410. RtlZeroMemory( Buffer, sizeof( FILE_STANDARD_INFORMATION ) );
  1411. SrvOpen = Fobx->pSrvOpen;
  1412. switch (NodeType( Fcb )) {
  1413. case RDBSS_NTC_STORAGE_TYPE_DIRECTORY:
  1414. case RDBSS_NTC_STORAGE_TYPE_FILE:
  1415. //
  1416. // If the file was not opened with back up intent then the wrapper has
  1417. // all the information that is required. In the cases that this is
  1418. // specified we fill in the information from the mini redirector. This
  1419. // is because backup pograms rely upon fields that are not available
  1420. // in the wrapper and that which cannot be cached easily.
  1421. //
  1422. if (!FlagOn( SrvOpen->CreateOptions,FILE_OPEN_FOR_BACKUP_INTENT )) {
  1423. //
  1424. // copy in all the stuff that we know....it may be enough.....
  1425. //
  1426. Buffer->NumberOfLinks = Fcb->NumberOfLinks;
  1427. Buffer->DeletePending = BooleanFlagOn( Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE );
  1428. Buffer->Directory = (NodeType( Fcb ) == RDBSS_NTC_STORAGE_TYPE_DIRECTORY);
  1429. if (Buffer->NumberOfLinks == 0) {
  1430. //
  1431. // This switch is required because of compatibility reasons with
  1432. // the old redirector.
  1433. //
  1434. Buffer->NumberOfLinks = 1;
  1435. }
  1436. if (NodeType( Fcb ) == RDBSS_NTC_STORAGE_TYPE_FILE) {
  1437. Buffer->AllocationSize = Fcb->Header.AllocationSize;
  1438. RxGetFileSizeWithLock( Fcb, &Buffer->EndOfFile.QuadPart );
  1439. }
  1440. if (!RxForceQFIPassThrough &&
  1441. FlagOn( Fcb->FcbState, FCB_STATE_FILESIZECACHEING_ENABLED )) {
  1442. //
  1443. // if we don't have to go to the mini, adjust the size and get out.......
  1444. //
  1445. RxContext->Info.LengthRemaining -= sizeof( FILE_STANDARD_INFORMATION );
  1446. break;
  1447. }
  1448. }
  1449. // falls thru
  1450. default:
  1451. Status = RxpQueryInfoMiniRdr( RxContext,
  1452. Fcb,
  1453. FileStandardInformation,
  1454. Buffer );
  1455. break;
  1456. }
  1457. RxDbgTrace( 0, Dbg, ("LengthRemaining = %08lx\n", RxContext->Info.LengthRemaining));
  1458. RxDbgTrace( -1, Dbg, ("RxQueryStandardInfo -> VOID\n", 0) );
  1459. return Status;
  1460. }
  1461. NTSTATUS
  1462. RxQueryInternalInfo (
  1463. IN PRX_CONTEXT RxContext,
  1464. IN PIRP Irp,
  1465. IN PFCB Fcb,
  1466. IN OUT PFILE_INTERNAL_INFORMATION Buffer
  1467. )
  1468. /*++
  1469. Routine Description:
  1470. (Internal Support Routine)
  1471. This routine performs the query internal information function for fat.
  1472. Arguments:
  1473. RxContext -
  1474. Irp -
  1475. Fcb -
  1476. Buffer - Supplies a pointer to the buffer where the information is to
  1477. be returned
  1478. Return Value:
  1479. STATUS_SUCCESS/STATUS_PENDING or an appropriate error code
  1480. --*/
  1481. {
  1482. NTSTATUS Status = STATUS_SUCCESS;
  1483. PAGED_CODE();
  1484. RxDbgTrace( +1, Dbg, ("RxQueryInternalInfo...\n", 0) );
  1485. RxLog(( "RxQueryInternalInfo\n" ));
  1486. RxWmiLog( LOG,
  1487. RxQueryInternalInfo,
  1488. LOGPTR( RxContext ) );
  1489. Status = RxpQueryInfoMiniRdr( RxContext,
  1490. Fcb,
  1491. FileInternalInformation,
  1492. Buffer );
  1493. RxDbgTrace( -1, Dbg, ("RxQueryInternalInfo...Status %lx\n", Status) );
  1494. return Status;
  1495. UNREFERENCED_PARAMETER( Irp );
  1496. }
  1497. NTSTATUS
  1498. RxQueryEaInfo (
  1499. IN PRX_CONTEXT RxContext,
  1500. IN PIRP Irp,
  1501. IN PFCB Fcb,
  1502. IN OUT PFILE_EA_INFORMATION Buffer
  1503. )
  1504. /*++
  1505. Routine Description:
  1506. This routine performs the query Ea information function for fat.
  1507. Arguments:
  1508. RxContext -
  1509. Irp -
  1510. Fcb -
  1511. Buffer - Supplies a pointer to the buffer where the information is to
  1512. be returned
  1513. Return Value:
  1514. STATUS_SUCCESS/STATUS_PENDING or an appropriate error code
  1515. --*/
  1516. {
  1517. NTSTATUS Status = STATUS_SUCCESS;
  1518. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1519. PAGED_CODE();
  1520. RxDbgTrace(+1, Dbg, ("RxQueryEaInfo...\n", 0));
  1521. RxLog(( "RxQueryEaInfo\n" ));
  1522. RxWmiLog( LOG,
  1523. RxQueryEaInfo,
  1524. LOGPTR( RxContext ));
  1525. Status = RxpQueryInfoMiniRdr( RxContext,
  1526. Fcb,
  1527. FileEaInformation,
  1528. Buffer );
  1529. if ((IrpSp->Parameters.QueryFile.FileInformationClass == FileAllInformation) &&
  1530. (Status == STATUS_NOT_IMPLEMENTED)) {
  1531. RxContext->Info.LengthRemaining -= sizeof( FILE_EA_INFORMATION );
  1532. Status = STATUS_SUCCESS;
  1533. }
  1534. RxDbgTrace(-1, Dbg, ("RxQueryEaInfo...Status %lx\n", Status));
  1535. return Status;
  1536. }
  1537. NTSTATUS
  1538. RxQueryPositionInfo (
  1539. IN PRX_CONTEXT RxContext,
  1540. IN PIRP Irp,
  1541. IN PFCB Fcb,
  1542. IN OUT PFILE_POSITION_INFORMATION Buffer
  1543. )
  1544. /*++
  1545. Routine Description:
  1546. This routine performs the query position information function for fat.
  1547. Arguments:
  1548. RxContext - the RDBSS context
  1549. Irp -
  1550. Fcb -
  1551. Buffer - Supplies a pointer to the buffer where the information is to
  1552. be returned
  1553. Return Value:
  1554. STATUS_SUCCESS/STATUS_PENDING or an appropriate error code
  1555. --*/
  1556. {
  1557. NTSTATUS Status = STATUS_SUCCESS;
  1558. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1559. PFILE_OBJECT FileObject = IrpSp->FileObject;
  1560. PAGED_CODE();
  1561. RxDbgTrace( +1, Dbg, ("RxQueryPositionInfo...\n", 0) );
  1562. RxLog(( "RxQueryPositionInfo\n" ));
  1563. RxWmiLog( LOG,
  1564. RxQueryPositionInfo,
  1565. LOGPTR( RxContext ) );
  1566. Buffer->CurrentByteOffset = FileObject->CurrentByteOffset;
  1567. RxContext->Info.LengthRemaining -= sizeof( FILE_POSITION_INFORMATION );
  1568. RxDbgTrace( 0, Dbg, ("LengthRemaining = %08lx\n", RxContext->Info.LengthRemaining) );
  1569. RxDbgTrace( -1, Dbg, ("RxQueryPositionInfo...Status %lx\n", Status) );
  1570. return Status;
  1571. UNREFERENCED_PARAMETER( Irp );
  1572. }
  1573. VOID
  1574. RxConjureOriginalName (
  1575. IN PFCB Fcb,
  1576. IN PFOBX Fobx,
  1577. OUT PLONG ActualNameLength,
  1578. IN PWCHAR OriginalName,
  1579. IN OUT PLONG LengthRemaining,
  1580. IN RX_NAME_CONJURING_METHODS NameConjuringMethod
  1581. )
  1582. /*++
  1583. Routine Description:
  1584. This routine conjures up the original name of an Fcb. it is used in querynameinfo below and
  1585. also in RxCanonicalizeAndObtainPieces in the create path for relative opens. for relative opens, we return
  1586. a name of the form \;m:\server\share\.....\name which is how it came down from createfile. otherwise, we give
  1587. back the name relative to the vnetroot.
  1588. Arguments:
  1589. Fcb - Supplies the Fcb whose original name is to be conjured
  1590. ActualNameLength - the place to store the actual name length. not all of it will be conjured
  1591. if the buffer is too small.
  1592. OriginalName - Supplies a pointer to the buffer where the name is to conjured
  1593. LengthRemaining - Supplies the length of the Name buffer in bytes, and receives the
  1594. remaining bytes free in the buffer upon return.
  1595. VNetRootAsPrefix - if true, give back the name as "\;m:", if false, give it back w/o net part.
  1596. Return Value:
  1597. None
  1598. --*/
  1599. {
  1600. PNET_ROOT NetRoot = Fcb->NetRoot;
  1601. PUNICODE_STRING NetRootName = &NetRoot->PrefixEntry.Prefix;
  1602. PUNICODE_STRING FcbName = &Fcb->FcbTableEntry.Path;
  1603. PWCHAR CopyBuffer,FcbNameBuffer;
  1604. LONG BytesToCopy,BytesToCopy2;
  1605. LONG FcbNameSuffixLength,PreFcbLength;
  1606. LONG InnerPrefixLength;
  1607. RX_NAME_CONJURING_METHODS OrigianlNameConjuringMethod = NameConjuringMethod;
  1608. PAGED_CODE();
  1609. RxDbgTrace(+1, Dbg, ("RxConjureOriginalFilename...\n", 0));
  1610. RxDbgTrace(0, Dbg, ("--> NetRootName = %wZ\n", NetRootName));
  1611. RxDbgTrace(0, Dbg, ("--> FcbNameName = %wZ\n", FcbName));
  1612. RxDbgTrace(0, Dbg, ("--> ,AddedBS = %08lx\n",
  1613. FlagOn(Fcb->FcbState,FCB_STATE_ADDEDBACKSLASH)));
  1614. //
  1615. // here, we have to copy in the vnetrootprefix and the servershare stuff.
  1616. // first figure out the size of the two pieces: prefcblength is the part that comes
  1617. // from the [v]netroot; fcbnamesuffix is the part that is left of the filename after
  1618. // the vnetroot prefix is skipped
  1619. //
  1620. if ((!Fcb->VNetRoot) ||
  1621. (Fcb->VNetRoot->PrefixEntry.Prefix.Buffer[1] != L';') ||
  1622. (FlagOn( Fobx->Flags, FOBX_FLAG_UNC_NAME )) ){
  1623. CopyBuffer = NetRootName->Buffer;
  1624. PreFcbLength = NetRootName->Length;
  1625. InnerPrefixLength = 0;
  1626. NameConjuringMethod = VNetRoot_As_Prefix; // override whatever was passed
  1627. } else {
  1628. PV_NET_ROOT VNetRoot = Fcb->VNetRoot;
  1629. PUNICODE_STRING VNetRootName = &VNetRoot->PrefixEntry.Prefix;
  1630. ASSERT( NodeType( VNetRoot ) == RDBSS_NTC_V_NETROOT );
  1631. RxDbgTrace( 0, Dbg, ("--> VNetRootName = %wZ\n", VNetRootName) );
  1632. RxDbgTrace(0, Dbg, ("--> VNetRootNamePrefix = %wZ\n", &VNetRoot->NamePrefix) );
  1633. InnerPrefixLength = VNetRoot->NamePrefix.Length;
  1634. RxDbgTrace( 0, Dbg, ("--> ,IPrefixLen = %08lx\n", InnerPrefixLength) );
  1635. CopyBuffer = VNetRootName->Buffer;
  1636. PreFcbLength = VNetRootName->Length;
  1637. if (NameConjuringMethod == VNetRoot_As_UNC_Name) {
  1638. //
  1639. // move up past the drive information
  1640. //
  1641. for (;;) {
  1642. CopyBuffer++;
  1643. PreFcbLength -= sizeof(WCHAR);
  1644. if (PreFcbLength == 0) break;
  1645. if (*CopyBuffer == L'\\') break;
  1646. }
  1647. }
  1648. }
  1649. if (FlagOn(Fcb->FcbState, FCB_STATE_ADDEDBACKSLASH )) {
  1650. InnerPrefixLength += sizeof(WCHAR);
  1651. }
  1652. //
  1653. // next, Copyin the NetRoot Part OR the VNetRoot part.
  1654. // If we overflow, set *LengthRemaining to -1 as a flag.
  1655. //
  1656. if (NameConjuringMethod != VNetRoot_As_DriveLetter) {
  1657. if (*LengthRemaining < PreFcbLength) {
  1658. BytesToCopy = *LengthRemaining;
  1659. *LengthRemaining = -1;
  1660. } else {
  1661. BytesToCopy = PreFcbLength;
  1662. *LengthRemaining -= BytesToCopy;
  1663. }
  1664. RtlCopyMemory( OriginalName,
  1665. CopyBuffer,
  1666. BytesToCopy );
  1667. BytesToCopy2 = BytesToCopy;
  1668. } else {
  1669. PreFcbLength = 0;
  1670. BytesToCopy2 = 0;
  1671. if ((FcbName->Length > InnerPrefixLength) &&
  1672. (*((PWCHAR)Add2Ptr( FcbName->Buffer , InnerPrefixLength )) != OBJ_NAME_PATH_SEPARATOR)) {
  1673. InnerPrefixLength -= sizeof(WCHAR);
  1674. }
  1675. }
  1676. FcbNameSuffixLength = FcbName->Length - InnerPrefixLength;
  1677. if (FcbNameSuffixLength <= 0) {
  1678. FcbNameBuffer = L"\\";
  1679. FcbNameSuffixLength = 2;
  1680. InnerPrefixLength = 0;
  1681. } else {
  1682. FcbNameBuffer = FcbName->Buffer;
  1683. }
  1684. //
  1685. // report how much is really needed
  1686. //
  1687. *ActualNameLength = PreFcbLength + FcbNameSuffixLength;
  1688. //
  1689. // the netroot part has been copied; finally, copy in the part of the name
  1690. // that is past the prefix
  1691. //
  1692. if (*LengthRemaining != -1) {
  1693. //
  1694. // Next, Copyin the Fcb Part
  1695. // If we overflow, set *LengthRemaining to -1 as a flag.
  1696. //
  1697. if (*LengthRemaining < FcbNameSuffixLength) {
  1698. BytesToCopy = *LengthRemaining;
  1699. *LengthRemaining = -1;
  1700. } else {
  1701. BytesToCopy = FcbNameSuffixLength;
  1702. *LengthRemaining -= BytesToCopy;
  1703. }
  1704. RtlCopyMemory( Add2Ptr( OriginalName, PreFcbLength ),
  1705. Add2Ptr( FcbNameBuffer, InnerPrefixLength ),
  1706. BytesToCopy );
  1707. } else {
  1708. // DbgPrint("No second copy\n");
  1709. DbgDoit( BytesToCopy=0; );
  1710. }
  1711. RxDbgTrace(-1, Dbg, ("RxConjureOriginalFilename -> VOID\n", 0));
  1712. return;
  1713. }
  1714. NTSTATUS
  1715. RxQueryNameInfo (
  1716. IN PRX_CONTEXT RxContext,
  1717. IN PIRP Irp,
  1718. IN PFCB Fcb,
  1719. IN PFOBX Fobx,
  1720. IN OUT PFILE_NAME_INFORMATION Buffer
  1721. )
  1722. /*++
  1723. Routine Description:
  1724. This routine performs the query name information function. what makes this hard is that
  1725. we have to return partial results.
  1726. Arguments:
  1727. Buffer - Supplies a pointer to the buffer where the information is to
  1728. be returned
  1729. Return Value:
  1730. STATUS_SUCCESS if the name fits
  1731. STATUS_BUFFER_OVERFLOW otherwise
  1732. --*/
  1733. {
  1734. NTSTATUS Status = STATUS_SUCCESS;
  1735. PLONG LengthRemaining = &RxContext->Info.LengthRemaining;
  1736. LONG OriginalLengthRemaining = RxContext->Info.LengthRemaining;
  1737. RxDbgTrace( +1, Dbg, ("RxQueryNameInfo...\n", 0) );
  1738. RxLog(( "RxQueryNameInfo\n" ));
  1739. RxWmiLog( LOG,
  1740. RxQueryNameInfo,
  1741. LOGPTR( RxContext ) );
  1742. PAGED_CODE();
  1743. *LengthRemaining -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]);
  1744. if (*LengthRemaining < 0) {
  1745. *LengthRemaining = 0;
  1746. Status = STATUS_BUFFER_OVERFLOW;
  1747. } else {
  1748. RxConjureOriginalName( Fcb,
  1749. Fobx,
  1750. &Buffer->FileNameLength,
  1751. &Buffer->FileName[0],
  1752. LengthRemaining,
  1753. VNetRoot_As_UNC_Name );
  1754. RxDbgTrace( 0, Dbg, ("*LengthRemaining = %08lx\n", *LengthRemaining) );
  1755. if (*LengthRemaining < 0) {
  1756. *LengthRemaining = 0;
  1757. Status = STATUS_BUFFER_OVERFLOW;
  1758. }
  1759. }
  1760. RxDbgTrace( -1, Dbg, ("RxQueryNameInfo -> %08lx\n", Status) );
  1761. return Status;
  1762. UNREFERENCED_PARAMETER( Irp );
  1763. }
  1764. NTSTATUS
  1765. RxQueryAlternateNameInfo (
  1766. IN PRX_CONTEXT RxContext,
  1767. IN PIRP Irp,
  1768. IN PFCB Fcb,
  1769. IN OUT PFILE_NAME_INFORMATION Buffer
  1770. )
  1771. /*++
  1772. Routine Description:
  1773. This routine queries the short name of the file.
  1774. Arguments:
  1775. Buffer - Supplies a pointer to the buffer where the information is to
  1776. be returned
  1777. Return Value:
  1778. STATUS_SUCCESS/STATUS_PENDING or an appropriate error code
  1779. --*/
  1780. {
  1781. NTSTATUS Status = STATUS_SUCCESS;
  1782. PAGED_CODE();
  1783. RxDbgTrace( +1, Dbg, ("RxQueryAlternateNameInfo...\n", 0) );
  1784. RxLog(( "RxQueryAlternateNameInfo\n" ));
  1785. RxWmiLog( LOG,
  1786. RxQueryAlternateNameInfo,
  1787. LOGPTR( RxContext ));
  1788. Status = RxpQueryInfoMiniRdr( RxContext,
  1789. Fcb,
  1790. FileAlternateNameInformation,
  1791. Buffer );
  1792. RxDbgTrace(-1, Dbg, ("RxQueryAlternateNameInfo...Status %lx\n", Status) );
  1793. return Status;
  1794. UNREFERENCED_PARAMETER( Irp );
  1795. }
  1796. NTSTATUS
  1797. RxQueryCompressedInfo (
  1798. IN PRX_CONTEXT RxContext,
  1799. IN PIRP Irp,
  1800. IN PFCB Fcb,
  1801. IN OUT PFILE_COMPRESSION_INFORMATION Buffer
  1802. )
  1803. /*++
  1804. Routine Description:
  1805. This routine performs the query compressed file size function for fat.
  1806. This is only defined for compressed volumes.
  1807. Arguments:
  1808. Buffer - Supplies a pointer to the buffer where the information is to
  1809. be returned
  1810. Return Value:
  1811. STATUS_SUCCESS/STATUS_PENDING or an appropriate error code
  1812. --*/
  1813. {
  1814. NTSTATUS Status = STATUS_SUCCESS;
  1815. PAGED_CODE();
  1816. RxDbgTrace( +1, Dbg, ("RxQueryCompressedFileSize...\n", 0) );
  1817. RxLog(( "RxQueryCompressedFileSize\n" ));
  1818. RxWmiLog( LOG,
  1819. RxQueryCompressedInfo,
  1820. LOGPTR( RxContext ));
  1821. //
  1822. // Start by flushing the file. We have to do this since the compressed
  1823. // file size is not defined until the file is actually written to disk.
  1824. //
  1825. Status = RxFlushFcbInSystemCache( Fcb, TRUE );
  1826. if (!NT_SUCCESS( Status )) {
  1827. RxNormalizeAndRaiseStatus( RxContext, Status );
  1828. }
  1829. Status = RxpQueryInfoMiniRdr( RxContext,
  1830. Fcb,
  1831. FileCompressionInformation,
  1832. Buffer );
  1833. RxDbgTrace( 0, Dbg, ("LengthRemaining = %08lx\n", RxContext->Info.LengthRemaining) );
  1834. RxDbgTrace( -1, Dbg, ("RxQueryCompressedFileSize -> Status\n", Status) );
  1835. return Status;
  1836. UNREFERENCED_PARAMETER( Irp );
  1837. }
  1838. NTSTATUS
  1839. RxSetPipeInfo (
  1840. IN OUT PRX_CONTEXT RxContext,
  1841. IN PIRP Irp,
  1842. IN PFCB Fcb,
  1843. IN PFOBX Fobx
  1844. )
  1845. /*++
  1846. Routine Description:
  1847. This routine updates the FILE_PIPE_INFORMATION/FILE_PIPE_REMOTE_INFORMATION
  1848. associated with an instance of a named pipe
  1849. Arguments:
  1850. RxContext -- the associated RDBSS context
  1851. Return Value:
  1852. STATUS_SUCCESS/STATUS_PENDING or an appropriate error code
  1853. --*/
  1854. {
  1855. NTSTATUS Status = STATUS_SUCCESS;
  1856. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1857. FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
  1858. PAGED_CODE();
  1859. RxDbgTrace( +1, Dbg, ("RxSetPipeInfo...\n", 0) );
  1860. RxLog(( "RxSetPipeInfo\n" ));
  1861. RxWmiLog( LOG,
  1862. RxSetPipeInfo,
  1863. LOGPTR( RxContext ));
  1864. if (Fcb->NetRoot->Type != NET_ROOT_PIPE) {
  1865. Status = STATUS_INVALID_PARAMETER;
  1866. } else {
  1867. switch (FileInformationClass) {
  1868. case FilePipeInformation:
  1869. if (IrpSp->Parameters.SetFile.Length == sizeof(FILE_PIPE_INFORMATION)) {
  1870. PFILE_PIPE_INFORMATION PipeInfo = (PFILE_PIPE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
  1871. if ((PipeInfo->ReadMode != Fobx->Specific.NamedPipe.ReadMode) ||
  1872. (PipeInfo->CompletionMode != Fobx->Specific.NamedPipe.CompletionMode)) {
  1873. RxContext->Info.FileInformationClass = (FilePipeInformation);
  1874. RxContext->Info.Buffer = PipeInfo;
  1875. RxContext->Info.Length = sizeof(FILE_PIPE_INFORMATION);
  1876. MINIRDR_CALL( Status,
  1877. RxContext,
  1878. Fcb->MRxDispatch,
  1879. MRxSetFileInfo,
  1880. (RxContext) );
  1881. if (Status == STATUS_SUCCESS) {
  1882. Fobx->Specific.NamedPipe.ReadMode = PipeInfo->ReadMode;
  1883. Fobx->Specific.NamedPipe.CompletionMode = PipeInfo->CompletionMode;
  1884. }
  1885. }
  1886. } else {
  1887. Status = STATUS_INVALID_PARAMETER;
  1888. }
  1889. break;
  1890. case FilePipeLocalInformation:
  1891. Status = STATUS_INVALID_PARAMETER;
  1892. break;
  1893. case FilePipeRemoteInformation:
  1894. if (IrpSp->Parameters.SetFile.Length == sizeof(FILE_PIPE_REMOTE_INFORMATION)) {
  1895. PFILE_PIPE_REMOTE_INFORMATION PipeRemoteInfo = (PFILE_PIPE_REMOTE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
  1896. Fobx->Specific.NamedPipe.CollectDataTime = PipeRemoteInfo->CollectDataTime;
  1897. Fobx->Specific.NamedPipe.CollectDataSize = PipeRemoteInfo->MaximumCollectionCount;
  1898. } else {
  1899. Status = STATUS_INVALID_PARAMETER;
  1900. }
  1901. break;
  1902. default:
  1903. Status = STATUS_INVALID_PARAMETER;
  1904. break;
  1905. }
  1906. }
  1907. RxDbgTrace( -1, Dbg, ("RxSetPipeInfo: Status ....%lx\n", Status) );
  1908. return Status;
  1909. }
  1910. NTSTATUS
  1911. RxSetSimpleInfo (
  1912. IN OUT PRX_CONTEXT RxContext,
  1913. IN PIRP Irp,
  1914. IN PFCB Fcb
  1915. )
  1916. /*++
  1917. Routine Description:
  1918. This routine updates file information that is changed through
  1919. a simple MiniRdr Call.
  1920. Right now this consists of ShortNameInfo & ValdiDataLengthInfo
  1921. Arguments:
  1922. RxContext -- the associated RDBSS context
  1923. Return Value:
  1924. STATUS_SUCCESS/STATUS_PENDING or an appropriate error code
  1925. --*/
  1926. {
  1927. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1928. FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
  1929. NTSTATUS Status = STATUS_SUCCESS;
  1930. PAGED_CODE();
  1931. //
  1932. // logging code
  1933. //
  1934. RxDbgTrace( +1, Dbg, ("RxSetSimpleInfo: %d\n", FileInformationClass) );
  1935. RxLog(( "RxSetSimpleInfo\n" ));
  1936. RxWmiLog( LOG,
  1937. RxSetSimpleInfo,
  1938. LOGPTR( RxContext ));
  1939. //
  1940. // call the MiniRdr
  1941. //
  1942. Status = RxpSetInfoMiniRdr( RxContext, Irp, Fcb, FileInformationClass );
  1943. //
  1944. // logging code
  1945. //
  1946. RxDbgTrace(-1, Dbg, ("RxSetSimpleInfo: Status ....%lx\n", Status) );
  1947. return Status;
  1948. }
  1949. NTSTATUS
  1950. RxQueryPipeInfo(
  1951. IN PRX_CONTEXT RxContext,
  1952. IN PIRP Irp,
  1953. IN PFCB Fcb,
  1954. IN PFOBX Fobx,
  1955. IN OUT PVOID Buffer
  1956. )
  1957. /*++
  1958. Routine Description:
  1959. This routine queries the FILE_PIPE_INFORMATION/FILE_PIPE_REMOTE_INFORMATION
  1960. and FILE_PIPE_LOCAL_INFORMATION associated with an instance of a named pipe
  1961. Arguments:
  1962. RxContext -- the associated RDBSS context
  1963. Buffer -- the buffer for query information
  1964. Return Value:
  1965. STATUS_SUCCESS/STATUS_PENDING or an appropriate error code
  1966. --*/
  1967. {
  1968. NTSTATUS Status = STATUS_SUCCESS;
  1969. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1970. FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
  1971. PLONG LengthRemaining = &RxContext->Info.LengthRemaining;
  1972. PAGED_CODE();
  1973. RxDbgTrace( +1, Dbg, ("RxQueryPipeInfo...\n", 0) );
  1974. RxLog(( "RxQueryPipeInfo\n" ));
  1975. RxWmiLog( LOG,
  1976. RxQueryPipeInfo,
  1977. LOGPTR( RxContext ) );
  1978. if (Fcb->NetRoot->Type != NET_ROOT_PIPE) {
  1979. Status = STATUS_INVALID_PARAMETER;
  1980. } else {
  1981. switch (FileInformationClass) {
  1982. case FilePipeInformation:
  1983. if (*LengthRemaining >= sizeof(FILE_PIPE_INFORMATION)) {
  1984. PFILE_PIPE_INFORMATION PipeInfo = (PFILE_PIPE_INFORMATION)Buffer;
  1985. PipeInfo->ReadMode = Fobx->Specific.NamedPipe.ReadMode;
  1986. PipeInfo->CompletionMode = Fobx->Specific.NamedPipe.CompletionMode;
  1987. //
  1988. // Update the buffer length
  1989. //
  1990. *LengthRemaining -= sizeof( FILE_PIPE_INFORMATION );
  1991. } else {
  1992. Status = STATUS_BUFFER_OVERFLOW;
  1993. }
  1994. break;
  1995. case FilePipeLocalInformation:
  1996. if (*LengthRemaining >= sizeof( FILE_PIPE_LOCAL_INFORMATION )) {
  1997. PFILE_PIPE_LOCAL_INFORMATION pPipeLocalInfo = (PFILE_PIPE_LOCAL_INFORMATION)Buffer;
  1998. Status = RxpQueryInfoMiniRdr( RxContext,
  1999. Fcb,
  2000. FilePipeLocalInformation,
  2001. Buffer );
  2002. } else {
  2003. Status = STATUS_BUFFER_OVERFLOW;
  2004. }
  2005. break;
  2006. case FilePipeRemoteInformation:
  2007. if (*LengthRemaining >= sizeof(FILE_PIPE_REMOTE_INFORMATION)) {
  2008. PFILE_PIPE_REMOTE_INFORMATION PipeRemoteInfo = (PFILE_PIPE_REMOTE_INFORMATION)Buffer;
  2009. PipeRemoteInfo->CollectDataTime = Fobx->Specific.NamedPipe.CollectDataTime;
  2010. PipeRemoteInfo->MaximumCollectionCount = Fobx->Specific.NamedPipe.CollectDataSize;
  2011. //
  2012. // Update the buffer length
  2013. //
  2014. *LengthRemaining -= sizeof( FILE_PIPE_REMOTE_INFORMATION );
  2015. } else {
  2016. Status = STATUS_BUFFER_OVERFLOW;
  2017. }
  2018. break;
  2019. default:
  2020. Status = STATUS_INVALID_PARAMETER;
  2021. break;
  2022. }
  2023. }
  2024. RxDbgTrace( 0, Dbg, ("RxQueryPipeInfo: *LengthRemaining = %08lx\n", *LengthRemaining) );
  2025. return Status;
  2026. }