Alexandre Julliard : kernel32: Don' t cache the full directory in FindFirstFileEx.

Alexandre Julliard julliard at wine.codeweavers.com
Wed May 4 11:38:20 CDT 2016


Module: wine
Branch: master
Commit: 0a8ce1d0bd1a4fb49aaec71874be14a1ae955915
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=0a8ce1d0bd1a4fb49aaec71874be14a1ae955915

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu May  5 01:27:44 2016 +0900

kernel32: Don't cache the full directory in FindFirstFileEx.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/file.c | 70 ++++++++++++++++++----------------------------------
 1 file changed, 24 insertions(+), 46 deletions(-)

diff --git a/dlls/kernel32/file.c b/dlls/kernel32/file.c
index 2111489..cc7ead1 100644
--- a/dlls/kernel32/file.c
+++ b/dlls/kernel32/file.c
@@ -64,7 +64,7 @@ typedef struct
     UINT              data_pos;    /* current position in dir data */
     UINT              data_len;    /* length of dir data */
     UINT              data_size;   /* size of data buffer, or 0 when everything has been read */
-    BYTE             *data;        /* directory data */
+    BYTE              data[1];     /* directory data */
 } FIND_FIRST_INFO;
 
 #define FIND_FIRST_MAGIC  0xc0ffee11
@@ -1946,7 +1946,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
     OBJECT_ATTRIBUTES attr;
     IO_STATUS_BLOCK io;
     NTSTATUS status;
-    DWORD device = 0;
+    DWORD size, device = 0;
 
     TRACE("%s %d %p %d %p %x\n", debugstr_w(filename), level, data, search_op, filter, flags);
 
@@ -1973,12 +1973,6 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
         return INVALID_HANDLE_VALUE;
     }
 
-    if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info))))
-    {
-        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
-        goto error;
-    }
-
     if (!mask && (device = RtlIsDosDeviceName_U( filename )))
     {
         static const WCHAR dotW[] = {'.',0};
@@ -2004,6 +1998,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
             goto error;
         }
         HeapFree( GetProcessHeap(), 0, dir );
+        size = 0;
     }
     else if (!mask || !*mask)
     {
@@ -2014,6 +2009,13 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
     {
         nt_name.Length = (mask - nt_name.Buffer) * sizeof(WCHAR);
         has_wildcard = strpbrkW( mask, wildcardsW ) != NULL;
+        size = has_wildcard ? 8192 : max_entry_size;
+    }
+
+    if (!(info = HeapAlloc( GetProcessHeap(), 0, offsetof( FIND_FIRST_INFO, data[size] ))))
+    {
+        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+        goto error;
     }
 
     /* check if path is the root of the drive, skipping the \??\ prefix */
@@ -2052,8 +2054,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
     info->wildcard = has_wildcard;
     info->data_pos = 0;
     info->data_len = 0;
-    info->data_size = 0;
-    info->data      = NULL;
+    info->data_size = size;
     info->search_op = search_op;
     info->level     = level;
 
@@ -2072,41 +2073,23 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
         UNICODE_STRING mask_str;
 
         RtlInitUnicodeString( &mask_str, mask );
-        info->data_size = has_wildcard ? 8192 : max_entry_size * 2;
-
-        while (info->data_size)
+        status = NtQueryDirectoryFile( info->handle, 0, NULL, NULL, &io, info->data, info->data_size,
+                                       FileBothDirectoryInformation, FALSE, &mask_str, TRUE );
+        if (status)
         {
-            if (!(info->data = HeapAlloc( GetProcessHeap(), 0, info->data_size )))
-            {
-                FindClose( info );
-                SetLastError( ERROR_NOT_ENOUGH_MEMORY );
-                return INVALID_HANDLE_VALUE;
-            }
-
-            status = NtQueryDirectoryFile( info->handle, 0, NULL, NULL, &io, info->data, info->data_size,
-                                           FileBothDirectoryInformation, FALSE, &mask_str, TRUE );
-            if (status)
-            {
-                FindClose( info );
-                SetLastError( RtlNtStatusToDosError( status ) );
-                return INVALID_HANDLE_VALUE;
-            }
-
-            if (io.Information < info->data_size - max_entry_size)
-            {
-                info->data_size = 0;  /* we read everything */
-            }
-            else if (info->data_size < 1024 * 1024)
-            {
-                HeapFree( GetProcessHeap(), 0, info->data );
-                info->data_size *= 2;
-            }
-            else break;
+            FindClose( info );
+            SetLastError( RtlNtStatusToDosError( status ) );
+            return INVALID_HANDLE_VALUE;
         }
 
         info->data_len = io.Information;
-        if (!info->data_size && has_wildcard)  /* release unused buffer space */
-            HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, info->data, info->data_len );
+        if (!has_wildcard || info->data_len < info->data_size - max_entry_size)
+        {
+            if (has_wildcard)  /* release unused buffer space */
+                HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY,
+                             info, offsetof( FIND_FIRST_INFO, data[info->data_len] ));
+            info->data_size = 0;  /* we read everything */
+        }
 
         if (!FindNextFileW( info, data ))
         {
@@ -2118,9 +2101,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
         if (!has_wildcard)  /* we can't find two files with the same name */
         {
             CloseHandle( info->handle );
-            HeapFree( GetProcessHeap(), 0, info->data );
             info->handle = 0;
-            info->data = NULL;
         }
     }
     return info;
@@ -2177,9 +2158,7 @@ BOOL WINAPI FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *data )
                 if (status == STATUS_NO_MORE_FILES)
                 {
                     CloseHandle( info->handle );
-                    HeapFree( GetProcessHeap(), 0, info->data );
                     info->handle = 0;
-                    info->data = NULL;
                 }
                 break;
             }
@@ -2266,7 +2245,6 @@ BOOL WINAPI FindClose( HANDLE handle )
                 RtlFreeUnicodeString( &info->path );
                 info->data_pos = 0;
                 info->data_len = 0;
-                HeapFree( GetProcessHeap(), 0, info->data );
                 RtlLeaveCriticalSection( &info->cs );
                 info->cs.DebugInfo->Spare[0] = 0;
                 RtlDeleteCriticalSection( &info->cs );




More information about the wine-cvs mailing list