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