Alexandre Julliard : setupapi: Copy the pre-compiled fake dll files instead of generating them if possible .

Alexandre Julliard julliard at winehq.org
Tue Aug 18 10:00:15 CDT 2009


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Aug 18 11:38:22 2009 +0200

setupapi: Copy the pre-compiled fake dll files instead of generating them if possible.

---

 dlls/setupapi/fakedll.c |  123 +++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 119 insertions(+), 4 deletions(-)

diff --git a/dlls/setupapi/fakedll.c b/dlls/setupapi/fakedll.c
index e6eddf1..51d7790 100644
--- a/dlls/setupapi/fakedll.c
+++ b/dlls/setupapi/fakedll.c
@@ -18,7 +18,17 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+#include "wine/port.h"
+
 #include <stdarg.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
 
 #define NONAMELESSSTRUCT
 #define NONAMELESSUNION
@@ -30,6 +40,7 @@
 #include "winnt.h"
 #include "winternl.h"
 #include "wine/unicode.h"
+#include "wine/library.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
@@ -297,14 +308,107 @@ static void create_directories( const WCHAR *name )
     HeapFree(GetProcessHeap(), 0, path);
 }
 
+static inline char *prepend( char *buffer, const char *str, size_t len )
+{
+    return memcpy( buffer - len, str, 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 )
+{
+    const char *build_dir = wine_get_build_dir();
+    const char *path;
+    struct stat st;
+    char *file, *ptr, *buffer = NULL;
+    unsigned int i, pos, len, namelen, maxlen = 0;
+    WCHAR *p;
+    int fd;
+
+    if ((p = strrchrW( name, '\\' ))) name = p + 1;
+
+    i = 0;
+    if (build_dir) maxlen = strlen(build_dir) + sizeof("/programs/") + strlenW(name);
+    while ((path = wine_dll_enum_load_path( i++ ))) maxlen = max( maxlen, strlen(path) );
+    maxlen += sizeof("/fakedlls") + strlenW(name) + 2;
+
+    if (!(file = HeapAlloc( GetProcessHeap(), 0, maxlen ))) return NULL;
+
+    len = strlenW( name );
+    pos = maxlen - len - sizeof(".fake");
+    for (i = 0; i < len; i++)
+    {
+        /* we don't want to depend on the current codepage here */
+        char c = name[i];
+        if (name[i] > 127) goto done;
+        if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
+        file[pos + i] = c;
+    }
+    file[--pos] = '/';
+
+    if (build_dir)
+    {
+        strcpy( file + pos + len + 1, ".fake" );
+
+        /* try as a dll */
+        ptr = file + pos;
+        namelen = len + 1;
+        if (namelen > 4 && !memcmp( ptr + namelen - 4, ".dll", 4 )) namelen -= 4;
+        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;
+
+        /* now as a program */
+        ptr = file + pos;
+        namelen = len + 1;
+        if (namelen > 4 && !memcmp( ptr + namelen - 4, ".exe", 4 )) namelen -= 4;
+        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;
+    }
+
+    file[pos + len + 1] = 0;
+    for (i = 0; (path = wine_dll_enum_load_path( i )); i++)
+    {
+        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;
+    }
+
+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);
+        }
+    }
+    close( fd );
+
+done:
+    HeapFree( GetProcessHeap(), 0, file );
+    return buffer;
+}
+
 /***********************************************************************
  *            create_fake_dll
  */
 BOOL create_fake_dll( const WCHAR *name, const WCHAR *source )
 {
     HANDLE h;
-    HMODULE module;
     BOOL ret;
+    unsigned int size = 0;
+    char *temp_buffer[4096];
+    void *buffer;
 
     /* check for empty name which means to only create the directory */
     if (name[strlenW(name) - 1] == '\\')
@@ -339,12 +443,23 @@ BOOL create_fake_dll( const WCHAR *name, const WCHAR *source )
         }
     }
 
-    module = LoadLibraryW( source );
+    if ((buffer = load_fake_dll( source, &size, temp_buffer, sizeof(temp_buffer) )))
+    {
+        DWORD written;
 
-    ret = build_fake_dll( h, module );
+        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
+    {
+        HMODULE module = LoadLibraryW( source );
+        WARN( "fake dll %s not found for %s\n", debugstr_w(source), debugstr_w(name) );
+        ret = build_fake_dll( h, module );
+        if (module) FreeLibrary( module );
+    }
 
     CloseHandle( h );
-    if (module) FreeLibrary( module );
     if (!ret) DeleteFileW( name );
     return ret;
 }




More information about the wine-cvs mailing list