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.

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