Commit e087508f authored by Alexandre Julliard's avatar Alexandre Julliard

Moved builtin dll registration to libwine.

Changed process initialization to not load imported dlls too early.
parent b1eb3014
...@@ -85,6 +85,7 @@ INSTALLED_INCLUDES = \ ...@@ -85,6 +85,7 @@ INSTALLED_INCLUDES = \
wine/exception.h \ wine/exception.h \
wine/icmpapi.h \ wine/icmpapi.h \
wine/ipexport.h \ wine/ipexport.h \
wine/library.h \
wine/obj_base.h \ wine/obj_base.h \
wine/obj_cache.h \ wine/obj_cache.h \
wine/obj_channel.h \ wine/obj_channel.h \
......
...@@ -30,7 +30,7 @@ typedef struct _DOSTASK { ...@@ -30,7 +30,7 @@ typedef struct _DOSTASK {
#define V86_FLAG 0x00020000 #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 BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
extern void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval ); extern void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval );
extern LPDOSTASK MZ_Current( void ); extern LPDOSTASK MZ_Current( void );
......
...@@ -180,7 +180,6 @@ extern void MODULE_DllThreadDetach( LPVOID lpReserved ); ...@@ -180,7 +180,6 @@ extern void MODULE_DllThreadDetach( LPVOID lpReserved );
extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags ); extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags );
extern BOOL MODULE_FreeLibrary( WINE_MODREF *wm ); extern BOOL MODULE_FreeLibrary( WINE_MODREF *wm );
extern WINE_MODREF *MODULE_FindModule( LPCSTR path ); 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 HMODULE MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name ); extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name );
extern SEGPTR WINAPI HasGPHandler16( SEGPTR address ); extern SEGPTR WINAPI HasGPHandler16( SEGPTR address );
...@@ -238,7 +237,7 @@ extern WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags); ...@@ -238,7 +237,7 @@ extern WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags);
/* relay32/builtin.c */ /* relay32/builtin.c */
extern WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags); 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 void *BUILTIN32_dlopen( const char *name );
extern int BUILTIN32_dlclose( void *handle ); extern int BUILTIN32_dlclose( void *handle );
......
...@@ -10,6 +10,7 @@ SONAME = libwine.so ...@@ -10,6 +10,7 @@ SONAME = libwine.so
C_SRCS = \ C_SRCS = \
debug.c \ debug.c \
loader.c \
port.c port.c
all: libwine.$(LIBEXT) all: libwine.$(LIBEXT)
......
...@@ -56,7 +56,7 @@ static void apply_option( struct dll *dll, const struct option *opt ) ...@@ -56,7 +56,7 @@ static void apply_option( struct dll *dll, const struct option *opt )
} }
/* register a new set of channels for a dll */ /* 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 option *opt = first_option;
struct dll *dll = malloc( sizeof(*dll) ); struct dll *dll = malloc( sizeof(*dll) );
...@@ -80,7 +80,7 @@ void *wine_dbg_register( char * const *channels, int nb ) ...@@ -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 */ /* 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; struct dll *dll = channel;
if (dll) if (dll)
......
/*
* 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
}
...@@ -203,7 +203,7 @@ static BOOL MZ_InitMemory(void) ...@@ -203,7 +203,7 @@ static BOOL MZ_InitMemory(void)
return TRUE; 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; LPDOSTASK lpDosTask = dos_current;
IMAGE_DOS_HEADER mz_header; IMAGE_DOS_HEADER mz_header;
...@@ -233,6 +233,12 @@ BOOL MZ_DoLoadImage( HMODULE module, HANDLE hFile, LPCSTR filename, OverlayBlock ...@@ -233,6 +233,12 @@ BOOL MZ_DoLoadImage( HMODULE module, HANDLE hFile, LPCSTR filename, OverlayBlock
if ( !ReadFile(hFile,&mz_header,sizeof(mz_header),&len,NULL) if ( !ReadFile(hFile,&mz_header,sizeof(mz_header),&len,NULL)
|| len != sizeof(mz_header) || len != sizeof(mz_header)
|| mz_header.e_magic != IMAGE_DOS_SIGNATURE) { || 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 */ old_com=1; /* assume .COM file */
image_start=0; image_start=0;
image_size=GetFileSize(hFile,NULL); image_size=GetFileSize(hFile,NULL);
...@@ -331,16 +337,33 @@ load_error: ...@@ -331,16 +337,33 @@ load_error:
return FALSE; 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) { if (p)
win_hdr->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; {
win_hdr->OptionalHeader.AddressOfEntryPoint = (LPBYTE)MZ_Launch - (LPBYTE)module; 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 ) 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 ) ...@@ -363,7 +386,7 @@ BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
PDB16 *psp = (PDB16 *)psp_start; PDB16 *psp = (PDB16 *)psp_start;
psp->saveStack = (DWORD)PTR_SEG_OFF_TO_SEGPTR(context->SegSs, LOWORD(context->Esp)); 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) { if (ret) {
/* MZ_LoadImage created a new PSP and loaded new values into lpDosTask, /* MZ_LoadImage created a new PSP and loaded new values into lpDosTask,
* let's work on the new values now */ * let's work on the new values now */
...@@ -393,7 +416,7 @@ BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk ) ...@@ -393,7 +416,7 @@ BOOL MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
case 3: /* load overlay */ case 3: /* load overlay */
{ {
OverlayBlock *blk = (OverlayBlock *)paramblk; OverlayBlock *blk = (OverlayBlock *)paramblk;
ret = MZ_DoLoadImage( NULL, hFile, filename, blk ); ret = MZ_DoLoadImage( hFile, filename, blk );
} }
break; break;
default: default:
...@@ -589,7 +612,7 @@ void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval ) ...@@ -589,7 +612,7 @@ void MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
#else /* !MZ_SUPPORTED */ #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"); WARN("DOS executables not supported on this platform\n");
SetLastError(ERROR_BAD_FORMAT); SetLastError(ERROR_BAD_FORMAT);
......
...@@ -532,7 +532,7 @@ good: ...@@ -532,7 +532,7 @@ good:
* Note that .COM and .PIF files are only recognized by their * Note that .COM and .PIF files are only recognized by their
* file name extension; but Windows does it the same way ... * 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; IMAGE_DOS_HEADER mz_header;
char magic[4], *ptr; char magic[4], *ptr;
......
...@@ -475,6 +475,7 @@ HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, DWORD flags ) ...@@ -475,6 +475,7 @@ HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, DWORD flags )
TRACE_(module)( "loading %s\n", filename ); TRACE_(module)( "loading %s\n", filename );
mapping = CreateFileMappingA( hFile, NULL, SEC_IMAGE, 0, 0, NULL ); mapping = CreateFileMappingA( hFile, NULL, SEC_IMAGE, 0, 0, NULL );
if (!mapping) return 0;
base = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); base = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
CloseHandle( mapping ); CloseHandle( mapping );
if (!base) return 0; if (!base) return 0;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "callback.h" #include "callback.h"
#include "options.h" #include "options.h"
#include "dosexe.h"
#include "process.h" #include "process.h"
#include "debugtools.h" #include "debugtools.h"
...@@ -27,6 +28,13 @@ void wine_initial_task(void) ...@@ -27,6 +28,13 @@ void wine_initial_task(void)
if ((instance = WinExec16( GetCommandLineA(), info.wShowWindow )) < 32) 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() ); MESSAGE( "%s: can't exec '%s': ", argv0, GetCommandLineA() );
switch (instance) switch (instance)
{ {
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "windef.h" #include "windef.h"
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "wine/library.h"
#include "elfdll.h" #include "elfdll.h"
#include "global.h" #include "global.h"
#include "neexe.h" #include "neexe.h"
...@@ -32,19 +33,9 @@ ...@@ -32,19 +33,9 @@
DEFAULT_DEBUG_CHANNEL(module); DEFAULT_DEBUG_CHANNEL(module);
DECLARE_DEBUG_CHANNEL(relay); 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 ); extern void RELAY_SetupDLL( const char *module );
static BUILTIN32_DESCRIPTOR builtin_dlls[MAX_DLLS]; static HMODULE main_module;
static int nb_dlls;
/*********************************************************************** /***********************************************************************
* BUILTIN32_dlopen * BUILTIN32_dlopen
...@@ -53,16 +44,10 @@ void *BUILTIN32_dlopen( const char *name ) ...@@ -53,16 +44,10 @@ void *BUILTIN32_dlopen( const char *name )
{ {
#ifdef HAVE_DL_API #ifdef HAVE_DL_API
void *handle; 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; LPSTR pErr, p;
pErr = dlerror(); pErr = dlerror();
p = strchr(pErr, ':'); p = strchr(pErr, ':');
...@@ -130,11 +115,11 @@ static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, char *root, void *ba ...@@ -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_DATA_DIRECTORY *dir;
IMAGE_DOS_HEADER *dos; IMAGE_DOS_HEADER *dos;
...@@ -154,13 +139,12 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr ) ...@@ -154,13 +139,12 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
assert( size <= page_size ); assert( size <= page_size );
if (descr->nt->OptionalHeader.ImageBase) if (nt_descr->OptionalHeader.ImageBase)
{ {
void *base = (void *)descr->nt->OptionalHeader.ImageBase; void *base = (void *)nt_descr->OptionalHeader.ImageBase;
if ((addr = VIRTUAL_mmap( -1, base, page_size, 0, if ((addr = wine_anon_mmap( base, page_size, PROT_READ|PROT_WRITE, MAP_FIXED )) != base)
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; return 0;
} }
} }
...@@ -182,7 +166,7 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr ) ...@@ -182,7 +166,7 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
dos->e_magic = IMAGE_DOS_SIGNATURE; dos->e_magic = IMAGE_DOS_SIGNATURE;
dos->e_lfanew = sizeof(*dos); dos->e_lfanew = sizeof(*dos);
*nt = *descr->nt; *nt = *nt_descr;
nt->FileHeader.NumberOfSections = nb_sections; nt->FileHeader.NumberOfSections = nb_sections;
nt->OptionalHeader.SizeOfCode = data_start - code_start; nt->OptionalHeader.SizeOfCode = data_start - code_start;
...@@ -255,6 +239,42 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr ) ...@@ -255,6 +239,42 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
return (HMODULE)addr; 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 * BUILTIN32_LoadLibraryExA
* *
...@@ -263,12 +283,10 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr ) ...@@ -263,12 +283,10 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
*/ */
WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags) WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
{ {
HMODULE module;
WINE_MODREF *wm; WINE_MODREF *wm;
char dllname[20], *p; char dllname[20], *p;
LPCSTR name; LPCSTR name;
void *handle; void *handle;
int i;
/* Fix the name in case we have a full path and extension */ /* Fix the name in case we have a full path and extension */
name = path; name = path;
...@@ -281,66 +299,36 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags) ...@@ -281,66 +299,36 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
p = strrchr( dllname, '.' ); p = strrchr( dllname, '.' );
if (!p) strcat( dllname, ".dll" ); if (!p) strcat( dllname, ".dll" );
/* Search built-in descriptor */ if (!(handle = BUILTIN32_dlopen( dllname ))) goto error;
for (i = 0; i < nb_dlls; i++)
if (!strcasecmp( builtin_dlls[i].filename, dllname )) goto found;
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 ); 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: error:
SetLastError( ERROR_FILE_NOT_FOUND ); SetLastError( ERROR_FILE_NOT_FOUND );
return NULL; 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; main_module = main;
wine_dll_set_callback( load_library );
/* Search built-in EXE descriptor */ if (!main_module)
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 )
{
MESSAGE( "No built-in EXE module loaded! Did you create a .spec file?\n" ); MESSAGE( "No built-in EXE module loaded! Did you create a .spec file?\n" );
return 0; return main_module;
}
/* Load built-in module */
return BUILTIN32_DoLoadImage( &builtin_dlls[exe] );
} }
...@@ -351,8 +339,6 @@ HMODULE BUILTIN32_LoadExeModule(void) ...@@ -351,8 +339,6 @@ HMODULE BUILTIN32_LoadExeModule(void)
*/ */
void BUILTIN32_RegisterDLL( const IMAGE_NT_HEADERS *header, const char *filename ) void BUILTIN32_RegisterDLL( const IMAGE_NT_HEADERS *header, const char *filename )
{ {
assert( nb_dlls < MAX_DLLS ); extern void __wine_dll_register( const IMAGE_NT_HEADERS *header, const char *filename );
builtin_dlls[nb_dlls].nt = header; __wine_dll_register( header, filename );
builtin_dlls[nb_dlls].filename = filename;
nb_dlls++;
} }
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "main.h" #include "main.h"
#include "module.h" #include "module.h"
#include "neexe.h" #include "neexe.h"
#include "dosexe.h"
#include "file.h" #include "file.h"
#include "global.h" #include "global.h"
#include "heap.h" #include "heap.h"
...@@ -42,6 +41,7 @@ PDB current_process; ...@@ -42,6 +41,7 @@ PDB current_process;
static char **main_exe_argv; static char **main_exe_argv;
static char main_exe_name[MAX_PATH]; static char main_exe_name[MAX_PATH];
static HANDLE main_exe_file = INVALID_HANDLE_VALUE; static HANDLE main_exe_file = INVALID_HANDLE_VALUE;
static HMODULE main_module;
unsigned int server_startticks; unsigned int server_startticks;
...@@ -317,27 +317,34 @@ static void start_process(void) ...@@ -317,27 +317,34 @@ static void start_process(void)
{ {
int debugged, console_app; int debugged, console_app;
LPTHREAD_START_ROUTINE entry; LPTHREAD_START_ROUTINE entry;
HMODULE module = current_process.exe_modref->module; WINE_MODREF *wm;
/* Increment EXE refcount */
current_process.exe_modref->refCount++;
/* build command line */ /* build command line */
if (!(current_envdb.cmd_line = build_command_line( main_exe_argv ))) goto error; if (!(current_envdb.cmd_line = build_command_line( main_exe_argv ))) goto error;
/* Retrieve entry point address */ /* create 32-bit module for main exe */
entry = (LPTHREAD_START_ROUTINE)((char*)module + PE_HEADER(module)->OptionalHeader.AddressOfEntryPoint); if (!(main_module = BUILTIN32_LoadExeModule( main_module ))) goto error;
console_app = (PE_HEADER(module)->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI);
/* 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; if (console_app) current_process.flags |= PDB32_CONSOLE_PROC;
/* Signal the parent process to continue */ /* Signal the parent process to continue */
SERVER_START_REQ SERVER_START_REQ
{ {
struct init_process_done_request *req = server_alloc_req( sizeof(*req), 0 ); 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->entry = entry;
req->name = &current_process.exe_modref->filename; req->name = main_exe_name;
req->gui = !console_app; req->gui = !console_app;
server_call( REQ_INIT_PROCESS_DONE ); server_call( REQ_INIT_PROCESS_DONE );
debugged = req->debugged; debugged = req->debugged;
...@@ -349,6 +356,11 @@ static void start_process(void) ...@@ -349,6 +356,11 @@ static void start_process(void)
* is sent by REQ_INIT_PROCESS_DONE */ * is sent by REQ_INIT_PROCESS_DONE */
if (!SIGNAL_Init()) goto error; 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 */ /* Load the system dlls */
if (!load_system_dlls()) goto error; if (!load_system_dlls()) goto error;
...@@ -373,50 +385,13 @@ static void start_process(void) ...@@ -373,50 +385,13 @@ 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 * PROCESS_InitWine
* *
* Wine initialisation: load and start the main exe file. * Wine initialisation: load and start the main exe file.
*/ */
void PROCESS_InitWine( int argc, char *argv[] ) void PROCESS_InitWine( int argc, char *argv[] )
{ {
DWORD type; DWORD stack_size = 0;
/* Initialize everything */ /* Initialize everything */
if (!process_init( argv )) exit(1); if (!process_init( argv )) exit(1);
...@@ -446,52 +421,29 @@ void PROCESS_InitWine( int argc, char *argv[] ) ...@@ -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 ); if (PE_HEADER(main_module)->FileHeader.Characteristics & IMAGE_FILE_DLL)
goto error; ExitProcess( ERROR_BAD_EXE_FORMAT );
stack_size = PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve;
} }
else /* it must be 16-bit or DOS format */
switch (type)
{ {
case SCS_32BIT_BINARY: NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
{ current_process.flags |= PDB32_WIN16_PROC;
HMODULE main_module = PE_LoadImage( main_exe_file, main_exe_name, 0 ); main_exe_name[0] = 0;
if (main_module) PROCESS_Start( main_module, main_exe_file, main_exe_name ); CloseHandle( main_exe_file );
} main_exe_file = INVALID_HANDLE_VALUE;
break; SYSLEVEL_EnterWin16Lock();
}
case SCS_WOW_BINARY: /* allocate main thread stack */
{ if (!THREAD_InitStack( NtCurrentTeb(), stack_size, TRUE )) goto error;
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;
case SCS_DOS_BINARY: /* switch to the new stack */
{ SYSDEPS_SwitchToThreadStack( start_process );
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: error:
ExitProcess( GetLastError() ); ExitProcess( GetLastError() );
} }
...@@ -504,15 +456,14 @@ void PROCESS_InitWine( int argc, char *argv[] ) ...@@ -504,15 +456,14 @@ void PROCESS_InitWine( int argc, char *argv[] )
*/ */
void PROCESS_InitWinelib( int argc, char *argv[] ) void PROCESS_InitWinelib( int argc, char *argv[] )
{ {
HMODULE main_module;
if (!process_init( argv )) exit(1); if (!process_init( argv )) exit(1);
main_exe_argv = argv;
/* create 32-bit module for main exe */ /* allocate main thread stack */
if (!(main_module = BUILTIN32_LoadExeModule())) ExitProcess( GetLastError() ); if (!THREAD_InitStack( NtCurrentTeb(), 0, TRUE )) ExitProcess( GetLastError() );
main_exe_argv = argv; /* switch to the new stack */
PROCESS_Start( main_module, -1, NULL ); SYSDEPS_SwitchToThreadStack( start_process );
} }
......
...@@ -605,26 +605,35 @@ void BuildSpec32File( FILE *outfile ) ...@@ -605,26 +605,35 @@ void BuildSpec32File( FILE *outfile )
/* Output the DLL constructor */ /* Output the DLL constructor */
fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "static void %s_init(void) __attribute__((constructor));\n", DLLName ); fprintf( outfile, "static void init(void) __attribute__((constructor));\n" );
fprintf( outfile, "static void %s_fini(void) __attribute__((destructor));\n", DLLName ); if (nr_debug)
fprintf( outfile, "static void fini(void) __attribute__((destructor));\n" );
fprintf( outfile, "#else /* defined(__GNUC__) */\n" ); fprintf( outfile, "#else /* defined(__GNUC__) */\n" );
fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" ); fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" ); fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tcall %s_init\\n\"\n", DLLName ); fprintf( outfile, " \"\\tcall init\\n\"\n" );
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, " \"\\t.previous\\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, "}\n" );
fprintf( outfile, "#endif /* defined(__GNUC__) */\n\n" ); fprintf( outfile, "#endif /* defined(__GNUC__) */\n\n" );
fprintf( outfile, "static void %s_init(void)\n{\n", DLLName ); fprintf( outfile, "static void init(void)\n{\n" );
fprintf( outfile, " extern void BUILTIN32_RegisterDLL( const struct image_nt_headers *, const char * );\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, " extern void *__wine_dbg_register( char * const *, int );\n");
fprintf( outfile, " BUILTIN32_RegisterDLL( &nt_header, \"%s\" );\n", DLLFileName ); 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 ); if (nr_debug)
fprintf( outfile, "}\n\n" ); fprintf( outfile, " debug_registration = __wine_dbg_register( debug_channels, %d );\n",
fprintf( outfile, "static void %s_fini(void)\n{\n", DLLName ); nr_debug );
fprintf( outfile, " extern void wine_dbg_unregister( void * );\n");
if (nr_debug) fprintf( outfile, " wine_dbg_unregister( debug_registration );\n" );
fprintf( outfile, "}\n" ); 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" );
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment