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 + -
显示快捷键?