ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fcb.c
Go to the documentation of this file.
00001 /*
00002 *  ReactOS kernel
00003 *  Copyright (C) 2002, 2004 ReactOS Team
00004 *
00005 *  This program is free software; you can redistribute it and/or modify
00006 *  it under the terms of the GNU General Public License as published by
00007 *  the Free Software Foundation; either version 2 of the License, or
00008 *  (at your option) any later version.
00009 *
00010 *  This program is distributed in the hope that it will be useful,
00011 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 *  GNU General Public License for more details.
00014 *
00015 *  You should have received a copy of the GNU General Public License along
00016 *  with this program; if not, write to the Free Software Foundation, Inc.,
00017 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018 */
00019 /* $Id: fcb.c 48654 2010-08-30 11:51:17Z mjmartin $
00020 *
00021 * COPYRIGHT:        See COPYING in the top level directory
00022 * PROJECT:          ReactOS kernel
00023 * FILE:             services/fs/cdfs/fcb.c
00024 * PURPOSE:          CDROM (ISO 9660) filesystem driver
00025 * PROGRAMMER:       Art Yerkes
00026 * UPDATE HISTORY:
00027 */
00028 
00029 /* INCLUDES *****************************************************************/
00030 
00031 #include "cdfs.h"
00032 
00033 #define NDEBUG
00034 #include <debug.h>
00035 
00036 /* FUNCTIONS ****************************************************************/
00037 
00038 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
00039 
00040 
00041 /* FUNCTIONS ****************************************************************/
00042 
00043 static PWCHAR
00044 CdfsGetNextPathElement(PWCHAR FileName)
00045 {
00046     if (*FileName == L'\0')
00047     {
00048         return(NULL);
00049     }
00050 
00051     while (*FileName != L'\0' && *FileName != L'\\')
00052     {
00053         FileName++;
00054     }
00055 
00056     return(FileName);
00057 }
00058 
00059 
00060 static VOID
00061 CdfsWSubString(PWCHAR pTarget, const PWCHAR pSource, size_t pLength)
00062 {
00063     wcsncpy (pTarget, pSource, pLength);
00064     pTarget [pLength] = L'\0';
00065 }
00066 
00067 
00068 PFCB
00069 CdfsCreateFCB(PCWSTR FileName)
00070 {
00071     PFCB Fcb;
00072 
00073     Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB);
00074     if(!Fcb) return NULL;
00075 
00076     RtlZeroMemory(Fcb, sizeof(FCB));
00077 
00078     if (FileName)
00079     {
00080         wcscpy(Fcb->PathName, FileName);
00081         if (wcsrchr(Fcb->PathName, '\\') != 0)
00082         {
00083             Fcb->ObjectName = wcsrchr(Fcb->PathName, '\\');
00084         }
00085         else
00086         {
00087             Fcb->ObjectName = Fcb->PathName;
00088         }
00089     }
00090 
00091     ExInitializeResourceLite(&Fcb->PagingIoResource);
00092     ExInitializeResourceLite(&Fcb->MainResource);
00093     ExInitializeResourceLite(&Fcb->NameListResource);
00094     Fcb->RFCB.PagingIoResource = &Fcb->PagingIoResource;
00095     Fcb->RFCB.Resource = &Fcb->MainResource;
00096     Fcb->RFCB.IsFastIoPossible = FastIoIsNotPossible;
00097     InitializeListHead(&Fcb->ShortNameList);
00098 
00099     return(Fcb);
00100 }
00101 
00102 
00103 VOID
00104 CdfsDestroyFCB(PFCB Fcb)
00105 {
00106     PLIST_ENTRY Entry;
00107 
00108     ExDeleteResourceLite(&Fcb->PagingIoResource);
00109     ExDeleteResourceLite(&Fcb->MainResource);
00110 
00111     while (!IsListEmpty(&Fcb->ShortNameList))
00112     {
00113         Entry = Fcb->ShortNameList.Flink;
00114         RemoveEntryList(Entry);
00115         ExFreePoolWithTag(Entry, TAG_FCB);
00116     }
00117 
00118     ExDeleteResourceLite(&Fcb->NameListResource);
00119     ExFreePoolWithTag(Fcb, TAG_FCB);
00120 }
00121 
00122 
00123 BOOLEAN
00124 CdfsFCBIsDirectory(PFCB Fcb)
00125 {
00126     return(Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY);
00127 }
00128 
00129 
00130 BOOLEAN
00131 CdfsFCBIsRoot(PFCB Fcb)
00132 {
00133     return(wcscmp(Fcb->PathName, L"\\") == 0);
00134 }
00135 
00136 
00137 VOID
00138 CdfsGrabFCB(PDEVICE_EXTENSION Vcb,
00139             PFCB Fcb)
00140 {
00141     KIRQL  oldIrql;
00142 
00143     DPRINT("grabbing FCB at %x: %S, refCount:%d\n",
00144         Fcb,
00145         Fcb->PathName,
00146         Fcb->RefCount);
00147 
00148     KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
00149     Fcb->RefCount++;
00150     KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
00151 }
00152 
00153 
00154 VOID
00155 CdfsReleaseFCB(PDEVICE_EXTENSION Vcb,
00156                PFCB Fcb)
00157 {
00158     KIRQL  oldIrql;
00159 
00160     DPRINT("releasing FCB at %x: %S, refCount:%d\n",
00161         Fcb,
00162         Fcb->PathName,
00163         Fcb->RefCount);
00164 
00165     KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
00166     Fcb->RefCount--;
00167     if (Fcb->RefCount <= 0 && !CdfsFCBIsDirectory(Fcb))
00168     {
00169         RemoveEntryList(&Fcb->FcbListEntry);
00170         CdfsDestroyFCB(Fcb);
00171     }
00172     KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
00173 }
00174 
00175 
00176 VOID
00177 CdfsAddFCBToTable(PDEVICE_EXTENSION Vcb,
00178                   PFCB Fcb)
00179 {
00180     KIRQL  oldIrql;
00181 
00182     KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
00183     Fcb->DevExt = Vcb;
00184     InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry);
00185     KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
00186 }
00187 
00188 
00189 PFCB
00190 CdfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb,
00191                      PUNICODE_STRING FileName)
00192 {
00193     KIRQL  oldIrql;
00194     PFCB Fcb;
00195     PLIST_ENTRY  current_entry;
00196 
00197     KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
00198 
00199     if (FileName == NULL || FileName->Length == 0 || FileName->Buffer[0] == 0)
00200     {
00201         DPRINT("Return FCB for stream file object\n");
00202         Fcb = Vcb->StreamFileObject->FsContext;
00203         Fcb->RefCount++;
00204         KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
00205         return(Fcb);
00206     }
00207 
00208     current_entry = Vcb->FcbListHead.Flink;
00209     while (current_entry != &Vcb->FcbListHead)
00210     {
00211         Fcb = CONTAINING_RECORD(current_entry, FCB, FcbListEntry);
00212 
00213         DPRINT("Comparing '%wZ' and '%S'\n", FileName, Fcb->PathName);
00214         if (_wcsicmp(FileName->Buffer, Fcb->PathName) == 0)
00215         {
00216             Fcb->RefCount++;
00217             KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
00218             return(Fcb);
00219         }
00220 
00221         //FIXME: need to compare against short name in FCB here
00222 
00223         current_entry = current_entry->Flink;
00224     }
00225     KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
00226 
00227     return(NULL);
00228 }
00229 
00230 
00231 NTSTATUS
00232 CdfsFCBInitializeCache(PVCB Vcb,
00233                        PFCB Fcb)
00234 {
00235     PFILE_OBJECT FileObject;
00236     PCCB  newCCB;
00237 
00238     FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice);
00239 
00240     newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB);
00241     if (newCCB == NULL)
00242     {
00243         return STATUS_INSUFFICIENT_RESOURCES;
00244     }
00245     RtlZeroMemory(newCCB,
00246         sizeof(CCB));
00247 
00248     FileObject->ReadAccess = TRUE;
00249     FileObject->WriteAccess = FALSE;
00250     FileObject->DeleteAccess = FALSE;
00251     FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
00252     FileObject->FsContext = Fcb;
00253     FileObject->FsContext2 = newCCB;
00254     newCCB->PtrFileObject = FileObject;
00255     Fcb->FileObject = FileObject;
00256     Fcb->DevExt = Vcb;
00257 
00258     CcInitializeCacheMap(FileObject,
00259         (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
00260         FALSE,
00261         &(CdfsGlobalData->CacheMgrCallbacks),
00262         Fcb);
00263 
00264     ObDereferenceObject(FileObject);
00265     Fcb->Flags |= FCB_CACHE_INITIALIZED;
00266 
00267     return STATUS_SUCCESS;
00268 }
00269 
00270 
00271 PFCB
00272 CdfsMakeRootFCB(PDEVICE_EXTENSION Vcb)
00273 {
00274     PFCB Fcb;
00275 
00276     Fcb = CdfsCreateFCB(L"\\");
00277 
00278     Fcb->Entry.DataLengthL = Vcb->CdInfo.RootSize;
00279     Fcb->Entry.ExtentLocationL = Vcb->CdInfo.RootStart;
00280     Fcb->Entry.FileFlags = FILE_FLAG_DIRECTORY;
00281     Fcb->IndexNumber.QuadPart = 0LL;
00282     Fcb->RefCount = 1;
00283     Fcb->DirIndex = 0;
00284     Fcb->RFCB.FileSize.QuadPart = Vcb->CdInfo.RootSize;
00285     Fcb->RFCB.ValidDataLength.QuadPart = Vcb->CdInfo.RootSize;
00286     Fcb->RFCB.AllocationSize.QuadPart = Vcb->CdInfo.RootSize;
00287 
00288     CdfsFCBInitializeCache(Vcb, Fcb);
00289     CdfsAddFCBToTable(Vcb, Fcb);
00290     CdfsGrabFCB(Vcb, Fcb);
00291 
00292     return(Fcb);
00293 }
00294 
00295 
00296 PFCB
00297 CdfsOpenRootFCB(PDEVICE_EXTENSION Vcb)
00298 {
00299     UNICODE_STRING FileName;
00300     PFCB Fcb;
00301 
00302     RtlInitUnicodeString(&FileName, L"\\");
00303 
00304     Fcb = CdfsGrabFCBFromTable(Vcb,
00305         &FileName);
00306     if (Fcb == NULL)
00307     {
00308         Fcb = CdfsMakeRootFCB(Vcb);
00309     }
00310 
00311     return(Fcb);
00312 }
00313 
00314 
00315 static VOID
00316 CdfsGetDirEntryName(PDEVICE_EXTENSION DeviceExt,
00317                     PDIR_RECORD Record,
00318                     PWSTR Name)
00319                     /*
00320                     * FUNCTION: Retrieves the file name from a directory record.
00321                     */
00322 {
00323     if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
00324     {
00325         wcscpy(Name, L".");
00326     }
00327     else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
00328     {
00329         wcscpy(Name, L"..");
00330     }
00331     else
00332     {
00333         if (DeviceExt->CdInfo.JolietLevel == 0)
00334         {
00335             ULONG i;
00336 
00337             for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
00338                 Name[i] = (WCHAR)Record->FileId[i];
00339             Name[i] = 0;
00340         }
00341         else
00342         {
00343             CdfsSwapString(Name,
00344                 Record->FileId,
00345                 Record->FileIdLength);
00346         }
00347     }
00348 
00349     DPRINT("Name '%S'\n", Name);
00350 }
00351 
00352 
00353 NTSTATUS
00354 CdfsMakeFCBFromDirEntry(PVCB Vcb,
00355                         PFCB DirectoryFCB,
00356                         PWSTR LongName,
00357                         PWSTR ShortName,
00358                         PDIR_RECORD Record,
00359                         ULONG DirectorySector,
00360                         ULONG DirectoryOffset,
00361                         PFCB * fileFCB)
00362 {
00363     WCHAR pathName[MAX_PATH];
00364     PFCB rcFCB;
00365     ULONG Size;
00366 
00367     if (LongName [0] != 0 && wcslen (DirectoryFCB->PathName) +
00368         sizeof(WCHAR) + wcslen (LongName) > MAX_PATH)
00369     {
00370         return(STATUS_OBJECT_NAME_INVALID);
00371     }
00372 
00373     wcscpy(pathName, DirectoryFCB->PathName);
00374     if (!CdfsFCBIsRoot(DirectoryFCB))
00375     {
00376         wcscat(pathName, L"\\");
00377     }
00378 
00379     if (LongName[0] != 0)
00380     {
00381         wcscat(pathName, LongName);
00382     }
00383     else
00384     {
00385         WCHAR entryName[MAX_PATH];
00386 
00387         CdfsGetDirEntryName(Vcb, Record, entryName);
00388         wcscat(pathName, entryName);
00389     }
00390 
00391     rcFCB = CdfsCreateFCB(pathName);
00392     memcpy(&rcFCB->Entry, Record, sizeof(DIR_RECORD));
00393 
00394     /* Copy short name into FCB */
00395     rcFCB->ShortNameU.Length = wcslen(ShortName) * sizeof(WCHAR);
00396     rcFCB->ShortNameU.MaximumLength = rcFCB->ShortNameU.Length;
00397     rcFCB->ShortNameU.Buffer = rcFCB->ShortNameBuffer;
00398     wcscpy(rcFCB->ShortNameBuffer, ShortName);
00399 
00400     Size = rcFCB->Entry.DataLengthL;
00401 
00402     rcFCB->RFCB.FileSize.QuadPart = Size;
00403     rcFCB->RFCB.ValidDataLength.QuadPart = Size;
00404     rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, BLOCKSIZE);
00405     if (CdfsFCBIsDirectory(rcFCB))
00406     {
00407         CdfsFCBInitializeCache(Vcb, rcFCB);
00408     }
00409     rcFCB->IndexNumber.u.HighPart = DirectorySector;
00410     rcFCB->IndexNumber.u.LowPart = DirectoryOffset;
00411     rcFCB->RefCount++;
00412     CdfsAddFCBToTable(Vcb, rcFCB);
00413     *fileFCB = rcFCB;
00414 
00415     DPRINT("%S %d %I64d\n", LongName, Size, rcFCB->RFCB.AllocationSize.QuadPart);
00416 
00417     return(STATUS_SUCCESS);
00418 }
00419 
00420 
00421 NTSTATUS
00422 CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb,
00423                           PFCB Fcb,
00424                           PFILE_OBJECT FileObject)
00425 {
00426     PCCB  newCCB;
00427 
00428     newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB);
00429     if (newCCB == NULL)
00430     {
00431         return(STATUS_INSUFFICIENT_RESOURCES);
00432     }
00433     memset(newCCB, 0, sizeof(CCB));
00434 
00435     FileObject->ReadAccess = TRUE;
00436     FileObject->WriteAccess = FALSE;
00437     FileObject->DeleteAccess = FALSE;
00438     FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
00439     FileObject->FsContext = Fcb;
00440     FileObject->FsContext2 = newCCB;
00441     newCCB->PtrFileObject = FileObject;
00442     Fcb->DevExt = Vcb;
00443 
00444     if (CdfsFCBIsDirectory(Fcb))
00445     {
00446         CcInitializeCacheMap(FileObject,
00447             (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
00448             FALSE,
00449             &(CdfsGlobalData->CacheMgrCallbacks),
00450             Fcb);
00451         Fcb->Flags |= FCB_CACHE_INITIALIZED;
00452     }
00453 
00454     DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL);
00455 
00456     return(STATUS_SUCCESS);
00457 }
00458 
00459 
00460 NTSTATUS
00461 CdfsDirFindFile(PDEVICE_EXTENSION DeviceExt,
00462                 PFCB DirectoryFcb,
00463                 PUNICODE_STRING FileToFind,
00464                 PFCB *FoundFCB)
00465 {
00466     UNICODE_STRING TempName;
00467     WCHAR Name[256];
00468     PVOID Block;
00469     ULONG DirSize;
00470     PDIR_RECORD Record;
00471     ULONG Offset;
00472     ULONG BlockOffset;
00473     NTSTATUS Status;
00474 
00475     LARGE_INTEGER StreamOffset, OffsetOfEntry;
00476     PVOID Context;
00477 
00478     WCHAR ShortNameBuffer[13];
00479     UNICODE_STRING ShortName;
00480     UNICODE_STRING LongName;
00481     UNICODE_STRING FileToFindUpcase;
00482 
00483     ASSERT(DeviceExt);
00484     ASSERT(DirectoryFcb);
00485     ASSERT(FileToFind);
00486 
00487     DPRINT("CdfsDirFindFile(VCB:%p, dirFCB:%p, File:%wZ)\n",
00488         DeviceExt,
00489         DirectoryFcb,
00490         FileToFind);
00491     DPRINT("Dir Path:%S\n", DirectoryFcb->PathName);
00492 
00493     /* default to '.' if no filename specified */
00494     if (FileToFind->Length == 0)
00495     {
00496         RtlInitUnicodeString(&TempName, L".");
00497         FileToFind = &TempName;
00498     }
00499 
00500     DirSize = DirectoryFcb->Entry.DataLengthL;
00501     StreamOffset.QuadPart = (LONGLONG)DirectoryFcb->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;
00502 
00503     if (!CcMapData(DeviceExt->StreamFileObject,
00504         &StreamOffset,
00505         BLOCKSIZE,
00506         TRUE,
00507         &Context,
00508         &Block))
00509     {
00510         DPRINT("CcMapData() failed\n");
00511         return STATUS_UNSUCCESSFUL;
00512     }
00513 
00514     Offset = 0;
00515     BlockOffset = 0;
00516     Record = (PDIR_RECORD)Block;
00517 
00518     /* Upper case the expression for FsRtlIsNameInExpression */
00519     Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFind, TRUE);
00520     if (!NT_SUCCESS(Status))
00521     {
00522         return Status;
00523     }
00524 
00525     while(TRUE)
00526     {
00527         if (Record->RecordLength == 0)
00528         {
00529             DPRINT("RecordLength == 0  Stopped!\n");
00530             break;
00531         }
00532 
00533         DPRINT("RecordLength %u  ExtAttrRecordLength %u  NameLength %u\n",
00534             Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);
00535 
00536         CdfsGetDirEntryName(DeviceExt, Record, Name);
00537         DPRINT ("Name '%S'\n", Name);
00538         DPRINT ("Sector %lu\n", DirectoryFcb->Entry.ExtentLocationL);
00539         DPRINT ("Offset %lu\n", Offset);
00540 
00541         RtlInitUnicodeString(&LongName, Name);
00542         ShortName.Length = 0;
00543         ShortName.MaximumLength = 26;
00544         ShortName.Buffer = ShortNameBuffer;
00545         memset(ShortNameBuffer, 0, 26);
00546 
00547         OffsetOfEntry.QuadPart = StreamOffset.QuadPart + Offset;
00548         CdfsShortNameCacheGet(DirectoryFcb, &OffsetOfEntry, &LongName, &ShortName);
00549 
00550         DPRINT("ShortName '%wZ'\n", &ShortName);
00551 
00552         if (FsRtlIsNameInExpression(&FileToFindUpcase, &LongName, TRUE, NULL) ||
00553             FsRtlIsNameInExpression(&FileToFindUpcase, &ShortName, TRUE, NULL))
00554         {
00555             DPRINT("Match found, %S\n", Name);
00556             Status = CdfsMakeFCBFromDirEntry(DeviceExt,
00557                 DirectoryFcb,
00558                 Name,
00559                 ShortNameBuffer,
00560                 Record,
00561                 DirectoryFcb->Entry.ExtentLocationL,
00562                 Offset,
00563                 FoundFCB);
00564 
00565             RtlFreeUnicodeString(&FileToFindUpcase);
00566             CcUnpinData(Context);
00567 
00568             return(Status);
00569         }
00570 
00571         Offset += Record->RecordLength;
00572         BlockOffset += Record->RecordLength;
00573         Record = (PDIR_RECORD)((ULONG_PTR)Block + BlockOffset);
00574         if (BlockOffset >= BLOCKSIZE || Record->RecordLength == 0)
00575         {
00576             DPRINT("Map next sector\n");
00577             CcUnpinData(Context);
00578             StreamOffset.QuadPart += BLOCKSIZE;
00579             Offset = ROUND_UP(Offset, BLOCKSIZE);
00580             BlockOffset = 0;
00581 
00582             if (!CcMapData(DeviceExt->StreamFileObject,
00583                 &StreamOffset,
00584                 BLOCKSIZE, TRUE,
00585                 &Context, &Block))
00586             {
00587                 DPRINT("CcMapData() failed\n");
00588                 RtlFreeUnicodeString(&FileToFindUpcase);
00589                 return(STATUS_UNSUCCESSFUL);
00590             }
00591             Record = (PDIR_RECORD)((ULONG_PTR)Block + BlockOffset);
00592         }
00593 
00594         if (Offset >= DirSize)
00595             break;
00596     }
00597 
00598     RtlFreeUnicodeString(&FileToFindUpcase);
00599     CcUnpinData(Context);
00600 
00601     return(STATUS_OBJECT_NAME_NOT_FOUND);
00602 }
00603 
00604 
00605 NTSTATUS
00606 CdfsGetFCBForFile(PDEVICE_EXTENSION Vcb,
00607                   PFCB *pParentFCB,
00608                   PFCB *pFCB,
00609                   PUNICODE_STRING FileName)
00610 {
00611     UNICODE_STRING PathName;
00612     UNICODE_STRING ElementName;
00613     NTSTATUS Status;
00614     WCHAR  pathName [MAX_PATH];
00615     WCHAR  elementName [MAX_PATH];
00616     PWCHAR  currentElement;
00617     PFCB  FCB;
00618     PFCB  parentFCB;
00619 
00620     DPRINT("CdfsGetFCBForFile(%x, %x, %x, '%wZ')\n",
00621         Vcb,
00622         pParentFCB,
00623         pFCB,
00624         FileName);
00625 
00626     /* Trivial case, open of the root directory on volume */
00627     if (FileName->Buffer[0] == L'\0' || wcscmp(FileName->Buffer, L"\\") == 0)
00628     {
00629         DPRINT("returning root FCB\n");
00630 
00631         FCB = CdfsOpenRootFCB(Vcb);
00632         *pFCB = FCB;
00633         *pParentFCB = NULL;
00634 
00635         return((FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND);
00636     }
00637     else
00638     {
00639         currentElement = &FileName->Buffer[1];
00640         wcscpy (pathName, L"\\");
00641         FCB = CdfsOpenRootFCB (Vcb);
00642     }
00643     parentFCB = NULL;
00644 
00645     /* Parse filename and check each path element for existance and access */
00646     while (CdfsGetNextPathElement(currentElement) != 0)
00647     {
00648         /*  Skip blank directory levels */
00649         if ((CdfsGetNextPathElement(currentElement) - currentElement) == 0)
00650         {
00651             currentElement++;
00652             continue;
00653         }
00654 
00655         DPRINT("Parsing, currentElement:%S\n", currentElement);
00656         DPRINT("  parentFCB:%x FCB:%x\n", parentFCB, FCB);
00657 
00658         /* Descend to next directory level */
00659         if (parentFCB)
00660         {
00661             CdfsReleaseFCB(Vcb, parentFCB);
00662             parentFCB = NULL;
00663         }
00664 
00665         /* fail if element in FCB is not a directory */
00666         if (!CdfsFCBIsDirectory(FCB))
00667         {
00668             DPRINT("Element in requested path is not a directory\n");
00669 
00670             CdfsReleaseFCB(Vcb, FCB);
00671             FCB = 0;
00672             *pParentFCB = NULL;
00673             *pFCB = NULL;
00674 
00675             return(STATUS_OBJECT_PATH_NOT_FOUND);
00676         }
00677         parentFCB = FCB;
00678 
00679         /* Extract next directory level into dirName */
00680         CdfsWSubString(pathName,
00681             FileName->Buffer,
00682             CdfsGetNextPathElement(currentElement) - FileName->Buffer);
00683         DPRINT("  pathName:%S\n", pathName);
00684 
00685         RtlInitUnicodeString(&PathName, pathName);
00686 
00687         FCB = CdfsGrabFCBFromTable(Vcb, &PathName);
00688         if (FCB == NULL)
00689         {
00690             CdfsWSubString(elementName,
00691                 currentElement,
00692                 CdfsGetNextPathElement(currentElement) - currentElement);
00693             DPRINT("  elementName:%S\n", elementName);
00694 
00695             RtlInitUnicodeString(&ElementName, elementName);
00696             Status = CdfsDirFindFile(Vcb,
00697                 parentFCB,
00698                 &ElementName,
00699                 &FCB);
00700             if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
00701             {
00702                 *pParentFCB = parentFCB;
00703                 *pFCB = NULL;
00704                 currentElement = CdfsGetNextPathElement(currentElement);
00705                 if (*currentElement == L'\0' || CdfsGetNextPathElement(currentElement + 1) == 0)
00706                 {
00707                     return(STATUS_OBJECT_NAME_NOT_FOUND);
00708                 }
00709                 else
00710                 {
00711                     return(STATUS_OBJECT_PATH_NOT_FOUND);
00712                 }
00713             }
00714             else if (!NT_SUCCESS(Status))
00715             {
00716                 CdfsReleaseFCB(Vcb, parentFCB);
00717                 *pParentFCB = NULL;
00718                 *pFCB = NULL;
00719 
00720                 return(Status);
00721             }
00722         }
00723         currentElement = CdfsGetNextPathElement(currentElement);
00724     }
00725 
00726     *pParentFCB = parentFCB;
00727     *pFCB = FCB;
00728 
00729     return STATUS_SUCCESS;
00730 }
00731 
00732 /* EOF */

Generated on Sun May 27 2012 04:27:35 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.