setupapi: Add support for installing PE builtins as fake dlls.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
948fc85186
commit
510e746718
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue