From c1d1cfe976c060a816af48688d4b4092bffb5a16 Mon Sep 17 00:00:00 2001 From: Bertho Stultiens Date: Sun, 18 Apr 1999 12:14:06 +0000 Subject: [PATCH] Reorganization of the loader to correctly load and free libraries and implementation of load order to load different types of libraries. --- if1632/builtin.c | 82 ------ include/builtin32.h | 2 - include/module.h | 28 +- include/pe_image.h | 8 +- include/winerror.h | 1 + loader/Makefile.in | 2 + loader/elf.c | 32 ++- loader/main.c | 5 + loader/module.c | 658 ++++++++++++++++++++++++++------------------ loader/ne/module.c | 81 +++++- loader/pe_image.c | 162 +++++------ memory/global.c | 6 +- misc/main.c | 4 - miscemu/main.c | 12 - relay32/builtin32.c | 144 +++++----- scheduler/process.c | 12 +- scheduler/thread.c | 4 +- 17 files changed, 677 insertions(+), 566 deletions(-) diff --git a/if1632/builtin.c b/if1632/builtin.c index 8cc9fc8ade6..f66f15042db 100644 --- a/if1632/builtin.c +++ b/if1632/builtin.c @@ -325,85 +325,3 @@ void BUILTIN_DefaultIntHandler( CONTEXT *context ) INT_BARF( context, ordinal - FIRST_INTERRUPT_ORDINAL ); } - -/*********************************************************************** - * BUILTIN_ParseDLLOptions - * - * Set runtime DLL usage flags - */ -BOOL BUILTIN_ParseDLLOptions( char *str ) -{ - BUILTIN16_DLL *dll; - char *p,*last; - - - last = str; - while (*str) - { - while (*str && (*str==',' || isspace(*str))) str++; - if (!*str) { - *last = '\0'; /* cut off garbage at end at */ - return TRUE; - } - if ((*str != '+') && (*str != '-')) return FALSE; - str++; - if (!(p = strchr( str, ',' ))) p = str + strlen(str); - while ((p > str) && isspace(p[-1])) p--; - if (p == str) return FALSE; - for (dll = BuiltinDLLs; dll->descr; dll++) - { - if (!lstrncmpiA( str, dll->descr->name, (int)(p - str) )) - { - if (dll->descr->name[(int)(p-str)]) /* only partial match */ - continue; - if (str[-1] == '-') - { - if (dll->flags & DLL_FLAG_ALWAYS_USED) return FALSE; - dll->flags |= DLL_FLAG_NOT_USED; - } - else dll->flags &= ~DLL_FLAG_NOT_USED; - break; - } - } - if (!dll->descr) { - /* not found, but could get handled by BUILTIN32_, so move last */ - last = p; - str = p; - } else { - /* handled. cut out the "[+-]DLL," string, so it isn't handled - * by BUILTIN32 - */ - if (*p) { - memcpy(last,p,strlen(p)+1); - str = last; - } else { - *last = '\0'; - break; - } - } - } - return TRUE; -} - - -/*********************************************************************** - * BUILTIN_PrintDLLs - * - * Print the list of built-in DLLs that can be disabled. - */ -void BUILTIN_PrintDLLs(void) -{ - int i; - BUILTIN16_DLL *dll; - - MSG("Example: -dll -ole2 Do not use emulated OLE2.DLL\n"); - MSG("Available Win16 DLLs:\n"); - for (i = 0, dll = BuiltinDLLs; dll->descr; dll++) - { - if (!(dll->flags & DLL_FLAG_ALWAYS_USED)) - MSG("%-9s%c", dll->descr->name, - ((++i) % 8) ? ' ' : '\n' ); - } - MSG("\n"); - BUILTIN32_PrintDLLs(); -} diff --git a/include/builtin32.h b/include/builtin32.h index 7423cdbadf3..3b263d68e4b 100644 --- a/include/builtin32.h +++ b/include/builtin32.h @@ -27,8 +27,6 @@ extern ENTRYPOINT32 BUILTIN32_GetEntryPoint( char *buffer, void *relay, unsigned int *typemask ); extern void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr, int ordinal ); -extern void BUILTIN32_PrintDLLs(void); extern void BUILTIN32_SwitchRelayDebug(int onoff); -extern int BUILTIN32_EnableDLL( const char *name, int len, int enable ); #endif /* __WINE_BUILTIN32_H */ diff --git a/include/module.h b/include/module.h index ff320b870a3..fa35ecad38d 100644 --- a/include/module.h +++ b/include/module.h @@ -121,7 +121,13 @@ typedef struct #pragma pack(4) /* internal representation of 32bit modules. per process. */ -typedef enum { MODULE32_PE=1, MODULE32_ELF /* ,... */ } MODULE32_TYPE; +typedef enum { + MODULE32_PE = 1, + MODULE32_ELF, + MODULE32_ELFDLL, + MODULE32_BI +} MODULE32_TYPE; + typedef struct _wine_modref { struct _wine_modref *next; @@ -132,7 +138,7 @@ typedef struct _wine_modref ELF_MODREF elf; } binfmt; - HMODULE module; + HMODULE module; int nDeps; struct _wine_modref **deps; @@ -148,7 +154,6 @@ typedef struct _wine_modref #define WINE_MODREF_INTERNAL 0x00000001 #define WINE_MODREF_NO_DLL_CALLS 0x00000002 #define WINE_MODREF_PROCESS_ATTACHED 0x00000004 -#define WINE_MODREF_PROCESS_DETACHED 0x00000008 #define WINE_MODREF_LOAD_AS_DATAFILE 0x00000010 #define WINE_MODREF_DONT_RESOLVE_REFS 0x00000020 #define WINE_MODREF_MARKER 0x80000000 @@ -171,13 +176,17 @@ typedef struct resource_nameinfo_s NE_NAMEINFO; /* module.c */ extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, BOOL snoop ); extern WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hModule ); -extern void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved ); -extern HMODULE MODULE_FindModule( LPCSTR path ); +extern BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved ); +extern void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved ); +extern void MODULE_DllThreadAttach( LPVOID lpReserved ); +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 HMODULE MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName ); extern FARPROC16 MODULE_GetWndProcEntry16( const char *name ); extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name ); extern SEGPTR WINAPI HasGPHandler16( SEGPTR address ); -HMODULE MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags ); /* resource.c */ extern INT WINAPI AccessResource(HMODULE,HRSRC); @@ -192,7 +201,7 @@ extern FARPROC16 NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal ); extern FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop ); extern BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset ); extern HANDLE NE_OpenFile( NE_MODULE *pModule ); -extern HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit ); +extern HINSTANCE16 MODULE_LoadModule16( LPCSTR name, BOOL implicit ); extern BOOL NE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line, LPCSTR env, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, BOOL inherit, LPSTARTUPINFOA startup, @@ -225,12 +234,11 @@ HGLOBAL16 NE_LoadPEResource( NE_MODULE *pModule, WORD type, LPVOID bits, DWORD s extern BOOL BUILTIN_Init(void); extern HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL force ); extern LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd ); -extern BOOL BUILTIN_ParseDLLOptions( char *str ); -extern void BUILTIN_PrintDLLs(void); /* relay32/builtin.c */ extern HMODULE BUILTIN32_LoadImage( LPCSTR name, OFSTRUCT *ofs, BOOL force ); -extern BOOL BUILTIN32_ParseDLLOptions( char *str ); +extern WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags, DWORD *err); +extern void BUILTIN32_UnloadLibrary(WINE_MODREF *wm); /* if1632/builtin.c */ extern HMODULE16 (*fnBUILTIN_LoadModule)(LPCSTR name, BOOL force); diff --git a/include/pe_image.h b/include/pe_image.h index 9ce289fe003..94396582d85 100644 --- a/include/pe_image.h +++ b/include/pe_image.h @@ -25,7 +25,8 @@ extern BOOL PE_EnumResourceLanguagesA(HMODULE,LPCSTR,LPCSTR,ENUMRESLANGPROCA,LON extern BOOL PE_EnumResourceLanguagesW(HMODULE,LPCWSTR,LPCWSTR,ENUMRESLANGPROCW,LONG); extern HRSRC PE_FindResourceExW(struct _wine_modref*,LPCWSTR,LPCWSTR,WORD); extern DWORD PE_SizeofResource(HMODULE,HRSRC); -extern HMODULE PE_LoadLibraryExA(LPCSTR,HFILE,DWORD); +extern struct _wine_modref *PE_LoadLibraryExA(LPCSTR, DWORD, DWORD *); +extern void PE_UnloadLibrary(struct _wine_modref *); extern HGLOBAL PE_LoadResource(struct _wine_modref *wm,HRSRC); extern HMODULE PE_LoadImage( HFILE hFile, OFSTRUCT *ofs, LPCSTR *modName ); extern struct _wine_modref *PE_CreateModule( HMODULE hModule, OFSTRUCT *ofs, @@ -36,7 +37,7 @@ extern BOOL PE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line, LPCST LPPROCESS_INFORMATION info ); extern void PE_InitTls(void); -extern void PE_InitDLL(struct _wine_modref *wm, DWORD type, LPVOID lpReserved); +extern BOOL PE_InitDLL(struct _wine_modref *wm, DWORD type, LPVOID lpReserved); extern PIMAGE_RESOURCE_DIRECTORY GetResDirEntryA(PIMAGE_RESOURCE_DIRECTORY,LPCSTR,DWORD,BOOL); extern PIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(PIMAGE_RESOURCE_DIRECTORY,LPCWSTR,DWORD,BOOL); @@ -64,7 +65,8 @@ typedef struct { } ELF_MODREF; extern struct _wine_modref *ELF_CreateDummyModule(LPCSTR,LPCSTR); -extern HMODULE ELF_LoadLibraryExA(LPCSTR,HFILE,DWORD); +extern struct _wine_modref *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags, DWORD *err); +extern void ELF_UnloadLibrary(struct _wine_modref *); extern FARPROC ELF_FindExportedFunction(struct _wine_modref *wm, LPCSTR funcName); #endif /* __WINE_PE_IMAGE_H */ diff --git a/include/winerror.h b/include/winerror.h index 0c73c7de487..0b047a4159a 100644 --- a/include/winerror.h +++ b/include/winerror.h @@ -245,6 +245,7 @@ extern int WIN32_LastError; #define ERROR_BADKEY 1010 /* Config reg key invalid */ #define ERROR_CANTREAD 1012 /* Config reg key couldn't be read */ #define ERROR_CANTWRITE 1013 /* Config reg key couldn't be written */ +#define ERROR_DLL_INIT_FAILED 1114 #define ERROR_IO_DEVICE 1117 #define ERROR_POSSIBLE_DEADLOCK 1131 #define ERROR_BAD_DEVICE 1200 diff --git a/loader/Makefile.in b/loader/Makefile.in index e405eeb979a..580d1e6d38e 100644 --- a/loader/Makefile.in +++ b/loader/Makefile.in @@ -7,7 +7,9 @@ MODULE = loader C_SRCS = \ elf.c \ + elfdll.c \ libres.c \ + loadorder.c \ main.c \ module.c \ pe_image.c \ diff --git a/loader/elf.c b/loader/elf.c index c2b1fb4ca86..be7369eaa88 100644 --- a/loader/elf.c +++ b/loader/elf.c @@ -21,9 +21,10 @@ #include "neexe.h" #include "peexe.h" #include "heap.h" -#include "pe_image.h" #include "module.h" +#include "pe_image.h" #include "debug.h" +#include "winerror.h" WINE_MODREF *ELF_CreateDummyModule( LPCSTR libname, LPCSTR modname ) { @@ -96,7 +97,7 @@ WINE_MODREF *ELF_CreateDummyModule( LPCSTR libname, LPCSTR modname ) #include -HMODULE ELF_LoadLibraryExA( LPCSTR libname, HANDLE hf, DWORD flags ) +WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags, DWORD *err) { WINE_MODREF *wm; char *modname,*s,*t,*x; @@ -138,14 +139,16 @@ HMODULE ELF_LoadLibraryExA( LPCSTR libname, HANDLE hf, DWORD flags ) dlhandle = dlopen(t,RTLD_NOW); if (!dlhandle) { HeapFree( GetProcessHeap(), 0, t ); - return 0; + *err = ERROR_FILE_NOT_FOUND; + return NULL; } wm = ELF_CreateDummyModule( t, modname ); wm->binfmt.elf.dlhandle = dlhandle; SNOOP_RegisterDLL(wm->module,libname,STUBSIZE/sizeof(ELF_STDCALL_STUB)); - return wm->module; + *err = 0; + return wm; } FARPROC ELF_FindExportedFunction( WINE_MODREF *wm, LPCSTR funcName) @@ -247,12 +250,29 @@ FARPROC ELF_FindExportedFunction( WINE_MODREF *wm, LPCSTR funcName) fun = SNOOP_GetProcAddress(wm->module,funcName,stub-wm->binfmt.elf.stubs,fun); return (FARPROC)fun; } + + +/*************************************************************************** + * ELF_UnloadLibrary + * + * Unload the elf library and free the modref + */ +void ELF_UnloadLibrary(WINE_MODREF *wm) +{ + /* FIXME: do something here */ +} + #else -HMODULE ELF_LoadLibraryExA( LPCSTR libname, HANDLE hf, DWORD flags) +WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, HANDLE hf, DWORD flags) { - return 0; + return NULL; } + +void ELF_UnloadLibrary(WINE_MODREF *wm) +{ +} + FARPROC ELF_FindExportedFunction( WINE_MODREF *wm, LPCSTR funcName) { return (FARPROC)0; diff --git a/loader/main.c b/loader/main.c index 707f16db633..e7b34ba39a4 100644 --- a/loader/main.c +++ b/loader/main.c @@ -45,6 +45,8 @@ #include "debug.h" #include "psdrv.h" #include "server.h" +#include "cursoricon.h" +#include "loadorder.h" int __winelib = 1; /* Winelib run-time flag */ @@ -69,6 +71,9 @@ BOOL MAIN_MainInit(void) /* Load the configuration file */ if (!PROFILE_LoadWineIni()) return FALSE; + /* Initialize module loadorder */ + if (!MODULE_InitLoadOrder()) return FALSE; + /* Initialize DOS memory */ if (!DOSMEM_Init(0)) return FALSE; diff --git a/loader/module.c b/loader/module.c index 8ba903c4dab..30e5bdc9b15 100644 --- a/loader/module.c +++ b/loader/module.c @@ -29,6 +29,8 @@ #include "task.h" #include "debug.h" #include "callback.h" +#include "loadorder.h" +#include "elfdll.h" /************************************************************************* @@ -53,10 +55,55 @@ WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod ) } /************************************************************************* - * MODULE_InitializeDLLs + * MODULE_InitDll + */ +static BOOL MODULE_InitDll( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) +{ + BOOL retv = TRUE; + + static LPCSTR typeName[] = { "PROCESS_DETACH", "PROCESS_ATTACH", + "THREAD_ATTACH", "THREAD_DETACH" }; + assert( wm ); + + + /* Skip calls for modules loaded with special load flags */ + + if ( ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS ) + || ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) ) + return TRUE; + + + TRACE( module, "(%s,%s,%p) - CALL\n", + wm->modname, typeName[type], lpReserved ); + + /* Call the initialization routine */ + switch ( wm->type ) + { + case MODULE32_PE: + retv = PE_InitDLL( wm, type, lpReserved ); + break; + + case MODULE32_ELF: + /* no need to do that, dlopen() already does */ + break; + + default: + ERR( module, "wine_modref type %d not handled.\n", wm->type ); + retv = FALSE; + break; + } + + TRACE( module, "(%s,%s,%p) - RETURN %d\n", + wm->modname, typeName[type], lpReserved, retv ); + + return retv; +} + +/************************************************************************* + * MODULE_DllProcessAttach * - * Call the initialization routines of all DLLs belonging to the - * current process. This is somewhat complicated due to the fact that + * Send the process attach notification to all DLLs the given module + * depends on (recursively). This is somewhat complicated due to the fact that * * - we have to respect the module dependencies, i.e. modules implicitly * referenced by another module have to be initialized before the module @@ -69,171 +116,159 @@ WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod ) * (Note that this routine can be recursively entered not only directly * from itself, but also via LoadLibrary from one of the called initialization * routines.) + * + * Furthermore, we need to rearrange the main WINE_MODREF list to allow + * the process *detach* notifications to be sent in the correct order. + * This must not only take into account module dependencies, but also + * 'hidden' dependencies created by modules calling LoadLibrary in their + * attach notification routine. + * + * The strategy is rather simple: we move a WINE_MODREF to the head of the + * list after the attach notification has returned. This implies that the + * detach notifications are called in the reverse of the sequence the attach + * notifications *returned*. + * + * NOTE: Assumes that the process critical section is held! + * */ -static void MODULE_DoInitializeDLLs( WINE_MODREF *wm, - DWORD type, LPVOID lpReserved ) +BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved ) { - WINE_MODREF *xwm; - int i, skip = FALSE; + BOOL retv = TRUE; + int i; + assert( wm ); - assert( wm && !(wm->flags & WINE_MODREF_MARKER) ); - TRACE( module, "(%s,%08x,%ld,%p) - START\n", - wm->modname, wm->module, type, lpReserved ); + /* prevent infinite recursion in case of cyclical dependencies */ + if ( ( wm->flags & WINE_MODREF_MARKER ) + || ( wm->flags & WINE_MODREF_PROCESS_ATTACHED ) ) + return retv; + + TRACE( module, "(%s,%p) - START\n", + wm->modname, lpReserved ); /* Tag current MODREF to prevent recursive loop */ wm->flags |= WINE_MODREF_MARKER; - switch ( type ) + /* Recursively attach all DLLs this one depends on */ + for ( i = 0; retv && i < wm->nDeps; i++ ) + if ( wm->deps[i] ) + retv = MODULE_DllProcessAttach( wm->deps[i], lpReserved ); + + /* Call DLL entry point */ + if ( retv ) { - default: - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - /* Recursively attach all DLLs this one depends on */ - for ( i = 0; i < wm->nDeps; i++ ) - if ( wm->deps[i] && !(wm->deps[i]->flags & WINE_MODREF_MARKER) ) - MODULE_DoInitializeDLLs( wm->deps[i], type, lpReserved ); - break; - - case DLL_PROCESS_DETACH: - case DLL_THREAD_DETACH: - /* Recursively detach all DLLs that depend on this one */ - for ( xwm = PROCESS_Current()->modref_list; xwm; xwm = xwm->next ) - if ( !(xwm->flags & WINE_MODREF_MARKER) ) - for ( i = 0; i < xwm->nDeps; i++ ) - if ( xwm->deps[i] == wm ) - { - MODULE_DoInitializeDLLs( xwm, type, lpReserved ); - break; - } - break; - } - - /* Evaluate module flags */ - - if ( ( wm->flags & WINE_MODREF_NO_DLL_CALLS ) - || ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS ) - || ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) ) - skip = TRUE; - - if ( type == DLL_PROCESS_ATTACH ) - { - if ( wm->flags & WINE_MODREF_PROCESS_ATTACHED ) - skip = TRUE; - else + retv = MODULE_InitDll( wm, DLL_PROCESS_ATTACH, lpReserved ); + if ( retv ) wm->flags |= WINE_MODREF_PROCESS_ATTACHED; } - if ( type == DLL_PROCESS_DETACH ) + /* Re-insert MODREF at head of list */ + if ( retv && wm->prev ) { - if ( wm->flags & WINE_MODREF_PROCESS_DETACHED ) - skip = TRUE; - else - wm->flags |= WINE_MODREF_PROCESS_DETACHED; + wm->prev->next = wm->next; + if ( wm->next ) wm->next->prev = wm->prev; + + wm->prev = NULL; + wm->next = PROCESS_Current()->modref_list; + PROCESS_Current()->modref_list = wm->next->prev = wm; } - if ( !skip ) - { - /* Now we can call the initialization routine */ - TRACE( module, "(%s,%08x,%ld,%p) - CALL\n", - wm->modname, wm->module, type, lpReserved ); + /* Remove recursion flag */ + wm->flags &= ~WINE_MODREF_MARKER; - switch ( wm->type ) - { - case MODULE32_PE: - PE_InitDLL( wm, type, lpReserved ); - break; + TRACE( module, "(%s,%p) - END\n", + wm->modname, lpReserved ); - case MODULE32_ELF: - /* no need to do that, dlopen() already does */ - break; - - default: - ERR(module, "wine_modref type %d not handled.\n", wm->type); - break; - } - } - - TRACE( module, "(%s,%08x,%ld,%p) - END\n", - wm->modname, wm->module, type, lpReserved ); + return retv; } -void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved ) +/************************************************************************* + * MODULE_DllProcessDetach + * + * Send DLL process detach notifications. See the comment about calling + * sequence at MODULE_DllProcessAttach. Unless the bForceDetach flag + * is set, only DLLs with zero refcount are notified. + * + * NOTE: Assumes that the process critical section is held! + * + */ +void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved ) { - BOOL inProgress = FALSE; WINE_MODREF *wm; - /* Grab the process critical section to protect the recursion flags */ - /* FIXME: This is probably overkill! */ - EnterCriticalSection( &PROCESS_Current()->crit_section ); - - TRACE( module, "(%08x,%ld,%p) - START\n", root, type, lpReserved ); - - /* First, check whether initialization is currently in progress */ - for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next ) - if ( wm->flags & WINE_MODREF_MARKER ) + do + { + for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next ) { - inProgress = TRUE; + /* Check whether to detach this DLL */ + if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) ) + continue; + if ( wm->refCount > 0 && !bForceDetach ) + continue; + + /* Call detach notification */ + wm->flags &= ~WINE_MODREF_PROCESS_ATTACHED; + MODULE_InitDll( wm, DLL_PROCESS_DETACH, lpReserved ); + + /* Restart at head of WINE_MODREF list, as entries might have + been added and/or removed while performing the call ... */ break; } + } while ( wm ); +} - if ( inProgress ) +/************************************************************************* + * MODULE_DllThreadAttach + * + * Send DLL thread attach notifications. These are sent in the + * reverse sequence of process detach notification. + * + */ +void MODULE_DllThreadAttach( LPVOID lpReserved ) +{ + WINE_MODREF *wm; + + EnterCriticalSection( &PROCESS_Current()->crit_section ); + + for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next ) + if ( !wm->next ) + break; + + for ( ; wm; wm = wm->prev ) { - /* - * If this a LoadLibrary call from within an initialization routine, - * treat it analogously to an implicitly referenced DLL. - * Anything else may not happen at this point! - */ - if ( root ) - { - wm = MODULE32_LookupHMODULE( root ); - if ( wm && !(wm->flags & WINE_MODREF_MARKER) ) - MODULE_DoInitializeDLLs( wm, type, lpReserved ); - } - else - FIXME(module, "Invalid recursion!\n"); - } - else - { - /* If we arrive here, this is the start of an initialization run */ - if ( !root ) - { - /* If called for main EXE, initialize all DLLs */ - switch ( type ) - { - default: /* Hmmm. */ - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next ) - if ( !wm->next ) - break; - for ( ; wm; wm = wm->prev ) - if ( !(wm->flags & WINE_MODREF_MARKER) ) - MODULE_DoInitializeDLLs( wm, type, lpReserved ); - break; + if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) ) + continue; + if ( wm->flags & WINE_MODREF_NO_DLL_CALLS ) + continue; - case DLL_PROCESS_DETACH: - case DLL_THREAD_DETACH: - for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next ) - if ( !(wm->flags & WINE_MODREF_MARKER) ) - MODULE_DoInitializeDLLs( wm, type, lpReserved ); - break; - } - } - else - { - /* If called for a specific DLL, initialize only it and its children */ - wm = MODULE32_LookupHMODULE( root ); - if (wm) MODULE_DoInitializeDLLs( wm, type, lpReserved ); - } - - /* We're finished, so we reset all recursion flags */ - for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next ) - wm->flags &= ~WINE_MODREF_MARKER; + MODULE_InitDll( wm, DLL_THREAD_ATTACH, lpReserved ); } - TRACE( module, "(%08x,%ld,%p) - END\n", root, type, lpReserved ); + LeaveCriticalSection( &PROCESS_Current()->crit_section ); +} + +/************************************************************************* + * MODULE_DllThreadDetach + * + * Send DLL thread detach notifications. These are sent in the + * same sequence as process detach notification. + * + */ +void MODULE_DllThreadDetach( LPVOID lpReserved ) +{ + WINE_MODREF *wm; + + EnterCriticalSection( &PROCESS_Current()->crit_section ); + + for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next ) + { + if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) ) + continue; + if ( wm->flags & WINE_MODREF_NO_DLL_CALLS ) + continue; + + MODULE_InitDll( wm, DLL_THREAD_DETACH, lpReserved ); + } - /* Release critical section */ LeaveCriticalSection( &PROCESS_Current()->crit_section ); } @@ -243,49 +278,21 @@ void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved ) * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set. */ BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule ) -{ - WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule ); - if ( !wm ) return FALSE; - - wm->flags |= WINE_MODREF_NO_DLL_CALLS; - return TRUE; -} - -/**************************************************************************** - * MODULE_IncRefCount - */ -static void MODULE_IncRefCount( HMODULE hModule ) { WINE_MODREF *wm; + BOOL retval = TRUE; EnterCriticalSection( &PROCESS_Current()->crit_section ); - wm = MODULE32_LookupHMODULE( hModule ); - if( wm ) - { - wm->refCount++; - TRACE(module, "(%08x) count now %d\n", hModule, wm->refCount); - } - LeaveCriticalSection( &PROCESS_Current()->crit_section ); -} -/**************************************************************************** - * MODULE_DecRefCount - */ -static int MODULE_DecRefCount( HMODULE hModule ) -{ - int retv = 0; - WINE_MODREF *wm; - - EnterCriticalSection( &PROCESS_Current()->crit_section ); wm = MODULE32_LookupHMODULE( hModule ); - if( wm && ( retv = wm->refCount ) > 0 ) - { - wm->refCount--; - TRACE(module, "(%08x) count now %d\n", hModule, wm->refCount); - } + if ( !wm ) + retval = FALSE; + else + wm->flags |= WINE_MODREF_NO_DLL_CALLS; + LeaveCriticalSection( &PROCESS_Current()->crit_section ); - return retv; + return retval; } @@ -449,7 +456,7 @@ FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name ) * the module handle if found * 0 if not */ -HMODULE MODULE_FindModule( +WINE_MODREF *MODULE_FindModule( LPCSTR path /* [in] pathname of module/library to be found */ ) { LPSTR filename; @@ -477,7 +484,7 @@ HMODULE MODULE_FindModule( if (!strcasecmp( filename, xmodname)) { HeapFree( GetProcessHeap(), 0, filename ); HeapFree( GetProcessHeap(), 0, xmodname ); - return wm->module; + return wm; } if (dotptr) *dotptr='.'; /* FIXME: add paths, shortname */ @@ -504,14 +511,14 @@ HMODULE MODULE_FindModule( if (!strcasecmp( filename, xlname)) { HeapFree( GetProcessHeap(), 0, filename ); HeapFree( GetProcessHeap(), 0, xlname ); - return wm->module; + return wm; } if (dotptr) *dotptr='.'; /* FIXME: add paths, shortname */ HeapFree( GetProcessHeap(), 0, xlname ); } HeapFree( GetProcessHeap(), 0, filename ); - return 0; + return NULL; } /*********************************************************************** @@ -1121,10 +1128,14 @@ BOOL WINAPI CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine, */ HMODULE WINAPI GetModuleHandleA(LPCSTR module) { - if (module == NULL) - return PROCESS_Current()->exe_modref->module; + WINE_MODREF *wm; + + if ( module == NULL ) + wm = PROCESS_Current()->exe_modref; else - return MODULE_FindModule( module ); + wm = MODULE_FindModule( module ); + + return wm? wm->module : 0; } HMODULE WINAPI GetModuleHandleW(LPCWSTR module) @@ -1186,43 +1197,116 @@ HMODULE WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf, } /*********************************************************************** - * LoadLibraryEx32A (KERNEL32) + * LoadLibraryExA (KERNEL32) */ -HMODULE WINAPI LoadLibraryExA(LPCSTR libname,HFILE hfile,DWORD flags) +HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HFILE hfile, DWORD flags) { - HMODULE hmod; + WINE_MODREF *wm; - if (!libname) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - hmod = MODULE_LoadLibraryExA( libname, hfile, flags ); + if(!libname) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } - if ( hmod >= 32 ) - { - /* Initialize DLL just loaded */ - MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, NULL ); - /* FIXME: check for failure, SLE(ERROR_DLL_INIT_FAILED) */ - } + wm = MODULE_LoadLibraryExA( libname, hfile, flags ); - return hmod; + return wm ? wm->module : 0; } -HMODULE MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags ) +/*********************************************************************** + * MODULE_LoadLibraryExA (internal) + * + * Load a PE style module according to the load order. + * + * The HFILE parameter is not used and marked reserved in the SDK. I can + * only guess that it should force a file to be mapped, but I rather + * ignore the parameter because it would be extremely difficult to + * integrate this with different types of module represenations. + * + */ +WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags ) { - HMODULE hmod; - - hmod = ELF_LoadLibraryExA( libname, hfile, flags ); - if(hmod < (HMODULE)32) - hmod = PE_LoadLibraryExA( libname, hfile, flags ); + DWORD err; + WINE_MODREF *pwm; + int i; + module_loadorder_t *plo; - if(hmod >= (HMODULE)32) - { - /* Increment RefCount */ - MODULE_IncRefCount( hmod ); - } + EnterCriticalSection(&PROCESS_Current()->crit_section); - return hmod; + /* Check for already loaded module */ + if((pwm = MODULE_FindModule(libname))) + { + pwm->refCount++; + TRACE(module, "Already loaded module '%s' at 0x%08x, count=%d, \n", libname, pwm->module, pwm->refCount); + LeaveCriticalSection(&PROCESS_Current()->crit_section); + return pwm; + } + + plo = MODULE_GetLoadOrder(libname); + + for(i = 0; i < MODULE_LOADORDER_NTYPES; i++) + { + switch(plo->loadorder[i]) + { + case MODULE_LOADORDER_DLL: + TRACE(module, "Trying native dll '%s'\n", libname); + pwm = PE_LoadLibraryExA(libname, flags, &err); + break; + + case MODULE_LOADORDER_ELFDLL: + TRACE(module, "Trying elfdll '%s'\n", libname); + pwm = ELFDLL_LoadLibraryExA(libname, flags, &err); + break; + + case MODULE_LOADORDER_SO: + TRACE(module, "Trying so-library '%s'\n", libname); + pwm = ELF_LoadLibraryExA(libname, flags, &err); + break; + + case MODULE_LOADORDER_BI: + TRACE(module, "Trying built-in '%s'\n", libname); + pwm = BUILTIN32_LoadLibraryExA(libname, flags, &err); + break; + + default: + ERR(module, "Got invalid loadorder type %d (%s index %d)\n", plo->loadorder[i], plo->modulename, i); + /* Fall through */ + + case MODULE_LOADORDER_INVALID: /* We ignore this as it is an empty entry */ + pwm = NULL; + break; + } + + if(pwm) + { + /* Initialize DLL just loaded */ + TRACE(module, "Loaded module '%s' at 0x%08x, \n", libname, pwm->module); + + /* Set the refCount here so that an attach failure will */ + /* decrement the dependencies through the MODULE_FreeLibrary call. */ + pwm->refCount++; + + if(!MODULE_DllProcessAttach(pwm, NULL)) + { + WARN(module, "Attach failed for module '%s', \n", libname); + MODULE_FreeLibrary(pwm); + SetLastError(ERROR_DLL_INIT_FAILED); + pwm = NULL; + } + + LeaveCriticalSection(&PROCESS_Current()->crit_section); + return pwm; + } + + if(err != ERROR_FILE_NOT_FOUND) + break; + } + + ERR(module, "Failed to load module '%s'; error=0x%08lx, \n", libname, err); + SetLastError(err); + LeaveCriticalSection(&PROCESS_Current()->crit_section); + return NULL; } /*********************************************************************** @@ -1252,97 +1336,121 @@ HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HFILE hfile,DWORD flags) return ret; } - /*********************************************************************** - * MODULE_FreeLibrary (internal) + * MODULE_FlushModrefs * - * Decrease the loadcount of the dll. - * If the count reaches 0, then notify the dll and free all dlls - * that depend on this one. + * NOTE: Assumes that the process critical section is held! * + * Remove all unused modrefs and call the internal unloading routines + * for the library type. */ -static void MODULE_FreeLibrary(WINE_MODREF *wm, BOOL first) +static void MODULE_FlushModrefs(void) { - int i; + WINE_MODREF *wm, *next; - assert(wm != NULL); + for(wm = PROCESS_Current()->modref_list; wm; wm = next) + { + next = wm->next; - /* Don't do anything if there still are references */ - if( MODULE_DecRefCount(wm->module) > 1 ) - return; + if(wm->refCount) + continue; - TRACE( module, "(%s, %08x, %d) - START\n", wm->modname, wm->module, first); + /* Unlink this modref from the chain */ + if(wm->next) + wm->next->prev = wm->prev; + if(wm->prev) + wm->prev->next = wm->next; + if(wm == PROCESS_Current()->modref_list) + PROCESS_Current()->modref_list = wm->next; - /* Evaluate module flags */ - if(!( ( wm->flags & WINE_MODREF_NO_DLL_CALLS ) - || ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS ) - || ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) )) - { - /* Now we can call the initialization routine */ - TRACE( module, "(%s, %08x, %d) - CALL\n", wm->modname, wm->module, first); + /* + * The unloaders are also responsible for freeing the modref itself + * because the loaders were responsible for allocating it. + */ + switch(wm->type) + { + case MODULE32_PE: PE_UnloadLibrary(wm); break; + case MODULE32_ELF: ELF_UnloadLibrary(wm); break; + case MODULE32_ELFDLL: ELFDLL_UnloadLibrary(wm); break; + case MODULE32_BI: BUILTIN32_UnloadLibrary(wm); break; - switch ( wm->type ) - { - case MODULE32_PE: - PE_InitDLL(wm, DLL_PROCESS_DETACH, (LPVOID)(first ? 0 : 1)); - break; - - case MODULE32_ELF: - FIXME(module, "FreeLibrary requested on ELF module '%s'\n", wm->modname); - break; - - default: - ERR(module, "wine_modref type %d not handled.\n", wm->type); - break; - } - } - - /* Recursively free all DLLs that depend on this one */ - for( i = 0; i < wm->nDeps; i++ ) - { - if(wm->deps[i]) - { - MODULE_FreeLibrary(wm->deps[i], FALSE); - break; - } - } - - /* Be sure that the freed library and the list head are unlinked properly */ - if(PROCESS_Current()->modref_list == wm) - PROCESS_Current()->modref_list = wm->next; - if(wm->next) - wm->next->prev = wm->prev; - if(wm->prev) - wm->prev->next = wm->next; - - FIXME(module,"should free memory of module %08x '%s'\n", wm->module, wm->modname); - - TRACE( module, "(%s, %08x, %d) - END\n", wm->modname, wm->module, first); + default: + ERR(module, "Invalid or unhandled MODREF type %d encountered (wm=%p)\n", wm->type, wm); + } + } } - /*********************************************************************** * FreeLibrary */ BOOL WINAPI FreeLibrary(HINSTANCE hLibModule) { + BOOL retv = TRUE; WINE_MODREF *wm; - BOOL retval = TRUE; - EnterCriticalSection(&PROCESS_Current()->crit_section); + EnterCriticalSection( &PROCESS_Current()->crit_section ); - wm = MODULE32_LookupHMODULE(hLibModule); - if(!wm) - { - ERR(module, "(%08x) module not found in process' modref_list. Freed too many times?\n", hLibModule); - retval = FALSE; - } + wm = MODULE32_LookupHMODULE( hLibModule ); + if ( !wm ) + SetLastError( ERROR_INVALID_HANDLE ); else - MODULE_FreeLibrary(wm, TRUE); /* This always succeeds */ + retv = MODULE_FreeLibrary( wm ); - LeaveCriticalSection(&PROCESS_Current()->crit_section); + LeaveCriticalSection( &PROCESS_Current()->crit_section ); - return retval; + return retv; +} + +/*********************************************************************** + * MODULE_DecRefCount + * + * NOTE: Assumes that the process critical section is held! + */ +static void MODULE_DecRefCount( WINE_MODREF *wm ) +{ + int i; + + if ( wm->flags & WINE_MODREF_MARKER ) + return; + + if ( wm->refCount <= 0 ) + return; + + --wm->refCount; + TRACE( module, "(%s) refCount: %d\n", wm->modname, wm->refCount ); + + if ( wm->refCount == 0 ) + { + wm->flags |= WINE_MODREF_MARKER; + + for ( i = 0; i < wm->nDeps; i++ ) + if ( wm->deps[i] ) + MODULE_DecRefCount( wm->deps[i] ); + + wm->flags &= ~WINE_MODREF_MARKER; + } +} + +/*********************************************************************** + * MODULE_FreeLibrary + * + * NOTE: Assumes that the process critical section is held! + */ +BOOL MODULE_FreeLibrary( WINE_MODREF *wm ) +{ + TRACE( module, "(%s) - START\n", wm->modname ); + + /* Recursively decrement reference counts */ + MODULE_DecRefCount( wm ); + + /* Call process detach notifications */ + MODULE_DllProcessDetach( FALSE, NULL ); + + MODULE_FlushModrefs(); + + TRACE( module, "(%s) - END\n", wm->modname ); + + return FALSE; } diff --git a/loader/ne/module.c b/loader/ne/module.c index 7856510a67b..73a81a10ac7 100644 --- a/loader/ne/module.c +++ b/loader/ne/module.c @@ -27,6 +27,8 @@ #include "stackframe.h" #include "debug.h" #include "file.h" +#include "loadorder.h" +#include "elfdll.h" FARPROC16 (*fnSNOOP16_GetProcAddress16)(HMODULE16,DWORD,FARPROC16) = NULL; void (*fnSNOOP16_RegisterDLL)(NE_MODULE*,LPCSTR) = NULL; @@ -755,7 +757,7 @@ static BOOL NE_LoadDLLs( NE_MODULE *pModule ) /* its handle in the list of DLLs to initialize. */ HMODULE16 hDLL; - if ((hDLL = NE_LoadModule( buffer, TRUE )) == 2) + if ((hDLL = MODULE_LoadModule16( buffer, TRUE )) == 2) { /* file not found */ char *p; @@ -765,7 +767,7 @@ static BOOL NE_LoadDLLs( NE_MODULE *pModule ) if (!(p = strrchr( buffer, '\\' ))) p = buffer; memcpy( p + 1, pstr + 1, *pstr ); strcpy( p + 1 + *pstr, ".dll" ); - hDLL = NE_LoadModule( buffer, TRUE ); + hDLL = MODULE_LoadModule16( buffer, TRUE ); } if (hDLL < 32) { @@ -857,23 +859,11 @@ static HINSTANCE16 NE_LoadFileModule( HFILE16 hFile, OFSTRUCT *ofs, HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit ) { HINSTANCE16 hInstance; - HMODULE16 hModule; HFILE16 hFile; OFSTRUCT ofs; - /* Try to load the built-in first if not disabled */ - - if ((hModule = fnBUILTIN_LoadModule( name, FALSE ))) return hModule; - if ((hFile = OpenFile16( name, &ofs, OF_READ )) == HFILE_ERROR16) { - /* Now try the built-in even if disabled */ - if ((hModule = fnBUILTIN_LoadModule( name, TRUE ))) - { - MSG( "Could not load Windows DLL '%s', using built-in module.\n", - name ); - return hModule; - } return 2; /* File not found */ } @@ -883,6 +873,67 @@ HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit ) return hInstance; } + +/********************************************************************** + * MODULE_LoadModule16 + * + * Load a NE module in the order of the loadorder specification. + * The caller is responsible that the module is not loaded already. + * + */ +HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit ) +{ + HINSTANCE16 hinst; + int i; + module_loadorder_t *plo; + + plo = MODULE_GetLoadOrder(libname); + + for(i = 0; i < MODULE_LOADORDER_NTYPES; i++) + { + switch(plo->loadorder[i]) + { + case MODULE_LOADORDER_DLL: + TRACE(module, "Trying native dll '%s'\n", libname); + hinst = NE_LoadModule(libname, implicit); + break; + + case MODULE_LOADORDER_ELFDLL: + TRACE(module, "Trying elfdll '%s'\n", libname); + hinst = ELFDLL_LoadModule16(libname, implicit); + break; + + case MODULE_LOADORDER_BI: + TRACE(module, "Trying built-in '%s'\n", libname); + hinst = fnBUILTIN_LoadModule(libname, TRUE); + break; + + default: + ERR(module, "Got invalid loadorder type %d (%s index %d)\n", plo->loadorder[i], plo->modulename, i); + /* Fall through */ + + case MODULE_LOADORDER_SO: /* This is not supported for NE modules */ + case MODULE_LOADORDER_INVALID: /* We ignore this as it is an empty entry */ + hinst = 2; + break; + } + + if(hinst >= 32) + { + TRACE(module, "Loaded module '%s' at 0x%04x, \n", libname, hinst); + return hinst; + } + + if(hinst != 2) + { + /* We quit searching when we get another error than 'File not found' */ + break; + } + } + return hinst; /* The last error that occured */ +} + + /********************************************************************** * LoadModule16 (KERNEL.45) */ @@ -918,7 +969,7 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock ) { /* Main case: load first instance of NE module */ - if ( (hInstance = NE_LoadModule( name, FALSE )) < 32 ) + if ( (hInstance = MODULE_LoadModule16( name, FALSE )) < 32 ) return hInstance; if ( !(pModule = NE_GetPtr( hInstance )) ) diff --git a/loader/pe_image.c b/loader/pe_image.c index 4982dc4877b..4b713681e39 100644 --- a/loader/pe_image.c +++ b/loader/pe_image.c @@ -196,7 +196,7 @@ FARPROC PE_FindExportedFunction( } if (forward) { - HMODULE hMod; + WINE_MODREF *wm; char module[256]; char *end = strchr(forward, '.'); @@ -204,9 +204,9 @@ FARPROC PE_FindExportedFunction( assert(end-forward<256); strncpy(module, forward, (end - forward)); module[end-forward] = 0; - hMod = MODULE_FindModule( module ); - assert(hMod); - return MODULE_GetProcAddress( hMod, end + 1, snoop ); + wm = MODULE_FindModule( module ); + assert(wm); + return MODULE_GetProcAddress( wm->module, end + 1, snoop ); } return NULL; } @@ -214,7 +214,6 @@ FARPROC PE_FindExportedFunction( DWORD fixup_imports( WINE_MODREF *wm ) { IMAGE_IMPORT_DESCRIPTOR *pe_imp; - WINE_MODREF *xwm; PE_MODREF *pem; unsigned int load_addr = wm->module; int i,characteristics_detection=1; @@ -256,7 +255,7 @@ DWORD fixup_imports( WINE_MODREF *wm ) */ for (i = 0, pe_imp = pem->pe_import; pe_imp->Name ; pe_imp++) { - HMODULE hImpModule; + WINE_MODREF *wmImp; IMAGE_IMPORT_BY_NAME *pe_name; PIMAGE_THUNK_DATA import_list,thunk_list; char *name = (char *) RVA(pe_imp->Name); @@ -265,8 +264,8 @@ DWORD fixup_imports( WINE_MODREF *wm ) break; /* don't use MODULE_Load, Win32 creates new task differently */ - hImpModule = MODULE_LoadLibraryExA( name, 0, 0 ); - if (!hImpModule) { + wmImp = MODULE_LoadLibraryExA( name, 0, 0 ); + if (!wmImp) { char *p,buffer[2000]; /* GetModuleFileName would use the wrong process, so don't use it */ @@ -274,15 +273,13 @@ DWORD fixup_imports( WINE_MODREF *wm ) if (!(p = strrchr (buffer, '\\'))) p = buffer; strcpy (p + 1, name); - hImpModule = MODULE_LoadLibraryExA( buffer, 0, 0 ); + wmImp = MODULE_LoadLibraryExA( buffer, 0, 0 ); } - if (!hImpModule) { + if (!wmImp) { ERR (module, "Module %s not found\n", name); return 1; } - xwm = MODULE32_LookupHMODULE( hImpModule ); - assert( xwm ); - wm->deps[i++] = xwm; + wm->deps[i++] = wmImp; /* FIXME: forwarder entries ... */ @@ -297,7 +294,7 @@ DWORD fixup_imports( WINE_MODREF *wm ) TRACE(win32, "--- Ordinal %s,%d\n", name, ordinal); thunk_list->u1.Function=MODULE_GetProcAddress( - hImpModule, (LPCSTR)ordinal, TRUE + wmImp->module, (LPCSTR)ordinal, TRUE ); if (!thunk_list->u1.Function) { ERR(win32,"No implementation for %s.%d, setting to 0xdeadbeef\n", @@ -308,7 +305,7 @@ DWORD fixup_imports( WINE_MODREF *wm ) pe_name = (PIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData); TRACE(win32, "--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint); thunk_list->u1.Function=MODULE_GetProcAddress( - hImpModule, pe_name->Name, TRUE + wmImp->module, pe_name->Name, TRUE ); if (!thunk_list->u1.Function) { ERR(win32,"No implementation for %s.%d(%s), setting to 0xdeadbeef\n", @@ -329,7 +326,7 @@ DWORD fixup_imports( WINE_MODREF *wm ) TRACE(win32,"--- Ordinal %s.%d\n",name,ordinal); thunk_list->u1.Function=MODULE_GetProcAddress( - hImpModule, (LPCSTR) ordinal, TRUE + wmImp->module, (LPCSTR) ordinal, TRUE ); if (!thunk_list->u1.Function) { ERR(win32, "No implementation for %s.%d, setting to 0xdeadbeef\n", @@ -341,7 +338,7 @@ DWORD fixup_imports( WINE_MODREF *wm ) TRACE(win32,"--- %s %s.%d\n", pe_name->Name,name,pe_name->Hint); thunk_list->u1.Function=MODULE_GetProcAddress( - hImpModule, pe_name->Name, TRUE + wmImp->module, pe_name->Name, TRUE ); if (!thunk_list->u1.Function) { ERR(win32, "No implementation for %s.%d, setting to 0xdeadbeef\n", @@ -829,68 +826,76 @@ WINE_MODREF *PE_CreateModule( HMODULE hModule, * The PE Library Loader frontend. * FIXME: handle the flags. */ -HMODULE PE_LoadLibraryExA (LPCSTR name, - HFILE hFile, DWORD flags) +WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags, DWORD *err) { - LPCSTR modName = NULL; - OFSTRUCT ofs; - HMODULE hModule32; - HMODULE16 hModule16; - NE_MODULE *pModule; - WINE_MODREF *wm; - BOOL builtin = TRUE; - char dllname[256], *p; + LPCSTR modName = NULL; + OFSTRUCT ofs; + HMODULE hModule32; + HMODULE16 hModule16; + NE_MODULE *pModule; + WINE_MODREF *wm; + BOOL builtin = TRUE; + char dllname[256], *p; + HFILE hFile; - /* Check for already loaded module */ - if ((hModule32 = MODULE_FindModule( name ))) - return hModule32; + /* Append .DLL to name if no extension present */ + strcpy( dllname, name ); + if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\')) + strcat( dllname, ".DLL" ); - /* Append .DLL to name if no extension present */ - strcpy( dllname, name ); - if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\')) - strcat( dllname, ".DLL" ); + /* Load PE module */ + hFile = OpenFile( dllname, &ofs, OF_READ | OF_SHARE_DENY_WRITE ); + if ( hFile != HFILE_ERROR ) + { + hModule32 = PE_LoadImage( hFile, &ofs, &modName ); + CloseHandle( hFile ); + if(!hModule32) + { + *err = ERROR_OUTOFMEMORY; /* Not entirely right, but good enough */ + return NULL; + } + } + else + { + *err = ERROR_FILE_NOT_FOUND; + return NULL; + } - /* Try to load builtin enabled modules first */ - if ( !(hModule32 = BUILTIN32_LoadImage( name, &ofs, FALSE )) ) - { - /* Load PE module */ + /* Create 16-bit dummy module */ + if ((hModule16 = MODULE_CreateDummyModule( &ofs, modName )) < 32) + { + *err = (DWORD)hModule16; /* This should give the correct error */ + return NULL; + } + pModule = (NE_MODULE *)GlobalLock16( hModule16 ); + pModule->flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA | NE_FFLAGS_WIN32; + pModule->module32 = hModule32; - hFile = OpenFile( dllname, &ofs, OF_READ | OF_SHARE_DENY_WRITE ); - if ( hFile != HFILE_ERROR ) - if ( (hModule32 = PE_LoadImage( hFile, &ofs, &modName )) >= 32 ) - builtin = FALSE; + /* Create 32-bit MODREF */ + if ( !(wm = PE_CreateModule( hModule32, &ofs, flags, builtin )) ) + { + ERR(win32,"can't load %s\n",ofs.szPathName); + FreeLibrary16( hModule16 ); + *err = ERROR_OUTOFMEMORY; + return NULL; + } - CloseHandle( hFile ); - } + if (wm->binfmt.pe.pe_export) + SNOOP_RegisterDLL(wm->module,wm->modname,wm->binfmt.pe.pe_export->NumberOfFunctions); - /* Now try the built-in even if disabled */ - if ( builtin ) { - if ( (hModule32 = BUILTIN32_LoadImage( name, &ofs, TRUE )) ) - WARN( module, "Could not load external DLL '%s', using built-in module.\n", name ); - else - return 0; - } + *err = 0; + return wm; +} - /* Create 16-bit dummy module */ - if ((hModule16 = MODULE_CreateDummyModule( &ofs, modName )) < 32) return hModule16; - pModule = (NE_MODULE *)GlobalLock16( hModule16 ); - pModule->flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA | - NE_FFLAGS_WIN32 | (builtin? NE_FFLAGS_BUILTIN : 0); - pModule->module32 = hModule32; - - /* Create 32-bit MODREF */ - if ( !(wm = PE_CreateModule( hModule32, &ofs, flags, builtin )) ) - { - ERR(win32,"can't load %s\n",ofs.szPathName); - FreeLibrary16( hModule16 ); - return 0; - } - - if (wm->binfmt.pe.pe_export) - SNOOP_RegisterDLL(wm->module,wm->modname,wm->binfmt.pe.pe_export->NumberOfFunctions); - - return wm->module; +/***************************************************************************** + * PE_UnloadLibrary + * + * Unload the library unmapping the image and freeing the modref structure. + */ +void PE_UnloadLibrary(WINE_MODREF *wm) +{ + /* FIXME, do something here */ } /***************************************************************************** @@ -958,18 +963,11 @@ int PE_UnloadImage( HMODULE hModule ) * DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH * (SDK) */ -void PE_InitDLL(WINE_MODREF *wm, DWORD type, LPVOID lpReserved) +BOOL PE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) { - if (wm->type!=MODULE32_PE) - return; + BOOL retv = TRUE; + assert( wm->type == MODULE32_PE ); - /* DLL_ATTACH_PROCESS: - * lpreserved is NULL for dynamic loads, not-NULL for static loads - * DLL_DETACH_PROCESS: - * lpreserved is NULL if called by FreeLibrary, not-NULL otherwise - * the SDK doesn't mention anything for DLL_THREAD_* - */ - /* Is this a library? And has it got an entrypoint? */ if ((PE_HEADER(wm->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) && (PE_HEADER(wm->module)->OptionalHeader.AddressOfEntryPoint) @@ -978,8 +976,10 @@ void PE_InitDLL(WINE_MODREF *wm, DWORD type, LPVOID lpReserved) TRACE(relay, "CallTo32(entryproc=%p,module=%08x,type=%ld,res=%p)\n", entry, wm->module, type, lpReserved ); - entry( wm->module, type, lpReserved ); + retv = entry( wm->module, type, lpReserved ); } + + return retv; } /************************************************************************ diff --git a/memory/global.c b/memory/global.c index e5b9a1b32b8..21da1fc34fc 100644 --- a/memory/global.c +++ b/memory/global.c @@ -388,7 +388,11 @@ HGLOBAL16 WINAPI GlobalReAlloc16( TRACE(global,"oldsize %08lx\n",oldsize); if (ptr && (size == oldsize)) return handle; /* Nothing to do */ - ptr = HeapReAlloc( SystemHeap, 0, ptr, size ); + if (((char *)ptr >= DOSMEM_MemoryBase(0)) && + ((char *)ptr <= DOSMEM_MemoryBase(0) + 0x100000)) + ptr = DOSMEM_ResizeBlock(0, ptr, size, NULL); + else + ptr = HeapReAlloc( SystemHeap, 0, ptr, size ); if (!ptr) { SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 ); diff --git a/misc/main.c b/misc/main.c index 54efa8cb20a..71c47216f00 100644 --- a/misc/main.c +++ b/misc/main.c @@ -812,10 +812,6 @@ BOOL MAIN_WineInit( int *argc, char *argv[] ) MONITOR_Initialize(&MONITOR_PrimaryMonitor); - if (Options.dllFlags) - BUILTIN32_ParseDLLOptions( Options.dllFlags ); - /* if (__winelib && errors ) print_error_message_like_misc_main(); */ - atexit(called_at_exit); return TRUE; } diff --git a/miscemu/main.c b/miscemu/main.c index c3c507227d5..5ee83ee88e4 100644 --- a/miscemu/main.c +++ b/miscemu/main.c @@ -140,18 +140,6 @@ int main( int argc, char *argv[] ) if (!MAIN_WineInit( &argc, argv )) return 1; MAIN_argc = argc; MAIN_argv = argv; - /* Handle -dll option (hack) */ - if (Options.dllFlags) - { - /* If there are options left, or if the parser had errors, report it */ - if (!BUILTIN_ParseDLLOptions( Options.dllFlags )||Options.dllFlags[0]) { - MSG("%s: Syntax: -dll +xxx,... or -dll -xxx,...\n", - argv[0] ); - BUILTIN_PrintDLLs(); - exit(1); - } - } - /* Set up debugger/instruction emulation callback routines */ ctx_debug_call = ctx_debug; fnWINE_Debugger = wine_debug; diff --git a/relay32/builtin32.c b/relay32/builtin32.c index 23af85c53ac..a8421a33235 100644 --- a/relay32/builtin32.c +++ b/relay32/builtin32.c @@ -14,6 +14,8 @@ #include "heap.h" #include "debug.h" #include "main.h" +#include "snoop.h" +#include "winerror.h" typedef struct { @@ -320,6 +322,77 @@ HMODULE BUILTIN32_LoadImage( LPCSTR name, OFSTRUCT *ofs, BOOL force ) } +/*********************************************************************** + * BUILTIN32_LoadLibraryExA + * + * Partly copied from the original PE_ version. + * + * Note: This implementation is not very nice and should be one with + * the BUILTIN32_LoadImage function. But, we don't care too much + * because this code will obsolete itself shortly when we get the + * modularization of wine implemented (BS 05-Mar-1999). + */ +WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags, DWORD *err) +{ + LPCSTR modName = NULL; + OFSTRUCT ofs; + HMODULE hModule32; + HMODULE16 hModule16; + NE_MODULE *pModule; + WINE_MODREF *wm; + char dllname[256], *p; + + /* Append .DLL to name if no extension present */ + strcpy( dllname, path ); + if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\')) + strcat( dllname, ".DLL" ); + + hModule32 = BUILTIN32_LoadImage( path, &ofs, TRUE ); + if(!hModule32) + { + *err = ERROR_FILE_NOT_FOUND; + return NULL; + } + + /* Create 16-bit dummy module */ + if ((hModule16 = MODULE_CreateDummyModule( &ofs, modName )) < 32) + { + *err = (DWORD)hModule16; + return NULL; /* FIXME: Should unload the builtin module */ + } + + pModule = (NE_MODULE *)GlobalLock16( hModule16 ); + pModule->flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA | NE_FFLAGS_WIN32 | NE_FFLAGS_BUILTIN; + pModule->module32 = hModule32; + + /* Create 32-bit MODREF */ + if ( !(wm = PE_CreateModule( hModule32, &ofs, flags, TRUE )) ) + { + ERR(win32,"can't load %s\n",ofs.szPathName); + FreeLibrary16( hModule16 ); /* FIXME: Should unload the builtin module */ + *err = ERROR_OUTOFMEMORY; + return NULL; + } + + if (wm->binfmt.pe.pe_export) + SNOOP_RegisterDLL(wm->module,wm->modname,wm->binfmt.pe.pe_export->NumberOfFunctions); + + *err = 0; + return wm; +} + + +/*********************************************************************** + * BUILTIN32_UnloadLibrary + * + * Unload the built-in library and free the modref. + */ +void BUILTIN32_UnloadLibrary(WINE_MODREF *wm) +{ + /* FIXME: do something here */ +} + + /*********************************************************************** * BUILTIN32_GetEntryPoint * @@ -435,74 +508,3 @@ void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr, int ordinal ) ExitProcess(1); } -/*********************************************************************** - * BUILTIN32_ParseDLLOptions - * - * Set runtime DLL usage flags - */ -BOOL BUILTIN32_ParseDLLOptions( char *str ) -{ - BUILTIN32_DLL *dll; - char *p,*last; - - last = str; - while (*str) - { - while (*str && (*str==',' || isspace(*str))) str++; - if (!*str) { - *last = '\0'; /* cut off garbage at end at */ - return TRUE; - } - if ((*str != '+') && (*str != '-')) return FALSE; - str++; - if (!(p = strchr( str, ',' ))) p = str + strlen(str); - while ((p > str) && isspace(p[-1])) p--; - if (p == str) return FALSE; - for (dll = BuiltinDLLs; dll->descr; dll++) - { - if (!lstrncmpiA( dll->descr->name, str, (int)(p-str) )) - { - if (dll->descr->name[p-str]) /* partial match - skip */ - continue; - dll->used = (str[-1]!='-'); - break; - } - } - if (!dll->descr) { - /* not found, but could get handled by BUILTIN_, so move last */ - last = p; - str = p; - } else { - /* handled. cut out the "[+-]DLL," string, so it isn't handled - * by BUILTIN - */ - if (*p) { - memcpy(last,p,strlen(p)+1); - str = last; - } else { - *last = '\0'; - break; - } - } - } - return TRUE; -} - - - -/*********************************************************************** - * BUILTIN32_PrintDLLs - * - * Print the list of built-in DLLs that can be disabled. - */ -void BUILTIN32_PrintDLLs(void) -{ - int i; - BUILTIN32_DLL *dll; - - MSG("Available Win32 DLLs:\n"); - for (i = 0, dll = BuiltinDLLs; dll->descr; dll++) - MSG("%-9s%c", dll->descr->name, - ((++i) % 8) ? ' ' : '\n' ); - MSG("\n"); -} diff --git a/scheduler/process.c b/scheduler/process.c index 94a44b701fa..5811498c1fd 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -486,6 +486,10 @@ void PROCESS_Start(void) /* Create 32-bit MODREF */ if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error; + /* Increment EXE refcount */ + assert( PROCESS_Current()->exe_modref ); + PROCESS_Current()->exe_modref->refCount++; + PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0, 0 ); /* FIXME: correct location? */ /* Initialize thread-local storage */ @@ -497,7 +501,9 @@ void PROCESS_Start(void) /* Now call the entry point */ - MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)1 ); + EnterCriticalSection( &PROCESS_Current()->crit_section ); + MODULE_DllProcessAttach( PROCESS_Current()->exe_modref, (LPVOID)1 ); + LeaveCriticalSection( &PROCESS_Current()->crit_section ); PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0, 0 ); @@ -651,7 +657,9 @@ error: */ void WINAPI ExitProcess( DWORD status ) { - MODULE_InitializeDLLs( 0, DLL_PROCESS_DETACH, (LPVOID)1 ); + EnterCriticalSection( &PROCESS_Current()->crit_section ); + MODULE_DllProcessDetach( TRUE, (LPVOID)1 ); + LeaveCriticalSection( &PROCESS_Current()->crit_section ); if ( THREAD_IsWin16( THREAD_Current() ) ) TASK_KillCurrentTask( status ); diff --git a/scheduler/thread.c b/scheduler/thread.c index b6909ce9025..c3a39b2c3ba 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -281,7 +281,7 @@ static void THREAD_Start(void) LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point; PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0, 0 ); PE_InitTls(); - MODULE_InitializeDLLs( 0, DLL_THREAD_ATTACH, NULL ); + MODULE_DllThreadAttach( NULL ); ExitThread( func( thdb->entry_arg ) ); } @@ -318,7 +318,7 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack, */ void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */ { - MODULE_InitializeDLLs( 0, DLL_THREAD_DETACH, NULL ); + MODULE_DllThreadDetach( NULL ); TerminateThread( GetCurrentThread(), code ); }