⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fcb.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -