Moved builtin dll registration to libwine.
Changed process initialization to not load imported dlls too early.
This commit is contained in:
parent
b1eb301477
commit
e087508f57
|
@ -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 \
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ SONAME = libwine.so
|
|||
|
||||
C_SRCS = \
|
||||
debug.c \
|
||||
loader.c \
|
||||
port.c
|
||||
|
||||
all: libwine.$(LIBEXT)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 = ¤t_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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue