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.

737 lines
27 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. Fat.h
  5. Abstract:
  6. This module defines the on-disk structure of the Fat file system.
  7. // @@BEGIN_DDKSPLIT
  8. Author:
  9. Gary Kimura [GaryKi] 28-Dec-1989
  10. Revision History:
  11. // @@END_DDKSPLIT
  12. --*/
  13. #ifndef _FAT_
  14. #define _FAT_
  15. //
  16. // The following nomenclature is used to describe the Fat on-disk
  17. // structure:
  18. //
  19. // LBN - is the number of a sector relative to the start of the disk.
  20. //
  21. // VBN - is the number of a sector relative to the start of a file,
  22. // directory, or allocation.
  23. //
  24. // LBO - is a byte offset relative to the start of the disk.
  25. //
  26. // VBO - is a byte offset relative to the start of a file, directory
  27. // or allocation.
  28. //
  29. typedef LONGLONG LBO; /* for Fat32, LBO is >32 bits */
  30. typedef LBO *PLBO;
  31. typedef ULONG32 VBO;
  32. typedef VBO *PVBO;
  33. //
  34. // The boot sector is the first physical sector (LBN == 0) on the volume.
  35. // Part of the sector contains a BIOS Parameter Block. The BIOS in the
  36. // sector is packed (i.e., unaligned) so we'll supply a unpacking macro
  37. // to translate a packed BIOS into its unpacked equivalent. The unpacked
  38. // BIOS structure is already defined in ntioapi.h so we only need to define
  39. // the packed BIOS.
  40. //
  41. //
  42. // Define the Packed and Unpacked BIOS Parameter Block
  43. //
  44. typedef struct _PACKED_BIOS_PARAMETER_BLOCK {
  45. UCHAR BytesPerSector[2]; // offset = 0x000 0
  46. UCHAR SectorsPerCluster[1]; // offset = 0x002 2
  47. UCHAR ReservedSectors[2]; // offset = 0x003 3
  48. UCHAR Fats[1]; // offset = 0x005 5
  49. UCHAR RootEntries[2]; // offset = 0x006 6
  50. UCHAR Sectors[2]; // offset = 0x008 8
  51. UCHAR Media[1]; // offset = 0x00A 10
  52. UCHAR SectorsPerFat[2]; // offset = 0x00B 11
  53. UCHAR SectorsPerTrack[2]; // offset = 0x00D 13
  54. UCHAR Heads[2]; // offset = 0x00F 15
  55. UCHAR HiddenSectors[4]; // offset = 0x011 17
  56. UCHAR LargeSectors[4]; // offset = 0x015 21
  57. } PACKED_BIOS_PARAMETER_BLOCK; // sizeof = 0x019 25
  58. typedef PACKED_BIOS_PARAMETER_BLOCK *PPACKED_BIOS_PARAMETER_BLOCK;
  59. typedef struct _PACKED_BIOS_PARAMETER_BLOCK_EX {
  60. UCHAR BytesPerSector[2]; // offset = 0x000 0
  61. UCHAR SectorsPerCluster[1]; // offset = 0x002 2
  62. UCHAR ReservedSectors[2]; // offset = 0x003 3
  63. UCHAR Fats[1]; // offset = 0x005 5
  64. UCHAR RootEntries[2]; // offset = 0x006 6
  65. UCHAR Sectors[2]; // offset = 0x008 8
  66. UCHAR Media[1]; // offset = 0x00A 10
  67. UCHAR SectorsPerFat[2]; // offset = 0x00B 11
  68. UCHAR SectorsPerTrack[2]; // offset = 0x00D 13
  69. UCHAR Heads[2]; // offset = 0x00F 15
  70. UCHAR HiddenSectors[4]; // offset = 0x011 17
  71. UCHAR LargeSectors[4]; // offset = 0x015 21
  72. UCHAR LargeSectorsPerFat[4]; // offset = 0x019 25
  73. UCHAR ExtendedFlags[2]; // offset = 0x01D 29
  74. UCHAR FsVersion[2]; // offset = 0x01F 31
  75. UCHAR RootDirFirstCluster[4]; // offset = 0x021 33
  76. UCHAR FsInfoSector[2]; // offset = 0x025 37
  77. UCHAR BackupBootSector[2]; // offset = 0x027 39
  78. UCHAR Reserved[12]; // offset = 0x029 41
  79. } PACKED_BIOS_PARAMETER_BLOCK_EX; // sizeof = 0x035 53
  80. typedef PACKED_BIOS_PARAMETER_BLOCK_EX *PPACKED_BIOS_PARAMETER_BLOCK_EX;
  81. //
  82. // The IsBpbFat32 macro is defined to work with both packed and unpacked
  83. // BPB structures. Since we are only checking for zero, the byte order
  84. // does not matter.
  85. //
  86. #define IsBpbFat32(bpb) (*(USHORT *)(&(bpb)->SectorsPerFat) == 0)
  87. typedef struct BIOS_PARAMETER_BLOCK {
  88. USHORT BytesPerSector;
  89. UCHAR SectorsPerCluster;
  90. USHORT ReservedSectors;
  91. UCHAR Fats;
  92. USHORT RootEntries;
  93. USHORT Sectors;
  94. UCHAR Media;
  95. USHORT SectorsPerFat;
  96. USHORT SectorsPerTrack;
  97. USHORT Heads;
  98. ULONG32 HiddenSectors;
  99. ULONG32 LargeSectors;
  100. ULONG32 LargeSectorsPerFat;
  101. union {
  102. USHORT ExtendedFlags;
  103. struct {
  104. ULONG ActiveFat:4;
  105. ULONG Reserved0:3;
  106. ULONG MirrorDisabled:1;
  107. ULONG Reserved1:8;
  108. };
  109. };
  110. USHORT FsVersion;
  111. ULONG32 RootDirFirstCluster;
  112. USHORT FsInfoSector;
  113. USHORT BackupBootSector;
  114. } BIOS_PARAMETER_BLOCK, *PBIOS_PARAMETER_BLOCK;
  115. //
  116. // This macro takes a Packed BIOS and fills in its Unpacked equivalent
  117. //
  118. #define FatUnpackBios(Bios,Pbios) { \
  119. CopyUchar2(&(Bios)->BytesPerSector, &(Pbios)->BytesPerSector[0] ); \
  120. CopyUchar1(&(Bios)->SectorsPerCluster, &(Pbios)->SectorsPerCluster[0]); \
  121. CopyUchar2(&(Bios)->ReservedSectors, &(Pbios)->ReservedSectors[0] ); \
  122. CopyUchar1(&(Bios)->Fats, &(Pbios)->Fats[0] ); \
  123. CopyUchar2(&(Bios)->RootEntries, &(Pbios)->RootEntries[0] ); \
  124. CopyUchar2(&(Bios)->Sectors, &(Pbios)->Sectors[0] ); \
  125. CopyUchar1(&(Bios)->Media, &(Pbios)->Media[0] ); \
  126. CopyUchar2(&(Bios)->SectorsPerFat, &(Pbios)->SectorsPerFat[0] ); \
  127. CopyUchar2(&(Bios)->SectorsPerTrack, &(Pbios)->SectorsPerTrack[0] ); \
  128. CopyUchar2(&(Bios)->Heads, &(Pbios)->Heads[0] ); \
  129. CopyUchar4(&(Bios)->HiddenSectors, &(Pbios)->HiddenSectors[0] ); \
  130. CopyUchar4(&(Bios)->LargeSectors, &(Pbios)->LargeSectors[0] ); \
  131. CopyUchar4(&(Bios)->LargeSectorsPerFat,&((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->LargeSectorsPerFat[0] ); \
  132. CopyUchar2(&(Bios)->ExtendedFlags, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->ExtendedFlags[0] ); \
  133. CopyUchar2(&(Bios)->FsVersion, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->FsVersion[0] ); \
  134. CopyUchar4(&(Bios)->RootDirFirstCluster, \
  135. &((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->RootDirFirstCluster[0] ); \
  136. CopyUchar2(&(Bios)->FsInfoSector, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->FsInfoSector[0] ); \
  137. CopyUchar2(&(Bios)->BackupBootSector, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->BackupBootSector[0] ); \
  138. }
  139. //
  140. // Define the boot sector
  141. //
  142. typedef struct _PACKED_BOOT_SECTOR {
  143. UCHAR Jump[3]; // offset = 0x000 0
  144. UCHAR Oem[8]; // offset = 0x003 3
  145. PACKED_BIOS_PARAMETER_BLOCK PackedBpb; // offset = 0x00B 11
  146. UCHAR PhysicalDriveNumber; // offset = 0x024 36
  147. UCHAR CurrentHead; // offset = 0x025 37
  148. UCHAR Signature; // offset = 0x026 38
  149. UCHAR Id[4]; // offset = 0x027 39
  150. UCHAR VolumeLabel[11]; // offset = 0x02B 43
  151. UCHAR SystemId[8]; // offset = 0x036 54
  152. } PACKED_BOOT_SECTOR; // sizeof = 0x03E 62
  153. typedef PACKED_BOOT_SECTOR *PPACKED_BOOT_SECTOR;
  154. typedef struct _PACKED_BOOT_SECTOR_EX {
  155. UCHAR Jump[3]; // offset = 0x000 0
  156. UCHAR Oem[8]; // offset = 0x003 3
  157. PACKED_BIOS_PARAMETER_BLOCK_EX PackedBpb; // offset = 0x00B 11
  158. UCHAR PhysicalDriveNumber; // offset = 0x040 64
  159. UCHAR CurrentHead; // offset = 0x041 65
  160. UCHAR Signature; // offset = 0x042 66
  161. UCHAR Id[4]; // offset = 0x043 67
  162. UCHAR VolumeLabel[11]; // offset = 0x047 71
  163. UCHAR SystemId[8]; // offset = 0x058 88
  164. } PACKED_BOOT_SECTOR_EX; // sizeof = 0x060 96
  165. typedef PACKED_BOOT_SECTOR_EX *PPACKED_BOOT_SECTOR_EX;
  166. //
  167. // Define the FAT32 FsInfo sector.
  168. //
  169. typedef struct _FSINFO_SECTOR {
  170. ULONG SectorBeginSignature; // offset = 0x000 0
  171. UCHAR ExtraBootCode[480]; // offset = 0x004 4
  172. ULONG FsInfoSignature; // offset = 0x1e4 484
  173. ULONG FreeClusterCount; // offset = 0x1e8 488
  174. ULONG NextFreeCluster; // offset = 0x1ec 492
  175. UCHAR Reserved[12]; // offset = 0x1f0 496
  176. ULONG SectorEndSignature; // offset = 0x1fc 508
  177. } FSINFO_SECTOR, *PFSINFO_SECTOR;
  178. #define FSINFO_SECTOR_BEGIN_SIGNATURE 0x41615252
  179. #define FSINFO_SECTOR_END_SIGNATURE 0xAA550000
  180. #define FSINFO_SIGNATURE 0x61417272
  181. //
  182. // We use the CurrentHead field for our dirty partition info.
  183. //
  184. #define FAT_BOOT_SECTOR_DIRTY 0x01
  185. #define FAT_BOOT_SECTOR_TEST_SURFACE 0x02
  186. //
  187. // Define a Fat Entry type.
  188. //
  189. // This type is used when representing a fat table entry. It also used
  190. // to be used when dealing with a fat table index and a count of entries,
  191. // but the ensuing type casting nightmare sealed this fate. These other
  192. // two types are represented as ULONGs.
  193. //
  194. typedef ULONG32 FAT_ENTRY;
  195. #define FAT32_ENTRY_MASK 0x0FFFFFFFUL
  196. //
  197. // We use these special index values to set the dirty info for
  198. // DOS/Win9x compatibility.
  199. //
  200. #define FAT_CLEAN_VOLUME (~FAT32_ENTRY_MASK | 0)
  201. #define FAT_DIRTY_VOLUME (~FAT32_ENTRY_MASK | 1)
  202. #define FAT_DIRTY_BIT_INDEX 1
  203. //
  204. // Physically, the entry is fully set if clean, and the high
  205. // bit knocked out if it is dirty (i.e., it is really a clean
  206. // bit). This means it is different per-FAT size.
  207. //
  208. #define FAT_CLEAN_ENTRY (~0)
  209. #define FAT12_DIRTY_ENTRY 0x7ff
  210. #define FAT16_DIRTY_ENTRY 0x7fff
  211. #define FAT32_DIRTY_ENTRY 0x7fffffff
  212. //
  213. // The following constants the are the valid Fat index values.
  214. //
  215. #define FAT_CLUSTER_AVAILABLE (FAT_ENTRY)0x00000000
  216. #define FAT_CLUSTER_RESERVED (FAT_ENTRY)0x0ffffff0
  217. #define FAT_CLUSTER_BAD (FAT_ENTRY)0x0ffffff7
  218. #define FAT_CLUSTER_LAST (FAT_ENTRY)0x0fffffff
  219. //
  220. // Fat files have the following time/date structures. Note that the
  221. // following structure is a 32 bits long but USHORT aligned.
  222. //
  223. typedef struct _FAT_TIME {
  224. USHORT DoubleSeconds : 5;
  225. USHORT Minute : 6;
  226. USHORT Hour : 5;
  227. } FAT_TIME;
  228. typedef FAT_TIME *PFAT_TIME;
  229. typedef struct _FAT_DATE {
  230. USHORT Day : 5;
  231. USHORT Month : 4;
  232. USHORT Year : 7; // Relative to 1980
  233. } FAT_DATE;
  234. typedef FAT_DATE *PFAT_DATE;
  235. typedef struct _FAT_TIME_STAMP {
  236. FAT_TIME Time;
  237. FAT_DATE Date;
  238. } FAT_TIME_STAMP;
  239. typedef FAT_TIME_STAMP *PFAT_TIME_STAMP;
  240. //
  241. // Fat files have 8 character file names and 3 character extensions
  242. //
  243. typedef UCHAR FAT8DOT3[11];
  244. typedef FAT8DOT3 *PFAT8DOT3;
  245. //
  246. // The directory entry record exists for every file/directory on the
  247. // disk except for the root directory.
  248. //
  249. typedef struct _PACKED_DIRENT {
  250. FAT8DOT3 FileName; // offset = 0
  251. UCHAR Attributes; // offset = 11
  252. UCHAR NtByte; // offset = 12
  253. UCHAR CreationMSec; // offset = 13
  254. FAT_TIME_STAMP CreationTime; // offset = 14
  255. FAT_DATE LastAccessDate; // offset = 18
  256. union {
  257. USHORT ExtendedAttributes; // offset = 20
  258. USHORT FirstClusterOfFileHi; // offset = 20
  259. };
  260. FAT_TIME_STAMP LastWriteTime; // offset = 22
  261. USHORT FirstClusterOfFile; // offset = 26
  262. ULONG32 FileSize; // offset = 28
  263. } PACKED_DIRENT; // sizeof = 32
  264. typedef PACKED_DIRENT *PPACKED_DIRENT;
  265. //
  266. // A packed dirent is already quadword aligned so simply declare a dirent as a
  267. // packed dirent
  268. //
  269. typedef PACKED_DIRENT DIRENT;
  270. typedef DIRENT *PDIRENT;
  271. //
  272. // The first byte of a dirent describes the dirent. There is also a routine
  273. // to help in deciding how to interpret the dirent.
  274. //
  275. #define FAT_DIRENT_NEVER_USED 0x00
  276. #define FAT_DIRENT_REALLY_0E5 0x05
  277. #define FAT_DIRENT_DIRECTORY_ALIAS 0x2e
  278. #define FAT_DIRENT_DELETED 0xe5
  279. //
  280. // Define the NtByte bits.
  281. //
  282. #define FAT_DIRENT_NT_BYTE_8_LOWER_CASE 0x08
  283. #define FAT_DIRENT_NT_BYTE_3_LOWER_CASE 0x10
  284. //
  285. // Define the various dirent attributes
  286. //
  287. #define FAT_DIRENT_ATTR_READ_ONLY 0x01
  288. #define FAT_DIRENT_ATTR_HIDDEN 0x02
  289. #define FAT_DIRENT_ATTR_SYSTEM 0x04
  290. #define FAT_DIRENT_ATTR_VOLUME_ID 0x08
  291. #define FAT_DIRENT_ATTR_DIRECTORY 0x10
  292. #define FAT_DIRENT_ATTR_ARCHIVE 0x20
  293. #define FAT_DIRENT_ATTR_DEVICE 0x40
  294. #define FAT_DIRENT_ATTR_LFN (FAT_DIRENT_ATTR_READ_ONLY | \
  295. FAT_DIRENT_ATTR_HIDDEN | \
  296. FAT_DIRENT_ATTR_SYSTEM | \
  297. FAT_DIRENT_ATTR_VOLUME_ID)
  298. //
  299. // These macros convert a number of fields in the Bpb to bytes from sectors
  300. //
  301. // ULONG
  302. // FatBytesPerCluster (
  303. // IN PBIOS_PARAMETER_BLOCK Bios
  304. // );
  305. //
  306. // ULONG
  307. // FatBytesPerFat (
  308. // IN PBIOS_PARAMETER_BLOCK Bios
  309. // );
  310. //
  311. // ULONG
  312. // FatReservedBytes (
  313. // IN PBIOS_PARAMETER_BLOCK Bios
  314. // );
  315. //
  316. #define FatBytesPerCluster(B) ((ULONG)((B)->BytesPerSector * (B)->SectorsPerCluster))
  317. #define FatBytesPerFat(B) (IsBpbFat32(B)? \
  318. ((ULONG)((B)->BytesPerSector * (B)->LargeSectorsPerFat)) : \
  319. ((ULONG)((B)->BytesPerSector * (B)->SectorsPerFat)))
  320. #define FatReservedBytes(B) ((ULONG)((B)->BytesPerSector * (B)->ReservedSectors))
  321. //
  322. // This macro returns the size of the root directory dirent area in bytes
  323. // For Fat32, the root directory is variable in length. This macro returns
  324. // 0 because it is also used to determine the location of cluster 2.
  325. //
  326. // ULONG
  327. // FatRootDirectorySize (
  328. // IN PBIOS_PARAMETER_BLOCK Bios
  329. // );
  330. //
  331. #define FatRootDirectorySize(B) ((ULONG)((B)->RootEntries * sizeof(DIRENT)))
  332. //
  333. // This macro returns the first Lbo (zero based) of the root directory on
  334. // the device. This area is after the reserved and fats.
  335. //
  336. // For Fat32, the root directory is moveable. This macro returns the LBO
  337. // for cluster 2 because it is used to determine the location of cluster 2.
  338. // FatRootDirectoryLbo32() returns the actual LBO of the beginning of the
  339. // actual root directory.
  340. //
  341. // LBO
  342. // FatRootDirectoryLbo (
  343. // IN PBIOS_PARAMETER_BLOCK Bios
  344. // );
  345. //
  346. #define FatRootDirectoryLbo(B) (FatReservedBytes(B) + ((B)->Fats * FatBytesPerFat(B)))
  347. #define FatRootDirectoryLbo32(B) (FatFileAreaLbo(B)+((B)->RootDirFirstCluster-2)*FatBytesPerCluster(B))
  348. //
  349. // This macro returns the first Lbo (zero based) of the file area on the
  350. // the device. This area is after the reserved, fats, and root directory.
  351. //
  352. // LBO
  353. // FatFirstFileAreaLbo (
  354. // IN PBIOS_PARAMTER_BLOCK Bios
  355. // );
  356. //
  357. #define FatFileAreaLbo(B) (FatRootDirectoryLbo(B) + FatRootDirectorySize(B))
  358. //
  359. // This macro returns the number of clusters on the disk. This value is
  360. // computed by taking the total sectors on the disk subtracting up to the
  361. // first file area sector and then dividing by the sectors per cluster count.
  362. // Note that I don't use any of the above macros since far too much
  363. // superfluous sector/byte conversion would take place.
  364. //
  365. // ULONG
  366. // FatNumberOfClusters (
  367. // IN PBIOS_PARAMETER_BLOCK Bios
  368. // );
  369. //
  370. //
  371. // for prior to MS-DOS Version 3.2
  372. //
  373. // After DOS 4.0, at least one of these, Sectors or LargeSectors, will be zero.
  374. // but DOS version 3.2 case, both of these value might contains some value,
  375. // because, before 3.2, we don't have Large Sector entry, some disk might have
  376. // unexpected value in the field, we will use LargeSectors if Sectors eqaul to zero.
  377. //
  378. #define FatNumberOfClusters(B) ( \
  379. \
  380. IsBpbFat32(B) ? \
  381. \
  382. ((((B)->Sectors ? (B)->Sectors : (B)->LargeSectors) \
  383. \
  384. - ((B)->ReservedSectors + \
  385. (B)->Fats * (B)->LargeSectorsPerFat )) \
  386. \
  387. / \
  388. \
  389. (B)->SectorsPerCluster) \
  390. : \
  391. ((((B)->Sectors ? (B)->Sectors : (B)->LargeSectors) \
  392. \
  393. - ((B)->ReservedSectors + \
  394. (B)->Fats * (B)->SectorsPerFat + \
  395. (B)->RootEntries * sizeof(DIRENT) / (B)->BytesPerSector ) ) \
  396. \
  397. / \
  398. \
  399. (B)->SectorsPerCluster) \
  400. )
  401. //
  402. // This macro returns the fat table bit size (i.e., 12 or 16 bits)
  403. //
  404. // ULONG
  405. // FatIndexBitSize (
  406. // IN PBIOS_PARAMETER_BLOCK Bios
  407. // );
  408. //
  409. #define FatIndexBitSize(B) \
  410. ((UCHAR)(IsBpbFat32(B) ? 32 : (FatNumberOfClusters(B) < 4087 ? 12 : 16)))
  411. //
  412. // This macro raises STATUS_FILE_CORRUPT and marks the Fcb bad if an
  413. // index value is not within the proper range.
  414. // Note that the first two index values are invalid (0, 1), so we must
  415. // add two from the top end to make sure the everything is within range
  416. //
  417. // VOID
  418. // FatVerifyIndexIsValid (
  419. // IN PIRP_CONTEXT IrpContext,
  420. // IN PVCB Vcb,
  421. // IN ULONG Index
  422. // );
  423. //
  424. #define FatVerifyIndexIsValid(IC,V,I) { \
  425. if (((I) < 2) || ((I) > ((V)->AllocationSupport.NumberOfClusters + 1))) { \
  426. FatRaiseStatus(IC,STATUS_FILE_CORRUPT_ERROR); \
  427. } \
  428. }
  429. //
  430. // These two macros are used to translate between Logical Byte Offsets,
  431. // and fat entry indexes. Note the use of variables stored in the Vcb.
  432. // These two macros are used at a higher level than the other macros
  433. // above.
  434. //
  435. // Note, these indexes are true cluster numbers.
  436. //
  437. // LBO
  438. // GetLboFromFatIndex (
  439. // IN FAT_ENTRY Fat_Index,
  440. // IN PVCB Vcb
  441. // );
  442. //
  443. // FAT_ENTRY
  444. // GetFatIndexFromLbo (
  445. // IN LBO Lbo,
  446. // IN PVCB Vcb
  447. // );
  448. //
  449. #define FatGetLboFromIndex(VCB,FAT_INDEX) ( \
  450. ( (LBO) \
  451. (VCB)->AllocationSupport.FileAreaLbo + \
  452. (((LBO)((FAT_INDEX) - 2)) << (VCB)->AllocationSupport.LogOfBytesPerCluster) \
  453. ) \
  454. )
  455. #define FatGetIndexFromLbo(VCB,LBO) ( \
  456. (ULONG) ( \
  457. (((LBO) - (VCB)->AllocationSupport.FileAreaLbo) >> \
  458. (VCB)->AllocationSupport.LogOfBytesPerCluster) + 2 \
  459. ) \
  460. )
  461. //
  462. // The following macro does the shifting and such to lookup an entry
  463. //
  464. // VOID
  465. // FatLookup12BitEntry(
  466. // IN PVOID Fat,
  467. // IN FAT_ENTRY Index,
  468. // OUT PFAT_ENTRY Entry
  469. // );
  470. //
  471. #define FatLookup12BitEntry(FAT,INDEX,ENTRY) { \
  472. \
  473. CopyUchar2((PUCHAR)(ENTRY), (PUCHAR)(FAT) + (INDEX) * 3 / 2); \
  474. \
  475. *ENTRY = (FAT_ENTRY)(0xfff & (((INDEX) & 1) ? (*(ENTRY) >> 4) : \
  476. *(ENTRY))); \
  477. }
  478. //
  479. // The following macro does the tmp shifting and such to store an entry
  480. //
  481. // VOID
  482. // FatSet12BitEntry(
  483. // IN PVOID Fat,
  484. // IN FAT_ENTRY Index,
  485. // IN FAT_ENTRY Entry
  486. // );
  487. //
  488. #define FatSet12BitEntry(FAT,INDEX,ENTRY) { \
  489. \
  490. FAT_ENTRY TmpFatEntry; \
  491. \
  492. CopyUchar2((PUCHAR)&TmpFatEntry, (PUCHAR)(FAT) + (INDEX) * 3 / 2); \
  493. \
  494. TmpFatEntry = (FAT_ENTRY) \
  495. (((INDEX) & 1) ? ((ENTRY) << 4) | (TmpFatEntry & 0xf) \
  496. : (ENTRY) | (TmpFatEntry & 0xf000)); \
  497. \
  498. *((UNALIGNED UCHAR2 *)((PUCHAR)(FAT) + (INDEX) * 3 / 2)) = *((UNALIGNED UCHAR2 *)(&TmpFatEntry)); \
  499. }
  500. //
  501. // The following macro compares two FAT_TIME_STAMPs
  502. //
  503. #define FatAreTimesEqual(TIME1,TIME2) ( \
  504. RtlEqualMemory((TIME1),(TIME2), sizeof(FAT_TIME_STAMP)) \
  505. )
  506. #define EA_FILE_SIGNATURE (0x4445) // "ED"
  507. #define EA_SET_SIGNATURE (0x4145) // "EA"
  508. //
  509. // If the volume contains any ea data then there is one EA file called
  510. // "EA DATA. SF" located in the root directory as Hidden, System and
  511. // ReadOnly.
  512. //
  513. typedef struct _EA_FILE_HEADER {
  514. USHORT Signature; // offset = 0
  515. USHORT FormatType; // offset = 2
  516. USHORT LogType; // offset = 4
  517. USHORT Cluster1; // offset = 6
  518. USHORT NewCValue1; // offset = 8
  519. USHORT Cluster2; // offset = 10
  520. USHORT NewCValue2; // offset = 12
  521. USHORT Cluster3; // offset = 14
  522. USHORT NewCValue3; // offset = 16
  523. USHORT Handle; // offset = 18
  524. USHORT NewHOffset; // offset = 20
  525. UCHAR Reserved[10]; // offset = 22
  526. USHORT EaBaseTable[240]; // offset = 32
  527. } EA_FILE_HEADER; // sizeof = 512
  528. typedef EA_FILE_HEADER *PEA_FILE_HEADER;
  529. typedef USHORT EA_OFF_TABLE[128];
  530. typedef EA_OFF_TABLE *PEA_OFF_TABLE;
  531. //
  532. // Every file with an extended attribute contains in its dirent an index
  533. // into the EaMapTable. The map table contains an offset within the ea
  534. // file (cluster aligned) of the ea data for the file. The individual
  535. // ea data for each file is prefaced with an Ea Data Header.
  536. //
  537. typedef struct _EA_SET_HEADER {
  538. USHORT Signature; // offset = 0
  539. USHORT OwnEaHandle; // offset = 2
  540. ULONG32 NeedEaCount; // offset = 4
  541. UCHAR OwnerFileName[14]; // offset = 8
  542. UCHAR Reserved[4]; // offset = 22
  543. UCHAR cbList[4]; // offset = 26
  544. UCHAR PackedEas[1]; // offset = 30
  545. } EA_SET_HEADER; // sizeof = 30
  546. typedef EA_SET_HEADER *PEA_SET_HEADER;
  547. #define SIZE_OF_EA_SET_HEADER 30
  548. #define MAXIMUM_EA_SIZE 0x0000ffff
  549. #define GetcbList(EASET) (((EASET)->cbList[0] << 0) + \
  550. ((EASET)->cbList[1] << 8) + \
  551. ((EASET)->cbList[2] << 16) + \
  552. ((EASET)->cbList[3] << 24))
  553. #define SetcbList(EASET,CB) { \
  554. (EASET)->cbList[0] = (CB >> 0) & 0x0ff; \
  555. (EASET)->cbList[1] = (CB >> 8) & 0x0ff; \
  556. (EASET)->cbList[2] = (CB >> 16) & 0x0ff; \
  557. (EASET)->cbList[3] = (CB >> 24) & 0x0ff; \
  558. }
  559. //
  560. // Every individual ea in an ea set is declared the following packed ea
  561. //
  562. typedef struct _PACKED_EA {
  563. UCHAR Flags;
  564. UCHAR EaNameLength;
  565. UCHAR EaValueLength[2];
  566. CHAR EaName[1];
  567. } PACKED_EA;
  568. typedef PACKED_EA *PPACKED_EA;
  569. //
  570. // The following two macros are used to get and set the ea value length
  571. // field of a packed ea
  572. //
  573. // VOID
  574. // GetEaValueLength (
  575. // IN PPACKED_EA Ea,
  576. // OUT PUSHORT ValueLength
  577. // );
  578. //
  579. // VOID
  580. // SetEaValueLength (
  581. // IN PPACKED_EA Ea,
  582. // IN USHORT ValueLength
  583. // );
  584. //
  585. #define GetEaValueLength(EA,LEN) { \
  586. *(LEN) = 0; \
  587. CopyUchar2( (LEN), (EA)->EaValueLength ); \
  588. }
  589. #define SetEaValueLength(EA,LEN) { \
  590. CopyUchar2( &((EA)->EaValueLength), (LEN) ); \
  591. }
  592. //
  593. // The following macro is used to get the size of a packed ea
  594. //
  595. // VOID
  596. // SizeOfPackedEa (
  597. // IN PPACKED_EA Ea,
  598. // OUT PUSHORT EaSize
  599. // );
  600. //
  601. #define SizeOfPackedEa(EA,SIZE) { \
  602. ULONG _NL,_DL; _NL = 0; _DL = 0; \
  603. CopyUchar1(&_NL, &(EA)->EaNameLength); \
  604. GetEaValueLength(EA, &_DL); \
  605. *(SIZE) = 1 + 1 + 2 + _NL + 1 + _DL; \
  606. }
  607. #define EA_NEED_EA_FLAG 0x80
  608. #define MIN_EA_HANDLE 1
  609. #define MAX_EA_HANDLE 30719
  610. #define UNUSED_EA_HANDLE 0xffff
  611. #define EA_CBLIST_OFFSET 0x1a
  612. #define MAX_EA_BASE_INDEX 240
  613. #define MAX_EA_OFFSET_INDEX 128
  614. #endif // _FAT_