fcb.c
来自「一个类似windows」· C语言 代码 · 共 687 行 · 第 1/2 页
C
687 行
/*
* ReactOS kernel
* Copyright (C) 2002 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.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: fcb.c 21707 2006-04-22 14:06:53Z tretiakov $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/ntfs/fcb.c
* PURPOSE: NTFS filesystem driver
* PROGRAMMER: Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include "ntfs.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS *****************************************************************/
/* MACROS *******************************************************************/
#define TAG_FCB TAG('I', 'F', 'C', 'B')
/* FUNCTIONS ****************************************************************/
static PWCHAR
NtfsGetNextPathElement(PWCHAR FileName)
{
if (*FileName == L'\0')
{
return(NULL);
}
while (*FileName != L'\0' && *FileName != L'\\')
{
FileName++;
}
return(FileName);
}
static VOID
NtfsWSubString(PWCHAR pTarget, const PWCHAR pSource, size_t pLength)
{
wcsncpy (pTarget, pSource, pLength);
pTarget [pLength] = L'\0';
}
PFCB
NtfsCreateFCB(PCWSTR FileName)
{
PFCB Fcb;
Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB);
RtlZeroMemory(Fcb, sizeof(FCB));
if (FileName)
{
wcscpy(Fcb->PathName, FileName);
if (wcsrchr(Fcb->PathName, '\\') != 0)
{
Fcb->ObjectName = wcsrchr(Fcb->PathName, '\\');
}
else
{
Fcb->ObjectName = Fcb->PathName;
}
}
ExInitializeResourceLite(&Fcb->MainResource);
return(Fcb);
}
VOID
NtfsDestroyFCB(PFCB Fcb)
{
ExDeleteResourceLite(&Fcb->MainResource);
ExFreePool(Fcb);
}
BOOLEAN
NtfsFCBIsDirectory(PFCB Fcb)
{
// return(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY);
// return(Fcb->Entry.FileFlags & 0x02);
return(TRUE);
}
BOOLEAN
NtfsFCBIsRoot(PFCB Fcb)
{
return(wcscmp(Fcb->PathName, L"\\") == 0);
}
VOID
NtfsGrabFCB(PDEVICE_EXTENSION Vcb,
PFCB Fcb)
{
KIRQL oldIrql;
DPRINT("grabbing FCB at %x: %S, refCount:%d\n",
Fcb,
Fcb->PathName,
Fcb->RefCount);
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
Fcb->RefCount++;
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
}
VOID
NtfsReleaseFCB(PDEVICE_EXTENSION Vcb,
PFCB Fcb)
{
KIRQL oldIrql;
DPRINT("releasing FCB at %x: %S, refCount:%d\n",
Fcb,
Fcb->PathName,
Fcb->RefCount);
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
Fcb->RefCount--;
if (Fcb->RefCount <= 0 && !NtfsFCBIsDirectory(Fcb))
{
RemoveEntryList(&Fcb->FcbListEntry);
#ifdef USE_ROS_CC_AND_FS
CcRosReleaseFileCache(Fcb->FileObject);
#else
CcUninitializeCacheMap (Fcb->FileObject, NULL, NULL);
#endif
NtfsDestroyFCB(Fcb);
}
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
}
VOID
NtfsAddFCBToTable(PDEVICE_EXTENSION Vcb,
PFCB Fcb)
{
KIRQL oldIrql;
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
Fcb->DevExt = Vcb;
InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry);
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
}
PFCB
NtfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb,
PCWSTR FileName)
{
KIRQL oldIrql;
PFCB Fcb;
PLIST_ENTRY current_entry;
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
if (FileName == NULL || *FileName == 0)
{
DPRINT("Return FCB for stream file object\n");
Fcb = Vcb->StreamFileObject->FsContext;
Fcb->RefCount++;
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
return(Fcb);
}
current_entry = Vcb->FcbListHead.Flink;
while (current_entry != &Vcb->FcbListHead)
{
Fcb = CONTAINING_RECORD(current_entry, FCB, FcbListEntry);
DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
if (_wcsicmp(FileName, Fcb->PathName) == 0)
{
Fcb->RefCount++;
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
return(Fcb);
}
//FIXME: need to compare against short name in FCB here
current_entry = current_entry->Flink;
}
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
return(NULL);
}
NTSTATUS
NtfsFCBInitializeCache(PVCB Vcb,
PFCB Fcb)
{
PFILE_OBJECT FileObject;
NTSTATUS Status;
PCCB newCCB;
FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice);
newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB);
if (newCCB == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(newCCB,
sizeof(CCB));
FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
FileObject->FsContext = Fcb;
FileObject->FsContext2 = newCCB;
newCCB->PtrFileObject = FileObject;
Fcb->FileObject = FileObject;
Fcb->DevExt = Vcb;
#ifdef ROS_USE_CC_AND_FS
Status = CcRosInitializeFileCache(FileObject,
CACHEPAGESIZE(Vcb));
if (!NT_SUCCESS(Status))
{
DbgPrint("CcRosInitializeFileCache failed\n");
KEBUGCHECK(0);
}
#else
Status = STATUS_SUCCESS;
CcInitializeCacheMap(FileObject,
(PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
FALSE,
NULL,
NULL);
#endif
ObDereferenceObject(FileObject);
Fcb->Flags |= FCB_CACHE_INITIALIZED;
return(Status);
}
PFCB
NtfsMakeRootFCB(PDEVICE_EXTENSION Vcb)
{
PFCB Fcb;
Fcb = NtfsCreateFCB(L"\\");
// memset(Fcb->entry.Filename, ' ', 11);
// Fcb->Entry.DataLengthL = Vcb->CdInfo.RootSize;
// Fcb->Entry.ExtentLocationL = Vcb->CdInfo.RootStart;
// Fcb->Entry.FileFlags = 0x02; // FILE_ATTRIBUTE_DIRECTORY;
Fcb->RefCount = 1;
Fcb->DirIndex = 0;
Fcb->RFCB.FileSize.QuadPart = PAGE_SIZE;//Vcb->CdInfo.RootSize;
Fcb->RFCB.ValidDataLength.QuadPart = PAGE_SIZE;//Vcb->CdInfo.RootSize;
Fcb->RFCB.AllocationSize.QuadPart = PAGE_SIZE;//Vcb->CdInfo.RootSize;
NtfsFCBInitializeCache(Vcb, Fcb);
NtfsAddFCBToTable(Vcb, Fcb);
NtfsGrabFCB(Vcb, Fcb);
return(Fcb);
}
PFCB
NtfsOpenRootFCB(PDEVICE_EXTENSION Vcb)
{
PFCB Fcb;
Fcb = NtfsGrabFCBFromTable(Vcb, L"\\");
if (Fcb == NULL)
{
Fcb = NtfsMakeRootFCB(Vcb);
}
return(Fcb);
}
#if 0
static VOID
NtfsGetDirEntryName(PDEVICE_EXTENSION DeviceExt,
PDIR_RECORD Record,
PWSTR Name)
/*
* FUNCTION: Retrieves the file name, be it in short or long file name format
*/
{
if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
{
wcscpy(Name, L".");
}
else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
{
wcscpy(Name, L"..");
}
else
{
if (DeviceExt->CdInfo.JolietLevel == 0)
{
ULONG i;
for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
Name[i] = (WCHAR)Record->FileId[i];
Name[i] = 0;
}
else
{
NtfsSwapString(Name, Record->FileId, Record->FileIdLength);
}
}
DPRINT("Name '%S'\n", Name);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?