Alexandre Julliard : setupapi: Use a global buffer to read fake dll files and free it only once we are done with all the fake dlls .

Alexandre Julliard julliard at winehq.org
Thu Oct 15 08:54:39 CDT 2009


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Oct 15 12:20:14 2009 +0200

setupapi: Use a global buffer to read fake dll files and free it only once we are done with all the fake dlls.

---

 dlls/setupapi/fakedll.c          |   86 ++++++++++++++++++++++++-------------
 dlls/setupapi/install.c          |    1 +
 dlls/setupapi/setupapi_private.h |    1 +
 3 files changed, 58 insertions(+), 30 deletions(-)

diff --git a/dlls/setupapi/fakedll.c b/dlls/setupapi/fakedll.c
index 8613ca3..903fd23 100644
--- a/dlls/setupapi/fakedll.c
+++ b/dlls/setupapi/fakedll.c
@@ -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;
+}
diff --git a/dlls/setupapi/install.c b/dlls/setupapi/install.c
index f90c2d8..293f977 100644
--- a/dlls/setupapi/install.c
+++ b/dlls/setupapi/install.c
@@ -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;
 }
 
diff --git a/dlls/setupapi/setupapi_private.h b/dlls/setupapi/setupapi_private.h
index e505503..70394e2 100644
--- a/dlls/setupapi/setupapi_private.h
+++ b/dlls/setupapi/setupapi_private.h
@@ -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 */




More information about the wine-cvs mailing list