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