[FASTFAT] Only initialize directory cache on use.
[reactos.git] / drivers / filesystems / fastfat / direntry.c
index 336f014..aa1e12f 100644 (file)
@@ -27,7 +27,7 @@ vfatDirEntryGetFirstCluster(
         cluster = pFatDirEntry->Fat.FirstCluster |
                  (pFatDirEntry->Fat.FirstClusterHigh << 16);
     }
-    else if (pDeviceExt->Flags & VCB_IS_FATX)
+    else if (vfatVolumeIsFatX(pDeviceExt))
     {
         cluster = pFatDirEntry->FatX.FirstCluster;
     }
@@ -39,15 +39,16 @@ vfatDirEntryGetFirstCluster(
     return  cluster;
 }
 
-static
 BOOLEAN
 FATIsDirectoryEmpty(
+    PDEVICE_EXTENSION DeviceExt,
     PVFATFCB Fcb)
 {
     LARGE_INTEGER FileOffset;
     PVOID Context = NULL;
     PFAT_DIR_ENTRY FatDirEntry;
     ULONG Index, MaxIndex;
+    NTSTATUS Status;
 
     if (vfatFCBIsRoot(Fcb))
     {
@@ -61,6 +62,12 @@ FATIsDirectoryEmpty(
     FileOffset.QuadPart = 0;
     MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FAT_DIR_ENTRY);
 
+    Status = vfatFCBInitializeCacheFromVolume(DeviceExt, Fcb);
+    if (!NT_SUCCESS(Status))
+    {
+        return FALSE;
+    }
+
     while (Index < MaxIndex)
     {
         if (Context == NULL || (Index % FAT_ENTRIES_PER_PAGE) == 0)
@@ -70,10 +77,15 @@ FATIsDirectoryEmpty(
                 CcUnpinData(Context);
             }
 
-            if (!CcMapData(Fcb->FileObject, &FileOffset, sizeof(FAT_DIR_ENTRY), TRUE, &Context, (PVOID*)&FatDirEntry))
+            _SEH2_TRY
+            {
+                CcMapData(Fcb->FileObject, &FileOffset, sizeof(FAT_DIR_ENTRY), MAP_WAIT, &Context, (PVOID*)&FatDirEntry);
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
-                return TRUE;
+                _SEH2_YIELD(return TRUE);
             }
+            _SEH2_END;
 
             FatDirEntry += Index % FAT_ENTRIES_PER_PAGE;
             FileOffset.QuadPart += PAGE_SIZE;
@@ -103,19 +115,26 @@ FATIsDirectoryEmpty(
     return TRUE;
 }
 
-static
 BOOLEAN
 FATXIsDirectoryEmpty(
+    PDEVICE_EXTENSION DeviceExt,
     PVFATFCB Fcb)
 {
     LARGE_INTEGER FileOffset;
     PVOID Context = NULL;
     PFATX_DIR_ENTRY FatXDirEntry;
     ULONG Index = 0, MaxIndex;
+    NTSTATUS Status;
 
     FileOffset.QuadPart = 0;
     MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FATX_DIR_ENTRY);
 
+    Status = vfatFCBInitializeCacheFromVolume(DeviceExt, Fcb);
+    if (!NT_SUCCESS(Status))
+    {
+        return FALSE;
+    }
+
     while (Index < MaxIndex)
     {
         if (Context == NULL || (Index % FATX_ENTRIES_PER_PAGE) == 0)
@@ -125,10 +144,15 @@ FATXIsDirectoryEmpty(
                 CcUnpinData(Context);
             }
 
-            if (!CcMapData(Fcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY), TRUE, &Context, (PVOID*)&FatXDirEntry))
+            _SEH2_TRY
             {
-                return TRUE;
+                CcMapData(Fcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY), MAP_WAIT, &Context, (PVOID*)&FatXDirEntry);
             }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                _SEH2_YIELD(return TRUE);
+            }
+            _SEH2_END;
 
             FatXDirEntry += Index % FATX_ENTRIES_PER_PAGE;
             FileOffset.QuadPart += PAGE_SIZE;
@@ -158,16 +182,6 @@ FATXIsDirectoryEmpty(
     return TRUE;
 }
 
-BOOLEAN
-VfatIsDirectoryEmpty(
-    PVFATFCB Fcb)
-{
-    if (Fcb->Flags & FCB_IS_FATX_ENTRY)
-        return FATXIsDirectoryEmpty(Fcb);
-    else
-        return FATIsDirectoryEmpty(Fcb);
-}
-
 NTSTATUS
 FATGetNextDirEntry(
     PVOID *pContext,
@@ -188,12 +202,20 @@ FATGetNextDirEntry(
     BOOLEAN Valid = TRUE;
     BOOLEAN Back = FALSE;
 
+    NTSTATUS Status;
+
     DirContext->LongNameU.Length = 0;
     DirContext->LongNameU.Buffer[0] = UNICODE_NULL;
 
     FileOffset.u.HighPart = 0;
     FileOffset.u.LowPart = ROUND_DOWN(DirContext->DirIndex * sizeof(FAT_DIR_ENTRY), PAGE_SIZE);
 
+    Status = vfatFCBInitializeCacheFromVolume(DirContext->DeviceExt, pDirFcb);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
     if (*pContext == NULL || (DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == 0)
     {
         if (*pContext != NULL)
@@ -201,12 +223,22 @@ FATGetNextDirEntry(
             CcUnpinData(*pContext);
         }
 
-        if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
-            !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
+        if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart)
         {
             *pContext = NULL;
             return STATUS_NO_MORE_ENTRIES;
         }
+
+        _SEH2_TRY
+        {
+            CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, MAP_WAIT, pContext, pPage);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            *pContext = NULL;
+            _SEH2_YIELD(return STATUS_NO_MORE_ENTRIES);
+        }
+        _SEH2_END;
     }
 
     fatDirEntry = (PFAT_DIR_ENTRY)(*pPage) + DirContext->DirIndex % FAT_ENTRIES_PER_PAGE;
@@ -232,13 +264,23 @@ FATGetNextDirEntry(
                 CcUnpinData(*pContext);
                 FileOffset.u.LowPart -= PAGE_SIZE;
 
-                if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
-                    !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
+                if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart)
                 {
                     *pContext = NULL;
                     return STATUS_NO_MORE_ENTRIES;
                 }
 
+                _SEH2_TRY
+                {
+                    CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, MAP_WAIT, pContext, pPage);
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    *pContext = NULL;
+                    _SEH2_YIELD(return STATUS_NO_MORE_ENTRIES);
+                }
+                _SEH2_END;
+
                 fatDirEntry = (PFAT_DIR_ENTRY)(*pPage) + DirContext->DirIndex % FAT_ENTRIES_PER_PAGE;
                 longNameEntry = (slot*) fatDirEntry;
             }
@@ -259,13 +301,23 @@ FATGetNextDirEntry(
                 CcUnpinData(*pContext);
                 FileOffset.u.LowPart += PAGE_SIZE;
 
-                if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
-                   !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
+                if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart)
                 {
                     *pContext = NULL;
                     return STATUS_NO_MORE_ENTRIES;
                 }
 
+                _SEH2_TRY
+                {
+                    CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, MAP_WAIT, pContext, pPage);
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    *pContext = NULL;
+                    _SEH2_YIELD(return STATUS_NO_MORE_ENTRIES);
+                }
+                _SEH2_END;
+
                 fatDirEntry = (PFAT_DIR_ENTRY)*pPage;
                 longNameEntry = (slot*) *pPage;
             }
@@ -314,7 +366,7 @@ FATGetNextDirEntry(
 
                 index = longNameEntry->id & 0x3f; // Note: it can be 0 for corrupted FS
                 
-                /* Make sure index is valid and we have enaugh space in buffer
+                /* Make sure index is valid and we have enough space in buffer
                   (we count one char for \0) */
                 if (index > 0 &&
                     index * 13 < DirContext->LongNameU.MaximumLength / sizeof(WCHAR))
@@ -379,13 +431,23 @@ FATGetNextDirEntry(
             CcUnpinData(*pContext);
             FileOffset.u.LowPart += PAGE_SIZE;
 
-            if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
-                !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
+            if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart)
             {
                 *pContext = NULL;
                 return STATUS_NO_MORE_ENTRIES;
             }
 
+            _SEH2_TRY
+            {
+                CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, MAP_WAIT, pContext, pPage);
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                *pContext = NULL;
+                _SEH2_YIELD(return STATUS_NO_MORE_ENTRIES);
+            }
+            _SEH2_END;
+
             fatDirEntry = (PFAT_DIR_ENTRY)*pPage;
             longNameEntry = (slot*) *pPage;
         }
@@ -423,6 +485,7 @@ FATXGetNextDirEntry(
     PFATX_DIR_ENTRY fatxDirEntry;
     OEM_STRING StringO;
     ULONG DirIndex = DirContext->DirIndex;
+    NTSTATUS Status;
 
     FileOffset.u.HighPart = 0;
 
@@ -460,6 +523,12 @@ FATXGetNextDirEntry(
         }
     }
 
+    Status = vfatFCBInitializeCacheFromVolume(DirContext->DeviceExt, pDirFcb);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
     if (*pContext == NULL || (DirIndex % FATX_ENTRIES_PER_PAGE) == 0)
     {
         if (*pContext != NULL)
@@ -467,12 +536,22 @@ FATXGetNextDirEntry(
             CcUnpinData(*pContext);
         }
         FileOffset.u.LowPart = ROUND_DOWN(DirIndex * sizeof(FATX_DIR_ENTRY), PAGE_SIZE);
-        if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
-            !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
+        if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart)
         {
             *pContext = NULL;
             return STATUS_NO_MORE_ENTRIES;
         }
+
+        _SEH2_TRY
+        {
+            CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, MAP_WAIT, pContext, pPage);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            *pContext = NULL;
+            _SEH2_YIELD(return STATUS_NO_MORE_ENTRIES);
+        }
+        _SEH2_END;
     }
 
     fatxDirEntry = (PFATX_DIR_ENTRY)(*pPage) + DirIndex % FATX_ENTRIES_PER_PAGE;
@@ -500,12 +579,23 @@ FATXGetNextDirEntry(
         {
             CcUnpinData(*pContext);
             FileOffset.u.LowPart += PAGE_SIZE;
-            if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
-                !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
+            if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart)
             {
                 *pContext = NULL;
                 return STATUS_NO_MORE_ENTRIES;
             }
+
+            _SEH2_TRY
+            {
+                CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, MAP_WAIT, pContext, pPage);
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                *pContext = NULL;
+                _SEH2_YIELD(return STATUS_NO_MORE_ENTRIES);
+            }
+            _SEH2_END;
+
             fatxDirEntry = (PFATX_DIR_ENTRY)*pPage;
         }
         else