Commit 0a8ce1d0 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent 0049ca10
...@@ -64,7 +64,7 @@ typedef struct ...@@ -64,7 +64,7 @@ typedef struct
UINT data_pos; /* current position in dir data */ UINT data_pos; /* current position in dir data */
UINT data_len; /* length of dir data */ UINT data_len; /* length of dir data */
UINT data_size; /* size of data buffer, or 0 when everything has been read */ 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; } FIND_FIRST_INFO;
#define FIND_FIRST_MAGIC 0xc0ffee11 #define FIND_FIRST_MAGIC 0xc0ffee11
...@@ -1946,7 +1946,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level, ...@@ -1946,7 +1946,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io; IO_STATUS_BLOCK io;
NTSTATUS status; 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); 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, ...@@ -1973,12 +1973,6 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info))))
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
goto error;
}
if (!mask && (device = RtlIsDosDeviceName_U( filename ))) if (!mask && (device = RtlIsDosDeviceName_U( filename )))
{ {
static const WCHAR dotW[] = {'.',0}; static const WCHAR dotW[] = {'.',0};
...@@ -2004,6 +1998,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level, ...@@ -2004,6 +1998,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
goto error; goto error;
} }
HeapFree( GetProcessHeap(), 0, dir ); HeapFree( GetProcessHeap(), 0, dir );
size = 0;
} }
else if (!mask || !*mask) else if (!mask || !*mask)
{ {
...@@ -2014,6 +2009,13 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level, ...@@ -2014,6 +2009,13 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
{ {
nt_name.Length = (mask - nt_name.Buffer) * sizeof(WCHAR); nt_name.Length = (mask - nt_name.Buffer) * sizeof(WCHAR);
has_wildcard = strpbrkW( mask, wildcardsW ) != NULL; 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 */ /* 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, ...@@ -2052,8 +2054,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
info->wildcard = has_wildcard; info->wildcard = has_wildcard;
info->data_pos = 0; info->data_pos = 0;
info->data_len = 0; info->data_len = 0;
info->data_size = 0; info->data_size = size;
info->data = NULL;
info->search_op = search_op; info->search_op = search_op;
info->level = level; info->level = level;
...@@ -2072,41 +2073,23 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level, ...@@ -2072,41 +2073,23 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
UNICODE_STRING mask_str; UNICODE_STRING mask_str;
RtlInitUnicodeString( &mask_str, mask ); RtlInitUnicodeString( &mask_str, mask );
info->data_size = has_wildcard ? 8192 : max_entry_size * 2; status = NtQueryDirectoryFile( info->handle, 0, NULL, NULL, &io, info->data, info->data_size,
FileBothDirectoryInformation, FALSE, &mask_str, TRUE );
while (info->data_size) if (status)
{ {
if (!(info->data = HeapAlloc( GetProcessHeap(), 0, info->data_size ))) FindClose( info );
{ SetLastError( RtlNtStatusToDosError( status ) );
FindClose( info ); return INVALID_HANDLE_VALUE;
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;
} }
info->data_len = io.Information; info->data_len = io.Information;
if (!info->data_size && has_wildcard) /* release unused buffer space */ if (!has_wildcard || info->data_len < info->data_size - max_entry_size)
HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, info->data, info->data_len ); {
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 )) if (!FindNextFileW( info, data ))
{ {
...@@ -2118,9 +2101,7 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level, ...@@ -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 */ if (!has_wildcard) /* we can't find two files with the same name */
{ {
CloseHandle( info->handle ); CloseHandle( info->handle );
HeapFree( GetProcessHeap(), 0, info->data );
info->handle = 0; info->handle = 0;
info->data = NULL;
} }
} }
return info; return info;
...@@ -2177,9 +2158,7 @@ BOOL WINAPI FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *data ) ...@@ -2177,9 +2158,7 @@ BOOL WINAPI FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *data )
if (status == STATUS_NO_MORE_FILES) if (status == STATUS_NO_MORE_FILES)
{ {
CloseHandle( info->handle ); CloseHandle( info->handle );
HeapFree( GetProcessHeap(), 0, info->data );
info->handle = 0; info->handle = 0;
info->data = NULL;
} }
break; break;
} }
...@@ -2266,7 +2245,6 @@ BOOL WINAPI FindClose( HANDLE handle ) ...@@ -2266,7 +2245,6 @@ BOOL WINAPI FindClose( HANDLE handle )
RtlFreeUnicodeString( &info->path ); RtlFreeUnicodeString( &info->path );
info->data_pos = 0; info->data_pos = 0;
info->data_len = 0; info->data_len = 0;
HeapFree( GetProcessHeap(), 0, info->data );
RtlLeaveCriticalSection( &info->cs ); RtlLeaveCriticalSection( &info->cs );
info->cs.DebugInfo->Spare[0] = 0; info->cs.DebugInfo->Spare[0] = 0;
RtlDeleteCriticalSection( &info->cs ); RtlDeleteCriticalSection( &info->cs );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment