📄 fcb.c
字号:
if (FCB == NULL)
{
FCB = vfatMakeRootFCB (pVCB);
}
return FCB;
}
NTSTATUS
vfatMakeFCBFromDirEntry(
PVCB vcb,
PVFATFCB directoryFCB,
PVFAT_DIRENTRY_CONTEXT DirContext,
PVFATFCB* fileFCB)
{
PVFATFCB rcFCB;
PWCHAR PathNameBuffer;
USHORT PathNameLength;
ULONG Size;
ULONG hash;
UNICODE_STRING NameU;
PathNameLength = directoryFCB->PathNameU.Length + max(DirContext->LongNameU.Length, DirContext->ShortNameU.Length);
if (!vfatFCBIsRoot (directoryFCB))
{
PathNameLength += sizeof(WCHAR);
}
if (PathNameLength > LONGNAME_MAX_LENGTH * sizeof(WCHAR))
{
return STATUS_OBJECT_NAME_INVALID;
}
PathNameBuffer = ExAllocatePool(NonPagedPool, PathNameLength + sizeof(WCHAR));
if (!PathNameBuffer)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
NameU.Buffer = PathNameBuffer;
NameU.Length = 0;
NameU.MaximumLength = PathNameLength;
RtlCopyUnicodeString(&NameU, &directoryFCB->PathNameU);
if (!vfatFCBIsRoot (directoryFCB))
{
RtlAppendUnicodeToString(&NameU, L"\\");
}
hash = vfatNameHash(0, &NameU);
if (DirContext->LongNameU.Length > 0)
{
RtlAppendUnicodeStringToString(&NameU, &DirContext->LongNameU);
}
else
{
RtlAppendUnicodeStringToString(&NameU, &DirContext->ShortNameU);
}
NameU.Buffer[NameU.Length / sizeof(WCHAR)] = 0;
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(hash, &rcFCB->ShortNameU);
}
if (vfatFCBIsDirectory(rcFCB))
{
ULONG FirstCluster, CurrentCluster;
NTSTATUS Status;
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)
{
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->parentFcb = directoryFCB;
vfatAddFCBToTable (vcb, rcFCB);
*fileFCB = rcFCB;
ExFreePool(PathNameBuffer);
return STATUS_SUCCESS;
}
NTSTATUS
vfatAttachFCBToFileObject (
PDEVICE_EXTENSION vcb,
PVFATFCB fcb,
PFILE_OBJECT fileObject)
{
PVFATCCB newCCB;
newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
if (newCCB == NULL)
{
CHECKPOINT;
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory (newCCB, sizeof (VFATCCB));
fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
fileObject->FsContext = fcb;
fileObject->FsContext2 = newCCB;
DPRINT ("file open: fcb:%x PathName:%wZ\n", fcb, &fcb->PathNameU);
return STATUS_SUCCESS;
}
NTSTATUS
vfatDirFindFile (
PDEVICE_EXTENSION pDeviceExt,
PVFATFCB pDirectoryFCB,
PUNICODE_STRING FileToFindU,
PVFATFCB * pFoundFCB)
{
NTSTATUS status;
PVOID Context = NULL;
PVOID Page = NULL;
BOOLEAN First = TRUE;
VFAT_DIRENTRY_CONTEXT DirContext;
/* This buffer must have a size of 260 characters, because
vfatMakeFCBFromDirEntry can copy 20 name entries with 13 characters. */
WCHAR LongNameBuffer[260];
WCHAR ShortNameBuffer[13];
BOOLEAN FoundLong = FALSE;
BOOLEAN FoundShort = FALSE;
ASSERT(pDeviceExt);
ASSERT(pDirectoryFCB);
ASSERT(FileToFindU);
DPRINT ("vfatDirFindFile(VCB:%08x, dirFCB:%08x, File:%wZ)\n",
pDeviceExt,
pDirectoryFCB,
FileToFindU);
DPRINT ("Dir Path:%wZ\n", &pDirectoryFCB->PathNameU);
DirContext.DirIndex = 0;
DirContext.LongNameU.Buffer = LongNameBuffer;
DirContext.LongNameU.Length = 0;
DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
DirContext.ShortNameU.Buffer = ShortNameBuffer;
DirContext.ShortNameU.Length = 0;
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
while (TRUE)
{
status = pDeviceExt->GetNextDirEntry(&Context,
&Page,
pDirectoryFCB,
&DirContext,
First);
First = FALSE;
if (status == STATUS_NO_MORE_ENTRIES)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
if (!NT_SUCCESS(status))
{
return status;
}
DPRINT (" Index:%d longName:%wZ\n",
DirContext.DirIndex,
&DirContext.LongNameU);
DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;
DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
if (!ENTRY_VOLUME(pDeviceExt, &DirContext.DirEntry))
{
FoundLong = RtlEqualUnicodeString(FileToFindU, &DirContext.LongNameU, TRUE);
if (FoundLong == FALSE)
{
FoundShort = RtlEqualUnicodeString(FileToFindU, &DirContext.ShortNameU, TRUE);
}
if (FoundLong || FoundShort)
{
status = vfatMakeFCBFromDirEntry (pDeviceExt,
pDirectoryFCB,
&DirContext,
pFoundFCB);
CcUnpinData(Context);
return status;
}
}
DirContext.DirIndex++;
}
return STATUS_OBJECT_NAME_NOT_FOUND;
}
NTSTATUS
vfatGetFCBForFile (
PDEVICE_EXTENSION pVCB,
PVFATFCB *pParentFCB,
PVFATFCB *pFCB,
PUNICODE_STRING pFileNameU)
{
NTSTATUS status;
PVFATFCB FCB = NULL;
PVFATFCB parentFCB;
UNICODE_STRING NameU;
UNICODE_STRING RootNameU = RTL_CONSTANT_STRING(L"\\");
UNICODE_STRING FileNameU;
WCHAR NameBuffer[260];
PWCHAR curr, prev, last;
ULONG Length;
DPRINT ("vfatGetFCBForFile (%x,%x,%x,%wZ)\n",
pVCB,
pParentFCB,
pFCB,
pFileNameU);
FileNameU.Buffer = NameBuffer;
FileNameU.MaximumLength = sizeof(NameBuffer);
RtlCopyUnicodeString(&FileNameU, pFileNameU);
parentFCB = *pParentFCB;
if (parentFCB == NULL)
{
// Trivial case, open of the root directory on volume
if (RtlEqualUnicodeString(&FileNameU, &RootNameU, FALSE))
{
DPRINT ("returning root FCB\n");
FCB = vfatOpenRootFCB (pVCB);
*pFCB = FCB;
*pParentFCB = NULL;
return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
}
/* Check for an existing FCB */
FCB = vfatGrabFCBFromTable (pVCB, &FileNameU);
if (FCB)
{
*pFCB = FCB;
*pParentFCB = FCB->parentFcb;
(*pParentFCB)->RefCount++;
return STATUS_SUCCESS;
}
last = curr = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
while (*curr != L'\\' && curr > FileNameU.Buffer)
{
curr--;
}
if (curr > FileNameU.Buffer)
{
NameU.Buffer = FileNameU.Buffer;
NameU.MaximumLength = NameU.Length = (curr - FileNameU.Buffer) * sizeof(WCHAR);
FCB = vfatGrabFCBFromTable(pVCB, &NameU);
if (FCB)
{
Length = (curr - FileNameU.Buffer) * sizeof(WCHAR);
if (Length != FCB->PathNameU.Length)
{
if (FileNameU.Length + FCB->PathNameU.Length - Length > FileNameU.MaximumLength)
{
vfatReleaseFCB (pVCB, FCB);
return STATUS_OBJECT_NAME_INVALID;
}
RtlMoveMemory(FileNameU.Buffer + FCB->PathNameU.Length / sizeof(WCHAR),
curr, FileNameU.Length - Length);
FileNameU.Length += (USHORT)(FCB->PathNameU.Length - Length);
curr = FileNameU.Buffer + FCB->PathNameU.Length / sizeof(WCHAR);
last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
}
RtlCopyMemory(FileNameU.Buffer, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
}
}
else
{
FCB = NULL;
}
if (FCB == NULL)
{
FCB = vfatOpenRootFCB(pVCB);
curr = FileNameU.Buffer;
}
parentFCB = NULL;
prev = curr;
}
else
{
FCB = parentFCB;
parentFCB = NULL;
prev = curr = FileNameU.Buffer - 1;
last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
}
while (curr <= last)
{
if (parentFCB)
{
vfatReleaseFCB (pVCB, parentFCB);
parentFCB = 0;
}
// fail if element in FCB is not a directory
if (!vfatFCBIsDirectory (FCB))
{
DPRINT ("Element in requested path is not a directory\n");
vfatReleaseFCB (pVCB, FCB);
FCB = NULL;
*pParentFCB = NULL;
*pFCB = NULL;
return STATUS_OBJECT_PATH_NOT_FOUND;
}
parentFCB = FCB;
if (prev < curr)
{
Length = (curr - prev) * sizeof(WCHAR);
if (Length != parentFCB->LongNameU.Length)
{
if (FileNameU.Length + parentFCB->LongNameU.Length - Length > FileNameU.MaximumLength)
{
vfatReleaseFCB (pVCB, parentFCB);
return STATUS_OBJECT_NAME_INVALID;
}
RtlMoveMemory(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr,
FileNameU.Length - (curr - FileNameU.Buffer) * sizeof(WCHAR));
FileNameU.Length += (USHORT)(parentFCB->LongNameU.Length - Length);
curr = prev + parentFCB->LongNameU.Length / sizeof(WCHAR);
last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1;
}
RtlCopyMemory(prev, parentFCB->LongNameU.Buffer, parentFCB->LongNameU.Length);
}
curr++;
prev = curr;
while (*curr != L'\\' && curr <= last)
{
curr++;
}
NameU.Buffer = FileNameU.Buffer;
NameU.Length = (curr - NameU.Buffer) * sizeof(WCHAR);
NameU.MaximumLength = FileNameU.MaximumLength;
DPRINT("%wZ\n", &NameU);
FCB = vfatGrabFCBFromTable(pVCB, &NameU);
if (FCB == NULL)
{
NameU.Buffer = prev;
NameU.MaximumLength = NameU.Length = (curr - prev) * sizeof(WCHAR);
status = vfatDirFindFile(pVCB, parentFCB, &NameU, &FCB);
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
{
*pFCB = NULL;
if (curr > last)
{
*pParentFCB = parentFCB;
return STATUS_OBJECT_NAME_NOT_FOUND;
}
else
{
vfatReleaseFCB (pVCB, parentFCB);
*pParentFCB = NULL;
return STATUS_OBJECT_PATH_NOT_FOUND;
}
}
else if (!NT_SUCCESS (status))
{
vfatReleaseFCB (pVCB, parentFCB);
*pParentFCB = NULL;
*pFCB = NULL;
return status;
}
}
}
*pParentFCB = parentFCB;
*pFCB = FCB;
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -