Reorganization of the loader to correctly load and free libraries and

implementation of load order to load different types of libraries.
This commit is contained in:
Bertho Stultiens 1999-04-18 12:14:06 +00:00 committed by Alexandre Julliard
parent 2594720195
commit c1d1cfe976
17 changed files with 677 additions and 566 deletions

View file

@ -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();
}

View file

@ -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 */

View file

@ -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);

View file

@ -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 */

View file

@ -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

View file

@ -7,7 +7,9 @@ MODULE = loader
C_SRCS = \
elf.c \
elfdll.c \
libres.c \
loadorder.c \
main.c \
module.c \
pe_image.c \

View file

@ -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 <dlfcn.h>
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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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 )) )

View file

@ -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;
}
/************************************************************************

View file

@ -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 );

View file

@ -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;
}

View file

@ -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;

View file

@ -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");
}

View file

@ -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 );

View file

@ -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 );
}