2005-08-24 18:29:45 +00:00
|
|
|
/*
|
[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
|
|
|
* FILE: drivers/filesystems/fastfat/fcb.c
|
2005-11-04 00:03:34 +00:00
|
|
|
* PURPOSE: Routines to manipulate FCBs.
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
|
|
|
* Rex Jolliff (rex@lvcablemodem.com)
|
|
|
|
* Herve Poussineau (reactos@poussine.freesurf.fr)
|
[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
|
|
|
* Pierre Schweitzer (pierre@reactos.org)
|
2005-11-04 00:03:34 +00:00
|
|
|
*/
|
2001-05-02 03:18:03 +00:00
|
|
|
|
|
|
|
/* ------------------------------------------------------- INCLUDES */
|
|
|
|
|
2013-12-19 16:20:28 +00:00
|
|
|
#include "vfat.h"
|
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2007-11-21 17:18:25 +00:00
|
|
|
#ifdef __GNUC__
|
2005-01-12 12:33:57 +00:00
|
|
|
#include <wctype.h> /* towlower prototype */
|
2007-11-21 17:18:25 +00:00
|
|
|
#endif
|
2001-05-02 03:18:03 +00:00
|
|
|
|
|
|
|
/* -------------------------------------------------------- DEFINES */
|
2002-09-08 10:23:54 +00:00
|
|
|
|
2009-08-24 17:12:25 +00:00
|
|
|
#define TAG_FCB 'BCFV'
|
2001-05-02 03:18:03 +00:00
|
|
|
|
|
|
|
/* -------------------------------------------------------- PUBLICS */
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
static
|
|
|
|
ULONG
|
|
|
|
vfatNameHash(
|
|
|
|
ULONG hash,
|
|
|
|
PUNICODE_STRING NameU)
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PWCHAR last;
|
|
|
|
PWCHAR curr;
|
|
|
|
register WCHAR c;
|
|
|
|
|
|
|
|
// LFN could start from "."
|
|
|
|
//ASSERT(NameU->Buffer[0] != L'.');
|
|
|
|
curr = NameU->Buffer;
|
|
|
|
last = NameU->Buffer + NameU->Length / sizeof(WCHAR);
|
|
|
|
|
|
|
|
while(curr < last)
|
|
|
|
{
|
|
|
|
c = towlower(*curr++);
|
|
|
|
hash = (hash + (c << 4) + (c >> 4)) * 11;
|
|
|
|
}
|
|
|
|
return hash;
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
}
|
|
|
|
|
2003-10-11 17:51:56 +00:00
|
|
|
VOID
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatSplitPathName(
|
|
|
|
PUNICODE_STRING PathNameU,
|
|
|
|
PUNICODE_STRING DirNameU,
|
|
|
|
PUNICODE_STRING FileNameU)
|
2003-10-11 17:51:56 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PWCHAR pName;
|
|
|
|
USHORT Length = 0;
|
|
|
|
pName = PathNameU->Buffer + PathNameU->Length / sizeof(WCHAR) - 1;
|
|
|
|
while (*pName != L'\\' && pName >= PathNameU->Buffer)
|
|
|
|
{
|
|
|
|
pName--;
|
|
|
|
Length++;
|
|
|
|
}
|
|
|
|
ASSERT(*pName == L'\\' || pName < PathNameU->Buffer);
|
|
|
|
if (FileNameU)
|
|
|
|
{
|
|
|
|
FileNameU->Buffer = pName + 1;
|
|
|
|
FileNameU->Length = FileNameU->MaximumLength = Length * sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
if (DirNameU)
|
|
|
|
{
|
|
|
|
DirNameU->Buffer = PathNameU->Buffer;
|
|
|
|
DirNameU->Length = (pName + 1 - PathNameU->Buffer) * sizeof(WCHAR);
|
|
|
|
DirNameU->MaximumLength = DirNameU->Length;
|
|
|
|
}
|
2003-10-11 17:51:56 +00:00
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
vfatInitFcb(
|
|
|
|
PVFATFCB Fcb,
|
|
|
|
PUNICODE_STRING NameU)
|
2003-10-11 17:51:56 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
USHORT PathNameBufferLength;
|
|
|
|
|
|
|
|
if (NameU)
|
|
|
|
PathNameBufferLength = NameU->Length + sizeof(WCHAR);
|
|
|
|
else
|
|
|
|
PathNameBufferLength = 0;
|
|
|
|
|
|
|
|
Fcb->PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameBufferLength, TAG_FCB);
|
|
|
|
if (!Fcb->PathNameBuffer)
|
|
|
|
{
|
|
|
|
/* FIXME: what to do if no more memory? */
|
|
|
|
DPRINT1("Unable to initialize FCB for filename '%wZ'\n", NameU);
|
|
|
|
KeBugCheckEx(FAT_FILE_SYSTEM, (ULONG_PTR)Fcb, (ULONG_PTR)NameU, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Fcb->PathNameU.Length = 0;
|
|
|
|
Fcb->PathNameU.Buffer = Fcb->PathNameBuffer;
|
|
|
|
Fcb->PathNameU.MaximumLength = PathNameBufferLength;
|
|
|
|
Fcb->ShortNameU.Length = 0;
|
|
|
|
Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer;
|
|
|
|
Fcb->ShortNameU.MaximumLength = sizeof(Fcb->ShortNameBuffer);
|
|
|
|
Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
|
|
|
|
if (NameU && NameU->Length)
|
|
|
|
{
|
|
|
|
RtlCopyUnicodeString(&Fcb->PathNameU, NameU);
|
|
|
|
vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Fcb->DirNameU.Buffer = Fcb->LongNameU.Buffer = NULL;
|
|
|
|
Fcb->DirNameU.MaximumLength = Fcb->DirNameU.Length = 0;
|
|
|
|
Fcb->LongNameU.MaximumLength = Fcb->LongNameU.Length = 0;
|
|
|
|
}
|
|
|
|
RtlZeroMemory(&Fcb->FCBShareAccess, sizeof(SHARE_ACCESS));
|
|
|
|
Fcb->OpenHandleCount = 0;
|
2005-05-08 02:16:32 +00:00
|
|
|
}
|
2003-10-11 17:51:56 +00:00
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
PVFATFCB
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatNewFCB(
|
|
|
|
PDEVICE_EXTENSION pVCB,
|
|
|
|
PUNICODE_STRING pFileNameU)
|
2001-05-02 03:18:03 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PVFATFCB rcFCB;
|
|
|
|
|
|
|
|
DPRINT("'%wZ'\n", pFileNameU);
|
|
|
|
|
|
|
|
rcFCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->FcbLookasideList);
|
|
|
|
if (rcFCB == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
RtlZeroMemory(rcFCB, sizeof(VFATFCB));
|
|
|
|
vfatInitFcb(rcFCB, pFileNameU);
|
2017-02-17 21:24:12 +00:00
|
|
|
if (vfatVolumeIsFatX(pVCB))
|
2013-12-09 18:48:13 +00:00
|
|
|
rcFCB->Attributes = &rcFCB->entry.FatX.Attrib;
|
|
|
|
else
|
|
|
|
rcFCB->Attributes = &rcFCB->entry.Fat.Attrib;
|
|
|
|
rcFCB->Hash.Hash = vfatNameHash(0, &rcFCB->PathNameU);
|
|
|
|
rcFCB->Hash.self = rcFCB;
|
|
|
|
rcFCB->ShortHash.self = rcFCB;
|
|
|
|
ExInitializeResourceLite(&rcFCB->PagingIoResource);
|
|
|
|
ExInitializeResourceLite(&rcFCB->MainResource);
|
|
|
|
FsRtlInitializeFileLock(&rcFCB->FileLock, NULL, NULL);
|
|
|
|
ExInitializeFastMutex(&rcFCB->LastMutex);
|
|
|
|
rcFCB->RFCB.PagingIoResource = &rcFCB->PagingIoResource;
|
|
|
|
rcFCB->RFCB.Resource = &rcFCB->MainResource;
|
|
|
|
rcFCB->RFCB.IsFastIoPossible = FastIoIsNotPossible;
|
2016-08-06 08:30:30 +00:00
|
|
|
InitializeListHead(&rcFCB->ParentListHead);
|
2013-12-09 18:48:13 +00:00
|
|
|
|
|
|
|
return rcFCB;
|
2001-05-02 03:18:03 +00:00
|
|
|
}
|
|
|
|
|
[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
|
|
|
static
|
|
|
|
VOID
|
|
|
|
vfatDelFCBFromTable(
|
|
|
|
PDEVICE_EXTENSION pVCB,
|
|
|
|
PVFATFCB pFCB)
|
|
|
|
{
|
|
|
|
ULONG Index;
|
|
|
|
ULONG ShortIndex;
|
|
|
|
HASHENTRY* entry;
|
|
|
|
|
|
|
|
Index = pFCB->Hash.Hash % pVCB->HashTableSize;
|
|
|
|
ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
|
|
|
|
|
|
|
|
if (pFCB->Hash.Hash != pFCB->ShortHash.Hash)
|
|
|
|
{
|
|
|
|
entry = pVCB->FcbHashTable[ShortIndex];
|
|
|
|
if (entry->self == pFCB)
|
|
|
|
{
|
|
|
|
pVCB->FcbHashTable[ShortIndex] = entry->next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (entry->next->self != pFCB)
|
|
|
|
{
|
|
|
|
entry = entry->next;
|
|
|
|
}
|
|
|
|
entry->next = pFCB->ShortHash.next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
entry = pVCB->FcbHashTable[Index];
|
|
|
|
if (entry->self == pFCB)
|
|
|
|
{
|
|
|
|
pVCB->FcbHashTable[Index] = entry->next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (entry->next->self != pFCB)
|
|
|
|
{
|
|
|
|
entry = entry->next;
|
|
|
|
}
|
|
|
|
entry->next = pFCB->Hash.next;
|
|
|
|
}
|
2014-10-20 09:31:50 +00:00
|
|
|
|
|
|
|
RemoveEntryList(&pFCB->FcbListEntry);
|
[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
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
NTSTATUS
|
|
|
|
vfatMakeFullName(
|
|
|
|
PVFATFCB directoryFCB,
|
|
|
|
PUNICODE_STRING LongNameU,
|
|
|
|
PUNICODE_STRING ShortNameU,
|
|
|
|
PUNICODE_STRING NameU)
|
|
|
|
{
|
|
|
|
PWCHAR PathNameBuffer;
|
|
|
|
USHORT PathNameLength;
|
|
|
|
|
|
|
|
PathNameLength = directoryFCB->PathNameU.Length + max(LongNameU->Length, ShortNameU->Length);
|
|
|
|
if (!vfatFCBIsRoot(directoryFCB))
|
|
|
|
{
|
|
|
|
PathNameLength += sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PathNameLength > LONGNAME_MAX_LENGTH * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
|
|
|
PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameLength + sizeof(WCHAR), TAG_FCB);
|
|
|
|
if (!PathNameBuffer)
|
|
|
|
{
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
NameU->Buffer = PathNameBuffer;
|
|
|
|
NameU->Length = 0;
|
|
|
|
NameU->MaximumLength = PathNameLength;
|
|
|
|
|
|
|
|
RtlCopyUnicodeString(NameU, &directoryFCB->PathNameU);
|
|
|
|
if (!vfatFCBIsRoot(directoryFCB))
|
|
|
|
{
|
|
|
|
RtlAppendUnicodeToString(NameU, L"\\");
|
|
|
|
}
|
|
|
|
if (LongNameU->Length > 0)
|
|
|
|
{
|
|
|
|
RtlAppendUnicodeStringToString(NameU, LongNameU);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RtlAppendUnicodeStringToString(NameU, ShortNameU);
|
|
|
|
}
|
|
|
|
NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2005-05-08 02:16:32 +00:00
|
|
|
VOID
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatDestroyCCB(
|
|
|
|
PVFATCCB pCcb)
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
if (pCcb->SearchPattern.Buffer)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(pCcb->SearchPattern.Buffer, TAG_VFAT);
|
|
|
|
}
|
|
|
|
ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, pCcb);
|
* Used look aside lists to allocate memory for VFATFCB, VFATCCB and VFAT_IRP_CONTEXT.
* Removed IsLastEntry, IsVolEntry, IsDeletedEntry, vfat_wstrlen, vfatGrabFCB,
vfat_initstr, vfat_wcsncat, vfat_wcsncpy, vfat_movestr, wstrcmpi and replaced
this functions with existing equivalents or functions from ntoskrnl.
* Merged GetEntryName into vfatGetNextDirEntry for reducing some overhead.
* Implemented a file name cache to speed up the searching for existing fcb.
* Removed some calls to FsdDosDateTimeToFileTime.
* Moved the call to CcZeroData behind the initializing of the cache (in VfatWrite).
* Using existing fcbs in FindFile if there is no '*?' within the search name.
svn path=/trunk/; revision=3740
2002-11-11 21:49:18 +00:00
|
|
|
}
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
VOID
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatDestroyFCB(
|
|
|
|
PVFATFCB pFCB)
|
2001-05-10 04:02:21 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
FsRtlUninitializeFileLock(&pFCB->FileLock);
|
2016-08-06 08:57:47 +00:00
|
|
|
if (!vfatFCBIsRoot(pFCB) &&
|
|
|
|
!BooleanFlagOn(pFCB->Flags, FCB_IS_FAT) && !BooleanFlagOn(pFCB->Flags, FCB_IS_VOLUME))
|
|
|
|
{
|
|
|
|
RemoveEntryList(&pFCB->ParentListEntry);
|
|
|
|
}
|
2013-12-09 18:48:13 +00:00
|
|
|
ExFreePool(pFCB->PathNameBuffer);
|
|
|
|
ExDeleteResourceLite(&pFCB->PagingIoResource);
|
|
|
|
ExDeleteResourceLite(&pFCB->MainResource);
|
2016-08-06 08:30:30 +00:00
|
|
|
ASSERT(IsListEmpty(&pFCB->ParentListHead));
|
2017-03-04 14:48:05 +00:00
|
|
|
ExFreeToNPagedLookasideList(&VfatGlobalData->FcbLookasideList, pFCB);
|
2001-05-10 04:02:21 +00:00
|
|
|
}
|
|
|
|
|
2005-01-12 10:46:13 +00:00
|
|
|
BOOLEAN
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatFCBIsRoot(
|
|
|
|
PVFATFCB FCB)
|
2001-07-05 01:51:53 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
return FCB->PathNameU.Length == sizeof(WCHAR) && FCB->PathNameU.Buffer[0] == L'\\' ? TRUE : FALSE;
|
2001-05-02 03:18:03 +00:00
|
|
|
}
|
|
|
|
|
2014-10-26 20:20:42 +00:00
|
|
|
VOID
|
|
|
|
vfatGrabFCB(
|
|
|
|
PDEVICE_EXTENSION pVCB,
|
|
|
|
PVFATFCB pFCB)
|
|
|
|
{
|
2014-10-26 20:29:00 +00:00
|
|
|
ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
|
|
|
|
|
2014-11-01 18:00:15 +00:00
|
|
|
ASSERT(pFCB != pVCB->VolumeFcb);
|
2014-11-05 19:06:19 +00:00
|
|
|
ASSERT(pFCB->RefCount > 0);
|
2014-10-26 20:20:42 +00:00
|
|
|
++pFCB->RefCount;
|
|
|
|
}
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
VOID
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatReleaseFCB(
|
|
|
|
PDEVICE_EXTENSION pVCB,
|
|
|
|
PVFATFCB pFCB)
|
2001-05-02 03:18:03 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PVFATFCB tmpFcb;
|
|
|
|
|
|
|
|
DPRINT("releasing FCB at %p: %wZ, refCount:%d\n",
|
|
|
|
pFCB, &pFCB->PathNameU, pFCB->RefCount);
|
|
|
|
|
2014-10-26 20:29:00 +00:00
|
|
|
ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
while (pFCB)
|
|
|
|
{
|
2014-11-01 18:00:15 +00:00
|
|
|
ASSERT(pFCB != pVCB->VolumeFcb);
|
2014-11-05 19:06:19 +00:00
|
|
|
ASSERT(pFCB->RefCount > 0);
|
2013-12-09 18:48:13 +00:00
|
|
|
pFCB->RefCount--;
|
|
|
|
if (pFCB->RefCount == 0)
|
|
|
|
{
|
[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
|
|
|
ASSERT(pFCB->OpenHandleCount == 0);
|
2013-12-09 18:48:13 +00:00
|
|
|
tmpFcb = pFCB->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
|
|
|
vfatDelFCBFromTable(pVCB, pFCB);
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatDestroyFCB(pFCB);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmpFcb = NULL;
|
|
|
|
}
|
|
|
|
pFCB = tmpFcb;
|
|
|
|
}
|
2001-05-02 03:18:03 +00:00
|
|
|
}
|
|
|
|
|
[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
|
|
|
static
|
2001-07-20 08:00:21 +00:00
|
|
|
VOID
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatAddFCBToTable(
|
|
|
|
PDEVICE_EXTENSION pVCB,
|
|
|
|
PVFATFCB pFCB)
|
2001-05-02 03:18:03 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
ULONG Index;
|
|
|
|
ULONG ShortIndex;
|
|
|
|
|
2016-08-07 14:24:45 +00:00
|
|
|
ASSERT(pFCB->Hash.Hash == vfatNameHash(0, &pFCB->PathNameU));
|
2013-12-09 18:48:13 +00:00
|
|
|
Index = pFCB->Hash.Hash % pVCB->HashTableSize;
|
|
|
|
ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
|
|
|
|
|
|
|
|
InsertTailList(&pVCB->FcbListHead, &pFCB->FcbListEntry);
|
|
|
|
|
|
|
|
pFCB->Hash.next = pVCB->FcbHashTable[Index];
|
|
|
|
pVCB->FcbHashTable[Index] = &pFCB->Hash;
|
|
|
|
if (pFCB->Hash.Hash != pFCB->ShortHash.Hash)
|
|
|
|
{
|
|
|
|
pFCB->ShortHash.next = pVCB->FcbHashTable[ShortIndex];
|
|
|
|
pVCB->FcbHashTable[ShortIndex] = &pFCB->ShortHash;
|
|
|
|
}
|
|
|
|
if (pFCB->parentFcb)
|
|
|
|
{
|
2014-10-26 20:20:42 +00:00
|
|
|
vfatGrabFCB(pVCB, pFCB->parentFcb);
|
2013-12-09 18:48:13 +00:00
|
|
|
}
|
2001-05-02 03:18:03 +00:00
|
|
|
}
|
|
|
|
|
2016-08-05 10:48:01 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
vfatInitFCBFromDirEntry(
|
|
|
|
PDEVICE_EXTENSION Vcb,
|
|
|
|
PVFATFCB Fcb,
|
|
|
|
PVFAT_DIRENTRY_CONTEXT DirContext)
|
|
|
|
{
|
|
|
|
ULONG Size;
|
|
|
|
|
|
|
|
RtlCopyMemory(&Fcb->entry, &DirContext->DirEntry, sizeof (DIR_ENTRY));
|
|
|
|
RtlCopyUnicodeString(&Fcb->ShortNameU, &DirContext->ShortNameU);
|
2016-08-07 14:24:45 +00:00
|
|
|
Fcb->Hash.Hash = vfatNameHash(0, &Fcb->PathNameU);
|
2017-02-17 21:24:12 +00:00
|
|
|
if (vfatVolumeIsFatX(Vcb))
|
2016-08-05 10:48:01 +00:00
|
|
|
{
|
|
|
|
Fcb->ShortHash.Hash = Fcb->Hash.Hash;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Fcb->ShortHash.Hash = vfatNameHash(0, &Fcb->DirNameU);
|
|
|
|
Fcb->ShortHash.Hash = vfatNameHash(Fcb->ShortHash.Hash, &Fcb->ShortNameU);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vfatFCBIsDirectory(Fcb))
|
|
|
|
{
|
|
|
|
ULONG FirstCluster, CurrentCluster;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
Size = 0;
|
|
|
|
FirstCluster = vfatDirEntryGetFirstCluster(Vcb, &Fcb->entry);
|
|
|
|
if (FirstCluster == 1)
|
|
|
|
{
|
|
|
|
Size = Vcb->FatInfo.rootDirectorySectors * Vcb->FatInfo.BytesPerSector;
|
|
|
|
}
|
|
|
|
else if (FirstCluster != 0)
|
|
|
|
{
|
|
|
|
CurrentCluster = FirstCluster;
|
|
|
|
while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Size += Vcb->FatInfo.BytesPerCluster;
|
|
|
|
Status = NextCluster(Vcb, FirstCluster, &CurrentCluster, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-02-17 21:24:12 +00:00
|
|
|
else if (vfatVolumeIsFatX(Vcb))
|
2016-08-05 10:48:01 +00:00
|
|
|
{
|
|
|
|
Size = Fcb->entry.FatX.FileSize;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Size = Fcb->entry.Fat.FileSize;
|
|
|
|
}
|
|
|
|
Fcb->dirIndex = DirContext->DirIndex;
|
|
|
|
Fcb->startIndex = DirContext->StartIndex;
|
2017-02-17 21:24:12 +00:00
|
|
|
if (vfatVolumeIsFatX(Vcb) && !vfatFCBIsRoot(Fcb))
|
2016-08-05 10:48:01 +00:00
|
|
|
{
|
|
|
|
ASSERT(DirContext->DirIndex >= 2 && DirContext->StartIndex >= 2);
|
|
|
|
Fcb->dirIndex = DirContext->DirIndex-2;
|
|
|
|
Fcb->startIndex = DirContext->StartIndex-2;
|
|
|
|
}
|
|
|
|
Fcb->RFCB.FileSize.QuadPart = Size;
|
|
|
|
Fcb->RFCB.ValidDataLength.QuadPart = Size;
|
|
|
|
Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP_64(Size, Vcb->FatInfo.BytesPerCluster);
|
|
|
|
}
|
|
|
|
|
2016-08-07 12:29:48 +00:00
|
|
|
NTSTATUS
|
|
|
|
vfatSetFCBNewDirName(
|
|
|
|
PDEVICE_EXTENSION pVCB,
|
|
|
|
PVFATFCB Fcb,
|
|
|
|
PVFATFCB ParentFcb)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
UNICODE_STRING NewNameU;
|
|
|
|
|
|
|
|
/* Get full path name */
|
|
|
|
Status = vfatMakeFullName(ParentFcb, &Fcb->LongNameU, &Fcb->ShortNameU, &NewNameU);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete old name */
|
|
|
|
if (Fcb->PathNameBuffer)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(Fcb->PathNameBuffer, TAG_FCB);
|
|
|
|
}
|
|
|
|
Fcb->PathNameU = NewNameU;
|
|
|
|
|
|
|
|
/* Delete from table */
|
|
|
|
vfatDelFCBFromTable(pVCB, Fcb);
|
|
|
|
|
|
|
|
/* Split it properly */
|
|
|
|
Fcb->PathNameBuffer = Fcb->PathNameU.Buffer;
|
|
|
|
Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
|
|
|
|
vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
|
2016-08-07 14:24:45 +00:00
|
|
|
Fcb->Hash.Hash = vfatNameHash(0, &Fcb->PathNameU);
|
2017-02-17 21:24:12 +00:00
|
|
|
if (vfatVolumeIsFatX(pVCB))
|
2016-08-07 12:29:48 +00:00
|
|
|
{
|
|
|
|
Fcb->ShortHash.Hash = Fcb->Hash.Hash;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Fcb->ShortHash.Hash = vfatNameHash(0, &Fcb->DirNameU);
|
|
|
|
Fcb->ShortHash.Hash = vfatNameHash(Fcb->ShortHash.Hash, &Fcb->ShortNameU);
|
|
|
|
}
|
|
|
|
|
|
|
|
vfatAddFCBToTable(pVCB, Fcb);
|
|
|
|
vfatReleaseFCB(pVCB, ParentFcb);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
[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,
|
2016-04-30 08:20:00 +00:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PVFATFCB OldParent;
|
|
|
|
|
2016-04-30 08:20:00 +00:00
|
|
|
DPRINT("vfatUpdateFCB(%p, %p, %p, %p)\n", pVCB, Fcb, DirContext, 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
|
|
|
|
2014-11-06 00:07:01 +00:00
|
|
|
/* Get full path name */
|
2016-04-30 08:20:00 +00:00
|
|
|
Status = vfatMakeFullName(ParentFcb, &DirContext->LongNameU, &DirContext->ShortNameU, &Fcb->PathNameU);
|
2014-11-06 00:07:01 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
[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
|
|
|
/* Delete old name */
|
|
|
|
if (Fcb->PathNameBuffer)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(Fcb->PathNameBuffer, TAG_FCB);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete from table */
|
|
|
|
vfatDelFCBFromTable(pVCB, Fcb);
|
|
|
|
|
|
|
|
/* Split it properly */
|
|
|
|
Fcb->PathNameBuffer = Fcb->PathNameU.Buffer;
|
|
|
|
Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
|
|
|
|
vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
|
|
|
|
|
2016-08-05 10:48:01 +00:00
|
|
|
/* Save old parent */
|
|
|
|
OldParent = Fcb->parentFcb;
|
2016-08-06 08:30:30 +00:00
|
|
|
RemoveEntryList(&Fcb->ParentListEntry);
|
[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
|
|
|
|
2016-08-05 10:48:01 +00:00
|
|
|
/* Reinit FCB */
|
|
|
|
vfatInitFCBFromDirEntry(pVCB, Fcb, DirContext);
|
2016-04-30 08:20:00 +00:00
|
|
|
|
2016-08-05 10:48:01 +00:00
|
|
|
if (vfatFCBIsDirectory(Fcb))
|
[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
|
|
|
{
|
2016-08-05 10:48:01 +00:00
|
|
|
CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);
|
[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
|
|
|
}
|
|
|
|
Fcb->parentFcb = ParentFcb;
|
2016-08-06 08:30:30 +00:00
|
|
|
InsertTailList(&ParentFcb->ParentListHead, &Fcb->ParentListEntry);
|
[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
|
|
|
vfatAddFCBToTable(pVCB, Fcb);
|
|
|
|
|
2014-11-06 00:07:01 +00:00
|
|
|
/* If we moved across directories, dereference our old parent
|
|
|
|
* We also dereference in case we're just renaming since AddFCBToTable references it
|
[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
|
|
|
*/
|
|
|
|
vfatReleaseFCB(pVCB, OldParent);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
PVFATFCB
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatGrabFCBFromTable(
|
|
|
|
PDEVICE_EXTENSION pVCB,
|
|
|
|
PUNICODE_STRING PathNameU)
|
2001-05-02 03:18:03 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PVFATFCB rcFCB;
|
|
|
|
ULONG Hash;
|
|
|
|
UNICODE_STRING DirNameU;
|
|
|
|
UNICODE_STRING FileNameU;
|
|
|
|
PUNICODE_STRING FcbNameU;
|
|
|
|
|
|
|
|
HASHENTRY* entry;
|
|
|
|
|
|
|
|
DPRINT("'%wZ'\n", PathNameU);
|
|
|
|
|
2015-12-08 12:57:45 +00:00
|
|
|
ASSERT(PathNameU->Length >= sizeof(WCHAR) && PathNameU->Buffer[0] == L'\\');
|
2013-12-09 18:48:13 +00:00
|
|
|
Hash = vfatNameHash(0, PathNameU);
|
|
|
|
|
|
|
|
entry = pVCB->FcbHashTable[Hash % pVCB->HashTableSize];
|
|
|
|
if (entry)
|
|
|
|
{
|
|
|
|
vfatSplitPathName(PathNameU, &DirNameU, &FileNameU);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (entry)
|
|
|
|
{
|
|
|
|
if (entry->Hash == Hash)
|
|
|
|
{
|
|
|
|
rcFCB = entry->self;
|
|
|
|
DPRINT("'%wZ' '%wZ'\n", &DirNameU, &rcFCB->DirNameU);
|
|
|
|
if (RtlEqualUnicodeString(&DirNameU, &rcFCB->DirNameU, TRUE))
|
|
|
|
{
|
|
|
|
if (rcFCB->Hash.Hash == Hash)
|
|
|
|
{
|
|
|
|
FcbNameU = &rcFCB->LongNameU;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FcbNameU = &rcFCB->ShortNameU;
|
|
|
|
}
|
|
|
|
/* compare the file name */
|
|
|
|
DPRINT("'%wZ' '%wZ'\n", &FileNameU, FcbNameU);
|
|
|
|
if (RtlEqualUnicodeString(&FileNameU, FcbNameU, TRUE))
|
|
|
|
{
|
2014-10-26 20:20:42 +00:00
|
|
|
vfatGrabFCB(pVCB, rcFCB);
|
2013-12-09 18:48:13 +00:00
|
|
|
return rcFCB;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
entry = entry->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
2001-05-02 03:18:03 +00:00
|
|
|
}
|
2001-05-10 04:02:21 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
static
|
|
|
|
NTSTATUS
|
|
|
|
vfatFCBInitializeCacheFromVolume(
|
|
|
|
PVCB vcb,
|
|
|
|
PVFATFCB fcb)
|
2001-05-10 04:02:21 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PFILE_OBJECT fileObject;
|
|
|
|
PVFATCCB newCCB;
|
2014-08-24 03:28:01 +00:00
|
|
|
NTSTATUS status;
|
2013-12-09 18:48:13 +00:00
|
|
|
|
|
|
|
fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
|
|
|
|
|
|
|
|
newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
|
|
|
|
if (newCCB == NULL)
|
|
|
|
{
|
2014-08-24 03:28:01 +00:00
|
|
|
ObDereferenceObject(fileObject);
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
RtlZeroMemory(newCCB, sizeof (VFATCCB));
|
|
|
|
|
|
|
|
fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
|
|
|
|
fileObject->FsContext = fcb;
|
|
|
|
fileObject->FsContext2 = newCCB;
|
|
|
|
fcb->FileObject = fileObject;
|
|
|
|
|
2014-08-24 03:28:01 +00:00
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
CcInitializeCacheMap(fileObject,
|
|
|
|
(PCC_FILE_SIZES)(&fcb->RFCB.AllocationSize),
|
|
|
|
TRUE,
|
|
|
|
&VfatGlobalData->CacheMgrCallbacks,
|
|
|
|
fcb);
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
status = _SEH2_GetExceptionCode();
|
|
|
|
fcb->FileObject = NULL;
|
|
|
|
ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, newCCB);
|
|
|
|
ObDereferenceObject(fileObject);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
2013-12-09 18:48:13 +00:00
|
|
|
|
2014-11-05 19:06:19 +00:00
|
|
|
vfatGrabFCB(vcb, fcb);
|
2013-12-09 18:48:13 +00:00
|
|
|
fcb->Flags |= FCB_CACHE_INITIALIZED;
|
|
|
|
return STATUS_SUCCESS;
|
2001-07-05 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
PVFATFCB
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatMakeRootFCB(
|
|
|
|
PDEVICE_EXTENSION pVCB)
|
2001-07-05 01:51:53 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PVFATFCB FCB;
|
|
|
|
ULONG FirstCluster, CurrentCluster, Size = 0;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\");
|
|
|
|
|
|
|
|
FCB = vfatNewFCB(pVCB, &NameU);
|
2017-02-17 21:24:12 +00:00
|
|
|
if (vfatVolumeIsFatX(pVCB))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
memset(FCB->entry.FatX.Filename, ' ', 42);
|
|
|
|
FCB->entry.FatX.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
|
|
|
|
FCB->entry.FatX.Attrib = FILE_ATTRIBUTE_DIRECTORY;
|
|
|
|
FCB->entry.FatX.FirstCluster = 1;
|
|
|
|
Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memset(FCB->entry.Fat.ShortName, ' ', 11);
|
|
|
|
FCB->entry.Fat.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
|
|
|
|
FCB->entry.Fat.Attrib = FILE_ATTRIBUTE_DIRECTORY;
|
|
|
|
if (pVCB->FatInfo.FatType == FAT32)
|
|
|
|
{
|
|
|
|
CurrentCluster = FirstCluster = pVCB->FatInfo.RootCluster;
|
|
|
|
FCB->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0xffff);
|
|
|
|
FCB->entry.Fat.FirstClusterHigh = (unsigned short)(FirstCluster >> 16);
|
|
|
|
|
|
|
|
while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Size += pVCB->FatInfo.BytesPerCluster;
|
|
|
|
Status = NextCluster (pVCB, FirstCluster, &CurrentCluster, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FCB->entry.Fat.FirstCluster = 1;
|
|
|
|
Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FCB->ShortHash.Hash = FCB->Hash.Hash;
|
|
|
|
FCB->RefCount = 2;
|
|
|
|
FCB->dirIndex = 0;
|
|
|
|
FCB->RFCB.FileSize.QuadPart = Size;
|
|
|
|
FCB->RFCB.ValidDataLength.QuadPart = Size;
|
|
|
|
FCB->RFCB.AllocationSize.QuadPart = Size;
|
|
|
|
FCB->RFCB.IsFastIoPossible = FastIoIsNotPossible;
|
|
|
|
|
|
|
|
vfatFCBInitializeCacheFromVolume(pVCB, FCB);
|
|
|
|
vfatAddFCBToTable(pVCB, FCB);
|
|
|
|
|
|
|
|
return FCB;
|
2001-05-10 04:02:21 +00:00
|
|
|
}
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
PVFATFCB
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatOpenRootFCB(
|
|
|
|
PDEVICE_EXTENSION pVCB)
|
2001-05-10 04:02:21 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PVFATFCB FCB;
|
|
|
|
UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\");
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
FCB = vfatGrabFCBFromTable(pVCB, &NameU);
|
|
|
|
if (FCB == NULL)
|
|
|
|
{
|
|
|
|
FCB = vfatMakeRootFCB(pVCB);
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
return FCB;
|
2001-05-10 04:02:21 +00:00
|
|
|
}
|
|
|
|
|
2001-07-05 01:51:53 +00:00
|
|
|
NTSTATUS
|
2005-11-04 00:03:34 +00:00
|
|
|
vfatMakeFCBFromDirEntry(
|
2013-12-09 18:48:13 +00:00
|
|
|
PVCB vcb,
|
|
|
|
PVFATFCB directoryFCB,
|
|
|
|
PVFAT_DIRENTRY_CONTEXT DirContext,
|
|
|
|
PVFATFCB *fileFCB)
|
2001-05-10 04:02:21 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PVFATFCB rcFCB;
|
|
|
|
UNICODE_STRING NameU;
|
[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 Status;
|
2013-12-09 18:48:13 +00:00
|
|
|
|
[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
|
|
|
Status = vfatMakeFullName(directoryFCB, &DirContext->LongNameU, &DirContext->ShortNameU, &NameU);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
[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
|
|
|
return Status;
|
2013-12-09 18:48:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rcFCB = vfatNewFCB(vcb, &NameU);
|
2016-08-05 10:48:01 +00:00
|
|
|
vfatInitFCBFromDirEntry(vcb, rcFCB, DirContext);
|
2013-12-09 18:48:13 +00:00
|
|
|
|
2014-11-05 19:06:19 +00:00
|
|
|
rcFCB->RefCount = 1;
|
2013-12-09 18:48:13 +00:00
|
|
|
if (vfatFCBIsDirectory(rcFCB))
|
|
|
|
{
|
2017-02-04 17:54:38 +00:00
|
|
|
Status = vfatFCBInitializeCacheFromVolume(vcb, rcFCB);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(vcb, rcFCB);
|
2017-02-04 19:37:40 +00:00
|
|
|
ExFreePoolWithTag(NameU.Buffer, TAG_FCB);
|
2017-02-04 17:54:38 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2013-12-09 18:48:13 +00:00
|
|
|
}
|
|
|
|
rcFCB->parentFcb = directoryFCB;
|
2016-08-06 08:30:30 +00:00
|
|
|
InsertTailList(&directoryFCB->ParentListHead, &rcFCB->ParentListEntry);
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatAddFCBToTable(vcb, rcFCB);
|
|
|
|
*fileFCB = rcFCB;
|
|
|
|
|
2017-02-04 19:37:40 +00:00
|
|
|
ExFreePoolWithTag(NameU.Buffer, TAG_FCB);
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_SUCCESS;
|
2001-05-10 04:02:21 +00:00
|
|
|
}
|
|
|
|
|
2001-07-05 01:51:53 +00:00
|
|
|
NTSTATUS
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatAttachFCBToFileObject(
|
|
|
|
PDEVICE_EXTENSION vcb,
|
|
|
|
PVFATFCB fcb,
|
|
|
|
PFILE_OBJECT fileObject)
|
2001-05-10 04:02:21 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PVFATCCB newCCB;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
UNREFERENCED_PARAMETER(vcb);
|
2013-05-11 11:03:12 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
|
|
|
|
if (newCCB == NULL)
|
|
|
|
{
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
RtlZeroMemory(newCCB, sizeof (VFATCCB));
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
|
|
|
|
fileObject->FsContext = fcb;
|
|
|
|
fileObject->FsContext2 = newCCB;
|
|
|
|
DPRINT("file open: fcb:%p PathName:%wZ\n", fcb, &fcb->PathNameU);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_SUCCESS;
|
2001-07-05 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatDirFindFile(
|
|
|
|
PDEVICE_EXTENSION pDeviceExt,
|
|
|
|
PVFATFCB pDirectoryFCB,
|
|
|
|
PUNICODE_STRING FileToFindU,
|
|
|
|
PVFATFCB *pFoundFCB)
|
2001-07-05 01:51:53 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
NTSTATUS status;
|
|
|
|
PVOID Context = NULL;
|
|
|
|
PVOID Page = NULL;
|
|
|
|
BOOLEAN First = TRUE;
|
|
|
|
VFAT_DIRENTRY_CONTEXT DirContext;
|
|
|
|
/* This buffer must have a size of 260 characters, because
|
|
|
|
vfatMakeFCBFromDirEntry can copy 20 name entries with 13 characters. */
|
|
|
|
WCHAR LongNameBuffer[260];
|
|
|
|
WCHAR ShortNameBuffer[13];
|
|
|
|
BOOLEAN FoundLong = FALSE;
|
|
|
|
BOOLEAN FoundShort = FALSE;
|
2017-02-18 21:37:56 +00:00
|
|
|
BOOLEAN IsFatX = vfatVolumeIsFatX(pDeviceExt);
|
2013-12-09 18:48:13 +00:00
|
|
|
|
|
|
|
ASSERT(pDeviceExt);
|
|
|
|
ASSERT(pDirectoryFCB);
|
|
|
|
ASSERT(FileToFindU);
|
|
|
|
|
|
|
|
DPRINT("vfatDirFindFile(VCB:%p, dirFCB:%p, File:%wZ)\n",
|
|
|
|
pDeviceExt, pDirectoryFCB, FileToFindU);
|
|
|
|
DPRINT("Dir Path:%wZ\n", &pDirectoryFCB->PathNameU);
|
|
|
|
|
|
|
|
DirContext.DirIndex = 0;
|
|
|
|
DirContext.LongNameU.Buffer = LongNameBuffer;
|
|
|
|
DirContext.LongNameU.Length = 0;
|
|
|
|
DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
|
|
|
|
DirContext.ShortNameU.Buffer = ShortNameBuffer;
|
|
|
|
DirContext.ShortNameU.Length = 0;
|
|
|
|
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
|
|
|
|
|
|
|
|
while (TRUE)
|
|
|
|
{
|
2017-02-17 22:25:03 +00:00
|
|
|
status = VfatGetNextDirEntry(pDeviceExt,
|
|
|
|
&Context,
|
2013-12-09 18:48:13 +00:00
|
|
|
&Page,
|
|
|
|
pDirectoryFCB,
|
|
|
|
&DirContext,
|
|
|
|
First);
|
|
|
|
First = FALSE;
|
|
|
|
if (status == STATUS_NO_MORE_ENTRIES)
|
|
|
|
{
|
|
|
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
}
|
|
|
|
if (!NT_SUCCESS(status))
|
|
|
|
{
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT(" Index:%u longName:%wZ\n",
|
|
|
|
DirContext.DirIndex, &DirContext.LongNameU);
|
|
|
|
|
2017-02-18 21:37:56 +00:00
|
|
|
if (!ENTRY_VOLUME(IsFatX, &DirContext.DirEntry))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
2015-11-30 11:25:14 +00:00
|
|
|
if (DirContext.LongNameU.Length == 0 ||
|
|
|
|
DirContext.ShortNameU.Length == 0)
|
|
|
|
{
|
|
|
|
DPRINT1("WARNING: File system corruption detected. You may need to run a disk repair utility.\n");
|
|
|
|
if (VfatGlobalData->Flags & VFAT_BREAK_ON_CORRUPTION)
|
|
|
|
{
|
|
|
|
ASSERT(DirContext.LongNameU.Length != 0 &&
|
|
|
|
DirContext.ShortNameU.Length != 0);
|
|
|
|
}
|
|
|
|
DirContext.DirIndex++;
|
|
|
|
continue;
|
|
|
|
}
|
2013-12-09 18:48:13 +00:00
|
|
|
FoundLong = RtlEqualUnicodeString(FileToFindU, &DirContext.LongNameU, TRUE);
|
|
|
|
if (FoundLong == FALSE)
|
|
|
|
{
|
|
|
|
FoundShort = RtlEqualUnicodeString(FileToFindU, &DirContext.ShortNameU, TRUE);
|
|
|
|
}
|
|
|
|
if (FoundLong || FoundShort)
|
|
|
|
{
|
|
|
|
status = vfatMakeFCBFromDirEntry(pDeviceExt,
|
|
|
|
pDirectoryFCB,
|
|
|
|
&DirContext,
|
|
|
|
pFoundFCB);
|
|
|
|
CcUnpinData(Context);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DirContext.DirIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
2001-05-10 04:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatGetFCBForFile(
|
|
|
|
PDEVICE_EXTENSION pVCB,
|
|
|
|
PVFATFCB *pParentFCB,
|
|
|
|
PVFATFCB *pFCB,
|
|
|
|
PUNICODE_STRING pFileNameU)
|
2001-05-10 04:02:21 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
NTSTATUS status;
|
|
|
|
PVFATFCB FCB = NULL;
|
|
|
|
PVFATFCB parentFCB;
|
|
|
|
UNICODE_STRING NameU;
|
|
|
|
UNICODE_STRING RootNameU = RTL_CONSTANT_STRING(L"\\");
|
|
|
|
UNICODE_STRING FileNameU;
|
|
|
|
WCHAR NameBuffer[260];
|
|
|
|
PWCHAR curr, prev, last;
|
|
|
|
ULONG Length;
|
|
|
|
|
|
|
|
DPRINT("vfatGetFCBForFile (%p,%p,%p,%wZ)\n",
|
|
|
|
pVCB, pParentFCB, pFCB, pFileNameU);
|
|
|
|
|
2015-12-08 12:57:45 +00:00
|
|
|
RtlInitEmptyUnicodeString(&FileNameU, NameBuffer, sizeof(NameBuffer));
|
2013-12-09 18:48:13 +00:00
|
|
|
|
|
|
|
parentFCB = *pParentFCB;
|
|
|
|
|
|
|
|
if (parentFCB == NULL)
|
|
|
|
{
|
2015-12-08 12:57:45 +00:00
|
|
|
/* Passed-in name is the full name */
|
|
|
|
RtlCopyUnicodeString(&FileNameU, pFileNameU);
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
// Trivial case, open of the root directory on volume
|
|
|
|
if (RtlEqualUnicodeString(&FileNameU, &RootNameU, FALSE))
|
|
|
|
{
|
|
|
|
DPRINT("returning root FCB\n");
|
|
|
|
|
|
|
|
FCB = vfatOpenRootFCB(pVCB);
|
|
|
|
*pFCB = FCB;
|
|
|
|
*pParentFCB = NULL;
|
|
|
|
|
|
|
|
return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for an existing FCB */
|
|
|
|
FCB = vfatGrabFCBFromTable(pVCB, &FileNameU);
|
|
|
|
if (FCB)
|
|
|
|
{
|
|
|
|
*pFCB = FCB;
|
|
|
|
*pParentFCB = FCB->parentFcb;
|
2014-10-26 20:20:42 +00:00
|
|
|
vfatGrabFCB(pVCB, *pParentFCB);
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
last = curr = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
|
|
|
|
while (*curr != L'\\' && curr > FileNameU.Buffer)
|
|
|
|
{
|
|
|
|
curr--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (curr > FileNameU.Buffer)
|
|
|
|
{
|
|
|
|
NameU.Buffer = FileNameU.Buffer;
|
|
|
|
NameU.MaximumLength = NameU.Length = (curr - FileNameU.Buffer) * sizeof(WCHAR);
|
|
|
|
FCB = vfatGrabFCBFromTable(pVCB, &NameU);
|
|
|
|
if (FCB)
|
|
|
|
{
|
|
|
|
Length = (curr - FileNameU.Buffer) * sizeof(WCHAR);
|
|
|
|
if (Length != FCB->PathNameU.Length)
|
|
|
|
{
|
|
|
|
if (FileNameU.Length + FCB->PathNameU.Length - Length > FileNameU.MaximumLength)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(pVCB, FCB);
|
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
|
|
|
RtlMoveMemory(FileNameU.Buffer + FCB->PathNameU.Length / sizeof(WCHAR),
|
|
|
|
curr, FileNameU.Length - Length);
|
|
|
|
FileNameU.Length += (USHORT)(FCB->PathNameU.Length - Length);
|
|
|
|
curr = FileNameU.Buffer + FCB->PathNameU.Length / sizeof(WCHAR);
|
|
|
|
last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
|
|
|
|
}
|
|
|
|
RtlCopyMemory(FileNameU.Buffer, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FCB = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FCB == NULL)
|
|
|
|
{
|
|
|
|
FCB = vfatOpenRootFCB(pVCB);
|
|
|
|
curr = FileNameU.Buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
parentFCB = NULL;
|
|
|
|
prev = curr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-12-08 12:57:45 +00:00
|
|
|
/* Make absolute path */
|
|
|
|
RtlCopyUnicodeString(&FileNameU, &parentFCB->PathNameU);
|
|
|
|
curr = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
|
|
|
|
if (*curr != L'\\')
|
|
|
|
{
|
|
|
|
RtlAppendUnicodeToString(&FileNameU, L"\\");
|
|
|
|
curr++;
|
|
|
|
}
|
|
|
|
ASSERT(*curr == L'\\');
|
|
|
|
RtlAppendUnicodeStringToString(&FileNameU, pFileNameU);
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
FCB = parentFCB;
|
|
|
|
parentFCB = NULL;
|
2015-12-08 12:57:45 +00:00
|
|
|
prev = curr;
|
2013-12-09 18:48:13 +00:00
|
|
|
last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (curr <= last)
|
|
|
|
{
|
|
|
|
if (parentFCB)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(pVCB, parentFCB);
|
2014-11-06 00:07:01 +00:00
|
|
|
parentFCB = NULL;
|
2013-12-09 18:48:13 +00:00
|
|
|
}
|
|
|
|
// fail if element in FCB is not a directory
|
|
|
|
if (!vfatFCBIsDirectory(FCB))
|
|
|
|
{
|
|
|
|
DPRINT ("Element in requested path is not a directory\n");
|
|
|
|
|
|
|
|
vfatReleaseFCB(pVCB, FCB);
|
|
|
|
FCB = NULL;
|
|
|
|
*pParentFCB = NULL;
|
|
|
|
*pFCB = NULL;
|
|
|
|
|
|
|
|
return STATUS_OBJECT_PATH_NOT_FOUND;
|
|
|
|
}
|
|
|
|
parentFCB = FCB;
|
|
|
|
if (prev < curr)
|
|
|
|
{
|
|
|
|
Length = (curr - prev) * sizeof(WCHAR);
|
|
|
|
if (Length != parentFCB->LongNameU.Length)
|
|
|
|
{
|
|
|
|
if (FileNameU.Length + parentFCB->LongNameU.Length - Length > FileNameU.MaximumLength)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(pVCB, parentFCB);
|
2014-11-06 00:07:01 +00:00
|
|
|
*pParentFCB = NULL;
|
|
|
|
*pFCB = NULL;
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
|
|
|
RtlMoveMemory(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr,
|
|
|
|
FileNameU.Length - (curr - FileNameU.Buffer) * sizeof(WCHAR));
|
|
|
|
FileNameU.Length += (USHORT)(parentFCB->LongNameU.Length - Length);
|
|
|
|
curr = prev + parentFCB->LongNameU.Length / sizeof(WCHAR);
|
|
|
|
last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
|
|
|
|
}
|
|
|
|
RtlCopyMemory(prev, parentFCB->LongNameU.Buffer, parentFCB->LongNameU.Length);
|
|
|
|
}
|
|
|
|
curr++;
|
|
|
|
prev = curr;
|
|
|
|
while (*curr != L'\\' && curr <= last)
|
|
|
|
{
|
|
|
|
curr++;
|
|
|
|
}
|
|
|
|
NameU.Buffer = FileNameU.Buffer;
|
|
|
|
NameU.Length = (curr - NameU.Buffer) * sizeof(WCHAR);
|
|
|
|
NameU.MaximumLength = FileNameU.MaximumLength;
|
|
|
|
DPRINT("%wZ\n", &NameU);
|
|
|
|
FCB = vfatGrabFCBFromTable(pVCB, &NameU);
|
|
|
|
if (FCB == NULL)
|
|
|
|
{
|
|
|
|
NameU.Buffer = prev;
|
|
|
|
NameU.MaximumLength = NameU.Length = (curr - prev) * sizeof(WCHAR);
|
|
|
|
status = vfatDirFindFile(pVCB, parentFCB, &NameU, &FCB);
|
|
|
|
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
|
|
|
|
{
|
|
|
|
*pFCB = NULL;
|
|
|
|
if (curr > last)
|
|
|
|
{
|
|
|
|
*pParentFCB = parentFCB;
|
|
|
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(pVCB, parentFCB);
|
|
|
|
*pParentFCB = NULL;
|
|
|
|
return STATUS_OBJECT_PATH_NOT_FOUND;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!NT_SUCCESS(status))
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(pVCB, parentFCB);
|
|
|
|
*pParentFCB = NULL;
|
|
|
|
*pFCB = NULL;
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*pParentFCB = parentFCB;
|
|
|
|
*pFCB = FCB;
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
2001-05-10 04:02:21 +00:00
|
|
|
}
|