Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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