-/* $Id: vfat.h,v 1.60 2003/10/11 17:51:56 hbirr Exp $ */
-
-#include <ddk/ntifs.h>
-
-#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
+#include <debug.h>
+#include <ntifs.h>
+#include <ntdddisk.h>
+#include <reactos/helper.h>
+
+#ifdef __GNUC__
+#include <ndk/ntndk.h>
+#include <ccros.h>
+
+#define USE_ROS_CC_AND_FS
+#else
+#define KEBUGCHECK KeBugCheck
+#define KEBUGCHECKEX KeBugCheckEx
#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
+#define ROUND_UP(N, S) ROUND_DOWN((N) + (S) - 1, (S))
+#endif
+#include <pshpack1.h>
struct _BootSector
{
unsigned char magic0, res0, magic1;
unsigned char Drive, Res1, Sig;
unsigned long VolumeID;
unsigned char VolumeLabel[11], SysType[8];
- unsigned char Res2[446];
- unsigned long Signatur1;
-} __attribute__((packed));
+ unsigned char Res2[448];
+ unsigned short Signatur1;
+};
struct _BootSector32
{
unsigned char ExtBootSignature; // 66
unsigned long VolumeID; // 67
unsigned char VolumeLabel[11], SysType[8]; // 71
- unsigned char Res2[418]; // 90
- unsigned long Signature1; // 508
-} __attribute__((packed));
+ unsigned char Res2[420]; // 90
+ unsigned short Signature1; // 510
+};
+
+struct _BootSectorFatX
+{
+ unsigned char SysType[4]; // 0
+ unsigned long VolumeID; // 4
+ unsigned long SectorsPerCluster; // 8
+ unsigned short FATCount; // 12
+ unsigned long Unknown; // 14
+ unsigned char Unused[4078]; // 18
+};
struct _FsInfoSector
{
unsigned long NextCluster; // 492
unsigned char Res7[12]; // 496
unsigned long Signatur2; // 508
-} __attribute__((packed));
+};
typedef struct _BootSector BootSector;
-#define VFAT_CASE_LOWER_BASE 8 // base is lower case
-#define VFAT_CASE_LOWER_EXT 16 // extension is lower case
-
-#define ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
-#define ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
-#define ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
-#define ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
-
struct _FATDirEntry
{
- unsigned char Filename[8], Ext[3];
+ union
+ {
+ struct { unsigned char Filename[8], Ext[3]; };
+ unsigned char ShortName[11];
+ };
unsigned char Attrib;
unsigned char lCase;
unsigned char CreationTimeMs;
unsigned short UpdateDate; //date create/update
unsigned short FirstCluster;
unsigned long FileSize;
-} __attribute__((packed));
+};
+
+typedef struct _FATDirEntry FAT_DIR_ENTRY, *PFAT_DIR_ENTRY;
-typedef struct _FATDirEntry FATDirEntry, FAT_DIR_ENTRY, *PFAT_DIR_ENTRY;
+struct _FATXDirEntry
+{
+ unsigned char FilenameLength; // 0
+ unsigned char Attrib; // 1
+ unsigned char Filename[42]; // 2
+ unsigned long FirstCluster; // 44
+ unsigned long FileSize; // 48
+ unsigned short UpdateTime; // 52
+ unsigned short UpdateDate; // 54
+ unsigned short CreationTime; // 56
+ unsigned short CreationDate; // 58
+ unsigned short AccessTime; // 60
+ unsigned short AccessDate; // 62
+};
struct _slot
{
WCHAR name5_10[6]; // 6 more characters in name
unsigned char start[2]; // starting cluster number
WCHAR name11_12[2]; // last 2 characters in name
-} __attribute__((packed));
-
+};
typedef struct _slot slot;
+#include <poppack.h>
+
+#define VFAT_CASE_LOWER_BASE 8 // base is lower case
+#define VFAT_CASE_LOWER_EXT 16 // extension is lower case
+
+#define LONGNAME_MAX_LENGTH 256 // max length for a long filename
+
+#define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat)))
+#define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
+#define ENTRY_END(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat)))
+
+#define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
+#define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
+#define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
+#define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
+
+#define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5)
+#define FATX_ENTRY_END(DirEntry) ((DirEntry)->FilenameLength == 0xff)
+#define FATX_ENTRY_LONG(DirEntry) (FALSE)
+#define FATX_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
+
+#define FAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FAT_DIR_ENTRY))
+#define FATX_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATX_DIR_ENTRY))
+
+typedef struct _FATXDirEntry FATX_DIR_ENTRY, *PFATX_DIR_ENTRY;
+
+union _DIR_ENTRY
+{
+ FAT_DIR_ENTRY Fat;
+ FATX_DIR_ENTRY FatX;
+};
+
+typedef union _DIR_ENTRY DIR_ENTRY, *PDIR_ENTRY;
+
#define BLOCKSIZE 512
-#define FAT16 (1)
-#define FAT12 (2)
-#define FAT32 (3)
+#define FAT16 (1)
+#define FAT12 (2)
+#define FAT32 (3)
+#define FATX16 (4)
+#define FATX32 (5)
#define VCB_VOLUME_LOCKED 0x0001
#define VCB_DISMOUNT_PENDING 0x0002
+#define VCB_IS_FATX 0x0004
+#define VCB_IS_DIRTY 0x4000 /* Volume is dirty */
+#define VCB_CLEAR_DIRTY 0x8000 /* Clean dirty flag at shutdown */
typedef struct
{
ULONG NumberOfClusters;
ULONG FatType;
ULONG Sectors;
+ BOOLEAN FixedMedia;
} FATINFO, *PFATINFO;
struct _VFATFCB;
+struct _VFAT_DIRENTRY_CONTEXT;
typedef struct _HASHENTRY
{
}
HASHENTRY;
-#define FCB_HASH_TABLE_SIZE 1024
+#define FCB_HASH_TABLE_SIZE 65536
-typedef struct
+typedef struct DEVICE_EXTENSION *PDEVICE_EXTENSION;
+
+typedef NTSTATUS (*PGET_NEXT_CLUSTER)(PDEVICE_EXTENSION,ULONG,PULONG);
+typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER)(PDEVICE_EXTENSION,PULONG);
+typedef NTSTATUS (*PWRITE_CLUSTER)(PDEVICE_EXTENSION,ULONG,ULONG,PULONG);
+
+typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY)(PVOID*,PVOID*,struct _VFATFCB*,struct _VFAT_DIRENTRY_CONTEXT*,BOOLEAN);
+
+typedef struct DEVICE_EXTENSION
{
ERESOURCE DirResource;
ERESOURCE FatResource;
KSPIN_LOCK FcbListLock;
LIST_ENTRY FcbListHead;
- struct _HASHENTRY* FcbHashTable[FCB_HASH_TABLE_SIZE];
+ ULONG HashTableSize;
+ struct _HASHENTRY** FcbHashTable;
PDEVICE_OBJECT StorageDevice;
PFILE_OBJECT FATFileObject;
ULONG LastAvailableCluster;
ULONG AvailableClusters;
BOOLEAN AvailableClustersValid;
- ULONG Flags;
+ ULONG Flags;
struct _VFATFCB * VolumeFcb;
+ /* Pointers to functions for manipulating FAT. */
+ PGET_NEXT_CLUSTER GetNextCluster;
+ PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster;
+ PWRITE_CLUSTER WriteCluster;
+ ULONG CleanShutBitMask;
+
+ /* Pointers to functions for manipulating directory entries. */
+ PGET_NEXT_DIR_ENTRY GetNextDirEntry;
+
+ ULONG BaseDateYear;
+
LIST_ENTRY VolumeListEntry;
-} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB;
+} DEVICE_EXTENSION, VCB, *PVCB;
typedef struct
{
NPAGED_LOOKASIDE_LIST FcbLookasideList;
NPAGED_LOOKASIDE_LIST CcbLookasideList;
NPAGED_LOOKASIDE_LIST IrpContextLookasideList;
+ FAST_IO_DISPATCH FastIoDispatch;
+ CACHE_MANAGER_CALLBACKS CacheMgrCallbacks;
} VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA;
extern PVFAT_GLOBAL_DATA VfatGlobalData;
#define FCB_IS_FAT 0x0004
#define FCB_IS_PAGE_FILE 0x0008
#define FCB_IS_VOLUME 0x0010
-#define FCB_IS_DIRTY 0x0020
+#define FCB_IS_DIRTY 0x0020
+#define FCB_IS_FATX_ENTRY 0x0040
typedef struct _VFATFCB
{
/* end FCB header required by ROS/NT */
/* directory entry for this file or directory */
- FATDirEntry entry;
+ DIR_ENTRY entry;
+
+ /* Pointer to attributes in entry */
+ PUCHAR Attributes;
/* long file name, points into PathNameBuffer */
UNICODE_STRING LongNameU;
UNICODE_STRING PathNameU;
/* buffer for PathNameU */
- WCHAR PathNameBuffer[MAX_PATH];
+ PWCHAR PathNameBuffer;
/* buffer for ShortNameU */
WCHAR ShortNameBuffer[13];
/* Share access for the file object */
SHARE_ACCESS FCBShareAccess;
+ /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */
+ ULONG OpenHandleCount;
+
/* Entry into the hash table for the path + long name */
HASHENTRY Hash;
/* List of byte-range locks for this file */
FILE_LOCK FileLock;
+ /*
+ * Optimalization: caching of last read/write cluster+offset pair. Can't
+ * be in VFATCCB because it must be reset everytime the allocated clusters
+ * change.
+ */
+ FAST_MUTEX LastMutex;
+ ULONG LastCluster;
+ ULONG LastOffset;
} VFATFCB, *PVFATFCB;
typedef struct _VFATCCB
ULONG Entry;
/* for DirectoryControl */
UNICODE_STRING SearchPattern;
- ULONG LastCluster;
- ULONG LastOffset;
-
} VFATCCB, *PVFATCCB;
#ifndef TAG
typedef struct __DOSTIME
{
- WORD Second:5;
- WORD Minute:6;
- WORD Hour:5;
+ USHORT Second:5;
+ USHORT Minute:6;
+ USHORT Hour:5;
}
DOSTIME, *PDOSTIME;
typedef struct __DOSDATE
{
- WORD Day:5;
- WORD Month:4;
- WORD Year:5;
+ USHORT Day:5;
+ USHORT Month:4;
+ USHORT Year:5;
}
DOSDATE, *PDOSDATE;
-#define IRPCONTEXT_CANWAIT 0x0001
+#define IRPCONTEXT_CANWAIT 0x0001
+#define IRPCONTEXT_PENDINGRETURNED 0x0002
typedef struct
{
UCHAR MajorFunction;
UCHAR MinorFunction;
PFILE_OBJECT FileObject;
+ ULONG RefCount;
+ KEVENT Event;
} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT;
typedef struct _VFAT_DIRENTRY_CONTEXT
{
ULONG StartIndex;
ULONG DirIndex;
- FAT_DIR_ENTRY FatDirEntry;
+ DIR_ENTRY DirEntry;
UNICODE_STRING LongNameU;
UNICODE_STRING ShortNameU;
} VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT;
/* ------------------------------------------------------ shutdown.c */
-NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject,
+NTSTATUS NTAPI VfatShutdown (PDEVICE_OBJECT DeviceObject,
PIRP Irp);
/* -------------------------------------------------------- volume.c */
NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject,
IN PLARGE_INTEGER ReadOffset,
IN ULONG ReadLength,
- IN PUCHAR Buffer);
+ IN PUCHAR Buffer,
+ IN BOOLEAN Override);
+
+NTSTATUS VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
+ IN PLARGE_INTEGER ReadOffset,
+ IN ULONG ReadLength,
+ IN ULONG BufferOffset,
+ IN BOOLEAN Wait);
-NTSTATUS VfatWriteDisk(IN PDEVICE_OBJECT pDeviceObject,
- IN PLARGE_INTEGER WriteOffset,
- IN ULONG WriteLength,
- IN PUCHAR Buffer);
+NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext,
+ IN PLARGE_INTEGER WriteOffset,
+ IN ULONG WriteLength,
+ IN ULONG BufferOffset,
+ IN BOOLEAN Wait);
NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
IN ULONG CtlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferSize,
- IN OUT PVOID OutputBuffer,
- IN OUT PULONG pOutputBufferSize);
+ IN OUT PVOID OutputBuffer,
+ IN OUT PULONG pOutputBufferSize,
+ IN BOOLEAN Override);
/* ----------------------------------------------------------- dir.c */
NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT);
-BOOL FsdDosDateTimeToFileTime (WORD wDosDate,
- WORD wDosTime,
- TIME *FileTime);
+BOOLEAN FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt,
+ USHORT DosDate,
+ USHORT DosTime,
+ PLARGE_INTEGER SystemTime);
-BOOL FsdFileTimeToDosDateTime (TIME *FileTime,
- WORD *pwDosDate,
- WORD *pwDosTime);
+BOOLEAN FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt,
+ PLARGE_INTEGER SystemTime,
+ USHORT *pDosDate,
+ USHORT *pDosTime);
/* -------------------------------------------------------- create.c */
NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext);
-NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt,
- PFILE_OBJECT FileObject,
- PUNICODE_STRING FileNameU);
-
NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt,
PVFATFCB Parent,
PUNICODE_STRING FileToFindU,
NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext);
+/* --------------------------------------------------------- fastio.c */
+
+VOID
+VfatInitFastIoRoutines(PFAST_IO_DISPATCH FastIoDispatch);
+
+BOOLEAN NTAPI
+VfatAcquireForLazyWrite(IN PVOID Context,
+ IN BOOLEAN Wait);
+
+VOID NTAPI
+VfatReleaseFromLazyWrite(IN PVOID Context);
+
+BOOLEAN NTAPI
+VfatAcquireForReadAhead(IN PVOID Context,
+ IN BOOLEAN Wait);
+
+VOID NTAPI
+VfatReleaseFromReadAhead(IN PVOID Context);
+
/* --------------------------------------------------------- fsctl.c */
NTSTATUS VfatFileSystemControl (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatSetInformation (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS
-VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
+VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
PVFATFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PLARGE_INTEGER AllocationSize);
/* --------------------------------------------------------- iface.c */
-NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject,
+NTSTATUS NTAPI DriverEntry (PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath);
/* --------------------------------------------------------- dirwr.c */
NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
PUNICODE_STRING PathNameU,
- PFILE_OBJECT pFileObject,
+ PVFATFCB* Fcb,
+ PVFATFCB ParentFcb,
ULONG RequestedOptions,
UCHAR ReqAttr);
NTSTATUS VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB);
+BOOLEAN
+vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
+ PVFATFCB pDirFcb,
+ ULONG nbSlots,
+ PULONG start);
+
/* -------------------------------------------------------- string.c */
VOID
-vfatSplitPathName(PUNICODE_STRING PathNameU,
- PUNICODE_STRING DirNameU,
+vfatSplitPathName(PUNICODE_STRING PathNameU,
+ PUNICODE_STRING DirNameU,
PUNICODE_STRING FileNameU);
BOOLEAN vfatIsLongIllegal(WCHAR c);
/* ----------------------------------------------------------- fat.c */
+NTSTATUS FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
+ ULONG CurrentCluster,
+ PULONG NextCluster);
+
+NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
+ PULONG Cluster);
+
+NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt,
+ ULONG ClusterToWrite,
+ ULONG NewValue,
+ PULONG OldValue);
+
+NTSTATUS FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt,
+ ULONG CurrentCluster,
+ PULONG NextCluster);
+
+NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
+ PULONG Cluster);
+
+NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt,
+ ULONG ClusterToWrite,
+ ULONG NewValue,
+ PULONG OldValue);
+
+NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt,
+ ULONG CurrentCluster,
+ PULONG NextCluster);
+
+NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
+ PULONG Cluster);
+
+NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt,
+ ULONG ClusterToWrite,
+ ULONG NewValue,
+ PULONG OldValue);
+
NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt,
ULONG FirstCluster,
ULONG FileOffset,
NTSTATUS GetNextCluster (PDEVICE_EXTENSION DeviceExt,
ULONG CurrentCluster,
- PULONG NextCluster,
- BOOLEAN Extend);
+ PULONG NextCluster);
+
+NTSTATUS GetNextClusterExtend (PDEVICE_EXTENSION DeviceExt,
+ ULONG CurrentCluster,
+ PULONG NextCluster);
NTSTATUS CountAvailableClusters (PDEVICE_EXTENSION DeviceExt,
PLARGE_INTEGER Clusters);
/* ------------------------------------------------------ direntry.c */
ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
- PFAT_DIR_ENTRY pDirEntry);
+ PDIR_ENTRY pDirEntry);
-BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb);
+BOOLEAN VfatIsDirectoryEmpty(PVFATFCB Fcb);
-NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
+NTSTATUS FATGetNextDirEntry(PVOID * pContext,
+ PVOID * pPage,
+ IN PVFATFCB pDirFcb,
+ IN PVFAT_DIRENTRY_CONTEXT DirContext,
+ BOOLEAN First);
+
+NTSTATUS FATXGetNextDirEntry(PVOID * pContext,
PVOID * pPage,
IN PVFATFCB pDirFcb,
IN PVFAT_DIRENTRY_CONTEXT DirContext,
/* ----------------------------------------------------------- fcb.c */
-PVFATFCB vfatNewFCB (PUNICODE_STRING pFileNameU);
+PVFATFCB vfatNewFCB (PDEVICE_EXTENSION pVCB,
+ PUNICODE_STRING pFileNameU);
VOID vfatDestroyFCB (PVFATFCB pFCB);
PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB);
-BOOL vfatFCBIsDirectory (PVFATFCB FCB);
+BOOLEAN vfatFCBIsDirectory (PVFATFCB FCB);
-BOOL vfatFCBIsRoot(PVFATFCB FCB);
+BOOLEAN vfatFCBIsRoot(PVFATFCB FCB);
NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
PVFATFCB fcb,
VOID VfatFreeIrpContext(PVFAT_IRP_CONTEXT IrpContext);
-NTSTATUS STDCALL VfatBuildRequest (PDEVICE_OBJECT DeviceObject,
+NTSTATUS NTAPI VfatBuildRequest (PDEVICE_OBJECT DeviceObject,
PIRP Irp);
PVOID VfatGetUserBuffer(IN PIRP);
NTSTATUS VfatLockUserBuffer(IN PIRP, IN ULONG,
IN LOCK_OPERATION);
-NTSTATUS
-VfatSetExtendedAttributes(PFILE_OBJECT FileObject,
+NTSTATUS
+VfatSetExtendedAttributes(PFILE_OBJECT FileObject,
PVOID Ea,
ULONG EaLength);
/* ------------------------------------------------------------- flush.c */