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.

1078 lines
15 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. fatdent.hxx
  5. Abstract:
  6. This class models a FAT directory entry.
  7. --*/
  8. #ifndef MAKEULONG
  9. #define MAKEULONG(a, b) ((ULONG)(((USHORT)(a)) | ((ULONG)((USHORT)(b))) << 16))
  10. #define LOUSHORT(l) ((USHORT)(l & 0xFFFF))
  11. #define HIUSHORT(l) ((USHORT)(((l) >> 16) & 0xFFFF))
  12. #endif // !MAKEULONG
  13. #if !defined(FAT_DIRENT_DEFN)
  14. #define FAT_DIRENT_DEFN
  15. #if defined ( _AUTOCHECK_ ) || defined( _EFICHECK_ )
  16. #define UFAT_EXPORT
  17. #elif defined ( _UFAT_MEMBER_ )
  18. #define UFAT_EXPORT __declspec(dllexport)
  19. #else
  20. #define UFAT_EXPORT __declspec(dllimport)
  21. #endif
  22. DECLARE_CLASS( FAT_DIRENT );
  23. DECLARE_CLASS( WSTRING );
  24. DECLARE_CLASS( WSTRING );
  25. DECLARE_CLASS( TIMEINFO );
  26. typedef struct _SHORT_FAT_DIRENT {
  27. UCHAR Name[11];
  28. UCHAR Attributes[1];
  29. UCHAR NtByte[1];
  30. UCHAR CreationMSec[1]; // actually count of 10msec's
  31. UCHAR CreationTime[2]; // two-second resolution
  32. UCHAR CreationDate[2];
  33. UCHAR LastAccessDate[2];
  34. UCHAR EaHandle[2];
  35. UCHAR LastWriteTime[2];
  36. UCHAR LastWriteDate[2];
  37. UCHAR FirstCluster[2];
  38. UCHAR Size[4];
  39. };
  40. DEFINE_TYPE( _SHORT_FAT_DIRENT, SHORT_FAT_DIRENT );
  41. typedef struct _LONG_FAT_DIRENT {
  42. UCHAR Ordinal[1];
  43. UCHAR Name1[10];
  44. UCHAR Attribute[1];
  45. UCHAR Type[1];
  46. UCHAR Checksum[1];
  47. UCHAR Name2[12];
  48. UCHAR FirstCluster[2];
  49. UCHAR Name3[4];
  50. };
  51. DEFINE_TYPE( _LONG_FAT_DIRENT, LONG_FAT_DIRENT );
  52. #define LONG_DIRENT_TYPE_NAME 0
  53. #define LONG_DIRENT_TYPE_CLASS 1
  54. class FAT_DIRENT : public OBJECT {
  55. public:
  56. UFAT_EXPORT
  57. DECLARE_CONSTRUCTOR( FAT_DIRENT );
  58. VIRTUAL
  59. UFAT_EXPORT
  60. ~FAT_DIRENT(
  61. );
  62. NONVIRTUAL
  63. UFAT_EXPORT
  64. BOOLEAN
  65. Initialize(
  66. IN OUT PVOID Dirent
  67. );
  68. NONVIRTUAL
  69. UFAT_EXPORT
  70. BOOLEAN
  71. Initialize(
  72. IN OUT PVOID Dirent,
  73. IN UCHAR FatType
  74. );
  75. NONVIRTUAL
  76. VOID
  77. Clear(
  78. );
  79. NONVIRTUAL
  80. UFAT_EXPORT
  81. BOOLEAN
  82. QueryName(
  83. OUT PWSTRING Name
  84. ) CONST;
  85. NONVIRTUAL
  86. BOOLEAN
  87. SetName(
  88. IN PCWSTRING Name
  89. );
  90. NONVIRTUAL
  91. BOOLEAN
  92. IsValidName(
  93. ) CONST;
  94. NONVIRTUAL
  95. BOOLEAN
  96. IsDot(
  97. ) CONST;
  98. NONVIRTUAL
  99. BOOLEAN
  100. IsDotDot(
  101. ) CONST;
  102. NONVIRTUAL
  103. BYTE
  104. QueryAttributeByte(
  105. ) CONST;
  106. NONVIRTUAL
  107. UFAT_EXPORT
  108. BOOLEAN
  109. IsValidLastWriteTime(
  110. ) CONST;
  111. NONVIRTUAL
  112. UFAT_EXPORT
  113. BOOLEAN
  114. QueryLastWriteTime(
  115. OUT LARGE_INTEGER *TimeStamp
  116. ) CONST;
  117. NONVIRTUAL
  118. BOOLEAN
  119. SetLastWriteTime(
  120. );
  121. NONVIRTUAL
  122. UFAT_EXPORT
  123. BOOLEAN
  124. IsValidCreationTime(
  125. ) CONST;
  126. NONVIRTUAL
  127. UFAT_EXPORT
  128. BOOLEAN
  129. QueryCreationTime(
  130. OUT LARGE_INTEGER *TimeStamp
  131. ) CONST;
  132. NONVIRTUAL
  133. BOOLEAN
  134. SetCreationTime(
  135. );
  136. NONVIRTUAL
  137. UFAT_EXPORT
  138. BOOLEAN
  139. IsValidLastAccessTime(
  140. ) CONST;
  141. NONVIRTUAL
  142. UFAT_EXPORT
  143. BOOLEAN
  144. QueryLastAccessTime(
  145. OUT LARGE_INTEGER *TimeStamp
  146. ) CONST;
  147. NONVIRTUAL
  148. BOOLEAN
  149. SetLastAccessTime(
  150. );
  151. NONVIRTUAL
  152. ULONG
  153. QueryStartingCluster(
  154. ) CONST;
  155. NONVIRTUAL
  156. VOID
  157. SetStartingCluster(
  158. IN ULONG NewStartingCluster
  159. );
  160. NONVIRTUAL
  161. ULONG
  162. QueryFileSize(
  163. ) CONST;
  164. NONVIRTUAL
  165. VOID
  166. SetFileSize(
  167. IN ULONG NewFileSize
  168. );
  169. NONVIRTUAL
  170. USHORT
  171. QueryEaHandle(
  172. ) CONST;
  173. NONVIRTUAL
  174. VOID
  175. SetEaHandle(
  176. IN USHORT NewHandle
  177. );
  178. NONVIRTUAL
  179. BOOLEAN
  180. IsEndOfDirectory(
  181. ) CONST;
  182. NONVIRTUAL
  183. VOID
  184. SetEndOfDirectory(
  185. );
  186. NONVIRTUAL
  187. BOOLEAN
  188. IsErased(
  189. ) CONST;
  190. NONVIRTUAL
  191. VOID
  192. SetErased(
  193. );
  194. NONVIRTUAL
  195. BOOLEAN
  196. IsHidden(
  197. ) CONST;
  198. NONVIRTUAL
  199. BOOLEAN
  200. IsSystem(
  201. ) CONST;
  202. NONVIRTUAL
  203. BOOLEAN
  204. IsVolumeLabel(
  205. ) CONST;
  206. NONVIRTUAL
  207. VOID
  208. SetVolumeLabel(
  209. );
  210. NONVIRTUAL
  211. BOOLEAN
  212. IsDirectory(
  213. ) CONST;
  214. NONVIRTUAL
  215. VOID
  216. SetDirectory(
  217. );
  218. NONVIRTUAL
  219. VOID
  220. ResetDirectory(
  221. );
  222. NONVIRTUAL
  223. UCHAR
  224. QueryChecksum(
  225. ) CONST;
  226. NONVIRTUAL
  227. BOOLEAN
  228. Is8LowerCase(
  229. ) CONST;
  230. NONVIRTUAL
  231. BOOLEAN
  232. Is3LowerCase(
  233. ) CONST;
  234. NONVIRTUAL
  235. BOOLEAN
  236. IsLongEntry(
  237. ) CONST;
  238. NONVIRTUAL
  239. BOOLEAN
  240. IsLongNameEntry(
  241. ) CONST;
  242. NONVIRTUAL
  243. BOOLEAN
  244. QueryLongOrdinal(
  245. ) CONST;
  246. NONVIRTUAL
  247. BOOLEAN
  248. IsLastLongEntry(
  249. ) CONST;
  250. NONVIRTUAL
  251. BOOLEAN
  252. IsWellTerminatedLongNameEntry(
  253. ) CONST;
  254. NONVIRTUAL
  255. BOOLEAN
  256. QueryLongNameComponent(
  257. OUT PWSTRING NameComponent
  258. ) CONST;
  259. NONVIRTUAL
  260. BOOLEAN
  261. NameHasTilde(
  262. ) CONST;
  263. NONVIRTUAL
  264. BOOLEAN
  265. NameHasExtendedChars(
  266. ) CONST;
  267. private:
  268. NONVIRTUAL
  269. BOOLEAN
  270. TimeStampsAreValid(
  271. USHORT t,
  272. USHORT d
  273. ) CONST;
  274. NONVIRTUAL
  275. VOID
  276. Construct(
  277. );
  278. NONVIRTUAL
  279. VOID
  280. Destroy(
  281. );
  282. PUCHAR _dirent;
  283. UCHAR _FatType;
  284. };
  285. INLINE
  286. VOID
  287. FAT_DIRENT::Clear(
  288. )
  289. /*++
  290. Routine Description:
  291. This routine zeros out the directory entry.
  292. Arguments:
  293. None.
  294. Return Value:
  295. None.
  296. --*/
  297. {
  298. memset(_dirent, 0, 32);
  299. }
  300. INLINE
  301. BOOLEAN
  302. FAT_DIRENT::IsDot(
  303. ) CONST
  304. /*++
  305. Routine Description:
  306. This routine computes whether or not the directory entry is the "."
  307. entry.
  308. Arguments:
  309. None.
  310. Return Value:
  311. FALSE - The entry is not the "." entry.
  312. TRUE - The entry is the "." entry.
  313. --*/
  314. {
  315. return !memcmp(_dirent, ". ", 11);
  316. }
  317. INLINE
  318. BOOLEAN
  319. FAT_DIRENT::IsDotDot(
  320. ) CONST
  321. /*++
  322. Routine Description:
  323. This routine computes whether or not the directory entry is the ".."
  324. entry.
  325. Arguments:
  326. None.
  327. Return Value:
  328. FALSE - The entry is not the ".." entry.
  329. TRUE - The entry is the ".." entry.
  330. --*/
  331. {
  332. return !memcmp(_dirent, ".. ", 11);
  333. }
  334. INLINE
  335. ULONG
  336. FAT_DIRENT::QueryStartingCluster(
  337. ) CONST
  338. /*++
  339. Routine Description:
  340. This routine computes the starting cluster number of the directory entry.
  341. Arguments:
  342. None.
  343. Return Value:
  344. The starting cluster number of the directory entry.
  345. --*/
  346. {
  347. DebugAssert(_dirent);
  348. ULONG dwSCN;
  349. if ( FAT_TYPE_FAT32 == _FatType )
  350. dwSCN = MAKEULONG( (*((PUSHORT) &_dirent[26])), (*((PUSHORT) &_dirent[20])));
  351. else
  352. dwSCN = *((PUSHORT) &_dirent[26]);
  353. return dwSCN;
  354. }
  355. INLINE
  356. VOID
  357. FAT_DIRENT::SetStartingCluster(
  358. IN ULONG NewStartingCluster
  359. )
  360. /*++
  361. Routine Description:
  362. This routine sets the starting cluster number for the directory entry.
  363. Arguments:
  364. NewStartingCluster - Supplies the starting cluster number for the
  365. directory entry.
  366. Return Value:
  367. None.
  368. --*/
  369. {
  370. DebugAssert(_dirent);
  371. if ( FAT_TYPE_FAT32 == _FatType )
  372. *((PUSHORT) &_dirent[20]) = HIUSHORT( NewStartingCluster );
  373. *((PUSHORT) &_dirent[26]) = LOUSHORT( NewStartingCluster );
  374. }
  375. INLINE
  376. ULONG
  377. FAT_DIRENT::QueryFileSize(
  378. ) CONST
  379. /*++
  380. Routine Description:
  381. This routine returns the number of bytes in the file.
  382. Arguments:
  383. None.
  384. Return Value:
  385. The number of bytes in the file.
  386. --*/
  387. {
  388. DebugAssert(_dirent);
  389. return *((PULONG) &_dirent[28]);
  390. }
  391. INLINE
  392. VOID
  393. FAT_DIRENT::SetFileSize(
  394. IN ULONG NewFileSize
  395. )
  396. /*++
  397. Routine Description:
  398. This routine sets the file size in the directory entry.
  399. Arguments:
  400. NewFileSize - Supplies the new file size.
  401. Return Value:
  402. None.
  403. --*/
  404. {
  405. DebugAssert(_dirent);
  406. *((PULONG) &_dirent[28]) = NewFileSize;
  407. }
  408. INLINE
  409. USHORT
  410. FAT_DIRENT::QueryEaHandle(
  411. ) CONST
  412. /*++
  413. Routine Description:
  414. This routine returns the EA handle for the file.
  415. Arguments:
  416. None.
  417. Return Value:
  418. The EA handle for the file.
  419. --*/
  420. {
  421. DebugAssert(_dirent);
  422. if ( FAT_TYPE_FAT32 == _FatType )
  423. return ( 0 );
  424. else
  425. return *((PUSHORT) &_dirent[20]);
  426. }
  427. INLINE
  428. VOID
  429. FAT_DIRENT::SetEaHandle(
  430. IN USHORT NewHandle
  431. )
  432. /*++
  433. Routine Description:
  434. This routine sets the EA handle for the file.
  435. Arguments:
  436. NewHandle - Supplies the EA handle for the file.
  437. Return Value:
  438. None.
  439. --*/
  440. {
  441. DebugAssert(_dirent);
  442. *((PUSHORT) &_dirent[20]) = NewHandle;
  443. }
  444. INLINE
  445. BOOLEAN
  446. FAT_DIRENT::IsEndOfDirectory(
  447. ) CONST
  448. /*++
  449. Routine Description:
  450. This routine computes whether or not this directory entry marks
  451. the end of the directory.
  452. Arguments:
  453. None.
  454. Return Value:
  455. FALSE - This entry does not mark the end of the directory.
  456. TRUE - This entry marks the end of the directory.
  457. --*/
  458. {
  459. DebugAssert(_dirent);
  460. return _dirent[0] ? FALSE : TRUE;
  461. }
  462. INLINE
  463. VOID
  464. FAT_DIRENT::SetEndOfDirectory(
  465. )
  466. /*++
  467. Routine Description:
  468. This routine sets this directory entry marks to the end of the
  469. directory.
  470. Arguments:
  471. None.
  472. Return Value:
  473. None.
  474. --*/
  475. {
  476. DebugAssert(_dirent);
  477. _dirent[0] = 0;
  478. }
  479. INLINE
  480. BOOLEAN
  481. FAT_DIRENT::IsErased(
  482. ) CONST
  483. /*++
  484. Routine Description:
  485. This routine computes whether or not the directory entry is erased or not.
  486. Arguments:
  487. None.
  488. Return Value:
  489. FALSE - The directory entry is not erased.
  490. TRUE - The directory entry is erased.
  491. --*/
  492. {
  493. DebugAssert(_dirent);
  494. return _dirent[0] == 0xE5 ? TRUE : FALSE;
  495. }
  496. INLINE
  497. VOID
  498. FAT_DIRENT::SetErased(
  499. )
  500. /*++
  501. Routine Description:
  502. This routine marks the directory entry as erased.
  503. Arguments:
  504. None.
  505. Return Value:
  506. None.
  507. --*/
  508. {
  509. DebugAssert(_dirent);
  510. _dirent[0] = 0xE5;
  511. }
  512. INLINE
  513. BOOLEAN
  514. FAT_DIRENT::IsHidden(
  515. ) CONST
  516. /*++
  517. Routine Description:
  518. This routine computes whether or not the file is hidden.
  519. Arguments:
  520. None.
  521. Return Value:
  522. FALSE - The file is not hidden.
  523. TRUE - The file is hidden.
  524. --*/
  525. {
  526. DebugAssert(_dirent);
  527. return _dirent[11]&0x02 ? TRUE : FALSE;
  528. }
  529. INLINE
  530. BOOLEAN
  531. FAT_DIRENT::IsSystem(
  532. ) CONST
  533. /*++
  534. Routine Description:
  535. This routine computes whether or not the file is a system file.
  536. Arguments:
  537. None.
  538. Return Value:
  539. FALSE - The file is not a system file.
  540. TRUE - The file is a system file.
  541. --*/
  542. {
  543. DebugAssert(_dirent);
  544. return _dirent[11]&0x04 ? TRUE : FALSE;
  545. }
  546. INLINE
  547. BOOLEAN
  548. FAT_DIRENT::IsVolumeLabel(
  549. ) CONST
  550. /*++
  551. Routine Description:
  552. This routine computes whether or not the first 11 characters of the
  553. directory entry are the volume label or not.
  554. Arguments:
  555. None.
  556. Return Value:
  557. FALSE - The directory entry is not a volume label.
  558. TRUE - The directory entry is a volume label.
  559. --*/
  560. {
  561. DebugAssert(_dirent);
  562. return ((_dirent[11]&0x08) && !IsLongEntry());
  563. }
  564. INLINE
  565. BOOLEAN
  566. FAT_DIRENT::IsLongEntry(
  567. ) CONST
  568. /*++
  569. Routine Description;
  570. This routine determines whether this entry is a
  571. Long Directory Entry.
  572. The entry is a Long Directory Entry if the attribute
  573. field has all four low-order bits (read-only, hidden,
  574. system, and volume-label) set. The four high-order
  575. bits are ignored.
  576. Arguments:
  577. None.
  578. Return Value:
  579. TRUE if the entry is a Long Name Directory Entry.
  580. --*/
  581. {
  582. return( (_dirent[11] & 0xF) == 0xF );
  583. }
  584. INLINE
  585. BOOLEAN
  586. FAT_DIRENT::IsLongNameEntry(
  587. ) CONST
  588. /*++
  589. Routine Description;
  590. This routine determines whether this entry is a
  591. Long Name Directory Entry.
  592. A Long Name directory entry is a Long Directory Entry
  593. with a type field of LONG_DIRENT_TYPE_LONG_NAME.
  594. Arguments:
  595. None.
  596. Return Value:
  597. TRUE if the entry is a Long Name Directory Entry.
  598. --*/
  599. {
  600. return( IsLongEntry() && (_dirent[12] == LONG_DIRENT_TYPE_NAME) );
  601. }
  602. INLINE
  603. BOOLEAN
  604. FAT_DIRENT::QueryLongOrdinal(
  605. ) CONST
  606. /*++
  607. Routine Description;
  608. This method returns the ordinal of a long directory entry.
  609. If the directory entry is not a long entry, it returns
  610. 0xFF. Note that this method strips off the Last Long Entry
  611. flag before returning the ordinal. To determine if an entry
  612. is the last of a set of long entries, call IsLastLongEntry.
  613. Arguments:
  614. None.
  615. Return Value:
  616. The ordinal of this entry.
  617. --*/
  618. {
  619. return( IsLongEntry() ? _dirent[0] & 0x3F: 0xFF );
  620. }
  621. INLINE
  622. BOOLEAN
  623. FAT_DIRENT::IsLastLongEntry(
  624. ) CONST
  625. /*++
  626. Routine Description:
  627. This method determines whether this entry is the last
  628. of a set of long directory entries.
  629. Arguments:
  630. None.
  631. Return Value:
  632. TRUE if this is the last of a set of long directory entries.
  633. --*/
  634. {
  635. return( IsLongEntry() ? _dirent[0] & 0x40 : FALSE );
  636. }
  637. INLINE
  638. VOID
  639. FAT_DIRENT::SetVolumeLabel(
  640. )
  641. /*++
  642. Routine Description:
  643. This routine sets the directory entry to be a volume label.
  644. Arguments:
  645. None.
  646. Return Value:
  647. None.
  648. --*/
  649. {
  650. DebugAssert(_dirent);
  651. _dirent[11] |= 0x08;
  652. }
  653. INLINE
  654. BOOLEAN
  655. FAT_DIRENT::IsDirectory(
  656. ) CONST
  657. /*++
  658. Routine Description:
  659. This routine computes whether or not the directory entry is a directory.
  660. Arguments:
  661. None.
  662. Return Value:
  663. FALSE - The directory entry is not a directory.
  664. TRUE - The directory entry is a directory.
  665. --*/
  666. {
  667. DebugAssert(_dirent);
  668. return ((_dirent[11]&0x10) && !IsLongEntry());
  669. }
  670. INLINE
  671. VOID
  672. FAT_DIRENT::SetDirectory(
  673. )
  674. /*++
  675. Routine Description:
  676. This routine sets the directory entry to be a directory.
  677. Arguments:
  678. None.
  679. Return Value:
  680. None.
  681. --*/
  682. {
  683. DebugAssert(_dirent);
  684. _dirent[11] |= 0x10;
  685. }
  686. INLINE
  687. VOID
  688. FAT_DIRENT::ResetDirectory(
  689. )
  690. /*++
  691. Routine Description:
  692. This routine sets the directory entry to not be a directory.
  693. Arguments:
  694. None.
  695. Return Value:
  696. None.
  697. --*/
  698. {
  699. DebugAssert(_dirent);
  700. _dirent[11] &= ~0x10;
  701. }
  702. INLINE
  703. BYTE
  704. FAT_DIRENT::QueryAttributeByte(
  705. ) CONST
  706. /*++
  707. Routine Description:
  708. This routine returns the attribute byte of the directory entry
  709. Arguments:
  710. None.
  711. Return Value:
  712. Attribute byte
  713. --*/
  714. {
  715. DebugAssert(_dirent);
  716. return _dirent[11];
  717. }
  718. INLINE
  719. BOOLEAN
  720. FAT_DIRENT::Is8LowerCase(
  721. ) CONST
  722. /*++
  723. Routine Description:
  724. This routine tells whether the first 8 bytes of the short name
  725. should be downcased after being read from the disk.
  726. Arguments:
  727. None.
  728. Return Value:
  729. TRUE or FALSE
  730. --*/
  731. {
  732. DebugAssert(_dirent);
  733. return (_dirent[12] & 0x08) != 0;
  734. }
  735. INLINE
  736. BOOLEAN
  737. FAT_DIRENT::Is3LowerCase(
  738. ) CONST
  739. /*++
  740. Routine Description:
  741. This routine tells whether the last 8 bytes of the short name
  742. should be downcased after being read from the disk.
  743. Arguments:
  744. None.
  745. Return Value:
  746. TRUE or FALSE
  747. --*/
  748. {
  749. DebugAssert(_dirent);
  750. return (_dirent[12] & 0x10) != 0;
  751. }
  752. #endif // FAT_DIRENT_DEFN