fcb.c
来自「一个类似windows」· C语言 代码 · 共 738 行 · 第 1/2 页
C
738 行
if (LongName[0] != 0)
{
wcscat(pathName, LongName);
}
else
{
WCHAR entryName[MAX_PATH];
CdfsGetDirEntryName(Vcb, Record, entryName);
wcscat(pathName, entryName);
}
rcFCB = CdfsCreateFCB(pathName);
memcpy(&rcFCB->Entry, Record, sizeof(DIR_RECORD));
/* Copy short name into FCB */
rcFCB->ShortNameU.Length = wcslen(ShortName) * sizeof(WCHAR);
rcFCB->ShortNameU.MaximumLength = rcFCB->ShortNameU.Length;
rcFCB->ShortNameU.Buffer = rcFCB->ShortNameBuffer;
wcscpy(rcFCB->ShortNameBuffer, ShortName);
Size = rcFCB->Entry.DataLengthL;
rcFCB->RFCB.FileSize.QuadPart = Size;
rcFCB->RFCB.ValidDataLength.QuadPart = Size;
rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, BLOCKSIZE);
if (CdfsFCBIsDirectory(rcFCB))
{
CdfsFCBInitializeCache(Vcb, rcFCB);
}
rcFCB->IndexNumber.u.HighPart = DirectorySector;
rcFCB->IndexNumber.u.LowPart = DirectoryOffset;
rcFCB->RefCount++;
CdfsAddFCBToTable(Vcb, rcFCB);
*fileFCB = rcFCB;
DPRINT("%S %d %I64d\n", LongName, Size, rcFCB->RFCB.AllocationSize.QuadPart);
return(STATUS_SUCCESS);
}
NTSTATUS
CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb,
PFCB Fcb,
PFILE_OBJECT FileObject)
{
PCCB newCCB;
newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB);
if (newCCB == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
memset(newCCB, 0, sizeof(CCB));
FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
FileObject->FsContext = Fcb;
FileObject->FsContext2 = newCCB;
newCCB->PtrFileObject = FileObject;
Fcb->DevExt = Vcb;
if (CdfsFCBIsDirectory(Fcb))
{
#ifdef USE_ROS_CC_AND_FS
NTSTATUS Status;
Status = CcRosInitializeFileCache(FileObject,
PAGE_SIZE);
if (!NT_SUCCESS(Status))
{
DbgPrint("CcRosInitializeFileCache failed\n");
KEBUGCHECK(0);
}
#else
CcInitializeCacheMap(FileObject,
(PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
FALSE,
NULL,
NULL);
#endif
Fcb->Flags |= FCB_CACHE_INITIALIZED;
}
DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL);
return(STATUS_SUCCESS);
}
NTSTATUS
CdfsDirFindFile(PDEVICE_EXTENSION DeviceExt,
PFCB DirectoryFcb,
PUNICODE_STRING FileToFind,
PFCB *FoundFCB)
{
UNICODE_STRING TempName;
WCHAR Name[256];
PVOID Block;
ULONG DirSize;
PDIR_RECORD Record;
ULONG Offset;
ULONG BlockOffset;
NTSTATUS Status;
LARGE_INTEGER StreamOffset;
PVOID Context;
WCHAR ShortNameBuffer[13];
UNICODE_STRING ShortName;
UNICODE_STRING LongName;
BOOLEAN HasSpaces;
GENERATE_NAME_CONTEXT NameContext;
ASSERT(DeviceExt);
ASSERT(DirectoryFcb);
ASSERT(FileToFind);
DPRINT("CdfsDirFindFile(VCB:%p, dirFCB:%p, File:%wZ)\n",
DeviceExt,
DirectoryFcb,
FileToFind);
DPRINT("Dir Path:%S\n", DirectoryFcb->PathName);
/* default to '.' if no filename specified */
if (FileToFind->Length == 0)
{
RtlInitUnicodeString(&TempName, L".");
FileToFind = &TempName;
}
DirSize = DirectoryFcb->Entry.DataLengthL;
StreamOffset.QuadPart = (LONGLONG)DirectoryFcb->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;
if (!CcMapData(DeviceExt->StreamFileObject,
&StreamOffset,
BLOCKSIZE,
TRUE,
&Context,
&Block))
{
DPRINT("CcMapData() failed\n");
return STATUS_UNSUCCESSFUL;
}
Offset = 0;
BlockOffset = 0;
Record = (PDIR_RECORD)Block;
while(TRUE)
{
if (Record->RecordLength == 0)
{
DPRINT("RecordLength == 0 Stopped!\n");
break;
}
DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n",
Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);
CdfsGetDirEntryName(DeviceExt, Record, Name);
DPRINT ("Name '%S'\n", Name);
DPRINT ("Sector %lu\n", DirectoryFcb->Entry.ExtentLocationL);
DPRINT ("Offset %lu\n", Offset);
RtlInitUnicodeString(&LongName, Name);
ShortName.Length = 0;
ShortName.MaximumLength = 26;
ShortName.Buffer = ShortNameBuffer;
memset(ShortNameBuffer, 0, 26);
if ((RtlIsNameLegalDOS8Dot3(&LongName, NULL, &HasSpaces) == FALSE) ||
(HasSpaces == TRUE))
{
/* Build short name */
RtlGenerate8dot3Name(&LongName,
FALSE,
&NameContext,
&ShortName);
}
else
{
/* copy short name */
RtlUpcaseUnicodeString(&ShortName,
&LongName,
FALSE);
}
DPRINT("ShortName '%wZ'\n", &ShortName);
if (FsRtlIsNameInExpression(FileToFind, &LongName, TRUE, NULL) ||
FsRtlIsNameInExpression(FileToFind, &ShortName, TRUE, NULL))
{
DPRINT("Match found, %S\n", Name);
Status = CdfsMakeFCBFromDirEntry(DeviceExt,
DirectoryFcb,
Name,
ShortNameBuffer,
Record,
DirectoryFcb->Entry.ExtentLocationL,
Offset,
FoundFCB);
CcUnpinData(Context);
return(Status);
}
Offset += Record->RecordLength;
BlockOffset += Record->RecordLength;
Record = (PDIR_RECORD)((ULONG_PTR)Block + BlockOffset);
if (BlockOffset >= BLOCKSIZE || Record->RecordLength == 0)
{
DPRINT("Map next sector\n");
CcUnpinData(Context);
StreamOffset.QuadPart += BLOCKSIZE;
Offset = ROUND_UP(Offset, BLOCKSIZE);
BlockOffset = 0;
if (!CcMapData(DeviceExt->StreamFileObject,
&StreamOffset,
BLOCKSIZE, TRUE,
&Context, &Block))
{
DPRINT("CcMapData() failed\n");
return(STATUS_UNSUCCESSFUL);
}
Record = (PDIR_RECORD)((ULONG_PTR)Block + BlockOffset);
}
if (Offset >= DirSize)
break;
}
CcUnpinData(Context);
return(STATUS_OBJECT_NAME_NOT_FOUND);
}
NTSTATUS
CdfsGetFCBForFile(PDEVICE_EXTENSION Vcb,
PFCB *pParentFCB,
PFCB *pFCB,
PUNICODE_STRING FileName)
{
UNICODE_STRING PathName;
UNICODE_STRING ElementName;
NTSTATUS Status;
WCHAR pathName [MAX_PATH];
WCHAR elementName [MAX_PATH];
PWCHAR currentElement;
PFCB FCB;
PFCB parentFCB;
DPRINT("CdfsGetFCBForFile(%x, %x, %x, '%wZ')\n",
Vcb,
pParentFCB,
pFCB,
FileName);
/* Trivial case, open of the root directory on volume */
if (FileName->Buffer[0] == L'\0' || wcscmp(FileName->Buffer, L"\\") == 0)
{
DPRINT("returning root FCB\n");
FCB = CdfsOpenRootFCB(Vcb);
*pFCB = FCB;
*pParentFCB = NULL;
return((FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND);
}
else
{
currentElement = &FileName->Buffer[1];
wcscpy (pathName, L"\\");
FCB = CdfsOpenRootFCB (Vcb);
}
parentFCB = NULL;
/* Parse filename and check each path element for existance and access */
while (CdfsGetNextPathElement(currentElement) != 0)
{
/* Skip blank directory levels */
if ((CdfsGetNextPathElement(currentElement) - currentElement) == 0)
{
currentElement++;
continue;
}
DPRINT("Parsing, currentElement:%S\n", currentElement);
DPRINT(" parentFCB:%x FCB:%x\n", parentFCB, FCB);
/* Descend to next directory level */
if (parentFCB)
{
CdfsReleaseFCB(Vcb, parentFCB);
parentFCB = NULL;
}
/* fail if element in FCB is not a directory */
if (!CdfsFCBIsDirectory(FCB))
{
DPRINT("Element in requested path is not a directory\n");
CdfsReleaseFCB(Vcb, FCB);
FCB = 0;
*pParentFCB = NULL;
*pFCB = NULL;
return(STATUS_OBJECT_PATH_NOT_FOUND);
}
parentFCB = FCB;
/* Extract next directory level into dirName */
CdfsWSubString(pathName,
FileName->Buffer,
CdfsGetNextPathElement(currentElement) - FileName->Buffer);
DPRINT(" pathName:%S\n", pathName);
RtlInitUnicodeString(&PathName, pathName);
FCB = CdfsGrabFCBFromTable(Vcb, &PathName);
if (FCB == NULL)
{
CdfsWSubString(elementName,
currentElement,
CdfsGetNextPathElement(currentElement) - currentElement);
DPRINT(" elementName:%S\n", elementName);
RtlInitUnicodeString(&ElementName, elementName);
Status = CdfsDirFindFile(Vcb,
parentFCB,
&ElementName,
&FCB);
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
*pParentFCB = parentFCB;
*pFCB = NULL;
currentElement = CdfsGetNextPathElement(currentElement);
if (*currentElement == L'\0' || CdfsGetNextPathElement(currentElement + 1) == 0)
{
return(STATUS_OBJECT_NAME_NOT_FOUND);
}
else
{
return(STATUS_OBJECT_PATH_NOT_FOUND);
}
}
else if (!NT_SUCCESS(Status))
{
CdfsReleaseFCB(Vcb, parentFCB);
*pParentFCB = NULL;
*pFCB = NULL;
return(Status);
}
}
currentElement = CdfsGetNextPathElement(currentElement);
}
*pParentFCB = parentFCB;
*pFCB = FCB;
return STATUS_SUCCESS;
}
/* EOF */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?