#define TAG_FCB 'BCFV'
+#ifdef KDBG
+extern UNICODE_STRING DebugFile;
+#endif
+
/* -------------------------------------------------------- PUBLICS */
static
KeBugCheckEx(FAT_FILE_SYSTEM, (ULONG_PTR)Fcb, (ULONG_PTR)NameU, 0, 0);
}
+ Fcb->RFCB.NodeTypeCode = NODE_TYPE_FCB;
+ Fcb->RFCB.NodeByteSize = sizeof(VFATFCB);
+
Fcb->PathNameU.Length = 0;
Fcb->PathNameU.Buffer = Fcb->PathNameBuffer;
Fcb->PathNameU.MaximumLength = PathNameBufferLength;
}
RtlZeroMemory(rcFCB, sizeof(VFATFCB));
vfatInitFcb(rcFCB, pFileNameU);
- if (pVCB->Flags & VCB_IS_FATX)
- {
- rcFCB->Flags |= FCB_IS_FATX_ENTRY;
+ if (vfatVolumeIsFatX(pVCB))
rcFCB->Attributes = &rcFCB->entry.FatX.Attrib;
- }
else
rcFCB->Attributes = &rcFCB->entry.Fat.Attrib;
rcFCB->Hash.Hash = vfatNameHash(0, &rcFCB->PathNameU);
rcFCB->RFCB.PagingIoResource = &rcFCB->PagingIoResource;
rcFCB->RFCB.Resource = &rcFCB->MainResource;
rcFCB->RFCB.IsFastIoPossible = FastIoIsNotPossible;
+ InitializeListHead(&rcFCB->ParentListHead);
return rcFCB;
}
vfatDestroyFCB(
PVFATFCB pFCB)
{
+#ifdef KDBG
+ if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL))
+ {
+ DPRINT1("Destroying: %p (%wZ) %d\n", pFCB, &pFCB->PathNameU, pFCB->RefCount);
+ }
+#endif
+
FsRtlUninitializeFileLock(&pFCB->FileLock);
+ if (!vfatFCBIsRoot(pFCB) &&
+ !BooleanFlagOn(pFCB->Flags, FCB_IS_FAT) && !BooleanFlagOn(pFCB->Flags, FCB_IS_VOLUME))
+ {
+ RemoveEntryList(&pFCB->ParentListEntry);
+ }
ExFreePool(pFCB->PathNameBuffer);
ExDeleteResourceLite(&pFCB->PagingIoResource);
ExDeleteResourceLite(&pFCB->MainResource);
+ ASSERT(IsListEmpty(&pFCB->ParentListHead));
ExFreeToNPagedLookasideList(&VfatGlobalData->FcbLookasideList, pFCB);
}
BOOLEAN
-vfatFCBIsDirectory(
+vfatFCBIsRoot(
PVFATFCB FCB)
{
- return ((*FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
+ return FCB->PathNameU.Length == sizeof(WCHAR) && FCB->PathNameU.Buffer[0] == L'\\' ? TRUE : FALSE;
}
-BOOLEAN
-vfatFCBIsRoot(
- PVFATFCB FCB)
+VOID
+#ifndef KDBG
+vfatGrabFCB(
+#else
+_vfatGrabFCB(
+#endif
+ PDEVICE_EXTENSION pVCB,
+ PVFATFCB pFCB
+#ifdef KDBG
+ ,
+ PCSTR File,
+ ULONG Line,
+ PCSTR Func
+#endif
+)
{
- return FCB->PathNameU.Length == sizeof(WCHAR) && FCB->PathNameU.Buffer[0] == L'\\' ? TRUE : FALSE;
+#ifdef KDBG
+ if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL))
+ {
+ DPRINT1("Inc ref count (%d, oc: %d) for: %p (%wZ) at: %s(%d) %s\n", pFCB->RefCount, pFCB->OpenHandleCount, pFCB, &pFCB->PathNameU, File, Line, Func);
+ }
+#endif
+
+ ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
+
+ ASSERT(pFCB != pVCB->VolumeFcb);
+ ASSERT(pFCB->RefCount > 0);
+ ++pFCB->RefCount;
}
VOID
+#ifndef KDBG
vfatReleaseFCB(
+#else
+_vfatReleaseFCB(
+#endif
PDEVICE_EXTENSION pVCB,
- PVFATFCB pFCB)
+ PVFATFCB pFCB
+#ifdef KDBG
+ ,
+ PCSTR File,
+ ULONG Line,
+ PCSTR Func
+#endif
+)
{
PVFATFCB tmpFcb;
+#ifdef KDBG
+ if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL))
+ {
+ DPRINT1("Dec ref count (%d, oc: %d) for: %p (%wZ) at: %s(%d) %s\n", pFCB->RefCount, pFCB->OpenHandleCount, pFCB, &pFCB->PathNameU, File, Line, Func);
+ }
+#else
DPRINT("releasing FCB at %p: %wZ, refCount:%d\n",
pFCB, &pFCB->PathNameU, pFCB->RefCount);
+#endif
+
+ ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
while (pFCB)
{
- pFCB->RefCount--;
- if (pFCB->RefCount == 0)
+ ULONG RefCount;
+
+ ASSERT(pFCB != pVCB->VolumeFcb);
+ ASSERT(pFCB->RefCount > 0);
+ RefCount = --pFCB->RefCount;
+
+ if (RefCount == 1 && BooleanFlagOn(pFCB->Flags, FCB_CACHE_INITIALIZED))
+ {
+ PFILE_OBJECT tmpFileObject;
+ tmpFileObject = pFCB->FileObject;
+
+ pFCB->FileObject = NULL;
+ CcUninitializeCacheMap(tmpFileObject, NULL, NULL);
+ ClearFlag(pFCB->Flags, FCB_CACHE_INITIALIZED);
+ ObDereferenceObject(tmpFileObject);
+ }
+
+ if (RefCount == 0)
{
ASSERT(pFCB->OpenHandleCount == 0);
tmpFcb = pFCB->parentFcb;
ULONG Index;
ULONG ShortIndex;
+ ASSERT(pFCB->Hash.Hash == vfatNameHash(0, &pFCB->PathNameU));
Index = pFCB->Hash.Hash % pVCB->HashTableSize;
ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
}
if (pFCB->parentFcb)
{
- pFCB->parentFcb->RefCount++;
+ vfatGrabFCB(pVCB, pFCB->parentFcb);
+ }
+}
+
+static
+VOID
+vfatInitFCBFromDirEntry(
+ PDEVICE_EXTENSION Vcb,
+ PVFATFCB Fcb,
+ PVFAT_DIRENTRY_CONTEXT DirContext)
+{
+ ULONG Size;
+
+ RtlCopyMemory(&Fcb->entry, &DirContext->DirEntry, sizeof (DIR_ENTRY));
+ RtlCopyUnicodeString(&Fcb->ShortNameU, &DirContext->ShortNameU);
+ Fcb->Hash.Hash = vfatNameHash(0, &Fcb->PathNameU);
+ if (vfatVolumeIsFatX(Vcb))
+ {
+ Fcb->ShortHash.Hash = Fcb->Hash.Hash;
+ }
+ else
+ {
+ Fcb->ShortHash.Hash = vfatNameHash(0, &Fcb->DirNameU);
+ Fcb->ShortHash.Hash = vfatNameHash(Fcb->ShortHash.Hash, &Fcb->ShortNameU);
+ }
+
+ if (vfatFCBIsDirectory(Fcb))
+ {
+ ULONG FirstCluster, CurrentCluster;
+ NTSTATUS Status = STATUS_SUCCESS;
+ Size = 0;
+ FirstCluster = vfatDirEntryGetFirstCluster(Vcb, &Fcb->entry);
+ if (FirstCluster == 1)
+ {
+ Size = Vcb->FatInfo.rootDirectorySectors * Vcb->FatInfo.BytesPerSector;
+ }
+ else if (FirstCluster != 0)
+ {
+ CurrentCluster = FirstCluster;
+ while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
+ {
+ Size += Vcb->FatInfo.BytesPerCluster;
+ Status = NextCluster(Vcb, FirstCluster, &CurrentCluster, FALSE);
+ }
+ }
+ }
+ else if (vfatVolumeIsFatX(Vcb))
+ {
+ Size = Fcb->entry.FatX.FileSize;
+ }
+ else
+ {
+ Size = Fcb->entry.Fat.FileSize;
+ }
+ Fcb->dirIndex = DirContext->DirIndex;
+ Fcb->startIndex = DirContext->StartIndex;
+ if (vfatVolumeIsFatX(Vcb) && !vfatFCBIsRoot(Fcb))
+ {
+ ASSERT(DirContext->DirIndex >= 2 && DirContext->StartIndex >= 2);
+ Fcb->dirIndex = DirContext->DirIndex-2;
+ Fcb->startIndex = DirContext->StartIndex-2;
}
+ Fcb->RFCB.FileSize.QuadPart = Size;
+ Fcb->RFCB.ValidDataLength.QuadPart = Size;
+ Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP_64(Size, Vcb->FatInfo.BytesPerCluster);
}
NTSTATUS
-vfatUpdateFCB(
+vfatSetFCBNewDirName(
PDEVICE_EXTENSION pVCB,
PVFATFCB Fcb,
- PUNICODE_STRING LongName,
- PUNICODE_STRING ShortName,
PVFATFCB ParentFcb)
{
NTSTATUS Status;
- PVFATFCB OldParent;
+ UNICODE_STRING NewNameU;
- DPRINT("vfatUpdateFCB(%p, %p, %wZ, %wZ, %p)\n", pVCB, Fcb, LongName, ShortName, ParentFcb);
+ /* Get full path name */
+ Status = vfatMakeFullName(ParentFcb, &Fcb->LongNameU, &Fcb->ShortNameU, &NewNameU);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
/* Delete old name */
if (Fcb->PathNameBuffer)
{
ExFreePoolWithTag(Fcb->PathNameBuffer, TAG_FCB);
}
+ Fcb->PathNameU = NewNameU;
/* Delete from table */
vfatDelFCBFromTable(pVCB, Fcb);
- /* Get full path name */
- Status = vfatMakeFullName(ParentFcb, LongName, ShortName, &Fcb->PathNameU);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
/* Split it properly */
Fcb->PathNameBuffer = Fcb->PathNameU.Buffer;
Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
-
- /* Copy short name */
- RtlCopyUnicodeString(&Fcb->ShortNameU, ShortName);
-
- /* Recompute hashes */
Fcb->Hash.Hash = vfatNameHash(0, &Fcb->PathNameU);
- if (pVCB->Flags & VCB_IS_FATX)
+ if (vfatVolumeIsFatX(pVCB))
{
Fcb->ShortHash.Hash = Fcb->Hash.Hash;
}
Fcb->ShortHash.Hash = vfatNameHash(Fcb->ShortHash.Hash, &Fcb->ShortNameU);
}
- /* Set parent */
+ vfatAddFCBToTable(pVCB, Fcb);
+ vfatReleaseFCB(pVCB, ParentFcb);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+vfatUpdateFCB(
+ PDEVICE_EXTENSION pVCB,
+ PVFATFCB Fcb,
+ PVFAT_DIRENTRY_CONTEXT DirContext,
+ PVFATFCB ParentFcb)
+{
+ NTSTATUS Status;
+ PVFATFCB OldParent;
+
+ DPRINT("vfatUpdateFCB(%p, %p, %p, %p)\n", pVCB, Fcb, DirContext, ParentFcb);
+
+ /* Get full path name */
+ Status = vfatMakeFullName(ParentFcb, &DirContext->LongNameU, &DirContext->ShortNameU, &Fcb->PathNameU);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Delete old name */
+ if (Fcb->PathNameBuffer)
+ {
+ ExFreePoolWithTag(Fcb->PathNameBuffer, TAG_FCB);
+ }
+
+ /* Delete from table */
+ vfatDelFCBFromTable(pVCB, Fcb);
+
+ /* Split it properly */
+ Fcb->PathNameBuffer = Fcb->PathNameU.Buffer;
+ Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
+ vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
+
+ /* Save old parent */
OldParent = Fcb->parentFcb;
- Fcb->parentFcb = ParentFcb;
+ RemoveEntryList(&Fcb->ParentListEntry);
+
+ /* Reinit FCB */
+ vfatInitFCBFromDirEntry(pVCB, Fcb, DirContext);
- /* Add to the table */
+ if (vfatFCBIsDirectory(Fcb))
+ {
+ CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);
+ }
+ Fcb->parentFcb = ParentFcb;
+ InsertTailList(&ParentFcb->ParentListHead, &Fcb->ParentListEntry);
vfatAddFCBToTable(pVCB, Fcb);
- /* If we moved accross directories, dereferenced our old parent
- * We also derefence in case we're just renaming since AddFCBToTable references it
+ /* If we moved across directories, dereference our old parent
+ * We also dereference in case we're just renaming since AddFCBToTable references it
*/
vfatReleaseFCB(pVCB, OldParent);
- /* In case we were moving accross directories, reset caching on old parent */
- //if (OldParent != ParentFcb)
- //{
- // CcUninitializeCacheMap(OldParent->FileObject, NULL, NULL);
- //}
-
return STATUS_SUCCESS;
}
DPRINT("'%wZ'\n", PathNameU);
+ ASSERT(PathNameU->Length >= sizeof(WCHAR) && PathNameU->Buffer[0] == L'\\');
Hash = vfatNameHash(0, PathNameU);
entry = pVCB->FcbHashTable[Hash % pVCB->HashTableSize];
DPRINT("'%wZ' '%wZ'\n", &FileNameU, FcbNameU);
if (RtlEqualUnicodeString(&FileNameU, FcbNameU, TRUE))
{
- rcFCB->RefCount++;
+ vfatGrabFCB(pVCB, rcFCB);
return rcFCB;
}
}
return NULL;
}
-static
-NTSTATUS
-vfatFCBInitializeCacheFromVolume(
- PVCB vcb,
- PVFATFCB fcb)
-{
- PFILE_OBJECT fileObject;
- PVFATCCB newCCB;
- NTSTATUS status;
-
- fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
-
- 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;
- fcb->FileObject = fileObject;
- fcb->RefCount++;
-
- _SEH2_TRY
- {
- CcInitializeCacheMap(fileObject,
- (PCC_FILE_SIZES)(&fcb->RFCB.AllocationSize),
- TRUE,
- &VfatGlobalData->CacheMgrCallbacks,
- fcb);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- status = _SEH2_GetExceptionCode();
- fcb->RefCount--;
- fcb->FileObject = NULL;
- ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, newCCB);
- ObDereferenceObject(fileObject);
- return status;
- }
- _SEH2_END;
-
- fcb->Flags |= FCB_CACHE_INITIALIZED;
- return STATUS_SUCCESS;
-}
-
PVFATFCB
vfatMakeRootFCB(
PDEVICE_EXTENSION pVCB)
UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\");
FCB = vfatNewFCB(pVCB, &NameU);
- if (FCB->Flags & FCB_IS_FATX_ENTRY)
+ if (vfatVolumeIsFatX(pVCB))
{
memset(FCB->entry.FatX.Filename, ' ', 42);
FCB->entry.FatX.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
PVFATFCB *fileFCB)
{
PVFATFCB rcFCB;
- ULONG Size;
UNICODE_STRING NameU;
NTSTATUS Status;
}
rcFCB = vfatNewFCB(vcb, &NameU);
- RtlCopyMemory(&rcFCB->entry, &DirContext->DirEntry, sizeof (DIR_ENTRY));
- RtlCopyUnicodeString(&rcFCB->ShortNameU, &DirContext->ShortNameU);
- if (vcb->Flags & VCB_IS_FATX)
- {
- rcFCB->ShortHash.Hash = rcFCB->Hash.Hash;
- }
- else
- {
- rcFCB->ShortHash.Hash = vfatNameHash(0, &rcFCB->DirNameU);
- rcFCB->ShortHash.Hash = vfatNameHash(rcFCB->ShortHash.Hash, &rcFCB->ShortNameU);
- }
+ vfatInitFCBFromDirEntry(vcb, rcFCB, DirContext);
- if (vfatFCBIsDirectory(rcFCB))
- {
- ULONG FirstCluster, CurrentCluster;
- NTSTATUS Status = STATUS_SUCCESS;
- Size = 0;
- FirstCluster = vfatDirEntryGetFirstCluster(vcb, &rcFCB->entry);
- if (FirstCluster == 1)
- {
- Size = vcb->FatInfo.rootDirectorySectors * vcb->FatInfo.BytesPerSector;
- }
- else if (FirstCluster != 0)
- {
- CurrentCluster = FirstCluster;
- while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
- {
- Size += vcb->FatInfo.BytesPerCluster;
- Status = NextCluster(vcb, FirstCluster, &CurrentCluster, FALSE);
- }
- }
- }
- else if (rcFCB->Flags & FCB_IS_FATX_ENTRY)
- {
- Size = rcFCB->entry.FatX.FileSize;
- }
- else
- {
- Size = rcFCB->entry.Fat.FileSize;
- }
- rcFCB->dirIndex = DirContext->DirIndex;
- rcFCB->startIndex = DirContext->StartIndex;
- if ((rcFCB->Flags & FCB_IS_FATX_ENTRY) && !vfatFCBIsRoot(directoryFCB))
- {
- ASSERT(DirContext->DirIndex >= 2 && DirContext->StartIndex >= 2);
- rcFCB->dirIndex = DirContext->DirIndex-2;
- rcFCB->startIndex = DirContext->StartIndex-2;
- }
- rcFCB->RFCB.FileSize.QuadPart = Size;
- rcFCB->RFCB.ValidDataLength.QuadPart = Size;
- rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->FatInfo.BytesPerCluster);
- rcFCB->RefCount++;
- if (vfatFCBIsDirectory(rcFCB))
- {
- vfatFCBInitializeCacheFromVolume(vcb, rcFCB);
- }
+ rcFCB->RefCount = 1;
rcFCB->parentFcb = directoryFCB;
+ InsertTailList(&directoryFCB->ParentListHead, &rcFCB->ParentListEntry);
vfatAddFCBToTable(vcb, rcFCB);
*fileFCB = rcFCB;
- ExFreePool(NameU.Buffer);
+ ExFreePoolWithTag(NameU.Buffer, TAG_FCB);
return STATUS_SUCCESS;
}
UNREFERENCED_PARAMETER(vcb);
+#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)
{
fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
fileObject->FsContext = fcb;
fileObject->FsContext2 = newCCB;
+ fileObject->Vpb = vcb->IoVPB;
DPRINT("file open: fcb:%p PathName:%wZ\n", fcb, &fcb->PathNameU);
+#ifdef KDBG
+ fcb->Flags &= ~FCB_CLEANED_UP;
+ fcb->Flags &= ~FCB_CLOSED;
+#endif
+
return STATUS_SUCCESS;
}
WCHAR ShortNameBuffer[13];
BOOLEAN FoundLong = FALSE;
BOOLEAN FoundShort = FALSE;
+ BOOLEAN IsFatX = vfatVolumeIsFatX(pDeviceExt);
ASSERT(pDeviceExt);
ASSERT(pDirectoryFCB);
DirContext.ShortNameU.Buffer = ShortNameBuffer;
DirContext.ShortNameU.Length = 0;
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
+ DirContext.DeviceExt = pDeviceExt;
while (TRUE)
{
- status = pDeviceExt->GetNextDirEntry(&Context,
+ status = VfatGetNextDirEntry(pDeviceExt,
+ &Context,
&Page,
pDirectoryFCB,
&DirContext,
DPRINT(" Index:%u longName:%wZ\n",
DirContext.DirIndex, &DirContext.LongNameU);
- if (!ENTRY_VOLUME(pDeviceExt, &DirContext.DirEntry))
+ if (!ENTRY_VOLUME(IsFatX, &DirContext.DirEntry))
{
+ if (DirContext.LongNameU.Length == 0 ||
+ DirContext.ShortNameU.Length == 0)
+ {
+ DPRINT1("WARNING: File system corruption detected. You may need to run a disk repair utility.\n");
+ if (VfatGlobalData->Flags & VFAT_BREAK_ON_CORRUPTION)
+ {
+ ASSERT(DirContext.LongNameU.Length != 0 &&
+ DirContext.ShortNameU.Length != 0);
+ }
+ DirContext.DirIndex++;
+ continue;
+ }
FoundLong = RtlEqualUnicodeString(FileToFindU, &DirContext.LongNameU, TRUE);
if (FoundLong == FALSE)
{
DPRINT("vfatGetFCBForFile (%p,%p,%p,%wZ)\n",
pVCB, pParentFCB, pFCB, pFileNameU);
- FileNameU.Buffer = NameBuffer;
- FileNameU.MaximumLength = sizeof(NameBuffer);
- RtlCopyUnicodeString(&FileNameU, pFileNameU);
+ RtlInitEmptyUnicodeString(&FileNameU, NameBuffer, sizeof(NameBuffer));
parentFCB = *pParentFCB;
if (parentFCB == NULL)
{
+ /* Passed-in name is the full name */
+ RtlCopyUnicodeString(&FileNameU, pFileNameU);
+
// Trivial case, open of the root directory on volume
if (RtlEqualUnicodeString(&FileNameU, &RootNameU, FALSE))
{
{
*pFCB = FCB;
*pParentFCB = FCB->parentFcb;
- (*pParentFCB)->RefCount++;
+ vfatGrabFCB(pVCB, *pParentFCB);
return STATUS_SUCCESS;
}
}
else
{
+ /* Make absolute path */
+ RtlCopyUnicodeString(&FileNameU, &parentFCB->PathNameU);
+ curr = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
+ if (*curr != L'\\')
+ {
+ RtlAppendUnicodeToString(&FileNameU, L"\\");
+ curr++;
+ }
+ ASSERT(*curr == L'\\');
+ RtlAppendUnicodeStringToString(&FileNameU, pFileNameU);
+
FCB = parentFCB;
parentFCB = NULL;
- prev = curr = FileNameU.Buffer - 1;
+ prev = curr;
last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
}
if (parentFCB)
{
vfatReleaseFCB(pVCB, parentFCB);
- parentFCB = 0;
+ parentFCB = NULL;
}
// fail if element in FCB is not a directory
if (!vfatFCBIsDirectory(FCB))
if (FileNameU.Length + parentFCB->LongNameU.Length - Length > FileNameU.MaximumLength)
{
vfatReleaseFCB(pVCB, parentFCB);
+ *pParentFCB = NULL;
+ *pFCB = NULL;
return STATUS_OBJECT_NAME_INVALID;
}
RtlMoveMemory(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr,