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.

1627 lines
45 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. FatStruc.h
  5. Abstract:
  6. This module defines the data structures that make up the major internal
  7. part of the Fat file system.
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Gary Kimura [GaryKi] 28-Dec-1989
  11. Revision History:
  12. // @@END_DDKSPLIT
  13. --*/
  14. #ifndef _FATSTRUC_
  15. #define _FATSTRUC_
  16. typedef PVOID PBCB; //**** Bcb's are now part of the cache module
  17. //
  18. // The FAT_DATA record is the top record in the Fat file system in-memory
  19. // data structure. This structure must be allocated from non-paged pool.
  20. //
  21. typedef struct _FAT_DATA {
  22. //
  23. // The type and size of this record (must be FAT_NTC_DATA_HEADER)
  24. //
  25. NODE_TYPE_CODE NodeTypeCode;
  26. NODE_BYTE_SIZE NodeByteSize;
  27. PVOID LazyWriteThread;
  28. //
  29. // A queue of all the devices that are mounted by the file system.
  30. //
  31. LIST_ENTRY VcbQueue;
  32. //
  33. // A pointer to the Driver object we were initialized with
  34. //
  35. PDRIVER_OBJECT DriverObject;
  36. //
  37. // A pointer to the filesystem device objects we created.
  38. //
  39. PVOID DiskFileSystemDeviceObject;
  40. PVOID CdromFileSystemDeviceObject;
  41. //
  42. // A resource variable to control access to the global Fat data record
  43. //
  44. ERESOURCE Resource;
  45. //
  46. // A pointer to our EPROCESS struct, which is a required input to the
  47. // Cache Management subsystem.
  48. //
  49. PEPROCESS OurProcess;
  50. //
  51. // The following tells us if we should use Chicago extensions.
  52. //
  53. BOOLEAN ChicagoMode:1;
  54. //
  55. // The following field tells us if we are running on a Fujitsu
  56. // FMR Series. These machines supports extra formats on the
  57. // FAT file system.
  58. //
  59. BOOLEAN FujitsuFMR:1;
  60. //
  61. // Inidicates that FspClose is currently processing closes.
  62. //
  63. BOOLEAN AsyncCloseActive:1;
  64. //
  65. // The following BOOLEAN says shutdown has started on FAT. It
  66. // instructs FspClose to not keep the Vcb resources anymore.
  67. //
  68. BOOLEAN ShutdownStarted:1;
  69. //
  70. // The following flag tells us if we are going to generate LFNs
  71. // for valid 8.3 names with extended characters.
  72. //
  73. BOOLEAN CodePageInvariant:1;
  74. //
  75. // The following flags tell us if we are in an aggresive push to lower
  76. // the size of the deferred close queues.
  77. //
  78. BOOLEAN HighAsync:1;
  79. BOOLEAN HighDelayed:1;
  80. //
  81. // The following list entry is used for performing closes that can't
  82. // be done in the context of the original caller.
  83. //
  84. ULONG AsyncCloseCount;
  85. LIST_ENTRY AsyncCloseList;
  86. //
  87. // The following two fields record if we are delaying a close.
  88. //
  89. ULONG DelayedCloseCount;
  90. LIST_ENTRY DelayedCloseList;
  91. //
  92. // This is the ExWorkerItem that does both kinds of deferred closes.
  93. //
  94. PIO_WORKITEM FatCloseItem;
  95. //
  96. // This spinlock protects several rapid-fire operations. NOTE: this is
  97. // pretty horrible style.
  98. //
  99. KSPIN_LOCK GeneralSpinLock;
  100. //
  101. // Cache manager call back structures, which must be passed on each call
  102. // to CcInitializeCacheMap.
  103. //
  104. CACHE_MANAGER_CALLBACKS CacheManagerCallbacks;
  105. CACHE_MANAGER_CALLBACKS CacheManagerNoOpCallbacks;
  106. } FAT_DATA;
  107. typedef FAT_DATA *PFAT_DATA;
  108. //
  109. // An array of these structures will keep
  110. typedef struct _FAT_WINDOW {
  111. ULONG FirstCluster; // The first cluster in this window.
  112. ULONG LastCluster; // The last cluster in this window.
  113. ULONG ClustersFree; // The number of clusters free in this window.
  114. } FAT_WINDOW;
  115. typedef FAT_WINDOW *PFAT_WINDOW;
  116. //
  117. // Forward reference some circular referenced structures.
  118. //
  119. typedef struct _VCB VCB;
  120. typedef VCB *PVCB;
  121. typedef struct _FCB FCB;
  122. typedef FCB *PFCB;
  123. //
  124. // This structure is used to keep track of information needed to do a
  125. // deferred close. It is now embedded in a CCB so we don't have to
  126. // allocate one in the close path (with mustsucceed).
  127. //
  128. typedef struct {
  129. //
  130. // Two sets of links, one for the global list and one for closes
  131. // on a particular volume.
  132. //
  133. LIST_ENTRY GlobalLinks;
  134. LIST_ENTRY VcbLinks;
  135. PVCB Vcb;
  136. PFCB Fcb;
  137. enum _TYPE_OF_OPEN TypeOfOpen;
  138. BOOLEAN Free;
  139. } CLOSE_CONTEXT;
  140. typedef CLOSE_CONTEXT *PCLOSE_CONTEXT;
  141. //
  142. // The Vcb (Volume control Block) record corresponds to every volume mounted
  143. // by the file system. They are ordered in a queue off of FatData.VcbQueue.
  144. // This structure must be allocated from non-paged pool
  145. //
  146. typedef enum _VCB_CONDITION {
  147. VcbGood = 1,
  148. VcbNotMounted,
  149. VcbBad
  150. } VCB_CONDITION;
  151. typedef struct _VCB {
  152. //
  153. // This is a common head for the FAT volume file
  154. //
  155. FSRTL_ADVANCED_FCB_HEADER VolumeFileHeader;
  156. //
  157. // The links for the device queue off of FatData.VcbQueue
  158. //
  159. LIST_ENTRY VcbLinks;
  160. //
  161. // A pointer the device object passed in by the I/O system on a mount
  162. // This is the target device object that the file system talks to when it
  163. // needs to do any I/O (e.g., the disk stripper device object).
  164. //
  165. //
  166. PDEVICE_OBJECT TargetDeviceObject;
  167. //
  168. // A pointer to the VPB for the volume passed in by the I/O system on
  169. // a mount.
  170. //
  171. PVPB Vpb;
  172. //
  173. // The internal state of the device. This is a collection of fsd device
  174. // state flags.
  175. //
  176. ULONG VcbState;
  177. VCB_CONDITION VcbCondition;
  178. //
  179. // A pointer to the root DCB for this volume
  180. //
  181. struct _FCB *RootDcb;
  182. //
  183. // If the FAT has so many entries that the free cluster bitmap would
  184. // be too large, we split the FAT into buckets, and only one bucket's
  185. // worth of bits are kept in the bitmap.
  186. //
  187. ULONG NumberOfWindows;
  188. PFAT_WINDOW Windows;
  189. PFAT_WINDOW CurrentWindow;
  190. //
  191. // A count of the number of file objects that have opened the volume
  192. // for direct access, and their share access state.
  193. //
  194. CLONG DirectAccessOpenCount;
  195. SHARE_ACCESS ShareAccess;
  196. //
  197. // A count of the number of file objects that have any file/directory
  198. // opened on this volume, not including direct access. And also the
  199. // count of the number of file objects that have a file opened for
  200. // only read access (i.e., they cannot be modifying the disk).
  201. //
  202. CLONG OpenFileCount;
  203. CLONG ReadOnlyCount;
  204. //
  205. // The bios parameter block field contains
  206. // an unpacked copy of the bpb for the volume, it is initialized
  207. // during mount time and can be read by everyone else after that.
  208. //
  209. BIOS_PARAMETER_BLOCK Bpb;
  210. PUCHAR First0x24BytesOfBootSector;
  211. //
  212. // The following structure contains information useful to the
  213. // allocation support routines. Many of them are computed from
  214. // elements of the Bpb, but are too involved to recompute every time
  215. // they are needed.
  216. //
  217. struct {
  218. LBO RootDirectoryLbo; // Lbo of beginning of root directory
  219. LBO FileAreaLbo; // Lbo of beginning of file area
  220. ULONG RootDirectorySize; // size of root directory in bytes
  221. ULONG NumberOfClusters; // total number of clusters on the volume
  222. ULONG NumberOfFreeClusters; // number of free clusters on the volume
  223. UCHAR FatIndexBitSize; // indicates if 12, 16, or 32 bit fat table
  224. UCHAR LogOfBytesPerSector; // Log(Bios->BytesPerSector)
  225. UCHAR LogOfBytesPerCluster; // Log(Bios->SectorsPerCluster)
  226. } AllocationSupport;
  227. //
  228. // The following Mcb is used to keep track of dirty sectors in the Fat.
  229. // Runs of holes denote clean sectors while runs of LBO == VBO denote
  230. // dirty sectors. The VBOs are that of the volume file, starting at
  231. // 0. The granuality of dirt is one sectors, and additions are only
  232. // made in sector chunks to prevent problems with several simultaneous
  233. // updaters.
  234. //
  235. LARGE_MCB DirtyFatMcb;
  236. //
  237. // The FreeClusterBitMap keeps track of all the clusters in the fat.
  238. // A 1 means occupied while a 0 means free. It allows quick location
  239. // of contiguous runs of free clusters. It is initialized on mount
  240. // or verify.
  241. //
  242. RTL_BITMAP FreeClusterBitMap;
  243. //
  244. // The following fast mutex controls access to the free cluster bit map
  245. // and the buckets.
  246. //
  247. FAST_MUTEX FreeClusterBitMapMutex;
  248. //
  249. // A resource variable to control access to the volume specific data
  250. // structures
  251. //
  252. ERESOURCE Resource;
  253. //
  254. // A resource to make sure no one changes the volume bitmap while
  255. // you're using it. Only for volumes with NumberOfWindows > 1.
  256. //
  257. ERESOURCE ChangeBitMapResource;
  258. //
  259. // The following field points to the file object used to do I/O to
  260. // the virtual volume file. The virtual volume file maps sectors
  261. // 0 through the end of fat and is of a fixed size (determined during
  262. // mount)
  263. //
  264. PFILE_OBJECT VirtualVolumeFile;
  265. //
  266. // The following field contains a record of special pointers used by
  267. // MM and Cache to manipluate section objects. Note that the values
  268. // are set outside of the file system. However the file system on an
  269. // open/create will set the file object's SectionObject field to point
  270. // to this field
  271. //
  272. SECTION_OBJECT_POINTERS SectionObjectPointers;
  273. //
  274. // The following fields is a hint cluster index used by the file system
  275. // when allocating a new cluster.
  276. //
  277. ULONG ClusterHint;
  278. //
  279. // This field contains the "DeviceObject" that this volume is
  280. // currently mounted on. Note Vcb->Vpb->RealDevice is constant.
  281. //
  282. PDEVICE_OBJECT CurrentDevice;
  283. //
  284. // This is a pointer to the file object and the Fcb which represent the ea data.
  285. //
  286. PFILE_OBJECT VirtualEaFile;
  287. struct _FCB *EaFcb;
  288. //
  289. // The following field is a pointer to the file object that has the
  290. // volume locked. if the VcbState has the locked flag set.
  291. //
  292. PFILE_OBJECT FileObjectWithVcbLocked;
  293. //
  294. // The following is the head of a list of notify Irps.
  295. //
  296. LIST_ENTRY DirNotifyList;
  297. //
  298. // The following is used to synchronize the dir notify list.
  299. //
  300. PNOTIFY_SYNC NotifySync;
  301. //
  302. // The following fast mutex is used to synchronize directory stream
  303. // file object creation.
  304. //
  305. FAST_MUTEX DirectoryFileCreationMutex;
  306. //
  307. // This field holds the thread address of the current (or most recent
  308. // depending on VcbState) thread doing a verify operation on this volume.
  309. //
  310. PKTHREAD VerifyThread;
  311. //
  312. // The following two structures are used for CleanVolume callbacks.
  313. //
  314. KDPC CleanVolumeDpc;
  315. KTIMER CleanVolumeTimer;
  316. //
  317. // This field records the last time FatMarkVolumeDirty was called, and
  318. // avoids excessive calls to push the CleanVolume forward in time.
  319. //
  320. LARGE_INTEGER LastFatMarkVolumeDirtyCall;
  321. //
  322. // The following fields holds a pointer to a struct which is used to
  323. // hold performance counters.
  324. //
  325. struct _FILE_SYSTEM_STATISTICS *Statistics;
  326. //
  327. // The property tunneling cache for this volume
  328. //
  329. TUNNEL Tunnel;
  330. //
  331. // The media change count is returned by IOCTL_CHECK_VERIFY and
  332. // is used to verify that no user-mode app has swallowed a media change
  333. // notification. This is only meaningful for removable media.
  334. //
  335. ULONG ChangeCount;
  336. //
  337. // Preallocated VPB for swapout, so we are not forced to consider
  338. // must succeed pool.
  339. //
  340. PVPB SwapVpb;
  341. //
  342. // Per volume threading of the close queues.
  343. //
  344. LIST_ENTRY AsyncCloseList;
  345. LIST_ENTRY DelayedCloseList;
  346. //
  347. // Fast mutex used by the ADVANCED FCB HEADER in this structure
  348. //
  349. FAST_MUTEX AdvancedFcbHeaderMutex;
  350. //
  351. // This is the close context associated with the Virtual Volume File.
  352. //
  353. PCLOSE_CONTEXT CloseContext;
  354. //
  355. // How many close contexts were preallocated on this Vcb
  356. //
  357. #if DBG
  358. ULONG CloseContextCount;
  359. #endif
  360. } VCB;
  361. typedef VCB *PVCB;
  362. #define VCB_STATE_FLAG_LOCKED (0x00000001)
  363. #define VCB_STATE_FLAG_REMOVABLE_MEDIA (0x00000002)
  364. #define VCB_STATE_FLAG_VOLUME_DIRTY (0x00000004)
  365. #define VCB_STATE_FLAG_MOUNTED_DIRTY (0x00000010)
  366. #define VCB_STATE_FLAG_SHUTDOWN (0x00000040)
  367. #define VCB_STATE_FLAG_CLOSE_IN_PROGRESS (0x00000080)
  368. #define VCB_STATE_FLAG_DELETED_FCB (0x00000100)
  369. #define VCB_STATE_FLAG_CREATE_IN_PROGRESS (0x00000200)
  370. #define VCB_STATE_FLAG_BOOT_OR_PAGING_FILE (0x00000800)
  371. #define VCB_STATE_FLAG_DEFERRED_FLUSH (0x00001000)
  372. #define VCB_STATE_FLAG_ASYNC_CLOSE_ACTIVE (0x00002000)
  373. #define VCB_STATE_FLAG_WRITE_PROTECTED (0x00004000)
  374. #define VCB_STATE_FLAG_REMOVAL_PREVENTED (0x00008000)
  375. #define VCB_STATE_FLAG_VOLUME_DISMOUNTED (0x00010000)
  376. #define VCB_STATE_VPB_NOT_ON_DEVICE (0x00020000)
  377. //
  378. // N.B - VOLUME_DISMOUNTED is an indication that FSCTL_DISMOUNT volume was
  379. // executed on a volume. It does not replace VcbCondition as an indication
  380. // that the volume is invalid/unrecoverable.
  381. //
  382. //
  383. // Define the file system statistics struct. Vcb->Statistics points to an
  384. // array of these (one per processor) and they must be 64 byte aligned to
  385. // prevent cache line tearing.
  386. //
  387. typedef struct _FILE_SYSTEM_STATISTICS {
  388. //
  389. // This contains the actual data.
  390. //
  391. FILESYSTEM_STATISTICS Common;
  392. FAT_STATISTICS Fat;
  393. //
  394. // Pad this structure to a multiple of 64 bytes.
  395. //
  396. UCHAR Pad[64-(sizeof(FILESYSTEM_STATISTICS)+sizeof(FAT_STATISTICS))%64];
  397. } FILE_SYSTEM_STATISTICS;
  398. typedef FILE_SYSTEM_STATISTICS *PFILE_SYSTEM_STATISTICS;
  399. //
  400. // The Volume Device Object is an I/O system device object with a workqueue
  401. // and an VCB record appended to the end. There are multiple of these
  402. // records, one for every mounted volume, and are created during
  403. // a volume mount operation. The work queue is for handling an overload of
  404. // work requests to the volume.
  405. //
  406. typedef struct _VOLUME_DEVICE_OBJECT {
  407. DEVICE_OBJECT DeviceObject;
  408. //
  409. // The following field tells how many requests for this volume have
  410. // either been enqueued to ExWorker threads or are currently being
  411. // serviced by ExWorker threads. If the number goes above
  412. // a certain threshold, put the request on the overflow queue to be
  413. // executed later.
  414. //
  415. ULONG PostedRequestCount;
  416. //
  417. // The following field indicates the number of IRP's waiting
  418. // to be serviced in the overflow queue.
  419. //
  420. ULONG OverflowQueueCount;
  421. //
  422. // The following field contains the queue header of the overflow queue.
  423. // The Overflow queue is a list of IRP's linked via the IRP's ListEntry
  424. // field.
  425. //
  426. LIST_ENTRY OverflowQueue;
  427. //
  428. // The following spinlock protects access to all the above fields.
  429. //
  430. KSPIN_LOCK OverflowQueueSpinLock;
  431. //
  432. // This is a common head for the FAT volume file
  433. //
  434. FSRTL_COMMON_FCB_HEADER VolumeFileHeader;
  435. //
  436. // This is the file system specific volume control block.
  437. //
  438. VCB Vcb;
  439. } VOLUME_DEVICE_OBJECT;
  440. typedef VOLUME_DEVICE_OBJECT *PVOLUME_DEVICE_OBJECT;
  441. //
  442. // This is the structure used to contains the short name for a file
  443. //
  444. typedef struct _FILE_NAME_NODE {
  445. //
  446. // This points back to the Fcb for this file.
  447. //
  448. struct _FCB *Fcb;
  449. //
  450. // This is the name of this node.
  451. //
  452. union {
  453. OEM_STRING Oem;
  454. UNICODE_STRING Unicode;
  455. } Name;
  456. //
  457. // Marker so we can figure out what kind of name we opened up in
  458. // Fcb searches
  459. //
  460. BOOLEAN FileNameDos;
  461. //
  462. // And the links. Our parent Dcb has a pointer to the root entry.
  463. //
  464. RTL_SPLAY_LINKS Links;
  465. } FILE_NAME_NODE;
  466. typedef FILE_NAME_NODE *PFILE_NAME_NODE;
  467. //
  468. // This structure contains fields which must be in non-paged pool.
  469. //
  470. typedef struct _NON_PAGED_FCB {
  471. //
  472. // The following field contains a record of special pointers used by
  473. // MM and Cache to manipluate section objects. Note that the values
  474. // are set outside of the file system. However the file system on an
  475. // open/create will set the file object's SectionObject field to point
  476. // to this field
  477. //
  478. SECTION_OBJECT_POINTERS SectionObjectPointers;
  479. //
  480. // This context is non-zero only if the file currently has asynchronous
  481. // non-cached valid data length extending writes. It allows
  482. // synchronization between pending writes and other operations.
  483. //
  484. ULONG OutstandingAsyncWrites;
  485. //
  486. // This event is set when OutstandingAsyncWrites transitions to zero.
  487. //
  488. PKEVENT OutstandingAsyncEvent;
  489. //
  490. // This is the mutex that is inserted into the FCB_ADVANCED_HEADER
  491. // FastMutex field
  492. //
  493. FAST_MUTEX AdvancedFcbHeaderMutex;
  494. } NON_PAGED_FCB;
  495. typedef NON_PAGED_FCB *PNON_PAGED_FCB;
  496. //
  497. // The Fcb/Dcb record corresponds to every open file and directory, and to
  498. // every directory on an opened path. They are ordered in two queues, one
  499. // queue contains every Fcb/Dcb record off of FatData.FcbQueue, the other
  500. // queue contains only device specific records off of Vcb.VcbSpecificFcbQueue
  501. //
  502. typedef enum _FCB_CONDITION {
  503. FcbGood = 1,
  504. FcbBad,
  505. FcbNeedsToBeVerified
  506. } FCB_CONDITION;
  507. typedef struct _FCB {
  508. //
  509. // The following field is used for fast I/O
  510. //
  511. // The following comments refer to the use of the AllocationSize field
  512. // of the FsRtl-defined header to the nonpaged Fcb.
  513. //
  514. // For a directory when we create a Dcb we will not immediately
  515. // initialize the cache map, instead we will postpone it until our first
  516. // call to FatReadDirectoryFile or FatPrepareWriteDirectoryFile.
  517. // At that time we will search the Fat to find out the current allocation
  518. // size (by calling FatLookupFileAllocationSize) and then initialize the
  519. // cache map to this allocation size.
  520. //
  521. // For a file when we create an Fcb we will not immediately initialize
  522. // the cache map, instead we will postpone it until we need it and
  523. // then we determine the allocation size from either searching the
  524. // fat to determine the real file allocation, or from the allocation
  525. // that we've just allocated if we're creating a file.
  526. //
  527. // A value of -1 indicates that we do not know what the current allocation
  528. // size really is, and need to examine the fat to find it. A value
  529. // of than -1 is the real file/directory allocation size.
  530. //
  531. // Whenever we need to extend the allocation size we call
  532. // FatAddFileAllocation which (if we're really extending the allocation)
  533. // will modify the Fat, Mcb, and update this field. The caller
  534. // of FatAddFileAllocation is then responsible for altering the Cache
  535. // map size.
  536. //
  537. // We are now using the ADVANCED fcb header to support filter contexts
  538. // at the stream level
  539. //
  540. FSRTL_ADVANCED_FCB_HEADER Header;
  541. //
  542. // This structure contains fields which must be in non-paged pool.
  543. //
  544. PNON_PAGED_FCB NonPaged;
  545. //
  546. // The head of the fat alloaction chain. FirstClusterOfFile == 0
  547. // means that the file has no current allocation.
  548. //
  549. ULONG FirstClusterOfFile;
  550. //
  551. // The links for the queue of all fcbs for a specific dcb off of
  552. // Dcb.ParentDcbQueue. For the root directory this queue is empty
  553. // For a non-existent fcb this queue is off of the non existent
  554. // fcb queue entry in the vcb.
  555. //
  556. LIST_ENTRY ParentDcbLinks;
  557. //
  558. // A pointer to the Dcb that is the parent directory containing
  559. // this fcb. If this record itself is the root dcb then this field
  560. // is null.
  561. //
  562. struct _FCB *ParentDcb;
  563. //
  564. // A pointer to the Vcb containing this Fcb
  565. //
  566. PVCB Vcb;
  567. //
  568. // The internal state of the Fcb. This is a collection Fcb state flags.
  569. // Also the shared access for each time this file/directory is opened.
  570. //
  571. ULONG FcbState;
  572. FCB_CONDITION FcbCondition;
  573. SHARE_ACCESS ShareAccess;
  574. #ifdef SYSCACHE_COMPILE
  575. //
  576. // For syscache we keep a bitmask that tells us if we have dispatched IO for
  577. // the page aligned chunks of the stream.
  578. //
  579. PULONG WriteMask;
  580. ULONG WriteMaskData;
  581. #endif
  582. //
  583. // A count of the number of file objects that have been opened for
  584. // this file/directory, but not yet been cleaned up yet. This count
  585. // is only used for data file objects, not for the Acl or Ea stream
  586. // file objects. This count gets decremented in FatCommonCleanup,
  587. // while the OpenCount below gets decremented in FatCommonClose.
  588. //
  589. CLONG UncleanCount;
  590. //
  591. // A count of the number of file objects that have opened
  592. // this file/directory. For files & directories the FsContext of the
  593. // file object points to this record.
  594. //
  595. CLONG OpenCount;
  596. //
  597. // A count of how many of "UncleanCount" handles were opened for
  598. // non-cached I/O.
  599. //
  600. CLONG NonCachedUncleanCount;
  601. //
  602. // The following field is used to locate the dirent for this fcb/dcb.
  603. // All directory are opened as mapped files so the only additional
  604. // information we need to locate this dirent (beside its parent directory)
  605. // is the byte offset for the dirent. Note that for the root dcb
  606. // this field is not used.
  607. //
  608. VBO DirentOffsetWithinDirectory;
  609. //
  610. // The following field is filled in when there is an Lfn associated
  611. // with this file. It is the STARTING offset of the Lfn.
  612. //
  613. VBO LfnOffsetWithinDirectory;
  614. //
  615. // Thess entries is kept in ssync with the dirent. It allows a more
  616. // accurate verify capability and speeds up FatFastQueryBasicInfo().
  617. //
  618. LARGE_INTEGER CreationTime;
  619. LARGE_INTEGER LastAccessTime;
  620. LARGE_INTEGER LastWriteTime;
  621. //
  622. // Valid data to disk
  623. //
  624. ULONG ValidDataToDisk;
  625. //
  626. // The following field contains the retrieval mapping structure
  627. // for the file/directory. Note that for the Root Dcb this
  628. // structure is set at mount time. Also note that in this
  629. // implementation of Fat the Mcb really maps VBOs to LBOs and not
  630. // VBNs to LBNs.
  631. //
  632. LARGE_MCB Mcb;
  633. //
  634. // The following union is cased off of the node type code for the fcb.
  635. // There is a seperate case for the directory versus file fcbs.
  636. //
  637. union {
  638. //
  639. // A Directory Control Block (Dcb)
  640. //
  641. struct {
  642. //
  643. // A queue of all the fcbs/dcbs that are opened under this
  644. // Dcb.
  645. //
  646. LIST_ENTRY ParentDcbQueue;
  647. //
  648. // The following field points to the file object used to do I/O to
  649. // the directory file for this dcb. The directory file maps the
  650. // sectors for the directory. This field is initialized by
  651. // CreateRootDcb but is left null by CreateDcb. It isn't
  652. // until we try to read/write the directory file that we
  653. // create the stream file object for non root dcbs.
  654. //
  655. ULONG DirectoryFileOpenCount;
  656. PFILE_OBJECT DirectoryFile;
  657. //
  658. // If the UnusedDirentVbo is != 0xffffffff, then the dirent at this
  659. // offset is guarenteed to unused. A value of 0xffffffff means
  660. // it has yet to be initialized. Note that a value beyond the
  661. // end of allocation means that there an unused dirent, but we
  662. // will have to allocate another cluster to use it.
  663. //
  664. // DeletedDirentHint contains lowest possible VBO of a deleted
  665. // dirent (assuming as above that it is not 0xffffffff).
  666. //
  667. VBO UnusedDirentVbo;
  668. VBO DeletedDirentHint;
  669. //
  670. // The following two entries links together all the Fcbs
  671. // opened under this Dcb sorted in a splay tree by name.
  672. //
  673. // I'd like to go into why we have (and must have) two separate
  674. // splay trees within the current fastfat architecture. I will
  675. // provide some insight into what would have to change if we
  676. // wanted to have a single UNICODE tree.
  677. //
  678. // What makes FAT unique is that both Oem and Unicode names sit
  679. // side by side on disk. Several unique UNICODE names coming
  680. // into fastfat can match a single OEM on-disk name, and there
  681. // is really no way to enumerate all the possible UNICODE
  682. // source strings that can map to a given OEM name. This argues
  683. // for converting the incomming UNICODE name into OEM, and then
  684. // running through an OEM splay tree of the open files. This
  685. // works well when there are only OEM names on disk.
  686. //
  687. // The UNICODE name on disk can be VERY different from the short
  688. // name in the DIRENT and not even representable in the OEM code
  689. // page. Even if it were representable in OEM, it is possible
  690. // that a case varient of the original UNICODE name would match
  691. // a different OEM name, causing us to miss the Fcb in the
  692. // prefix lookup phase. In these cases, we must put UNICODE
  693. // name in the splay to guarentee that we find any case varient
  694. // of the input UNICODE name. See the routine description of
  695. // FatConstructNamesInFcb() for a detailed analysis of how we
  696. // detect this case.
  697. //
  698. // The fundamental limitation we are imposing here is that if
  699. // an Fcb exists for an open file, we MUST find it during the
  700. // prefix stage. This is a basic premise of the create path
  701. // in fastfat. In fact if we later find it gravelling through
  702. // the disk (but not the splay tree), we will bug check if we
  703. // try to add a duplicate entry to the splay tree (not to
  704. // mention having two Fcbs). If we had some mechanism to deal
  705. // with cases (and they would be rare) that we don't find the
  706. // entry in the splay tree, but the Fcb is actually in there,
  707. // then we could go to a single UNICODE splay tree. While
  708. // this uses more pool for the splay tree, and makes string
  709. // compares maybe take a bit as longer, it would eliminate the
  710. // need for any NLS conversion during the prefix phase, so it
  711. // might really be a net win.
  712. //
  713. // The current scheme was optimized for non-extended names
  714. // (i.e. US names). As soon as you start using extended
  715. // characters, then it is clearly a win as many code paths
  716. // become active that would otherwise not be needed if we
  717. // only had a single UNICODE splay tree.
  718. //
  719. // We may think about changing this someday.
  720. //
  721. PRTL_SPLAY_LINKS RootOemNode;
  722. PRTL_SPLAY_LINKS RootUnicodeNode;
  723. //
  724. // The following field keeps track of free dirents, i.e.,
  725. // dirents that are either unallocated for deleted.
  726. //
  727. RTL_BITMAP FreeDirentBitmap;
  728. //
  729. // Since the FCB specific part of this union is larger, use
  730. // the slack here for an initial bitmap buffer. Currently
  731. // there is enough space here for an 8K cluster.
  732. //
  733. ULONG FreeDirentBitmapBuffer[1];
  734. } Dcb;
  735. //
  736. // A File Control Block (Fcb)
  737. //
  738. struct {
  739. //
  740. // The following field is used by the filelock module
  741. // to maintain current byte range locking information.
  742. //
  743. FILE_LOCK FileLock;
  744. //
  745. // The following field is used by the oplock module
  746. // to maintain current oplock information.
  747. //
  748. OPLOCK Oplock;
  749. //
  750. // This pointer is used to detect writes that eminated in the
  751. // cache manager's lazywriter. It prevents lazy writer threads,
  752. // who already have the Fcb shared, from trying to acquire it
  753. // exclusive, and thus causing a deadlock.
  754. //
  755. PVOID LazyWriteThread;
  756. } Fcb;
  757. } Specific;
  758. //
  759. // The following field is used to verify that the Ea's for a file
  760. // have not changed between calls to query for Ea's. It is compared
  761. // with a similar field in a Ccb.
  762. //
  763. // IMPORTANT!! **** DO NOT MOVE THIS FIELD ****
  764. //
  765. // The slack space in the union above is computed from
  766. // the field offset of the EaModificationCount.
  767. //
  768. ULONG EaModificationCount;
  769. //
  770. // The following field is the fully qualified file name for this FCB/DCB
  771. // starting from the root of the volume, and last file name in the
  772. // fully qualified name.
  773. //
  774. FILE_NAME_NODE ShortName;
  775. //
  776. // The following field is only filled in if it is needed with the user's
  777. // opened path
  778. //
  779. UNICODE_STRING FullFileName;
  780. USHORT FinalNameLength;
  781. //
  782. // To make life simpler we also keep in the Fcb/Dcb a current copy of
  783. // the fat attribute byte for the file/directory. This field must
  784. // also be updated when we create the Fcb, modify the File, or verify
  785. // the Fcb
  786. //
  787. UCHAR DirentFatFlags;
  788. //
  789. // The case preserved long filename
  790. //
  791. UNICODE_STRING ExactCaseLongName;
  792. //
  793. // If the UNICODE Lfn is fully expressible in the system Oem code
  794. // page, then we will store it in a prefix table, otherwise we will
  795. // store the last UNICODE name in the Fcb. In both cases the name
  796. // has been upcased.
  797. //
  798. // Note that we may need neither of these fields if an LFN was strict
  799. // 8.3 or differed only in case. Indeed if there wasn't an LFN, we
  800. // don't need them at all.
  801. //
  802. union {
  803. //
  804. // This first field is present if FCB_STATE_HAS_OEM_LONG_NAME
  805. // is set in the FcbState.
  806. //
  807. FILE_NAME_NODE Oem;
  808. //
  809. // This first field is present if FCB_STATE_HAS_UNICODE_LONG_NAME
  810. // is set in the FcbState.
  811. //
  812. FILE_NAME_NODE Unicode;
  813. } LongName;
  814. //
  815. // Defragmentation / ReallocateOnWrite synchronization object. This
  816. // is filled in by FatMoveFile() and affects the read and write paths.
  817. //
  818. PKEVENT MoveFileEvent;
  819. } FCB, *PFCB;
  820. #ifndef BUILDING_FSKDEXT
  821. //
  822. // DCB clashes with a type defined outside the filesystems, in headers
  823. // pulled in by FSKD. We don't need this typedef for fskd anyway....
  824. //
  825. typedef FCB DCB;
  826. typedef DCB *PDCB;
  827. #endif
  828. //
  829. // Here are the Fcb state fields.
  830. //
  831. #define FCB_STATE_DELETE_ON_CLOSE (0x00000001)
  832. #define FCB_STATE_TRUNCATE_ON_CLOSE (0x00000002)
  833. #define FCB_STATE_PAGING_FILE (0x00000004)
  834. #define FCB_STATE_FORCE_MISS_IN_PROGRESS (0x00000008)
  835. #define FCB_STATE_FLUSH_FAT (0x00000010)
  836. #define FCB_STATE_TEMPORARY (0x00000020)
  837. #define FCB_STATE_SYSTEM_FILE (0x00000080)
  838. #define FCB_STATE_NAMES_IN_SPLAY_TREE (0x00000100)
  839. #define FCB_STATE_HAS_OEM_LONG_NAME (0x00000200)
  840. #define FCB_STATE_HAS_UNICODE_LONG_NAME (0x00000400)
  841. #define FCB_STATE_DELAY_CLOSE (0x00000800)
  842. //
  843. // Copies of the dirent's FAT_DIRENT_NT_BYTE_* flags for
  844. // preserving case of the short name of a file
  845. //
  846. #define FCB_STATE_8_LOWER_CASE (0x00001000)
  847. #define FCB_STATE_3_LOWER_CASE (0x00002000)
  848. //
  849. // This is the slack allocation in the Dcb part of the UNION above
  850. //
  851. #define DCB_UNION_SLACK_SPACE ((ULONG) \
  852. (FIELD_OFFSET(DCB, EaModificationCount) - \
  853. FIELD_OFFSET(DCB, Specific.Dcb.FreeDirentBitmapBuffer)) \
  854. )
  855. //
  856. // This is the special (64bit) allocation size that indicates the
  857. // real size must be retrieved from disk. Define it here so we
  858. // avoid excessive magic numbering around the driver.
  859. //
  860. #define FCB_LOOKUP_ALLOCATIONSIZE_HINT ((LONGLONG) -1)
  861. //
  862. // The Ccb record is allocated for every file object. Note that this
  863. // record is exactly 0x34 long on x86 so that it will fit into a 0x40
  864. // piece of pool. Please carefully consider modifications.
  865. //
  866. // Define the Flags field.
  867. //
  868. #define CCB_FLAG_MATCH_ALL (0x0001)
  869. #define CCB_FLAG_SKIP_SHORT_NAME_COMPARE (0x0002)
  870. //
  871. // This tells us whether we allocated buffers to hold search templates.
  872. //
  873. #define CCB_FLAG_FREE_OEM_BEST_FIT (0x0004)
  874. #define CCB_FLAG_FREE_UNICODE (0x0008)
  875. //
  876. // These flags prevents cleanup from updating the modify time, etc.
  877. //
  878. #define CCB_FLAG_USER_SET_LAST_WRITE (0x0010)
  879. #define CCB_FLAG_USER_SET_LAST_ACCESS (0x0020)
  880. #define CCB_FLAG_USER_SET_CREATION (0x0040)
  881. //
  882. // This bit says the file object associated with this Ccb was opened for
  883. // read only access.
  884. //
  885. #define CCB_FLAG_READ_ONLY (0x0080)
  886. //
  887. // These flags, are used is DASD handles in read and write.
  888. //
  889. #define CCB_FLAG_DASD_FLUSH_DONE (0x0100)
  890. #define CCB_FLAG_DASD_PURGE_DONE (0x0200)
  891. //
  892. // This flag keeps track of a handle that was opened for
  893. // DELETE_ON_CLOSE.
  894. //
  895. #define CCB_FLAG_DELETE_ON_CLOSE (0x0400)
  896. //
  897. // This flag keeps track of which side of the name pair on the file
  898. // associated with the handle was opened
  899. //
  900. #define CCB_FLAG_OPENED_BY_SHORTNAME (0x0800)
  901. //
  902. // This flag indicates that the query template has not been upcased
  903. // (i.e., query should be case-insensitive)
  904. //
  905. #define CCB_FLAG_QUERY_TEMPLATE_MIXED (0x1000)
  906. //
  907. // This flag indicates that reads and writes via this DASD handle
  908. // are allowed to start or extend past the end of file.
  909. //
  910. #define CCB_FLAG_ALLOW_EXTENDED_DASD_IO (0x2000)
  911. //
  912. // This flag indicates we want to match volume labels in directory
  913. // searches (important for the root dir defrag).
  914. //
  915. #define CCB_FLAG_MATCH_VOLUME_ID (0x4000)
  916. //
  917. // This flag indicates the ccb has been converted over into a
  918. // close context for asynchronous/delayed closing of the handle.
  919. //
  920. #define CCB_FLAG_CLOSE_CONTEXT (0x8000)
  921. //
  922. // This flag indicates that when the handle is closed, we want
  923. // a physical dismount to occur.
  924. //
  925. #define CCB_FLAG_COMPLETE_DISMOUNT (0x10000)
  926. //
  927. // This flag indicates the handle may not call priveleged
  928. // FSCTL which modify the volume.
  929. //
  930. #define CCB_FLAG_MANAGE_VOLUME_ACCESS (0x20000)
  931. typedef struct _CCB {
  932. //
  933. // Type and size of this record (must be FAT_NTC_CCB)
  934. //
  935. NODE_TYPE_CODE NodeTypeCode;
  936. NODE_BYTE_SIZE NodeByteSize;
  937. //
  938. // Define a 24bit wide field for Flags, but a UCHAR for Wild Cards Present
  939. // since it is used so often. Line these up on byte boundaries for grins.
  940. //
  941. ULONG Flags:24;
  942. BOOLEAN ContainsWildCards;
  943. //
  944. // Overlay a close context on the data of the CCB. The remaining
  945. // fields are not useful during close, and we would like to avoid
  946. // paying extra pool for it.
  947. //
  948. union {
  949. struct {
  950. //
  951. // Save the offset to start search from.
  952. //
  953. VBO OffsetToStartSearchFrom;
  954. //
  955. // The query template is used to filter directory query requests.
  956. // It originally is set to null and on the first call the NtQueryDirectory
  957. // it is set to the input filename or "*" if the name is not supplied.
  958. // All subsquent queries then use this template.
  959. //
  960. // The Oem structure are unions because if the name is wild we store
  961. // the arbitrary length string, while if the name is constant we store
  962. // 8.3 representation for fast comparison.
  963. //
  964. union {
  965. //
  966. // If the template contains a wild card use this.
  967. //
  968. OEM_STRING Wild;
  969. //
  970. // If the name is constant, use this part.
  971. //
  972. FAT8DOT3 Constant;
  973. } OemQueryTemplate;
  974. UNICODE_STRING UnicodeQueryTemplate;
  975. //
  976. // The field is compared with the similar field in the Fcb to determine
  977. // if the Ea's for a file have been modified.
  978. //
  979. ULONG EaModificationCount;
  980. //
  981. // The following field is used as an offset into the Eas for a
  982. // particular file. This will be the offset for the next
  983. // Ea to return. A value of 0xffffffff indicates that the
  984. // Ea's are exhausted.
  985. //
  986. ULONG OffsetOfNextEaToReturn;
  987. };
  988. CLOSE_CONTEXT CloseContext;
  989. };
  990. } CCB;
  991. typedef CCB *PCCB;
  992. //
  993. // The Irp Context record is allocated for every orginating Irp. It is
  994. // created by the Fsd dispatch routines, and deallocated by the FatComplete
  995. // request routine. It contains a structure called of type REPINNED_BCBS
  996. // which is used to retain pinned bcbs needed to handle abnormal termination
  997. // unwinding.
  998. //
  999. #define REPINNED_BCBS_ARRAY_SIZE (4)
  1000. typedef struct _REPINNED_BCBS {
  1001. //
  1002. // A pointer to the next structure contains additional repinned bcbs
  1003. //
  1004. struct _REPINNED_BCBS *Next;
  1005. //
  1006. // A fixed size array of pinned bcbs. Whenever a new bcb is added to
  1007. // the repinned bcb structure it is added to this array. If the
  1008. // array is already full then another repinned bcb structure is allocated
  1009. // and pointed to with Next.
  1010. //
  1011. PBCB Bcb[ REPINNED_BCBS_ARRAY_SIZE ];
  1012. } REPINNED_BCBS;
  1013. typedef REPINNED_BCBS *PREPINNED_BCBS;
  1014. typedef struct _IRP_CONTEXT {
  1015. //
  1016. // Type and size of this record (must be FAT_NTC_IRP_CONTEXT)
  1017. //
  1018. NODE_TYPE_CODE NodeTypeCode;
  1019. NODE_BYTE_SIZE NodeByteSize;
  1020. //
  1021. // This structure is used for posting to the Ex worker threads.
  1022. //
  1023. WORK_QUEUE_ITEM WorkQueueItem;
  1024. //
  1025. // A pointer to the originating Irp.
  1026. //
  1027. PIRP OriginatingIrp;
  1028. //
  1029. // Originating Device (required for workque algorithms)
  1030. //
  1031. PDEVICE_OBJECT RealDevice;
  1032. //
  1033. // Originating Vcb (required for exception handling)
  1034. // On mounts, this will be set before any exceptions
  1035. // indicating corruption can be thrown.
  1036. //
  1037. PVCB Vcb;
  1038. //
  1039. // Major and minor function codes copied from the Irp
  1040. //
  1041. UCHAR MajorFunction;
  1042. UCHAR MinorFunction;
  1043. //
  1044. // The following fields indicate if we can wait/block for a resource
  1045. // or I/O, if we are to do everything write through, and if this
  1046. // entry into the Fsd is a recursive call.
  1047. //
  1048. UCHAR PinCount;
  1049. ULONG Flags;
  1050. //
  1051. // The following field contains the NTSTATUS value used when we are
  1052. // unwinding due to an exception
  1053. //
  1054. NTSTATUS ExceptionStatus;
  1055. //
  1056. // The following context block is used for non-cached Io
  1057. //
  1058. struct _FAT_IO_CONTEXT *FatIoContext;
  1059. //
  1060. // For a abnormal termination unwinding this field contains the Bcbs
  1061. // that are kept pinned until the Irp is completed.
  1062. //
  1063. REPINNED_BCBS Repinned;
  1064. } IRP_CONTEXT;
  1065. typedef IRP_CONTEXT *PIRP_CONTEXT;
  1066. #define IRP_CONTEXT_FLAG_DISABLE_DIRTY (0x00000001)
  1067. #define IRP_CONTEXT_FLAG_WAIT (0x00000002)
  1068. #define IRP_CONTEXT_FLAG_WRITE_THROUGH (0x00000004)
  1069. #define IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH (0x00000008)
  1070. #define IRP_CONTEXT_FLAG_RECURSIVE_CALL (0x00000010)
  1071. #define IRP_CONTEXT_FLAG_DISABLE_POPUPS (0x00000020)
  1072. #define IRP_CONTEXT_FLAG_DEFERRED_WRITE (0x00000040)
  1073. #define IRP_CONTEXT_FLAG_VERIFY_READ (0x00000080)
  1074. #define IRP_CONTEXT_STACK_IO_CONTEXT (0x00000100)
  1075. #define IRP_CONTEXT_FLAG_IN_FSP (0x00000200)
  1076. #define IRP_CONTEXT_FLAG_USER_IO (0x00000400) // for performance counters
  1077. #define IRP_CONTEXT_FLAG_DISABLE_RAISE (0x00000800)
  1078. #define IRP_CONTEXT_FLAG_PARENT_BY_CHILD (0x80000000)
  1079. //
  1080. // Context structure for non-cached I/O calls. Most of these fields
  1081. // are actually only required for the Read/Write Multiple routines, but
  1082. // the caller must allocate one as a local variable anyway before knowing
  1083. // whether there are multiple requests are not. Therefore, a single
  1084. // structure is used for simplicity.
  1085. //
  1086. typedef struct _FAT_IO_CONTEXT {
  1087. //
  1088. // These two field are used for multiple run Io
  1089. //
  1090. LONG IrpCount;
  1091. PIRP MasterIrp;
  1092. //
  1093. // MDL to describe partial sector zeroing
  1094. //
  1095. PMDL ZeroMdl;
  1096. union {
  1097. //
  1098. // This element handles the asychronous non-cached Io
  1099. //
  1100. struct {
  1101. PERESOURCE Resource;
  1102. PERESOURCE Resource2;
  1103. ERESOURCE_THREAD ResourceThreadId;
  1104. ULONG RequestedByteCount;
  1105. PFILE_OBJECT FileObject;
  1106. PNON_PAGED_FCB NonPagedFcb;
  1107. } Async;
  1108. //
  1109. // and this element the sycnrhonous non-cached Io
  1110. //
  1111. KEVENT SyncEvent;
  1112. } Wait;
  1113. } FAT_IO_CONTEXT;
  1114. typedef FAT_IO_CONTEXT *PFAT_IO_CONTEXT;
  1115. //
  1116. // An array of these structures is passed to FatMultipleAsync describing
  1117. // a set of runs to execute in parallel.
  1118. //
  1119. typedef struct _IO_RUNS {
  1120. LBO Lbo;
  1121. VBO Vbo;
  1122. ULONG Offset;
  1123. ULONG ByteCount;
  1124. PIRP SavedIrp;
  1125. } IO_RUN;
  1126. typedef IO_RUN *PIO_RUN;
  1127. //
  1128. // This structure is used by FatDeleteDirent to preserve the first cluster
  1129. // and file size info for undelete utilities.
  1130. //
  1131. typedef struct _DELETE_CONTEXT {
  1132. ULONG FileSize;
  1133. ULONG FirstClusterOfFile;
  1134. } DELETE_CONTEXT;
  1135. typedef DELETE_CONTEXT *PDELETE_CONTEXT;
  1136. //
  1137. // This record is used with to set a flush to go off one second after the
  1138. // first write on slow devices with a physical indication of activity, like
  1139. // a floppy. This is an attempt to keep the red light on.
  1140. //
  1141. typedef struct _DEFERRED_FLUSH_CONTEXT {
  1142. KDPC Dpc;
  1143. KTIMER Timer;
  1144. WORK_QUEUE_ITEM Item;
  1145. PFILE_OBJECT File;
  1146. } DEFERRED_FLUSH_CONTEXT;
  1147. typedef DEFERRED_FLUSH_CONTEXT *PDEFERRED_FLUSH_CONTEXT;
  1148. //
  1149. // This structure is used for the FatMarkVolumeClean callbacks.
  1150. //
  1151. typedef struct _CLEAN_AND_DIRTY_VOLUME_PACKET {
  1152. WORK_QUEUE_ITEM Item;
  1153. PIRP Irp;
  1154. PVCB Vcb;
  1155. PKEVENT Event;
  1156. } CLEAN_AND_DIRTY_VOLUME_PACKET, *PCLEAN_AND_DIRTY_VOLUME_PACKET;
  1157. //
  1158. // This structure is used when a page fault is running out of stack.
  1159. //
  1160. typedef struct _PAGING_FILE_OVERFLOW_PACKET {
  1161. PIRP Irp;
  1162. PFCB Fcb;
  1163. } PAGING_FILE_OVERFLOW_PACKET, *PPAGING_FILE_OVERFLOW_PACKET;
  1164. //
  1165. // This structure is used to access the EaFile.
  1166. //
  1167. #define EA_BCB_ARRAY_SIZE 8
  1168. typedef struct _EA_RANGE {
  1169. PCHAR Data;
  1170. ULONG StartingVbo;
  1171. ULONG Length;
  1172. USHORT BcbChainLength;
  1173. BOOLEAN AuxilaryBuffer;
  1174. PBCB *BcbChain;
  1175. PBCB BcbArray[EA_BCB_ARRAY_SIZE];
  1176. } EA_RANGE, *PEA_RANGE;
  1177. #define EA_RANGE_HEADER_SIZE (FIELD_OFFSET( EA_RANGE, BcbArray ))
  1178. //
  1179. // These symbols are used by the upcase/downcase routines.
  1180. //
  1181. #define WIDE_LATIN_CAPITAL_A (0xff21)
  1182. #define WIDE_LATIN_CAPITAL_Z (0xff3a)
  1183. #define WIDE_LATIN_SMALL_A (0xff41)
  1184. #define WIDE_LATIN_SMALL_Z (0xff5a)
  1185. //
  1186. // These values are returned by FatInterpretClusterType.
  1187. //
  1188. typedef enum _CLUSTER_TYPE {
  1189. FatClusterAvailable,
  1190. FatClusterReserved,
  1191. FatClusterBad,
  1192. FatClusterLast,
  1193. FatClusterNext
  1194. } CLUSTER_TYPE;
  1195. #endif // _FATSTRUC_