Added support for loading a Winelib app linked as a .so from the wine

launcher, based on the value of argv[0].
This commit is contained in:
Alexandre Julliard 2000-11-10 01:38:28 +00:00
parent 70098f6990
commit 591832ec2e
3 changed files with 100 additions and 10 deletions

View file

@ -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_set_callback( load_dll_callback_t load );
extern void *wine_dll_load( const char *filename ); 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 ); extern void wine_dll_unload( void *handle );
/* debugging */ /* debugging */

View file

@ -350,3 +350,53 @@ void wine_dll_unload( void *handle )
if (handle != (void *)1) dlclose( handle ); if (handle != (void *)1) dlclose( handle );
#endif #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;
}

View file

@ -14,6 +14,7 @@
#include <unistd.h> #include <unistd.h>
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "wine/exception.h" #include "wine/exception.h"
#include "wine/library.h"
#include "process.h" #include "process.h"
#include "drive.h" #include "drive.h"
#include "main.h" #include "main.h"
@ -170,6 +171,7 @@ static BOOL process_init( char *argv[] )
/* store the program name */ /* store the program name */
argv0 = argv[0]; argv0 = argv[0];
main_exe_argv = argv;
/* Fill the initial process structure */ /* Fill the initial process structure */
current_process.exit_code = STILL_ACTIVE; 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 * PROCESS_InitWine
* *
@ -378,6 +415,8 @@ void PROCESS_InitWine( int argc, char *argv[] )
/* Initialize everything */ /* Initialize everything */
if (!process_init( argv )) exit(1); 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) */ main_exe_argv = ++argv; /* remove argv[0] (wine itself) */
if (!main_exe_name[0]) 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) if (PE_HEADER(main_module)->FileHeader.Characteristics & IMAGE_FILE_DLL)
ExitProcess( ERROR_BAD_EXE_FORMAT ); ExitProcess( ERROR_BAD_EXE_FORMAT );
stack_size = PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve; stack_size = PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve;
} goto found;
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();
} }
/* 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 */ /* allocate main thread stack */
if (!THREAD_InitStack( NtCurrentTeb(), stack_size, TRUE )) goto error; 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[] ) void PROCESS_InitWinelib( int argc, char *argv[] )
{ {
if (!process_init( argv )) exit(1); if (!process_init( argv )) exit(1);
main_exe_argv = argv;
/* allocate main thread stack */ /* allocate main thread stack */
if (!THREAD_InitStack( NtCurrentTeb(), 0, TRUE )) ExitProcess( GetLastError() ); if (!THREAD_InitStack( NtCurrentTeb(), 0, TRUE )) ExitProcess( GetLastError() );