/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
- * FILE: drivers/fs/vfat/dirwr.c
+ * FILE: drivers/filesystems/fastfat/dirwr.c
* PURPOSE: VFAT Filesystem : write in directory
+ * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com)
+ * Herve Poussineau (reactos@poussine.freesurf.fr)
+ * Pierre Schweitzer (pierre@reactos.org)
*
*/
/* INCLUDES *****************************************************************/
-#define NDEBUG
#include "vfat.h"
+#define NDEBUG
+#include <debug.h>
+
/*
* update an existing FAT entry
*/
dirIndex = pFcb->dirIndex;
}
- DPRINT("updEntry dirIndex %d, PathName \'%wZ\'\n", dirIndex, &pFcb->PathNameU);
+ DPRINT("updEntry dirIndex %u, PathName \'%wZ\'\n", dirIndex, &pFcb->PathNameU);
if (vfatFCBIsRoot(pFcb) || (pFcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)))
{
}
}
+/*
+ * rename an existing FAT entry
+ */
+NTSTATUS
+vfatRenameEntry(
+ IN PDEVICE_EXTENSION DeviceExt,
+ IN PVFATFCB pFcb,
+ IN PUNICODE_STRING FileName,
+ IN BOOLEAN CaseChangeOnly)
+{
+ OEM_STRING NameA;
+ ULONG StartIndex;
+ PVOID Context = NULL;
+ LARGE_INTEGER Offset;
+ PFATX_DIR_ENTRY pDirEntry;
+ UNICODE_STRING ShortName;
+ NTSTATUS Status;
+
+ DPRINT("vfatRenameEntry(%p, %p, %wZ, %d)\n", DeviceExt, pFcb, FileName, CaseChangeOnly);
+
+ if (pFcb->Flags & FCB_IS_FATX_ENTRY)
+ {
+ /* Open associated dir entry */
+ StartIndex = pFcb->startIndex;
+ Offset.u.HighPart = 0;
+ Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
+ if (!CcPinRead(pFcb->parentFcb->FileObject, &Offset, sizeof(FATX_DIR_ENTRY), TRUE,
+ &Context, (PVOID*)&pDirEntry))
+ {
+ DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];
+
+ /* Set file name */
+ NameA.Buffer = (PCHAR)pDirEntry->Filename;
+ NameA.Length = 0;
+ NameA.MaximumLength = 42;
+ RtlUnicodeStringToOemString(&NameA, FileName, FALSE);
+ pDirEntry->FilenameLength = (unsigned char)NameA.Length;
+
+ CcSetDirtyPinnedData(Context, NULL);
+ CcUnpinData(Context);
+
+ /* Update FCB */
+ ShortName.Length = 0;
+ ShortName.MaximumLength = 0;
+ ShortName.Buffer = NULL;
+ Status = vfatUpdateFCB(DeviceExt, pFcb, FileName, &ShortName, pFcb->parentFcb);
+ if (NT_SUCCESS(Status))
+ {
+ CcPurgeCacheSection(&pFcb->parentFcb->SectionObjectPointers, NULL, 0, FALSE);
+ }
+
+ return Status;
+ }
+ else
+ {
+ /* This we cannot handle properly, move file - would likely need love */
+ return VfatMoveEntry(DeviceExt, pFcb, FileName, pFcb->parentFcb);
+ }
+}
+
/*
* try to find contiguous entries frees in directory,
* extend a directory if is neccesary
{
CcUnpinData(Context);
}
- /* FIXME: check return value */
- CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
- TRUE, &Context, (PVOID*)&pFatEntry);
+ if (!CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
+ TRUE, &Context, (PVOID*)&pFatEntry))
+ {
+ return FALSE;
+ }
FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster;
}
if (ENTRY_END(DeviceExt, pFatEntry))
/* clear the new dir cluster */
FileOffset.u.LowPart = (ULONG)(pDirFcb->RFCB.FileSize.QuadPart -
DeviceExt->FatInfo.BytesPerCluster);
- CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
- TRUE, &Context, (PVOID*)&pFatEntry);
+ if (!CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
+ TRUE, &Context, (PVOID*)&pFatEntry))
+ {
+ return FALSE;
+ }
if (DeviceExt->Flags & VCB_IS_FATX)
memset(pFatEntry, 0xff, DeviceExt->FatInfo.BytesPerCluster);
else
{
/* clear the entry after the last new entry */
FileOffset.u.LowPart = (*start + nbSlots) * SizeDirEntry;
- CcPinRead(pDirFcb->FileObject, &FileOffset, SizeDirEntry,
- TRUE, &Context, (PVOID*)&pFatEntry);
+ if (!CcPinRead(pDirFcb->FileObject, &FileOffset, SizeDirEntry,
+ TRUE, &Context, (PVOID*)&pFatEntry))
+ {
+ return FALSE;
+ }
if (DeviceExt->Flags & VCB_IS_FATX)
memset(pFatEntry, 0xff, SizeDirEntry);
else
CcUnpinData(Context);
}
}
- DPRINT("nbSlots %d nbFree %d, entry number %d\n", nbSlots, nbFree, *start);
+ DPRINT("nbSlots %u nbFree %u, entry number %u\n", nbSlots, nbFree, *start);
return TRUE;
}
IN PVFATFCB* Fcb,
IN PVFATFCB ParentFcb,
IN ULONG RequestedOptions,
- IN UCHAR ReqAttr)
+ IN UCHAR ReqAttr,
+ IN PVFAT_MOVE_CONTEXT MoveContext)
{
PVOID Context = NULL;
PFAT_DIR_ENTRY pFatEntry;
/* nb of entry needed for long name+normal entry */
nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1;
- DPRINT("NameLen= %d, nbSlots =%d\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);
+ DPRINT("NameLen= %u, nbSlots =%u\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);
Buffer = ExAllocatePoolWithTag(NonPagedPool, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY), TAG_VFAT);
if (Buffer == NULL)
{
needLong = TRUE;
}
}
- DPRINT("'%s', '%wZ', needTilde=%d, needLong=%d\n",
+ DPRINT("'%s', '%wZ', needTilde=%u, needLong=%u\n",
aName, &DirContext.LongNameU, needTilde, needLong);
memset(DirContext.DirEntry.Fat.ShortName, ' ', 11);
for (i = 0; i < 8 && aName[i] && aName[i] != '.'; i++)
DirContext.DirEntry.Fat.UpdateDate = DirContext.DirEntry.Fat.CreationDate;
DirContext.DirEntry.Fat.UpdateTime = DirContext.DirEntry.Fat.CreationTime;
DirContext.DirEntry.Fat.AccessDate = DirContext.DirEntry.Fat.CreationDate;
+ /* If it's moving, preserve creation time and file size */
+ if (MoveContext != NULL)
+ {
+ DirContext.DirEntry.Fat.CreationDate = MoveContext->CreationDate;
+ DirContext.DirEntry.Fat.CreationTime = MoveContext->CreationTime;
+ DirContext.DirEntry.Fat.FileSize = MoveContext->FileSize;
+ }
if (needLong)
{
DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;
if (RequestedOptions & FILE_DIRECTORY_FILE)
{
- CurrentCluster = 0;
- Status = NextCluster(DeviceExt, 0, &CurrentCluster, TRUE);
- if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
+ /* If we aren't moving, use next */
+ if (MoveContext == NULL)
{
- ExFreePoolWithTag(Buffer, TAG_VFAT);
- if (!NT_SUCCESS(Status))
+ CurrentCluster = 0;
+ Status = NextCluster(DeviceExt, 0, &CurrentCluster, TRUE);
+ if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
{
- return Status;
+ ExFreePoolWithTag(Buffer, TAG_VFAT);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ return STATUS_DISK_FULL;
}
- return STATUS_DISK_FULL;
}
+ else
+ {
+ CurrentCluster = MoveContext->FirstCluster;
+ }
+
+ if (DeviceExt->FatInfo.FatType == FAT32)
+ {
+ DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
+ }
+ DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;
+ }
+ else if (MoveContext != NULL)
+ {
+ CurrentCluster = MoveContext->FirstCluster;
+
if (DeviceExt->FatInfo.FatType == FAT32)
{
DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
if (DirContext.StartIndex / i == DirContext.DirIndex / i)
{
/* one cluster */
- CcPinRead(ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY),
- TRUE, &Context, (PVOID*)&pFatEntry);
+ if (!CcPinRead(ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY),
+ TRUE, &Context, (PVOID*)&pFatEntry))
+ {
+ ExFreePoolWithTag(Buffer, TAG_VFAT);
+ return STATUS_UNSUCCESSFUL;
+ }
if (nbSlots > 1)
{
RtlCopyMemory(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));
size = DeviceExt->FatInfo.BytesPerCluster -
(DirContext.StartIndex * sizeof(FAT_DIR_ENTRY)) % DeviceExt->FatInfo.BytesPerCluster;
i = size / sizeof(FAT_DIR_ENTRY);
- CcPinRead(ParentFcb->FileObject, &FileOffset, size, TRUE,
- &Context, (PVOID*)&pFatEntry);
+ if (!CcPinRead(ParentFcb->FileObject, &FileOffset, size, TRUE,
+ &Context, (PVOID*)&pFatEntry))
+ {
+ ExFreePoolWithTag(Buffer, TAG_VFAT);
+ return STATUS_UNSUCCESSFUL;
+ }
RtlCopyMemory(pFatEntry, Buffer, size);
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
FileOffset.u.LowPart += size;
- CcPinRead(ParentFcb->FileObject, &FileOffset,
+ if (!CcPinRead(ParentFcb->FileObject, &FileOffset,
nbSlots * sizeof(FAT_DIR_ENTRY) - size,
- TRUE, &Context, (PVOID*)&pFatEntry);
+ TRUE, &Context, (PVOID*)&pFatEntry))
+ {
+ ExFreePoolWithTag(Buffer, TAG_VFAT);
+ return STATUS_UNSUCCESSFUL;
+ }
if (nbSlots - 1 > i)
{
RtlCopyMemory(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FAT_DIR_ENTRY));
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
- Status = vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);
+ if (MoveContext != NULL)
+ {
+ /* We're modifying an existing FCB - likely rename/move */
+ Status = vfatUpdateFCB(DeviceExt, *Fcb, &DirContext.LongNameU, &DirContext.ShortNameU, ParentFcb);
+ (*Fcb)->dirIndex = DirContext.DirIndex;
+ (*Fcb)->startIndex = DirContext.StartIndex;
+ }
+ else
+ {
+ Status = vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);
+ }
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Buffer, TAG_VFAT);
if (RequestedOptions & FILE_DIRECTORY_FILE)
{
FileOffset.QuadPart = 0;
- CcPinRead((*Fcb)->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE,
- &Context, (PVOID*)&pFatEntry);
- /* clear the new directory cluster */
- RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
- /* create '.' and '..' */
- RtlCopyMemory(&pFatEntry[0].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
- RtlCopyMemory(pFatEntry[0].ShortName, ". ", 11);
- RtlCopyMemory(&pFatEntry[1].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
- RtlCopyMemory(pFatEntry[1].ShortName, ".. ", 11);
+ if (!CcPinRead((*Fcb)->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE,
+ &Context, (PVOID*)&pFatEntry))
+ {
+ ExFreePoolWithTag(Buffer, TAG_VFAT);
+ return STATUS_UNSUCCESSFUL;
+ }
+ /* clear the new directory cluster if not moving */
+ if (MoveContext == NULL)
+ {
+ RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
+ /* create '.' and '..' */
+ RtlCopyMemory(&pFatEntry[0].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
+ RtlCopyMemory(pFatEntry[0].ShortName, ". ", 11);
+ RtlCopyMemory(&pFatEntry[1].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
+ RtlCopyMemory(pFatEntry[1].ShortName, ".. ", 11);
+ }
+
pFatEntry[1].FirstCluster = ParentFcb->entry.Fat.FirstCluster;
pFatEntry[1].FirstClusterHigh = ParentFcb->entry.Fat.FirstClusterHigh;
if (vfatFCBIsRoot(ParentFcb))
IN PVFATFCB* Fcb,
IN PVFATFCB ParentFcb,
IN ULONG RequestedOptions,
- IN UCHAR ReqAttr)
+ IN UCHAR ReqAttr,
+ IN PVFAT_MOVE_CONTEXT MoveContext)
{
PVOID Context = NULL;
LARGE_INTEGER SystemTime, FileOffset;
DirContext.ShortNameU.MaximumLength = 0;
RtlZeroMemory(&DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
memset(DirContext.DirEntry.FatX.Filename, 0xff, 42);
- DirContext.DirEntry.FatX.FirstCluster = 0;
+ /* Use cluster, if moving */
+ if (MoveContext != NULL)
+ {
+ DirContext.DirEntry.FatX.FirstCluster = MoveContext->FirstCluster;
+ }
+ else
+ {
+ DirContext.DirEntry.FatX.FirstCluster = 0;
+ }
DirContext.DirEntry.FatX.FileSize = 0;
/* set file name */
DirContext.DirEntry.FatX.UpdateTime = DirContext.DirEntry.FatX.CreationTime;
DirContext.DirEntry.FatX.AccessDate = DirContext.DirEntry.FatX.CreationDate;
DirContext.DirEntry.FatX.AccessTime = DirContext.DirEntry.FatX.CreationTime;
+ /* If it's moving, preserve creation time and file size */
+ if (MoveContext != NULL)
+ {
+ DirContext.DirEntry.FatX.CreationDate = MoveContext->CreationDate;
+ DirContext.DirEntry.FatX.CreationTime = MoveContext->CreationTime;
+ DirContext.DirEntry.FatX.FileSize = MoveContext->FileSize;
+ }
/* add entry into parent directory */
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = Index * sizeof(FATX_DIR_ENTRY);
- CcPinRead(ParentFcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY),
- TRUE, &Context, (PVOID*)&pFatXDirEntry);
+ if (!CcPinRead(ParentFcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY),
+ TRUE, &Context, (PVOID*)&pFatXDirEntry))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
RtlCopyMemory(pFatXDirEntry, &DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
- /* FIXME: check status */
- vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);
+ if (MoveContext != NULL)
+ {
+ /* We're modifying an existing FCB - likely rename/move */
+ /* FIXME: check status */
+ vfatUpdateFCB(DeviceExt, *Fcb, &DirContext.LongNameU, &DirContext.ShortNameU, ParentFcb);
+ (*Fcb)->dirIndex = DirContext.DirIndex;
+ (*Fcb)->startIndex = DirContext.StartIndex;
+ }
+ else
+ {
+ /* FIXME: check status */
+ vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb);
+ }
DPRINT("addentry ok\n");
return STATUS_SUCCESS;
IN PVFATFCB *Fcb,
IN PVFATFCB ParentFcb,
IN ULONG RequestedOptions,
- IN UCHAR ReqAttr)
+ IN UCHAR ReqAttr,
+ IN PVFAT_MOVE_CONTEXT MoveContext)
{
if (DeviceExt->Flags & VCB_IS_FATX)
- return FATXAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr);
+ return FATXAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr, MoveContext);
else
- return FATAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr);
+ return FATAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr, MoveContext);
}
/*
static NTSTATUS
FATDelEntry(
IN PDEVICE_EXTENSION DeviceExt,
- IN PVFATFCB pFcb)
+ IN PVFATFCB pFcb,
+ OUT PVFAT_MOVE_CONTEXT MoveContext)
{
ULONG CurrentCluster = 0, NextCluster, i;
PVOID Context = NULL;
ASSERT(pFcb->parentFcb);
DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
- DPRINT("delete entry: %d to %d\n", pFcb->startIndex, pFcb->dirIndex);
+ DPRINT("delete entry: %u to %u\n", pFcb->startIndex, pFcb->dirIndex);
Offset.u.HighPart = 0;
for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++)
{
CcUnpinData(Context);
}
Offset.u.LowPart = (i * sizeof(FAT_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
- CcPinRead(pFcb->parentFcb->FileObject, &Offset, sizeof(FAT_DIR_ENTRY), TRUE,
- &Context, (PVOID*)&pDirEntry);
+ if (!CcPinRead(pFcb->parentFcb->FileObject, &Offset, sizeof(FAT_DIR_ENTRY), TRUE,
+ &Context, (PVOID*)&pDirEntry))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
}
pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))].Filename[0] = 0xe5;
if (i == pFcb->dirIndex)
CcUnpinData(Context);
}
- while (CurrentCluster && CurrentCluster != 0xffffffff)
+ /* In case of moving, don't delete data */
+ if (MoveContext != NULL)
{
- GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
- /* FIXME: check status */
- WriteCluster(DeviceExt, CurrentCluster, 0);
- CurrentCluster = NextCluster;
+ pDirEntry = &pDirEntry[pFcb->dirIndex % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))];
+ MoveContext->FirstCluster = CurrentCluster;
+ MoveContext->FileSize = pDirEntry->FileSize;
+ MoveContext->CreationTime = pDirEntry->CreationTime;
+ MoveContext->CreationDate = pDirEntry->CreationDate;
}
+ else
+ {
+ while (CurrentCluster && CurrentCluster != 0xffffffff)
+ {
+ GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
+ /* FIXME: check status */
+ WriteCluster(DeviceExt, CurrentCluster, 0);
+ CurrentCluster = NextCluster;
+ }
+ }
+
return STATUS_SUCCESS;
}
static NTSTATUS
FATXDelEntry(
IN PDEVICE_EXTENSION DeviceExt,
- IN PVFATFCB pFcb)
+ IN PVFATFCB pFcb,
+ OUT PVFAT_MOVE_CONTEXT MoveContext)
{
ULONG CurrentCluster = 0, NextCluster;
PVOID Context = NULL;
StartIndex = pFcb->startIndex;
DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
- DPRINT("delete entry: %d\n", StartIndex);
+ DPRINT("delete entry: %u\n", StartIndex);
Offset.u.HighPart = 0;
Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
if (!CcPinRead(pFcb->parentFcb->FileObject, &Offset, sizeof(FATX_DIR_ENTRY), TRUE,
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
- while (CurrentCluster && CurrentCluster != 0xffffffff)
+ /* In case of moving, don't delete data */
+ if (MoveContext != NULL)
{
- GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
- /* FIXME: check status */
- WriteCluster(DeviceExt, CurrentCluster, 0);
- CurrentCluster = NextCluster;
+ MoveContext->FirstCluster = CurrentCluster;
+ MoveContext->FileSize = pDirEntry->FileSize;
+ MoveContext->CreationTime = pDirEntry->CreationTime;
+ MoveContext->CreationDate = pDirEntry->CreationDate;
}
+ else
+ {
+ while (CurrentCluster && CurrentCluster != 0xffffffff)
+ {
+ GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
+ /* FIXME: check status */
+ WriteCluster(DeviceExt, CurrentCluster, 0);
+ CurrentCluster = NextCluster;
+ }
+ }
+
return STATUS_SUCCESS;
}
NTSTATUS
VfatDelEntry(
IN PDEVICE_EXTENSION DeviceExt,
- IN PVFATFCB pFcb)
+ IN PVFATFCB pFcb,
+ OUT PVFAT_MOVE_CONTEXT MoveContext)
{
if (DeviceExt->Flags & VCB_IS_FATX)
- return FATXDelEntry(DeviceExt, pFcb);
+ return FATXDelEntry(DeviceExt, pFcb, MoveContext);
else
- return FATDelEntry(DeviceExt, pFcb);
+ return FATDelEntry(DeviceExt, pFcb, MoveContext);
+}
+
+/*
+ * move an existing FAT entry
+ */
+NTSTATUS
+VfatMoveEntry(
+ IN PDEVICE_EXTENSION DeviceExt,
+ IN PVFATFCB pFcb,
+ IN PUNICODE_STRING FileName,
+ IN PVFATFCB ParentFcb)
+{
+ NTSTATUS Status;
+ PVFATFCB OldParent;
+ VFAT_MOVE_CONTEXT MoveContext;
+
+ DPRINT("VfatMoveEntry(%p, %p, %wZ, %p)\n", DeviceExt, pFcb, FileName, ParentFcb);
+
+ /* Delete old entry while keeping data */
+ Status = VfatDelEntry(DeviceExt, pFcb, &MoveContext);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ OldParent = pFcb->parentFcb;
+ CcPurgeCacheSection(&OldParent->SectionObjectPointers, NULL, 0, FALSE);
+
+ /* Add our new entry with our cluster */
+ Status = VfatAddEntry(DeviceExt,
+ FileName,
+ &pFcb,
+ ParentFcb,
+ (vfatFCBIsDirectory(pFcb) ? FILE_DIRECTORY_FILE : 0),
+ *pFcb->Attributes,
+ &MoveContext);
+
+ CcPurgeCacheSection(&pFcb->parentFcb->SectionObjectPointers, NULL, 0, FALSE);
+
+ return Status;
}
/* EOF */