create.c

来自「一个类似windows」· C语言 代码 · 共 788 行 · 第 1/2 页

C
788
字号
/*
 *  ReactOS kernel
 *  Copyright (C) 1998, 1999, 2000, 2001 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.
 */
/*
 * PROJECT:          ReactOS kernel
 * FILE:             drivers/fs/vfat/create.c
 * PURPOSE:          VFAT Filesystem
 * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
 */

/* INCLUDES *****************************************************************/

#define NDEBUG
#include "vfat.h"

/* FUNCTIONS *****************************************************************/

void
vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
{
	OEM_STRING StringA;
	USHORT Length;
	CHAR  cString[12];

	RtlCopyMemory(cString, pEntry->ShortName, 11);
	cString[11] = 0;
	if (cString[0] == 0x05)
	{
		cString[0] = 0xe5;
	}

	StringA.Buffer = cString;
	for (StringA.Length = 0;
	StringA.Length < 8 && StringA.Buffer[StringA.Length] != ' ';
	StringA.Length++);
	StringA.MaximumLength = StringA.Length;

	RtlOemStringToUnicodeString(NameU, &StringA, FALSE);

	if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
	{
		RtlDowncaseUnicodeString(NameU, NameU, FALSE);
	}
	if (cString[8] != ' ')
	{
		Length = NameU->Length;
		NameU->Buffer += Length / sizeof(WCHAR);
		if (!FAT_ENTRY_VOLUME(pEntry))
		{
			Length += sizeof(WCHAR);
			NameU->Buffer[0] = L'.';
			NameU->Buffer++;
		}
		NameU->Length = 0;
		NameU->MaximumLength -= Length;

		StringA.Buffer = &cString[8];
		for (StringA.Length = 0;
		StringA.Length < 3 && StringA.Buffer[StringA.Length] != ' ';
		StringA.Length++);
		StringA.MaximumLength = StringA.Length;
		RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
		if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
		{
			RtlDowncaseUnicodeString(NameU, NameU, FALSE);
		}
		NameU->Buffer -= Length / sizeof(WCHAR);
		NameU->Length += Length;
		NameU->MaximumLength += Length;
	}
	NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
	DPRINT("'%wZ'\n", NameU);
}

NTSTATUS
ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
/*
 * FUNCTION: Read the volume label
 */
{
	PVOID Context = NULL;
	ULONG DirIndex = 0;
	PDIR_ENTRY Entry;
	PVFATFCB pFcb;
	LARGE_INTEGER FileOffset;
	UNICODE_STRING NameU;
	ULONG SizeDirEntry;
	ULONG EntriesPerPage;
	OEM_STRING StringO;

	NameU.Buffer = Vpb->VolumeLabel;
	NameU.Length = 0;
	NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
	*(Vpb->VolumeLabel) = 0;
	Vpb->VolumeLabelLength = 0;

	if (DeviceExt->Flags & VCB_IS_FATX)
	{
		SizeDirEntry = sizeof(FATX_DIR_ENTRY);
		EntriesPerPage = FATX_ENTRIES_PER_PAGE;
	}
	else
	{
		SizeDirEntry = sizeof(FAT_DIR_ENTRY);
		EntriesPerPage = FAT_ENTRIES_PER_PAGE;
	}

	ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
	pFcb = vfatOpenRootFCB (DeviceExt);
	ExReleaseResourceLite (&DeviceExt->DirResource);

	FileOffset.QuadPart = 0;
	if (CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
	{
		while (TRUE)
		{
			if (ENTRY_VOLUME(DeviceExt, Entry))
			{
				/* copy volume label */
				if (DeviceExt->Flags & VCB_IS_FATX)
				{
					StringO.Buffer = (PCHAR)Entry->FatX.Filename;
					StringO.MaximumLength = StringO.Length = Entry->FatX.FilenameLength;
					RtlOemStringToUnicodeString(&NameU, &StringO, FALSE);
				}
				else
				{
					vfat8Dot3ToString (&Entry->Fat, &NameU);
				}
				Vpb->VolumeLabelLength = NameU.Length;
				break;
			}
			if (ENTRY_END(DeviceExt, Entry))
			{
				break;
			}
			DirIndex++;
			Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
			if ((DirIndex % EntriesPerPage) == 0)
			{
				CcUnpinData(Context);
				FileOffset.u.LowPart += PAGE_SIZE;
				if (!CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
				{
					Context = NULL;
					break;
				}
			}
		}
		if (Context)
		{
			CcUnpinData(Context);
		}
	}
	ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
	vfatReleaseFCB (DeviceExt, pFcb);
	ExReleaseResourceLite (&DeviceExt->DirResource);

	return STATUS_SUCCESS;
}

NTSTATUS
FindFile (
	PDEVICE_EXTENSION DeviceExt,
	PVFATFCB Parent,
	PUNICODE_STRING FileToFindU,
	PVFAT_DIRENTRY_CONTEXT DirContext,
	BOOLEAN First)
/*
 * FUNCTION: Find a file
 */
{
	PWCHAR PathNameBuffer;
	USHORT PathNameBufferLength;
	NTSTATUS Status;
	PVOID Context = NULL;
	PVOID Page;
	PVFATFCB rcFcb;
	BOOLEAN Found;
	UNICODE_STRING PathNameU;
	UNICODE_STRING FileToFindUpcase;
	BOOLEAN WildCard;

	DPRINT ("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
		Parent, FileToFindU, DirContext->DirIndex);
	DPRINT ("FindFile: Path %wZ)\n",&Parent->PathNameU);

	PathNameBufferLength = LONGNAME_MAX_LENGTH * sizeof(WCHAR);
	PathNameBuffer = ExAllocatePool(NonPagedPool, PathNameBufferLength + sizeof(WCHAR));
	if (!PathNameBuffer)
	{
		CHECKPOINT1;
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	PathNameU.Buffer = PathNameBuffer;
	PathNameU.Length = 0;
	PathNameU.MaximumLength = PathNameBufferLength;

	DirContext->LongNameU.Length = 0;
	DirContext->ShortNameU.Length = 0;

	WildCard = FsRtlDoesNameContainWildCards(FileToFindU);

	if (WildCard == FALSE)
	{
		/* if there is no '*?' in the search name, than look first for an existing fcb */
		RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
		if (!vfatFCBIsRoot(Parent))
		{
			PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
			PathNameU.Length += sizeof(WCHAR);
		}
		RtlAppendUnicodeStringToString(&PathNameU, FileToFindU);
		PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
		rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
		if (rcFcb)
		{
			ULONG startIndex = rcFcb->startIndex;
			if ((rcFcb->Flags & FCB_IS_FATX_ENTRY) && !vfatFCBIsRoot(Parent))
			{
				startIndex += 2;
			}
			if(startIndex >= DirContext->DirIndex)
			{
				RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU);
				RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU);
				RtlCopyMemory(&DirContext->DirEntry, &rcFcb->entry, sizeof(DIR_ENTRY));
				DirContext->StartIndex = rcFcb->startIndex;
				DirContext->DirIndex = rcFcb->dirIndex;
				DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
					&DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex);
				Status = STATUS_SUCCESS;
			}
			else
			{
				CHECKPOINT1;
				Status = STATUS_UNSUCCESSFUL;
			}
			vfatReleaseFCB(DeviceExt, rcFcb);
			ExFreePool(PathNameBuffer);
			return Status;
		}
	}

	/* FsRtlIsNameInExpression need the searched string to be upcase,
	* even if IgnoreCase is specified */
	Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFindU, TRUE);
	if (!NT_SUCCESS(Status))
	{
		CHECKPOINT;
		ExFreePool(PathNameBuffer);
		return Status;
	}

	while(TRUE)
	{
		Status = DeviceExt->GetNextDirEntry(&Context, &Page, Parent, DirContext, First);
		First = FALSE;
		if (Status == STATUS_NO_MORE_ENTRIES)
		{
			break;
		}
		if (ENTRY_VOLUME(DeviceExt, &DirContext->DirEntry))
		{
			DirContext->DirIndex++;
			continue;
		}
		if (WildCard)
		{
			Found = FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->LongNameU, TRUE, NULL) ||
				FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->ShortNameU, TRUE, NULL);
		}
		else
		{
			Found = FsRtlAreNamesEqual(&DirContext->LongNameU, FileToFindU, TRUE, NULL) ||
				FsRtlAreNamesEqual(&DirContext->ShortNameU, FileToFindU, TRUE, NULL);
		}

		if (Found)
		{
			if (WildCard)
			{
				RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
				if (!vfatFCBIsRoot(Parent))
				{
					PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
					PathNameU.Length += sizeof(WCHAR);
				}
				RtlAppendUnicodeStringToString(&PathNameU, &DirContext->LongNameU);
				PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
				rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
				if (rcFcb != NULL)
				{
					RtlCopyMemory(&DirContext->DirEntry, &rcFcb->entry, sizeof(DIR_ENTRY));
					vfatReleaseFCB(DeviceExt, rcFcb);
				}
			}
			DPRINT("%d\n", DirContext->LongNameU.Length);
			DPRINT("FindFile: new Name %wZ, DirIndex %d\n",
				&DirContext->LongNameU, DirContext->DirIndex);

			if (Context)
			{
				CcUnpinData(Context);
			}
			RtlFreeUnicodeString(&FileToFindUpcase);
			ExFreePool(PathNameBuffer);
			return STATUS_SUCCESS;
		}
		DirContext->DirIndex++;
	}

	if (Context)
	{
		CcUnpinData(Context);
	}

	RtlFreeUnicodeString(&FileToFindUpcase);
	ExFreePool(PathNameBuffer);
	return Status;
}

static
NTSTATUS
VfatOpenFile (
	PDEVICE_EXTENSION DeviceExt,
        PUNICODE_STRING PathNameU,
	PFILE_OBJECT FileObject,
	PVFATFCB* ParentFcb )
/*
 * FUNCTION: Opens a file
 */
{
	PVFATFCB Fcb;
	NTSTATUS Status;

	DPRINT ("VfatOpenFile(%08lx, '%wZ', %08lx, %08lx)\n", DeviceExt, PathNameU, FileObject, ParentFcb);

	if (FileObject->RelatedFileObject)
	{
		DPRINT ("'%wZ'\n", &FileObject->RelatedFileObject->FileName);

		*ParentFcb = FileObject->RelatedFileObject->FsContext;
		(*ParentFcb)->RefCount++;
	}
	else
	{
		*ParentFcb = NULL;
	}

	if (!DeviceExt->FatInfo.FixedMedia)
	{
		Status = VfatBlockDeviceIoControl (DeviceExt->StorageDevice,
			IOCTL_DISK_CHECK_VERIFY,
			NULL,
			0,
			NULL,
			0,
			FALSE);

		if (Status == STATUS_VERIFY_REQUIRED)

		{
			PDEVICE_OBJECT DeviceToVerify;

			DPRINT ("Media change detected!\n");
			DPRINT ("Device %p\n", DeviceExt->StorageDevice);

			DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ());

			IoSetDeviceToVerify (PsGetCurrentThread (),
				NULL);
			Status = IoVerifyVolume (DeviceExt->StorageDevice,
				FALSE);
		}
		if (!NT_SUCCESS(Status))
		{
			DPRINT ("Status %lx\n", Status);

⌨️ 快捷键说明

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