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 * 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 doxygen 1.7.6.1

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