From 7984ded712d3d0f1bb534df2481a4b8d9f24f7ac Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 2 Jan 2004 21:08:05 +0000 Subject: [PATCH] Added wine_dll_get_owner function that retrieves the 32-bit dll containing a given 16-bit dll by reading the symlink, so that we don't need to dlopen it. --- include/wine/library.h | 1 + libs/wine/loader.c | 105 ++++++++++++++++++++++++++++++++++------- libs/wine/wine.def | 1 + 3 files changed, 90 insertions(+), 17 deletions(-) diff --git a/include/wine/library.h b/include/wine/library.h index 9f03f393e11..29af25800dd 100644 --- a/include/wine/library.h +++ b/include/wine/library.h @@ -47,6 +47,7 @@ extern void *wine_dll_load( const char *filename, char *error, int errorsize, in extern void *wine_dll_load_main_exe( const char *name, char *error, int errorsize, int test_only, int *file_exists ); extern void wine_dll_unload( void *handle ); +extern int wine_dll_get_owner( const char *name, char *buffer, int size, int *file_exists ); extern int __wine_main_argc; extern char **__wine_main_argv; diff --git a/libs/wine/loader.c b/libs/wine/loader.c index 04eeae36dd5..403f62e884b 100644 --- a/libs/wine/loader.c +++ b/libs/wine/loader.c @@ -47,6 +47,12 @@ char **__wine_main_argv = NULL; WCHAR **__wine_main_wargv = NULL; char **__wine_main_environ = NULL; +struct dll_path_context +{ + int index; + char *buffer; +}; + #define MAX_DLLS 100 static struct @@ -121,33 +127,64 @@ inline static int file_exists( const char *name ) return (fd != -1); } + +/* get a filename from the next entry in the dll path */ +static char *next_dll_path( struct dll_path_context *context ) +{ + int index = context->index++; + + if (index < nb_dll_paths) + { + int len = strlen( dll_paths[index] ); + char *path = context->buffer + dll_path_maxlen - len; + memcpy( path, dll_paths[index], len ); + return path; + } + return NULL; +} + + +/* get a filename from the first entry in the dll path */ +static char *first_dll_path( const char *name, const char *ext, struct dll_path_context *context ) +{ + char *p; + int namelen = strlen( name ); + + context->buffer = p = malloc( dll_path_maxlen + namelen + strlen(ext) + 2 ); + context->index = 0; + + /* store the name at the end of the buffer, followed by extension */ + p += dll_path_maxlen; + *p++ = '/'; + memcpy( p, name, namelen ); + strcpy( p + namelen, ext ); + return next_dll_path( context ); +} + + +/* free the dll path context created by first_dll_path */ +inline static void free_dll_path( struct dll_path_context *context ) +{ + free( context->buffer ); +} + + /* open a library for a given dll, searching in the dll path * 'name' must be the Windows dll name (e.g. "kernel32.dll") */ static void *dlopen_dll( const char *name, char *error, int errorsize, int test_only, int *exists ) { - int i, namelen = strlen(name); - char *buffer, *p; + struct dll_path_context context; + char *path; void *ret = NULL; - buffer = malloc( dll_path_maxlen + namelen + 5 ); - - /* store the name at the end of the buffer, followed by .so */ - p = buffer + dll_path_maxlen; - *p++ = '/'; - memcpy( p, name, namelen ); - strcpy( p + namelen, ".so" ); *exists = 0; - - for (i = 0; i < nb_dll_paths; i++) + for (path = first_dll_path( name, ".so", &context ); path; path = next_dll_path( &context )) { - int len = strlen(dll_paths[i]); - p = buffer + dll_path_maxlen - len; - memcpy( p, dll_paths[i], len ); - if (!test_only && (ret = wine_dlopen( p, RTLD_NOW, error, errorsize ))) break; - if ((*exists = file_exists( p ))) break; /* exists but cannot be loaded, return the error */ + if (!test_only && (ret = wine_dlopen( path, RTLD_NOW, error, errorsize ))) break; + if ((*exists = file_exists( path ))) break; /* exists but cannot be loaded, return the error */ } - free( buffer ); + free_dll_path( &context ); return ret; } @@ -411,6 +448,40 @@ void *wine_dll_load_main_exe( const char *name, char *error, int errorsize, } +/*********************************************************************** + * wine_dll_get_owner + * + * Retrieve the name of the 32-bit owner dll for a 16-bit dll. + * Return 0 if OK, -1 on error. + */ +int wine_dll_get_owner( const char *name, char *buffer, int size, int *exists ) +{ + int ret = -1; + char *path; + struct dll_path_context context; + + *exists = 0; + for (path = first_dll_path( name, ".so", &context ); path; path = next_dll_path( &context )) + { + int res = readlink( path, buffer, size ); + if (res != -1) /* got a symlink */ + { + *exists = 1; + if (res < 4 || res >= size) break; + buffer[res] = 0; + if (strchr( buffer, '/' )) break; /* contains a path, not valid */ + if (strcmp( buffer + res - 3, ".so" )) break; /* does not end in .so, not valid */ + buffer[res - 3] = 0; /* remove .so */ + ret = 0; + break; + } + if ((*exists = file_exists( path ))) break; /* exists but not a symlink, return the error */ + } + free_dll_path( &context ); + return ret; +} + + /*********************************************************************** * debug_usage */ diff --git a/libs/wine/wine.def b/libs/wine/wine.def index 61dac7b1fad..aabba48621c 100644 --- a/libs/wine/wine.def +++ b/libs/wine/wine.def @@ -24,6 +24,7 @@ EXPORTS wine_dbgstr_w wine_dbgstr_wn wine_dlclose + wine_dll_get_owner wine_dll_load wine_dll_load_main_exe wine_dll_set_callback