Alexandre Julliard : setupapi: Add support for installing PE builtins as fake dlls.

Alexandre Julliard julliard at winehq.org
Mon Apr 22 16:30:38 CDT 2019


Module: wine
Branch: master
Commit: 510e746718bb11f45fff58517582e72c09f1055a
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=510e746718bb11f45fff58517582e72c09f1055a

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Apr 22 11:40:41 2019 +0200

setupapi: Add support for installing PE builtins as fake dlls.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/setupapi/fakedll.c | 53 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 33 insertions(+), 20 deletions(-)

diff --git a/dlls/setupapi/fakedll.c b/dlls/setupapi/fakedll.c
index e0d012a..260eb1e 100644
--- a/dlls/setupapi/fakedll.c
+++ b/dlls/setupapi/fakedll.c
@@ -51,6 +51,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
 
+static const char builtin_signature[] = "Wine builtin DLL";
 static const char fakedll_signature[] = "Wine placeholder DLL";
 
 static const unsigned int file_alignment = 512;
@@ -191,14 +192,15 @@ failed:
 
 /* 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 int read_file( const char *name, void **data, SIZE_T *size, BOOL expect_builtin )
 {
     struct stat st;
     int fd, ret = -1;
     size_t header_size;
     IMAGE_DOS_HEADER *dos;
     IMAGE_NT_HEADERS *nt;
-    const size_t min_size = sizeof(*dos) + sizeof(fakedll_signature) +
+    const char *signature = expect_builtin ? builtin_signature : fakedll_signature;
+    const size_t min_size = sizeof(*dos) + 32 +
         FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader.MajorLinkerVersion );
 
     if ((fd = open( name, O_RDONLY | O_BINARY )) == -1) return 0;
@@ -220,8 +222,8 @@ static int read_file( const char *name, void **data, SIZE_T *size )
     if (pread( fd, file_buffer, header_size, 0 ) != header_size) goto done;
     dos = file_buffer;
     if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto done;
-    if (dos->e_lfanew < sizeof(fakedll_signature)) goto done;
-    if (memcmp( dos + 1, fakedll_signature, sizeof(fakedll_signature) )) goto done;
+    if (dos->e_lfanew < strlen(signature) + 1) goto done;
+    if (memcmp( dos + 1, signature, strlen(signature) + 1 )) goto done;
     if (dos->e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader.MajorLinkerVersion) > header_size)
         goto done;
     nt = (IMAGE_NT_HEADERS *)((char *)file_buffer + dos->e_lfanew);
@@ -354,14 +356,15 @@ static BOOL is_fake_dll( HANDLE h )
 {
     IMAGE_DOS_HEADER *dos;
     DWORD size;
-    BYTE buffer[sizeof(*dos) + sizeof(fakedll_signature)];
+    BYTE buffer[sizeof(*dos) + 32];
 
     if (!ReadFile( h, buffer, sizeof(buffer), &size, NULL ) || size != sizeof(buffer))
         return FALSE;
     dos = (IMAGE_DOS_HEADER *)buffer;
     if (dos->e_magic != IMAGE_DOS_SIGNATURE) return FALSE;
     if (dos->e_lfanew < size) return FALSE;
-    return !memcmp( dos + 1, fakedll_signature, sizeof(fakedll_signature) );
+    return (!memcmp( dos + 1, builtin_signature, sizeof(builtin_signature) ) ||
+            !memcmp( dos + 1, fakedll_signature, sizeof(fakedll_signature) ));
 }
 
 /* create directories leading to a given file */
@@ -417,33 +420,39 @@ static void *load_fake_dll( const WCHAR *name, SIZE_T *size )
 
     if (build_dir)
     {
-        strcpy( file + pos + len + 1, ".fake" );
-
         /* try as a dll */
         ptr = file + pos;
         namelen = len + 1;
+        file[pos + len + 1] = 0;
         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 ((res = read_file( ptr, &data, size ))) goto done;
+        if ((res = read_file( ptr, &data, size, TRUE ))) goto done;
+        strcpy( file + pos + len + 1, ".fake" );
+        if ((res = read_file( ptr, &data, size, FALSE ))) goto done;
 
         /* now as a program */
         ptr = file + pos;
         namelen = len + 1;
+        file[pos + len + 1] = 0;
         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 ((res = read_file( ptr, &data, size ))) goto done;
+        if ((res = read_file( ptr, &data, size, TRUE ))) goto done;
+        strcpy( file + pos + len + 1, ".fake" );
+        if ((res = read_file( ptr, &data, size, FALSE ))) goto done;
     }
 
     file[pos + len + 1] = 0;
     for (i = 0; (path = wine_dll_enum_load_path( i )); i++)
     {
+        ptr = prepend( file + pos, path, strlen(path) );
+        if ((res = read_file( ptr, &data, size, TRUE ))) break;
         ptr = prepend( file + pos, "/fakedlls", sizeof("/fakedlls") - 1 );
         ptr = prepend( ptr, path, strlen(path) );
-        if ((res = read_file( ptr, &data, size ))) break;
+        if ((res = read_file( ptr, &data, size, FALSE ))) break;
     }
 
 done:
@@ -842,7 +851,7 @@ static void register_fake_dll( const WCHAR *name, const void *data, size_t size
 }
 
 /* copy a fake dll file to the dest directory */
-static void install_fake_dll( WCHAR *dest, char *file, const char *ext )
+static int install_fake_dll( WCHAR *dest, char *file, const char *ext, BOOL expect_builtin )
 {
     int ret;
     SIZE_T size;
@@ -852,8 +861,8 @@ static void install_fake_dll( WCHAR *dest, char *file, const char *ext )
     char *name = strrchr( file, '/' ) + 1;
     char *end = name + strlen(name);
 
-    if (ext) strcpy( end, ext );
-    if (!(ret = read_file( file, &data, &size ))) return;
+    strcpy( end, ext );
+    if (!(ret = read_file( file, &data, &size, expect_builtin ))) return 0;
 
     if (end > name + 2 && !strncmp( end - 2, "16", 2 )) end -= 2;  /* remove "16" suffix */
     dll_name_AtoW( destname, name, end - name );
@@ -875,10 +884,11 @@ static void install_fake_dll( WCHAR *dest, char *file, const char *ext )
         }
     }
     *destname = 0;  /* restore it for next file */
+    return ret;
 }
 
 /* find and install all fake dlls in a given lib directory */
-static void install_lib_dir( WCHAR *dest, char *file, const char *default_ext )
+static void install_lib_dir( WCHAR *dest, char *file, const char *default_ext, BOOL expect_builtin )
 {
     DIR *dir;
     struct dirent *de;
@@ -898,9 +908,10 @@ static void install_lib_dir( WCHAR *dest, char *file, const char *default_ext )
             strcat( name, "/" );
             strcat( name, de->d_name );
             if (!strchr( de->d_name, '.' )) strcat( name, default_ext );
-            install_fake_dll( dest, file, ".fake" );
+            if (!install_fake_dll( dest, file, "", expect_builtin ))
+                install_fake_dll( dest, file, ".fake", FALSE );
         }
-        else install_fake_dll( dest, file, NULL );
+        else install_fake_dll( dest, file, "", expect_builtin );
     }
     closedir( dir );
 }
@@ -931,16 +942,18 @@ static BOOL create_wildcard_dlls( const WCHAR *dirname )
     {
         strcpy( file, build_dir );
         strcat( file, "/dlls" );
-        install_lib_dir( dest, file, ".dll" );
+        install_lib_dir( dest, file, ".dll", TRUE );
         strcpy( file, build_dir );
         strcat( file, "/programs" );
-        install_lib_dir( dest, file, ".exe" );
+        install_lib_dir( dest, file, ".exe", TRUE );
     }
     for (i = 0; (path = wine_dll_enum_load_path( i )); i++)
     {
         strcpy( file, path );
+        install_lib_dir( dest, file, NULL, TRUE );
+        strcpy( file, path );
         strcat( file, "/fakedlls" );
-        install_lib_dir( dest, file, NULL );
+        install_lib_dir( dest, file, NULL, FALSE );
     }
     HeapFree( GetProcessHeap(), 0, file );
     HeapFree( GetProcessHeap(), 0, dest );




More information about the wine-cvs mailing list