Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfcb.c
Go to the documentation of this file.
00001 /* 00002 * FILE: drivers/fs/vfat/fcb.c 00003 * PURPOSE: Routines to manipulate FCBs. 00004 * COPYRIGHT: See COPYING in the top level directory 00005 * PROJECT: ReactOS kernel 00006 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) 00007 * Rex Jolliff (rex@lvcablemodem.com) 00008 * Herve Poussineau (reactos@poussine.freesurf.fr) 00009 */ 00010 00011 /* ------------------------------------------------------- INCLUDES */ 00012 00013 #ifdef __GNUC__ 00014 #include <wctype.h> /* towlower prototype */ 00015 #endif 00016 00017 #define NDEBUG 00018 #include "vfat.h" 00019 00020 /* -------------------------------------------------------- DEFINES */ 00021 00022 #define TAG_FCB 'BCFV' 00023 00024 /* -------------------------------------------------------- PUBLICS */ 00025 00026 static ULONG vfatNameHash(ULONG hash, PUNICODE_STRING NameU) 00027 { 00028 PWCHAR last; 00029 PWCHAR curr; 00030 register WCHAR c; 00031 00032 // LFN could start from "." 00033 //ASSERT(NameU->Buffer[0] != L'.'); 00034 curr = NameU->Buffer; 00035 last = NameU->Buffer + NameU->Length / sizeof(WCHAR); 00036 00037 while(curr < last) 00038 { 00039 c = towlower(*curr++); 00040 hash = (hash + (c << 4) + (c >> 4)) * 11; 00041 } 00042 return hash; 00043 } 00044 00045 VOID 00046 vfatSplitPathName(PUNICODE_STRING PathNameU, PUNICODE_STRING DirNameU, PUNICODE_STRING FileNameU) 00047 { 00048 PWCHAR pName; 00049 USHORT Length = 0; 00050 pName = PathNameU->Buffer + PathNameU->Length / sizeof(WCHAR) - 1; 00051 while (*pName != L'\\' && pName >= PathNameU->Buffer) 00052 { 00053 pName--; 00054 Length++; 00055 } 00056 ASSERT(*pName == L'\\' || pName < PathNameU->Buffer); 00057 if (FileNameU) 00058 { 00059 FileNameU->Buffer = pName + 1; 00060 FileNameU->Length = FileNameU->MaximumLength = Length * sizeof(WCHAR); 00061 } 00062 if (DirNameU) 00063 { 00064 DirNameU->Buffer = PathNameU->Buffer; 00065 DirNameU->Length = (pName + 1 - PathNameU->Buffer) * sizeof(WCHAR); 00066 DirNameU->MaximumLength = DirNameU->Length; 00067 } 00068 } 00069 00070 static VOID 00071 vfatInitFcb(PVFATFCB Fcb, PUNICODE_STRING NameU) 00072 { 00073 USHORT PathNameBufferLength; 00074 00075 if (NameU) 00076 PathNameBufferLength = NameU->Length + sizeof(WCHAR); 00077 else 00078 PathNameBufferLength = 0; 00079 00080 Fcb->PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameBufferLength, TAG_FCB); 00081 if (!Fcb->PathNameBuffer) 00082 { 00083 /* FIXME: what to do if no more memory? */ 00084 DPRINT1("Unable to initialize FCB for filename '%wZ'\n", NameU); 00085 KeBugCheckEx(FAT_FILE_SYSTEM, (ULONG_PTR)Fcb, (ULONG_PTR)NameU, 0, 0); 00086 } 00087 00088 Fcb->PathNameU.Length = 0; 00089 Fcb->PathNameU.Buffer = Fcb->PathNameBuffer; 00090 Fcb->PathNameU.MaximumLength = PathNameBufferLength; 00091 Fcb->ShortNameU.Length = 0; 00092 Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer; 00093 Fcb->ShortNameU.MaximumLength = sizeof(Fcb->ShortNameBuffer); 00094 Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer; 00095 if (NameU && NameU->Length) 00096 { 00097 RtlCopyUnicodeString(&Fcb->PathNameU, NameU); 00098 vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU); 00099 } 00100 else 00101 { 00102 Fcb->DirNameU.Buffer = Fcb->LongNameU.Buffer = NULL; 00103 Fcb->DirNameU.MaximumLength = Fcb->DirNameU.Length = 0; 00104 Fcb->LongNameU.MaximumLength = Fcb->LongNameU.Length = 0; 00105 } 00106 RtlZeroMemory(&Fcb->FCBShareAccess, sizeof(SHARE_ACCESS)); 00107 Fcb->OpenHandleCount = 0; 00108 } 00109 00110 PVFATFCB 00111 vfatNewFCB(PDEVICE_EXTENSION pVCB, PUNICODE_STRING pFileNameU) 00112 { 00113 PVFATFCB rcFCB; 00114 00115 DPRINT("'%wZ'\n", pFileNameU); 00116 00117 rcFCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->FcbLookasideList); 00118 if (rcFCB == NULL) 00119 { 00120 return NULL; 00121 } 00122 RtlZeroMemory(rcFCB, sizeof(VFATFCB)); 00123 vfatInitFcb(rcFCB, pFileNameU); 00124 if (pVCB->Flags & VCB_IS_FATX) 00125 { 00126 rcFCB->Flags |= FCB_IS_FATX_ENTRY; 00127 rcFCB->Attributes = &rcFCB->entry.FatX.Attrib; 00128 } 00129 else 00130 rcFCB->Attributes = &rcFCB->entry.Fat.Attrib; 00131 rcFCB->Hash.Hash = vfatNameHash(0, &rcFCB->PathNameU); 00132 rcFCB->Hash.self = rcFCB; 00133 rcFCB->ShortHash.self = rcFCB; 00134 ExInitializeResourceLite(&rcFCB->PagingIoResource); 00135 ExInitializeResourceLite(&rcFCB->MainResource); 00136 FsRtlInitializeFileLock(&rcFCB->FileLock, NULL, NULL); 00137 ExInitializeFastMutex(&rcFCB->LastMutex); 00138 rcFCB->RFCB.PagingIoResource = &rcFCB->PagingIoResource; 00139 rcFCB->RFCB.Resource = &rcFCB->MainResource; 00140 rcFCB->RFCB.IsFastIoPossible = FastIoIsNotPossible; 00141 00142 return rcFCB; 00143 } 00144 00145 VOID 00146 vfatDestroyCCB(PVFATCCB pCcb) 00147 { 00148 if (pCcb->SearchPattern.Buffer) 00149 { 00150 ExFreePool(pCcb->SearchPattern.Buffer); 00151 } 00152 ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, pCcb); 00153 } 00154 00155 VOID 00156 vfatDestroyFCB(PVFATFCB pFCB) 00157 { 00158 FsRtlUninitializeFileLock(&pFCB->FileLock); 00159 ExFreePool(pFCB->PathNameBuffer); 00160 ExDeleteResourceLite(&pFCB->PagingIoResource); 00161 ExDeleteResourceLite(&pFCB->MainResource); 00162 ExFreeToNPagedLookasideList(&VfatGlobalData->FcbLookasideList, pFCB); 00163 } 00164 00165 BOOLEAN 00166 vfatFCBIsDirectory(PVFATFCB FCB) 00167 { 00168 return *FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY; 00169 } 00170 00171 BOOLEAN 00172 vfatFCBIsRoot(PVFATFCB FCB) 00173 { 00174 return FCB->PathNameU.Length == sizeof(WCHAR) && FCB->PathNameU.Buffer[0] == L'\\' ? TRUE : FALSE; 00175 } 00176 00177 VOID 00178 vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB) 00179 { 00180 HASHENTRY* entry; 00181 ULONG Index; 00182 ULONG ShortIndex; 00183 PVFATFCB tmpFcb; 00184 00185 DPRINT ("releasing FCB at %p: %wZ, refCount:%d\n", 00186 pFCB, 00187 &pFCB->PathNameU, 00188 pFCB->RefCount); 00189 00190 while (pFCB) 00191 { 00192 Index = pFCB->Hash.Hash % pVCB->HashTableSize; 00193 ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize; 00194 pFCB->RefCount--; 00195 if (pFCB->RefCount == 0) 00196 { 00197 tmpFcb = pFCB->parentFcb; 00198 RemoveEntryList (&pFCB->FcbListEntry); 00199 if (pFCB->Hash.Hash != pFCB->ShortHash.Hash) 00200 { 00201 entry = pVCB->FcbHashTable[ShortIndex]; 00202 if (entry->self == pFCB) 00203 { 00204 pVCB->FcbHashTable[ShortIndex] = entry->next; 00205 } 00206 else 00207 { 00208 while (entry->next->self != pFCB) 00209 { 00210 entry = entry->next; 00211 } 00212 entry->next = pFCB->ShortHash.next; 00213 } 00214 } 00215 entry = pVCB->FcbHashTable[Index]; 00216 if (entry->self == pFCB) 00217 { 00218 pVCB->FcbHashTable[Index] = entry->next; 00219 } 00220 else 00221 { 00222 while (entry->next->self != pFCB) 00223 { 00224 entry = entry->next; 00225 } 00226 entry->next = pFCB->Hash.next; 00227 } 00228 vfatDestroyFCB (pFCB); 00229 } 00230 else 00231 { 00232 tmpFcb = NULL; 00233 } 00234 pFCB = tmpFcb; 00235 } 00236 } 00237 00238 VOID 00239 vfatAddFCBToTable(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB) 00240 { 00241 ULONG Index; 00242 ULONG ShortIndex; 00243 00244 Index = pFCB->Hash.Hash % pVCB->HashTableSize; 00245 ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize; 00246 00247 InsertTailList (&pVCB->FcbListHead, &pFCB->FcbListEntry); 00248 00249 pFCB->Hash.next = pVCB->FcbHashTable[Index]; 00250 pVCB->FcbHashTable[Index] = &pFCB->Hash; 00251 if (pFCB->Hash.Hash != pFCB->ShortHash.Hash) 00252 { 00253 pFCB->ShortHash.next = pVCB->FcbHashTable[ShortIndex]; 00254 pVCB->FcbHashTable[ShortIndex] = &pFCB->ShortHash; 00255 } 00256 if (pFCB->parentFcb) 00257 { 00258 pFCB->parentFcb->RefCount++; 00259 } 00260 } 00261 00262 PVFATFCB 00263 vfatGrabFCBFromTable(PDEVICE_EXTENSION pVCB, PUNICODE_STRING PathNameU) 00264 { 00265 PVFATFCB rcFCB; 00266 ULONG Hash; 00267 UNICODE_STRING DirNameU; 00268 UNICODE_STRING FileNameU; 00269 PUNICODE_STRING FcbNameU; 00270 00271 HASHENTRY* entry; 00272 00273 DPRINT("'%wZ'\n", PathNameU); 00274 00275 Hash = vfatNameHash(0, PathNameU); 00276 00277 entry = pVCB->FcbHashTable[Hash % pVCB->HashTableSize]; 00278 if (entry) 00279 { 00280 vfatSplitPathName(PathNameU, &DirNameU, &FileNameU); 00281 } 00282 00283 while (entry) 00284 { 00285 if (entry->Hash == Hash) 00286 { 00287 rcFCB = entry->self; 00288 DPRINT("'%wZ' '%wZ'\n", &DirNameU, &rcFCB->DirNameU); 00289 if (RtlEqualUnicodeString(&DirNameU, &rcFCB->DirNameU, TRUE)) 00290 { 00291 if (rcFCB->Hash.Hash == Hash) 00292 { 00293 FcbNameU = &rcFCB->LongNameU; 00294 } 00295 else 00296 { 00297 FcbNameU = &rcFCB->ShortNameU; 00298 } 00299 /* compare the file name */ 00300 DPRINT("'%wZ' '%wZ'\n", &FileNameU, FcbNameU); 00301 if (RtlEqualUnicodeString(&FileNameU, FcbNameU, TRUE)) 00302 { 00303 rcFCB->RefCount++; 00304 return rcFCB; 00305 } 00306 } 00307 } 00308 entry = entry->next; 00309 } 00310 return NULL; 00311 } 00312 00313 static NTSTATUS 00314 vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb) 00315 { 00316 PFILE_OBJECT fileObject; 00317 PVFATCCB newCCB; 00318 00319 fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice); 00320 00321 newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList); 00322 if (newCCB == NULL) 00323 { 00324 return STATUS_INSUFFICIENT_RESOURCES; 00325 } 00326 RtlZeroMemory(newCCB, sizeof (VFATCCB)); 00327 00328 fileObject->SectionObjectPointer = &fcb->SectionObjectPointers; 00329 fileObject->FsContext = fcb; 00330 fileObject->FsContext2 = newCCB; 00331 fcb->FileObject = fileObject; 00332 fcb->RefCount++; 00333 00334 CcInitializeCacheMap(fileObject, 00335 (PCC_FILE_SIZES)(&fcb->RFCB.AllocationSize), 00336 TRUE, 00337 &VfatGlobalData->CacheMgrCallbacks, 00338 fcb); 00339 00340 fcb->Flags |= FCB_CACHE_INITIALIZED; 00341 return STATUS_SUCCESS; 00342 } 00343 00344 PVFATFCB 00345 vfatMakeRootFCB(PDEVICE_EXTENSION pVCB) 00346 { 00347 PVFATFCB FCB; 00348 ULONG FirstCluster, CurrentCluster, Size = 0; 00349 NTSTATUS Status = STATUS_SUCCESS; 00350 UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\"); 00351 00352 FCB = vfatNewFCB(pVCB, &NameU); 00353 if (FCB->Flags & FCB_IS_FATX_ENTRY) 00354 { 00355 memset(FCB->entry.FatX.Filename, ' ', 42); 00356 FCB->entry.FatX.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector; 00357 FCB->entry.FatX.Attrib = FILE_ATTRIBUTE_DIRECTORY; 00358 FCB->entry.FatX.FirstCluster = 1; 00359 Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector; 00360 } 00361 else 00362 { 00363 memset(FCB->entry.Fat.ShortName, ' ', 11); 00364 FCB->entry.Fat.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector; 00365 FCB->entry.Fat.Attrib = FILE_ATTRIBUTE_DIRECTORY; 00366 if (pVCB->FatInfo.FatType == FAT32) 00367 { 00368 CurrentCluster = FirstCluster = pVCB->FatInfo.RootCluster; 00369 FCB->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0xffff); 00370 FCB->entry.Fat.FirstClusterHigh = (unsigned short)(FirstCluster >> 16); 00371 00372 while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status)) 00373 { 00374 Size += pVCB->FatInfo.BytesPerCluster; 00375 Status = NextCluster (pVCB, FirstCluster, &CurrentCluster, FALSE); 00376 } 00377 } 00378 else 00379 { 00380 FCB->entry.Fat.FirstCluster = 1; 00381 Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector; 00382 } 00383 } 00384 FCB->ShortHash.Hash = FCB->Hash.Hash; 00385 FCB->RefCount = 2; 00386 FCB->dirIndex = 0; 00387 FCB->RFCB.FileSize.QuadPart = Size; 00388 FCB->RFCB.ValidDataLength.QuadPart = Size; 00389 FCB->RFCB.AllocationSize.QuadPart = Size; 00390 FCB->RFCB.IsFastIoPossible = FastIoIsNotPossible; 00391 00392 vfatFCBInitializeCacheFromVolume(pVCB, FCB); 00393 vfatAddFCBToTable(pVCB, FCB); 00394 00395 return(FCB); 00396 } 00397 00398 PVFATFCB 00399 vfatOpenRootFCB(PDEVICE_EXTENSION pVCB) 00400 { 00401 PVFATFCB FCB; 00402 UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\"); 00403 00404 FCB = vfatGrabFCBFromTable (pVCB, &NameU); 00405 if (FCB == NULL) 00406 { 00407 FCB = vfatMakeRootFCB (pVCB); 00408 } 00409 00410 return FCB; 00411 } 00412 00413 NTSTATUS 00414 vfatMakeFCBFromDirEntry( 00415 PVCB vcb, 00416 PVFATFCB directoryFCB, 00417 PVFAT_DIRENTRY_CONTEXT DirContext, 00418 PVFATFCB* fileFCB) 00419 { 00420 PVFATFCB rcFCB; 00421 PWCHAR PathNameBuffer; 00422 USHORT PathNameLength; 00423 ULONG Size; 00424 ULONG hash; 00425 00426 UNICODE_STRING NameU; 00427 00428 PathNameLength = directoryFCB->PathNameU.Length + max(DirContext->LongNameU.Length, DirContext->ShortNameU.Length); 00429 if (!vfatFCBIsRoot (directoryFCB)) 00430 { 00431 PathNameLength += sizeof(WCHAR); 00432 } 00433 00434 if (PathNameLength > LONGNAME_MAX_LENGTH * sizeof(WCHAR)) 00435 { 00436 return STATUS_OBJECT_NAME_INVALID; 00437 } 00438 PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameLength + sizeof(WCHAR), TAG_FCB); 00439 if (!PathNameBuffer) 00440 { 00441 return STATUS_INSUFFICIENT_RESOURCES; 00442 } 00443 NameU.Buffer = PathNameBuffer; 00444 NameU.Length = 0; 00445 NameU.MaximumLength = PathNameLength; 00446 00447 RtlCopyUnicodeString(&NameU, &directoryFCB->PathNameU); 00448 if (!vfatFCBIsRoot (directoryFCB)) 00449 { 00450 RtlAppendUnicodeToString(&NameU, L"\\"); 00451 } 00452 hash = vfatNameHash(0, &NameU); 00453 if (DirContext->LongNameU.Length > 0) 00454 { 00455 RtlAppendUnicodeStringToString(&NameU, &DirContext->LongNameU); 00456 } 00457 else 00458 { 00459 RtlAppendUnicodeStringToString(&NameU, &DirContext->ShortNameU); 00460 } 00461 NameU.Buffer[NameU.Length / sizeof(WCHAR)] = 0; 00462 00463 rcFCB = vfatNewFCB (vcb, &NameU); 00464 RtlCopyMemory (&rcFCB->entry, &DirContext->DirEntry, sizeof (DIR_ENTRY)); 00465 RtlCopyUnicodeString(&rcFCB->ShortNameU, &DirContext->ShortNameU); 00466 if (vcb->Flags & VCB_IS_FATX) 00467 { 00468 rcFCB->ShortHash.Hash = rcFCB->Hash.Hash; 00469 } 00470 else 00471 { 00472 rcFCB->ShortHash.Hash = vfatNameHash(hash, &rcFCB->ShortNameU); 00473 } 00474 00475 if (vfatFCBIsDirectory(rcFCB)) 00476 { 00477 ULONG FirstCluster, CurrentCluster; 00478 NTSTATUS Status = STATUS_SUCCESS; 00479 Size = 0; 00480 FirstCluster = vfatDirEntryGetFirstCluster (vcb, &rcFCB->entry); 00481 if (FirstCluster == 1) 00482 { 00483 Size = vcb->FatInfo.rootDirectorySectors * vcb->FatInfo.BytesPerSector; 00484 } 00485 else if (FirstCluster != 0) 00486 { 00487 CurrentCluster = FirstCluster; 00488 while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status)) 00489 { 00490 Size += vcb->FatInfo.BytesPerCluster; 00491 Status = NextCluster (vcb, FirstCluster, &CurrentCluster, FALSE); 00492 } 00493 } 00494 } 00495 else if (rcFCB->Flags & FCB_IS_FATX_ENTRY) 00496 { 00497 Size = rcFCB->entry.FatX.FileSize; 00498 } 00499 else 00500 { 00501 Size = rcFCB->entry.Fat.FileSize; 00502 } 00503 rcFCB->dirIndex = DirContext->DirIndex; 00504 rcFCB->startIndex = DirContext->StartIndex; 00505 if ((rcFCB->Flags & FCB_IS_FATX_ENTRY) && !vfatFCBIsRoot (directoryFCB)) 00506 { 00507 ASSERT(DirContext->DirIndex >= 2 && DirContext->StartIndex >= 2); 00508 rcFCB->dirIndex = DirContext->DirIndex-2; 00509 rcFCB->startIndex = DirContext->StartIndex-2; 00510 } 00511 rcFCB->RFCB.FileSize.QuadPart = Size; 00512 rcFCB->RFCB.ValidDataLength.QuadPart = Size; 00513 rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->FatInfo.BytesPerCluster); 00514 rcFCB->RefCount++; 00515 if (vfatFCBIsDirectory(rcFCB)) 00516 { 00517 vfatFCBInitializeCacheFromVolume(vcb, rcFCB); 00518 } 00519 rcFCB->parentFcb = directoryFCB; 00520 vfatAddFCBToTable (vcb, rcFCB); 00521 *fileFCB = rcFCB; 00522 00523 ExFreePool(PathNameBuffer); 00524 return STATUS_SUCCESS; 00525 } 00526 00527 NTSTATUS 00528 vfatAttachFCBToFileObject ( 00529 PDEVICE_EXTENSION vcb, 00530 PVFATFCB fcb, 00531 PFILE_OBJECT fileObject) 00532 { 00533 PVFATCCB newCCB; 00534 00535 newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList); 00536 if (newCCB == NULL) 00537 { 00538 return STATUS_INSUFFICIENT_RESOURCES; 00539 } 00540 RtlZeroMemory (newCCB, sizeof (VFATCCB)); 00541 00542 fileObject->SectionObjectPointer = &fcb->SectionObjectPointers; 00543 fileObject->FsContext = fcb; 00544 fileObject->FsContext2 = newCCB; 00545 DPRINT ("file open: fcb:%p PathName:%wZ\n", fcb, &fcb->PathNameU); 00546 00547 return STATUS_SUCCESS; 00548 } 00549 00550 NTSTATUS 00551 vfatDirFindFile ( 00552 PDEVICE_EXTENSION pDeviceExt, 00553 PVFATFCB pDirectoryFCB, 00554 PUNICODE_STRING FileToFindU, 00555 PVFATFCB * pFoundFCB) 00556 { 00557 NTSTATUS status; 00558 PVOID Context = NULL; 00559 PVOID Page = NULL; 00560 BOOLEAN First = TRUE; 00561 VFAT_DIRENTRY_CONTEXT DirContext; 00562 /* This buffer must have a size of 260 characters, because 00563 vfatMakeFCBFromDirEntry can copy 20 name entries with 13 characters. */ 00564 WCHAR LongNameBuffer[260]; 00565 WCHAR ShortNameBuffer[13]; 00566 BOOLEAN FoundLong = FALSE; 00567 BOOLEAN FoundShort = FALSE; 00568 00569 ASSERT(pDeviceExt); 00570 ASSERT(pDirectoryFCB); 00571 ASSERT(FileToFindU); 00572 00573 DPRINT ("vfatDirFindFile(VCB:%p, dirFCB:%p, File:%wZ)\n", 00574 pDeviceExt, 00575 pDirectoryFCB, 00576 FileToFindU); 00577 DPRINT ("Dir Path:%wZ\n", &pDirectoryFCB->PathNameU); 00578 00579 DirContext.DirIndex = 0; 00580 DirContext.LongNameU.Buffer = LongNameBuffer; 00581 DirContext.LongNameU.Length = 0; 00582 DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer); 00583 DirContext.ShortNameU.Buffer = ShortNameBuffer; 00584 DirContext.ShortNameU.Length = 0; 00585 DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer); 00586 00587 while (TRUE) 00588 { 00589 status = pDeviceExt->GetNextDirEntry(&Context, 00590 &Page, 00591 pDirectoryFCB, 00592 &DirContext, 00593 First); 00594 First = FALSE; 00595 if (status == STATUS_NO_MORE_ENTRIES) 00596 { 00597 return STATUS_OBJECT_NAME_NOT_FOUND; 00598 } 00599 if (!NT_SUCCESS(status)) 00600 { 00601 return status; 00602 } 00603 00604 DPRINT (" Index:%d longName:%wZ\n", 00605 DirContext.DirIndex, 00606 &DirContext.LongNameU); 00607 00608 if (!ENTRY_VOLUME(pDeviceExt, &DirContext.DirEntry)) 00609 { 00610 FoundLong = RtlEqualUnicodeString(FileToFindU, &DirContext.LongNameU, TRUE); 00611 if (FoundLong == FALSE) 00612 { 00613 FoundShort = RtlEqualUnicodeString(FileToFindU, &DirContext.ShortNameU, TRUE); 00614 } 00615 if (FoundLong || FoundShort) 00616 { 00617 status = vfatMakeFCBFromDirEntry (pDeviceExt, 00618 pDirectoryFCB, 00619 &DirContext, 00620 pFoundFCB); 00621 CcUnpinData(Context); 00622 return status; 00623 } 00624 } 00625 DirContext.DirIndex++; 00626 } 00627 00628 return STATUS_OBJECT_NAME_NOT_FOUND; 00629 } 00630 00631 NTSTATUS 00632 vfatGetFCBForFile ( 00633 PDEVICE_EXTENSION pVCB, 00634 PVFATFCB *pParentFCB, 00635 PVFATFCB *pFCB, 00636 PUNICODE_STRING pFileNameU) 00637 { 00638 NTSTATUS status; 00639 PVFATFCB FCB = NULL; 00640 PVFATFCB parentFCB; 00641 UNICODE_STRING NameU; 00642 UNICODE_STRING RootNameU = RTL_CONSTANT_STRING(L"\\"); 00643 UNICODE_STRING FileNameU; 00644 WCHAR NameBuffer[260]; 00645 PWCHAR curr, prev, last; 00646 ULONG Length; 00647 00648 DPRINT ("vfatGetFCBForFile (%p,%p,%p,%wZ)\n", 00649 pVCB, 00650 pParentFCB, 00651 pFCB, 00652 pFileNameU); 00653 00654 FileNameU.Buffer = NameBuffer; 00655 FileNameU.MaximumLength = sizeof(NameBuffer); 00656 RtlCopyUnicodeString(&FileNameU, pFileNameU); 00657 00658 parentFCB = *pParentFCB; 00659 00660 if (parentFCB == NULL) 00661 { 00662 // Trivial case, open of the root directory on volume 00663 if (RtlEqualUnicodeString(&FileNameU, &RootNameU, FALSE)) 00664 { 00665 DPRINT ("returning root FCB\n"); 00666 00667 FCB = vfatOpenRootFCB (pVCB); 00668 *pFCB = FCB; 00669 *pParentFCB = NULL; 00670 00671 return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND; 00672 } 00673 00674 /* Check for an existing FCB */ 00675 FCB = vfatGrabFCBFromTable (pVCB, &FileNameU); 00676 if (FCB) 00677 { 00678 *pFCB = FCB; 00679 *pParentFCB = FCB->parentFcb; 00680 (*pParentFCB)->RefCount++; 00681 return STATUS_SUCCESS; 00682 } 00683 00684 last = curr = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1; 00685 while (*curr != L'\\' && curr > FileNameU.Buffer) 00686 { 00687 curr--; 00688 } 00689 00690 if (curr > FileNameU.Buffer) 00691 { 00692 NameU.Buffer = FileNameU.Buffer; 00693 NameU.MaximumLength = NameU.Length = (curr - FileNameU.Buffer) * sizeof(WCHAR); 00694 FCB = vfatGrabFCBFromTable(pVCB, &NameU); 00695 if (FCB) 00696 { 00697 Length = (curr - FileNameU.Buffer) * sizeof(WCHAR); 00698 if (Length != FCB->PathNameU.Length) 00699 { 00700 if (FileNameU.Length + FCB->PathNameU.Length - Length > FileNameU.MaximumLength) 00701 { 00702 vfatReleaseFCB (pVCB, FCB); 00703 return STATUS_OBJECT_NAME_INVALID; 00704 } 00705 RtlMoveMemory(FileNameU.Buffer + FCB->PathNameU.Length / sizeof(WCHAR), 00706 curr, FileNameU.Length - Length); 00707 FileNameU.Length += (USHORT)(FCB->PathNameU.Length - Length); 00708 curr = FileNameU.Buffer + FCB->PathNameU.Length / sizeof(WCHAR); 00709 last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1; 00710 } 00711 RtlCopyMemory(FileNameU.Buffer, FCB->PathNameU.Buffer, FCB->PathNameU.Length); 00712 } 00713 } 00714 else 00715 { 00716 FCB = NULL; 00717 } 00718 00719 if (FCB == NULL) 00720 { 00721 FCB = vfatOpenRootFCB(pVCB); 00722 curr = FileNameU.Buffer; 00723 } 00724 00725 parentFCB = NULL; 00726 prev = curr; 00727 } 00728 else 00729 { 00730 FCB = parentFCB; 00731 parentFCB = NULL; 00732 prev = curr = FileNameU.Buffer - 1; 00733 last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1; 00734 } 00735 00736 while (curr <= last) 00737 { 00738 if (parentFCB) 00739 { 00740 vfatReleaseFCB (pVCB, parentFCB); 00741 parentFCB = 0; 00742 } 00743 // fail if element in FCB is not a directory 00744 if (!vfatFCBIsDirectory (FCB)) 00745 { 00746 DPRINT ("Element in requested path is not a directory\n"); 00747 00748 vfatReleaseFCB (pVCB, FCB); 00749 FCB = NULL; 00750 *pParentFCB = NULL; 00751 *pFCB = NULL; 00752 00753 return STATUS_OBJECT_PATH_NOT_FOUND; 00754 } 00755 parentFCB = FCB; 00756 if (prev < curr) 00757 { 00758 Length = (curr - prev) * sizeof(WCHAR); 00759 if (Length != parentFCB->LongNameU.Length) 00760 { 00761 if (FileNameU.Length + parentFCB->LongNameU.Length - Length > FileNameU.MaximumLength) 00762 { 00763 vfatReleaseFCB (pVCB, parentFCB); 00764 return STATUS_OBJECT_NAME_INVALID; 00765 } 00766 RtlMoveMemory(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr, 00767 FileNameU.Length - (curr - FileNameU.Buffer) * sizeof(WCHAR)); 00768 FileNameU.Length += (USHORT)(parentFCB->LongNameU.Length - Length); 00769 curr = prev + parentFCB->LongNameU.Length / sizeof(WCHAR); 00770 last = FileNameU.Buffer + FileNameU.Length / sizeof(WCHAR) - 1; 00771 } 00772 RtlCopyMemory(prev, parentFCB->LongNameU.Buffer, parentFCB->LongNameU.Length); 00773 } 00774 curr++; 00775 prev = curr; 00776 while (*curr != L'\\' && curr <= last) 00777 { 00778 curr++; 00779 } 00780 NameU.Buffer = FileNameU.Buffer; 00781 NameU.Length = (curr - NameU.Buffer) * sizeof(WCHAR); 00782 NameU.MaximumLength = FileNameU.MaximumLength; 00783 DPRINT("%wZ\n", &NameU); 00784 FCB = vfatGrabFCBFromTable(pVCB, &NameU); 00785 if (FCB == NULL) 00786 { 00787 NameU.Buffer = prev; 00788 NameU.MaximumLength = NameU.Length = (curr - prev) * sizeof(WCHAR); 00789 status = vfatDirFindFile(pVCB, parentFCB, &NameU, &FCB); 00790 if (status == STATUS_OBJECT_NAME_NOT_FOUND) 00791 { 00792 *pFCB = NULL; 00793 if (curr > last) 00794 { 00795 *pParentFCB = parentFCB; 00796 return STATUS_OBJECT_NAME_NOT_FOUND; 00797 } 00798 else 00799 { 00800 vfatReleaseFCB (pVCB, parentFCB); 00801 *pParentFCB = NULL; 00802 return STATUS_OBJECT_PATH_NOT_FOUND; 00803 } 00804 } 00805 else if (!NT_SUCCESS (status)) 00806 { 00807 vfatReleaseFCB (pVCB, parentFCB); 00808 *pParentFCB = NULL; 00809 *pFCB = NULL; 00810 00811 return status; 00812 } 00813 } 00814 } 00815 00816 *pParentFCB = parentFCB; 00817 *pFCB = FCB; 00818 00819 return STATUS_SUCCESS; 00820 } 00821 Generated on Sat May 26 2012 04:26:05 for ReactOS by
1.7.6.1
|