Commit 11d66a87 authored by Alexandre Julliard's avatar Alexandre Julliard

setupapi: Use a global buffer to read fake dll files and free it only once we…

setupapi: Use a global buffer to read fake dll files and free it only once we are done with all the fake dlls.
parent f1dc1d35
......@@ -50,6 +50,9 @@ static const char fakedll_signature[] = "Wine placeholder DLL";
static const unsigned int file_alignment = 512;
static const unsigned int section_alignment = 4096;
static void *file_buffer;
static size_t file_buffer_size;
struct dll_info
{
HANDLE handle;
......@@ -105,6 +108,39 @@ static inline void add_directory( struct dll_info *info, unsigned int idx, DWORD
info->nt->OptionalHeader.DataDirectory[idx].Size = size;
}
/* read in the contents of a file into the global file buffer */
/* return 1 on success, 0 on nonexistent file, -1 on other error */
static int read_file( const char *name, void **data, size_t *size )
{
static char static_file_buffer[4096];
struct stat st;
void *buffer = static_file_buffer;
int fd, ret = -1;
if ((fd = open( name, O_RDONLY | O_BINARY )) == -1) return 0;
if (fstat( fd, &st ) == -1) goto done;
*size = st.st_size;
if (st.st_size > sizeof(static_file_buffer))
{
if (!file_buffer || st.st_size > file_buffer_size)
{
HeapFree( GetProcessHeap(), 0, file_buffer );
if (!(file_buffer = HeapAlloc( GetProcessHeap(), 0, st.st_size ))) goto done;
file_buffer_size = st.st_size;
}
buffer = file_buffer;
}
if (pread( fd, buffer, st.st_size, 0 ) == st.st_size)
{
*data = buffer;
ret = 1;
}
done:
close( fd );
return ret;
}
/* build a complete fake dll from scratch */
static BOOL build_fake_dll( HANDLE file )
{
......@@ -238,15 +274,15 @@ static inline char *prepend( char *buffer, const char *str, size_t len )
}
/* try to load a pre-compiled fake dll */
static void *load_fake_dll( const WCHAR *name, unsigned int *size, void *buf, unsigned int buf_size )
static void *load_fake_dll( const WCHAR *name, size_t *size )
{
const char *build_dir = wine_get_build_dir();
const char *path;
struct stat st;
char *file, *ptr, *buffer = NULL;
char *file, *ptr;
void *data = NULL;
unsigned int i, pos, len, namelen, maxlen = 0;
WCHAR *p;
int fd;
int res = 0;
if ((p = strrchrW( name, '\\' ))) name = p + 1;
......@@ -280,7 +316,7 @@ static void *load_fake_dll( const WCHAR *name, unsigned int *size, void *buf, un
ptr = prepend( ptr, ptr, namelen );
ptr = prepend( ptr, "/dlls", sizeof("/dlls") - 1 );
ptr = prepend( ptr, build_dir, strlen(build_dir) );
if ((fd = open( ptr, O_RDONLY | O_BINARY )) != -1) goto found;
if ((res = read_file( ptr, &data, size ))) goto done;
/* now as a program */
ptr = file + pos;
......@@ -289,7 +325,7 @@ static void *load_fake_dll( const WCHAR *name, unsigned int *size, void *buf, un
ptr = prepend( ptr, ptr, namelen );
ptr = prepend( ptr, "/programs", sizeof("/programs") - 1 );
ptr = prepend( ptr, build_dir, strlen(build_dir) );
if ((fd = open( ptr, O_RDONLY | O_BINARY )) != -1) goto found;
if ((res = read_file( ptr, &data, size ))) goto done;
}
file[pos + len + 1] = 0;
......@@ -297,31 +333,13 @@ static void *load_fake_dll( const WCHAR *name, unsigned int *size, void *buf, un
{
ptr = prepend( file + pos, "/fakedlls", sizeof("/fakedlls") - 1 );
ptr = prepend( ptr, path, strlen(path) );
if ((fd = open( ptr, O_RDONLY | O_BINARY )) != -1) goto found;
}
goto done;
found:
if (!fstat( fd, &st ))
{
*size = st.st_size;
if (st.st_size <= buf_size) buffer = buf;
else buffer = HeapAlloc( GetProcessHeap(), 0, st.st_size );
if (buffer)
{
if (read( fd, buffer, st.st_size ) != st.st_size)
{
if (buffer != buf) HeapFree( GetProcessHeap(), 0, buffer );
buffer = NULL;
}
else TRACE( "found %s %u bytes\n", ptr, *size);
}
if ((res = read_file( ptr, &data, size ))) break;
}
close( fd );
done:
HeapFree( GetProcessHeap(), 0, file );
return buffer;
if (res == 1) return data;
return NULL;
}
/***********************************************************************
......@@ -332,7 +350,6 @@ BOOL create_fake_dll( const WCHAR *name, const WCHAR *source )
HANDLE h;
BOOL ret;
unsigned int size = 0;
char *temp_buffer[4096];
void *buffer;
/* check for empty name which means to only create the directory */
......@@ -368,13 +385,12 @@ BOOL create_fake_dll( const WCHAR *name, const WCHAR *source )
}
}
if ((buffer = load_fake_dll( source, &size, temp_buffer, sizeof(temp_buffer) )))
if ((buffer = load_fake_dll( source, &size )))
{
DWORD written;
ret = (WriteFile( h, buffer, size, &written, NULL ) && written == size);
if (!ret) ERR( "failed to write to %s (error=%u)\n", debugstr_w(name), GetLastError() );
if (buffer != temp_buffer) HeapFree( GetProcessHeap(), 0, buffer );
}
else
{
......@@ -386,3 +402,13 @@ BOOL create_fake_dll( const WCHAR *name, const WCHAR *source )
if (!ret) DeleteFileW( name );
return ret;
}
/***********************************************************************
* cleanup_fake_dlls
*/
void cleanup_fake_dlls(void)
{
HeapFree( GetProcessHeap(), 0, file_buffer );
file_buffer = NULL;
}
......@@ -700,6 +700,7 @@ static BOOL fake_dlls_callback( HINF hinf, PCWSTR field, void *arg )
HeapFree( GetProcessHeap(), 0, path );
if (!ret) break;
}
cleanup_fake_dlls();
return ret;
}
......
......@@ -105,5 +105,6 @@ UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, UINT_PTR, U
extern OSVERSIONINFOW OsVersionInfo;
extern BOOL create_fake_dll( const WCHAR *name, const WCHAR *source );
extern void cleanup_fake_dlls(void);
#endif /* __SETUPAPI_PRIVATE_H */
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