2002-08-14 20:58:39 +00:00
|
|
|
/*
|
|
|
|
* ReactOS kernel
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
2009-10-27 10:34:16 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2002-08-14 20:58:39 +00:00
|
|
|
*/
|
2005-08-24 18:29:45 +00:00
|
|
|
/*
|
1999-12-11 21:14:49 +00:00
|
|
|
* PROJECT: ReactOS kernel
|
[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/create.c
|
1999-12-11 21:14:49 +00:00
|
|
|
* PURPOSE: VFAT Filesystem
|
|
|
|
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
[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)
|
1999-12-11 21:14:49 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include "vfat.h"
|
|
|
|
|
2013-12-19 16:20:28 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2001-03-13 16:25:55 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
1999-12-11 21:14:49 +00:00
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
VOID
|
|
|
|
vfat8Dot3ToString(
|
|
|
|
PFAT_DIR_ENTRY pEntry,
|
|
|
|
PUNICODE_STRING NameU)
|
2001-05-02 03:18:03 +00:00
|
|
|
{
|
2013-12-09 10:35:15 +00:00
|
|
|
OEM_STRING StringA;
|
|
|
|
USHORT Length;
|
|
|
|
CHAR cString[12];
|
2005-11-04 00:10:39 +00:00
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
RtlCopyMemory(cString, pEntry->ShortName, 11);
|
|
|
|
cString[11] = 0;
|
|
|
|
if (cString[0] == 0x05)
|
|
|
|
{
|
|
|
|
cString[0] = 0xe5;
|
|
|
|
}
|
2005-11-04 00:10:39 +00:00
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
StringA.Buffer = cString;
|
|
|
|
for (StringA.Length = 0;
|
|
|
|
StringA.Length < 8 && StringA.Buffer[StringA.Length] != ' ';
|
|
|
|
StringA.Length++);
|
|
|
|
StringA.MaximumLength = StringA.Length;
|
2005-11-04 00:10:39 +00:00
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
|
2005-11-04 00:10:39 +00:00
|
|
|
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(pEntry->lCase, VFAT_CASE_LOWER_BASE))
|
2013-12-09 10:35:15 +00:00
|
|
|
{
|
|
|
|
RtlDowncaseUnicodeString(NameU, NameU, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cString[8] != ' ')
|
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
Length = NameU->Length;
|
|
|
|
NameU->Buffer += Length / sizeof(WCHAR);
|
|
|
|
if (!FAT_ENTRY_VOLUME(pEntry))
|
|
|
|
{
|
|
|
|
Length += sizeof(WCHAR);
|
|
|
|
NameU->Buffer[0] = L'.';
|
|
|
|
NameU->Buffer++;
|
|
|
|
}
|
|
|
|
NameU->Length = 0;
|
|
|
|
NameU->MaximumLength -= Length;
|
|
|
|
|
|
|
|
StringA.Buffer = &cString[8];
|
|
|
|
for (StringA.Length = 0;
|
|
|
|
StringA.Length < 3 && StringA.Buffer[StringA.Length] != ' ';
|
|
|
|
StringA.Length++);
|
|
|
|
StringA.MaximumLength = StringA.Length;
|
|
|
|
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(pEntry->lCase, VFAT_CASE_LOWER_EXT))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
RtlDowncaseUnicodeString(NameU, NameU, FALSE);
|
|
|
|
}
|
|
|
|
NameU->Buffer -= Length / sizeof(WCHAR);
|
|
|
|
NameU->Length += Length;
|
|
|
|
NameU->MaximumLength += Length;
|
|
|
|
}
|
2013-12-09 10:35:15 +00:00
|
|
|
|
|
|
|
NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
|
|
|
|
DPRINT("'%wZ'\n", NameU);
|
2001-05-02 03:18:03 +00:00
|
|
|
}
|
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Find a file
|
|
|
|
*/
|
2013-12-09 18:48:13 +00:00
|
|
|
NTSTATUS
|
|
|
|
FindFile(
|
|
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PVFATFCB Parent,
|
|
|
|
PUNICODE_STRING FileToFindU,
|
|
|
|
PVFAT_DIRENTRY_CONTEXT DirContext,
|
|
|
|
BOOLEAN First)
|
1999-12-11 21:14:49 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PWCHAR PathNameBuffer;
|
|
|
|
USHORT PathNameBufferLength;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PVOID Context = NULL;
|
|
|
|
PVOID Page;
|
|
|
|
PVFATFCB rcFcb;
|
|
|
|
BOOLEAN Found;
|
|
|
|
UNICODE_STRING PathNameU;
|
|
|
|
UNICODE_STRING FileToFindUpcase;
|
|
|
|
BOOLEAN WildCard;
|
2017-02-18 21:37:56 +00:00
|
|
|
BOOLEAN IsFatX = vfatVolumeIsFatX(DeviceExt);
|
2013-12-09 18:48:13 +00:00
|
|
|
|
|
|
|
DPRINT("FindFile(Parent %p, FileToFind '%wZ', DirIndex: %u)\n",
|
|
|
|
Parent, FileToFindU, DirContext->DirIndex);
|
|
|
|
DPRINT("FindFile: Path %wZ\n",&Parent->PathNameU);
|
|
|
|
|
|
|
|
PathNameBufferLength = LONGNAME_MAX_LENGTH * sizeof(WCHAR);
|
|
|
|
PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameBufferLength + sizeof(WCHAR), TAG_VFAT);
|
|
|
|
if (!PathNameBuffer)
|
|
|
|
{
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
PathNameU.Buffer = PathNameBuffer;
|
|
|
|
PathNameU.Length = 0;
|
|
|
|
PathNameU.MaximumLength = PathNameBufferLength;
|
|
|
|
|
|
|
|
DirContext->LongNameU.Length = 0;
|
|
|
|
DirContext->ShortNameU.Length = 0;
|
|
|
|
|
|
|
|
WildCard = FsRtlDoesNameContainWildCards(FileToFindU);
|
|
|
|
|
|
|
|
if (WildCard == FALSE)
|
|
|
|
{
|
|
|
|
/* if there is no '*?' in the search name, than look first for an existing fcb */
|
|
|
|
RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
|
|
|
|
if (!vfatFCBIsRoot(Parent))
|
|
|
|
{
|
|
|
|
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
|
|
|
|
PathNameU.Length += sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
RtlAppendUnicodeStringToString(&PathNameU, FileToFindU);
|
|
|
|
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
|
|
|
|
rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
|
|
|
|
if (rcFcb)
|
|
|
|
{
|
|
|
|
ULONG startIndex = rcFcb->startIndex;
|
2017-02-18 21:37:56 +00:00
|
|
|
if (IsFatX && !vfatFCBIsRoot(Parent))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
startIndex += 2;
|
|
|
|
}
|
|
|
|
if(startIndex >= DirContext->DirIndex)
|
|
|
|
{
|
|
|
|
RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU);
|
|
|
|
RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU);
|
|
|
|
RtlCopyMemory(&DirContext->DirEntry, &rcFcb->entry, sizeof(DIR_ENTRY));
|
|
|
|
DirContext->StartIndex = rcFcb->startIndex;
|
|
|
|
DirContext->DirIndex = rcFcb->dirIndex;
|
|
|
|
DPRINT("FindFile: new Name %wZ, DirIndex %u (%u)\n",
|
|
|
|
&DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex);
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT("FCB not found for %wZ\n", &PathNameU);
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
vfatReleaseFCB(DeviceExt, rcFcb);
|
|
|
|
ExFreePool(PathNameBuffer);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FsRtlIsNameInExpression need the searched string to be upcase,
|
|
|
|
* even if IgnoreCase is specified */
|
|
|
|
Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFindU, TRUE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ExFreePool(PathNameBuffer);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2013-12-12 13:51:50 +00:00
|
|
|
while (TRUE)
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
2017-02-17 22:25:03 +00:00
|
|
|
Status = VfatGetNextDirEntry(DeviceExt, &Context, &Page, Parent, DirContext, First);
|
2013-12-09 18:48:13 +00:00
|
|
|
First = FALSE;
|
|
|
|
if (Status == STATUS_NO_MORE_ENTRIES)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2017-02-18 21:37:56 +00:00
|
|
|
if (ENTRY_VOLUME(IsFatX, &DirContext->DirEntry))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
DirContext->DirIndex++;
|
|
|
|
continue;
|
|
|
|
}
|
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
|
|
|
if (WildCard)
|
|
|
|
{
|
|
|
|
Found = FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->LongNameU, TRUE, NULL) ||
|
|
|
|
FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->ShortNameU, TRUE, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Found = FsRtlAreNamesEqual(&DirContext->LongNameU, FileToFindU, TRUE, NULL) ||
|
|
|
|
FsRtlAreNamesEqual(&DirContext->ShortNameU, FileToFindU, TRUE, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Found)
|
|
|
|
{
|
|
|
|
if (WildCard)
|
|
|
|
{
|
|
|
|
RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
|
|
|
|
if (!vfatFCBIsRoot(Parent))
|
|
|
|
{
|
|
|
|
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
|
|
|
|
PathNameU.Length += sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
RtlAppendUnicodeStringToString(&PathNameU, &DirContext->LongNameU);
|
|
|
|
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
|
|
|
|
rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
|
|
|
|
if (rcFcb != NULL)
|
|
|
|
{
|
|
|
|
RtlCopyMemory(&DirContext->DirEntry, &rcFcb->entry, sizeof(DIR_ENTRY));
|
|
|
|
vfatReleaseFCB(DeviceExt, rcFcb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DPRINT("%u\n", DirContext->LongNameU.Length);
|
|
|
|
DPRINT("FindFile: new Name %wZ, DirIndex %u\n",
|
|
|
|
&DirContext->LongNameU, DirContext->DirIndex);
|
|
|
|
|
|
|
|
if (Context)
|
|
|
|
{
|
|
|
|
CcUnpinData(Context);
|
|
|
|
}
|
|
|
|
RtlFreeUnicodeString(&FileToFindUpcase);
|
|
|
|
ExFreePool(PathNameBuffer);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
DirContext->DirIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Context)
|
|
|
|
{
|
|
|
|
CcUnpinData(Context);
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlFreeUnicodeString(&FileToFindUpcase);
|
|
|
|
ExFreePool(PathNameBuffer);
|
|
|
|
return Status;
|
2001-05-02 03:18:03 +00:00
|
|
|
}
|
1999-12-11 21:14:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: Opens a file
|
|
|
|
*/
|
2013-12-09 18:48:13 +00:00
|
|
|
static
|
|
|
|
NTSTATUS
|
|
|
|
VfatOpenFile(
|
|
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PUNICODE_STRING PathNameU,
|
|
|
|
PFILE_OBJECT FileObject,
|
2013-12-11 11:42:44 +00:00
|
|
|
ULONG RequestedDisposition,
|
2015-11-19 16:36:39 +00:00
|
|
|
ULONG RequestedOptions,
|
2013-12-09 18:48:13 +00:00
|
|
|
PVFATFCB *ParentFcb)
|
1999-12-11 21:14:49 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PVFATFCB Fcb;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("VfatOpenFile(%p, '%wZ', %p, %p)\n", DeviceExt, PathNameU, FileObject, ParentFcb);
|
|
|
|
|
|
|
|
if (FileObject->RelatedFileObject)
|
|
|
|
{
|
|
|
|
DPRINT("'%wZ'\n", &FileObject->RelatedFileObject->FileName);
|
|
|
|
|
|
|
|
*ParentFcb = FileObject->RelatedFileObject->FsContext;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*ParentFcb = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!DeviceExt->FatInfo.FixedMedia)
|
|
|
|
{
|
|
|
|
Status = VfatBlockDeviceIoControl(DeviceExt->StorageDevice,
|
|
|
|
IOCTL_DISK_CHECK_VERIFY,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2013-12-12 13:51:50 +00:00
|
|
|
DPRINT("Status %lx\n", Status);
|
2013-12-09 18:48:13 +00:00
|
|
|
*ParentFcb = NULL;
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*ParentFcb)
|
|
|
|
{
|
2014-10-26 20:20:42 +00:00
|
|
|
vfatGrabFCB(DeviceExt, *ParentFcb);
|
2013-12-09 18:48:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* try first to find an existing FCB in memory */
|
|
|
|
DPRINT("Checking for existing FCB in memory\n");
|
|
|
|
|
|
|
|
Status = vfatGetFCBForFile(DeviceExt, ParentFcb, &Fcb, PathNameU);
|
2013-12-12 13:51:50 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
DPRINT ("Could not make a new FCB, status: %x\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
2014-04-28 19:40:26 +00:00
|
|
|
|
2015-11-19 16:36:39 +00:00
|
|
|
/* Fail, if we try to overwrite an existing directory */
|
2017-02-17 17:58:18 +00:00
|
|
|
if ((!BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE) && vfatFCBIsDirectory(Fcb)) &&
|
2015-11-19 16:36:39 +00:00
|
|
|
(RequestedDisposition == FILE_OVERWRITE ||
|
|
|
|
RequestedDisposition == FILE_OVERWRITE_IF ||
|
|
|
|
RequestedDisposition == FILE_SUPERSEDE))
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, Fcb);
|
|
|
|
return STATUS_OBJECT_NAME_COLLISION;
|
|
|
|
}
|
|
|
|
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
2013-12-12 13:51:50 +00:00
|
|
|
vfatReleaseFCB(DeviceExt, Fcb);
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_DELETE_PENDING;
|
|
|
|
}
|
2013-12-11 11:42:44 +00:00
|
|
|
|
|
|
|
/* Fail, if we try to overwrite a read-only file */
|
2017-02-17 17:58:18 +00:00
|
|
|
if (vfatFCBIsReadOnly(Fcb) &&
|
2015-11-13 19:03:34 +00:00
|
|
|
(RequestedDisposition == FILE_OVERWRITE ||
|
|
|
|
RequestedDisposition == FILE_OVERWRITE_IF))
|
2013-12-11 11:42:44 +00:00
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, Fcb);
|
|
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
}
|
|
|
|
|
2017-02-17 17:58:18 +00:00
|
|
|
if (vfatFCBIsReadOnly(Fcb) &&
|
2016-08-11 13:25:57 +00:00
|
|
|
(RequestedOptions & FILE_DELETE_ON_CLOSE))
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, Fcb);
|
|
|
|
return STATUS_CANNOT_DELETE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((vfatFCBIsRoot(Fcb) ||
|
|
|
|
(Fcb->LongNameU.Length == sizeof(WCHAR) && Fcb->LongNameU.Buffer[0] == L'.') ||
|
|
|
|
(Fcb->LongNameU.Length == 2 * sizeof(WCHAR) && Fcb->LongNameU.Buffer[0] == L'.' && Fcb->LongNameU.Buffer[1] == L'.')) &&
|
2017-02-17 17:58:18 +00:00
|
|
|
BooleanFlagOn(RequestedOptions, FILE_DELETE_ON_CLOSE))
|
2016-08-11 13:25:57 +00:00
|
|
|
{
|
|
|
|
// we cannot delete a '.', '..' or the root directory
|
|
|
|
vfatReleaseFCB(DeviceExt, Fcb);
|
|
|
|
return STATUS_CANNOT_DELETE;
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
DPRINT("Attaching FCB to fileObject\n");
|
|
|
|
Status = vfatAttachFCBToFileObject(DeviceExt, Fcb, FileObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2013-12-12 13:51:50 +00:00
|
|
|
vfatReleaseFCB(DeviceExt, Fcb);
|
2013-12-09 18:48:13 +00:00
|
|
|
}
|
|
|
|
return Status;
|
2005-11-04 00:07:47 +00:00
|
|
|
}
|
2002-08-14 20:58:39 +00:00
|
|
|
|
2005-11-04 00:07:47 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Create or open a file
|
|
|
|
*/
|
2013-12-09 18:48:13 +00:00
|
|
|
static NTSTATUS
|
|
|
|
VfatCreateFile(
|
|
|
|
PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
2005-11-04 00:07:47 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PIO_STACK_LOCATION Stack;
|
|
|
|
PFILE_OBJECT FileObject;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PDEVICE_EXTENSION DeviceExt;
|
|
|
|
ULONG RequestedDisposition, RequestedOptions;
|
|
|
|
PVFATFCB pFcb = NULL;
|
|
|
|
PVFATFCB ParentFcb = NULL;
|
2017-05-02 19:33:14 +00:00
|
|
|
PVFATCCB pCcb = NULL;
|
2013-12-09 18:48:13 +00:00
|
|
|
PWCHAR c, last;
|
2014-10-27 13:39:03 +00:00
|
|
|
BOOLEAN PagingFileCreate;
|
2013-12-09 18:48:13 +00:00
|
|
|
BOOLEAN Dots;
|
2014-10-27 13:39:03 +00:00
|
|
|
BOOLEAN OpenTargetDir;
|
2017-02-26 13:32:55 +00:00
|
|
|
BOOLEAN TrailingBackslash;
|
2013-12-09 18:48:13 +00:00
|
|
|
UNICODE_STRING FileNameU;
|
|
|
|
UNICODE_STRING PathNameU;
|
|
|
|
ULONG Attributes;
|
|
|
|
|
|
|
|
/* Unpack the various parameters. */
|
2013-12-12 13:51:50 +00:00
|
|
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
2013-12-09 18:48:13 +00:00
|
|
|
RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
|
|
|
|
RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
|
2017-02-17 17:58:18 +00:00
|
|
|
PagingFileCreate = BooleanFlagOn(Stack->Flags, SL_OPEN_PAGING_FILE);
|
|
|
|
OpenTargetDir = BooleanFlagOn(Stack->Flags, SL_OPEN_TARGET_DIRECTORY);
|
[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
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
FileObject = Stack->FileObject;
|
|
|
|
DeviceExt = DeviceObject->DeviceExtension;
|
|
|
|
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_OPEN_BY_FILE_ID))
|
2016-08-08 07:28:14 +00:00
|
|
|
{
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
/* Check their validity. */
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE) &&
|
2013-12-09 18:48:13 +00:00
|
|
|
RequestedDisposition == FILE_SUPERSEDE)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2005-11-04 00:10:39 +00:00
|
|
|
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE) &&
|
|
|
|
BooleanFlagOn(RequestedOptions, FILE_NON_DIRECTORY_FILE))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2014-10-30 20:56:40 +00:00
|
|
|
/* Deny create if the volume is locked */
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED))
|
2014-10-30 20:56:40 +00:00
|
|
|
{
|
|
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
/* This a open operation for the volume itself */
|
|
|
|
if (FileObject->FileName.Length == 0 &&
|
2015-11-29 18:43:50 +00:00
|
|
|
(FileObject->RelatedFileObject == NULL ||
|
|
|
|
FileObject->RelatedFileObject->FsContext2 != NULL ||
|
|
|
|
FileObject->RelatedFileObject->FsContext == DeviceExt->VolumeFcb))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
2014-11-02 11:30:14 +00:00
|
|
|
DPRINT("Volume opening\n");
|
2014-10-30 20:56:40 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
if (RequestedDisposition != FILE_OPEN &&
|
|
|
|
RequestedDisposition != FILE_OPEN_IF)
|
2005-11-24 21:08:13 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_ACCESS_DENIED;
|
2005-11-24 21:08:13 +00:00
|
|
|
}
|
2017-02-26 18:46:30 +00:00
|
|
|
|
|
|
|
if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE) &&
|
|
|
|
(FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 == NULL || FileObject->RelatedFileObject->FsContext == DeviceExt->VolumeFcb))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
return STATUS_NOT_A_DIRECTORY;
|
|
|
|
}
|
2011-03-02 21:51:33 +00:00
|
|
|
|
2014-04-28 19:40:26 +00:00
|
|
|
if (OpenTargetDir)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(RequestedOptions, FILE_DELETE_ON_CLOSE))
|
2016-08-11 13:25:57 +00:00
|
|
|
{
|
|
|
|
return STATUS_CANNOT_DELETE;
|
|
|
|
}
|
|
|
|
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.CreateHits, 1);
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
pFcb = DeviceExt->VolumeFcb;
|
2014-11-27 20:28:50 +00:00
|
|
|
|
|
|
|
if (pFcb->OpenHandleCount == 0)
|
|
|
|
{
|
|
|
|
IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
|
|
|
|
Stack->Parameters.Create.ShareAccess,
|
|
|
|
FileObject,
|
|
|
|
&pFcb->FCBShareAccess);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
|
|
|
|
Stack->Parameters.Create.ShareAccess,
|
|
|
|
FileObject,
|
|
|
|
&pFcb->FCBShareAccess,
|
|
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2014-11-27 20:28:50 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
|
2014-10-30 20:56:40 +00:00
|
|
|
DeviceExt->OpenHandleCount++;
|
2014-11-29 20:09:44 +00:00
|
|
|
pFcb->OpenHandleCount++;
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.SuccessfulCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
|
|
|
|
Irp->IoStatus.Information = FILE_OPENED;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2015-11-29 18:43:50 +00:00
|
|
|
if (FileObject->RelatedFileObject != NULL &&
|
|
|
|
FileObject->RelatedFileObject->FsContext == DeviceExt->VolumeFcb)
|
|
|
|
{
|
|
|
|
ASSERT(FileObject->FileName.Length != 0);
|
|
|
|
return STATUS_OBJECT_PATH_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
2016-11-13 15:31:39 +00:00
|
|
|
/* Check for illegal characters and illegal dot sequences in the file name */
|
2013-12-09 18:48:13 +00:00
|
|
|
PathNameU = FileObject->FileName;
|
|
|
|
c = PathNameU.Buffer + PathNameU.Length / sizeof(WCHAR);
|
|
|
|
last = c - 1;
|
2017-02-26 13:32:55 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
Dots = TRUE;
|
|
|
|
while (c-- > PathNameU.Buffer)
|
|
|
|
{
|
|
|
|
if (*c == L'\\' || c == PathNameU.Buffer)
|
|
|
|
{
|
|
|
|
if (Dots && last > c)
|
|
|
|
{
|
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
2017-02-26 13:32:55 +00:00
|
|
|
if (*c == L'\\' && (c - 1) > PathNameU.Buffer &&
|
|
|
|
*(c - 1) == L'\\')
|
|
|
|
{
|
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
last = c - 1;
|
|
|
|
Dots = TRUE;
|
|
|
|
}
|
|
|
|
else if (*c != L'.')
|
|
|
|
{
|
|
|
|
Dots = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*c != '\\' && vfatIsLongIllegal(*c))
|
|
|
|
{
|
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-28 19:40:26 +00:00
|
|
|
/* Check if we try to open target directory of root dir */
|
|
|
|
if (OpenTargetDir && FileObject->RelatedFileObject == NULL && PathNameU.Length == sizeof(WCHAR) &&
|
|
|
|
PathNameU.Buffer[0] == L'\\')
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
if (FileObject->RelatedFileObject && PathNameU.Length >= sizeof(WCHAR) && PathNameU.Buffer[0] == L'\\')
|
|
|
|
{
|
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
|
|
|
|
2017-02-26 13:57:17 +00:00
|
|
|
TrailingBackslash = FALSE;
|
2013-12-09 18:48:13 +00:00
|
|
|
if (PathNameU.Length > sizeof(WCHAR) && PathNameU.Buffer[PathNameU.Length/sizeof(WCHAR)-1] == L'\\')
|
|
|
|
{
|
|
|
|
PathNameU.Length -= sizeof(WCHAR);
|
2017-02-26 13:57:17 +00:00
|
|
|
TrailingBackslash = TRUE;
|
2013-12-09 18:48:13 +00:00
|
|
|
}
|
|
|
|
|
2015-11-29 20:23:43 +00:00
|
|
|
if (PathNameU.Length > sizeof(WCHAR) && PathNameU.Buffer[PathNameU.Length/sizeof(WCHAR)-1] == L'\\')
|
|
|
|
{
|
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
/* Try opening the file. */
|
[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
|
|
|
if (!OpenTargetDir)
|
2014-04-28 19:40:26 +00:00
|
|
|
{
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.CreateHits, 1);
|
|
|
|
|
2015-11-19 16:36:39 +00:00
|
|
|
Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, RequestedOptions, &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
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PVFATFCB TargetFcb;
|
2017-09-26 13:49:09 +00:00
|
|
|
LONG idx, FileNameLen;
|
2014-04-28 19:40:26 +00:00
|
|
|
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.CreateHits, 1);
|
|
|
|
|
[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
|
|
|
ParentFcb = (FileObject->RelatedFileObject != NULL) ? FileObject->RelatedFileObject->FsContext : NULL;
|
2014-11-05 23:23:52 +00:00
|
|
|
if (ParentFcb)
|
|
|
|
{
|
|
|
|
vfatGrabFCB(DeviceExt, 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
|
|
|
|
2017-09-26 12:36:17 +00:00
|
|
|
Status = vfatGetFCBForFile(DeviceExt, &ParentFcb, &TargetFcb, &PathNameU);
|
2014-11-05 23:23:52 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
2014-04-28 19:40:26 +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
|
|
|
vfatReleaseFCB(DeviceExt, TargetFcb);
|
2014-04-28 19:40:26 +00:00
|
|
|
Irp->IoStatus.Information = FILE_EXISTS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
|
|
|
|
}
|
|
|
|
|
|
|
|
idx = FileObject->FileName.Length / sizeof(WCHAR) - 1;
|
|
|
|
|
2014-11-06 00:07:01 +00:00
|
|
|
/* Skip trailing \ - if any */
|
2014-04-28 19:40:26 +00:00
|
|
|
if (PathNameU.Buffer[idx] == L'\\')
|
|
|
|
{
|
|
|
|
--idx;
|
|
|
|
PathNameU.Length -= sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get file name */
|
|
|
|
while (idx >= 0 && PathNameU.Buffer[idx] != L'\\')
|
|
|
|
{
|
|
|
|
--idx;
|
|
|
|
}
|
|
|
|
|
2014-04-29 18:25:02 +00:00
|
|
|
if (idx > 0 || PathNameU.Buffer[0] == L'\\')
|
2014-04-28 19:40:26 +00:00
|
|
|
{
|
2017-09-26 13:49:09 +00:00
|
|
|
/* We don't want to include / in the name */
|
|
|
|
FileNameLen = PathNameU.Length - ((idx + 1) * sizeof(WCHAR));
|
|
|
|
|
|
|
|
/* Update FO just to keep file name */
|
|
|
|
/* Skip first slash */
|
|
|
|
++idx;
|
|
|
|
FileObject->FileName.Length = FileNameLen;
|
|
|
|
RtlMoveMemory(&PathNameU.Buffer[0], &PathNameU.Buffer[idx], FileObject->FileName.Length);
|
|
|
|
#if 0
|
2017-09-26 12:36:17 +00:00
|
|
|
/* Terminate the string at the last backslash */
|
|
|
|
PathNameU.Buffer[idx + 1] = UNICODE_NULL;
|
|
|
|
PathNameU.Length = (idx + 1) * sizeof(WCHAR);
|
|
|
|
PathNameU.MaximumLength = PathNameU.Length + sizeof(WCHAR);
|
|
|
|
|
|
|
|
/* Update the file object as well */
|
|
|
|
FileObject->FileName.Length = PathNameU.Length;
|
|
|
|
FileObject->FileName.MaximumLength = PathNameU.MaximumLength;
|
2017-09-26 13:49:09 +00:00
|
|
|
#endif
|
2014-04-28 19:40:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* This is a relative open and we have only the filename, so open the parent directory
|
|
|
|
* It is in RelatedFileObject
|
|
|
|
*/
|
[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(FileObject->RelatedFileObject != NULL);
|
2014-04-28 19:40:26 +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
|
|
|
/* No need to modify the FO, it already has the name */
|
|
|
|
}
|
2014-04-28 19:40:26 +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
|
|
|
/* We're done with opening! */
|
|
|
|
if (ParentFcb != NULL)
|
|
|
|
{
|
|
|
|
Status = vfatAttachFCBToFileObject(DeviceExt, ParentFcb, FileObject);
|
|
|
|
}
|
2014-04-28 19:40:26 +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
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
pFcb = FileObject->FsContext;
|
2014-11-05 23:23:52 +00:00
|
|
|
ASSERT(pFcb == ParentFcb);
|
2014-04-28 19:40:26 +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
|
|
|
if (pFcb->OpenHandleCount == 0)
|
2014-04-28 19:40:26 +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
|
|
|
IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
|
|
|
|
Stack->Parameters.Create.ShareAccess,
|
|
|
|
FileObject,
|
|
|
|
&pFcb->FCBShareAccess);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
|
|
|
|
Stack->Parameters.Create.ShareAccess,
|
|
|
|
FileObject,
|
|
|
|
&pFcb->FCBShareAccess,
|
|
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
VfatCloseFile(DeviceExt, FileObject);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
[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;
|
|
|
|
}
|
2014-04-28 19:40:26 +00:00
|
|
|
}
|
|
|
|
|
2017-05-02 19:33:14 +00:00
|
|
|
pCcb = FileObject->FsContext2;
|
|
|
|
if (BooleanFlagOn(RequestedOptions, FILE_DELETE_ON_CLOSE))
|
|
|
|
{
|
|
|
|
pCcb->Flags |= CCB_DELETE_ON_CLOSE;
|
|
|
|
}
|
|
|
|
|
[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
|
|
|
pFcb->OpenHandleCount++;
|
2014-10-30 20:56:40 +00:00
|
|
|
DeviceExt->OpenHandleCount++;
|
[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
|
|
|
}
|
|
|
|
else if (ParentFcb != NULL)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, ParentFcb);
|
2014-04-28 19:40:26 +00:00
|
|
|
}
|
|
|
|
|
2017-09-24 09:50:36 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
vfatAddToStat(DeviceExt, Fat.SuccessfulCreates, 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
|
|
|
}
|
|
|
|
|
2014-04-28 19:40:26 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2013-12-09 18:48:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the directory containing the file to open doesn't exist then
|
|
|
|
* fail immediately
|
|
|
|
*/
|
|
|
|
if (Status == STATUS_OBJECT_PATH_NOT_FOUND ||
|
|
|
|
Status == STATUS_INVALID_PARAMETER ||
|
2015-11-22 21:46:58 +00:00
|
|
|
Status == STATUS_DELETE_PENDING ||
|
|
|
|
Status == STATUS_ACCESS_DENIED ||
|
|
|
|
Status == STATUS_OBJECT_NAME_COLLISION)
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
if (ParentFcb)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, ParentFcb);
|
|
|
|
}
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status) && ParentFcb == NULL)
|
|
|
|
{
|
2014-04-25 17:09:37 +00:00
|
|
|
DPRINT1("VfatOpenFile failed for '%wZ', status %x\n", &PathNameU, Status);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2018-01-06 21:02:10 +00:00
|
|
|
Attributes = (Stack->Parameters.Create.FileAttributes & (FILE_ATTRIBUTE_ARCHIVE |
|
|
|
|
FILE_ATTRIBUTE_SYSTEM |
|
|
|
|
FILE_ATTRIBUTE_HIDDEN |
|
|
|
|
FILE_ATTRIBUTE_DIRECTORY |
|
|
|
|
FILE_ATTRIBUTE_READONLY));
|
2018-01-01 11:12:08 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
/* If the file open failed then create the required file */
|
|
|
|
if (!NT_SUCCESS (Status))
|
|
|
|
{
|
|
|
|
if (RequestedDisposition == FILE_CREATE ||
|
|
|
|
RequestedDisposition == FILE_OPEN_IF ||
|
|
|
|
RequestedDisposition == FILE_OVERWRITE_IF ||
|
|
|
|
RequestedDisposition == FILE_SUPERSEDE)
|
|
|
|
{
|
2017-02-17 17:58:18 +00:00
|
|
|
if (!BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE))
|
2017-02-26 13:57:17 +00:00
|
|
|
{
|
|
|
|
if (TrailingBackslash)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, ParentFcb);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2017-02-26 13:57:17 +00:00
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
2013-12-10 09:53:21 +00:00
|
|
|
Attributes |= FILE_ATTRIBUTE_ARCHIVE;
|
2017-02-26 13:57:17 +00:00
|
|
|
}
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatSplitPathName(&PathNameU, NULL, &FileNameU);
|
|
|
|
Status = VfatAddEntry(DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions,
|
2018-01-06 21:02:10 +00:00
|
|
|
Attributes, NULL);
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatReleaseFCB(DeviceExt, ParentFcb);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Status = vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, pFcb);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Irp->IoStatus.Information = FILE_CREATED;
|
|
|
|
VfatSetAllocationSizeInformation(FileObject,
|
|
|
|
pFcb,
|
|
|
|
DeviceExt,
|
|
|
|
&Irp->Overlay.AllocationSize);
|
|
|
|
VfatSetExtendedAttributes(FileObject,
|
|
|
|
Irp->AssociatedIrp.SystemBuffer,
|
|
|
|
Stack->Parameters.Create.EaLength);
|
|
|
|
|
|
|
|
if (PagingFileCreate)
|
|
|
|
{
|
|
|
|
pFcb->Flags |= FCB_IS_PAGE_FILE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-02-26 14:43:01 +00:00
|
|
|
vfatReleaseFCB(DeviceExt, ParentFcb);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (ParentFcb)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, ParentFcb);
|
|
|
|
}
|
|
|
|
|
2017-02-26 13:57:17 +00:00
|
|
|
pFcb = FileObject->FsContext;
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
/* Otherwise fail if the caller wanted to create a new file */
|
|
|
|
if (RequestedDisposition == FILE_CREATE)
|
|
|
|
{
|
|
|
|
VfatCloseFile(DeviceExt, FileObject);
|
2017-02-26 13:57:17 +00:00
|
|
|
if (TrailingBackslash && !vfatFCBIsDirectory(pFcb))
|
|
|
|
{
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2017-02-26 13:57:17 +00:00
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
|
|
|
Irp->IoStatus.Information = FILE_EXISTS;
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_OBJECT_NAME_COLLISION;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pFcb->OpenHandleCount != 0)
|
|
|
|
{
|
|
|
|
Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
|
|
|
|
Stack->Parameters.Create.ShareAccess,
|
|
|
|
FileObject,
|
|
|
|
&pFcb->FCBShareAccess,
|
|
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
VfatCloseFile(DeviceExt, FileObject);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2005-12-04 15:09:07 +00:00
|
|
|
return Status;
|
2013-12-09 18:48:13 +00:00
|
|
|
}
|
2005-12-04 15:09:07 +00:00
|
|
|
}
|
2005-11-04 00:10:39 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
/*
|
|
|
|
* Check the file has the requested attributes
|
|
|
|
*/
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(RequestedOptions, FILE_NON_DIRECTORY_FILE) &&
|
|
|
|
vfatFCBIsDirectory(pFcb))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
VfatCloseFile (DeviceExt, FileObject);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_FILE_IS_A_DIRECTORY;
|
|
|
|
}
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE) &&
|
|
|
|
!vfatFCBIsDirectory(pFcb))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
VfatCloseFile (DeviceExt, FileObject);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_NOT_A_DIRECTORY;
|
|
|
|
}
|
2017-02-26 13:57:17 +00:00
|
|
|
if (TrailingBackslash && !vfatFCBIsDirectory(pFcb))
|
2017-02-26 13:32:55 +00:00
|
|
|
{
|
|
|
|
VfatCloseFile (DeviceExt, FileObject);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2017-02-26 13:32:55 +00:00
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
2006-12-31 16:43:40 +00:00
|
|
|
#ifndef USE_ROS_CC_AND_FS
|
2017-02-17 17:58:18 +00:00
|
|
|
if (!vfatFCBIsDirectory(pFcb))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(Stack->Parameters.Create.SecurityContext->DesiredAccess, FILE_WRITE_DATA) ||
|
2013-12-09 18:48:13 +00:00
|
|
|
RequestedDisposition == FILE_OVERWRITE ||
|
2016-08-11 13:25:57 +00:00
|
|
|
RequestedDisposition == FILE_OVERWRITE_IF ||
|
|
|
|
(RequestedOptions & FILE_DELETE_ON_CLOSE))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
if (!MmFlushImageSection(&pFcb->SectionObjectPointers, MmFlushForWrite))
|
|
|
|
{
|
|
|
|
DPRINT1("%wZ\n", &pFcb->PathNameU);
|
|
|
|
DPRINT1("%d %d %d\n", Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA,
|
|
|
|
RequestedDisposition == FILE_OVERWRITE, RequestedDisposition == FILE_OVERWRITE_IF);
|
|
|
|
VfatCloseFile (DeviceExt, FileObject);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2017-02-17 17:58:18 +00:00
|
|
|
return (BooleanFlagOn(RequestedOptions, FILE_DELETE_ON_CLOSE)) ? STATUS_CANNOT_DELETE
|
|
|
|
: STATUS_SHARING_VIOLATION;
|
2013-12-09 18:48:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-12-31 16:43:40 +00:00
|
|
|
#endif
|
2013-12-09 18:48:13 +00:00
|
|
|
if (PagingFileCreate)
|
|
|
|
{
|
|
|
|
/* FIXME:
|
|
|
|
* Do more checking for page files. It is possible,
|
|
|
|
* that the file was opened and closed previously
|
|
|
|
* as a normal cached file. In this case, the cache
|
|
|
|
* manager has referenced the fileobject and the fcb
|
|
|
|
* is held in memory. Try to remove the fileobject
|
|
|
|
* from cache manager and use the fcb.
|
|
|
|
*/
|
|
|
|
if (pFcb->RefCount > 1)
|
|
|
|
{
|
2017-02-17 17:58:18 +00:00
|
|
|
if(!BooleanFlagOn(pFcb->Flags, FCB_IS_PAGE_FILE))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
VfatCloseFile(DeviceExt, FileObject);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pFcb->Flags |= FCB_IS_PAGE_FILE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-02-17 17:58:18 +00:00
|
|
|
if (BooleanFlagOn(pFcb->Flags, FCB_IS_PAGE_FILE))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
|
|
|
VfatCloseFile(DeviceExt, FileObject);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
}
|
1999-12-11 21:14:49 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
if (RequestedDisposition == FILE_OVERWRITE ||
|
|
|
|
RequestedDisposition == FILE_OVERWRITE_IF ||
|
|
|
|
RequestedDisposition == FILE_SUPERSEDE)
|
|
|
|
{
|
2018-01-01 11:12:08 +00:00
|
|
|
if ((BooleanFlagOn(*pFcb->Attributes, FILE_ATTRIBUTE_HIDDEN) && !BooleanFlagOn(Attributes, FILE_ATTRIBUTE_HIDDEN)) ||
|
|
|
|
(BooleanFlagOn(*pFcb->Attributes, FILE_ATTRIBUTE_SYSTEM) && !BooleanFlagOn(Attributes, FILE_ATTRIBUTE_SYSTEM)))
|
|
|
|
{
|
|
|
|
VfatCloseFile(DeviceExt, FileObject);
|
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
|
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
}
|
|
|
|
|
2017-02-17 17:58:18 +00:00
|
|
|
if (!vfatFCBIsDirectory(pFcb))
|
2013-12-10 18:48:55 +00:00
|
|
|
{
|
2018-01-07 10:34:41 +00:00
|
|
|
LARGE_INTEGER SystemTime;
|
|
|
|
|
2018-01-01 13:29:15 +00:00
|
|
|
if (RequestedDisposition == FILE_SUPERSEDE)
|
|
|
|
{
|
2018-01-06 21:02:10 +00:00
|
|
|
*pFcb->Attributes = Attributes;
|
2018-01-01 13:29:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-01-06 21:02:10 +00:00
|
|
|
*pFcb->Attributes |= Attributes;
|
2018-01-01 13:29:15 +00:00
|
|
|
}
|
2013-12-10 18:48:55 +00:00
|
|
|
*pFcb->Attributes |= FILE_ATTRIBUTE_ARCHIVE;
|
2018-01-07 10:34:41 +00:00
|
|
|
|
|
|
|
KeQuerySystemTime(&SystemTime);
|
|
|
|
if (vfatVolumeIsFatX(DeviceExt))
|
|
|
|
{
|
|
|
|
FsdSystemTimeToDosDateTime(DeviceExt,
|
|
|
|
&SystemTime, &pFcb->entry.FatX.UpdateDate,
|
|
|
|
&pFcb->entry.FatX.UpdateTime);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FsdSystemTimeToDosDateTime(DeviceExt,
|
|
|
|
&SystemTime, &pFcb->entry.Fat.UpdateDate,
|
|
|
|
&pFcb->entry.Fat.UpdateTime);
|
|
|
|
}
|
|
|
|
|
2017-02-17 21:24:12 +00:00
|
|
|
VfatUpdateEntry(pFcb, vfatVolumeIsFatX(DeviceExt));
|
2013-12-10 18:48:55 +00:00
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
ExAcquireResourceExclusiveLite(&(pFcb->MainResource), TRUE);
|
|
|
|
Status = VfatSetAllocationSizeInformation(FileObject,
|
|
|
|
pFcb,
|
|
|
|
DeviceExt,
|
|
|
|
&Irp->Overlay.AllocationSize);
|
|
|
|
ExReleaseResourceLite(&(pFcb->MainResource));
|
|
|
|
if (!NT_SUCCESS (Status))
|
|
|
|
{
|
|
|
|
VfatCloseFile(DeviceExt, FileObject);
|
2017-09-24 09:50:36 +00:00
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
2013-12-09 18:48:13 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (RequestedDisposition == FILE_SUPERSEDE)
|
|
|
|
{
|
|
|
|
Irp->IoStatus.Information = FILE_SUPERSEDED;
|
|
|
|
}
|
|
|
|
else if (RequestedDisposition == FILE_OVERWRITE ||
|
|
|
|
RequestedDisposition == FILE_OVERWRITE_IF)
|
|
|
|
{
|
|
|
|
Irp->IoStatus.Information = FILE_OVERWRITTEN;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Irp->IoStatus.Information = FILE_OPENED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pFcb->OpenHandleCount == 0)
|
|
|
|
{
|
|
|
|
IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
|
|
|
|
Stack->Parameters.Create.ShareAccess,
|
|
|
|
FileObject,
|
|
|
|
&pFcb->FCBShareAccess);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IoUpdateShareAccess(FileObject,
|
|
|
|
&pFcb->FCBShareAccess);
|
|
|
|
}
|
|
|
|
|
2017-05-02 19:33:14 +00:00
|
|
|
pCcb = FileObject->FsContext2;
|
|
|
|
if (BooleanFlagOn(RequestedOptions, FILE_DELETE_ON_CLOSE))
|
|
|
|
{
|
|
|
|
pCcb->Flags |= CCB_DELETE_ON_CLOSE;
|
|
|
|
}
|
|
|
|
|
2014-03-07 19:46:37 +00:00
|
|
|
if (Irp->IoStatus.Information == FILE_CREATED)
|
|
|
|
{
|
2018-01-07 13:16:11 +00:00
|
|
|
vfatReportChange(DeviceExt,
|
|
|
|
pFcb,
|
|
|
|
(vfatFCBIsDirectory(pFcb) ?
|
|
|
|
FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
|
|
|
|
FILE_ACTION_ADDED);
|
2014-03-07 19:46:37 +00:00
|
|
|
}
|
2018-01-07 10:44:25 +00:00
|
|
|
else if (Irp->IoStatus.Information == FILE_OVERWRITTEN ||
|
|
|
|
Irp->IoStatus.Information == FILE_SUPERSEDED)
|
|
|
|
{
|
2018-01-07 13:16:11 +00:00
|
|
|
vfatReportChange(DeviceExt,
|
|
|
|
pFcb,
|
|
|
|
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE,
|
|
|
|
FILE_ACTION_MODIFIED);
|
2018-01-07 10:44:25 +00:00
|
|
|
}
|
2014-03-07 19:46:37 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
pFcb->OpenHandleCount++;
|
2014-10-30 20:56:40 +00:00
|
|
|
DeviceExt->OpenHandleCount++;
|
2013-12-09 18:48:13 +00:00
|
|
|
|
|
|
|
/* FIXME : test write access if requested */
|
|
|
|
|
2017-12-17 17:25:43 +00:00
|
|
|
/* FIXME: That is broken, we cannot reach this code path with failure */
|
|
|
|
ASSERT(NT_SUCCESS(Status));
|
2017-09-24 09:50:36 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
vfatAddToStat(DeviceExt, Fat.SuccessfulCreates, 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
return Status;
|
|
|
|
}
|
1999-12-11 21:14:49 +00:00
|
|
|
|
2000-07-07 02:14:14 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Create or open a file
|
|
|
|
*/
|
2013-12-09 18:48:13 +00:00
|
|
|
NTSTATUS
|
|
|
|
VfatCreate(
|
|
|
|
PVFAT_IRP_CONTEXT IrpContext)
|
2000-07-07 02:14:14 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
ASSERT(IrpContext);
|
|
|
|
|
|
|
|
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
|
|
|
|
{
|
|
|
|
/* DeviceObject represents FileSystem instead of logical volume */
|
|
|
|
DPRINT ("FsdCreate called with file system\n");
|
|
|
|
IrpContext->Irp->IoStatus.Information = FILE_OPENED;
|
2015-05-15 16:03:29 +00:00
|
|
|
IrpContext->PriorityBoost = IO_DISK_INCREMENT;
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-02-17 17:58:18 +00:00
|
|
|
if (!BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))
|
2013-12-09 18:48:13 +00:00
|
|
|
{
|
2015-05-15 16:03:29 +00:00
|
|
|
return VfatMarkIrpContextForQueue(IrpContext);
|
2013-12-09 18:48:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IrpContext->Irp->IoStatus.Information = 0;
|
|
|
|
ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
|
|
|
|
Status = VfatCreateFile(IrpContext->DeviceObject, IrpContext->Irp);
|
|
|
|
ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
|
|
|
|
|
2015-05-15 16:03:29 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
IrpContext->PriorityBoost = IO_DISK_INCREMENT;
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
return Status;
|
2000-07-07 02:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|