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
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
|
|
|
|
{
|
|
|
|
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: Read the volume label
|
|
|
|
*/
|
2013-12-09 18:48:13 +00:00
|
|
|
NTSTATUS
|
|
|
|
ReadVolumeLabel(
|
|
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PVPB Vpb)
|
1999-12-11 21:14:49 +00:00
|
|
|
{
|
2013-12-09 18:48:13 +00:00
|
|
|
PVOID Context = NULL;
|
|
|
|
ULONG DirIndex = 0;
|
|
|
|
PDIR_ENTRY Entry;
|
|
|
|
PVFATFCB pFcb;
|
|
|
|
LARGE_INTEGER FileOffset;
|
|
|
|
UNICODE_STRING NameU;
|
|
|
|
ULONG SizeDirEntry;
|
|
|
|
ULONG EntriesPerPage;
|
|
|
|
OEM_STRING StringO;
|
|
|
|
|
|
|
|
NameU.Buffer = Vpb->VolumeLabel;
|
|
|
|
NameU.Length = 0;
|
|
|
|
NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
|
|
|
|
*(Vpb->VolumeLabel) = 0;
|
|
|
|
Vpb->VolumeLabelLength = 0;
|
|
|
|
|
|
|
|
if (DeviceExt->Flags & VCB_IS_FATX)
|
|
|
|
{
|
|
|
|
SizeDirEntry = sizeof(FATX_DIR_ENTRY);
|
|
|
|
EntriesPerPage = FATX_ENTRIES_PER_PAGE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SizeDirEntry = sizeof(FAT_DIR_ENTRY);
|
|
|
|
EntriesPerPage = FAT_ENTRIES_PER_PAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
|
|
|
|
pFcb = vfatOpenRootFCB(DeviceExt);
|
|
|
|
ExReleaseResourceLite(&DeviceExt->DirResource);
|
|
|
|
|
|
|
|
FileOffset.QuadPart = 0;
|
|
|
|
if (CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry))
|
|
|
|
{
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
if (ENTRY_VOLUME(DeviceExt, Entry))
|
|
|
|
{
|
|
|
|
/* copy volume label */
|
|
|
|
if (DeviceExt->Flags & VCB_IS_FATX)
|
|
|
|
{
|
|
|
|
StringO.Buffer = (PCHAR)Entry->FatX.Filename;
|
|
|
|
StringO.MaximumLength = StringO.Length = Entry->FatX.FilenameLength;
|
|
|
|
RtlOemStringToUnicodeString(&NameU, &StringO, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vfat8Dot3ToString(&Entry->Fat, &NameU);
|
|
|
|
}
|
|
|
|
Vpb->VolumeLabelLength = NameU.Length;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ENTRY_END(DeviceExt, Entry))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
DirIndex++;
|
|
|
|
Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
|
|
|
|
if ((DirIndex % EntriesPerPage) == 0)
|
|
|
|
{
|
|
|
|
CcUnpinData(Context);
|
|
|
|
FileOffset.u.LowPart += PAGE_SIZE;
|
|
|
|
if (!CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry))
|
|
|
|
{
|
|
|
|
Context = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Context)
|
|
|
|
{
|
|
|
|
CcUnpinData(Context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
|
|
|
|
vfatReleaseFCB(DeviceExt, pFcb);
|
|
|
|
ExReleaseResourceLite(&DeviceExt->DirResource);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
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;
|
|
|
|
|
|
|
|
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;
|
|
|
|
if ((rcFcb->Flags & FCB_IS_FATX_ENTRY) && !vfatFCBIsRoot(Parent))
|
|
|
|
{
|
|
|
|
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
|
|
|
{
|
|
|
|
Status = DeviceExt->GetNextDirEntry(&Context, &Page, Parent, DirContext, First);
|
|
|
|
First = FALSE;
|
|
|
|
if (Status == STATUS_NO_MORE_ENTRIES)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ENTRY_VOLUME(DeviceExt, &DirContext->DirEntry))
|
|
|
|
{
|
|
|
|
DirContext->DirIndex++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
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,
|
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
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
if (Fcb->Flags & FCB_DELETE_PENDING)
|
|
|
|
{
|
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 */
|
|
|
|
if ((*Fcb->Attributes & FILE_ATTRIBUTE_READONLY) &&
|
|
|
|
(RequestedDisposition == FILE_OVERWRITE))
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, Fcb);
|
|
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
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;
|
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;
|
|
|
|
PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
|
2014-04-28 19:40:26 +00:00
|
|
|
OpenTargetDir = (Stack->Flags & SL_OPEN_TARGET_DIRECTORY) ? TRUE : FALSE;
|
[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;
|
|
|
|
|
|
|
|
/* Check their validity. */
|
|
|
|
if (RequestedOptions & FILE_DIRECTORY_FILE &&
|
|
|
|
RequestedDisposition == FILE_SUPERSEDE)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2005-11-04 00:10:39 +00:00
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
if (RequestedOptions & FILE_DIRECTORY_FILE &&
|
|
|
|
RequestedOptions & FILE_NON_DIRECTORY_FILE)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2014-10-30 20:56:40 +00:00
|
|
|
/* Deny create if the volume is locked */
|
|
|
|
if (DeviceExt->Flags & VCB_VOLUME_LOCKED)
|
|
|
|
{
|
|
|
|
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 &&
|
|
|
|
(FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
|
|
|
|
{
|
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
|
|
|
}
|
2010-08-10 20:08:31 +00:00
|
|
|
#if 0
|
|
|
|
/* In spite of what is shown in WDK, it seems that Windows FAT driver doesn't perform that test */
|
2013-12-09 18:48:13 +00:00
|
|
|
if (RequestedOptions & FILE_DIRECTORY_FILE)
|
|
|
|
{
|
|
|
|
return STATUS_NOT_A_DIRECTORY;
|
|
|
|
}
|
2010-08-10 20:08:31 +00:00
|
|
|
#endif
|
2011-03-02 21:51:33 +00:00
|
|
|
|
2014-04-28 19:40:26 +00:00
|
|
|
if (OpenTargetDir)
|
|
|
|
{
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:48:13 +00:00
|
|
|
pFcb = DeviceExt->VolumeFcb;
|
|
|
|
vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
|
2014-10-30 20:56:40 +00:00
|
|
|
DeviceExt->OpenHandleCount++;
|
2013-12-09 18:48:13 +00:00
|
|
|
|
|
|
|
Irp->IoStatus.Information = FILE_OPENED;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for illegal characters and illegale dot sequences in the file name */
|
|
|
|
PathNameU = FileObject->FileName;
|
|
|
|
c = PathNameU.Buffer + PathNameU.Length / sizeof(WCHAR);
|
|
|
|
last = c - 1;
|
|
|
|
Dots = TRUE;
|
|
|
|
while (c-- > PathNameU.Buffer)
|
|
|
|
{
|
|
|
|
if (*c == L'\\' || c == PathNameU.Buffer)
|
|
|
|
{
|
|
|
|
if (Dots && last > c)
|
|
|
|
{
|
|
|
|
return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PathNameU.Length > sizeof(WCHAR) && PathNameU.Buffer[PathNameU.Length/sizeof(WCHAR)-1] == L'\\')
|
|
|
|
{
|
|
|
|
PathNameU.Length -= sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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
|
|
|
{
|
[FASTFAT]
- Implement vfatPrepareTargetForRename() that prepares for renaming. It tries to open target and deletes it if it exists and if allowed. And then, it opens the parent directory.
- Implement VfatSetRenameInformation() that actually does the renaming (call as SetInformationFile). It handles cases we we have (or we don't have) TargetDirectory provided. It sends notifications as appropriated on demands.
- Implement vfatRenameEntry() that renames an entry in place. So far, it only supports FATX entries renaming. FAT entries are a bit more complex. It falls back to vfatMoveEntry() in later cases.
- Implement VfatMoveEntry() that will move an entry accross directories (or in place for FAT). Its principles are simple: it deletes the entry in old parent, and recreate it in new parent, keeping file metadata & data.
- Modify VfatDelEntry() and VfatAddEntry() so that they can handle deleting an entry without touching its data and adding an entry with an already provided FCB and thus use the given metadata.
- Implement vfatDelFCBFromTable() which is just old code moved to new routine to allow reuse. It deletes a FCB entry from hash table. Doesn't deal with references!
- Implement vfatMakeFullName() which is mostly old code moved to new routine to allow reuse. It allocates buffer and copy data for FCB full name.
- Implement vfatUpdateFCB() that will update a FCB with new names and parent. It will remove anything related to old name and will recreate using new data. It will adjust references count.
- Modify vfatMakeFCBFromDirEntry() so that it calls vfatMakeFullName().
- Modify vfatReleaseFCB() so that it calls vfatDelFCBFromTable().
- Revert VfatOpenFile() to its previous features.
- Modify VfatCreateFile() to reimplement support for SL_OPEN_TARGET_DIRECTORY. It is way less hackish than previously. It also properly opens parent now, by incrementing its handle count and by setting appropriate access rights.
[KERNEL32]
- Rewritten MoveFileWithProgressW() to implement all the missing features that are used in Windows 2k3 including links and reparse points.
- Implemented BasepMoveFileDelayed() to replace deprecated add_boot_rename_entry(). This functions is matching the features implemented in SMSS.
- Implemented BasepMoveFileCopyProgress() which is used in MoveFileWithProgressW().
- Stubbed BasepNotifyTrackingService() which is not use at the moment (FastFAT, even in Windows doesn't provide such feature).
- Reimplemented ReplaceFileA(), MoveFileWithProgressA() to quit Winisms and use our internal helpers.
- Make MoveFileX() use MoveFileWithProgressX() directly.
- Fixed a few prototypes.
TL;DR:
This (huge) commit implements file and directory renaming in FastFAT driver. This allows getting rid of old implementation in kernel32 where files were force copied.
A feature is still missing, but Jérôme should implement it anytime soon (he prototyped it already): moving directories across volumes. This requires some work in BasepCopyFileExW().
Kudos to all the devs who helped me on this: Christoph, Hervé, Jérôme, Thomas.
This finally allows killing CR-52... It was about time!
svn path=/trunk/; revision=64836
2014-10-19 21:38:32 +00:00
|
|
|
Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, &ParentFcb);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PVFATFCB TargetFcb;
|
2014-04-28 19:40:26 +00:00
|
|
|
LONG idx, FileNameLen;
|
|
|
|
|
[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
|
|
|
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;
|
|
|
|
|
|
|
|
/* Skip tailing \ - if any */
|
|
|
|
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
|
|
|
{
|
|
|
|
/* 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;
|
2014-04-29 20:50:51 +00:00
|
|
|
FileObject->FileName.Length = FileNameLen;
|
|
|
|
RtlMoveMemory(&PathNameU.Buffer[0], &PathNameU.Buffer[idx], FileObject->FileName.Length);
|
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);
|
|
|
|
return 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
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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 ||
|
|
|
|
Status == STATUS_DELETE_PENDING)
|
|
|
|
{
|
|
|
|
if (ParentFcb)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, ParentFcb);
|
|
|
|
}
|
|
|
|
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);
|
2013-12-09 18:48:13 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
|
|
|
Attributes = Stack->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL;
|
2013-12-10 09:53:21 +00:00
|
|
|
if (!(RequestedOptions & FILE_DIRECTORY_FILE))
|
|
|
|
Attributes |= FILE_ATTRIBUTE_ARCHIVE;
|
2013-12-09 18:48:13 +00:00
|
|
|
vfatSplitPathName(&PathNameU, NULL, &FileNameU);
|
|
|
|
Status = VfatAddEntry(DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions,
|
[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
|
|
|
(UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS), 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);
|
|
|
|
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
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (ParentFcb)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, ParentFcb);
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (ParentFcb)
|
|
|
|
{
|
|
|
|
vfatReleaseFCB(DeviceExt, ParentFcb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise fail if the caller wanted to create a new file */
|
|
|
|
if (RequestedDisposition == FILE_CREATE)
|
|
|
|
{
|
|
|
|
Irp->IoStatus.Information = FILE_EXISTS;
|
|
|
|
VfatCloseFile(DeviceExt, FileObject);
|
|
|
|
return STATUS_OBJECT_NAME_COLLISION;
|
|
|
|
}
|
|
|
|
|
|
|
|
pFcb = FileObject->FsContext;
|
|
|
|
|
|
|
|
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);
|
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
|
|
|
|
*/
|
|
|
|
if (RequestedOptions & FILE_NON_DIRECTORY_FILE &&
|
|
|
|
*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
|
|
{
|
|
|
|
VfatCloseFile (DeviceExt, FileObject);
|
|
|
|
return STATUS_FILE_IS_A_DIRECTORY;
|
|
|
|
}
|
|
|
|
if (RequestedOptions & FILE_DIRECTORY_FILE &&
|
|
|
|
!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
|
|
{
|
|
|
|
VfatCloseFile (DeviceExt, FileObject);
|
|
|
|
return STATUS_NOT_A_DIRECTORY;
|
|
|
|
}
|
2006-12-31 16:43:40 +00:00
|
|
|
#ifndef USE_ROS_CC_AND_FS
|
2013-12-09 18:48:13 +00:00
|
|
|
if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
|
|
{
|
|
|
|
if (Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA ||
|
|
|
|
RequestedDisposition == FILE_OVERWRITE ||
|
|
|
|
RequestedDisposition == FILE_OVERWRITE_IF)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
return STATUS_SHARING_VIOLATION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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)
|
|
|
|
{
|
|
|
|
if(!(pFcb->Flags & FCB_IS_PAGE_FILE))
|
|
|
|
{
|
|
|
|
VfatCloseFile(DeviceExt, FileObject);
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pFcb->Flags |= FCB_IS_PAGE_FILE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pFcb->Flags & FCB_IS_PAGE_FILE)
|
|
|
|
{
|
|
|
|
VfatCloseFile(DeviceExt, FileObject);
|
|
|
|
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)
|
|
|
|
{
|
2013-12-10 18:48:55 +00:00
|
|
|
if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
|
|
{
|
|
|
|
*pFcb->Attributes = Stack->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL;
|
|
|
|
*pFcb->Attributes |= FILE_ATTRIBUTE_ARCHIVE;
|
|
|
|
VfatUpdateEntry(pFcb);
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-03-07 19:46:37 +00:00
|
|
|
if (Irp->IoStatus.Information == FILE_CREATED)
|
|
|
|
{
|
|
|
|
FsRtlNotifyFullReportChange(DeviceExt->NotifySync,
|
|
|
|
&(DeviceExt->NotifyList),
|
|
|
|
(PSTRING)&pFcb->PathNameU,
|
|
|
|
pFcb->PathNameU.Length - pFcb->LongNameU.Length,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
2014-03-07 20:30:29 +00:00
|
|
|
((*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY) ?
|
|
|
|
FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
|
2014-03-07 19:46:37 +00:00
|
|
|
FILE_ACTION_ADDED,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
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 */
|
|
|
|
|
|
|
|
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;
|
|
|
|
IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
IoCompleteRequest(IrpContext->Irp, IO_DISK_INCREMENT);
|
|
|
|
VfatFreeIrpContext(IrpContext);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
|
|
|
|
{
|
|
|
|
return(VfatQueueRequest(IrpContext));
|
|
|
|
}
|
|
|
|
|
|
|
|
IrpContext->Irp->IoStatus.Information = 0;
|
|
|
|
ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
|
|
|
|
Status = VfatCreateFile(IrpContext->DeviceObject, IrpContext->Irp);
|
|
|
|
ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
|
|
|
|
|
|
|
|
IrpContext->Irp->IoStatus.Status = Status;
|
|
|
|
IoCompleteRequest(IrpContext->Irp,
|
|
|
|
(CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
|
|
|
|
VfatFreeIrpContext(IrpContext);
|
|
|
|
return Status;
|
2000-07-07 02:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|