Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfcb.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
1.7.6.1
|