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
|
|
|
|
2018-04-28 07:34:10 +00:00
|
|
|
#ifdef KDBG
|
|
|
|
extern UNICODE_STRING DebugFile;
|
|
|
|
#endif
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-04-27 16:56:31 +00:00
|
|
|
Fcb->RFCB.NodeTypeCode = NODE_TYPE_FCB;
|
|
|
|
Fcb->RFCB.NodeByteSize = sizeof(VFATFCB);
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
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
|
|
|
{
|
2018-04-28 07:34:10 +00:00
|
|
|
#ifdef KDBG
|
|
|
|
if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL))
|
|
|
|
{
|
|
|
|
DPRINT1("Destroying: %p (%wZ) %d\n", pFCB, &pFCB->PathNameU, pFCB->RefCount);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
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
|
2018-04-28 07:34:10 +00:00
|
|
|
#ifndef KDBG
|
2014-10-26 20:20:42 +00:00
|
|
|
vfatGrabFCB(
|
2018-04-28 07:34:10 +00:00
|
|
|
#else
|
|
|
|
_vfatGrabFCB(
|
|
|
|
#endif
|
2014-10-26 20:20:42 +00:00
|
|
|
PDEVICE_EXTENSION pVCB,
|
2018-04-28 07:34:10 +00:00
|
|
|
PVFATFCB pFCB
|
|
|
|
#ifdef KDBG
|
|
|
|
,
|
|
|
|
PCSTR File,
|
|
|
|
ULONG Line,
|
|
|
|
PCSTR Func
|
|
|
|
#endif
|
|
|
|
)
|
2014-10-26 20:20:42 +00:00
|
|
|
{
|
2018-04-28 07:34:10 +00:00
|
|
|
#ifdef KDBG
|
|
|
|
if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL))
|
|
|
|
{
|
|
|
|
DPRINT1("Inc ref count (%d, oc: %d) for: %p (%wZ) at: %s(%d) %s\n", pFCB->RefCount, pFCB->OpenHandleCount, pFCB, &pFCB->PathNameU, File, Line, Func);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
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
|
2018-04-28 07:34:10 +00:00
|
|
|
#ifndef KDBG
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatReleaseFCB(
|
2018-04-28 07:34:10 +00:00
|
|
|
#else
|
|
|
|
_vfatReleaseFCB(
|
|
|
|
#endif
|
2013-12-09 18:48:13 +00:00
|
|
|
PDEVICE_EXTENSION pVCB,
|
2018-04-28 07:34:10 +00:00
|
|
|
PVFATFCB pFCB
|
|
|
|
#ifdef KDBG
|
|
|
|
,
|
|
|
|
PCSTR File,
|
|
|
|
ULONG Line,
|
|
|
|
PCSTR Func
|
|
|
|
#endif
|
|
|
|
)
|
2001-05-02 03:18:03 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PVFATFCB tmpFcb;
|
|
|
|
|
2018-04-28 07:34:10 +00:00
|
|
|
#ifdef KDBG
|
|
|
|
if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL))
|
|
|
|
{
|
|
|
|
DPRINT1("Dec ref count (%d, oc: %d) for: %p (%wZ) at: %s(%d) %s\n", pFCB->RefCount, pFCB->OpenHandleCount, pFCB, &pFCB->PathNameU, File, Line, Func);
|
|
|
|
}
|
|
|
|
#else
|
2013-12-09 18:48:13 +00:00
|
|
|
DPRINT("releasing FCB at %p: %wZ, refCount:%d\n",
|
|
|
|
pFCB, &pFCB->PathNameU, pFCB->RefCount);
|
2018-04-28 07:34:10 +00:00
|
|
|
#endif
|
2013-12-09 18:48:13 +00:00
|
|
|
|
2014-10-26 20:29:00 +00:00
|
|
|
ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
while (pFCB)
|
|
|
|
{
|
[FASTFAT] Don't leak directories FILE_OBJECT, FCB and cache entries.
Once a directory is crossed (opened or a child is opened), associated
FCB structure is created in FastFAT, but also a stream FO for caching.
Up to now, due to an extra reference taken by the stream file object,
even when the directory was no longer used, the directory was kept in
memory: the FCB was never deleted, the file object was never dereferenced,
and the cache never released.
The immediate effect of this bug is that our FAT driver was leaking every
directory that was used affecting the whole OS situation. In case of
directories intensive operation (like extraction the ReactOS source code
in ReactOS ;-)), we were just killin the whole OS RAM without any way to
release it and recover.
The other side effects: IOs were faster as half of the FS was always
permanant in RAM.
This commit fixes the issue by forcing the FSD to release the FO,
and the cache when a directory is no longer used, leading to its
destruction in RAM.
Downside: on IO intensive operation, expect slowdowns, obviously,
there's less caching now. But more efficient!
CORE-14557
2018-04-26 16:25:19 +00:00
|
|
|
ULONG RefCount;
|
|
|
|
|
2014-11-01 18:00:15 +00:00
|
|
|
ASSERT(pFCB != pVCB->VolumeFcb);
|
2014-11-05 19:06:19 +00:00
|
|
|
ASSERT(pFCB->RefCount > 0);
|
[FASTFAT] Don't leak directories FILE_OBJECT, FCB and cache entries.
Once a directory is crossed (opened or a child is opened), associated
FCB structure is created in FastFAT, but also a stream FO for caching.
Up to now, due to an extra reference taken by the stream file object,
even when the directory was no longer used, the directory was kept in
memory: the FCB was never deleted, the file object was never dereferenced,
and the cache never released.
The immediate effect of this bug is that our FAT driver was leaking every
directory that was used affecting the whole OS situation. In case of
directories intensive operation (like extraction the ReactOS source code
in ReactOS ;-)), we were just killin the whole OS RAM without any way to
release it and recover.
The other side effects: IOs were faster as half of the FS was always
permanant in RAM.
This commit fixes the issue by forcing the FSD to release the FO,
and the cache when a directory is no longer used, leading to its
destruction in RAM.
Downside: on IO intensive operation, expect slowdowns, obviously,
there's less caching now. But more efficient!
CORE-14557
2018-04-26 16:25:19 +00:00
|
|
|
RefCount = --pFCB->RefCount;
|
|
|
|
|
|
|
|
if (RefCount == 1 && BooleanFlagOn(pFCB->Flags, FCB_CACHE_INITIALIZED))
|
|
|
|
{
|
|
|
|
PFILE_OBJECT tmpFileObject;
|
|
|
|
tmpFileObject = pFCB->FileObject;
|
|
|
|
|
|
|
|
pFCB->FileObject = NULL;
|
|
|
|
CcUninitializeCacheMap(tmpFileObject, NULL, NULL);
|
|
|
|
ClearFlag(pFCB->Flags, FCB_CACHE_INITIALIZED);
|
|
|
|
ObDereferenceObject(tmpFileObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (RefCount == 0)
|
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
|
|
|
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
|
|
|
|
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
|
|
|
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
|
|
|
|
2018-04-28 07:34:10 +00:00
|
|
|
#ifdef KDBG
|
|
|
|
if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &fcb->LongNameU, FALSE, NULL))
|
|
|
|
{
|
|
|
|
DPRINT1("Attaching %p to %p (%d)\n", fcb, fileObject, fcb->RefCount);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
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;
|
2018-05-18 08:29:45 +00:00
|
|
|
fileObject->Vpb = vcb->IoVPB;
|
2013-12-09 18:48:13 +00:00
|
|
|
DPRINT("file open: fcb:%p PathName:%wZ\n", fcb, &fcb->PathNameU);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2018-04-28 07:34:10 +00:00
|
|
|
#ifdef KDBG
|
|
|
|
fcb->Flags &= ~FCB_CLEANED_UP;
|
|
|
|
fcb->Flags &= ~FCB_CLOSED;
|
|
|
|
#endif
|
|
|
|
|
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);
|
2018-05-18 12:03:20 +00:00
|
|
|
DirContext.DeviceExt = pDeviceExt;
|
2013-12-09 18:48:13 +00:00
|
|
|
|
|
|
|
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
|
|
|
}
|