+++ /dev/null
-/*
- * ReactOS kernel
- * Copyright (C) 2002, 2004 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: drivers/filesystems/cdfs/fcb.c
- * PURPOSE: CDROM (ISO 9660) filesystem driver
- * PROGRAMMER: Art Yerkes
- * UPDATE HISTORY:
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "cdfs.h"
-
-#define NDEBUG
-#include <debug.h>
-
-/* FUNCTIONS ****************************************************************/
-
-#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
-
-
-/* FUNCTIONS ****************************************************************/
-
-static BOOLEAN
-CdfsGetNextPathElement(PCUNICODE_STRING CurrentElement, PUNICODE_STRING NextElement)
-{
- *NextElement = *CurrentElement;
-
- if (NextElement->Length == 0)
- return FALSE;
-
- while ((NextElement->Length) && (NextElement->Buffer[0] != L'\\'))
- {
- NextElement->Buffer++;
- NextElement->Length -= sizeof(WCHAR);
- NextElement->MaximumLength -= sizeof(WCHAR);
- }
-
- return TRUE;
-}
-
-
-PFCB
-CdfsCreateFCB(PCWSTR FileName)
-{
- PFCB Fcb;
-
- Fcb = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(FCB),
- CDFS_NONPAGED_FCB_TAG);
- if(!Fcb) return NULL;
-
- RtlZeroMemory(Fcb, sizeof(FCB));
- RtlInitEmptyUnicodeString(&Fcb->PathName, Fcb->PathNameBuffer, sizeof(Fcb->PathNameBuffer));
-
- if (FileName)
- {
- RtlAppendUnicodeToString(&Fcb->PathName, FileName);
- if (wcsrchr(Fcb->PathName.Buffer, '\\') != 0)
- {
- Fcb->ObjectName = wcsrchr(Fcb->PathName.Buffer, '\\');
- }
- else
- {
- Fcb->ObjectName = Fcb->PathName.Buffer;
- }
- }
-
- ExInitializeResourceLite(&Fcb->PagingIoResource);
- ExInitializeResourceLite(&Fcb->MainResource);
- ExInitializeResourceLite(&Fcb->NameListResource);
- Fcb->RFCB.PagingIoResource = &Fcb->PagingIoResource;
- Fcb->RFCB.Resource = &Fcb->MainResource;
- Fcb->RFCB.IsFastIoPossible = FastIoIsNotPossible;
- InitializeListHead(&Fcb->ShortNameList);
- FsRtlInitializeFileLock(&Fcb->FileLock, NULL, NULL);
-
- return(Fcb);
-}
-
-
-VOID
-CdfsDestroyFCB(PFCB Fcb)
-{
- PLIST_ENTRY Entry;
-
- FsRtlUninitializeFileLock(&Fcb->FileLock);
- ExDeleteResourceLite(&Fcb->PagingIoResource);
- ExDeleteResourceLite(&Fcb->MainResource);
-
- while (!IsListEmpty(&Fcb->ShortNameList))
- {
- Entry = Fcb->ShortNameList.Flink;
- RemoveEntryList(Entry);
- ExFreePoolWithTag(Entry, CDFS_SHORT_NAME_TAG);
- }
-
- ExDeleteResourceLite(&Fcb->NameListResource);
- ExFreePoolWithTag(Fcb, CDFS_NONPAGED_FCB_TAG);
-}
-
-
-BOOLEAN
-CdfsFCBIsDirectory(PFCB Fcb)
-{
- return(Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY);
-}
-
-
-BOOLEAN
-CdfsFCBIsRoot(PFCB Fcb)
-{
- return (Fcb->PathName.Length == sizeof(WCHAR) && Fcb->PathName.Buffer[0] == L'\\');
-}
-
-
-VOID
-CdfsGrabFCB(PDEVICE_EXTENSION Vcb,
- PFCB Fcb)
-{
- KIRQL oldIrql;
-
- DPRINT("grabbing FCB at %p: %wZ, refCount:%d\n",
- Fcb,
- &Fcb->PathName,
- Fcb->RefCount);
-
- KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
- Fcb->RefCount++;
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
-}
-
-
-VOID
-CdfsReleaseFCB(PDEVICE_EXTENSION Vcb,
- PFCB Fcb)
-{
- KIRQL oldIrql;
-
- DPRINT("releasing FCB at %p: %wZ, refCount:%d\n",
- Fcb,
- &Fcb->PathName,
- Fcb->RefCount);
-
- KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
- Fcb->RefCount--;
- if (Fcb->RefCount <= 0 && !CdfsFCBIsDirectory(Fcb))
- {
- RemoveEntryList(&Fcb->FcbListEntry);
- CdfsDestroyFCB(Fcb);
- }
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
-}
-
-
-VOID
-CdfsAddFCBToTable(PDEVICE_EXTENSION Vcb,
- PFCB Fcb)
-{
- KIRQL oldIrql;
-
- KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
- Fcb->DevExt = Vcb;
- InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry);
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
-}
-
-
-PFCB
-CdfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb,
- PUNICODE_STRING FileName)
-{
- KIRQL oldIrql;
- PFCB Fcb;
- PLIST_ENTRY current_entry;
-
- KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
-
- if (FileName == NULL || FileName->Length == 0 || FileName->Buffer[0] == 0)
- {
- DPRINT("Return FCB for stream file object\n");
- Fcb = Vcb->StreamFileObject->FsContext;
- Fcb->RefCount++;
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
- return(Fcb);
- }
-
- current_entry = Vcb->FcbListHead.Flink;
- while (current_entry != &Vcb->FcbListHead)
- {
- Fcb = CONTAINING_RECORD(current_entry, FCB, FcbListEntry);
-
- // Disabled the DPRINT! Can't be called at DISPATCH_LEVEL!
- //DPRINT("Comparing '%wZ' and '%wZ'\n", FileName, &Fcb->PathName);
- if (RtlCompareUnicodeString(FileName, &Fcb->PathName, TRUE) == 0)
- {
- Fcb->RefCount++;
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
- return(Fcb);
- }
-
- //FIXME: need to compare against short name in FCB here
-
- current_entry = current_entry->Flink;
- }
- KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
-
- return(NULL);
-}
-
-
-NTSTATUS
-CdfsFCBInitializeCache(PVCB Vcb,
- PFCB Fcb)
-{
- PFILE_OBJECT FileObject;
- PCCB newCCB;
-
- FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice);
-
- newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), CDFS_CCB_TAG);
- if (newCCB == NULL)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- RtlZeroMemory(newCCB,
- sizeof(CCB));
-
- FileObject->ReadAccess = TRUE;
- FileObject->WriteAccess = FALSE;
- FileObject->DeleteAccess = FALSE;
- FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
- FileObject->FsContext = Fcb;
- FileObject->FsContext2 = newCCB;
- newCCB->PtrFileObject = FileObject;
- Fcb->FileObject = FileObject;
- Fcb->DevExt = Vcb;
-
- _SEH2_TRY
- {
- CcInitializeCacheMap(FileObject,
- (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
- FALSE,
- &(CdfsGlobalData->CacheMgrCallbacks),
- Fcb);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- FileObject->FsContext2 = NULL;
- ExFreePoolWithTag(newCCB, CDFS_CCB_TAG);
- ObDereferenceObject(FileObject);
- Fcb->FileObject = NULL;
- return _SEH2_GetExceptionCode();
- }
- _SEH2_END;
-
- ObDereferenceObject(FileObject);
- Fcb->Flags |= FCB_CACHE_INITIALIZED;
-
- return STATUS_SUCCESS;
-}
-
-
-PFCB
-CdfsMakeRootFCB(PDEVICE_EXTENSION Vcb)
-{
- PFCB Fcb;
-
- Fcb = CdfsCreateFCB(L"\\");
-
- Fcb->Entry.DataLengthL = Vcb->CdInfo.RootSize;
- Fcb->Entry.ExtentLocationL = Vcb->CdInfo.RootStart;
- Fcb->Entry.FileFlags = FILE_FLAG_DIRECTORY;
- Fcb->IndexNumber.QuadPart = 0LL;
- Fcb->RefCount = 1;
- Fcb->DirIndex = 0;
- Fcb->RFCB.FileSize.QuadPart = Vcb->CdInfo.RootSize;
- Fcb->RFCB.ValidDataLength.QuadPart = Vcb->CdInfo.RootSize;
- Fcb->RFCB.AllocationSize.QuadPart = Vcb->CdInfo.RootSize;
-
- CdfsFCBInitializeCache(Vcb, Fcb);
- CdfsAddFCBToTable(Vcb, Fcb);
- CdfsGrabFCB(Vcb, Fcb);
-
- return(Fcb);
-}
-
-
-PFCB
-CdfsOpenRootFCB(PDEVICE_EXTENSION Vcb)
-{
- UNICODE_STRING FileName;
- PFCB Fcb;
-
- RtlInitUnicodeString(&FileName, L"\\");
-
- Fcb = CdfsGrabFCBFromTable(Vcb,
- &FileName);
- if (Fcb == NULL)
- {
- Fcb = CdfsMakeRootFCB(Vcb);
- }
-
- return(Fcb);
-}
-
-
-NTSTATUS
-CdfsMakeFCBFromDirEntry(PVCB Vcb,
- PFCB DirectoryFCB,
- PWSTR LongName,
- PWSTR ShortName,
- PDIR_RECORD Record,
- ULONG DirectorySector,
- ULONG DirectoryOffset,
- PFCB * fileFCB)
-{
- WCHAR pathName[MAX_PATH];
- PFCB rcFCB;
- ULONG Size;
-
- /* Check if the full string would overflow the pathName buffer (the additional characters are for '\\' and '\0') */
- if ((LongName[0] != 0) &&
- ((DirectoryFCB->PathName.Length / sizeof(WCHAR)) + 1 + wcslen(LongName) + 1 > MAX_PATH))
- {
- return(STATUS_OBJECT_NAME_INVALID);
- }
-
- wcscpy(pathName, DirectoryFCB->PathName.Buffer);
- if (!CdfsFCBIsRoot(DirectoryFCB))
- {
- wcscat(pathName, L"\\");
- }
-
- 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 %u %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), CDFS_CCB_TAG);
- if (newCCB == NULL)
- {
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
- memset(newCCB, 0, sizeof(CCB));
-
- FileObject->ReadAccess = TRUE;
- FileObject->WriteAccess = FALSE;
- FileObject->DeleteAccess = FALSE;
- FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
- FileObject->FsContext = Fcb;
- FileObject->FsContext2 = newCCB;
- newCCB->PtrFileObject = FileObject;
- Fcb->DevExt = Vcb;
-
- if (CdfsFCBIsDirectory(Fcb))
- {
- _SEH2_TRY
- {
- CcInitializeCacheMap(FileObject,
- (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
- FALSE,
- &(CdfsGlobalData->CacheMgrCallbacks),
- Fcb);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- FileObject->FsContext2 = NULL;
- ExFreePoolWithTag(newCCB, CDFS_CCB_TAG);
- return _SEH2_GetExceptionCode();
- }
- _SEH2_END;
- Fcb->Flags |= FCB_CACHE_INITIALIZED;
- }
-
- DPRINT("file open: fcb:%p file size: %u\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, OffsetOfEntry;
- PVOID Context;
-
- WCHAR ShortNameBuffer[13];
- UNICODE_STRING ShortName;
- UNICODE_STRING LongName;
- UNICODE_STRING FileToFindUpcase;
-
- ASSERT(DeviceExt);
- ASSERT(DirectoryFcb);
- ASSERT(FileToFind);
-
- DPRINT("CdfsDirFindFile(VCB:%p, dirFCB:%p, File:%wZ)\n",
- DeviceExt,
- DirectoryFcb,
- FileToFind);
- DPRINT("Dir Path:%wZ\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;
-
- _SEH2_TRY
- {
- CcMapData(DeviceExt->StreamFileObject, &StreamOffset, BLOCKSIZE, MAP_WAIT, &Context, &Block);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- DPRINT("CcMapData() failed\n");
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
-
- Offset = 0;
- BlockOffset = 0;
- Record = (PDIR_RECORD)Block;
-
- /* Upper case the expression for FsRtlIsNameInExpression */
- Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFind, TRUE);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- 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);
-
- if (!CdfsIsRecordValid(DeviceExt, Record))
- {
- RtlFreeUnicodeString(&FileToFindUpcase);
- CcUnpinData(Context);
- return STATUS_DISK_CORRUPT_ERROR;
- }
-
- CdfsGetDirEntryName(DeviceExt, Record, Name);
- DPRINT ("Name '%S'\n", Name);
- DPRINT ("Sector %lu\n", DirectoryFcb->Entry.ExtentLocationL);
- DPRINT ("Offset %lu\n", Offset);
-
- RtlInitUnicodeString(&LongName, Name);
- RtlInitEmptyUnicodeString(&ShortName, ShortNameBuffer, sizeof(ShortNameBuffer));
- RtlZeroMemory(ShortNameBuffer, sizeof(ShortNameBuffer));
-
- OffsetOfEntry.QuadPart = StreamOffset.QuadPart + Offset;
- CdfsShortNameCacheGet(DirectoryFcb, &OffsetOfEntry, &LongName, &ShortName);
-
- DPRINT("ShortName '%wZ'\n", &ShortName);
-
- ASSERT(LongName.Length >= sizeof(WCHAR));
- ASSERT(ShortName.Length >= sizeof(WCHAR));
- if (FsRtlIsNameInExpression(&FileToFindUpcase, &LongName, TRUE, NULL) ||
- FsRtlIsNameInExpression(&FileToFindUpcase, &ShortName, TRUE, NULL))
- {
- DPRINT("Match found, %S\n", Name);
- Status = CdfsMakeFCBFromDirEntry(DeviceExt,
- DirectoryFcb,
- Name,
- ShortNameBuffer,
- Record,
- DirectoryFcb->Entry.ExtentLocationL,
- Offset,
- FoundFCB);
-
- RtlFreeUnicodeString(&FileToFindUpcase);
- 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;
-
- _SEH2_TRY
- {
- CcMapData(DeviceExt->StreamFileObject, &StreamOffset, BLOCKSIZE, MAP_WAIT, &Context, &Block);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- DPRINT("CcMapData() failed\n");
- RtlFreeUnicodeString(&FileToFindUpcase);
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- Record = (PDIR_RECORD)((ULONG_PTR)Block + BlockOffset);
- }
-
- if (Offset >= DirSize)
- break;
- }
-
- RtlFreeUnicodeString(&FileToFindUpcase);
- 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 NextElement;
- UNICODE_STRING CurrentElement;
- NTSTATUS Status;
- PFCB FCB;
- PFCB parentFCB;
-
- DPRINT("CdfsGetFCBForFile(%p, %p, %p, '%wZ')\n",
- Vcb,
- pParentFCB,
- pFCB,
- FileName);
-
- /* Trivial case, open of the root directory on volume */
- if (FileName->Length == 0 ||
- ((FileName->Buffer[0] == '\\') && (FileName->Length == sizeof(WCHAR))))
- {
- DPRINT("returning root FCB\n");
-
- FCB = CdfsOpenRootFCB(Vcb);
- *pFCB = FCB;
- *pParentFCB = NULL;
-
- return((FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND);
- }
- else
- {
- /* Start with empty path */
- PathName = *FileName;
- PathName.Length = 0;
- CurrentElement = *FileName;
-
- FCB = CdfsOpenRootFCB (Vcb);
- }
- parentFCB = NULL;
-
- /* Parse filename and check each path element for existence and access */
- while (CdfsGetNextPathElement(&CurrentElement, &NextElement))
- {
- /* Skip blank directory levels */
- if (CurrentElement.Buffer[0] == L'\\')
- {
- CurrentElement.Buffer++;
- CurrentElement.Length -= sizeof(WCHAR);
- CurrentElement.MaximumLength -= sizeof(WCHAR);
- continue;
- }
-
- DPRINT("Parsing, currentElement:%wZ\n", &CurrentElement);
- DPRINT(" parentFCB:%p FCB:%p\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 */
- PathName.Length = (NextElement.Buffer - FileName->Buffer) * sizeof(WCHAR);
- DPRINT(" PathName:%wZ\n", &PathName);
-
- FCB = CdfsGrabFCBFromTable(Vcb, &PathName);
- if (FCB == NULL)
- {
- UNICODE_STRING ChildElement = CurrentElement;
- ChildElement.Length = (NextElement.Buffer - CurrentElement.Buffer) * sizeof(WCHAR);
-
- Status = CdfsDirFindFile(Vcb,
- parentFCB,
- &ChildElement,
- &FCB);
- if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
- {
- *pParentFCB = parentFCB;
- *pFCB = NULL;
-
- if (NextElement.Length == 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 = NextElement;
- }
-
- *pParentFCB = parentFCB;
- *pFCB = FCB;
-
- return STATUS_SUCCESS;
-}
-
-/* EOF */