mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
320abafdc3
Cc may decide to process deferred writes any time, so the context might already be freed by the time we return from CcDeferWrite. Also mark the IRP as pending, since we're going to return STATUS_PENDING.
1238 lines
28 KiB
C
1238 lines
28 KiB
C
#ifndef _FASTFAT_PCH_
|
|
#define _FASTFAT_PCH_
|
|
|
|
#include <ntifs.h>
|
|
#include <ntdddisk.h>
|
|
#include <dos.h>
|
|
#include <pseh/pseh2.h>
|
|
#include <section_attribs.h>
|
|
#ifdef KDBG
|
|
#include <ndk/kdfuncs.h>
|
|
#include <reactos/kdros.h>
|
|
#endif
|
|
|
|
|
|
#define USE_ROS_CC_AND_FS
|
|
#define ENABLE_SWAPOUT
|
|
|
|
/* FIXME: because volume is not cached, we have to perform direct IOs
|
|
* The day this is fixed, just comment out that line, and check
|
|
* it still works (and delete old code ;-))
|
|
*/
|
|
#define VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
|
|
|
|
|
|
#define ROUND_DOWN(n, align) \
|
|
(((ULONG)n) & ~((align) - 1l))
|
|
|
|
#define ROUND_UP(n, align) \
|
|
ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
|
|
|
|
#define ROUND_DOWN_64(n, align) \
|
|
(((ULONGLONG)n) & ~((align) - 1LL))
|
|
|
|
#define ROUND_UP_64(n, align) \
|
|
ROUND_DOWN_64(((ULONGLONG)n) + (align) - 1LL, (align))
|
|
|
|
#include <pshpack1.h>
|
|
struct _BootSector
|
|
{
|
|
unsigned char magic0, res0, magic1;
|
|
unsigned char OEMName[8];
|
|
unsigned short BytesPerSector;
|
|
unsigned char SectorsPerCluster;
|
|
unsigned short ReservedSectors;
|
|
unsigned char FATCount;
|
|
unsigned short RootEntries, Sectors;
|
|
unsigned char Media;
|
|
unsigned short FATSectors, SectorsPerTrack, Heads;
|
|
unsigned long HiddenSectors, SectorsHuge;
|
|
unsigned char Drive, Res1, Sig;
|
|
unsigned long VolumeID;
|
|
unsigned char VolumeLabel[11], SysType[8];
|
|
unsigned char Res2[448];
|
|
unsigned short Signatur1;
|
|
};
|
|
|
|
struct _BootSector32
|
|
{
|
|
unsigned char magic0, res0, magic1; // 0
|
|
unsigned char OEMName[8]; // 3
|
|
unsigned short BytesPerSector; // 11
|
|
unsigned char SectorsPerCluster; // 13
|
|
unsigned short ReservedSectors; // 14
|
|
unsigned char FATCount; // 16
|
|
unsigned short RootEntries, Sectors; // 17
|
|
unsigned char Media; // 21
|
|
unsigned short FATSectors, SectorsPerTrack, Heads; // 22
|
|
unsigned long HiddenSectors, SectorsHuge; // 28
|
|
unsigned long FATSectors32; // 36
|
|
unsigned short ExtFlag; // 40
|
|
unsigned short FSVersion; // 42
|
|
unsigned long RootCluster; // 44
|
|
unsigned short FSInfoSector; // 48
|
|
unsigned short BootBackup; // 50
|
|
unsigned char Res3[12]; // 52
|
|
unsigned char Drive; // 64
|
|
unsigned char Res4; // 65
|
|
unsigned char ExtBootSignature; // 66
|
|
unsigned long VolumeID; // 67
|
|
unsigned char VolumeLabel[11], SysType[8]; // 71
|
|
unsigned char Res2[420]; // 90
|
|
unsigned short Signature1; // 510
|
|
};
|
|
|
|
#define FAT_DIRTY_BIT 0x01
|
|
|
|
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 ExtBootSignature2; // 0
|
|
unsigned char Res6[480]; // 4
|
|
unsigned long FSINFOSignature; // 484
|
|
unsigned long FreeCluster; // 488
|
|
unsigned long NextCluster; // 492
|
|
unsigned char Res7[12]; // 496
|
|
unsigned long Signatur2; // 508
|
|
};
|
|
|
|
typedef struct _BootSector BootSector;
|
|
|
|
struct _FATDirEntry
|
|
{
|
|
union
|
|
{
|
|
struct { unsigned char Filename[8], Ext[3]; };
|
|
unsigned char ShortName[11];
|
|
};
|
|
unsigned char Attrib;
|
|
unsigned char lCase;
|
|
unsigned char CreationTimeMs;
|
|
unsigned short CreationTime,CreationDate,AccessDate;
|
|
union
|
|
{
|
|
unsigned short FirstClusterHigh; // FAT32
|
|
unsigned short ExtendedAttributes; // FAT12/FAT16
|
|
};
|
|
unsigned short UpdateTime; //time create/update
|
|
unsigned short UpdateDate; //date create/update
|
|
unsigned short FirstCluster;
|
|
unsigned long FileSize;
|
|
};
|
|
|
|
#define FAT_EAFILE "EA DATA. SF"
|
|
|
|
typedef struct _EAFileHeader FAT_EA_FILE_HEADER, *PFAT_EA_FILE_HEADER;
|
|
|
|
struct _EAFileHeader
|
|
{
|
|
unsigned short Signature; // ED
|
|
unsigned short Unknown[15];
|
|
unsigned short EASetTable[240];
|
|
};
|
|
|
|
typedef struct _EASetHeader FAT_EA_SET_HEADER, *PFAT_EA_SET_HEADER;
|
|
|
|
struct _EASetHeader
|
|
{
|
|
unsigned short Signature; // EA
|
|
unsigned short Offset; // relative offset, same value as in the EASetTable
|
|
unsigned short Unknown1[2];
|
|
char TargetFileName[12];
|
|
unsigned short Unknown2[3];
|
|
unsigned int EALength;
|
|
// EA Header
|
|
};
|
|
|
|
typedef struct _EAHeader FAT_EA_HEADER, *PFAT_EA_HEADER;
|
|
|
|
struct _EAHeader
|
|
{
|
|
unsigned char Unknown;
|
|
unsigned char EANameLength;
|
|
unsigned short EAValueLength;
|
|
// Name Data
|
|
// Value Data
|
|
};
|
|
|
|
typedef struct _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
|
|
{
|
|
unsigned char id; // sequence number for slot
|
|
WCHAR name0_4[5]; // first 5 characters in name
|
|
unsigned char attr; // attribute byte
|
|
unsigned char reserved; // always 0
|
|
unsigned char alias_checksum; // checksum for 8.3 alias
|
|
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
|
|
};
|
|
|
|
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(IsFatX, DirEntry) (IsFatX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat)))
|
|
#define ENTRY_VOLUME(IsFatX, DirEntry) (IsFatX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
|
|
#define ENTRY_END(IsFatX, DirEntry) (IsFatX ? 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 FATX16 (4)
|
|
#define FATX32 (5)
|
|
|
|
#define VCB_VOLUME_LOCKED 0x0001
|
|
#define VCB_DISMOUNT_PENDING 0x0002
|
|
#define VCB_IS_FATX 0x0004
|
|
#define VCB_IS_SYS_OR_HAS_PAGE 0x0008
|
|
#define VCB_IS_DIRTY 0x4000 /* Volume is dirty */
|
|
#define VCB_CLEAR_DIRTY 0x8000 /* Clean dirty flag at shutdown */
|
|
/* VCB condition state */
|
|
#define VCB_GOOD 0x0010 /* If not set, the VCB is improper for usage */
|
|
|
|
typedef struct
|
|
{
|
|
ULONG VolumeID;
|
|
CHAR VolumeLabel[11];
|
|
ULONG FATStart;
|
|
ULONG FATCount;
|
|
ULONG FATSectors;
|
|
ULONG rootDirectorySectors;
|
|
ULONG rootStart;
|
|
ULONG dataStart;
|
|
ULONG RootCluster;
|
|
ULONG SectorsPerCluster;
|
|
ULONG BytesPerSector;
|
|
ULONG BytesPerCluster;
|
|
ULONG NumberOfClusters;
|
|
ULONG FatType;
|
|
ULONG Sectors;
|
|
BOOLEAN FixedMedia;
|
|
ULONG FSInfoSector;
|
|
} FATINFO, *PFATINFO;
|
|
|
|
struct _VFATFCB;
|
|
struct _VFAT_DIRENTRY_CONTEXT;
|
|
struct _VFAT_MOVE_CONTEXT;
|
|
struct _VFAT_CLOSE_CONTEXT;
|
|
|
|
typedef struct _HASHENTRY
|
|
{
|
|
ULONG Hash;
|
|
struct _VFATFCB* self;
|
|
struct _HASHENTRY* next;
|
|
}
|
|
HASHENTRY;
|
|
|
|
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 BOOLEAN (*PIS_DIRECTORY_EMPTY)(PDEVICE_EXTENSION,struct _VFATFCB*);
|
|
typedef NTSTATUS (*PADD_ENTRY)(PDEVICE_EXTENSION,PUNICODE_STRING,struct _VFATFCB**,struct _VFATFCB*,ULONG,UCHAR,struct _VFAT_MOVE_CONTEXT*);
|
|
typedef NTSTATUS (*PDEL_ENTRY)(PDEVICE_EXTENSION,struct _VFATFCB*,struct _VFAT_MOVE_CONTEXT*);
|
|
typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY)(PVOID*,PVOID*,struct _VFATFCB*,struct _VFAT_DIRENTRY_CONTEXT*,BOOLEAN);
|
|
typedef NTSTATUS (*PGET_DIRTY_STATUS)(PDEVICE_EXTENSION,PBOOLEAN);
|
|
typedef NTSTATUS (*PSET_DIRTY_STATUS)(PDEVICE_EXTENSION,BOOLEAN);
|
|
|
|
typedef struct _VFAT_DISPATCH
|
|
{
|
|
PIS_DIRECTORY_EMPTY IsDirectoryEmpty;
|
|
PADD_ENTRY AddEntry;
|
|
PDEL_ENTRY DelEntry;
|
|
PGET_NEXT_DIR_ENTRY GetNextDirEntry;
|
|
} VFAT_DISPATCH, *PVFAT_DISPATCH;
|
|
|
|
#define STATISTICS_SIZE_NO_PAD (sizeof(FILESYSTEM_STATISTICS) + sizeof(FAT_STATISTICS))
|
|
typedef struct _STATISTICS {
|
|
FILESYSTEM_STATISTICS Base;
|
|
FAT_STATISTICS Fat;
|
|
UCHAR Pad[((STATISTICS_SIZE_NO_PAD + 0x3f) & ~0x3f) - STATISTICS_SIZE_NO_PAD];
|
|
} STATISTICS, *PSTATISTICS;
|
|
|
|
typedef struct DEVICE_EXTENSION
|
|
{
|
|
ERESOURCE DirResource;
|
|
ERESOURCE FatResource;
|
|
|
|
KSPIN_LOCK FcbListLock;
|
|
LIST_ENTRY FcbListHead;
|
|
ULONG HashTableSize;
|
|
struct _HASHENTRY **FcbHashTable;
|
|
|
|
PDEVICE_OBJECT VolumeDevice;
|
|
PDEVICE_OBJECT StorageDevice;
|
|
PFILE_OBJECT FATFileObject;
|
|
FATINFO FatInfo;
|
|
ULONG LastAvailableCluster;
|
|
ULONG AvailableClusters;
|
|
BOOLEAN AvailableClustersValid;
|
|
ULONG Flags;
|
|
struct _VFATFCB *VolumeFcb;
|
|
struct _VFATFCB *RootFcb;
|
|
PSTATISTICS Statistics;
|
|
|
|
/* Pointers to functions for manipulating FAT. */
|
|
PGET_NEXT_CLUSTER GetNextCluster;
|
|
PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster;
|
|
PWRITE_CLUSTER WriteCluster;
|
|
PGET_DIRTY_STATUS GetDirtyStatus;
|
|
PSET_DIRTY_STATUS SetDirtyStatus;
|
|
|
|
ULONG BaseDateYear;
|
|
|
|
LIST_ENTRY VolumeListEntry;
|
|
|
|
/* Notifications */
|
|
LIST_ENTRY NotifyList;
|
|
PNOTIFY_SYNC NotifySync;
|
|
|
|
/* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLOSE */
|
|
ULONG OpenHandleCount;
|
|
|
|
/* VPBs for dismount */
|
|
PVPB IoVPB;
|
|
PVPB SpareVPB;
|
|
|
|
/* Pointers to functions for manipulating directory entries. */
|
|
VFAT_DISPATCH Dispatch;
|
|
} DEVICE_EXTENSION, VCB, *PVCB;
|
|
|
|
FORCEINLINE
|
|
BOOLEAN
|
|
VfatIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt,
|
|
struct _VFATFCB* Fcb)
|
|
{
|
|
return DeviceExt->Dispatch.IsDirectoryEmpty(DeviceExt, Fcb);
|
|
}
|
|
|
|
FORCEINLINE
|
|
NTSTATUS
|
|
VfatAddEntry(PDEVICE_EXTENSION DeviceExt,
|
|
PUNICODE_STRING NameU,
|
|
struct _VFATFCB** Fcb,
|
|
struct _VFATFCB* ParentFcb,
|
|
ULONG RequestedOptions,
|
|
UCHAR ReqAttr,
|
|
struct _VFAT_MOVE_CONTEXT* MoveContext)
|
|
{
|
|
return DeviceExt->Dispatch.AddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr, MoveContext);
|
|
}
|
|
|
|
FORCEINLINE
|
|
NTSTATUS
|
|
VfatDelEntry(PDEVICE_EXTENSION DeviceExt,
|
|
struct _VFATFCB* Fcb,
|
|
struct _VFAT_MOVE_CONTEXT* MoveContext)
|
|
{
|
|
return DeviceExt->Dispatch.DelEntry(DeviceExt, Fcb, MoveContext);
|
|
}
|
|
|
|
FORCEINLINE
|
|
NTSTATUS
|
|
VfatGetNextDirEntry(PDEVICE_EXTENSION DeviceExt,
|
|
PVOID *pContext,
|
|
PVOID *pPage,
|
|
struct _VFATFCB* pDirFcb,
|
|
struct _VFAT_DIRENTRY_CONTEXT* DirContext,
|
|
BOOLEAN First)
|
|
{
|
|
return DeviceExt->Dispatch.GetNextDirEntry(pContext, pPage, pDirFcb, DirContext, First);
|
|
}
|
|
|
|
#define VFAT_BREAK_ON_CORRUPTION 1
|
|
|
|
typedef struct
|
|
{
|
|
PDRIVER_OBJECT DriverObject;
|
|
PDEVICE_OBJECT DeviceObject;
|
|
ULONG Flags;
|
|
ULONG NumberProcessors;
|
|
ERESOURCE VolumeListLock;
|
|
LIST_ENTRY VolumeListHead;
|
|
NPAGED_LOOKASIDE_LIST FcbLookasideList;
|
|
NPAGED_LOOKASIDE_LIST CcbLookasideList;
|
|
NPAGED_LOOKASIDE_LIST IrpContextLookasideList;
|
|
PAGED_LOOKASIDE_LIST CloseContextLookasideList;
|
|
FAST_IO_DISPATCH FastIoDispatch;
|
|
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks;
|
|
FAST_MUTEX CloseMutex;
|
|
ULONG CloseCount;
|
|
LIST_ENTRY CloseListHead;
|
|
BOOLEAN CloseWorkerRunning;
|
|
PIO_WORKITEM CloseWorkItem;
|
|
BOOLEAN ShutdownStarted;
|
|
} VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA;
|
|
|
|
extern PVFAT_GLOBAL_DATA VfatGlobalData;
|
|
|
|
#define FCB_CACHE_INITIALIZED 0x0001
|
|
#define FCB_DELETE_PENDING 0x0002
|
|
#define FCB_IS_FAT 0x0004
|
|
#define FCB_IS_PAGE_FILE 0x0008
|
|
#define FCB_IS_VOLUME 0x0010
|
|
#define FCB_IS_DIRTY 0x0020
|
|
#define FCB_DELAYED_CLOSE 0x0040
|
|
#ifdef KDBG
|
|
#define FCB_CLEANED_UP 0x0080
|
|
#define FCB_CLOSED 0x0100
|
|
#endif
|
|
|
|
#define NODE_TYPE_FCB ((CSHORT)0x0502)
|
|
|
|
typedef struct _VFATFCB
|
|
{
|
|
/* FCB header required by ROS/NT */
|
|
FSRTL_COMMON_FCB_HEADER RFCB;
|
|
SECTION_OBJECT_POINTERS SectionObjectPointers;
|
|
ERESOURCE MainResource;
|
|
ERESOURCE PagingIoResource;
|
|
/* end FCB header required by ROS/NT */
|
|
|
|
/* directory entry for this file or directory */
|
|
DIR_ENTRY entry;
|
|
|
|
/* Pointer to attributes in entry */
|
|
PUCHAR Attributes;
|
|
|
|
/* long file name, points into PathNameBuffer */
|
|
UNICODE_STRING LongNameU;
|
|
|
|
/* short file name */
|
|
UNICODE_STRING ShortNameU;
|
|
|
|
/* directory name, points into PathNameBuffer */
|
|
UNICODE_STRING DirNameU;
|
|
|
|
/* path + long file name 260 max*/
|
|
UNICODE_STRING PathNameU;
|
|
|
|
/* buffer for PathNameU */
|
|
PWCHAR PathNameBuffer;
|
|
|
|
/* buffer for ShortNameU */
|
|
WCHAR ShortNameBuffer[13];
|
|
|
|
/* */
|
|
LONG RefCount;
|
|
|
|
/* List of FCB's for this volume */
|
|
LIST_ENTRY FcbListEntry;
|
|
|
|
/* List of FCB's for the parent */
|
|
LIST_ENTRY ParentListEntry;
|
|
|
|
/* pointer to the parent fcb */
|
|
struct _VFATFCB *parentFcb;
|
|
|
|
/* List for the children */
|
|
LIST_ENTRY ParentListHead;
|
|
|
|
/* Flags for the fcb */
|
|
ULONG Flags;
|
|
|
|
/* pointer to the file object which has initialized the fcb */
|
|
PFILE_OBJECT FileObject;
|
|
|
|
/* Directory index for the short name entry */
|
|
ULONG dirIndex;
|
|
|
|
/* Directory index where the long name starts */
|
|
ULONG startIndex;
|
|
|
|
/* 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;
|
|
|
|
/* Entry into the hash table for the path + short name */
|
|
HASHENTRY ShortHash;
|
|
|
|
/* List of byte-range locks for this file */
|
|
FILE_LOCK FileLock;
|
|
|
|
/*
|
|
* Optimization: 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;
|
|
|
|
struct _VFAT_CLOSE_CONTEXT * CloseContext;
|
|
} VFATFCB, *PVFATFCB;
|
|
|
|
#define CCB_DELETE_ON_CLOSE 0x0001
|
|
|
|
typedef struct _VFATCCB
|
|
{
|
|
LARGE_INTEGER CurrentByteOffset;
|
|
ULONG Flags;
|
|
/* for DirectoryControl */
|
|
ULONG Entry;
|
|
/* for DirectoryControl */
|
|
UNICODE_STRING SearchPattern;
|
|
} VFATCCB, *PVFATCCB;
|
|
|
|
#define TAG_CCB 'CtaF'
|
|
#define TAG_FCB 'FtaF'
|
|
#define TAG_IRP 'ItaF'
|
|
#define TAG_CLOSE 'xtaF'
|
|
#define TAG_STATS 'VtaF'
|
|
#define TAG_BUFFER 'OtaF'
|
|
#define TAG_VPB 'vtaF'
|
|
#define TAG_NAME 'ntaF'
|
|
#define TAG_SEARCH 'LtaF'
|
|
#define TAG_DIRENT 'DtaF'
|
|
|
|
#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
|
|
|
|
typedef struct __DOSTIME
|
|
{
|
|
USHORT Second:5;
|
|
USHORT Minute:6;
|
|
USHORT Hour:5;
|
|
}
|
|
DOSTIME, *PDOSTIME;
|
|
|
|
typedef struct __DOSDATE
|
|
{
|
|
USHORT Day:5;
|
|
USHORT Month:4;
|
|
USHORT Year:7;
|
|
}
|
|
DOSDATE, *PDOSDATE;
|
|
|
|
#define IRPCONTEXT_CANWAIT 0x0001
|
|
#define IRPCONTEXT_COMPLETE 0x0002
|
|
#define IRPCONTEXT_QUEUE 0x0004
|
|
#define IRPCONTEXT_PENDINGRETURNED 0x0008
|
|
#define IRPCONTEXT_DEFERRED_WRITE 0x0010
|
|
|
|
typedef struct
|
|
{
|
|
PIRP Irp;
|
|
PDEVICE_OBJECT DeviceObject;
|
|
PDEVICE_EXTENSION DeviceExt;
|
|
ULONG Flags;
|
|
WORK_QUEUE_ITEM WorkQueueItem;
|
|
PIO_STACK_LOCATION Stack;
|
|
UCHAR MajorFunction;
|
|
UCHAR MinorFunction;
|
|
PFILE_OBJECT FileObject;
|
|
ULONG RefCount;
|
|
KEVENT Event;
|
|
CCHAR PriorityBoost;
|
|
} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT;
|
|
|
|
typedef struct _VFAT_DIRENTRY_CONTEXT
|
|
{
|
|
ULONG StartIndex;
|
|
ULONG DirIndex;
|
|
DIR_ENTRY DirEntry;
|
|
UNICODE_STRING LongNameU;
|
|
UNICODE_STRING ShortNameU;
|
|
PDEVICE_EXTENSION DeviceExt;
|
|
} VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT;
|
|
|
|
typedef struct _VFAT_MOVE_CONTEXT
|
|
{
|
|
ULONG FirstCluster;
|
|
ULONG FileSize;
|
|
USHORT CreationDate;
|
|
USHORT CreationTime;
|
|
BOOLEAN InPlace;
|
|
} VFAT_MOVE_CONTEXT, *PVFAT_MOVE_CONTEXT;
|
|
|
|
typedef struct _VFAT_CLOSE_CONTEXT
|
|
{
|
|
PDEVICE_EXTENSION Vcb;
|
|
PVFATFCB Fcb;
|
|
LIST_ENTRY CloseListEntry;
|
|
} VFAT_CLOSE_CONTEXT, *PVFAT_CLOSE_CONTEXT;
|
|
|
|
FORCEINLINE
|
|
NTSTATUS
|
|
VfatMarkIrpContextForQueue(PVFAT_IRP_CONTEXT IrpContext)
|
|
{
|
|
PULONG Flags = &IrpContext->Flags;
|
|
|
|
*Flags &= ~IRPCONTEXT_COMPLETE;
|
|
*Flags |= IRPCONTEXT_QUEUE;
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
FORCEINLINE
|
|
BOOLEAN
|
|
vfatFCBIsDirectory(PVFATFCB FCB)
|
|
{
|
|
return BooleanFlagOn(*FCB->Attributes, FILE_ATTRIBUTE_DIRECTORY);
|
|
}
|
|
|
|
FORCEINLINE
|
|
BOOLEAN
|
|
vfatFCBIsReadOnly(PVFATFCB FCB)
|
|
{
|
|
return BooleanFlagOn(*FCB->Attributes, FILE_ATTRIBUTE_READONLY);
|
|
}
|
|
|
|
FORCEINLINE
|
|
BOOLEAN
|
|
vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
|
|
{
|
|
return BooleanFlagOn(DeviceExt->Flags, VCB_IS_FATX);
|
|
}
|
|
|
|
FORCEINLINE
|
|
VOID
|
|
vfatReportChange(
|
|
IN PDEVICE_EXTENSION DeviceExt,
|
|
IN PVFATFCB Fcb,
|
|
IN ULONG FilterMatch,
|
|
IN ULONG Action)
|
|
{
|
|
FsRtlNotifyFullReportChange(DeviceExt->NotifySync,
|
|
&(DeviceExt->NotifyList),
|
|
(PSTRING)&Fcb->PathNameU,
|
|
Fcb->PathNameU.Length - Fcb->LongNameU.Length,
|
|
NULL, NULL, FilterMatch, Action, NULL);
|
|
}
|
|
|
|
#define vfatAddToStat(Vcb, Stat, Inc) \
|
|
{ \
|
|
PSTATISTICS Stats = &(Vcb)->Statistics[KeGetCurrentProcessorNumber() % VfatGlobalData->NumberProcessors]; \
|
|
Stats->Stat += Inc; \
|
|
}
|
|
|
|
/* blockdev.c */
|
|
|
|
NTSTATUS
|
|
VfatReadDisk(
|
|
IN PDEVICE_OBJECT pDeviceObject,
|
|
IN PLARGE_INTEGER ReadOffset,
|
|
IN ULONG ReadLength,
|
|
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 OUT PUCHAR Buffer,
|
|
IN BOOLEAN Override);
|
|
|
|
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 BOOLEAN Override);
|
|
|
|
/* cleanup.c */
|
|
|
|
NTSTATUS
|
|
VfatCleanup(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
/* close.c */
|
|
|
|
NTSTATUS
|
|
VfatClose(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
NTSTATUS
|
|
VfatCloseFile(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PFILE_OBJECT FileObject);
|
|
|
|
/* create.c */
|
|
|
|
NTSTATUS
|
|
VfatCreate(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
NTSTATUS
|
|
FindFile(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PVFATFCB Parent,
|
|
PUNICODE_STRING FileToFindU,
|
|
PVFAT_DIRENTRY_CONTEXT DirContext,
|
|
BOOLEAN First);
|
|
|
|
VOID
|
|
vfat8Dot3ToString(
|
|
PFAT_DIR_ENTRY pEntry,
|
|
PUNICODE_STRING NameU);
|
|
|
|
/* dir.c */
|
|
|
|
NTSTATUS
|
|
VfatDirectoryControl(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
BOOLEAN
|
|
FsdDosDateTimeToSystemTime(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
USHORT DosDate,
|
|
USHORT DosTime,
|
|
PLARGE_INTEGER SystemTime);
|
|
|
|
BOOLEAN
|
|
FsdSystemTimeToDosDateTime(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PLARGE_INTEGER SystemTime,
|
|
USHORT *pDosDate,
|
|
USHORT *pDosTime);
|
|
|
|
/* direntry.c */
|
|
|
|
ULONG
|
|
vfatDirEntryGetFirstCluster(
|
|
PDEVICE_EXTENSION pDeviceExt,
|
|
PDIR_ENTRY pDirEntry);
|
|
|
|
/* dirwr.c */
|
|
|
|
NTSTATUS
|
|
vfatFCBInitializeCacheFromVolume(
|
|
PVCB vcb,
|
|
PVFATFCB fcb);
|
|
|
|
NTSTATUS
|
|
VfatUpdateEntry(
|
|
IN PDEVICE_EXTENSION DeviceExt,
|
|
PVFATFCB pFcb);
|
|
|
|
BOOLEAN
|
|
vfatFindDirSpace(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PVFATFCB pDirFcb,
|
|
ULONG nbSlots,
|
|
PULONG start);
|
|
|
|
NTSTATUS
|
|
vfatRenameEntry(
|
|
IN PDEVICE_EXTENSION DeviceExt,
|
|
IN PVFATFCB pFcb,
|
|
IN PUNICODE_STRING FileName,
|
|
IN BOOLEAN CaseChangeOnly);
|
|
|
|
NTSTATUS
|
|
VfatMoveEntry(
|
|
IN PDEVICE_EXTENSION DeviceExt,
|
|
IN PVFATFCB pFcb,
|
|
IN PUNICODE_STRING FileName,
|
|
IN PVFATFCB ParentFcb);
|
|
|
|
/* ea.h */
|
|
|
|
NTSTATUS
|
|
VfatSetExtendedAttributes(
|
|
PFILE_OBJECT FileObject,
|
|
PVOID Ea,
|
|
ULONG EaLength);
|
|
|
|
/* fastio.c */
|
|
|
|
INIT_FUNCTION
|
|
VOID
|
|
VfatInitFastIoRoutines(
|
|
PFAST_IO_DISPATCH FastIoDispatch);
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
VfatAcquireForLazyWrite(
|
|
IN PVOID Context,
|
|
IN BOOLEAN Wait);
|
|
|
|
VOID
|
|
NTAPI
|
|
VfatReleaseFromLazyWrite(
|
|
IN PVOID Context);
|
|
|
|
/* 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,
|
|
PULONG Cluster,
|
|
BOOLEAN Extend);
|
|
|
|
ULONGLONG
|
|
ClusterToSector(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
ULONG Cluster);
|
|
|
|
NTSTATUS
|
|
GetNextCluster(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
ULONG CurrentCluster,
|
|
PULONG NextCluster);
|
|
|
|
NTSTATUS
|
|
GetNextClusterExtend(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
ULONG CurrentCluster,
|
|
PULONG NextCluster);
|
|
|
|
NTSTATUS
|
|
CountAvailableClusters(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PLARGE_INTEGER Clusters);
|
|
|
|
NTSTATUS
|
|
WriteCluster(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
ULONG ClusterToWrite,
|
|
ULONG NewValue);
|
|
|
|
NTSTATUS
|
|
GetDirtyStatus(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PBOOLEAN DirtyStatus);
|
|
|
|
NTSTATUS
|
|
FAT16GetDirtyStatus(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PBOOLEAN DirtyStatus);
|
|
|
|
NTSTATUS
|
|
FAT32GetDirtyStatus(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PBOOLEAN DirtyStatus);
|
|
|
|
NTSTATUS
|
|
SetDirtyStatus(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
BOOLEAN DirtyStatus);
|
|
|
|
NTSTATUS
|
|
FAT16SetDirtyStatus(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
BOOLEAN DirtyStatus);
|
|
|
|
NTSTATUS
|
|
FAT32SetDirtyStatus(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
BOOLEAN DirtyStatus);
|
|
|
|
NTSTATUS
|
|
FAT32UpdateFreeClustersCount(
|
|
PDEVICE_EXTENSION DeviceExt);
|
|
|
|
/* fcb.c */
|
|
|
|
PVFATFCB
|
|
vfatNewFCB(
|
|
PDEVICE_EXTENSION pVCB,
|
|
PUNICODE_STRING pFileNameU);
|
|
|
|
NTSTATUS
|
|
vfatSetFCBNewDirName(
|
|
PDEVICE_EXTENSION pVCB,
|
|
PVFATFCB Fcb,
|
|
PVFATFCB ParentFcb);
|
|
|
|
NTSTATUS
|
|
vfatUpdateFCB(
|
|
PDEVICE_EXTENSION pVCB,
|
|
PVFATFCB Fcb,
|
|
PVFAT_DIRENTRY_CONTEXT DirContext,
|
|
PVFATFCB ParentFcb);
|
|
|
|
VOID
|
|
vfatDestroyFCB(
|
|
PVFATFCB pFCB);
|
|
|
|
VOID
|
|
vfatDestroyCCB(
|
|
PVFATCCB pCcb);
|
|
|
|
VOID
|
|
#ifndef KDBG
|
|
vfatGrabFCB(
|
|
#else
|
|
_vfatGrabFCB(
|
|
#endif
|
|
PDEVICE_EXTENSION pVCB,
|
|
PVFATFCB pFCB
|
|
#ifdef KDBG
|
|
,
|
|
PCSTR File,
|
|
ULONG Line,
|
|
PCSTR Func
|
|
#endif
|
|
);
|
|
|
|
VOID
|
|
#ifndef KDBG
|
|
vfatReleaseFCB(
|
|
#else
|
|
_vfatReleaseFCB(
|
|
#endif
|
|
PDEVICE_EXTENSION pVCB,
|
|
PVFATFCB pFCB
|
|
#ifdef KDBG
|
|
,
|
|
PCSTR File,
|
|
ULONG Line,
|
|
PCSTR Func
|
|
#endif
|
|
);
|
|
|
|
#ifdef KDBG
|
|
#define vfatGrabFCB(v, f) _vfatGrabFCB(v, f, __FILE__, __LINE__, __FUNCTION__)
|
|
#define vfatReleaseFCB(v, f) _vfatReleaseFCB(v, f, __FILE__, __LINE__, __FUNCTION__)
|
|
#endif
|
|
|
|
PVFATFCB
|
|
vfatGrabFCBFromTable(
|
|
PDEVICE_EXTENSION pDeviceExt,
|
|
PUNICODE_STRING pFileNameU);
|
|
|
|
PVFATFCB
|
|
vfatMakeRootFCB(
|
|
PDEVICE_EXTENSION pVCB);
|
|
|
|
PVFATFCB
|
|
vfatOpenRootFCB(
|
|
PDEVICE_EXTENSION pVCB);
|
|
|
|
BOOLEAN
|
|
vfatFCBIsDirectory(
|
|
PVFATFCB FCB);
|
|
|
|
BOOLEAN
|
|
vfatFCBIsRoot(
|
|
PVFATFCB FCB);
|
|
|
|
NTSTATUS
|
|
vfatAttachFCBToFileObject(
|
|
PDEVICE_EXTENSION vcb,
|
|
PVFATFCB fcb,
|
|
PFILE_OBJECT fileObject);
|
|
|
|
NTSTATUS
|
|
vfatDirFindFile(
|
|
PDEVICE_EXTENSION pVCB,
|
|
PVFATFCB parentFCB,
|
|
PUNICODE_STRING FileToFindU,
|
|
PVFATFCB *fileFCB);
|
|
|
|
NTSTATUS
|
|
vfatGetFCBForFile(
|
|
PDEVICE_EXTENSION pVCB,
|
|
PVFATFCB *pParentFCB,
|
|
PVFATFCB *pFCB,
|
|
PUNICODE_STRING pFileNameU);
|
|
|
|
NTSTATUS
|
|
vfatMakeFCBFromDirEntry(
|
|
PVCB vcb,
|
|
PVFATFCB directoryFCB,
|
|
PVFAT_DIRENTRY_CONTEXT DirContext,
|
|
PVFATFCB *fileFCB);
|
|
|
|
/* finfo.c */
|
|
|
|
NTSTATUS
|
|
VfatGetStandardInformation(
|
|
PVFATFCB FCB,
|
|
PFILE_STANDARD_INFORMATION StandardInfo,
|
|
PULONG BufferLength);
|
|
|
|
NTSTATUS
|
|
VfatGetBasicInformation(
|
|
PFILE_OBJECT FileObject,
|
|
PVFATFCB FCB,
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PFILE_BASIC_INFORMATION BasicInfo,
|
|
PULONG BufferLength);
|
|
|
|
NTSTATUS
|
|
VfatQueryInformation(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
NTSTATUS
|
|
VfatSetInformation(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
NTSTATUS
|
|
VfatSetAllocationSizeInformation(
|
|
PFILE_OBJECT FileObject,
|
|
PVFATFCB Fcb,
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PLARGE_INTEGER AllocationSize);
|
|
|
|
/* flush.c */
|
|
|
|
NTSTATUS
|
|
VfatFlush(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
NTSTATUS
|
|
VfatFlushVolume(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
PVFATFCB VolumeFcb);
|
|
|
|
/* fsctl.c */
|
|
|
|
NTSTATUS
|
|
VfatFileSystemControl(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
/* iface.c */
|
|
|
|
INIT_FUNCTION
|
|
NTSTATUS
|
|
NTAPI
|
|
DriverEntry(
|
|
PDRIVER_OBJECT DriverObject,
|
|
PUNICODE_STRING RegistryPath);
|
|
|
|
#ifdef KDBG
|
|
/* kdbg.c */
|
|
KDBG_CLI_ROUTINE vfatKdbgHandler;
|
|
#endif
|
|
|
|
/* misc.c */
|
|
|
|
DRIVER_DISPATCH
|
|
VfatBuildRequest;
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
VfatBuildRequest(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp);
|
|
|
|
PVOID
|
|
VfatGetUserBuffer(
|
|
IN PIRP Irp,
|
|
IN BOOLEAN Paging);
|
|
|
|
NTSTATUS
|
|
VfatLockUserBuffer(
|
|
IN PIRP Irp,
|
|
IN ULONG Length,
|
|
IN LOCK_OPERATION Operation);
|
|
|
|
BOOLEAN
|
|
VfatCheckForDismount(
|
|
IN PDEVICE_EXTENSION DeviceExt,
|
|
IN BOOLEAN Create);
|
|
|
|
VOID
|
|
vfatReportChange(
|
|
IN PDEVICE_EXTENSION DeviceExt,
|
|
IN PVFATFCB Fcb,
|
|
IN ULONG FilterMatch,
|
|
IN ULONG Action);
|
|
|
|
VOID
|
|
NTAPI
|
|
VfatHandleDeferredWrite(
|
|
IN PVOID IrpContext,
|
|
IN PVOID Unused);
|
|
|
|
/* pnp.c */
|
|
|
|
NTSTATUS
|
|
VfatPnp(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
/* rw.c */
|
|
|
|
NTSTATUS
|
|
VfatRead(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
NTSTATUS
|
|
VfatWrite(
|
|
PVFAT_IRP_CONTEXT *pIrpContext);
|
|
|
|
NTSTATUS
|
|
NextCluster(
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
ULONG FirstCluster,
|
|
PULONG CurrentCluster,
|
|
BOOLEAN Extend);
|
|
|
|
/* shutdown.c */
|
|
|
|
DRIVER_DISPATCH
|
|
VfatShutdown;
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
VfatShutdown(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp);
|
|
|
|
/* string.c */
|
|
|
|
VOID
|
|
vfatSplitPathName(
|
|
PUNICODE_STRING PathNameU,
|
|
PUNICODE_STRING DirNameU,
|
|
PUNICODE_STRING FileNameU);
|
|
|
|
BOOLEAN
|
|
vfatIsLongIllegal(
|
|
WCHAR c);
|
|
|
|
BOOLEAN
|
|
IsDotOrDotDot(
|
|
PCUNICODE_STRING Name);
|
|
|
|
/* volume.c */
|
|
|
|
NTSTATUS
|
|
VfatQueryVolumeInformation(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
NTSTATUS
|
|
VfatSetVolumeInformation(
|
|
PVFAT_IRP_CONTEXT IrpContext);
|
|
|
|
#endif /* _FASTFAT_PCH_ */
|