#define NDEBUG
#include <debug.h>
+#ifdef KDBG
+extern UNICODE_STRING DebugFile;
+#endif
+
+NTSTATUS
+vfatFCBInitializeCacheFromVolume(
+ PVCB vcb,
+ PVFATFCB fcb)
+{
+ PFILE_OBJECT fileObject;
+ PVFATCCB newCCB;
+ NTSTATUS status;
+ BOOLEAN Acquired;
+
+ /* Don't re-initialize if already done */
+ if (BooleanFlagOn(fcb->Flags, FCB_CACHE_INITIALIZED))
+ {
+ return STATUS_SUCCESS;
+ }
+
+ ASSERT(vfatFCBIsDirectory(fcb));
+
+ Acquired = FALSE;
+ if (!ExIsResourceAcquiredExclusive(&vcb->DirResource))
+ {
+ ExAcquireResourceExclusiveLite(&vcb->DirResource, TRUE);
+ Acquired = TRUE;
+ }
+
+ fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
+
+#ifdef KDBG
+ if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &fcb->LongNameU, FALSE, NULL))
+ {
+ DPRINT1("Attaching %p to %p (%d)\n", fcb, fileObject, fcb->RefCount);
+ }
+#endif
+
+ newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
+ if (newCCB == NULL)
+ {
+ ObDereferenceObject(fileObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(newCCB, sizeof (VFATCCB));
+
+ fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
+ fileObject->FsContext = fcb;
+ fileObject->FsContext2 = newCCB;
+ fileObject->Vpb = vcb->IoVPB;
+ fcb->FileObject = fileObject;
+
+ _SEH2_TRY
+ {
+ CcInitializeCacheMap(fileObject,
+ (PCC_FILE_SIZES)(&fcb->RFCB.AllocationSize),
+ TRUE,
+ &VfatGlobalData->CacheMgrCallbacks,
+ fcb);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ status = _SEH2_GetExceptionCode();
+ fcb->FileObject = NULL;
+ ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, newCCB);
+ ObDereferenceObject(fileObject);
+ return status;
+ }
+ _SEH2_END;
+
+ vfatGrabFCB(vcb, fcb);
+ SetFlag(fcb->Flags, FCB_CACHE_INITIALIZED);
+
+ if (Acquired)
+ {
+ ExReleaseResourceLite(&vcb->DirResource);
+ }
+
+ return STATUS_SUCCESS;
+}
+
/*
* update an existing FAT entry
*/
NTSTATUS
VfatUpdateEntry(
- IN PVFATFCB pFcb,
- IN BOOLEAN IsFatX)
+ IN PDEVICE_EXTENSION DeviceExt,
+ IN PVFATFCB pFcb)
{
PVOID Context;
PDIR_ENTRY PinEntry;
LARGE_INTEGER Offset;
ULONG SizeDirEntry;
ULONG dirIndex;
+ NTSTATUS Status;
ASSERT(pFcb);
- if (IsFatX)
+ if (vfatVolumeIsFatX(DeviceExt))
{
SizeDirEntry = sizeof(FATX_DIR_ENTRY);
dirIndex = pFcb->startIndex;
ASSERT(pFcb->parentFcb);
+ Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
Offset.u.HighPart = 0;
Offset.u.LowPart = dirIndex * SizeDirEntry;
_SEH2_TRY
DPRINT("vfatRenameEntry(%p, %p, %wZ, %d)\n", DeviceExt, pFcb, FileName, CaseChangeOnly);
+ Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
if (vfatVolumeIsFatX(DeviceExt))
{
VFAT_DIRENTRY_CONTEXT DirContext;
pDirEntry->FilenameLength = (unsigned char)NameA.Length;
/* Update FCB */
+ DirContext.DeviceExt = DeviceExt;
DirContext.ShortNameU.Length = 0;
DirContext.ShortNameU.MaximumLength = 0;
DirContext.ShortNameU.Buffer = NULL;
else
SizeDirEntry = sizeof(FAT_DIR_ENTRY);
+ Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pDirFcb);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
count = pDirFcb->RFCB.FileSize.u.LowPart / SizeDirEntry;
size = DeviceExt->FatInfo.BytesPerCluster / SizeDirEntry;
for (i = 0; i < count; i++, pFatEntry = (PDIR_ENTRY)((ULONG_PTR)pFatEntry + SizeDirEntry))
NameA.Length = 0;
NameA.MaximumLength = sizeof(aName);
+ DirContext.DeviceExt = DeviceExt;
DirContext.ShortNameU.Buffer = ShortNameBuffer;
DirContext.ShortNameU.Length = 0;
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
needTilde = TRUE;
needLong = TRUE;
RtlZeroMemory(&NameContext, sizeof(GENERATE_NAME_CONTEXT));
+ SearchContext.DeviceExt = DeviceExt;
SearchContext.LongNameU.Buffer = LongNameBuffer;
SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
SearchContext.ShortNameU.Buffer = ShortSearchName;
DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;
}
+ /* No need to init cache here, vfatFindDirSpace() will have done it for us */
+
i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FAT_DIR_ENTRY);
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FAT_DIR_ENTRY);
if (IsDirectory)
{
+ Status = vfatFCBInitializeCacheFromVolume(DeviceExt, (*Fcb));
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
FileOffset.QuadPart = 0;
_SEH2_TRY
{
DirContext.ShortNameU.Buffer = 0;
DirContext.ShortNameU.Length = 0;
DirContext.ShortNameU.MaximumLength = 0;
+ DirContext.DeviceExt = DeviceExt;
RtlZeroMemory(&DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
memset(DirContext.DirEntry.FatX.Filename, 0xff, 42);
/* Use cluster, if moving */
DirContext.DirEntry.FatX.FileSize = MoveContext->FileSize;
}
+ /* No need to init cache here, vfatFindDirSpace() will have done it for us */
+
/* add entry into parent directory */
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = Index * sizeof(FATX_DIR_ENTRY);
PVOID Context = NULL;
LARGE_INTEGER Offset;
PFAT_DIR_ENTRY pDirEntry = NULL;
+ NTSTATUS Status;
ASSERT(pFcb);
ASSERT(pFcb->parentFcb);
+ Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
DPRINT("delete entry: %u to %u\n", pFcb->startIndex, pFcb->dirIndex);
Offset.u.HighPart = 0;
LARGE_INTEGER Offset;
PFATX_DIR_ENTRY pDirEntry;
ULONG StartIndex;
+ NTSTATUS Status;
ASSERT(pFcb);
ASSERT(pFcb->parentFcb);
StartIndex = pFcb->startIndex;
+ Status = vfatFCBInitializeCacheFromVolume(DeviceExt, pFcb->parentFcb);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
DPRINT("delete entry: %u\n", StartIndex);
Offset.u.HighPart = 0;
return Status;
}
-extern BOOLEAN FATXIsDirectoryEmpty(PVFATFCB Fcb);
-extern BOOLEAN FATIsDirectoryEmpty(PVFATFCB Fcb);
+extern BOOLEAN FATXIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb);
+extern BOOLEAN FATIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb);
extern NTSTATUS FATGetNextDirEntry(PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First);
extern NTSTATUS FATXGetNextDirEntry(PVOID *pContext, PVOID *pPage, PVFATFCB pDirFcb, PVFAT_DIRENTRY_CONTEXT DirContext, BOOLEAN First);