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

📄 fcb.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
* FILE:             drivers/fs/vfat/fcb.c
* PURPOSE:          Routines to manipulate FCBs.
* COPYRIGHT:        See COPYING in the top level directory
* PROJECT:          ReactOS kernel
* PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
*                   Rex Jolliff (rex@lvcablemodem.com)
*                   Herve Poussineau (reactos@poussine.freesurf.fr)
*/

/*  -------------------------------------------------------  INCLUDES  */

#include <wctype.h> /* towlower prototype */

#define NDEBUG
#include "vfat.h"

/*  --------------------------------------------------------  DEFINES  */

#define TAG_FCB TAG('V', 'F', 'C', 'B')

/*  --------------------------------------------------------  PUBLICS  */

static ULONG vfatNameHash(ULONG hash, PUNICODE_STRING NameU)
{
	PWCHAR last;
	PWCHAR curr;
	register WCHAR c;
	
	ASSERT(NameU->Buffer[0] != L'.');
	curr = NameU->Buffer;
	last = NameU->Buffer + NameU->Length / sizeof(WCHAR);
	
	while(curr < last)
	{
		c = towlower(*curr++);
		hash = (hash + (c << 4) + (c >> 4)) * 11;
	}
	return hash;
}

VOID
vfatSplitPathName(PUNICODE_STRING PathNameU, PUNICODE_STRING DirNameU, PUNICODE_STRING FileNameU)
{
	PWCHAR pName;
	USHORT Length = 0;
	pName = PathNameU->Buffer + PathNameU->Length / sizeof(WCHAR) - 1;
	while (*pName != L'\\' && pName >= PathNameU->Buffer)
	{
		pName--;
		Length++;
	}
	ASSERT(*pName == L'\\' || pName < PathNameU->Buffer);
	if (FileNameU)
	{
		FileNameU->Buffer = pName + 1;
		FileNameU->Length = FileNameU->MaximumLength = Length * sizeof(WCHAR);
	}
	if (DirNameU)
	{
		DirNameU->Buffer = PathNameU->Buffer;
		DirNameU->Length = (pName + 1 - PathNameU->Buffer) * sizeof(WCHAR);
		DirNameU->MaximumLength = DirNameU->Length;
	}
}

static VOID
vfatInitFcb(PVFATFCB Fcb, PUNICODE_STRING NameU)
{
	USHORT PathNameBufferLength;
	
	if (NameU)
		PathNameBufferLength = NameU->Length + sizeof(WCHAR);
	else
		PathNameBufferLength = 0;
	
	Fcb->PathNameBuffer = ExAllocatePool(NonPagedPool, PathNameBufferLength);
	if (!Fcb->PathNameBuffer)
	{
		/* FIXME: what to do if no more memory? */
		DPRINT1("Unable to initialize FCB for filename '%wZ'\n", NameU);
		KEBUGCHECKEX(0, (ULONG_PTR)Fcb, (ULONG_PTR)NameU, 0, 0);
	}
	
	Fcb->PathNameU.Length = 0;
	Fcb->PathNameU.Buffer = Fcb->PathNameBuffer;
	Fcb->PathNameU.MaximumLength = PathNameBufferLength;
	Fcb->ShortNameU.Length = 0;
	Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer;
	Fcb->ShortNameU.MaximumLength = sizeof(Fcb->ShortNameBuffer);
	Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
	if (NameU && NameU->Length)
	{
		RtlCopyUnicodeString(&Fcb->PathNameU, NameU);
		vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
	}
	else
	{
		Fcb->DirNameU.Buffer = Fcb->LongNameU.Buffer = NULL;
		Fcb->DirNameU.MaximumLength = Fcb->DirNameU.Length = 0;
		Fcb->LongNameU.MaximumLength = Fcb->LongNameU.Length = 0;
	}
	RtlZeroMemory(&Fcb->FCBShareAccess, sizeof(SHARE_ACCESS));
	Fcb->OpenHandleCount = 0;
}

PVFATFCB
vfatNewFCB(PDEVICE_EXTENSION  pVCB, PUNICODE_STRING pFileNameU)
{
	PVFATFCB  rcFCB;
	
	DPRINT("'%wZ'\n", pFileNameU);
	
	rcFCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->FcbLookasideList);
	if (rcFCB == NULL)
	{
		return NULL;
	}
	RtlZeroMemory(rcFCB, sizeof(VFATFCB));
	vfatInitFcb(rcFCB, pFileNameU);
	if (pVCB->Flags & VCB_IS_FATX)
	{
		rcFCB->Flags |= FCB_IS_FATX_ENTRY;
		rcFCB->Attributes = &rcFCB->entry.FatX.Attrib;
	}
	else
		rcFCB->Attributes = &rcFCB->entry.Fat.Attrib;
	rcFCB->Hash.Hash = vfatNameHash(0, &rcFCB->PathNameU);
	rcFCB->Hash.self = rcFCB;
	rcFCB->ShortHash.self = rcFCB;
	ExInitializeResourceLite(&rcFCB->PagingIoResource);
	ExInitializeResourceLite(&rcFCB->MainResource);
	FsRtlInitializeFileLock(&rcFCB->FileLock, NULL, NULL);
	ExInitializeFastMutex(&rcFCB->LastMutex);
	rcFCB->RFCB.PagingIoResource = &rcFCB->PagingIoResource;
	rcFCB->RFCB.Resource = &rcFCB->MainResource;
	rcFCB->RFCB.IsFastIoPossible = FastIoIsNotPossible;
	
	return  rcFCB;
}

VOID
vfatDestroyCCB(PVFATCCB pCcb)
{
	if (pCcb->SearchPattern.Buffer)
	{
		ExFreePool(pCcb->SearchPattern.Buffer);
	}
	ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, pCcb);
}

VOID
vfatDestroyFCB(PVFATFCB pFCB)
{
	FsRtlUninitializeFileLock(&pFCB->FileLock);
	ExFreePool(pFCB->PathNameBuffer);
	ExDeleteResourceLite(&pFCB->PagingIoResource);
	ExDeleteResourceLite(&pFCB->MainResource);
	ExFreeToNPagedLookasideList(&VfatGlobalData->FcbLookasideList, pFCB);
}

BOOLEAN
vfatFCBIsDirectory(PVFATFCB FCB)
{
	return  *FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY;
}

BOOLEAN
vfatFCBIsRoot(PVFATFCB FCB)
{
	return  FCB->PathNameU.Length == sizeof(WCHAR) && FCB->PathNameU.Buffer[0] == L'\\' ? TRUE : FALSE;
}

VOID
vfatReleaseFCB(PDEVICE_EXTENSION  pVCB,  PVFATFCB  pFCB)
{
	HASHENTRY* entry;
	ULONG Index;
	ULONG ShortIndex;
	PVFATFCB tmpFcb;
	
	DPRINT ("releasing FCB at %x: %wZ, refCount:%d\n",
		pFCB,
		&pFCB->PathNameU,
		pFCB->RefCount);
	
	while (pFCB)
	{
		Index = pFCB->Hash.Hash % pVCB->HashTableSize;
		ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
		pFCB->RefCount--;
		if (pFCB->RefCount == 0)
		{
			tmpFcb = pFCB->parentFcb;
			RemoveEntryList (&pFCB->FcbListEntry);
			if (pFCB->Hash.Hash != pFCB->ShortHash.Hash)
			{
				entry = pVCB->FcbHashTable[ShortIndex];
				if (entry->self == pFCB)
				{
					pVCB->FcbHashTable[ShortIndex] = entry->next;
				}
				else
				{
					while (entry->next->self != pFCB)
					{
						entry = entry->next;
					}
					entry->next = pFCB->ShortHash.next;
				}
			}
			entry = pVCB->FcbHashTable[Index];
			if (entry->self == pFCB)
			{
				pVCB->FcbHashTable[Index] = entry->next;
			}
			else
			{
				while (entry->next->self != pFCB)
				{
					entry = entry->next;
				}
				entry->next = pFCB->Hash.next;
			}
			vfatDestroyFCB (pFCB);
		}
		else
		{
			tmpFcb = NULL;
		}
		pFCB = tmpFcb;
	}
}

VOID
vfatAddFCBToTable(PDEVICE_EXTENSION  pVCB,  PVFATFCB  pFCB)
{
	ULONG Index;
	ULONG ShortIndex;
	
	Index = pFCB->Hash.Hash % pVCB->HashTableSize;
	ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
	
	InsertTailList (&pVCB->FcbListHead, &pFCB->FcbListEntry);
	
	pFCB->Hash.next = pVCB->FcbHashTable[Index];
	pVCB->FcbHashTable[Index] = &pFCB->Hash;
	if (pFCB->Hash.Hash != pFCB->ShortHash.Hash)
	{
		pFCB->ShortHash.next = pVCB->FcbHashTable[ShortIndex];
		pVCB->FcbHashTable[ShortIndex] = &pFCB->ShortHash;
	}
	if (pFCB->parentFcb)
	{
		pFCB->parentFcb->RefCount++;
	}
}

PVFATFCB
vfatGrabFCBFromTable(PDEVICE_EXTENSION  pVCB, PUNICODE_STRING  PathNameU)
{
	PVFATFCB  rcFCB;
	ULONG Hash;
	UNICODE_STRING DirNameU;
	UNICODE_STRING FileNameU;
	PUNICODE_STRING FcbNameU;
	
	HASHENTRY* entry;
	
	DPRINT("'%wZ'\n", PathNameU);
	
	Hash = vfatNameHash(0, PathNameU);
	
	entry = pVCB->FcbHashTable[Hash % pVCB->HashTableSize];
	if (entry)
	{
		vfatSplitPathName(PathNameU, &DirNameU, &FileNameU);
	}
	
	while (entry)
	{
		if (entry->Hash == Hash)
		{
			rcFCB = entry->self;
			DPRINT("'%wZ' '%wZ'\n", &DirNameU, &rcFCB->DirNameU);
			if (RtlEqualUnicodeString(&DirNameU, &rcFCB->DirNameU, TRUE))
			{
				if (rcFCB->Hash.Hash == Hash)
				{
					FcbNameU = &rcFCB->LongNameU;
				}
				else
				{
					FcbNameU = &rcFCB->ShortNameU;
				}
				/* compare the file name */
				DPRINT("'%wZ' '%wZ'\n", &FileNameU, FcbNameU);
				if (RtlEqualUnicodeString(&FileNameU, FcbNameU, TRUE))
				{
					rcFCB->RefCount++;
					CHECKPOINT;
					return rcFCB;
				}
			}
		}
		entry = entry->next;
	}
	CHECKPOINT;
	return  NULL;
}

static NTSTATUS
vfatFCBInitializeCacheFromVolume (PVCB  vcb, PVFATFCB  fcb)
{
#ifdef USE_ROS_CC_AND_FS
	NTSTATUS  status;
	ULONG  fileCacheQuantum;
#endif
	PFILE_OBJECT  fileObject;
	PVFATCCB  newCCB;
	
	fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
	
	newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
	if (newCCB == NULL)
	{
		return  STATUS_INSUFFICIENT_RESOURCES;
	}
	RtlZeroMemory(newCCB, sizeof (VFATCCB));
	
	fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
	fileObject->FsContext = fcb;
	fileObject->FsContext2 = newCCB;
	fcb->FileObject = fileObject;
	fcb->RefCount++;
	
#ifdef USE_ROS_CC_AND_FS
	fileCacheQuantum = (vcb->FatInfo.BytesPerCluster >= PAGE_SIZE) ?
		vcb->FatInfo.BytesPerCluster : PAGE_SIZE;
	
	status = CcRosInitializeFileCache (fileObject,
		fileCacheQuantum);
	if (!NT_SUCCESS (status))
	{
		DbgPrint ("CcRosInitializeFileCache failed\n");
		KEBUGCHECK (0);
	}
#else
	/* FIXME: Guard by SEH. */
	CcInitializeCacheMap(fileObject,
		(PCC_FILE_SIZES)(&fcb->RFCB.AllocationSize),
		FALSE,
		&VfatGlobalData->CacheMgrCallbacks,
		fcb);
#endif
	
	fcb->Flags |= FCB_CACHE_INITIALIZED;
	return STATUS_SUCCESS;
}

PVFATFCB
vfatMakeRootFCB(PDEVICE_EXTENSION  pVCB)
{
	PVFATFCB  FCB;
	ULONG FirstCluster, CurrentCluster, Size = 0;
	NTSTATUS Status = STATUS_SUCCESS;
	UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\");
	
	FCB = vfatNewFCB(pVCB, &NameU);
	if (FCB->Flags & FCB_IS_FATX_ENTRY)
	{
		memset(FCB->entry.FatX.Filename, ' ', 42);
		FCB->entry.FatX.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
		FCB->entry.FatX.Attrib = FILE_ATTRIBUTE_DIRECTORY;
		FCB->entry.FatX.FirstCluster = 1;
		Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
	}
	else
	{
		memset(FCB->entry.Fat.ShortName, ' ', 11);
		FCB->entry.Fat.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
		FCB->entry.Fat.Attrib = FILE_ATTRIBUTE_DIRECTORY;
		if (pVCB->FatInfo.FatType == FAT32)
		{
			CurrentCluster = FirstCluster = pVCB->FatInfo.RootCluster;
			FCB->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0xffff);
			FCB->entry.Fat.FirstClusterHigh = (unsigned short)(FirstCluster >> 16);
			
			while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
			{
				Size += pVCB->FatInfo.BytesPerCluster;
				Status = NextCluster (pVCB, FirstCluster, &CurrentCluster, FALSE);
			}
		}
		else
		{
			FCB->entry.Fat.FirstCluster = 1;
			Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
		}
	}
	FCB->ShortHash.Hash = FCB->Hash.Hash;
	FCB->RefCount = 2;
	FCB->dirIndex = 0;
	FCB->RFCB.FileSize.QuadPart = Size;
	FCB->RFCB.ValidDataLength.QuadPart = Size;
	FCB->RFCB.AllocationSize.QuadPart = Size;
	FCB->RFCB.IsFastIoPossible = FastIoIsNotPossible;
	
	vfatFCBInitializeCacheFromVolume(pVCB, FCB);
	vfatAddFCBToTable(pVCB, FCB);
	
	return(FCB);
}

PVFATFCB
vfatOpenRootFCB(PDEVICE_EXTENSION  pVCB)
{
	PVFATFCB  FCB;
	UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\");
	
	FCB = vfatGrabFCBFromTable (pVCB, &NameU);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -