reactos/drivers/filesystems/fastfat/vfat.h

1245 lines
28 KiB
C
Raw Normal View History

#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
[FASTFAT] Improvements for volume dismount + minor bugfixing. - Cache the RootFcb so that its cleanup can be handled separately during dismounting. - Force volume dismount at cleanup if the VCB_DISMOUNT_PENDING flag is set. - Actually dismount a volume if its VCB has been flagged as not good, or if we force dismounting. NOTE: In their *CheckForDismount() function, our 3rd-party FS drivers as well as MS' fastfat, perform a comparison check of the current VCB's VPB ReferenceCount with some sort of "dangling"/"residual" open count. It seems to be related to the fact that the volume root directory as well as auxiliary data stream(s) are still opened, and only these are allowed to be opened at that moment. After analysis it appears that for the ReactOS' fastfat, this number is equal to "3". - On dismounting, cleanup and destroy the RootFcb, VolumeFcb and the FATFileObject. Then cleanup the SpareVPB or the IoVPB members, and finish by removing the dismounted volume from the VolumeListEntry and cleaning up the notify synchronization object and the resources. - During dismounting, and on shutdown, flush the volume before resetting its dirty bit. - On shutdown, after volume flushing, try to unmount it without forcing. - Release the VCB resources only when we actually dismount the volume in VfatCheckForDismount(). - Initialize first the notify list and the synchronization object, before sending the FSRTL_VOLUME_MOUNT notification. - If we failed at mounting a volume but its VCB's FATFileObject was already initialized, first call CcUninitializeCacheMap() on it before dereferencing it. - Send FSRTL_VOLUME_LOCK, FSRTL_VOLUME_LOCK_FAILED and FSRTL_VOLUME_UNLOCK notifications during volume locking (and failure) and volume unlocking. - Flush the volume before locking it, and clean its dirty bit if needed. NOTE: In addition to checking for VCB_CLEAR_DIRTY, we also check for the presence of the VCB_IS_DIRTY flag before cleaning up the dirty bit: this allows us to not re-clean the bit if it has been previously cleaned. This is needed for instance in this scenario: - The volume is locked (it gets flushed and the dirty bit is possibly cleared); - The volume then gets formatted with a completely different FS, that possibly clears up the first sector (e.g. BTRFS ignores 1st sector); - The volume is then dismounted: if we didn't check whether VCB_IS_DIRTY was set prior to resetting it, we could attempt clearing it again! But now that the volume's filesystem has been completely changed, we would then try to modify the dirty bit on an erroneous position on disk! That's why it should not be touched in this case during dismounting. - The volume is unlocked (same comment as above), and later can be detected as being BTRFS.
2018-11-11 16:17:48 +00:00
#define USE_ROS_CC_AND_FS
#define ENABLE_SWAPOUT
[FASTFAT] Improvements for volume dismount + minor bugfixing. - Cache the RootFcb so that its cleanup can be handled separately during dismounting. - Force volume dismount at cleanup if the VCB_DISMOUNT_PENDING flag is set. - Actually dismount a volume if its VCB has been flagged as not good, or if we force dismounting. NOTE: In their *CheckForDismount() function, our 3rd-party FS drivers as well as MS' fastfat, perform a comparison check of the current VCB's VPB ReferenceCount with some sort of "dangling"/"residual" open count. It seems to be related to the fact that the volume root directory as well as auxiliary data stream(s) are still opened, and only these are allowed to be opened at that moment. After analysis it appears that for the ReactOS' fastfat, this number is equal to "3". - On dismounting, cleanup and destroy the RootFcb, VolumeFcb and the FATFileObject. Then cleanup the SpareVPB or the IoVPB members, and finish by removing the dismounted volume from the VolumeListEntry and cleaning up the notify synchronization object and the resources. - During dismounting, and on shutdown, flush the volume before resetting its dirty bit. - On shutdown, after volume flushing, try to unmount it without forcing. - Release the VCB resources only when we actually dismount the volume in VfatCheckForDismount(). - Initialize first the notify list and the synchronization object, before sending the FSRTL_VOLUME_MOUNT notification. - If we failed at mounting a volume but its VCB's FATFileObject was already initialized, first call CcUninitializeCacheMap() on it before dereferencing it. - Send FSRTL_VOLUME_LOCK, FSRTL_VOLUME_LOCK_FAILED and FSRTL_VOLUME_UNLOCK notifications during volume locking (and failure) and volume unlocking. - Flush the volume before locking it, and clean its dirty bit if needed. NOTE: In addition to checking for VCB_CLEAR_DIRTY, we also check for the presence of the VCB_IS_DIRTY flag before cleaning up the dirty bit: this allows us to not re-clean the bit if it has been previously cleaned. This is needed for instance in this scenario: - The volume is locked (it gets flushed and the dirty bit is possibly cleared); - The volume then gets formatted with a completely different FS, that possibly clears up the first sector (e.g. BTRFS ignores 1st sector); - The volume is then dismounted: if we didn't check whether VCB_IS_DIRTY was set prior to resetting it, we could attempt clearing it again! But now that the volume's filesystem has been completely changed, we would then try to modify the dirty bit on an erroneous position on disk! That's why it should not be touched in this case during dismounting. - The volume is unlocked (same comment as above), and later can be detected as being BTRFS.
2018-11-11 16:17:48 +00:00
/* 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 */
[FASTFAT] Improvements for volume dismount + minor bugfixing. - Cache the RootFcb so that its cleanup can be handled separately during dismounting. - Force volume dismount at cleanup if the VCB_DISMOUNT_PENDING flag is set. - Actually dismount a volume if its VCB has been flagged as not good, or if we force dismounting. NOTE: In their *CheckForDismount() function, our 3rd-party FS drivers as well as MS' fastfat, perform a comparison check of the current VCB's VPB ReferenceCount with some sort of "dangling"/"residual" open count. It seems to be related to the fact that the volume root directory as well as auxiliary data stream(s) are still opened, and only these are allowed to be opened at that moment. After analysis it appears that for the ReactOS' fastfat, this number is equal to "3". - On dismounting, cleanup and destroy the RootFcb, VolumeFcb and the FATFileObject. Then cleanup the SpareVPB or the IoVPB members, and finish by removing the dismounted volume from the VolumeListEntry and cleaning up the notify synchronization object and the resources. - During dismounting, and on shutdown, flush the volume before resetting its dirty bit. - On shutdown, after volume flushing, try to unmount it without forcing. - Release the VCB resources only when we actually dismount the volume in VfatCheckForDismount(). - Initialize first the notify list and the synchronization object, before sending the FSRTL_VOLUME_MOUNT notification. - If we failed at mounting a volume but its VCB's FATFileObject was already initialized, first call CcUninitializeCacheMap() on it before dereferencing it. - Send FSRTL_VOLUME_LOCK, FSRTL_VOLUME_LOCK_FAILED and FSRTL_VOLUME_UNLOCK notifications during volume locking (and failure) and volume unlocking. - Flush the volume before locking it, and clean its dirty bit if needed. NOTE: In addition to checking for VCB_CLEAR_DIRTY, we also check for the presence of the VCB_IS_DIRTY flag before cleaning up the dirty bit: this allows us to not re-clean the bit if it has been previously cleaned. This is needed for instance in this scenario: - The volume is locked (it gets flushed and the dirty bit is possibly cleared); - The volume then gets formatted with a completely different FS, that possibly clears up the first sector (e.g. BTRFS ignores 1st sector); - The volume is then dismounted: if we didn't check whether VCB_IS_DIRTY was set prior to resetting it, we could attempt clearing it again! But now that the volume's filesystem has been completely changed, we would then try to modify the dirty bit on an erroneous position on disk! That's why it should not be touched in this case during dismounting. - The volume is unlocked (same comment as above), and later can be detected as being BTRFS.
2018-11-11 16:17:48 +00:00
/* 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;
2002-08-14 David Welch <welch@computer2.darkstar.org> * subsys/smss/init.c (SmPagingFilesQueryRoutine): If possible take the size of the paging file from the registry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/section.c (MmCreateDataFileSection): Extend the section if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/pagefile.c (NtCreatePagingFile): Set the file size using the FileAllocationInformation class. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/anonmem.c (MmWritePageVirtualMemory): Implemented function to write anonymous memory pages to the swap file. * ntoskrnl/mm/anonmem.c (MmFreeVirtualMemoryPage): Free any swap page associated with the page. * ntoskrnl/mm/mpw.c (MmWriteDirtyPages): New function to find pages to write to disk. * ntoskrnl/mm/mpw.c (MmMpwThreadMain): Implemented MPW functionality. * ntoskrnl/mm/rmap.c (MmWritePagePhysicalAddress): New function to write a single page back to disk. * ntoskrnl/mm/rmap.c (MmSetCleanAllRmaps, MmSetDirtyAllRmaps, MmIsDirtyPageRmap): New rmap function to support the MPW thread. * ntoskrnl/mm/section.c (MmWritePageSectionView): Implemented function to write back section pages. * ntoskrnl/mm/section.c (MmFreeSectionPage): Free any swap entry associated with the page; mark pages shared with the cache as dirty if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/ldr/loader.c (LdrPEProcessModule): Set name of the module into the module text structure. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/io/rw.c (NtReadFile, NtWriteFile): Use the correct test for whether to wait for the completion of i/o. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cm/ntfunc.c (NtFlushKey): Request synchronous i/o from NtOpenFile. * ntoskrnl/cm/regfile (CmiInitPermanentRegistryHive): Request synchronous i/o from NtCreateFile. * ntoskrnl/dbg/kdb_stabs.c (LdrpLoadModuleSymbols): Request synchronous i/o from NtOpenFile. * ntoskrnl/ldr/sysdll.c (LdrpMapSystemDll): Request synchronous i/o from NtOpenFile. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosSuggestFreeCacheSegment): Maintain the correct reference count. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosFlushCacheSegment): New function to write back a modified cache segment. * ntoskrnl/cc/view.c (CcRosFlushDirtyPages): New function to flush some dirty pages from the cache. * ntoskrnl/cc/view.c (CcRosMarkDirtyCacheSegment): New function to mark a cache segment modified while mapped into memory as dirty. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/pin.c (CcMapData, CcUnpinData, CcSetDirtyPinnedData): Store the dirty status in the BCB; don't write back dirty data immediately. 2002-08-14 David Welch <welch@computer2.darkstar.org> * include/ntos/mm.h: Added SEC_XXXX defines from 'Windows NT/2000 Native API Reference' 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/ea.c (VfatSetExtendedAttributes): Empty placeholder for extended attribute functions. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/finfo.c (VfatSetAllocationSizeInformation): Added function to set allocation size. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/fcb.c (vfatFCBInitializeCache): Renamed to vfatFCBInitializeCacheFromVolume. * drivers/fs/vfat/fcb.c (vfatMakeFCBFromDirEntry): Don't initialise the cache with a file object representing the volume unless the FCB is for a directory. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/create.c (VfatPagingFileCreate): Added a new function for handling paging file only code. * drivers/fs/vfat/create.c (VfatSupersedeFile): Added a new function for doing a file supersede. * drivers/fs/vfat/create.c (VfatCreateFile): Reformatted and adjusted control flow. Set allocation size and extended attributes on create. * drivers/fs/vfat/create.c (VfatCreate): Removed goto. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/cleanup.c (VfatCleanupFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/close.c (VfatCloseFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (updEntry): Renamed to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (addEntry): Renamed to VfatAddEntry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * apps/tests/sectest/sectest.c (main): Fixed formatting. svn path=/trunk/; revision=3331
2002-08-14 20:58:39 +00:00
} 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;
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
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;
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
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;
[FASTFAT] Improvements for volume dismount + minor bugfixing. - Cache the RootFcb so that its cleanup can be handled separately during dismounting. - Force volume dismount at cleanup if the VCB_DISMOUNT_PENDING flag is set. - Actually dismount a volume if its VCB has been flagged as not good, or if we force dismounting. NOTE: In their *CheckForDismount() function, our 3rd-party FS drivers as well as MS' fastfat, perform a comparison check of the current VCB's VPB ReferenceCount with some sort of "dangling"/"residual" open count. It seems to be related to the fact that the volume root directory as well as auxiliary data stream(s) are still opened, and only these are allowed to be opened at that moment. After analysis it appears that for the ReactOS' fastfat, this number is equal to "3". - On dismounting, cleanup and destroy the RootFcb, VolumeFcb and the FATFileObject. Then cleanup the SpareVPB or the IoVPB members, and finish by removing the dismounted volume from the VolumeListEntry and cleaning up the notify synchronization object and the resources. - During dismounting, and on shutdown, flush the volume before resetting its dirty bit. - On shutdown, after volume flushing, try to unmount it without forcing. - Release the VCB resources only when we actually dismount the volume in VfatCheckForDismount(). - Initialize first the notify list and the synchronization object, before sending the FSRTL_VOLUME_MOUNT notification. - If we failed at mounting a volume but its VCB's FATFileObject was already initialized, first call CcUninitializeCacheMap() on it before dereferencing it. - Send FSRTL_VOLUME_LOCK, FSRTL_VOLUME_LOCK_FAILED and FSRTL_VOLUME_UNLOCK notifications during volume locking (and failure) and volume unlocking. - Flush the volume before locking it, and clean its dirty bit if needed. NOTE: In addition to checking for VCB_CLEAR_DIRTY, we also check for the presence of the VCB_IS_DIRTY flag before cleaning up the dirty bit: this allows us to not re-clean the bit if it has been previously cleaned. This is needed for instance in this scenario: - The volume is locked (it gets flushed and the dirty bit is possibly cleared); - The volume then gets formatted with a completely different FS, that possibly clears up the first sector (e.g. BTRFS ignores 1st sector); - The volume is then dismounted: if we didn't check whether VCB_IS_DIRTY was set prior to resetting it, we could attempt clearing it again! But now that the volume's filesystem has been completely changed, we would then try to modify the dirty bit on an erroneous position on disk! That's why it should not be touched in this case during dismounting. - The volume is unlocked (same comment as above), and later can be detected as being BTRFS.
2018-11-11 16:17:48 +00:00
struct _VFATFCB *RootFcb;
PSTATISTICS Statistics;
/* Overflow request queue */
KSPIN_LOCK OverflowQueueSpinLock;
LIST_ENTRY OverflowQueue;
ULONG OverflowQueueCount;
ULONG PostedRequestCount;
/* 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;
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
} 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;
2002-08-14 David Welch <welch@computer2.darkstar.org> * subsys/smss/init.c (SmPagingFilesQueryRoutine): If possible take the size of the paging file from the registry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/section.c (MmCreateDataFileSection): Extend the section if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/pagefile.c (NtCreatePagingFile): Set the file size using the FileAllocationInformation class. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/anonmem.c (MmWritePageVirtualMemory): Implemented function to write anonymous memory pages to the swap file. * ntoskrnl/mm/anonmem.c (MmFreeVirtualMemoryPage): Free any swap page associated with the page. * ntoskrnl/mm/mpw.c (MmWriteDirtyPages): New function to find pages to write to disk. * ntoskrnl/mm/mpw.c (MmMpwThreadMain): Implemented MPW functionality. * ntoskrnl/mm/rmap.c (MmWritePagePhysicalAddress): New function to write a single page back to disk. * ntoskrnl/mm/rmap.c (MmSetCleanAllRmaps, MmSetDirtyAllRmaps, MmIsDirtyPageRmap): New rmap function to support the MPW thread. * ntoskrnl/mm/section.c (MmWritePageSectionView): Implemented function to write back section pages. * ntoskrnl/mm/section.c (MmFreeSectionPage): Free any swap entry associated with the page; mark pages shared with the cache as dirty if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/ldr/loader.c (LdrPEProcessModule): Set name of the module into the module text structure. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/io/rw.c (NtReadFile, NtWriteFile): Use the correct test for whether to wait for the completion of i/o. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cm/ntfunc.c (NtFlushKey): Request synchronous i/o from NtOpenFile. * ntoskrnl/cm/regfile (CmiInitPermanentRegistryHive): Request synchronous i/o from NtCreateFile. * ntoskrnl/dbg/kdb_stabs.c (LdrpLoadModuleSymbols): Request synchronous i/o from NtOpenFile. * ntoskrnl/ldr/sysdll.c (LdrpMapSystemDll): Request synchronous i/o from NtOpenFile. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosSuggestFreeCacheSegment): Maintain the correct reference count. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosFlushCacheSegment): New function to write back a modified cache segment. * ntoskrnl/cc/view.c (CcRosFlushDirtyPages): New function to flush some dirty pages from the cache. * ntoskrnl/cc/view.c (CcRosMarkDirtyCacheSegment): New function to mark a cache segment modified while mapped into memory as dirty. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/pin.c (CcMapData, CcUnpinData, CcSetDirtyPinnedData): Store the dirty status in the BCB; don't write back dirty data immediately. 2002-08-14 David Welch <welch@computer2.darkstar.org> * include/ntos/mm.h: Added SEC_XXXX defines from 'Windows NT/2000 Native API Reference' 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/ea.c (VfatSetExtendedAttributes): Empty placeholder for extended attribute functions. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/finfo.c (VfatSetAllocationSizeInformation): Added function to set allocation size. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/fcb.c (vfatFCBInitializeCache): Renamed to vfatFCBInitializeCacheFromVolume. * drivers/fs/vfat/fcb.c (vfatMakeFCBFromDirEntry): Don't initialise the cache with a file object representing the volume unless the FCB is for a directory. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/create.c (VfatPagingFileCreate): Added a new function for handling paging file only code. * drivers/fs/vfat/create.c (VfatSupersedeFile): Added a new function for doing a file supersede. * drivers/fs/vfat/create.c (VfatCreateFile): Reformatted and adjusted control flow. Set allocation size and extended attributes on create. * drivers/fs/vfat/create.c (VfatCreate): Removed goto. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/cleanup.c (VfatCleanupFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/close.c (VfatCloseFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (updEntry): Renamed to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (addEntry): Renamed to VfatAddEntry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * apps/tests/sectest/sectest.c (main): Fixed formatting. svn path=/trunk/; revision=3331
2002-08-14 20:58:39 +00:00
} 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;
2002-08-14 David Welch <welch@computer2.darkstar.org> * subsys/smss/init.c (SmPagingFilesQueryRoutine): If possible take the size of the paging file from the registry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/section.c (MmCreateDataFileSection): Extend the section if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/pagefile.c (NtCreatePagingFile): Set the file size using the FileAllocationInformation class. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/anonmem.c (MmWritePageVirtualMemory): Implemented function to write anonymous memory pages to the swap file. * ntoskrnl/mm/anonmem.c (MmFreeVirtualMemoryPage): Free any swap page associated with the page. * ntoskrnl/mm/mpw.c (MmWriteDirtyPages): New function to find pages to write to disk. * ntoskrnl/mm/mpw.c (MmMpwThreadMain): Implemented MPW functionality. * ntoskrnl/mm/rmap.c (MmWritePagePhysicalAddress): New function to write a single page back to disk. * ntoskrnl/mm/rmap.c (MmSetCleanAllRmaps, MmSetDirtyAllRmaps, MmIsDirtyPageRmap): New rmap function to support the MPW thread. * ntoskrnl/mm/section.c (MmWritePageSectionView): Implemented function to write back section pages. * ntoskrnl/mm/section.c (MmFreeSectionPage): Free any swap entry associated with the page; mark pages shared with the cache as dirty if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/ldr/loader.c (LdrPEProcessModule): Set name of the module into the module text structure. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/io/rw.c (NtReadFile, NtWriteFile): Use the correct test for whether to wait for the completion of i/o. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cm/ntfunc.c (NtFlushKey): Request synchronous i/o from NtOpenFile. * ntoskrnl/cm/regfile (CmiInitPermanentRegistryHive): Request synchronous i/o from NtCreateFile. * ntoskrnl/dbg/kdb_stabs.c (LdrpLoadModuleSymbols): Request synchronous i/o from NtOpenFile. * ntoskrnl/ldr/sysdll.c (LdrpMapSystemDll): Request synchronous i/o from NtOpenFile. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosSuggestFreeCacheSegment): Maintain the correct reference count. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosFlushCacheSegment): New function to write back a modified cache segment. * ntoskrnl/cc/view.c (CcRosFlushDirtyPages): New function to flush some dirty pages from the cache. * ntoskrnl/cc/view.c (CcRosMarkDirtyCacheSegment): New function to mark a cache segment modified while mapped into memory as dirty. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/pin.c (CcMapData, CcUnpinData, CcSetDirtyPinnedData): Store the dirty status in the BCB; don't write back dirty data immediately. 2002-08-14 David Welch <welch@computer2.darkstar.org> * include/ntos/mm.h: Added SEC_XXXX defines from 'Windows NT/2000 Native API Reference' 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/ea.c (VfatSetExtendedAttributes): Empty placeholder for extended attribute functions. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/finfo.c (VfatSetAllocationSizeInformation): Added function to set allocation size. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/fcb.c (vfatFCBInitializeCache): Renamed to vfatFCBInitializeCacheFromVolume. * drivers/fs/vfat/fcb.c (vfatMakeFCBFromDirEntry): Don't initialise the cache with a file object representing the volume unless the FCB is for a directory. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/create.c (VfatPagingFileCreate): Added a new function for handling paging file only code. * drivers/fs/vfat/create.c (VfatSupersedeFile): Added a new function for doing a file supersede. * drivers/fs/vfat/create.c (VfatCreateFile): Reformatted and adjusted control flow. Set allocation size and extended attributes on create. * drivers/fs/vfat/create.c (VfatCreate): Removed goto. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/cleanup.c (VfatCleanupFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/close.c (VfatCloseFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (updEntry): Renamed to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (addEntry): Renamed to VfatAddEntry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * apps/tests/sectest/sectest.c (main): Fixed formatting. svn path=/trunk/; revision=3331
2002-08-14 20:58:39 +00:00
} 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;
2002-08-14 David Welch <welch@computer2.darkstar.org> * subsys/smss/init.c (SmPagingFilesQueryRoutine): If possible take the size of the paging file from the registry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/section.c (MmCreateDataFileSection): Extend the section if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/pagefile.c (NtCreatePagingFile): Set the file size using the FileAllocationInformation class. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/anonmem.c (MmWritePageVirtualMemory): Implemented function to write anonymous memory pages to the swap file. * ntoskrnl/mm/anonmem.c (MmFreeVirtualMemoryPage): Free any swap page associated with the page. * ntoskrnl/mm/mpw.c (MmWriteDirtyPages): New function to find pages to write to disk. * ntoskrnl/mm/mpw.c (MmMpwThreadMain): Implemented MPW functionality. * ntoskrnl/mm/rmap.c (MmWritePagePhysicalAddress): New function to write a single page back to disk. * ntoskrnl/mm/rmap.c (MmSetCleanAllRmaps, MmSetDirtyAllRmaps, MmIsDirtyPageRmap): New rmap function to support the MPW thread. * ntoskrnl/mm/section.c (MmWritePageSectionView): Implemented function to write back section pages. * ntoskrnl/mm/section.c (MmFreeSectionPage): Free any swap entry associated with the page; mark pages shared with the cache as dirty if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/ldr/loader.c (LdrPEProcessModule): Set name of the module into the module text structure. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/io/rw.c (NtReadFile, NtWriteFile): Use the correct test for whether to wait for the completion of i/o. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cm/ntfunc.c (NtFlushKey): Request synchronous i/o from NtOpenFile. * ntoskrnl/cm/regfile (CmiInitPermanentRegistryHive): Request synchronous i/o from NtCreateFile. * ntoskrnl/dbg/kdb_stabs.c (LdrpLoadModuleSymbols): Request synchronous i/o from NtOpenFile. * ntoskrnl/ldr/sysdll.c (LdrpMapSystemDll): Request synchronous i/o from NtOpenFile. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosSuggestFreeCacheSegment): Maintain the correct reference count. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosFlushCacheSegment): New function to write back a modified cache segment. * ntoskrnl/cc/view.c (CcRosFlushDirtyPages): New function to flush some dirty pages from the cache. * ntoskrnl/cc/view.c (CcRosMarkDirtyCacheSegment): New function to mark a cache segment modified while mapped into memory as dirty. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/pin.c (CcMapData, CcUnpinData, CcSetDirtyPinnedData): Store the dirty status in the BCB; don't write back dirty data immediately. 2002-08-14 David Welch <welch@computer2.darkstar.org> * include/ntos/mm.h: Added SEC_XXXX defines from 'Windows NT/2000 Native API Reference' 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/ea.c (VfatSetExtendedAttributes): Empty placeholder for extended attribute functions. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/finfo.c (VfatSetAllocationSizeInformation): Added function to set allocation size. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/fcb.c (vfatFCBInitializeCache): Renamed to vfatFCBInitializeCacheFromVolume. * drivers/fs/vfat/fcb.c (vfatMakeFCBFromDirEntry): Don't initialise the cache with a file object representing the volume unless the FCB is for a directory. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/create.c (VfatPagingFileCreate): Added a new function for handling paging file only code. * drivers/fs/vfat/create.c (VfatSupersedeFile): Added a new function for doing a file supersede. * drivers/fs/vfat/create.c (VfatCreateFile): Reformatted and adjusted control flow. Set allocation size and extended attributes on create. * drivers/fs/vfat/create.c (VfatCreate): Removed goto. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/cleanup.c (VfatCleanupFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/close.c (VfatCloseFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (updEntry): Renamed to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (addEntry): Renamed to VfatAddEntry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * apps/tests/sectest/sectest.c (main): Fixed formatting. svn path=/trunk/; revision=3331
2002-08-14 20:58:39 +00:00
} 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;
2002-08-14 David Welch <welch@computer2.darkstar.org> * subsys/smss/init.c (SmPagingFilesQueryRoutine): If possible take the size of the paging file from the registry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/section.c (MmCreateDataFileSection): Extend the section if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/pagefile.c (NtCreatePagingFile): Set the file size using the FileAllocationInformation class. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/anonmem.c (MmWritePageVirtualMemory): Implemented function to write anonymous memory pages to the swap file. * ntoskrnl/mm/anonmem.c (MmFreeVirtualMemoryPage): Free any swap page associated with the page. * ntoskrnl/mm/mpw.c (MmWriteDirtyPages): New function to find pages to write to disk. * ntoskrnl/mm/mpw.c (MmMpwThreadMain): Implemented MPW functionality. * ntoskrnl/mm/rmap.c (MmWritePagePhysicalAddress): New function to write a single page back to disk. * ntoskrnl/mm/rmap.c (MmSetCleanAllRmaps, MmSetDirtyAllRmaps, MmIsDirtyPageRmap): New rmap function to support the MPW thread. * ntoskrnl/mm/section.c (MmWritePageSectionView): Implemented function to write back section pages. * ntoskrnl/mm/section.c (MmFreeSectionPage): Free any swap entry associated with the page; mark pages shared with the cache as dirty if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/ldr/loader.c (LdrPEProcessModule): Set name of the module into the module text structure. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/io/rw.c (NtReadFile, NtWriteFile): Use the correct test for whether to wait for the completion of i/o. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cm/ntfunc.c (NtFlushKey): Request synchronous i/o from NtOpenFile. * ntoskrnl/cm/regfile (CmiInitPermanentRegistryHive): Request synchronous i/o from NtCreateFile. * ntoskrnl/dbg/kdb_stabs.c (LdrpLoadModuleSymbols): Request synchronous i/o from NtOpenFile. * ntoskrnl/ldr/sysdll.c (LdrpMapSystemDll): Request synchronous i/o from NtOpenFile. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosSuggestFreeCacheSegment): Maintain the correct reference count. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosFlushCacheSegment): New function to write back a modified cache segment. * ntoskrnl/cc/view.c (CcRosFlushDirtyPages): New function to flush some dirty pages from the cache. * ntoskrnl/cc/view.c (CcRosMarkDirtyCacheSegment): New function to mark a cache segment modified while mapped into memory as dirty. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/pin.c (CcMapData, CcUnpinData, CcSetDirtyPinnedData): Store the dirty status in the BCB; don't write back dirty data immediately. 2002-08-14 David Welch <welch@computer2.darkstar.org> * include/ntos/mm.h: Added SEC_XXXX defines from 'Windows NT/2000 Native API Reference' 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/ea.c (VfatSetExtendedAttributes): Empty placeholder for extended attribute functions. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/finfo.c (VfatSetAllocationSizeInformation): Added function to set allocation size. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/fcb.c (vfatFCBInitializeCache): Renamed to vfatFCBInitializeCacheFromVolume. * drivers/fs/vfat/fcb.c (vfatMakeFCBFromDirEntry): Don't initialise the cache with a file object representing the volume unless the FCB is for a directory. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/create.c (VfatPagingFileCreate): Added a new function for handling paging file only code. * drivers/fs/vfat/create.c (VfatSupersedeFile): Added a new function for doing a file supersede. * drivers/fs/vfat/create.c (VfatCreateFile): Reformatted and adjusted control flow. Set allocation size and extended attributes on create. * drivers/fs/vfat/create.c (VfatCreate): Removed goto. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/cleanup.c (VfatCleanupFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/close.c (VfatCloseFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (updEntry): Renamed to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (addEntry): Renamed to VfatAddEntry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * apps/tests/sectest/sectest.c (main): Fixed formatting. svn path=/trunk/; revision=3331
2002-08-14 20:58:39 +00:00
} 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;
[FASTFAT] - Implement vfatPrepareTargetForRename() that prepares for renaming. It tries to open target and deletes it if it exists and if allowed. And then, it opens the parent directory. - Implement VfatSetRenameInformation() that actually does the renaming (call as SetInformationFile). It handles cases we we have (or we don't have) TargetDirectory provided. It sends notifications as appropriated on demands. - Implement vfatRenameEntry() that renames an entry in place. So far, it only supports FATX entries renaming. FAT entries are a bit more complex. It falls back to vfatMoveEntry() in later cases. - Implement VfatMoveEntry() that will move an entry accross directories (or in place for FAT). Its principles are simple: it deletes the entry in old parent, and recreate it in new parent, keeping file metadata & data. - Modify VfatDelEntry() and VfatAddEntry() so that they can handle deleting an entry without touching its data and adding an entry with an already provided FCB and thus use the given metadata. - Implement vfatDelFCBFromTable() which is just old code moved to new routine to allow reuse. It deletes a FCB entry from hash table. Doesn't deal with references! - Implement vfatMakeFullName() which is mostly old code moved to new routine to allow reuse. It allocates buffer and copy data for FCB full name. - Implement vfatUpdateFCB() that will update a FCB with new names and parent. It will remove anything related to old name and will recreate using new data. It will adjust references count. - Modify vfatMakeFCBFromDirEntry() so that it calls vfatMakeFullName(). - Modify vfatReleaseFCB() so that it calls vfatDelFCBFromTable(). - Revert VfatOpenFile() to its previous features. - Modify VfatCreateFile() to reimplement support for SL_OPEN_TARGET_DIRECTORY. It is way less hackish than previously. It also properly opens parent now, by incrementing its handle count and by setting appropriate access rights. [KERNEL32] - Rewritten MoveFileWithProgressW() to implement all the missing features that are used in Windows 2k3 including links and reparse points. - Implemented BasepMoveFileDelayed() to replace deprecated add_boot_rename_entry(). This functions is matching the features implemented in SMSS. - Implemented BasepMoveFileCopyProgress() which is used in MoveFileWithProgressW(). - Stubbed BasepNotifyTrackingService() which is not use at the moment (FastFAT, even in Windows doesn't provide such feature). - Reimplemented ReplaceFileA(), MoveFileWithProgressA() to quit Winisms and use our internal helpers. - Make MoveFileX() use MoveFileWithProgressX() directly. - Fixed a few prototypes. TL;DR: This (huge) commit implements file and directory renaming in FastFAT driver. This allows getting rid of old implementation in kernel32 where files were force copied. A feature is still missing, but Jérôme should implement it anytime soon (he prototyped it already): moving directories across volumes. This requires some work in BasepCopyFileExW(). Kudos to all the devs who helped me on this: Christoph, Hervé, Jérôme, Thomas. This finally allows killing CR-52... It was about time! svn path=/trunk/; revision=64836
2014-10-19 21:38:32 +00:00
typedef struct _VFAT_MOVE_CONTEXT
{
ULONG FirstCluster;
ULONG FileSize;
USHORT CreationDate;
USHORT CreationTime;
BOOLEAN InPlace;
[FASTFAT] - Implement vfatPrepareTargetForRename() that prepares for renaming. It tries to open target and deletes it if it exists and if allowed. And then, it opens the parent directory. - Implement VfatSetRenameInformation() that actually does the renaming (call as SetInformationFile). It handles cases we we have (or we don't have) TargetDirectory provided. It sends notifications as appropriated on demands. - Implement vfatRenameEntry() that renames an entry in place. So far, it only supports FATX entries renaming. FAT entries are a bit more complex. It falls back to vfatMoveEntry() in later cases. - Implement VfatMoveEntry() that will move an entry accross directories (or in place for FAT). Its principles are simple: it deletes the entry in old parent, and recreate it in new parent, keeping file metadata & data. - Modify VfatDelEntry() and VfatAddEntry() so that they can handle deleting an entry without touching its data and adding an entry with an already provided FCB and thus use the given metadata. - Implement vfatDelFCBFromTable() which is just old code moved to new routine to allow reuse. It deletes a FCB entry from hash table. Doesn't deal with references! - Implement vfatMakeFullName() which is mostly old code moved to new routine to allow reuse. It allocates buffer and copy data for FCB full name. - Implement vfatUpdateFCB() that will update a FCB with new names and parent. It will remove anything related to old name and will recreate using new data. It will adjust references count. - Modify vfatMakeFCBFromDirEntry() so that it calls vfatMakeFullName(). - Modify vfatReleaseFCB() so that it calls vfatDelFCBFromTable(). - Revert VfatOpenFile() to its previous features. - Modify VfatCreateFile() to reimplement support for SL_OPEN_TARGET_DIRECTORY. It is way less hackish than previously. It also properly opens parent now, by incrementing its handle count and by setting appropriate access rights. [KERNEL32] - Rewritten MoveFileWithProgressW() to implement all the missing features that are used in Windows 2k3 including links and reparse points. - Implemented BasepMoveFileDelayed() to replace deprecated add_boot_rename_entry(). This functions is matching the features implemented in SMSS. - Implemented BasepMoveFileCopyProgress() which is used in MoveFileWithProgressW(). - Stubbed BasepNotifyTrackingService() which is not use at the moment (FastFAT, even in Windows doesn't provide such feature). - Reimplemented ReplaceFileA(), MoveFileWithProgressA() to quit Winisms and use our internal helpers. - Make MoveFileX() use MoveFileWithProgressX() directly. - Fixed a few prototypes. TL;DR: This (huge) commit implements file and directory renaming in FastFAT driver. This allows getting rid of old implementation in kernel32 where files were force copied. A feature is still missing, but Jérôme should implement it anytime soon (he prototyped it already): moving directories across volumes. This requires some work in BasepCopyFileExW(). Kudos to all the devs who helped me on this: Christoph, Hervé, Jérôme, Thomas. This finally allows killing CR-52... It was about time! svn path=/trunk/; revision=64836
2014-10-19 21:38:32 +00:00
} 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);
[FASTFAT] - Implement vfatPrepareTargetForRename() that prepares for renaming. It tries to open target and deletes it if it exists and if allowed. And then, it opens the parent directory. - Implement VfatSetRenameInformation() that actually does the renaming (call as SetInformationFile). It handles cases we we have (or we don't have) TargetDirectory provided. It sends notifications as appropriated on demands. - Implement vfatRenameEntry() that renames an entry in place. So far, it only supports FATX entries renaming. FAT entries are a bit more complex. It falls back to vfatMoveEntry() in later cases. - Implement VfatMoveEntry() that will move an entry accross directories (or in place for FAT). Its principles are simple: it deletes the entry in old parent, and recreate it in new parent, keeping file metadata & data. - Modify VfatDelEntry() and VfatAddEntry() so that they can handle deleting an entry without touching its data and adding an entry with an already provided FCB and thus use the given metadata. - Implement vfatDelFCBFromTable() which is just old code moved to new routine to allow reuse. It deletes a FCB entry from hash table. Doesn't deal with references! - Implement vfatMakeFullName() which is mostly old code moved to new routine to allow reuse. It allocates buffer and copy data for FCB full name. - Implement vfatUpdateFCB() that will update a FCB with new names and parent. It will remove anything related to old name and will recreate using new data. It will adjust references count. - Modify vfatMakeFCBFromDirEntry() so that it calls vfatMakeFullName(). - Modify vfatReleaseFCB() so that it calls vfatDelFCBFromTable(). - Revert VfatOpenFile() to its previous features. - Modify VfatCreateFile() to reimplement support for SL_OPEN_TARGET_DIRECTORY. It is way less hackish than previously. It also properly opens parent now, by incrementing its handle count and by setting appropriate access rights. [KERNEL32] - Rewritten MoveFileWithProgressW() to implement all the missing features that are used in Windows 2k3 including links and reparse points. - Implemented BasepMoveFileDelayed() to replace deprecated add_boot_rename_entry(). This functions is matching the features implemented in SMSS. - Implemented BasepMoveFileCopyProgress() which is used in MoveFileWithProgressW(). - Stubbed BasepNotifyTrackingService() which is not use at the moment (FastFAT, even in Windows doesn't provide such feature). - Reimplemented ReplaceFileA(), MoveFileWithProgressA() to quit Winisms and use our internal helpers. - Make MoveFileX() use MoveFileWithProgressX() directly. - Fixed a few prototypes. TL;DR: This (huge) commit implements file and directory renaming in FastFAT driver. This allows getting rid of old implementation in kernel32 where files were force copied. A feature is still missing, but Jérôme should implement it anytime soon (he prototyped it already): moving directories across volumes. This requires some work in BasepCopyFileExW(). Kudos to all the devs who helped me on this: Christoph, Hervé, Jérôme, Thomas. This finally allows killing CR-52... It was about time! svn path=/trunk/; revision=64836
2014-10-19 21:38:32 +00:00
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 */
CODE_SEG("INIT")
VOID
VfatInitFastIoRoutines(
PFAST_IO_DISPATCH FastIoDispatch);
BOOLEAN
NTAPI
VfatAcquireForLazyWrite(
IN PVOID Context,
IN BOOLEAN Wait);
VOID
NTAPI
VfatReleaseFromLazyWrite(
IN PVOID Context);
/* fat.c */
2002-08-14 David Welch <welch@computer2.darkstar.org> * subsys/smss/init.c (SmPagingFilesQueryRoutine): If possible take the size of the paging file from the registry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/section.c (MmCreateDataFileSection): Extend the section if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/pagefile.c (NtCreatePagingFile): Set the file size using the FileAllocationInformation class. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/anonmem.c (MmWritePageVirtualMemory): Implemented function to write anonymous memory pages to the swap file. * ntoskrnl/mm/anonmem.c (MmFreeVirtualMemoryPage): Free any swap page associated with the page. * ntoskrnl/mm/mpw.c (MmWriteDirtyPages): New function to find pages to write to disk. * ntoskrnl/mm/mpw.c (MmMpwThreadMain): Implemented MPW functionality. * ntoskrnl/mm/rmap.c (MmWritePagePhysicalAddress): New function to write a single page back to disk. * ntoskrnl/mm/rmap.c (MmSetCleanAllRmaps, MmSetDirtyAllRmaps, MmIsDirtyPageRmap): New rmap function to support the MPW thread. * ntoskrnl/mm/section.c (MmWritePageSectionView): Implemented function to write back section pages. * ntoskrnl/mm/section.c (MmFreeSectionPage): Free any swap entry associated with the page; mark pages shared with the cache as dirty if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/ldr/loader.c (LdrPEProcessModule): Set name of the module into the module text structure. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/io/rw.c (NtReadFile, NtWriteFile): Use the correct test for whether to wait for the completion of i/o. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cm/ntfunc.c (NtFlushKey): Request synchronous i/o from NtOpenFile. * ntoskrnl/cm/regfile (CmiInitPermanentRegistryHive): Request synchronous i/o from NtCreateFile. * ntoskrnl/dbg/kdb_stabs.c (LdrpLoadModuleSymbols): Request synchronous i/o from NtOpenFile. * ntoskrnl/ldr/sysdll.c (LdrpMapSystemDll): Request synchronous i/o from NtOpenFile. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosSuggestFreeCacheSegment): Maintain the correct reference count. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosFlushCacheSegment): New function to write back a modified cache segment. * ntoskrnl/cc/view.c (CcRosFlushDirtyPages): New function to flush some dirty pages from the cache. * ntoskrnl/cc/view.c (CcRosMarkDirtyCacheSegment): New function to mark a cache segment modified while mapped into memory as dirty. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/pin.c (CcMapData, CcUnpinData, CcSetDirtyPinnedData): Store the dirty status in the BCB; don't write back dirty data immediately. 2002-08-14 David Welch <welch@computer2.darkstar.org> * include/ntos/mm.h: Added SEC_XXXX defines from 'Windows NT/2000 Native API Reference' 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/ea.c (VfatSetExtendedAttributes): Empty placeholder for extended attribute functions. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/finfo.c (VfatSetAllocationSizeInformation): Added function to set allocation size. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/fcb.c (vfatFCBInitializeCache): Renamed to vfatFCBInitializeCacheFromVolume. * drivers/fs/vfat/fcb.c (vfatMakeFCBFromDirEntry): Don't initialise the cache with a file object representing the volume unless the FCB is for a directory. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/create.c (VfatPagingFileCreate): Added a new function for handling paging file only code. * drivers/fs/vfat/create.c (VfatSupersedeFile): Added a new function for doing a file supersede. * drivers/fs/vfat/create.c (VfatCreateFile): Reformatted and adjusted control flow. Set allocation size and extended attributes on create. * drivers/fs/vfat/create.c (VfatCreate): Removed goto. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/cleanup.c (VfatCleanupFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/close.c (VfatCloseFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (updEntry): Renamed to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (addEntry): Renamed to VfatAddEntry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * apps/tests/sectest/sectest.c (main): Fixed formatting. svn path=/trunk/; revision=3331
2002-08-14 20:58:39 +00:00
NTSTATUS
FAT12GetNextCluster(
PDEVICE_EXTENSION DeviceExt,
ULONG CurrentCluster,
PULONG NextCluster);
2002-08-14 David Welch <welch@computer2.darkstar.org> * subsys/smss/init.c (SmPagingFilesQueryRoutine): If possible take the size of the paging file from the registry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/section.c (MmCreateDataFileSection): Extend the section if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/pagefile.c (NtCreatePagingFile): Set the file size using the FileAllocationInformation class. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/mm/anonmem.c (MmWritePageVirtualMemory): Implemented function to write anonymous memory pages to the swap file. * ntoskrnl/mm/anonmem.c (MmFreeVirtualMemoryPage): Free any swap page associated with the page. * ntoskrnl/mm/mpw.c (MmWriteDirtyPages): New function to find pages to write to disk. * ntoskrnl/mm/mpw.c (MmMpwThreadMain): Implemented MPW functionality. * ntoskrnl/mm/rmap.c (MmWritePagePhysicalAddress): New function to write a single page back to disk. * ntoskrnl/mm/rmap.c (MmSetCleanAllRmaps, MmSetDirtyAllRmaps, MmIsDirtyPageRmap): New rmap function to support the MPW thread. * ntoskrnl/mm/section.c (MmWritePageSectionView): Implemented function to write back section pages. * ntoskrnl/mm/section.c (MmFreeSectionPage): Free any swap entry associated with the page; mark pages shared with the cache as dirty if necessary. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/ldr/loader.c (LdrPEProcessModule): Set name of the module into the module text structure. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/io/rw.c (NtReadFile, NtWriteFile): Use the correct test for whether to wait for the completion of i/o. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cm/ntfunc.c (NtFlushKey): Request synchronous i/o from NtOpenFile. * ntoskrnl/cm/regfile (CmiInitPermanentRegistryHive): Request synchronous i/o from NtCreateFile. * ntoskrnl/dbg/kdb_stabs.c (LdrpLoadModuleSymbols): Request synchronous i/o from NtOpenFile. * ntoskrnl/ldr/sysdll.c (LdrpMapSystemDll): Request synchronous i/o from NtOpenFile. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosSuggestFreeCacheSegment): Maintain the correct reference count. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/view.c (CcRosFlushCacheSegment): New function to write back a modified cache segment. * ntoskrnl/cc/view.c (CcRosFlushDirtyPages): New function to flush some dirty pages from the cache. * ntoskrnl/cc/view.c (CcRosMarkDirtyCacheSegment): New function to mark a cache segment modified while mapped into memory as dirty. 2002-08-14 David Welch <welch@computer2.darkstar.org> * ntoskrnl/cc/pin.c (CcMapData, CcUnpinData, CcSetDirtyPinnedData): Store the dirty status in the BCB; don't write back dirty data immediately. 2002-08-14 David Welch <welch@computer2.darkstar.org> * include/ntos/mm.h: Added SEC_XXXX defines from 'Windows NT/2000 Native API Reference' 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/ea.c (VfatSetExtendedAttributes): Empty placeholder for extended attribute functions. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/finfo.c (VfatSetAllocationSizeInformation): Added function to set allocation size. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/fcb.c (vfatFCBInitializeCache): Renamed to vfatFCBInitializeCacheFromVolume. * drivers/fs/vfat/fcb.c (vfatMakeFCBFromDirEntry): Don't initialise the cache with a file object representing the volume unless the FCB is for a directory. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/create.c (VfatPagingFileCreate): Added a new function for handling paging file only code. * drivers/fs/vfat/create.c (VfatSupersedeFile): Added a new function for doing a file supersede. * drivers/fs/vfat/create.c (VfatCreateFile): Reformatted and adjusted control flow. Set allocation size and extended attributes on create. * drivers/fs/vfat/create.c (VfatCreate): Removed goto. 2002-08-14 David Welch <welch@computer2.darkstar.org> * drivers/fs/vfat/cleanup.c (VfatCleanupFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/close.c (VfatCloseFile): Renamed updEntry to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (updEntry): Renamed to VfatUpdateEntry. * drivers/fs/vfat/dirwr.c (addEntry): Renamed to VfatAddEntry. 2002-08-14 David Welch <welch@computer2.darkstar.org> * apps/tests/sectest/sectest.c (main): Fixed formatting. svn path=/trunk/; revision=3331
2002-08-14 20:58:39 +00:00
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);
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
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 */
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
PVFATFCB
vfatNewFCB(
PDEVICE_EXTENSION pVCB,
PUNICODE_STRING pFileNameU);
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
NTSTATUS
vfatSetFCBNewDirName(
PDEVICE_EXTENSION pVCB,
PVFATFCB Fcb,
PVFATFCB ParentFcb);
[FASTFAT] - Implement vfatPrepareTargetForRename() that prepares for renaming. It tries to open target and deletes it if it exists and if allowed. And then, it opens the parent directory. - Implement VfatSetRenameInformation() that actually does the renaming (call as SetInformationFile). It handles cases we we have (or we don't have) TargetDirectory provided. It sends notifications as appropriated on demands. - Implement vfatRenameEntry() that renames an entry in place. So far, it only supports FATX entries renaming. FAT entries are a bit more complex. It falls back to vfatMoveEntry() in later cases. - Implement VfatMoveEntry() that will move an entry accross directories (or in place for FAT). Its principles are simple: it deletes the entry in old parent, and recreate it in new parent, keeping file metadata & data. - Modify VfatDelEntry() and VfatAddEntry() so that they can handle deleting an entry without touching its data and adding an entry with an already provided FCB and thus use the given metadata. - Implement vfatDelFCBFromTable() which is just old code moved to new routine to allow reuse. It deletes a FCB entry from hash table. Doesn't deal with references! - Implement vfatMakeFullName() which is mostly old code moved to new routine to allow reuse. It allocates buffer and copy data for FCB full name. - Implement vfatUpdateFCB() that will update a FCB with new names and parent. It will remove anything related to old name and will recreate using new data. It will adjust references count. - Modify vfatMakeFCBFromDirEntry() so that it calls vfatMakeFullName(). - Modify vfatReleaseFCB() so that it calls vfatDelFCBFromTable(). - Revert VfatOpenFile() to its previous features. - Modify VfatCreateFile() to reimplement support for SL_OPEN_TARGET_DIRECTORY. It is way less hackish than previously. It also properly opens parent now, by incrementing its handle count and by setting appropriate access rights. [KERNEL32] - Rewritten MoveFileWithProgressW() to implement all the missing features that are used in Windows 2k3 including links and reparse points. - Implemented BasepMoveFileDelayed() to replace deprecated add_boot_rename_entry(). This functions is matching the features implemented in SMSS. - Implemented BasepMoveFileCopyProgress() which is used in MoveFileWithProgressW(). - Stubbed BasepNotifyTrackingService() which is not use at the moment (FastFAT, even in Windows doesn't provide such feature). - Reimplemented ReplaceFileA(), MoveFileWithProgressA() to quit Winisms and use our internal helpers. - Make MoveFileX() use MoveFileWithProgressX() directly. - Fixed a few prototypes. TL;DR: This (huge) commit implements file and directory renaming in FastFAT driver. This allows getting rid of old implementation in kernel32 where files were force copied. A feature is still missing, but Jérôme should implement it anytime soon (he prototyped it already): moving directories across volumes. This requires some work in BasepCopyFileExW(). Kudos to all the devs who helped me on this: Christoph, Hervé, Jérôme, Thomas. This finally allows killing CR-52... It was about time! svn path=/trunk/; revision=64836
2014-10-19 21:38:32 +00:00
NTSTATUS
vfatUpdateFCB(
PDEVICE_EXTENSION pVCB,
PVFATFCB Fcb,
PVFAT_DIRENTRY_CONTEXT DirContext,
[FASTFAT] - Implement vfatPrepareTargetForRename() that prepares for renaming. It tries to open target and deletes it if it exists and if allowed. And then, it opens the parent directory. - Implement VfatSetRenameInformation() that actually does the renaming (call as SetInformationFile). It handles cases we we have (or we don't have) TargetDirectory provided. It sends notifications as appropriated on demands. - Implement vfatRenameEntry() that renames an entry in place. So far, it only supports FATX entries renaming. FAT entries are a bit more complex. It falls back to vfatMoveEntry() in later cases. - Implement VfatMoveEntry() that will move an entry accross directories (or in place for FAT). Its principles are simple: it deletes the entry in old parent, and recreate it in new parent, keeping file metadata & data. - Modify VfatDelEntry() and VfatAddEntry() so that they can handle deleting an entry without touching its data and adding an entry with an already provided FCB and thus use the given metadata. - Implement vfatDelFCBFromTable() which is just old code moved to new routine to allow reuse. It deletes a FCB entry from hash table. Doesn't deal with references! - Implement vfatMakeFullName() which is mostly old code moved to new routine to allow reuse. It allocates buffer and copy data for FCB full name. - Implement vfatUpdateFCB() that will update a FCB with new names and parent. It will remove anything related to old name and will recreate using new data. It will adjust references count. - Modify vfatMakeFCBFromDirEntry() so that it calls vfatMakeFullName(). - Modify vfatReleaseFCB() so that it calls vfatDelFCBFromTable(). - Revert VfatOpenFile() to its previous features. - Modify VfatCreateFile() to reimplement support for SL_OPEN_TARGET_DIRECTORY. It is way less hackish than previously. It also properly opens parent now, by incrementing its handle count and by setting appropriate access rights. [KERNEL32] - Rewritten MoveFileWithProgressW() to implement all the missing features that are used in Windows 2k3 including links and reparse points. - Implemented BasepMoveFileDelayed() to replace deprecated add_boot_rename_entry(). This functions is matching the features implemented in SMSS. - Implemented BasepMoveFileCopyProgress() which is used in MoveFileWithProgressW(). - Stubbed BasepNotifyTrackingService() which is not use at the moment (FastFAT, even in Windows doesn't provide such feature). - Reimplemented ReplaceFileA(), MoveFileWithProgressA() to quit Winisms and use our internal helpers. - Make MoveFileX() use MoveFileWithProgressX() directly. - Fixed a few prototypes. TL;DR: This (huge) commit implements file and directory renaming in FastFAT driver. This allows getting rid of old implementation in kernel32 where files were force copied. A feature is still missing, but Jérôme should implement it anytime soon (he prototyped it already): moving directories across volumes. This requires some work in BasepCopyFileExW(). Kudos to all the devs who helped me on this: Christoph, Hervé, Jérôme, Thomas. This finally allows killing CR-52... It was about time! svn path=/trunk/; revision=64836
2014-10-19 21:38:32 +00:00
PVFATFCB ParentFcb);
VOID
vfatDestroyFCB(
PVFATFCB pFCB);
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
VOID
vfatDestroyCCB(
PVFATCCB pCcb);
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
VOID
#ifndef KDBG
vfatGrabFCB(
#else
_vfatGrabFCB(
#endif
PDEVICE_EXTENSION pVCB,
PVFATFCB pFCB
#ifdef KDBG
,
PCSTR File,
ULONG Line,
PCSTR Func
#endif
);
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
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
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
PVFATFCB
vfatGrabFCBFromTable(
PDEVICE_EXTENSION pDeviceExt,
PUNICODE_STRING pFileNameU);
- Change all FAT*FindAvailableCluster functions to new functions FAT*FindAndMarkAvailableCluster which have incorporated the setting of EOF marker in the File Allocation Table for the returned cluster. - Rewritten FAT32CountAvailableClusters, FAT32FindAndMarkAvailableCluster, FAT16CountAvailableClusters and FAT16FindAndMarkAvailableCluster for better performance. These functions were using one big loop for traversing the FAT and had a block of code in the loop for requesting cache manger for next chunk of FAT *if necessary* (which commonly wasn't the case). Now it's changed to request always a whole FAT chunk and process it at once in a nested loop. - Cache last offset + cluster pair while reading/writing from/to file. This ensures almost linear times when doing sequential reads/writes, because the whole FAT traversing for the file is not done again for every request. Previously there was code for this, but it was neither correctly used nor working. It stored the last offset + cluster pair in file CCB structure (that is unique for each opened file handle) and not FCB structure (which is shared among all instances of the same file). This resulted in inconsistent cluster + offset number when the file allocation chain was changed (eg. by enlarging/shrinking the file), but since the cached offsets weren't actully used it went unnoticed. - Remove old hack from NextCluster and fix the call to it in VfatAddEntry. Not much to say about it, there was an temporary hack in NextCluster and with fixed VfatAddEntry it's now no longer needed. - Add pointers to WriteCluster, FindAndMarkAvailableCluster and GetNextCluster functions to device extension (set during mount) and use them at appropriate locations. This avoids some nasty if's in the code and causes some unnoticable performance improvment in the low-level FAT code. - Lock the directory FCB in VfatAddEntry while modifying it. This should propably be done on more places, but it needs more investigations. - Increase the file cache allocation size in VfatRead/VfatWrite. It boosts the overall speed of the driver a lot. svn path=/trunk/; revision=10344
2004-08-01 21:57:18 +00:00
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 */
CODE_SEG("INIT")
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_ */