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:
parent
2594720195
commit
c1d1cfe976
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -7,7 +7,9 @@ MODULE = loader
|
|||
|
||||
C_SRCS = \
|
||||
elf.c \
|
||||
elfdll.c \
|
||||
libres.c \
|
||||
loadorder.c \
|
||||
main.c \
|
||||
module.c \
|
||||
pe_image.c \
|
||||
|
|
32
loader/elf.c
32
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 <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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
658
loader/module.c
658
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 )) )
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue