From 591832ec2e57e06e025f4bc3a5ea5f70a3ea9851 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 10 Nov 2000 01:38:28 +0000 Subject: [PATCH] Added support for loading a Winelib app linked as a .so from the wine launcher, based on the value of argv[0]. --- include/wine/library.h | 1 + library/loader.c | 50 +++++++++++++++++++++++++++++++++++ scheduler/process.c | 59 +++++++++++++++++++++++++++++++++++------- 3 files changed, 100 insertions(+), 10 deletions(-) diff --git a/include/wine/library.h b/include/wine/library.h index 5387f30f16e..f656ae91233 100644 --- a/include/wine/library.h +++ b/include/wine/library.h @@ -15,6 +15,7 @@ typedef void (*load_dll_callback_t)( void *, const char * ); extern void wine_dll_set_callback( load_dll_callback_t load ); extern void *wine_dll_load( const char *filename ); +extern void *wine_dll_load_main_exe( const char *name, int search_path ); extern void wine_dll_unload( void *handle ); /* debugging */ diff --git a/library/loader.c b/library/loader.c index 4d202ac7218..0a04c1c643d 100644 --- a/library/loader.c +++ b/library/loader.c @@ -350,3 +350,53 @@ void wine_dll_unload( void *handle ) if (handle != (void *)1) dlclose( handle ); #endif } + + +/*********************************************************************** + * wine_dll_load_main_exe + * + * Try to load the .so for the main exe, optionally searching for it in PATH. + */ +void *wine_dll_load_main_exe( const char *name, int search_path ) +{ + void *ret = NULL; +#ifdef HAVE_DL_API + const char *path = NULL; + if (search_path) path = getenv( "PATH" ); + + if (!path) + { + /* no path, try only the specified name */ + ret = dlopen( name, RTLD_NOW ); + } + else + { + char buffer[128], *tmp = buffer; + size_t namelen = strlen(name); + size_t pathlen = strlen(path); + + if (namelen + pathlen + 2 > sizeof(buffer)) tmp = malloc( namelen + pathlen + 2 ); + if (tmp) + { + char *basename = tmp + pathlen; + *basename = '/'; + strcpy( basename + 1, name ); + for (;;) + { + int len; + const char *p = strchr( path, ':' ); + if (!p) p = path + strlen(path); + if ((len = p - path) > 0) + { + memcpy( basename - len, path, len ); + if ((ret = dlopen( basename - len, RTLD_NOW ))) break; + } + if (!*p) break; + path = p + 1; + } + if (tmp != buffer) free( tmp ); + } + } +#endif /* HAVE_DL_API */ + return ret; +} diff --git a/scheduler/process.c b/scheduler/process.c index f6bc48a875b..6db56a78aa6 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -14,6 +14,7 @@ #include #include "wine/winbase16.h" #include "wine/exception.h" +#include "wine/library.h" #include "process.h" #include "drive.h" #include "main.h" @@ -170,6 +171,7 @@ static BOOL process_init( char *argv[] ) /* store the program name */ argv0 = argv[0]; + main_exe_argv = argv; /* Fill the initial process structure */ current_process.exit_code = STILL_ACTIVE; @@ -366,6 +368,41 @@ static void start_process(void) } +/*********************************************************************** + * open_winelib_app + * + * Try to open the Winelib app .so file based on argv[0] or WINEPRELOAD. + */ +void *open_winelib_app( const char *argv0 ) +{ + void *ret = NULL; + char *tmp; + const char *name; + + if ((name = getenv( "WINEPRELOAD" ))) + { + ret = wine_dll_load_main_exe( name, 0 ); + } + else + { + /* if argv[0] is "wine", don't try to load anything */ + if (!(name = strrchr( argv0, '/' ))) name = argv0; + else name++; + if (!strcmp( name, "wine" )) return NULL; + + /* now try argv[0] with ".so" appended */ + if ((tmp = HeapAlloc( GetProcessHeap(), 0, strlen(argv0) + 4 ))) + { + strcpy( tmp, argv0 ); + strcat( tmp, ".so" ); + /* search in PATH only if there was no '/' in argv[0] */ + ret = wine_dll_load_main_exe( tmp, (name == argv0) ); + HeapFree( GetProcessHeap(), 0, tmp ); + } + } + return ret; +} + /*********************************************************************** * PROCESS_InitWine * @@ -378,6 +415,8 @@ void PROCESS_InitWine( int argc, char *argv[] ) /* Initialize everything */ if (!process_init( argv )) exit(1); + if (open_winelib_app( argv[0] )) goto found; /* try to open argv[0] as a winelib app */ + main_exe_argv = ++argv; /* remove argv[0] (wine itself) */ if (!main_exe_name[0]) @@ -409,17 +448,18 @@ void PROCESS_InitWine( int argc, char *argv[] ) if (PE_HEADER(main_module)->FileHeader.Characteristics & IMAGE_FILE_DLL) ExitProcess( ERROR_BAD_EXE_FORMAT ); stack_size = PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve; - } - else /* it must be 16-bit or DOS format */ - { - NtCurrentTeb()->tibflags &= ~TEBF_WIN32; - current_process.flags |= PDB32_WIN16_PROC; - main_exe_name[0] = 0; - CloseHandle( main_exe_file ); - main_exe_file = INVALID_HANDLE_VALUE; - SYSLEVEL_EnterWin16Lock(); + goto found; } + /* it must be 16-bit or DOS format */ + NtCurrentTeb()->tibflags &= ~TEBF_WIN32; + current_process.flags |= PDB32_WIN16_PROC; + main_exe_name[0] = 0; + CloseHandle( main_exe_file ); + main_exe_file = INVALID_HANDLE_VALUE; + SYSLEVEL_EnterWin16Lock(); + + found: /* allocate main thread stack */ if (!THREAD_InitStack( NtCurrentTeb(), stack_size, TRUE )) goto error; @@ -439,7 +479,6 @@ void PROCESS_InitWine( int argc, char *argv[] ) void PROCESS_InitWinelib( int argc, char *argv[] ) { if (!process_init( argv )) exit(1); - main_exe_argv = argv; /* allocate main thread stack */ if (!THREAD_InitStack( NtCurrentTeb(), 0, TRUE )) ExitProcess( GetLastError() );