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 );
|
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 );
|
unsigned int *typemask );
|
||||||
extern void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr,
|
extern void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr,
|
||||||
int ordinal );
|
int ordinal );
|
||||||
extern void BUILTIN32_PrintDLLs(void);
|
|
||||||
extern void BUILTIN32_SwitchRelayDebug(int onoff);
|
extern void BUILTIN32_SwitchRelayDebug(int onoff);
|
||||||
extern int BUILTIN32_EnableDLL( const char *name, int len, int enable );
|
|
||||||
|
|
||||||
#endif /* __WINE_BUILTIN32_H */
|
#endif /* __WINE_BUILTIN32_H */
|
||||||
|
|
|
@ -121,7 +121,13 @@ typedef struct
|
||||||
#pragma pack(4)
|
#pragma pack(4)
|
||||||
|
|
||||||
/* internal representation of 32bit modules. per process. */
|
/* 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
|
typedef struct _wine_modref
|
||||||
{
|
{
|
||||||
struct _wine_modref *next;
|
struct _wine_modref *next;
|
||||||
|
@ -132,7 +138,7 @@ typedef struct _wine_modref
|
||||||
ELF_MODREF elf;
|
ELF_MODREF elf;
|
||||||
} binfmt;
|
} binfmt;
|
||||||
|
|
||||||
HMODULE module;
|
HMODULE module;
|
||||||
|
|
||||||
int nDeps;
|
int nDeps;
|
||||||
struct _wine_modref **deps;
|
struct _wine_modref **deps;
|
||||||
|
@ -148,7 +154,6 @@ typedef struct _wine_modref
|
||||||
#define WINE_MODREF_INTERNAL 0x00000001
|
#define WINE_MODREF_INTERNAL 0x00000001
|
||||||
#define WINE_MODREF_NO_DLL_CALLS 0x00000002
|
#define WINE_MODREF_NO_DLL_CALLS 0x00000002
|
||||||
#define WINE_MODREF_PROCESS_ATTACHED 0x00000004
|
#define WINE_MODREF_PROCESS_ATTACHED 0x00000004
|
||||||
#define WINE_MODREF_PROCESS_DETACHED 0x00000008
|
|
||||||
#define WINE_MODREF_LOAD_AS_DATAFILE 0x00000010
|
#define WINE_MODREF_LOAD_AS_DATAFILE 0x00000010
|
||||||
#define WINE_MODREF_DONT_RESOLVE_REFS 0x00000020
|
#define WINE_MODREF_DONT_RESOLVE_REFS 0x00000020
|
||||||
#define WINE_MODREF_MARKER 0x80000000
|
#define WINE_MODREF_MARKER 0x80000000
|
||||||
|
@ -171,13 +176,17 @@ typedef struct resource_nameinfo_s NE_NAMEINFO;
|
||||||
/* module.c */
|
/* module.c */
|
||||||
extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, BOOL snoop );
|
extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, BOOL snoop );
|
||||||
extern WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hModule );
|
extern WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hModule );
|
||||||
extern void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved );
|
extern BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved );
|
||||||
extern HMODULE MODULE_FindModule( LPCSTR path );
|
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 HMODULE MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName );
|
||||||
extern FARPROC16 MODULE_GetWndProcEntry16( const char *name );
|
extern FARPROC16 MODULE_GetWndProcEntry16( const char *name );
|
||||||
extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name );
|
extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name );
|
||||||
extern SEGPTR WINAPI HasGPHandler16( SEGPTR address );
|
extern SEGPTR WINAPI HasGPHandler16( SEGPTR address );
|
||||||
HMODULE MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags );
|
|
||||||
|
|
||||||
/* resource.c */
|
/* resource.c */
|
||||||
extern INT WINAPI AccessResource(HMODULE,HRSRC);
|
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 FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop );
|
||||||
extern BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset );
|
extern BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset );
|
||||||
extern HANDLE NE_OpenFile( NE_MODULE *pModule );
|
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,
|
extern BOOL NE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line, LPCSTR env,
|
||||||
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
||||||
BOOL inherit, LPSTARTUPINFOA startup,
|
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 BOOL BUILTIN_Init(void);
|
||||||
extern HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL force );
|
extern HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL force );
|
||||||
extern LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd );
|
extern LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd );
|
||||||
extern BOOL BUILTIN_ParseDLLOptions( char *str );
|
|
||||||
extern void BUILTIN_PrintDLLs(void);
|
|
||||||
|
|
||||||
/* relay32/builtin.c */
|
/* relay32/builtin.c */
|
||||||
extern HMODULE BUILTIN32_LoadImage( LPCSTR name, OFSTRUCT *ofs, BOOL force );
|
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 */
|
/* if1632/builtin.c */
|
||||||
extern HMODULE16 (*fnBUILTIN_LoadModule)(LPCSTR name, BOOL force);
|
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 BOOL PE_EnumResourceLanguagesW(HMODULE,LPCWSTR,LPCWSTR,ENUMRESLANGPROCW,LONG);
|
||||||
extern HRSRC PE_FindResourceExW(struct _wine_modref*,LPCWSTR,LPCWSTR,WORD);
|
extern HRSRC PE_FindResourceExW(struct _wine_modref*,LPCWSTR,LPCWSTR,WORD);
|
||||||
extern DWORD PE_SizeofResource(HMODULE,HRSRC);
|
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 HGLOBAL PE_LoadResource(struct _wine_modref *wm,HRSRC);
|
||||||
extern HMODULE PE_LoadImage( HFILE hFile, OFSTRUCT *ofs, LPCSTR *modName );
|
extern HMODULE PE_LoadImage( HFILE hFile, OFSTRUCT *ofs, LPCSTR *modName );
|
||||||
extern struct _wine_modref *PE_CreateModule( HMODULE hModule, OFSTRUCT *ofs,
|
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 );
|
LPPROCESS_INFORMATION info );
|
||||||
|
|
||||||
extern void PE_InitTls(void);
|
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 GetResDirEntryA(PIMAGE_RESOURCE_DIRECTORY,LPCSTR,DWORD,BOOL);
|
||||||
extern PIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(PIMAGE_RESOURCE_DIRECTORY,LPCWSTR,DWORD,BOOL);
|
extern PIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(PIMAGE_RESOURCE_DIRECTORY,LPCWSTR,DWORD,BOOL);
|
||||||
|
@ -64,7 +65,8 @@ typedef struct {
|
||||||
} ELF_MODREF;
|
} ELF_MODREF;
|
||||||
|
|
||||||
extern struct _wine_modref *ELF_CreateDummyModule(LPCSTR,LPCSTR);
|
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);
|
extern FARPROC ELF_FindExportedFunction(struct _wine_modref *wm, LPCSTR funcName);
|
||||||
|
|
||||||
#endif /* __WINE_PE_IMAGE_H */
|
#endif /* __WINE_PE_IMAGE_H */
|
||||||
|
|
|
@ -245,6 +245,7 @@ extern int WIN32_LastError;
|
||||||
#define ERROR_BADKEY 1010 /* Config reg key invalid */
|
#define ERROR_BADKEY 1010 /* Config reg key invalid */
|
||||||
#define ERROR_CANTREAD 1012 /* Config reg key couldn't be read */
|
#define ERROR_CANTREAD 1012 /* Config reg key couldn't be read */
|
||||||
#define ERROR_CANTWRITE 1013 /* Config reg key couldn't be written */
|
#define ERROR_CANTWRITE 1013 /* Config reg key couldn't be written */
|
||||||
|
#define ERROR_DLL_INIT_FAILED 1114
|
||||||
#define ERROR_IO_DEVICE 1117
|
#define ERROR_IO_DEVICE 1117
|
||||||
#define ERROR_POSSIBLE_DEADLOCK 1131
|
#define ERROR_POSSIBLE_DEADLOCK 1131
|
||||||
#define ERROR_BAD_DEVICE 1200
|
#define ERROR_BAD_DEVICE 1200
|
||||||
|
|
|
@ -7,7 +7,9 @@ MODULE = loader
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
elf.c \
|
elf.c \
|
||||||
|
elfdll.c \
|
||||||
libres.c \
|
libres.c \
|
||||||
|
loadorder.c \
|
||||||
main.c \
|
main.c \
|
||||||
module.c \
|
module.c \
|
||||||
pe_image.c \
|
pe_image.c \
|
||||||
|
|
32
loader/elf.c
32
loader/elf.c
|
@ -21,9 +21,10 @@
|
||||||
#include "neexe.h"
|
#include "neexe.h"
|
||||||
#include "peexe.h"
|
#include "peexe.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "pe_image.h"
|
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
#include "pe_image.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "winerror.h"
|
||||||
|
|
||||||
WINE_MODREF *ELF_CreateDummyModule( LPCSTR libname, LPCSTR modname )
|
WINE_MODREF *ELF_CreateDummyModule( LPCSTR libname, LPCSTR modname )
|
||||||
{
|
{
|
||||||
|
@ -96,7 +97,7 @@ WINE_MODREF *ELF_CreateDummyModule( LPCSTR libname, LPCSTR modname )
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#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;
|
WINE_MODREF *wm;
|
||||||
char *modname,*s,*t,*x;
|
char *modname,*s,*t,*x;
|
||||||
|
@ -138,14 +139,16 @@ HMODULE ELF_LoadLibraryExA( LPCSTR libname, HANDLE hf, DWORD flags )
|
||||||
dlhandle = dlopen(t,RTLD_NOW);
|
dlhandle = dlopen(t,RTLD_NOW);
|
||||||
if (!dlhandle) {
|
if (!dlhandle) {
|
||||||
HeapFree( GetProcessHeap(), 0, t );
|
HeapFree( GetProcessHeap(), 0, t );
|
||||||
return 0;
|
*err = ERROR_FILE_NOT_FOUND;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wm = ELF_CreateDummyModule( t, modname );
|
wm = ELF_CreateDummyModule( t, modname );
|
||||||
wm->binfmt.elf.dlhandle = dlhandle;
|
wm->binfmt.elf.dlhandle = dlhandle;
|
||||||
|
|
||||||
SNOOP_RegisterDLL(wm->module,libname,STUBSIZE/sizeof(ELF_STDCALL_STUB));
|
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)
|
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);
|
fun = SNOOP_GetProcAddress(wm->module,funcName,stub-wm->binfmt.elf.stubs,fun);
|
||||||
return (FARPROC)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
|
#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)
|
FARPROC ELF_FindExportedFunction( WINE_MODREF *wm, LPCSTR funcName)
|
||||||
{
|
{
|
||||||
return (FARPROC)0;
|
return (FARPROC)0;
|
||||||
|
|
|
@ -45,6 +45,8 @@
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "psdrv.h"
|
#include "psdrv.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#include "cursoricon.h"
|
||||||
|
#include "loadorder.h"
|
||||||
|
|
||||||
int __winelib = 1; /* Winelib run-time flag */
|
int __winelib = 1; /* Winelib run-time flag */
|
||||||
|
|
||||||
|
@ -69,6 +71,9 @@ BOOL MAIN_MainInit(void)
|
||||||
/* Load the configuration file */
|
/* Load the configuration file */
|
||||||
if (!PROFILE_LoadWineIni()) return FALSE;
|
if (!PROFILE_LoadWineIni()) return FALSE;
|
||||||
|
|
||||||
|
/* Initialize module loadorder */
|
||||||
|
if (!MODULE_InitLoadOrder()) return FALSE;
|
||||||
|
|
||||||
/* Initialize DOS memory */
|
/* Initialize DOS memory */
|
||||||
if (!DOSMEM_Init(0)) return FALSE;
|
if (!DOSMEM_Init(0)) return FALSE;
|
||||||
|
|
||||||
|
|
658
loader/module.c
658
loader/module.c
|
@ -29,6 +29,8 @@
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "callback.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
|
* Send the process attach notification to all DLLs the given module
|
||||||
* current process. This is somewhat complicated due to the fact that
|
* depends on (recursively). This is somewhat complicated due to the fact that
|
||||||
*
|
*
|
||||||
* - we have to respect the module dependencies, i.e. modules implicitly
|
* - we have to respect the module dependencies, i.e. modules implicitly
|
||||||
* referenced by another module have to be initialized before the module
|
* 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
|
* (Note that this routine can be recursively entered not only directly
|
||||||
* from itself, but also via LoadLibrary from one of the called initialization
|
* from itself, but also via LoadLibrary from one of the called initialization
|
||||||
* routines.)
|
* 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,
|
BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
|
||||||
DWORD type, LPVOID lpReserved )
|
|
||||||
{
|
{
|
||||||
WINE_MODREF *xwm;
|
BOOL retv = TRUE;
|
||||||
int i, skip = FALSE;
|
int i;
|
||||||
|
assert( wm );
|
||||||
|
|
||||||
assert( wm && !(wm->flags & WINE_MODREF_MARKER) );
|
/* prevent infinite recursion in case of cyclical dependencies */
|
||||||
TRACE( module, "(%s,%08x,%ld,%p) - START\n",
|
if ( ( wm->flags & WINE_MODREF_MARKER )
|
||||||
wm->modname, wm->module, type, lpReserved );
|
|| ( wm->flags & WINE_MODREF_PROCESS_ATTACHED ) )
|
||||||
|
return retv;
|
||||||
|
|
||||||
|
TRACE( module, "(%s,%p) - START\n",
|
||||||
|
wm->modname, lpReserved );
|
||||||
|
|
||||||
/* Tag current MODREF to prevent recursive loop */
|
/* Tag current MODREF to prevent recursive loop */
|
||||||
wm->flags |= WINE_MODREF_MARKER;
|
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:
|
retv = MODULE_InitDll( wm, DLL_PROCESS_ATTACH, lpReserved );
|
||||||
case DLL_PROCESS_ATTACH:
|
if ( retv )
|
||||||
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
|
|
||||||
wm->flags |= WINE_MODREF_PROCESS_ATTACHED;
|
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 )
|
wm->prev->next = wm->next;
|
||||||
skip = TRUE;
|
if ( wm->next ) wm->next->prev = wm->prev;
|
||||||
else
|
|
||||||
wm->flags |= WINE_MODREF_PROCESS_DETACHED;
|
wm->prev = NULL;
|
||||||
|
wm->next = PROCESS_Current()->modref_list;
|
||||||
|
PROCESS_Current()->modref_list = wm->next->prev = wm;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !skip )
|
/* Remove recursion flag */
|
||||||
{
|
wm->flags &= ~WINE_MODREF_MARKER;
|
||||||
/* Now we can call the initialization routine */
|
|
||||||
TRACE( module, "(%s,%08x,%ld,%p) - CALL\n",
|
|
||||||
wm->modname, wm->module, type, lpReserved );
|
|
||||||
|
|
||||||
switch ( wm->type )
|
TRACE( module, "(%s,%p) - END\n",
|
||||||
{
|
wm->modname, lpReserved );
|
||||||
case MODULE32_PE:
|
|
||||||
PE_InitDLL( wm, type, lpReserved );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MODULE32_ELF:
|
return retv;
|
||||||
/* 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
WINE_MODREF *wm;
|
||||||
|
|
||||||
/* Grab the process critical section to protect the recursion flags */
|
do
|
||||||
/* FIXME: This is probably overkill! */
|
{
|
||||||
EnterCriticalSection( &PROCESS_Current()->crit_section );
|
for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
|
||||||
|
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
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;
|
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 ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) )
|
||||||
* If this a LoadLibrary call from within an initialization routine,
|
continue;
|
||||||
* treat it analogously to an implicitly referenced DLL.
|
if ( wm->flags & WINE_MODREF_NO_DLL_CALLS )
|
||||||
* Anything else may not happen at this point!
|
continue;
|
||||||
*/
|
|
||||||
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;
|
|
||||||
|
|
||||||
case DLL_PROCESS_DETACH:
|
MODULE_InitDll( wm, DLL_THREAD_ATTACH, lpReserved );
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 );
|
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.
|
* Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
|
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;
|
WINE_MODREF *wm;
|
||||||
|
BOOL retval = TRUE;
|
||||||
|
|
||||||
EnterCriticalSection( &PROCESS_Current()->crit_section );
|
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 );
|
wm = MODULE32_LookupHMODULE( hModule );
|
||||||
if( wm && ( retv = wm->refCount ) > 0 )
|
if ( !wm )
|
||||||
{
|
retval = FALSE;
|
||||||
wm->refCount--;
|
else
|
||||||
TRACE(module, "(%08x) count now %d\n", hModule, wm->refCount);
|
wm->flags |= WINE_MODREF_NO_DLL_CALLS;
|
||||||
}
|
|
||||||
LeaveCriticalSection( &PROCESS_Current()->crit_section );
|
LeaveCriticalSection( &PROCESS_Current()->crit_section );
|
||||||
|
|
||||||
return retv;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -449,7 +456,7 @@ FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
|
||||||
* the module handle if found
|
* the module handle if found
|
||||||
* 0 if not
|
* 0 if not
|
||||||
*/
|
*/
|
||||||
HMODULE MODULE_FindModule(
|
WINE_MODREF *MODULE_FindModule(
|
||||||
LPCSTR path /* [in] pathname of module/library to be found */
|
LPCSTR path /* [in] pathname of module/library to be found */
|
||||||
) {
|
) {
|
||||||
LPSTR filename;
|
LPSTR filename;
|
||||||
|
@ -477,7 +484,7 @@ HMODULE MODULE_FindModule(
|
||||||
if (!strcasecmp( filename, xmodname)) {
|
if (!strcasecmp( filename, xmodname)) {
|
||||||
HeapFree( GetProcessHeap(), 0, filename );
|
HeapFree( GetProcessHeap(), 0, filename );
|
||||||
HeapFree( GetProcessHeap(), 0, xmodname );
|
HeapFree( GetProcessHeap(), 0, xmodname );
|
||||||
return wm->module;
|
return wm;
|
||||||
}
|
}
|
||||||
if (dotptr) *dotptr='.';
|
if (dotptr) *dotptr='.';
|
||||||
/* FIXME: add paths, shortname */
|
/* FIXME: add paths, shortname */
|
||||||
|
@ -504,14 +511,14 @@ HMODULE MODULE_FindModule(
|
||||||
if (!strcasecmp( filename, xlname)) {
|
if (!strcasecmp( filename, xlname)) {
|
||||||
HeapFree( GetProcessHeap(), 0, filename );
|
HeapFree( GetProcessHeap(), 0, filename );
|
||||||
HeapFree( GetProcessHeap(), 0, xlname );
|
HeapFree( GetProcessHeap(), 0, xlname );
|
||||||
return wm->module;
|
return wm;
|
||||||
}
|
}
|
||||||
if (dotptr) *dotptr='.';
|
if (dotptr) *dotptr='.';
|
||||||
/* FIXME: add paths, shortname */
|
/* FIXME: add paths, shortname */
|
||||||
HeapFree( GetProcessHeap(), 0, xlname );
|
HeapFree( GetProcessHeap(), 0, xlname );
|
||||||
}
|
}
|
||||||
HeapFree( GetProcessHeap(), 0, filename );
|
HeapFree( GetProcessHeap(), 0, filename );
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -1121,10 +1128,14 @@ BOOL WINAPI CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||||
*/
|
*/
|
||||||
HMODULE WINAPI GetModuleHandleA(LPCSTR module)
|
HMODULE WINAPI GetModuleHandleA(LPCSTR module)
|
||||||
{
|
{
|
||||||
if (module == NULL)
|
WINE_MODREF *wm;
|
||||||
return PROCESS_Current()->exe_modref->module;
|
|
||||||
|
if ( module == NULL )
|
||||||
|
wm = PROCESS_Current()->exe_modref;
|
||||||
else
|
else
|
||||||
return MODULE_FindModule( module );
|
wm = MODULE_FindModule( module );
|
||||||
|
|
||||||
|
return wm? wm->module : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
|
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) {
|
if(!libname)
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
{
|
||||||
return 0;
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
}
|
return 0;
|
||||||
hmod = MODULE_LoadLibraryExA( libname, hfile, flags );
|
}
|
||||||
|
|
||||||
if ( hmod >= 32 )
|
wm = MODULE_LoadLibraryExA( libname, hfile, flags );
|
||||||
{
|
|
||||||
/* Initialize DLL just loaded */
|
|
||||||
MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, NULL );
|
|
||||||
/* FIXME: check for failure, SLE(ERROR_DLL_INIT_FAILED) */
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
DWORD err;
|
||||||
|
WINE_MODREF *pwm;
|
||||||
hmod = ELF_LoadLibraryExA( libname, hfile, flags );
|
int i;
|
||||||
if(hmod < (HMODULE)32)
|
module_loadorder_t *plo;
|
||||||
hmod = PE_LoadLibraryExA( libname, hfile, flags );
|
|
||||||
|
|
||||||
if(hmod >= (HMODULE)32)
|
EnterCriticalSection(&PROCESS_Current()->crit_section);
|
||||||
{
|
|
||||||
/* Increment RefCount */
|
|
||||||
MODULE_IncRefCount( hmod );
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MODULE_FreeLibrary (internal)
|
* MODULE_FlushModrefs
|
||||||
*
|
*
|
||||||
* Decrease the loadcount of the dll.
|
* NOTE: Assumes that the process critical section is held!
|
||||||
* If the count reaches 0, then notify the dll and free all dlls
|
|
||||||
* that depend on this one.
|
|
||||||
*
|
*
|
||||||
|
* 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(wm->refCount)
|
||||||
if( MODULE_DecRefCount(wm->module) > 1 )
|
continue;
|
||||||
return;
|
|
||||||
|
|
||||||
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 )
|
* The unloaders are also responsible for freeing the modref itself
|
||||||
|| ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS )
|
* because the loaders were responsible for allocating it.
|
||||||
|| ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) ))
|
*/
|
||||||
{
|
switch(wm->type)
|
||||||
/* Now we can call the initialization routine */
|
{
|
||||||
TRACE( module, "(%s, %08x, %d) - CALL\n", wm->modname, wm->module, first);
|
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 )
|
default:
|
||||||
{
|
ERR(module, "Invalid or unhandled MODREF type %d encountered (wm=%p)\n", wm->type, wm);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* FreeLibrary
|
* FreeLibrary
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
|
BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
|
||||||
{
|
{
|
||||||
|
BOOL retv = TRUE;
|
||||||
WINE_MODREF *wm;
|
WINE_MODREF *wm;
|
||||||
BOOL retval = TRUE;
|
|
||||||
|
|
||||||
EnterCriticalSection(&PROCESS_Current()->crit_section);
|
EnterCriticalSection( &PROCESS_Current()->crit_section );
|
||||||
|
|
||||||
wm = MODULE32_LookupHMODULE(hLibModule);
|
wm = MODULE32_LookupHMODULE( hLibModule );
|
||||||
if(!wm)
|
if ( !wm )
|
||||||
{
|
SetLastError( ERROR_INVALID_HANDLE );
|
||||||
ERR(module, "(%08x) module not found in process' modref_list. Freed too many times?\n", hLibModule);
|
|
||||||
retval = FALSE;
|
|
||||||
}
|
|
||||||
else
|
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 "stackframe.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "loadorder.h"
|
||||||
|
#include "elfdll.h"
|
||||||
|
|
||||||
FARPROC16 (*fnSNOOP16_GetProcAddress16)(HMODULE16,DWORD,FARPROC16) = NULL;
|
FARPROC16 (*fnSNOOP16_GetProcAddress16)(HMODULE16,DWORD,FARPROC16) = NULL;
|
||||||
void (*fnSNOOP16_RegisterDLL)(NE_MODULE*,LPCSTR) = 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. */
|
/* its handle in the list of DLLs to initialize. */
|
||||||
HMODULE16 hDLL;
|
HMODULE16 hDLL;
|
||||||
|
|
||||||
if ((hDLL = NE_LoadModule( buffer, TRUE )) == 2)
|
if ((hDLL = MODULE_LoadModule16( buffer, TRUE )) == 2)
|
||||||
{
|
{
|
||||||
/* file not found */
|
/* file not found */
|
||||||
char *p;
|
char *p;
|
||||||
|
@ -765,7 +767,7 @@ static BOOL NE_LoadDLLs( NE_MODULE *pModule )
|
||||||
if (!(p = strrchr( buffer, '\\' ))) p = buffer;
|
if (!(p = strrchr( buffer, '\\' ))) p = buffer;
|
||||||
memcpy( p + 1, pstr + 1, *pstr );
|
memcpy( p + 1, pstr + 1, *pstr );
|
||||||
strcpy( p + 1 + *pstr, ".dll" );
|
strcpy( p + 1 + *pstr, ".dll" );
|
||||||
hDLL = NE_LoadModule( buffer, TRUE );
|
hDLL = MODULE_LoadModule16( buffer, TRUE );
|
||||||
}
|
}
|
||||||
if (hDLL < 32)
|
if (hDLL < 32)
|
||||||
{
|
{
|
||||||
|
@ -857,23 +859,11 @@ static HINSTANCE16 NE_LoadFileModule( HFILE16 hFile, OFSTRUCT *ofs,
|
||||||
HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit )
|
HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit )
|
||||||
{
|
{
|
||||||
HINSTANCE16 hInstance;
|
HINSTANCE16 hInstance;
|
||||||
HMODULE16 hModule;
|
|
||||||
HFILE16 hFile;
|
HFILE16 hFile;
|
||||||
OFSTRUCT ofs;
|
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)
|
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 */
|
return 2; /* File not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,6 +873,67 @@ HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit )
|
||||||
return hInstance;
|
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)
|
* LoadModule16 (KERNEL.45)
|
||||||
*/
|
*/
|
||||||
|
@ -918,7 +969,7 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
|
||||||
{
|
{
|
||||||
/* Main case: load first instance of NE module */
|
/* Main case: load first instance of NE module */
|
||||||
|
|
||||||
if ( (hInstance = NE_LoadModule( name, FALSE )) < 32 )
|
if ( (hInstance = MODULE_LoadModule16( name, FALSE )) < 32 )
|
||||||
return hInstance;
|
return hInstance;
|
||||||
|
|
||||||
if ( !(pModule = NE_GetPtr( hInstance )) )
|
if ( !(pModule = NE_GetPtr( hInstance )) )
|
||||||
|
|
|
@ -196,7 +196,7 @@ FARPROC PE_FindExportedFunction(
|
||||||
}
|
}
|
||||||
if (forward)
|
if (forward)
|
||||||
{
|
{
|
||||||
HMODULE hMod;
|
WINE_MODREF *wm;
|
||||||
char module[256];
|
char module[256];
|
||||||
char *end = strchr(forward, '.');
|
char *end = strchr(forward, '.');
|
||||||
|
|
||||||
|
@ -204,9 +204,9 @@ FARPROC PE_FindExportedFunction(
|
||||||
assert(end-forward<256);
|
assert(end-forward<256);
|
||||||
strncpy(module, forward, (end - forward));
|
strncpy(module, forward, (end - forward));
|
||||||
module[end-forward] = 0;
|
module[end-forward] = 0;
|
||||||
hMod = MODULE_FindModule( module );
|
wm = MODULE_FindModule( module );
|
||||||
assert(hMod);
|
assert(wm);
|
||||||
return MODULE_GetProcAddress( hMod, end + 1, snoop );
|
return MODULE_GetProcAddress( wm->module, end + 1, snoop );
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,6 @@ FARPROC PE_FindExportedFunction(
|
||||||
DWORD fixup_imports( WINE_MODREF *wm )
|
DWORD fixup_imports( WINE_MODREF *wm )
|
||||||
{
|
{
|
||||||
IMAGE_IMPORT_DESCRIPTOR *pe_imp;
|
IMAGE_IMPORT_DESCRIPTOR *pe_imp;
|
||||||
WINE_MODREF *xwm;
|
|
||||||
PE_MODREF *pem;
|
PE_MODREF *pem;
|
||||||
unsigned int load_addr = wm->module;
|
unsigned int load_addr = wm->module;
|
||||||
int i,characteristics_detection=1;
|
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++) {
|
for (i = 0, pe_imp = pem->pe_import; pe_imp->Name ; pe_imp++) {
|
||||||
HMODULE hImpModule;
|
WINE_MODREF *wmImp;
|
||||||
IMAGE_IMPORT_BY_NAME *pe_name;
|
IMAGE_IMPORT_BY_NAME *pe_name;
|
||||||
PIMAGE_THUNK_DATA import_list,thunk_list;
|
PIMAGE_THUNK_DATA import_list,thunk_list;
|
||||||
char *name = (char *) RVA(pe_imp->Name);
|
char *name = (char *) RVA(pe_imp->Name);
|
||||||
|
@ -265,8 +264,8 @@ DWORD fixup_imports( WINE_MODREF *wm )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* don't use MODULE_Load, Win32 creates new task differently */
|
/* don't use MODULE_Load, Win32 creates new task differently */
|
||||||
hImpModule = MODULE_LoadLibraryExA( name, 0, 0 );
|
wmImp = MODULE_LoadLibraryExA( name, 0, 0 );
|
||||||
if (!hImpModule) {
|
if (!wmImp) {
|
||||||
char *p,buffer[2000];
|
char *p,buffer[2000];
|
||||||
|
|
||||||
/* GetModuleFileName would use the wrong process, so don't use it */
|
/* 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, '\\')))
|
if (!(p = strrchr (buffer, '\\')))
|
||||||
p = buffer;
|
p = buffer;
|
||||||
strcpy (p + 1, name);
|
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);
|
ERR (module, "Module %s not found\n", name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
xwm = MODULE32_LookupHMODULE( hImpModule );
|
wm->deps[i++] = wmImp;
|
||||||
assert( xwm );
|
|
||||||
wm->deps[i++] = xwm;
|
|
||||||
|
|
||||||
/* FIXME: forwarder entries ... */
|
/* FIXME: forwarder entries ... */
|
||||||
|
|
||||||
|
@ -297,7 +294,7 @@ DWORD fixup_imports( WINE_MODREF *wm )
|
||||||
|
|
||||||
TRACE(win32, "--- Ordinal %s,%d\n", name, ordinal);
|
TRACE(win32, "--- Ordinal %s,%d\n", name, ordinal);
|
||||||
thunk_list->u1.Function=MODULE_GetProcAddress(
|
thunk_list->u1.Function=MODULE_GetProcAddress(
|
||||||
hImpModule, (LPCSTR)ordinal, TRUE
|
wmImp->module, (LPCSTR)ordinal, TRUE
|
||||||
);
|
);
|
||||||
if (!thunk_list->u1.Function) {
|
if (!thunk_list->u1.Function) {
|
||||||
ERR(win32,"No implementation for %s.%d, setting to 0xdeadbeef\n",
|
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);
|
pe_name = (PIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData);
|
||||||
TRACE(win32, "--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint);
|
TRACE(win32, "--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint);
|
||||||
thunk_list->u1.Function=MODULE_GetProcAddress(
|
thunk_list->u1.Function=MODULE_GetProcAddress(
|
||||||
hImpModule, pe_name->Name, TRUE
|
wmImp->module, pe_name->Name, TRUE
|
||||||
);
|
);
|
||||||
if (!thunk_list->u1.Function) {
|
if (!thunk_list->u1.Function) {
|
||||||
ERR(win32,"No implementation for %s.%d(%s), setting to 0xdeadbeef\n",
|
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);
|
TRACE(win32,"--- Ordinal %s.%d\n",name,ordinal);
|
||||||
thunk_list->u1.Function=MODULE_GetProcAddress(
|
thunk_list->u1.Function=MODULE_GetProcAddress(
|
||||||
hImpModule, (LPCSTR) ordinal, TRUE
|
wmImp->module, (LPCSTR) ordinal, TRUE
|
||||||
);
|
);
|
||||||
if (!thunk_list->u1.Function) {
|
if (!thunk_list->u1.Function) {
|
||||||
ERR(win32, "No implementation for %s.%d, setting to 0xdeadbeef\n",
|
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",
|
TRACE(win32,"--- %s %s.%d\n",
|
||||||
pe_name->Name,name,pe_name->Hint);
|
pe_name->Name,name,pe_name->Hint);
|
||||||
thunk_list->u1.Function=MODULE_GetProcAddress(
|
thunk_list->u1.Function=MODULE_GetProcAddress(
|
||||||
hImpModule, pe_name->Name, TRUE
|
wmImp->module, pe_name->Name, TRUE
|
||||||
);
|
);
|
||||||
if (!thunk_list->u1.Function) {
|
if (!thunk_list->u1.Function) {
|
||||||
ERR(win32, "No implementation for %s.%d, setting to 0xdeadbeef\n",
|
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.
|
* The PE Library Loader frontend.
|
||||||
* FIXME: handle the flags.
|
* FIXME: handle the flags.
|
||||||
*/
|
*/
|
||||||
HMODULE PE_LoadLibraryExA (LPCSTR name,
|
WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags, DWORD *err)
|
||||||
HFILE hFile, DWORD flags)
|
|
||||||
{
|
{
|
||||||
LPCSTR modName = NULL;
|
LPCSTR modName = NULL;
|
||||||
OFSTRUCT ofs;
|
OFSTRUCT ofs;
|
||||||
HMODULE hModule32;
|
HMODULE hModule32;
|
||||||
HMODULE16 hModule16;
|
HMODULE16 hModule16;
|
||||||
NE_MODULE *pModule;
|
NE_MODULE *pModule;
|
||||||
WINE_MODREF *wm;
|
WINE_MODREF *wm;
|
||||||
BOOL builtin = TRUE;
|
BOOL builtin = TRUE;
|
||||||
char dllname[256], *p;
|
char dllname[256], *p;
|
||||||
|
HFILE hFile;
|
||||||
|
|
||||||
/* Check for already loaded module */
|
/* Append .DLL to name if no extension present */
|
||||||
if ((hModule32 = MODULE_FindModule( name )))
|
strcpy( dllname, name );
|
||||||
return hModule32;
|
if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
|
||||||
|
strcat( dllname, ".DLL" );
|
||||||
|
|
||||||
/* Append .DLL to name if no extension present */
|
/* Load PE module */
|
||||||
strcpy( dllname, name );
|
hFile = OpenFile( dllname, &ofs, OF_READ | OF_SHARE_DENY_WRITE );
|
||||||
if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
|
if ( hFile != HFILE_ERROR )
|
||||||
strcat( dllname, ".DLL" );
|
{
|
||||||
|
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 */
|
/* Create 16-bit dummy module */
|
||||||
if ( !(hModule32 = BUILTIN32_LoadImage( name, &ofs, FALSE )) )
|
if ((hModule16 = MODULE_CreateDummyModule( &ofs, modName )) < 32)
|
||||||
{
|
{
|
||||||
/* Load PE module */
|
*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 );
|
/* Create 32-bit MODREF */
|
||||||
if ( hFile != HFILE_ERROR )
|
if ( !(wm = PE_CreateModule( hModule32, &ofs, flags, builtin )) )
|
||||||
if ( (hModule32 = PE_LoadImage( hFile, &ofs, &modName )) >= 32 )
|
{
|
||||||
builtin = FALSE;
|
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 */
|
*err = 0;
|
||||||
if ( builtin ) {
|
return wm;
|
||||||
if ( (hModule32 = BUILTIN32_LoadImage( name, &ofs, TRUE )) )
|
}
|
||||||
WARN( module, "Could not load external DLL '%s', using built-in module.\n", name );
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Create 16-bit dummy module */
|
/*****************************************************************************
|
||||||
if ((hModule16 = MODULE_CreateDummyModule( &ofs, modName )) < 32) return hModule16;
|
* PE_UnloadLibrary
|
||||||
pModule = (NE_MODULE *)GlobalLock16( hModule16 );
|
*
|
||||||
pModule->flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA |
|
* Unload the library unmapping the image and freeing the modref structure.
|
||||||
NE_FFLAGS_WIN32 | (builtin? NE_FFLAGS_BUILTIN : 0);
|
*/
|
||||||
pModule->module32 = hModule32;
|
void PE_UnloadLibrary(WINE_MODREF *wm)
|
||||||
|
{
|
||||||
/* Create 32-bit MODREF */
|
/* FIXME, do something here */
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
@ -958,18 +963,11 @@ int PE_UnloadImage( HMODULE hModule )
|
||||||
* DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH
|
* DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH
|
||||||
* (SDK)
|
* (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)
|
BOOL retv = TRUE;
|
||||||
return;
|
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? */
|
/* Is this a library? And has it got an entrypoint? */
|
||||||
if ((PE_HEADER(wm->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
|
if ((PE_HEADER(wm->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
|
||||||
(PE_HEADER(wm->module)->OptionalHeader.AddressOfEntryPoint)
|
(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",
|
TRACE(relay, "CallTo32(entryproc=%p,module=%08x,type=%ld,res=%p)\n",
|
||||||
entry, wm->module, type, lpReserved );
|
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);
|
TRACE(global,"oldsize %08lx\n",oldsize);
|
||||||
if (ptr && (size == oldsize)) return handle; /* Nothing to do */
|
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)
|
if (!ptr)
|
||||||
{
|
{
|
||||||
SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 );
|
SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 );
|
||||||
|
|
|
@ -812,10 +812,6 @@ BOOL MAIN_WineInit( int *argc, char *argv[] )
|
||||||
|
|
||||||
MONITOR_Initialize(&MONITOR_PrimaryMonitor);
|
MONITOR_Initialize(&MONITOR_PrimaryMonitor);
|
||||||
|
|
||||||
if (Options.dllFlags)
|
|
||||||
BUILTIN32_ParseDLLOptions( Options.dllFlags );
|
|
||||||
/* if (__winelib && errors ) print_error_message_like_misc_main(); */
|
|
||||||
|
|
||||||
atexit(called_at_exit);
|
atexit(called_at_exit);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,18 +140,6 @@ int main( int argc, char *argv[] )
|
||||||
if (!MAIN_WineInit( &argc, argv )) return 1;
|
if (!MAIN_WineInit( &argc, argv )) return 1;
|
||||||
MAIN_argc = argc; MAIN_argv = argv;
|
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 */
|
/* Set up debugger/instruction emulation callback routines */
|
||||||
ctx_debug_call = ctx_debug;
|
ctx_debug_call = ctx_debug;
|
||||||
fnWINE_Debugger = wine_debug;
|
fnWINE_Debugger = wine_debug;
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "snoop.h"
|
||||||
|
#include "winerror.h"
|
||||||
|
|
||||||
typedef struct
|
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
|
* BUILTIN32_GetEntryPoint
|
||||||
*
|
*
|
||||||
|
@ -435,74 +508,3 @@ void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr, int ordinal )
|
||||||
ExitProcess(1);
|
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 */
|
/* Create 32-bit MODREF */
|
||||||
if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
|
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? */
|
PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0, 0 ); /* FIXME: correct location? */
|
||||||
|
|
||||||
/* Initialize thread-local storage */
|
/* Initialize thread-local storage */
|
||||||
|
@ -497,7 +501,9 @@ void PROCESS_Start(void)
|
||||||
|
|
||||||
/* Now call the entry point */
|
/* 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 );
|
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0, 0 );
|
||||||
|
|
||||||
|
@ -651,7 +657,9 @@ error:
|
||||||
*/
|
*/
|
||||||
void WINAPI ExitProcess( DWORD status )
|
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() ) )
|
if ( THREAD_IsWin16( THREAD_Current() ) )
|
||||||
TASK_KillCurrentTask( status );
|
TASK_KillCurrentTask( status );
|
||||||
|
|
|
@ -281,7 +281,7 @@ static void THREAD_Start(void)
|
||||||
LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point;
|
LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point;
|
||||||
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0, 0 );
|
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0, 0 );
|
||||||
PE_InitTls();
|
PE_InitTls();
|
||||||
MODULE_InitializeDLLs( 0, DLL_THREAD_ATTACH, NULL );
|
MODULE_DllThreadAttach( NULL );
|
||||||
ExitThread( func( thdb->entry_arg ) );
|
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 */
|
void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
|
||||||
{
|
{
|
||||||
MODULE_InitializeDLLs( 0, DLL_THREAD_DETACH, NULL );
|
MODULE_DllThreadDetach( NULL );
|
||||||
TerminateThread( GetCurrentThread(), code );
|
TerminateThread( GetCurrentThread(), code );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue