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.

1509 lines
34 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. FileInfo.c
  5. Abstract:
  6. This module implements the File Information routines for Cdfs called by
  7. the Fsd/Fsp dispatch drivers.
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Brian Andrew [BrianAn] 01-July-1995
  11. Revision History:
  12. // @@END_DDKSPLIT
  13. --*/
  14. #include "CdProcs.h"
  15. //
  16. // The Bug check file id for this module
  17. //
  18. #define BugCheckFileId (CDFS_BUG_CHECK_FILEINFO)
  19. //
  20. // Local support routines
  21. //
  22. VOID
  23. CdQueryBasicInfo (
  24. IN PIRP_CONTEXT IrpContext,
  25. IN PFCB Fcb,
  26. IN OUT PFILE_BASIC_INFORMATION Buffer,
  27. IN OUT PULONG Length
  28. );
  29. VOID
  30. CdQueryStandardInfo (
  31. IN PIRP_CONTEXT IrpContext,
  32. IN PFCB Fcb,
  33. IN OUT PFILE_STANDARD_INFORMATION Buffer,
  34. IN OUT PULONG Length
  35. );
  36. VOID
  37. CdQueryInternalInfo (
  38. IN PIRP_CONTEXT IrpContext,
  39. IN PFCB Fcb,
  40. IN OUT PFILE_INTERNAL_INFORMATION Buffer,
  41. IN OUT PULONG Length
  42. );
  43. VOID
  44. CdQueryEaInfo (
  45. IN PIRP_CONTEXT IrpContext,
  46. IN PFCB Fcb,
  47. IN OUT PFILE_EA_INFORMATION Buffer,
  48. IN OUT PULONG Length
  49. );
  50. VOID
  51. CdQueryPositionInfo (
  52. IN PIRP_CONTEXT IrpContext,
  53. IN PFILE_OBJECT FileObject,
  54. IN OUT PFILE_POSITION_INFORMATION Buffer,
  55. IN OUT PULONG Length
  56. );
  57. NTSTATUS
  58. CdQueryNameInfo (
  59. IN PIRP_CONTEXT IrpContext,
  60. IN PFILE_OBJECT FileObject,
  61. IN OUT PFILE_NAME_INFORMATION Buffer,
  62. IN OUT PULONG Length
  63. );
  64. NTSTATUS
  65. CdQueryAlternateNameInfo (
  66. IN PIRP_CONTEXT IrpContext,
  67. IN PFCB Fcb,
  68. IN PCCB Ccb,
  69. IN OUT PFILE_NAME_INFORMATION Buffer,
  70. IN OUT PULONG Length
  71. );
  72. VOID
  73. CdQueryNetworkInfo (
  74. IN PIRP_CONTEXT IrpContext,
  75. IN PFCB Fcb,
  76. IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
  77. IN OUT PULONG Length
  78. );
  79. #ifdef ALLOC_PRAGMA
  80. #pragma alloc_text(PAGE, CdCommonQueryInfo)
  81. #pragma alloc_text(PAGE, CdCommonSetInfo)
  82. #pragma alloc_text(PAGE, CdFastQueryBasicInfo)
  83. #pragma alloc_text(PAGE, CdFastQueryStdInfo)
  84. #pragma alloc_text(PAGE, CdFastQueryNetworkInfo)
  85. #pragma alloc_text(PAGE, CdQueryAlternateNameInfo)
  86. #pragma alloc_text(PAGE, CdQueryBasicInfo)
  87. #pragma alloc_text(PAGE, CdQueryEaInfo)
  88. #pragma alloc_text(PAGE, CdQueryInternalInfo)
  89. #pragma alloc_text(PAGE, CdQueryNameInfo)
  90. #pragma alloc_text(PAGE, CdQueryNetworkInfo)
  91. #pragma alloc_text(PAGE, CdQueryPositionInfo)
  92. #pragma alloc_text(PAGE, CdQueryStandardInfo)
  93. #endif
  94. NTSTATUS
  95. CdCommonQueryInfo (
  96. IN PIRP_CONTEXT IrpContext,
  97. IN PIRP Irp
  98. )
  99. /*++
  100. Routine Description:
  101. This is the common routine for query file information called by both the
  102. fsd and fsp threads.
  103. Arguments:
  104. Irp - Supplies the Irp to process.
  105. Return Value:
  106. NTSTATUS - The return status for this operation.
  107. --*/
  108. {
  109. NTSTATUS Status = STATUS_SUCCESS;
  110. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  111. ULONG Length;
  112. FILE_INFORMATION_CLASS FileInformationClass;
  113. PFILE_ALL_INFORMATION Buffer;
  114. TYPE_OF_OPEN TypeOfOpen;
  115. PFCB Fcb;
  116. PCCB Ccb;
  117. BOOLEAN ReleaseFcb = FALSE;
  118. PAGED_CODE();
  119. //
  120. // Reference our input parameters to make things easier
  121. //
  122. Length = IrpSp->Parameters.QueryFile.Length;
  123. FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
  124. Buffer = Irp->AssociatedIrp.SystemBuffer;
  125. //
  126. // Decode the file object
  127. //
  128. TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
  129. //
  130. // Use a try-finally to facilitate cleanup.
  131. //
  132. try {
  133. //
  134. // We only support query on file and directory handles.
  135. //
  136. switch (TypeOfOpen) {
  137. case UserDirectoryOpen :
  138. case UserFileOpen :
  139. //
  140. // Acquire shared access to this file. NOTE that this could be
  141. // a recursive acquire, if we already preacquired in
  142. // CdAcquireForCreateSection().
  143. //
  144. CdAcquireFileShared( IrpContext, Fcb );
  145. ReleaseFcb = TRUE;
  146. //
  147. // Make sure we have the correct sizes for a directory.
  148. //
  149. if (!FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED )) {
  150. ASSERT( TypeOfOpen == UserDirectoryOpen );
  151. CdCreateInternalStream( IrpContext, Fcb->Vcb, Fcb );
  152. }
  153. //
  154. // Make sure the Fcb is in a usable condition. This will raise
  155. // an error condition if the volume is unusable
  156. //
  157. CdVerifyFcbOperation( IrpContext, Fcb );
  158. //
  159. // Based on the information class we'll do different
  160. // actions. Each of hte procedures that we're calling fills
  161. // up the output buffer, if possible. They will raise the
  162. // status STATUS_BUFFER_OVERFLOW for an insufficient buffer.
  163. // This is considered a somewhat unusual case and is handled
  164. // more cleanly with the exception mechanism rather than
  165. // testing a return status value for each call.
  166. //
  167. switch (FileInformationClass) {
  168. case FileAllInformation:
  169. //
  170. // We don't allow this operation on a file opened by file Id.
  171. //
  172. if (FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
  173. Status = STATUS_INVALID_PARAMETER;
  174. break;
  175. }
  176. //
  177. // In this case go ahead and call the individual routines to
  178. // fill in the buffer. Only the name routine will
  179. // pointer to the output buffer and then call the
  180. // individual routines to fill in the buffer.
  181. //
  182. Length -= (sizeof( FILE_ACCESS_INFORMATION ) +
  183. sizeof( FILE_MODE_INFORMATION ) +
  184. sizeof( FILE_ALIGNMENT_INFORMATION ));
  185. CdQueryBasicInfo( IrpContext, Fcb, &Buffer->BasicInformation, &Length );
  186. CdQueryStandardInfo( IrpContext, Fcb, &Buffer->StandardInformation, &Length );
  187. CdQueryInternalInfo( IrpContext, Fcb, &Buffer->InternalInformation, &Length );
  188. CdQueryEaInfo( IrpContext, Fcb, &Buffer->EaInformation, &Length );
  189. CdQueryPositionInfo( IrpContext, IrpSp->FileObject, &Buffer->PositionInformation, &Length );
  190. Status = CdQueryNameInfo( IrpContext, IrpSp->FileObject, &Buffer->NameInformation, &Length );
  191. break;
  192. case FileBasicInformation:
  193. CdQueryBasicInfo( IrpContext, Fcb, (PFILE_BASIC_INFORMATION) Buffer, &Length );
  194. break;
  195. case FileStandardInformation:
  196. CdQueryStandardInfo( IrpContext, Fcb, (PFILE_STANDARD_INFORMATION) Buffer, &Length );
  197. break;
  198. case FileInternalInformation:
  199. CdQueryInternalInfo( IrpContext, Fcb, (PFILE_INTERNAL_INFORMATION) Buffer, &Length );
  200. break;
  201. case FileEaInformation:
  202. CdQueryEaInfo( IrpContext, Fcb, (PFILE_EA_INFORMATION) Buffer, &Length );
  203. break;
  204. case FilePositionInformation:
  205. CdQueryPositionInfo( IrpContext, IrpSp->FileObject, (PFILE_POSITION_INFORMATION) Buffer, &Length );
  206. break;
  207. case FileNameInformation:
  208. //
  209. // We don't allow this operation on a file opened by file Id.
  210. //
  211. if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
  212. Status = CdQueryNameInfo( IrpContext, IrpSp->FileObject, (PFILE_NAME_INFORMATION) Buffer, &Length );
  213. } else {
  214. Status = STATUS_INVALID_PARAMETER;
  215. }
  216. break;
  217. case FileAlternateNameInformation:
  218. if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
  219. Status = CdQueryAlternateNameInfo( IrpContext, Fcb, Ccb, (PFILE_NAME_INFORMATION) Buffer, &Length );
  220. } else {
  221. Status = STATUS_INVALID_PARAMETER;
  222. }
  223. break;
  224. case FileNetworkOpenInformation:
  225. CdQueryNetworkInfo( IrpContext, Fcb, (PFILE_NETWORK_OPEN_INFORMATION) Buffer, &Length );
  226. break;
  227. default :
  228. Status = STATUS_INVALID_PARAMETER;
  229. }
  230. break;
  231. default :
  232. Status = STATUS_INVALID_PARAMETER;
  233. }
  234. //
  235. // Set the information field to the number of bytes actually filled in
  236. // and then complete the request
  237. //
  238. Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length;
  239. } finally {
  240. //
  241. // Release the file.
  242. //
  243. if (ReleaseFcb) {
  244. CdReleaseFile( IrpContext, Fcb );
  245. }
  246. }
  247. //
  248. // Complete the request if we didn't raise.
  249. //
  250. CdCompleteRequest( IrpContext, Irp, Status );
  251. return Status;
  252. }
  253. NTSTATUS
  254. CdCommonSetInfo (
  255. IN PIRP_CONTEXT IrpContext,
  256. IN PIRP Irp
  257. )
  258. /*++
  259. Routine Description:
  260. This is the common routine for set file information called by both the
  261. fsd and fsp threads. We only support operations which set the file position.
  262. Arguments:
  263. Irp - Supplies the Irp to process.
  264. Return Value:
  265. NTSTATUS - The return status for this operation.
  266. --*/
  267. {
  268. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  269. TYPE_OF_OPEN TypeOfOpen;
  270. PFCB Fcb;
  271. PCCB Ccb;
  272. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  273. PFILE_POSITION_INFORMATION Buffer;
  274. PAGED_CODE();
  275. //
  276. // Decode the file object
  277. //
  278. TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
  279. //
  280. // We only support a SetPositionInformation on a user file.
  281. //
  282. if ((TypeOfOpen != UserFileOpen) ||
  283. (IrpSp->Parameters.QueryFile.FileInformationClass != FilePositionInformation)) {
  284. CdCompleteRequest( IrpContext, Irp, Status );
  285. return Status;
  286. }
  287. //
  288. // Acquire shared access to this file.
  289. //
  290. CdAcquireFileShared( IrpContext, Fcb );
  291. try {
  292. //
  293. // Make sure the Fcb is in a usable condition. This
  294. // will raise an error condition if the fcb is unusable
  295. //
  296. CdVerifyFcbOperation( IrpContext, Fcb );
  297. Buffer = Irp->AssociatedIrp.SystemBuffer;
  298. //
  299. // Check if the file does not use intermediate buffering. If it
  300. // does not use intermediate buffering then the new position we're
  301. // supplied must be aligned properly for the device
  302. //
  303. if (FlagOn( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ) &&
  304. ((Buffer->CurrentByteOffset.LowPart & IrpSp->DeviceObject->AlignmentRequirement) != 0)) {
  305. try_return( NOTHING );
  306. }
  307. //
  308. // The input parameter is fine so set the current byte offset and
  309. // complete the request
  310. //
  311. //
  312. // Lock the Fcb to provide synchronization.
  313. //
  314. CdLockFcb( IrpContext, Fcb );
  315. IrpSp->FileObject->CurrentByteOffset = Buffer->CurrentByteOffset;
  316. CdUnlockFcb( IrpContext, Fcb );
  317. Status = STATUS_SUCCESS;
  318. try_exit: NOTHING;
  319. } finally {
  320. CdReleaseFile( IrpContext, Fcb );
  321. }
  322. //
  323. // Complete the request if there was no raise.
  324. //
  325. CdCompleteRequest( IrpContext, Irp, Status );
  326. return Status;
  327. }
  328. BOOLEAN
  329. CdFastQueryBasicInfo (
  330. IN PFILE_OBJECT FileObject,
  331. IN BOOLEAN Wait,
  332. IN OUT PFILE_BASIC_INFORMATION Buffer,
  333. OUT PIO_STATUS_BLOCK IoStatus,
  334. IN PDEVICE_OBJECT DeviceObject
  335. )
  336. /*++
  337. Routine Description:
  338. This routine is for the fast query call for basic file information.
  339. Arguments:
  340. FileObject - Supplies the file object used in this operation
  341. Wait - Indicates if we are allowed to wait for the information
  342. Buffer - Supplies the output buffer to receive the basic information
  343. IoStatus - Receives the final status of the operation
  344. Return Value:
  345. BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
  346. needs to take the long route.
  347. --*/
  348. {
  349. BOOLEAN Result = FALSE;
  350. TYPE_OF_OPEN TypeOfOpen;
  351. PFCB Fcb;
  352. PAGED_CODE();
  353. ASSERT_FILE_OBJECT( FileObject );
  354. FsRtlEnterFileSystem();
  355. //
  356. // Decode the file object to find the type of open and the data
  357. // structures.
  358. //
  359. TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
  360. //
  361. // We only support this request on user file or directory objects.
  362. //
  363. if ((TypeOfOpen != UserFileOpen) &&
  364. ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED))) {
  365. FsRtlExitFileSystem();
  366. return FALSE;
  367. }
  368. //
  369. // Acquire the file shared to access the Fcb.
  370. //
  371. if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {
  372. FsRtlExitFileSystem();
  373. return FALSE;
  374. }
  375. //
  376. // Use a try-finally to facilitate cleanup.
  377. //
  378. try {
  379. //
  380. // Only deal with 'good' Fcb's.
  381. //
  382. if (CdVerifyFcbOperation( NULL, Fcb )) {
  383. //
  384. // Fill in the input buffer from the Fcb fields.
  385. //
  386. Buffer->CreationTime.QuadPart =
  387. Buffer->LastWriteTime.QuadPart =
  388. Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
  389. Buffer->LastAccessTime.QuadPart = 0;
  390. Buffer->FileAttributes = Fcb->FileAttributes;
  391. //
  392. // Update the IoStatus block with the size of this data.
  393. //
  394. IoStatus->Status = STATUS_SUCCESS;
  395. IoStatus->Information = sizeof( FILE_BASIC_INFORMATION );
  396. Result = TRUE;
  397. }
  398. } finally {
  399. ExReleaseResourceLite( Fcb->Resource );
  400. FsRtlExitFileSystem();
  401. }
  402. return Result;
  403. }
  404. BOOLEAN
  405. CdFastQueryStdInfo (
  406. IN PFILE_OBJECT FileObject,
  407. IN BOOLEAN Wait,
  408. IN OUT PFILE_STANDARD_INFORMATION Buffer,
  409. OUT PIO_STATUS_BLOCK IoStatus,
  410. IN PDEVICE_OBJECT DeviceObject
  411. )
  412. /*++
  413. Routine Description:
  414. This routine is for the fast query call for standard file information.
  415. Arguments:
  416. FileObject - Supplies the file object used in this operation
  417. Wait - Indicates if we are allowed to wait for the information
  418. Buffer - Supplies the output buffer to receive the basic information
  419. IoStatus - Receives the final status of the operation
  420. Return Value:
  421. BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
  422. needs to take the long route.
  423. --*/
  424. {
  425. BOOLEAN Result = FALSE;
  426. TYPE_OF_OPEN TypeOfOpen;
  427. PFCB Fcb;
  428. PAGED_CODE();
  429. ASSERT_FILE_OBJECT( FileObject );
  430. FsRtlEnterFileSystem();
  431. //
  432. // Decode the file object to find the type of open and the data
  433. // structures.
  434. //
  435. TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
  436. //
  437. // We only support this request on initialized user file or directory objects.
  438. //
  439. if ((TypeOfOpen != UserFileOpen) &&
  440. ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED ))) {
  441. FsRtlExitFileSystem();
  442. return FALSE;
  443. }
  444. //
  445. // Acquire the file shared to access the Fcb.
  446. //
  447. if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {
  448. FsRtlExitFileSystem();
  449. return FALSE;
  450. }
  451. //
  452. // Use a try-finally to facilitate cleanup.
  453. //
  454. try {
  455. //
  456. // Only deal with 'good' Fcb's.
  457. //
  458. if (CdVerifyFcbOperation( NULL, Fcb )) {
  459. //
  460. // Check whether this is a directory.
  461. //
  462. if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
  463. Buffer->AllocationSize.QuadPart =
  464. Buffer->EndOfFile.QuadPart = 0;
  465. Buffer->Directory = TRUE;
  466. } else {
  467. Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
  468. Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
  469. Buffer->Directory = FALSE;
  470. }
  471. Buffer->NumberOfLinks = 1;
  472. Buffer->DeletePending = FALSE;
  473. //
  474. // Update the IoStatus block with the size of this data.
  475. //
  476. IoStatus->Status = STATUS_SUCCESS;
  477. IoStatus->Information = sizeof( FILE_STANDARD_INFORMATION );
  478. Result = TRUE;
  479. }
  480. } finally {
  481. ExReleaseResourceLite( Fcb->Resource );
  482. FsRtlExitFileSystem();
  483. }
  484. return Result;
  485. }
  486. BOOLEAN
  487. CdFastQueryNetworkInfo (
  488. IN PFILE_OBJECT FileObject,
  489. IN BOOLEAN Wait,
  490. OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
  491. OUT PIO_STATUS_BLOCK IoStatus,
  492. IN PDEVICE_OBJECT DeviceObject
  493. )
  494. /*++
  495. Routine Description:
  496. This routine is for the fast query call for network file information.
  497. Arguments:
  498. FileObject - Supplies the file object used in this operation
  499. Wait - Indicates if we are allowed to wait for the information
  500. Buffer - Supplies the output buffer to receive the basic information
  501. IoStatus - Receives the final status of the operation
  502. Return Value:
  503. BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
  504. needs to take the long route.
  505. --*/
  506. {
  507. BOOLEAN Result = FALSE;
  508. TYPE_OF_OPEN TypeOfOpen;
  509. PFCB Fcb;
  510. PAGED_CODE();
  511. ASSERT_FILE_OBJECT( FileObject );
  512. FsRtlEnterFileSystem();
  513. //
  514. // Decode the file object to find the type of open and the data
  515. // structures.
  516. //
  517. TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
  518. //
  519. // We only support this request on user file or directory objects.
  520. //
  521. if ((TypeOfOpen != UserFileOpen) &&
  522. ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED))) {
  523. FsRtlExitFileSystem();
  524. return FALSE;
  525. }
  526. //
  527. // Acquire the file shared to access the Fcb.
  528. //
  529. if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {
  530. FsRtlExitFileSystem();
  531. return FALSE;
  532. }
  533. //
  534. // Use a try-finally to facilitate cleanup.
  535. //
  536. try {
  537. //
  538. // Only deal with 'good' Fcb's.
  539. //
  540. if (CdVerifyFcbOperation( NULL, Fcb )) {
  541. //
  542. // Fill in the input buffer from the Fcb fields.
  543. //
  544. Buffer->CreationTime.QuadPart =
  545. Buffer->LastWriteTime.QuadPart =
  546. Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
  547. Buffer->LastAccessTime.QuadPart = 0;
  548. Buffer->FileAttributes = Fcb->FileAttributes;
  549. //
  550. // Check whether this is a directory.
  551. //
  552. if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
  553. Buffer->AllocationSize.QuadPart =
  554. Buffer->EndOfFile.QuadPart = 0;
  555. } else {
  556. Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
  557. Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
  558. }
  559. //
  560. // Update the IoStatus block with the size of this data.
  561. //
  562. IoStatus->Status = STATUS_SUCCESS;
  563. IoStatus->Information = sizeof( FILE_NETWORK_OPEN_INFORMATION );
  564. Result = TRUE;
  565. }
  566. } finally {
  567. ExReleaseResourceLite( Fcb->Resource );
  568. FsRtlExitFileSystem();
  569. }
  570. return Result;
  571. }
  572. //
  573. // Local support routine
  574. //
  575. VOID
  576. CdQueryBasicInfo (
  577. IN PIRP_CONTEXT IrpContext,
  578. IN PFCB Fcb,
  579. IN OUT PFILE_BASIC_INFORMATION Buffer,
  580. IN OUT PULONG Length
  581. )
  582. /*++
  583. Description:
  584. This routine performs the query basic information function for Cdfs
  585. Arguments:
  586. Fcb - Supplies the Fcb being queried, it has been verified
  587. Buffer - Supplies a pointer to the buffer where the information is to
  588. be returned
  589. Length - Supplies the length of the buffer in bytes, and receives the
  590. remaining bytes free in the buffer upon return.
  591. Return Value:
  592. None
  593. --*/
  594. {
  595. PAGED_CODE();
  596. //
  597. // We only support creation, last modify and last write times on Cdfs.
  598. //
  599. Buffer->LastWriteTime.QuadPart =
  600. Buffer->CreationTime.QuadPart =
  601. Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
  602. Buffer->LastAccessTime.QuadPart = 0;
  603. Buffer->FileAttributes = Fcb->FileAttributes;
  604. //
  605. // Update the length and status output variables
  606. //
  607. *Length -= sizeof( FILE_BASIC_INFORMATION );
  608. return;
  609. }
  610. //
  611. // Local support routine
  612. //
  613. VOID
  614. CdQueryStandardInfo (
  615. IN PIRP_CONTEXT IrpContext,
  616. IN PFCB Fcb,
  617. IN OUT PFILE_STANDARD_INFORMATION Buffer,
  618. IN OUT PULONG Length
  619. )
  620. /*++
  621. Routine Description:
  622. This routine performs the query standard information function for cdfs.
  623. Arguments:
  624. Fcb - Supplies the Fcb being queried, it has been verified
  625. Buffer - Supplies a pointer to the buffer where the information is to
  626. be returned
  627. Length - Supplies the length of the buffer in bytes, and receives the
  628. remaining bytes free in the buffer upon return.
  629. Return Value:
  630. None
  631. --*/
  632. {
  633. PAGED_CODE();
  634. //
  635. // There is only one link and delete is never pending on a Cdrom file.
  636. //
  637. Buffer->NumberOfLinks = 1;
  638. Buffer->DeletePending = FALSE;
  639. //
  640. // We get the sizes from the header. Return a size of zero
  641. // for all directories.
  642. //
  643. if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
  644. Buffer->AllocationSize.QuadPart =
  645. Buffer->EndOfFile.QuadPart = 0;
  646. Buffer->Directory = TRUE;
  647. } else {
  648. Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
  649. Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
  650. Buffer->Directory = FALSE;
  651. }
  652. //
  653. // Update the length and status output variables
  654. //
  655. *Length -= sizeof( FILE_STANDARD_INFORMATION );
  656. return;
  657. }
  658. //
  659. // Local support routine
  660. //
  661. VOID
  662. CdQueryInternalInfo (
  663. IN PIRP_CONTEXT IrpContext,
  664. IN PFCB Fcb,
  665. IN OUT PFILE_INTERNAL_INFORMATION Buffer,
  666. IN OUT PULONG Length
  667. )
  668. /*++
  669. Routine Description:
  670. This routine performs the query internal information function for cdfs.
  671. Arguments:
  672. Fcb - Supplies the Fcb being queried, it has been verified
  673. Buffer - Supplies a pointer to the buffer where the information is to
  674. be returned
  675. Length - Supplies the length of the buffer in bytes, and receives the
  676. remaining bytes free in the buffer upon return.
  677. Return Value:
  678. None
  679. --*/
  680. {
  681. PAGED_CODE();
  682. //
  683. // Index number is the file Id number in the Fcb.
  684. //
  685. Buffer->IndexNumber = Fcb->FileId;
  686. *Length -= sizeof( FILE_INTERNAL_INFORMATION );
  687. return;
  688. }
  689. //
  690. // Local support routine
  691. //
  692. VOID
  693. CdQueryEaInfo (
  694. IN PIRP_CONTEXT IrpContext,
  695. IN PFCB Fcb,
  696. IN OUT PFILE_EA_INFORMATION Buffer,
  697. IN OUT PULONG Length
  698. )
  699. /*++
  700. Routine Description:
  701. This routine performs the query Ea information function for cdfs.
  702. Arguments:
  703. Fcb - Supplies the Fcb being queried, it has been verified
  704. Buffer - Supplies a pointer to the buffer where the information is to
  705. be returned
  706. Length - Supplies the length of the buffer in bytes, and receives the
  707. remaining bytes free in the buffer upon return.
  708. Return Value:
  709. None
  710. --*/
  711. {
  712. PAGED_CODE();
  713. //
  714. // No Ea's on Cdfs volumes.
  715. //
  716. Buffer->EaSize = 0;
  717. *Length -= sizeof( FILE_EA_INFORMATION );
  718. return;
  719. }
  720. //
  721. // Local support routine
  722. //
  723. VOID
  724. CdQueryPositionInfo (
  725. IN PIRP_CONTEXT IrpContext,
  726. IN PFILE_OBJECT FileObject,
  727. IN OUT PFILE_POSITION_INFORMATION Buffer,
  728. IN OUT PULONG Length
  729. )
  730. /*++
  731. Routine Description:
  732. This routine performs the query position information function for cdfs.
  733. Arguments:
  734. FileObject - Supplies the File object being queried
  735. Buffer - Supplies a pointer to the buffer where the information is to
  736. be returned
  737. Length - Supplies the length of the buffer in bytes, and receives the
  738. remaining bytes free in the buffer upon return.
  739. Return Value:
  740. None
  741. --*/
  742. {
  743. PAGED_CODE();
  744. //
  745. // Get the current position found in the file object.
  746. //
  747. Buffer->CurrentByteOffset = FileObject->CurrentByteOffset;
  748. //
  749. // Update the length and status output variables
  750. //
  751. *Length -= sizeof( FILE_POSITION_INFORMATION );
  752. return;
  753. }
  754. //
  755. // Local support routine
  756. //
  757. NTSTATUS
  758. CdQueryNameInfo (
  759. IN PIRP_CONTEXT IrpContext,
  760. IN PFILE_OBJECT FileObject,
  761. IN OUT PFILE_NAME_INFORMATION Buffer,
  762. IN OUT PULONG Length
  763. )
  764. /*++
  765. Routine Description:
  766. This routine performs the query name information function for cdfs.
  767. Arguments:
  768. FileObject - Supplies the file object containing the name.
  769. Buffer - Supplies a pointer to the buffer where the information is to
  770. be returned
  771. Length - Supplies the length of the buffer in bytes, and receives the
  772. remaining bytes free in the buffer upon return.
  773. Return Value:
  774. NTSTATUS - STATUS_BUFFER_OVERFLOW if the entire name can't be copied.
  775. --*/
  776. {
  777. NTSTATUS Status = STATUS_SUCCESS;
  778. ULONG LengthToCopy;
  779. PAGED_CODE();
  780. ASSERT(*Length >= sizeof(ULONG));
  781. //
  782. // Simply copy the name in the file object to the user's buffer.
  783. //
  784. //
  785. // Place the size of the filename in the user's buffer and reduce the remaining
  786. // size to match.
  787. //
  788. Buffer->FileNameLength = LengthToCopy = FileObject->FileName.Length;
  789. *Length -= sizeof(ULONG);
  790. if (LengthToCopy > *Length) {
  791. LengthToCopy = *Length;
  792. Status = STATUS_BUFFER_OVERFLOW;
  793. }
  794. RtlCopyMemory( Buffer->FileName, FileObject->FileName.Buffer, LengthToCopy );
  795. //
  796. // Reduce the available bytes by the amount stored into this buffer. In the overflow
  797. // case, this simply drops to zero. The returned filenamelength will indicate to the
  798. // caller how much space is required.
  799. //
  800. *Length -= LengthToCopy;
  801. return Status;
  802. }
  803. //
  804. // Local support routine
  805. //
  806. NTSTATUS
  807. CdQueryAlternateNameInfo (
  808. IN PIRP_CONTEXT IrpContext,
  809. IN PFCB Fcb,
  810. IN PCCB Ccb,
  811. IN OUT PFILE_NAME_INFORMATION Buffer,
  812. IN OUT PULONG Length
  813. )
  814. /*++
  815. Routine Description:
  816. This routine performs the query alternate name information function.
  817. We lookup the dirent for this file and then check if there is a
  818. short name.
  819. Arguments:
  820. Fcb - Supplies the Fcb being queried, it has been verified.
  821. Ccb - Ccb for this open handle.
  822. Buffer - Supplies a pointer to the buffer where the information is to
  823. be returned.
  824. Length - Supplies the length of the buffer in bytes, and receives the
  825. remaining bytes free in the buffer upon return.
  826. Return Value:
  827. NTSTATUS - STATUS_SUCCESS if the whole name would fit into the user buffer,
  828. STATUS_OBJECT_NAME_NOT_FOUND if we can't return the name,
  829. STATUS_BUFFER_OVERFLOW otherwise.
  830. --*/
  831. {
  832. NTSTATUS Status = STATUS_SUCCESS;
  833. DIRENT_ENUM_CONTEXT DirContext;
  834. DIRENT Dirent;
  835. PUNICODE_STRING NameToUse;
  836. ULONG DirentOffset;
  837. COMPOUND_PATH_ENTRY CompoundPathEntry;
  838. FILE_ENUM_CONTEXT FileContext;
  839. PFCB ParentFcb;
  840. BOOLEAN ReleaseParentFcb = FALSE;
  841. BOOLEAN CleanupFileLookup = FALSE;
  842. BOOLEAN CleanupDirectoryLookup = FALSE;
  843. WCHAR ShortNameBuffer[ BYTE_COUNT_8_DOT_3 / 2 ];
  844. USHORT ShortNameLength;
  845. PAGED_CODE();
  846. //
  847. // Initialize the buffer length to zero.
  848. //
  849. Buffer->FileNameLength = 0;
  850. //
  851. // If this is the root or this file was opened using a version number then
  852. // there is no short name.
  853. //
  854. if ((Fcb == Fcb->Vcb->RootIndexFcb) ||
  855. FlagOn( Ccb->Flags, CCB_FLAG_OPEN_WITH_VERSION)) {
  856. return STATUS_OBJECT_NAME_NOT_FOUND;
  857. }
  858. //
  859. // Use a try-finally to cleanup the structures.
  860. //
  861. try {
  862. ParentFcb = Fcb->ParentFcb;
  863. CdAcquireFileShared( IrpContext, ParentFcb );
  864. ReleaseParentFcb = TRUE;
  865. //
  866. // Do an unsafe test to see if we need to create a file object.
  867. //
  868. if (ParentFcb->FileObject == NULL) {
  869. CdCreateInternalStream( IrpContext, ParentFcb->Vcb, ParentFcb );
  870. }
  871. if (CdFidIsDirectory( Fcb->FileId)) {
  872. //
  873. // Fcb is for a directory, so we need to dig the dirent from the parent. In
  874. // order to do this we need to get the name of the directory from its pathtable
  875. // entry and then search in the parent for a matching dirent.
  876. //
  877. // This could be optimized somewhat.
  878. //
  879. CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry );
  880. CdInitializeFileContext( IrpContext, &FileContext );
  881. CleanupDirectoryLookup = TRUE;
  882. CdLookupPathEntry( IrpContext,
  883. CdQueryFidPathTableOffset( Fcb->FileId ),
  884. Fcb->Ordinal,
  885. FALSE,
  886. &CompoundPathEntry );
  887. CdUpdatePathEntryName( IrpContext, &CompoundPathEntry.PathEntry, TRUE );
  888. if (!CdFindDirectory( IrpContext,
  889. ParentFcb,
  890. &CompoundPathEntry.PathEntry.CdCaseDirName,
  891. TRUE,
  892. &FileContext )) {
  893. //
  894. // If we failed to find the child directory by name in the parent
  895. // something is quite wrong with this disc.
  896. //
  897. CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
  898. }
  899. NameToUse = &FileContext.InitialDirent->Dirent.CdCaseFileName.FileName;
  900. DirentOffset = FileContext.InitialDirent->Dirent.DirentOffset;
  901. } else {
  902. //
  903. // Initialize the search dirent structures.
  904. //
  905. CdInitializeDirContext( IrpContext, &DirContext );
  906. CdInitializeDirent( IrpContext, &Dirent );
  907. CleanupFileLookup = TRUE;
  908. CdLookupDirent( IrpContext,
  909. ParentFcb,
  910. CdQueryFidDirentOffset( Fcb->FileId ),
  911. &DirContext );
  912. CdUpdateDirentFromRawDirent( IrpContext,
  913. ParentFcb,
  914. &DirContext,
  915. &Dirent );
  916. //
  917. // Now update the dirent name.
  918. //
  919. CdUpdateDirentName( IrpContext, &Dirent, TRUE );
  920. NameToUse = &Dirent.CdCaseFileName.FileName;
  921. DirentOffset = Dirent.DirentOffset;
  922. }
  923. //
  924. // If the name is 8.3 then fail this request.
  925. //
  926. if (CdIs8dot3Name( IrpContext,
  927. *NameToUse )) {
  928. try_return( Status = STATUS_OBJECT_NAME_NOT_FOUND );
  929. }
  930. CdGenerate8dot3Name( IrpContext,
  931. NameToUse,
  932. DirentOffset,
  933. ShortNameBuffer,
  934. &ShortNameLength );
  935. //
  936. // We now have the short name. We have left it in Unicode form so copy it directly.
  937. //
  938. Buffer->FileNameLength = ShortNameLength;
  939. if (Buffer->FileNameLength + sizeof( ULONG ) > *Length) {
  940. Buffer->FileNameLength = *Length - sizeof( ULONG );
  941. Status = STATUS_BUFFER_OVERFLOW;
  942. }
  943. RtlCopyMemory( Buffer->FileName, ShortNameBuffer, Buffer->FileNameLength );
  944. try_exit: NOTHING;
  945. } finally {
  946. if (CleanupFileLookup) {
  947. CdCleanupDirContext( IrpContext, &DirContext );
  948. CdCleanupDirent( IrpContext, &Dirent );
  949. } else if (CleanupDirectoryLookup) {
  950. CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry );
  951. CdCleanupFileContext( IrpContext, &FileContext );
  952. }
  953. if (ReleaseParentFcb) {
  954. CdReleaseFile( IrpContext, ParentFcb );
  955. }
  956. }
  957. //
  958. // Reduce the available bytes by the amount stored into this buffer.
  959. //
  960. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  961. *Length -= sizeof( ULONG ) + Buffer->FileNameLength;
  962. }
  963. return Status;
  964. }
  965. //
  966. // Local support routine
  967. //
  968. VOID
  969. CdQueryNetworkInfo (
  970. IN PIRP_CONTEXT IrpContext,
  971. IN PFCB Fcb,
  972. IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
  973. IN OUT PULONG Length
  974. )
  975. /*++
  976. Description:
  977. This routine performs the query network open information function for Cdfs
  978. Arguments:
  979. Fcb - Supplies the Fcb being queried, it has been verified
  980. Buffer - Supplies a pointer to the buffer where the information is to
  981. be returned
  982. Length - Supplies the length of the buffer in bytes, and receives the
  983. remaining bytes free in the buffer upon return.
  984. Return Value:
  985. None
  986. --*/
  987. {
  988. PAGED_CODE();
  989. //
  990. // We only support creation, last modify and last write times on Cdfs.
  991. //
  992. Buffer->LastWriteTime.QuadPart =
  993. Buffer->CreationTime.QuadPart =
  994. Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
  995. Buffer->LastAccessTime.QuadPart = 0;
  996. Buffer->FileAttributes = Fcb->FileAttributes;
  997. //
  998. // We get the sizes from the header. Return a size of zero
  999. // for all directories.
  1000. //
  1001. if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
  1002. Buffer->AllocationSize.QuadPart =
  1003. Buffer->EndOfFile.QuadPart = 0;
  1004. } else {
  1005. Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
  1006. Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
  1007. }
  1008. //
  1009. // Update the length and status output variables
  1010. //
  1011. *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION );
  1012. return;
  1013. }