diff --git a/include/Makefile.in b/include/Makefile.in index 35161949fc0..c20d6f76186 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -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 \ diff --git a/include/dosexe.h b/include/dosexe.h index d35d0085d56..0ecbc8bcf9c 100644 --- a/include/dosexe.h +++ b/include/dosexe.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 ); diff --git a/include/module.h b/include/module.h index c99c6c6a304..ef9bec2f70f 100644 --- a/include/module.h +++ b/include/module.h @@ -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 ); diff --git a/library/Makefile.in b/library/Makefile.in index 224f1fd2200..ab3271598d4 100644 --- a/library/Makefile.in +++ b/library/Makefile.in @@ -10,6 +10,7 @@ SONAME = libwine.so C_SRCS = \ debug.c \ + loader.c \ port.c all: libwine.$(LIBEXT) diff --git a/library/debug.c b/library/debug.c index 3f38487b4a5..84a832a556f 100644 --- a/library/debug.c +++ b/library/debug.c @@ -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) diff --git a/library/loader.c b/library/loader.c new file mode 100644 index 00000000000..95922d042e6 --- /dev/null +++ b/library/loader.c @@ -0,0 +1,203 @@ +/* + * Win32 builtin dlls support + * + * Copyright 2000 Alexandre Julliard + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#ifdef HAVE_DL_API +#include +#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 +} diff --git a/loader/dos/module.c b/loader/dos/module.c index 3e55afae5d0..015346ba60a 100644 --- a/loader/dos/module.c +++ b/loader/dos/module.c @@ -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); diff --git a/loader/module.c b/loader/module.c index 1585f022ba6..e1978cf0697 100644 --- a/loader/module.c +++ b/loader/module.c @@ -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; diff --git a/loader/pe_image.c b/loader/pe_image.c index 1acb81463c5..dfff47c2707 100644 --- a/loader/pe_image.c +++ b/loader/pe_image.c @@ -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; diff --git a/miscemu/main.c b/miscemu/main.c index 764c5d21348..b8bd8cdb601 100644 --- a/miscemu/main.c +++ b/miscemu/main.c @@ -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) { diff --git a/relay32/builtin32.c b/relay32/builtin32.c index e741bc98139..c17a402bb86 100644 --- a/relay32/builtin32.c +++ b/relay32/builtin32.c @@ -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 ); } diff --git a/scheduler/process.c b/scheduler/process.c index acf14d8ec8a..44a56cd1a41 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -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 ); } diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index c1ded913340..b0a78c2e10b 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -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" ); + } }