Moved builtin dll registration to libwine.

Changed process initialization to not load imported dlls too early.
This commit is contained in:
Alexandre Julliard 2000-11-08 04:33:20 +00:00
parent b1eb301477
commit e087508f57
13 changed files with 390 additions and 208 deletions

View File

@ -85,6 +85,7 @@ INSTALLED_INCLUDES = \
wine/exception.h \
wine/icmpapi.h \
wine/ipexport.h \
wine/library.h \
wine/obj_base.h \
wine/obj_cache.h \
wine/obj_channel.h \

View File

@ -30,7 +30,7 @@ typedef struct _DOSTASK {
#define V86_FLAG 0x00020000
extern BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename );
extern BOOL MZ_LoadImage( LPCSTR cmdline );
extern BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
extern void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval );
extern LPDOSTASK MZ_Current( void );

View File

@ -180,7 +180,6 @@ extern void MODULE_DllThreadDetach( LPVOID lpReserved );
extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags );
extern BOOL MODULE_FreeLibrary( WINE_MODREF *wm );
extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
extern BOOL MODULE_GetBinaryType( HANDLE hfile, LPCSTR filename, LPDWORD lpBinaryType );
extern HMODULE MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name );
extern SEGPTR WINAPI HasGPHandler16( SEGPTR address );
@ -238,7 +237,7 @@ extern WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags);
/* relay32/builtin.c */
extern WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags);
extern HMODULE BUILTIN32_LoadExeModule(void);
extern HMODULE BUILTIN32_LoadExeModule( HMODULE main );
extern void *BUILTIN32_dlopen( const char *name );
extern int BUILTIN32_dlclose( void *handle );

View File

@ -10,6 +10,7 @@ SONAME = libwine.so
C_SRCS = \
debug.c \
loader.c \
port.c
all: libwine.$(LIBEXT)

View File

@ -56,7 +56,7 @@ static void apply_option( struct dll *dll, const struct option *opt )
}
/* register a new set of channels for a dll */
void *wine_dbg_register( char * const *channels, int nb )
void *__wine_dbg_register( char * const *channels, int nb )
{
struct option *opt = first_option;
struct dll *dll = malloc( sizeof(*dll) );
@ -80,7 +80,7 @@ void *wine_dbg_register( char * const *channels, int nb )
/* unregister a set of channels; must pass the pointer obtained from wine_dbg_register */
void wine_dbg_unregister( void *channel )
void __wine_dbg_unregister( void *channel )
{
struct dll *dll = channel;
if (dll)

203
library/loader.c Normal file
View File

@ -0,0 +1,203 @@
/*
* Win32 builtin dlls support
*
* Copyright 2000 Alexandre Julliard
*/
#include "config.h"
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_DL_API
#include <dlfcn.h>
#endif
#include "windef.h"
#include "wine/library.h"
#define MAX_DLLS 100
static struct
{
const IMAGE_NT_HEADERS *nt; /* NT header */
const char *filename; /* DLL file name */
} builtin_dlls[MAX_DLLS];
static int nb_dlls;
static const IMAGE_NT_HEADERS *main_exe;
static load_dll_callback_t load_dll_callback;
static char **dll_paths;
static int nb_dll_paths;
static int dll_path_maxlen;
static int init_done;
/* build the dll load path from the WINEDLLPATH variable */
static void build_dll_path(void)
{
int count = 0;
char *p, *path = getenv( "WINEDLLPATH" );
init_done = 1;
if (!path) return;
path = strdup(path);
p = path;
while (*p)
{
while (*p == ':') p++;
if (!*p) break;
count++;
while (*p && *p != ':') p++;
}
dll_paths = malloc( count * sizeof(*dll_paths) );
p = path;
nb_dll_paths = 0;
while (*p)
{
while (*p == ':') *p++ = 0;
if (!*p) break;
dll_paths[nb_dll_paths] = p;
while (*p && *p != ':') p++;
if (p - dll_paths[nb_dll_paths] > dll_path_maxlen)
dll_path_maxlen = p - dll_paths[nb_dll_paths];
nb_dll_paths++;
}
}
/* 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 )
{
#ifdef HAVE_DL_API
int i, namelen = strlen(name);
char *buffer, *p;
void *ret = NULL;
if (!init_done) build_dll_path();
/* check for .dll or .exe extension to remove */
if ((p = strrchr( name, '.' )))
{
if (!strcasecmp( p, ".dll" ) || !strcasecmp( p, ".exe" )) namelen -= 4;
}
buffer = malloc( dll_path_maxlen + namelen + 8 );
/* store the name at the end of the buffer, prefixed by /lib and followed by .so */
p = buffer + dll_path_maxlen;
memcpy( p, "/lib", 4 );
for (i = 0, p += 4; i < namelen; i++, p++) *p = tolower(name[i]);
memcpy( p, ".so", 4 );
for (i = 0; i < nb_dll_paths; i++)
{
int len = strlen(dll_paths[i]);
char *p = buffer + dll_path_maxlen - len;
memcpy( p, dll_paths[i], len );
if ((ret = dlopen( p, RTLD_NOW ))) break;
}
/* now try the default dlopen search path */
if (!ret) ret = dlopen( buffer + dll_path_maxlen + 1, RTLD_NOW );
free( buffer );
return ret;
#else
return NULL;
#endif
}
/***********************************************************************
* __wine_dll_register
*
* Register a built-in DLL descriptor.
*/
void __wine_dll_register( const IMAGE_NT_HEADERS *header, const char *filename )
{
if (load_dll_callback) load_dll_callback( header, filename );
else
{
if (!(header->FileHeader.Characteristics & IMAGE_FILE_DLL))
main_exe = header;
else
{
assert( nb_dlls < MAX_DLLS );
builtin_dlls[nb_dlls].nt = header;
builtin_dlls[nb_dlls].filename = filename;
nb_dlls++;
}
}
}
/***********************************************************************
* wine_dll_set_callback
*
* Set the callback function for dll loading, and call it
* for all dlls that were implicitly loaded already.
*/
void wine_dll_set_callback( load_dll_callback_t load )
{
int i;
load_dll_callback = load;
for (i = 0; i < nb_dlls; i++)
{
const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
if (!nt) continue;
builtin_dlls[i].nt = NULL;
load_dll_callback( nt, builtin_dlls[i].filename );
}
nb_dlls = 0;
if (main_exe) load_dll_callback( main_exe, "" );
}
/***********************************************************************
* wine_dll_load
*
* Load a builtin dll.
*/
void *wine_dll_load( const char *filename )
{
int i;
/* callback must have been set already */
assert( load_dll_callback );
/* check if we have it in the list */
/* this can happen when initializing pre-loaded dlls in wine_dll_set_callback */
for (i = 0; i < nb_dlls; i++)
{
if (!builtin_dlls[i].nt) continue;
if (!strcasecmp( builtin_dlls[i].filename, filename ))
{
const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
builtin_dlls[i].nt = NULL;
load_dll_callback( nt, builtin_dlls[i].filename );
return (void *)1;
}
}
return dlopen_dll( filename );
}
/***********************************************************************
* wine_dll_unload
*
* Unload a builtin dll.
*/
void wine_dll_unload( void *handle )
{
#ifdef HAVE_DL_API
if (handle != (void *)1) dlclose( handle );
#endif
}

View File

@ -203,7 +203,7 @@ static BOOL MZ_InitMemory(void)
return TRUE;
}
BOOL MZ_DoLoadImage( HMODULE module, HANDLE hFile, LPCSTR filename, OverlayBlock *oblk )
BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk )
{
LPDOSTASK lpDosTask = dos_current;
IMAGE_DOS_HEADER mz_header;
@ -233,6 +233,12 @@ BOOL MZ_DoLoadImage( HMODULE module, HANDLE hFile, LPCSTR filename, OverlayBlock
if ( !ReadFile(hFile,&mz_header,sizeof(mz_header),&len,NULL)
|| len != sizeof(mz_header)
|| mz_header.e_magic != IMAGE_DOS_SIGNATURE) {
char *p = strrchr( filename, '.' );
if (!p || strcasecmp( p, ".com" )) /* check for .COM extension */
{
SetLastError(ERROR_BAD_FORMAT);
goto load_error;
}
old_com=1; /* assume .COM file */
image_start=0;
image_size=GetFileSize(hFile,NULL);
@ -331,16 +337,33 @@ load_error:
return FALSE;
}
BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
BOOL MZ_LoadImage( LPCSTR cmdline )
{
IMAGE_NT_HEADERS *win_hdr = PE_HEADER(module);
HFILE hFile;
char *name, buffer[MAX_PATH];
LPCSTR p = strchr( cmdline, ' ' );
if (win_hdr) {
win_hdr->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
win_hdr->OptionalHeader.AddressOfEntryPoint = (LPBYTE)MZ_Launch - (LPBYTE)module;
}
if (p)
{
if (!(name = HeapAlloc( GetProcessHeap(), 0, p - cmdline + 1 ))) return FALSE;
memcpy( name, cmdline, p - cmdline );
name[p - cmdline] = 0;
}
else name = (char *)cmdline;
return MZ_DoLoadImage( module, hFile, filename, NULL );
if (!SearchPathA( NULL, name, ".exe", sizeof(buffer), buffer, NULL )) goto error;
if ((hFile = CreateFileA( buffer, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, -1 )) == INVALID_HANDLE_VALUE)
goto error;
if (!MZ_DoLoadImage( hFile, buffer, NULL ))
{
CloseHandle( hFile );
goto error;
}
MZ_Launch();
error:
if (name != cmdline) HeapFree( GetProcessHeap(), 0, name );
return FALSE;
}
BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
@ -363,7 +386,7 @@ BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
PDB16 *psp = (PDB16 *)psp_start;
psp->saveStack = (DWORD)PTR_SEG_OFF_TO_SEGPTR(context->SegSs, LOWORD(context->Esp));
}
ret = MZ_DoLoadImage( NULL, hFile, filename, NULL );
ret = MZ_DoLoadImage( hFile, filename, NULL );
if (ret) {
/* MZ_LoadImage created a new PSP and loaded new values into lpDosTask,
* let's work on the new values now */
@ -393,7 +416,7 @@ BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
case 3: /* load overlay */
{
OverlayBlock *blk = (OverlayBlock *)paramblk;
ret = MZ_DoLoadImage( NULL, hFile, filename, blk );
ret = MZ_DoLoadImage( hFile, filename, blk );
}
break;
default:
@ -589,7 +612,7 @@ void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
#else /* !MZ_SUPPORTED */
BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
BOOL MZ_LoadImage( LPCSTR cmdline )
{
WARN("DOS executables not supported on this platform\n");
SetLastError(ERROR_BAD_FORMAT);

View File

@ -532,7 +532,7 @@ good:
* Note that .COM and .PIF files are only recognized by their
* file name extension; but Windows does it the same way ...
*/
BOOL MODULE_GetBinaryType( HANDLE hfile, LPCSTR filename, LPDWORD lpBinaryType )
static BOOL MODULE_GetBinaryType( HANDLE hfile, LPCSTR filename, LPDWORD lpBinaryType )
{
IMAGE_DOS_HEADER mz_header;
char magic[4], *ptr;

View File

@ -475,6 +475,7 @@ HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, DWORD flags )
TRACE_(module)( "loading %s\n", filename );
mapping = CreateFileMappingA( hFile, NULL, SEC_IMAGE, 0, 0, NULL );
if (!mapping) return 0;
base = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
CloseHandle( mapping );
if (!base) return 0;

View File

@ -10,6 +10,7 @@
#include "callback.h"
#include "options.h"
#include "dosexe.h"
#include "process.h"
#include "debugtools.h"
@ -27,6 +28,13 @@ void wine_initial_task(void)
if ((instance = WinExec16( GetCommandLineA(), info.wShowWindow )) < 32)
{
if (instance == 11) /* try DOS format */
{
MZ_LoadImage( GetCommandLineA() );
/* if we get back here it failed */
instance = GetLastError();
}
MESSAGE( "%s: can't exec '%s': ", argv0, GetCommandLineA() );
switch (instance)
{

View File

@ -20,6 +20,7 @@
#include "windef.h"
#include "wine/winbase16.h"
#include "wine/library.h"
#include "elfdll.h"
#include "global.h"
#include "neexe.h"
@ -32,19 +33,9 @@
DEFAULT_DEBUG_CHANNEL(module);
DECLARE_DEBUG_CHANNEL(relay);
#define MAX_DLLS 100
typedef struct
{
const IMAGE_NT_HEADERS *nt; /* NT header */
const char *filename; /* DLL file name */
} BUILTIN32_DESCRIPTOR;
extern void RELAY_SetupDLL( const char *module );
static BUILTIN32_DESCRIPTOR builtin_dlls[MAX_DLLS];
static int nb_dlls;
static HMODULE main_module;
/***********************************************************************
* BUILTIN32_dlopen
@ -53,16 +44,10 @@ void *BUILTIN32_dlopen( const char *name )
{
#ifdef HAVE_DL_API
void *handle;
char buffer[128], *p;
if ((p = strrchr( name, '/' ))) name = p + 1;
if ((p = strrchr( name, '\\' ))) name = p + 1;
sprintf( buffer, "lib%s", name );
for (p = buffer; *p; p++) *p = tolower(*p);
if ((p = strrchr( buffer, '.' )) && (!strcmp( p, ".dll" ) || !strcmp( p, ".exe" ))) *p = 0;
strcat( buffer, ".so" );
if (!(handle = ELFDLL_dlopen( buffer, RTLD_NOW )))
if (!(handle = wine_dll_load( name )))
{
char buffer[128];
LPSTR pErr, p;
pErr = dlerror();
p = strchr(pErr, ':');
@ -130,11 +115,11 @@ static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *ba
/***********************************************************************
* BUILTIN32_DoLoadImage
* load_image
*
* Load a built-in Win32 module. Helper function for BUILTIN32_LoadImage.
* Load a built-in Win32 module. Helper function for load_library.
*/
static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
static HMODULE load_image( const IMAGE_NT_HEADERS *nt_descr, const char *filename )
{
IMAGE_DATA_DIRECTORY *dir;
IMAGE_DOS_HEADER *dos;
@ -154,13 +139,12 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
assert( size <= page_size );
if (descr->nt->OptionalHeader.ImageBase)
if (nt_descr->OptionalHeader.ImageBase)
{
void *base = (void *)descr->nt->OptionalHeader.ImageBase;
if ((addr = VIRTUAL_mmap( -1, base, page_size, 0,
PROT_READ|PROT_WRITE, MAP_FIXED )) != base)
void *base = (void *)nt_descr->OptionalHeader.ImageBase;
if ((addr = wine_anon_mmap( base, page_size, PROT_READ|PROT_WRITE, MAP_FIXED )) != base)
{
ERR("failed to map over PE header for %s at %p\n", descr->filename, base );
ERR("failed to map over PE header for %s at %p\n", filename, base );
return 0;
}
}
@ -182,7 +166,7 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
dos->e_magic = IMAGE_DOS_SIGNATURE;
dos->e_lfanew = sizeof(*dos);
*nt = *descr->nt;
*nt = *nt_descr;
nt->FileHeader.NumberOfSections = nb_sections;
nt->OptionalHeader.SizeOfCode = data_start - code_start;
@ -255,6 +239,42 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
return (HMODULE)addr;
}
/***********************************************************************
* load_library
*
* Load a library in memory; callback function for wine_dll_register
*/
static void load_library( const IMAGE_NT_HEADERS *nt, const char *filename )
{
HMODULE module;
WINE_MODREF *wm;
if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
{
/* if we already have an executable, ignore this one */
if (!main_module) main_module = load_image( nt, "main exe" );
return; /* don't create the modref here, will be done later on */
}
if (GetModuleHandleA( filename ))
MESSAGE( "Warning: loading builtin %s, but native version already present. Expect trouble.\n", filename );
/* Load built-in module */
if (!(module = load_image( nt, filename ))) return;
/* Create 32-bit MODREF */
if (!(wm = PE_CreateModule( module, filename, 0, -1, TRUE )))
{
ERR( "can't load %s\n", filename );
SetLastError( ERROR_OUTOFMEMORY );
return;
}
TRACE( "loaded %s %p %x %p\n", filename, wm, module, nt );
wm->refCount++; /* we don't support freeing builtin dlls (FIXME)*/
}
/***********************************************************************
* BUILTIN32_LoadLibraryExA
*
@ -263,12 +283,10 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
*/
WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
{
HMODULE module;
WINE_MODREF *wm;
char dllname[20], *p;
LPCSTR name;
void *handle;
int i;
/* Fix the name in case we have a full path and extension */
name = path;
@ -281,66 +299,36 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
p = strrchr( dllname, '.' );
if (!p) strcat( dllname, ".dll" );
/* Search built-in descriptor */
for (i = 0; i < nb_dlls; i++)
if (!strcasecmp( builtin_dlls[i].filename, dllname )) goto found;
if (!(handle = BUILTIN32_dlopen( dllname ))) goto error;
if ((handle = BUILTIN32_dlopen( dllname )))
if (!(wm = MODULE_FindModule( path ))) wm = MODULE_FindModule( dllname );
if (!wm)
{
for (i = 0; i < nb_dlls; i++)
if (!strcasecmp( builtin_dlls[i].filename, dllname )) goto found;
ERR( "loaded .so but dll %s still not found\n", dllname );
BUILTIN32_dlclose( handle );
/* wine_dll_unload( handle );*/
return NULL;
}
wm->dlhandle = handle;
return wm;
error:
SetLastError( ERROR_FILE_NOT_FOUND );
return NULL;
found:
/* Load built-in module */
if (!(module = BUILTIN32_DoLoadImage( &builtin_dlls[i] ))) return NULL;
/* Create 32-bit MODREF */
if ( !(wm = PE_CreateModule( module, path, flags, -1, TRUE )) )
{
ERR( "can't load %s\n", path );
SetLastError( ERROR_OUTOFMEMORY );
return NULL;
}
wm->refCount++; /* we don't support freeing builtin dlls (FIXME)*/
return wm;
}
/***********************************************************************
* BUILTIN32_LoadExeModule
* BUILTIN32_Init
*
* Initialize loading callbacks and return HMODULE of main exe.
* 'main' is the main exe in case if was already loaded from a PE file.
*/
HMODULE BUILTIN32_LoadExeModule(void)
HMODULE BUILTIN32_LoadExeModule( HMODULE main )
{
int i, exe = -1;
/* Search built-in EXE descriptor */
for ( i = 0; i < nb_dlls; i++ )
if ( !(builtin_dlls[i].nt->FileHeader.Characteristics & IMAGE_FILE_DLL) )
{
if ( exe != -1 )
{
MESSAGE( "More than one built-in EXE module loaded!\n" );
break;
}
exe = i;
}
if ( exe == -1 )
{
main_module = main;
wine_dll_set_callback( load_library );
if (!main_module)
MESSAGE( "No built-in EXE module loaded! Did you create a .spec file?\n" );
return 0;
}
/* Load built-in module */
return BUILTIN32_DoLoadImage( &builtin_dlls[exe] );
return main_module;
}
@ -351,8 +339,6 @@ HMODULE BUILTIN32_LoadExeModule(void)
*/
void BUILTIN32_RegisterDLL( const IMAGE_NT_HEADERS *header, const char *filename )
{
assert( nb_dlls < MAX_DLLS );
builtin_dlls[nb_dlls].nt = header;
builtin_dlls[nb_dlls].filename = filename;
nb_dlls++;
extern void __wine_dll_register( const IMAGE_NT_HEADERS *header, const char *filename );
__wine_dll_register( header, filename );
}

View File

@ -19,7 +19,6 @@
#include "main.h"
#include "module.h"
#include "neexe.h"
#include "dosexe.h"
#include "file.h"
#include "global.h"
#include "heap.h"
@ -42,6 +41,7 @@ PDB current_process;
static char **main_exe_argv;
static char main_exe_name[MAX_PATH];
static HANDLE main_exe_file = INVALID_HANDLE_VALUE;
static HMODULE main_module;
unsigned int server_startticks;
@ -317,27 +317,34 @@ static void start_process(void)
{
int debugged, console_app;
LPTHREAD_START_ROUTINE entry;
HMODULE module = current_process.exe_modref->module;
/* Increment EXE refcount */
current_process.exe_modref->refCount++;
WINE_MODREF *wm;
/* build command line */
if (!(current_envdb.cmd_line = build_command_line( main_exe_argv ))) goto error;
/* Retrieve entry point address */
entry = (LPTHREAD_START_ROUTINE)((char*)module + PE_HEADER(module)->OptionalHeader.AddressOfEntryPoint);
console_app = (PE_HEADER(module)->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI);
/* create 32-bit module for main exe */
if (!(main_module = BUILTIN32_LoadExeModule( main_module ))) goto error;
/* use original argv[0] as name for the main module */
if (!main_exe_name[0])
{
if (!GetLongPathNameA( full_argv0, main_exe_name, sizeof(main_exe_name) ))
lstrcpynA( main_exe_name, full_argv0, sizeof(main_exe_name) );
}
/* Retrieve entry point address */
entry = (LPTHREAD_START_ROUTINE)((char*)main_module +
PE_HEADER(main_module)->OptionalHeader.AddressOfEntryPoint);
console_app = (PE_HEADER(main_module)->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI);
if (console_app) current_process.flags |= PDB32_CONSOLE_PROC;
/* Signal the parent process to continue */
SERVER_START_REQ
{
struct init_process_done_request *req = server_alloc_req( sizeof(*req), 0 );
req->module = (void *)module;
req->module = (void *)main_module;
req->entry = entry;
req->name = &current_process.exe_modref->filename;
req->name = main_exe_name;
req->gui = !console_app;
server_call( REQ_INIT_PROCESS_DONE );
debugged = req->debugged;
@ -349,6 +356,11 @@ static void start_process(void)
* is sent by REQ_INIT_PROCESS_DONE */
if (!SIGNAL_Init()) goto error;
/* create the main modref and load dependencies */
if (!(wm = PE_CreateModule( main_module, main_exe_name, 0, main_exe_file, FALSE )))
goto error;
wm->refCount++;
/* Load the system dlls */
if (!load_system_dlls()) goto error;
@ -372,43 +384,6 @@ static void start_process(void)
}
/***********************************************************************
* PROCESS_Start
*
* Startup routine of a new Win32 process once the main module has been loaded.
*/
static void PROCESS_Start( HMODULE main_module, HFILE hFile, LPCSTR filename ) WINE_NORETURN;
static void PROCESS_Start( HMODULE main_module, HFILE hFile, LPCSTR filename )
{
if (!filename)
{
/* if no explicit filename, use argv[0] */
filename = main_exe_name;
if (!GetLongPathNameA( full_argv0, main_exe_name, sizeof(main_exe_name) ))
lstrcpynA( main_exe_name, full_argv0, sizeof(main_exe_name) );
}
/* load main module */
if (PE_HEADER(main_module)->FileHeader.Characteristics & IMAGE_FILE_DLL)
ExitProcess( ERROR_BAD_EXE_FORMAT );
/* Create 32-bit MODREF */
if (!PE_CreateModule( main_module, filename, 0, hFile, FALSE ))
goto error;
/* allocate main thread stack */
if (!THREAD_InitStack( NtCurrentTeb(),
PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
goto error;
/* switch to the new stack */
SYSDEPS_SwitchToThreadStack( start_process );
error:
ExitProcess( GetLastError() );
}
/***********************************************************************
* PROCESS_InitWine
*
@ -416,7 +391,7 @@ static void PROCESS_Start( HMODULE main_module, HFILE hFile, LPCSTR filename )
*/
void PROCESS_InitWine( int argc, char *argv[] )
{
DWORD type;
DWORD stack_size = 0;
/* Initialize everything */
if (!process_init( argv )) exit(1);
@ -446,52 +421,29 @@ void PROCESS_InitWine( int argc, char *argv[] )
}
}
if (!MODULE_GetBinaryType( main_exe_file, main_exe_name, &type ))
/* first try Win32 format; this will fail if the file is not a PE binary */
if ((main_module = PE_LoadImage( main_exe_file, main_exe_name, 0 )))
{
MESSAGE( "%s: unrecognized executable '%s'\n", argv0, main_exe_name );
goto error;
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();
}
switch (type)
{
case SCS_32BIT_BINARY:
{
HMODULE main_module = PE_LoadImage( main_exe_file, main_exe_name, 0 );
if (main_module) PROCESS_Start( main_module, main_exe_file, main_exe_name );
}
break;
/* allocate main thread stack */
if (!THREAD_InitStack( NtCurrentTeb(), stack_size, TRUE )) goto error;
case SCS_WOW_BINARY:
{
HMODULE main_module;
/* create 32-bit module for main exe */
if (!(main_module = BUILTIN32_LoadExeModule())) goto error;
NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
current_process.flags |= PDB32_WIN16_PROC;
SYSLEVEL_EnterWin16Lock();
PROCESS_Start( main_module, -1, NULL );
}
break;
/* switch to the new stack */
SYSDEPS_SwitchToThreadStack( start_process );
case SCS_DOS_BINARY:
{
HMODULE main_module;
/* create 32-bit module for main exe */
if (!(main_module = BUILTIN32_LoadExeModule())) goto error;
NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
if (!MZ_LoadImage( main_module, main_exe_file, main_exe_name )) goto error;
PROCESS_Start( main_module, main_exe_file, NULL );
}
break;
case SCS_PIF_BINARY:
case SCS_POSIX_BINARY:
case SCS_OS216_BINARY:
default:
MESSAGE( "%s: unrecognized executable '%s'\n", argv0, main_exe_name );
SetLastError( ERROR_BAD_FORMAT );
break;
}
error:
ExitProcess( GetLastError() );
}
@ -504,15 +456,14 @@ void PROCESS_InitWine( int argc, char *argv[] )
*/
void PROCESS_InitWinelib( int argc, char *argv[] )
{
HMODULE main_module;
if (!process_init( argv )) exit(1);
/* create 32-bit module for main exe */
if (!(main_module = BUILTIN32_LoadExeModule())) ExitProcess( GetLastError() );
main_exe_argv = argv;
PROCESS_Start( main_module, -1, NULL );
/* allocate main thread stack */
if (!THREAD_InitStack( NtCurrentTeb(), 0, TRUE )) ExitProcess( GetLastError() );
/* switch to the new stack */
SYSDEPS_SwitchToThreadStack( start_process );
}

View File

@ -605,26 +605,35 @@ void BuildSpec32File( FILE *outfile )
/* Output the DLL constructor */
fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "static void %s_init(void) __attribute__((constructor));\n", DLLName );
fprintf( outfile, "static void %s_fini(void) __attribute__((destructor));\n", DLLName );
fprintf( outfile, "static void init(void) __attribute__((constructor));\n" );
if (nr_debug)
fprintf( outfile, "static void fini(void) __attribute__((destructor));\n" );
fprintf( outfile, "#else /* defined(__GNUC__) */\n" );
fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tcall %s_init\\n\"\n", DLLName );
fprintf( outfile, " \"\\t.previous\\n\");\n" );
fprintf( outfile, "asm(\"\\t.section\t.fini ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tcall %s_fini\\n\"\n", DLLName );
fprintf( outfile, " \"\\tcall init\\n\"\n" );
fprintf( outfile, " \"\\t.previous\\n\");\n" );
if (nr_debug)
{
fprintf( outfile, "asm(\"\\t.section\t.fini ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tcall fini\\n\"\n" );
fprintf( outfile, " \"\\t.previous\\n\");\n" );
}
fprintf( outfile, "}\n" );
fprintf( outfile, "#endif /* defined(__GNUC__) */\n\n" );
fprintf( outfile, "static void %s_init(void)\n{\n", DLLName );
fprintf( outfile, " extern void BUILTIN32_RegisterDLL( const struct image_nt_headers *, const char * );\n" );
fprintf( outfile, " extern void *wine_dbg_register( char * const *, int );\n");
fprintf( outfile, " BUILTIN32_RegisterDLL( &nt_header, \"%s\" );\n", DLLFileName );
if (nr_debug) fprintf( outfile, " debug_registration = wine_dbg_register( debug_channels, %d );\n", nr_debug );
fprintf( outfile, "}\n\n" );
fprintf( outfile, "static void %s_fini(void)\n{\n", DLLName );
fprintf( outfile, " extern void wine_dbg_unregister( void * );\n");
if (nr_debug) fprintf( outfile, " wine_dbg_unregister( debug_registration );\n" );
fprintf( outfile, "static void init(void)\n{\n" );
fprintf( outfile, " extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n" );
fprintf( outfile, " extern void *__wine_dbg_register( char * const *, int );\n");
fprintf( outfile, " __wine_dll_register( &nt_header, \"%s\" );\n", DLLFileName );
if (nr_debug)
fprintf( outfile, " debug_registration = __wine_dbg_register( debug_channels, %d );\n",
nr_debug );
fprintf( outfile, "}\n" );
if (nr_debug)
{
fprintf( outfile, "\nstatic void fini(void)\n{\n" );
fprintf( outfile, " extern void __wine_dbg_unregister( void * );\n");
fprintf( outfile, " __wine_dbg_unregister( debug_registration );\n" );
fprintf( outfile, "}\n" );
}
}