Converted most of the loader code to Unicode.
This commit is contained in:
parent
1bb7a9f736
commit
f80b869939
|
@ -34,6 +34,7 @@
|
||||||
#include "selectors.h"
|
#include "selectors.h"
|
||||||
#include "builtin16.h"
|
#include "builtin16.h"
|
||||||
#include "kernel_private.h"
|
#include "kernel_private.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
#include "wine/library.h"
|
#include "wine/library.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
@ -76,6 +77,15 @@ DWORD WINAPI CALL32_CBClientEx( FARPROC proc, LPWORD args, DWORD *esi, INT *nArg
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* compare an ASCII and a Unicode string without depending on the current codepage */
|
||||||
|
inline static int strncmpiAW( const char *strA, const WCHAR *strW, int n )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
for ( ; n > 0; n--, strA++, strW++)
|
||||||
|
if ((ret = toupperW((unsigned char)*strA) - toupperW(*strW)) || !*strA) break;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* RELAY_ShowDebugmsgRelay
|
* RELAY_ShowDebugmsgRelay
|
||||||
*
|
*
|
||||||
|
@ -84,12 +94,12 @@ DWORD WINAPI CALL32_CBClientEx( FARPROC proc, LPWORD args, DWORD *esi, INT *nArg
|
||||||
*/
|
*/
|
||||||
static int RELAY_ShowDebugmsgRelay(const char *func)
|
static int RELAY_ShowDebugmsgRelay(const char *func)
|
||||||
{
|
{
|
||||||
/* from relay32/relay386.c */
|
/* from dlls/ntdll/relay.c (FIXME) */
|
||||||
extern const char **debug_relay_excludelist,**debug_relay_includelist;
|
extern const WCHAR **debug_relay_excludelist,**debug_relay_includelist;
|
||||||
|
|
||||||
if(debug_relay_excludelist || debug_relay_includelist) {
|
if(debug_relay_excludelist || debug_relay_includelist) {
|
||||||
const char *term = strchr(func, ':');
|
const char *term = strchr(func, ':');
|
||||||
const char **listitem;
|
const WCHAR **listitem;
|
||||||
int len, len2, itemlen, show;
|
int len, len2, itemlen, show;
|
||||||
|
|
||||||
if(debug_relay_excludelist) {
|
if(debug_relay_excludelist) {
|
||||||
|
@ -105,14 +115,12 @@ static int RELAY_ShowDebugmsgRelay(const char *func)
|
||||||
len2 = strchr(func, '.') - func;
|
len2 = strchr(func, '.') - func;
|
||||||
assert(len2 && len2 > 0 && len2 < 64);
|
assert(len2 && len2 > 0 && len2 < 64);
|
||||||
term += 2;
|
term += 2;
|
||||||
for(; *listitem; listitem++) {
|
for(; *listitem; listitem++)
|
||||||
itemlen = strlen(*listitem);
|
{
|
||||||
if((itemlen == len && !strncasecmp(*listitem, func, len)) ||
|
itemlen = strlenW(*listitem);
|
||||||
(itemlen == len2 && !strncasecmp(*listitem, func, len2)) ||
|
if (itemlen == len && !strncmpiAW(func, *listitem, len)) return !show;
|
||||||
!strcasecmp(*listitem, term)) {
|
if (itemlen == len2 && !strncmpiAW(func, *listitem, len2)) return !show;
|
||||||
show = !show;
|
if (!strncmpiAW(term, *listitem, itemlen) && !term[itemlen]) return !show;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return show;
|
return show;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,6 @@ struct _wine_modref
|
||||||
int nDeps;
|
int nDeps;
|
||||||
struct _wine_modref **deps;
|
struct _wine_modref **deps;
|
||||||
char *filename;
|
char *filename;
|
||||||
char *modname;
|
|
||||||
char data[1]; /* space for storing filename and modname */
|
char data[1]; /* space for storing filename and modname */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,8 +92,9 @@ static CRITICAL_SECTION loader_section = { &critsect_debug, -1, 0, 0, 0, 0 };
|
||||||
static WINE_MODREF *cached_modref;
|
static WINE_MODREF *cached_modref;
|
||||||
static WINE_MODREF *current_modref;
|
static WINE_MODREF *current_modref;
|
||||||
static NTSTATUS last_builtin_status; /* use to gather all errors in callback */
|
static NTSTATUS last_builtin_status; /* use to gather all errors in callback */
|
||||||
|
static const WCHAR *current_load_path;
|
||||||
|
|
||||||
static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm );
|
static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm );
|
||||||
static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
|
static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
|
||||||
DWORD exp_size, const char *name, int hint );
|
DWORD exp_size, const char *name, int hint );
|
||||||
|
|
||||||
|
@ -104,6 +104,18 @@ inline static void *get_rva( HMODULE module, DWORD va )
|
||||||
return (void *)((char *)module + va);
|
return (void *)((char *)module + va);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check whether the file name contains a path */
|
||||||
|
inline static int contains_path( LPCWSTR name )
|
||||||
|
{
|
||||||
|
return ((*name && (name[1] == ':')) || strchrW(name, '/') || strchrW(name, '\\'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert from straight ASCII to Unicode without depending on the current codepage */
|
||||||
|
inline static void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
|
||||||
|
{
|
||||||
|
while (len--) *dst++ = (unsigned char)*src++;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* get_modref
|
* get_modref
|
||||||
*
|
*
|
||||||
|
@ -133,29 +145,29 @@ static WINE_MODREF *get_modref( HMODULE hmod )
|
||||||
* find_module
|
* find_module
|
||||||
*
|
*
|
||||||
* Find a (loaded) win32 module depending on path
|
* Find a (loaded) win32 module depending on path
|
||||||
* LPCSTR path: [in] pathname of module/library to be found
|
* path: [in] pathname of module/library to be found
|
||||||
*
|
*
|
||||||
* The loader_section must be locked while calling this function
|
* The loader_section must be locked while calling this function
|
||||||
* RETURNS
|
* RETURNS
|
||||||
* the module handle if found
|
* the module handle if found
|
||||||
* 0 if not
|
* 0 if not
|
||||||
*/
|
*/
|
||||||
static WINE_MODREF *find_module( LPCSTR path )
|
static WINE_MODREF *find_module( LPCWSTR path )
|
||||||
{
|
{
|
||||||
WINE_MODREF *wm;
|
WINE_MODREF *wm;
|
||||||
PLIST_ENTRY mark, entry;
|
PLIST_ENTRY mark, entry;
|
||||||
PLDR_MODULE mod;
|
PLDR_MODULE mod;
|
||||||
char dllname[260], *p;
|
WCHAR dllname[260], *p;
|
||||||
|
|
||||||
/* Append .DLL to name if no extension present */
|
/* Append .DLL to name if no extension present */
|
||||||
strcpy( dllname, path );
|
strcpyW( dllname, path );
|
||||||
if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
|
if (!(p = strrchrW( dllname, '.')) || strchrW( p, '/' ) || strchrW( p, '\\'))
|
||||||
strcat( dllname, ".DLL" );
|
strcatW( dllname, dllW );
|
||||||
|
|
||||||
if ((wm = cached_modref) != NULL)
|
if ((wm = cached_modref) != NULL)
|
||||||
{
|
{
|
||||||
if ( !FILE_strcasecmp( dllname, wm->modname ) ) return wm;
|
if ( !strcmpiW( dllname, wm->ldr.BaseDllName.Buffer ) ) return wm;
|
||||||
if ( !FILE_strcasecmp( dllname, wm->filename ) ) return wm;
|
if ( !strcmpiW( dllname, wm->ldr.FullDllName.Buffer ) ) return wm;
|
||||||
}
|
}
|
||||||
|
|
||||||
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
|
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
|
||||||
|
@ -164,8 +176,8 @@ static WINE_MODREF *find_module( LPCSTR path )
|
||||||
mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
|
mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
|
||||||
wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
|
wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
|
||||||
|
|
||||||
if ( !FILE_strcasecmp( dllname, wm->modname ) ) break;
|
if ( !strcmpiW( dllname, wm->ldr.BaseDllName.Buffer ) ) break;
|
||||||
if ( !FILE_strcasecmp( dllname, wm->filename ) ) break;
|
if ( !strcmpiW( dllname, wm->ldr.FullDllName.Buffer ) ) break;
|
||||||
}
|
}
|
||||||
if (entry == mark) wm = NULL;
|
if (entry == mark) wm = NULL;
|
||||||
|
|
||||||
|
@ -185,19 +197,19 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward )
|
||||||
IMAGE_EXPORT_DIRECTORY *exports;
|
IMAGE_EXPORT_DIRECTORY *exports;
|
||||||
DWORD exp_size;
|
DWORD exp_size;
|
||||||
WINE_MODREF *wm;
|
WINE_MODREF *wm;
|
||||||
char mod_name[256];
|
WCHAR mod_name[256];
|
||||||
char *end = strchr(forward, '.');
|
char *end = strchr(forward, '.');
|
||||||
FARPROC proc = NULL;
|
FARPROC proc = NULL;
|
||||||
|
|
||||||
if (!end) return NULL;
|
if (!end) return NULL;
|
||||||
if (end - forward >= sizeof(mod_name)) return NULL;
|
if (end - forward >= sizeof(mod_name)/sizeof(WCHAR)) return NULL;
|
||||||
memcpy( mod_name, forward, end - forward );
|
ascii_to_unicode( mod_name, forward, end - forward );
|
||||||
mod_name[end-forward] = 0;
|
mod_name[end - forward] = 0;
|
||||||
|
|
||||||
if (!(wm = find_module( mod_name )))
|
if (!(wm = find_module( mod_name )))
|
||||||
{
|
{
|
||||||
ERR("module not found for forward '%s' used by '%s'\n",
|
ERR("module not found for forward '%s' used by %s\n",
|
||||||
forward, get_modref(module)->filename );
|
forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if ((exports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
|
if ((exports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
|
||||||
|
@ -206,9 +218,10 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward )
|
||||||
|
|
||||||
if (!proc)
|
if (!proc)
|
||||||
{
|
{
|
||||||
ERR("function not found for forward '%s' used by '%s'."
|
ERR("function not found for forward '%s' used by %s."
|
||||||
" If you are using builtin '%s', try using the native one instead.\n",
|
" If you are using builtin %s, try using the native one instead.\n",
|
||||||
forward, get_modref(module)->filename, get_modref(module)->modname );
|
forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer),
|
||||||
|
debugstr_w(get_modref(module)->ldr.BaseDllName.Buffer) );
|
||||||
}
|
}
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
@ -246,7 +259,8 @@ static FARPROC find_ordinal_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *expo
|
||||||
}
|
}
|
||||||
if (TRACE_ON(relay) && current_modref)
|
if (TRACE_ON(relay) && current_modref)
|
||||||
{
|
{
|
||||||
proc = RELAY_GetProcAddress( module, exports, exp_size, proc, current_modref->modname );
|
proc = RELAY_GetProcAddress( module, exports, exp_size, proc,
|
||||||
|
current_modref->ldr.BaseDllName.Buffer );
|
||||||
}
|
}
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
@ -302,17 +316,32 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr )
|
||||||
IMAGE_EXPORT_DIRECTORY *exports;
|
IMAGE_EXPORT_DIRECTORY *exports;
|
||||||
DWORD exp_size;
|
DWORD exp_size;
|
||||||
IMAGE_THUNK_DATA *import_list, *thunk_list;
|
IMAGE_THUNK_DATA *import_list, *thunk_list;
|
||||||
|
WCHAR buffer[32];
|
||||||
char *name = get_rva( module, descr->Name );
|
char *name = get_rva( module, descr->Name );
|
||||||
|
DWORD len = strlen(name) + 1;
|
||||||
|
|
||||||
|
if (len * sizeof(WCHAR) <= sizeof(buffer))
|
||||||
|
{
|
||||||
|
ascii_to_unicode( buffer, name, len );
|
||||||
|
status = load_dll( buffer, 0, &wmImp );
|
||||||
|
}
|
||||||
|
else /* need to allocate a larger buffer */
|
||||||
|
{
|
||||||
|
WCHAR *ptr = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||||
|
if (!ptr) return NULL;
|
||||||
|
ascii_to_unicode( ptr, name, len );
|
||||||
|
status = load_dll( ptr, 0, &wmImp );
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, ptr );
|
||||||
|
}
|
||||||
|
|
||||||
status = load_dll( name, 0, &wmImp );
|
|
||||||
if (status)
|
if (status)
|
||||||
{
|
{
|
||||||
if (status == STATUS_NO_SUCH_FILE)
|
if (status == STATUS_DLL_NOT_FOUND)
|
||||||
ERR("Module (file) %s (which is needed by %s) not found\n",
|
ERR("Module (file) %s (which is needed by %s) not found\n",
|
||||||
name, current_modref->filename);
|
name, debugstr_w(current_modref->ldr.FullDllName.Buffer));
|
||||||
else
|
else
|
||||||
ERR("Loading module (file) %s (which is needed by %s) failed (error %lx).\n",
|
ERR("Loading module (file) %s (which is needed by %s) failed (error %lx).\n",
|
||||||
name, current_modref->filename, status);
|
name, debugstr_w(current_modref->ldr.FullDllName.Buffer), status);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,7 +368,7 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr )
|
||||||
if (!thunk_list->u1.Function)
|
if (!thunk_list->u1.Function)
|
||||||
{
|
{
|
||||||
ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n",
|
ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n",
|
||||||
name, ordinal, current_modref->filename );
|
name, ordinal, debugstr_w(current_modref->ldr.FullDllName.Buffer) );
|
||||||
thunk_list->u1.Function = (PDWORD)0xdeadbeef;
|
thunk_list->u1.Function = (PDWORD)0xdeadbeef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,7 +382,7 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr )
|
||||||
if (!thunk_list->u1.Function)
|
if (!thunk_list->u1.Function)
|
||||||
{
|
{
|
||||||
ERR("No implementation for %s.%s imported from %s, setting to 0xdeadbeef\n",
|
ERR("No implementation for %s.%s imported from %s, setting to 0xdeadbeef\n",
|
||||||
name, pe_name->Name, current_modref->filename );
|
name, pe_name->Name, debugstr_w(current_modref->ldr.FullDllName.Buffer) );
|
||||||
thunk_list->u1.Function = (PDWORD)0xdeadbeef;
|
thunk_list->u1.Function = (PDWORD)0xdeadbeef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,77 +441,104 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm )
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* MODULE_AllocModRef
|
* alloc_module
|
||||||
*
|
*
|
||||||
* Allocate a WINE_MODREF structure and add it to the process list
|
* Allocate a WINE_MODREF structure and add it to the process list
|
||||||
* The loader_section must be locked while calling this function.
|
* The loader_section must be locked while calling this function.
|
||||||
*/
|
*/
|
||||||
WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename )
|
static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
|
||||||
{
|
{
|
||||||
WINE_MODREF *wm;
|
WINE_MODREF *wm;
|
||||||
|
WCHAR *p;
|
||||||
IMAGE_NT_HEADERS *nt = RtlImageNtHeader(hModule);
|
IMAGE_NT_HEADERS *nt = RtlImageNtHeader(hModule);
|
||||||
PLIST_ENTRY entry, mark;
|
PLIST_ENTRY entry, mark;
|
||||||
BOOLEAN linked = FALSE;
|
BOOLEAN linked = FALSE;
|
||||||
DWORD len = strlen( filename ) + 1;
|
DWORD len;
|
||||||
|
|
||||||
if ((wm = RtlAllocateHeap( ntdll_get_process_heap(), HEAP_ZERO_MEMORY, sizeof(*wm) + len )))
|
RtlUnicodeToMultiByteSize( &len, filename, (strlenW(filename) + 1) * sizeof(WCHAR) );
|
||||||
|
if (!(wm = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*wm) + len )))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wm->dlhandle = NULL;
|
||||||
|
wm->nDeps = 0;
|
||||||
|
wm->deps = NULL;
|
||||||
|
wm->filename = (char *)(wm + 1);
|
||||||
|
RtlUnicodeToMultiByteN( wm->filename, len, NULL,
|
||||||
|
filename, (strlenW(filename) + 1) * sizeof(WCHAR) );
|
||||||
|
|
||||||
|
wm->ldr.BaseAddress = hModule;
|
||||||
|
wm->ldr.EntryPoint = (nt->OptionalHeader.AddressOfEntryPoint) ?
|
||||||
|
((char *)hModule + nt->OptionalHeader.AddressOfEntryPoint) : 0;
|
||||||
|
wm->ldr.SizeOfImage = nt->OptionalHeader.SizeOfImage;
|
||||||
|
wm->ldr.Flags = 0;
|
||||||
|
wm->ldr.LoadCount = 0;
|
||||||
|
wm->ldr.TlsIndex = -1;
|
||||||
|
wm->ldr.SectionHandle = NULL;
|
||||||
|
wm->ldr.CheckSum = 0;
|
||||||
|
wm->ldr.TimeDateStamp = 0;
|
||||||
|
|
||||||
|
RtlCreateUnicodeString( &wm->ldr.FullDllName, filename );
|
||||||
|
if ((p = strrchrW( wm->ldr.FullDllName.Buffer, '\\' ))) p++;
|
||||||
|
else p = wm->ldr.FullDllName.Buffer;
|
||||||
|
RtlInitUnicodeString( &wm->ldr.BaseDllName, p );
|
||||||
|
|
||||||
|
/* this is a bit ugly, but we need to have app module first in LoadOrder
|
||||||
|
* list, But in wine, ntdll is loaded first, so by inserting DLLs at the tail
|
||||||
|
* and app module at the head we insure that order
|
||||||
|
*/
|
||||||
|
if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
|
||||||
{
|
{
|
||||||
wm->filename = (char *)(wm + 1);
|
/* is first loaded module a DLL or an exec ? */
|
||||||
memcpy( wm->filename, filename, len );
|
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
|
||||||
if ((wm->modname = strrchr( wm->filename, '\\' ))) wm->modname++;
|
if (mark->Flink == mark ||
|
||||||
else wm->modname = wm->filename;
|
(CONTAINING_RECORD(mark->Flink, LDR_MODULE, InLoadOrderModuleList)->Flags & LDR_IMAGE_IS_DLL))
|
||||||
|
|
||||||
wm->ldr.BaseAddress = hModule;
|
|
||||||
wm->ldr.EntryPoint = (nt->OptionalHeader.AddressOfEntryPoint) ?
|
|
||||||
((char *)hModule + nt->OptionalHeader.AddressOfEntryPoint) : 0;
|
|
||||||
wm->ldr.SizeOfImage = nt->OptionalHeader.SizeOfImage;
|
|
||||||
RtlCreateUnicodeStringFromAsciiz( &wm->ldr.FullDllName, wm->filename);
|
|
||||||
RtlCreateUnicodeStringFromAsciiz( &wm->ldr.BaseDllName, wm->modname);
|
|
||||||
wm->ldr.Flags = 0;
|
|
||||||
wm->ldr.LoadCount = 0;
|
|
||||||
wm->ldr.TlsIndex = -1;
|
|
||||||
wm->ldr.SectionHandle = NULL;
|
|
||||||
wm->ldr.CheckSum = 0;
|
|
||||||
wm->ldr.TimeDateStamp = 0;
|
|
||||||
|
|
||||||
/* this is a bit ugly, but we need to have app module first in LoadOrder
|
|
||||||
* list, But in wine, ntdll is loaded first, so by inserting DLLs at the tail
|
|
||||||
* and app module at the head we insure that order
|
|
||||||
*/
|
|
||||||
if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
|
|
||||||
{
|
{
|
||||||
/* is first loaded module a DLL or an exec ? */
|
InsertHeadList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
|
||||||
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
|
|
||||||
if (mark->Flink == mark ||
|
|
||||||
(CONTAINING_RECORD(mark->Flink, LDR_MODULE, InLoadOrderModuleList)->Flags & LDR_IMAGE_IS_DLL))
|
|
||||||
{
|
|
||||||
InsertHeadList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
|
|
||||||
&wm->ldr.InLoadOrderModuleList);
|
|
||||||
linked = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else wm->ldr.Flags |= LDR_IMAGE_IS_DLL;
|
|
||||||
|
|
||||||
if (!linked)
|
|
||||||
InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
|
|
||||||
&wm->ldr.InLoadOrderModuleList);
|
&wm->ldr.InLoadOrderModuleList);
|
||||||
|
linked = TRUE;
|
||||||
/* insert module in MemoryList, sorted in increasing base addresses */
|
|
||||||
mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
|
|
||||||
for (entry = mark->Flink; entry != mark; entry = entry->Flink)
|
|
||||||
{
|
|
||||||
if (CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList)->BaseAddress > wm->ldr.BaseAddress)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
entry->Blink->Flink = &wm->ldr.InMemoryOrderModuleList;
|
|
||||||
wm->ldr.InMemoryOrderModuleList.Blink = entry->Blink;
|
|
||||||
wm->ldr.InMemoryOrderModuleList.Flink = entry;
|
|
||||||
entry->Blink = &wm->ldr.InMemoryOrderModuleList;
|
|
||||||
|
|
||||||
/* wait until init is called for inserting into this list */
|
|
||||||
wm->ldr.InInitializationOrderModuleList.Flink = NULL;
|
|
||||||
wm->ldr.InInitializationOrderModuleList.Blink = NULL;
|
|
||||||
}
|
}
|
||||||
|
else wm->ldr.Flags |= LDR_IMAGE_IS_DLL;
|
||||||
|
|
||||||
|
if (!linked)
|
||||||
|
InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
|
||||||
|
&wm->ldr.InLoadOrderModuleList);
|
||||||
|
|
||||||
|
/* insert module in MemoryList, sorted in increasing base addresses */
|
||||||
|
mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
|
||||||
|
for (entry = mark->Flink; entry != mark; entry = entry->Flink)
|
||||||
|
{
|
||||||
|
if (CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList)->BaseAddress > wm->ldr.BaseAddress)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
entry->Blink->Flink = &wm->ldr.InMemoryOrderModuleList;
|
||||||
|
wm->ldr.InMemoryOrderModuleList.Blink = entry->Blink;
|
||||||
|
wm->ldr.InMemoryOrderModuleList.Flink = entry;
|
||||||
|
entry->Blink = &wm->ldr.InMemoryOrderModuleList;
|
||||||
|
|
||||||
|
/* wait until init is called for inserting into this list */
|
||||||
|
wm->ldr.InInitializationOrderModuleList.Flink = NULL;
|
||||||
|
wm->ldr.InInitializationOrderModuleList.Blink = NULL;
|
||||||
|
return wm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* MODULE_AllocModRef
|
||||||
|
*
|
||||||
|
* Allocate a WINE_MODREF structure and add it to the process list
|
||||||
|
* The loader_section must be locked while calling this function.
|
||||||
|
*
|
||||||
|
* FIXME: should be removed.
|
||||||
|
*/
|
||||||
|
WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename )
|
||||||
|
{
|
||||||
|
WINE_MODREF *wm;
|
||||||
|
UNICODE_STRING strW;
|
||||||
|
|
||||||
|
RtlCreateUnicodeStringFromAsciiz( &strW, filename );
|
||||||
|
wm = alloc_module( hModule, strW.Buffer );
|
||||||
|
RtlFreeUnicodeString( &strW );
|
||||||
return wm;
|
return wm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,7 +663,7 @@ static void call_tls_callbacks( HMODULE module, UINT reason )
|
||||||
*/
|
*/
|
||||||
static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
|
static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
|
||||||
{
|
{
|
||||||
char mod_name[32];
|
WCHAR mod_name[32];
|
||||||
BOOL retv = TRUE;
|
BOOL retv = TRUE;
|
||||||
DLLENTRYPROC entry = wm->ldr.EntryPoint;
|
DLLENTRYPROC entry = wm->ldr.EntryPoint;
|
||||||
void *module = wm->ldr.BaseAddress;
|
void *module = wm->ldr.BaseAddress;
|
||||||
|
@ -620,13 +676,15 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
|
||||||
|
|
||||||
if (TRACE_ON(relay))
|
if (TRACE_ON(relay))
|
||||||
{
|
{
|
||||||
size_t len = max( strlen(wm->modname), sizeof(mod_name)-1 );
|
size_t len = max( wm->ldr.BaseDllName.Length, sizeof(mod_name)-sizeof(WCHAR) );
|
||||||
memcpy( mod_name, wm->modname, len );
|
memcpy( mod_name, wm->ldr.BaseDllName.Buffer, len );
|
||||||
mod_name[len] = 0;
|
mod_name[len / sizeof(WCHAR)] = 0;
|
||||||
DPRINTF("%04lx:Call PE DLL (proc=%p,module=%p (%s),reason=%s,res=%p)\n",
|
DPRINTF("%04lx:Call PE DLL (proc=%p,module=%p %s,reason=%s,res=%p)\n",
|
||||||
GetCurrentThreadId(), entry, module, mod_name, reason_names[reason], lpReserved );
|
GetCurrentThreadId(), entry, module, debugstr_w(mod_name),
|
||||||
|
reason_names[reason], lpReserved );
|
||||||
}
|
}
|
||||||
else TRACE("(%p (%s),%s,%p) - CALL\n", module, wm->modname, reason_names[reason], lpReserved );
|
else TRACE("(%p %s,%s,%p) - CALL\n", module, debugstr_w(wm->ldr.BaseDllName.Buffer),
|
||||||
|
reason_names[reason], lpReserved );
|
||||||
|
|
||||||
retv = entry( module, reason, lpReserved );
|
retv = entry( module, reason, lpReserved );
|
||||||
|
|
||||||
|
@ -634,8 +692,9 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
|
||||||
to the dll. We cannot assume that this module has not been
|
to the dll. We cannot assume that this module has not been
|
||||||
deleted. */
|
deleted. */
|
||||||
if (TRACE_ON(relay))
|
if (TRACE_ON(relay))
|
||||||
DPRINTF("%04lx:Ret PE DLL (proc=%p,module=%p (%s),reason=%s,res=%p) retval=%x\n",
|
DPRINTF("%04lx:Ret PE DLL (proc=%p,module=%p %s,reason=%s,res=%p) retval=%x\n",
|
||||||
GetCurrentThreadId(), entry, module, mod_name, reason_names[reason], lpReserved, retv );
|
GetCurrentThreadId(), entry, module, debugstr_w(mod_name),
|
||||||
|
reason_names[reason], lpReserved, retv );
|
||||||
else TRACE("(%p,%s,%p) - RETURN %d\n", module, reason_names[reason], lpReserved, retv );
|
else TRACE("(%p,%s,%p) - RETURN %d\n", module, reason_names[reason], lpReserved, retv );
|
||||||
|
|
||||||
return retv;
|
return retv;
|
||||||
|
@ -698,7 +757,7 @@ NTSTATUS MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
|
||||||
|| ( wm->ldr.Flags & LDR_PROCESS_ATTACHED ) )
|
|| ( wm->ldr.Flags & LDR_PROCESS_ATTACHED ) )
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
TRACE("(%s,%p) - START\n", wm->modname, lpReserved );
|
TRACE("(%s,%p) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
|
||||||
|
|
||||||
/* Tag current MODREF to prevent recursive loop */
|
/* Tag current MODREF to prevent recursive loop */
|
||||||
wm->ldr.Flags |= LDR_LOAD_IN_PROGRESS;
|
wm->ldr.Flags |= LDR_LOAD_IN_PROGRESS;
|
||||||
|
@ -728,7 +787,7 @@ NTSTATUS MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
|
||||||
/* Remove recursion flag */
|
/* Remove recursion flag */
|
||||||
wm->ldr.Flags &= ~LDR_LOAD_IN_PROGRESS;
|
wm->ldr.Flags &= ~LDR_LOAD_IN_PROGRESS;
|
||||||
|
|
||||||
TRACE("(%s,%p) - END\n", wm->modname, lpReserved );
|
TRACE("(%s,%p) - END\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
|
||||||
|
|
||||||
done:
|
done:
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
RtlLeaveCriticalSection( &loader_section );
|
||||||
|
@ -899,7 +958,7 @@ NTSTATUS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG magic )
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* LdrGetDllHandle (NTDLL.@)
|
* LdrGetDllHandle (NTDLL.@)
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI LdrGetDllHandle(ULONG x, ULONG y, PUNICODE_STRING name, HMODULE *base)
|
NTSTATUS WINAPI LdrGetDllHandle(ULONG x, ULONG y, const UNICODE_STRING *name, HMODULE *base)
|
||||||
{
|
{
|
||||||
NTSTATUS status = STATUS_DLL_NOT_FOUND;
|
NTSTATUS status = STATUS_DLL_NOT_FOUND;
|
||||||
WCHAR dllname[MAX_PATH+4], *p;
|
WCHAR dllname[MAX_PATH+4], *p;
|
||||||
|
@ -957,7 +1016,8 @@ done:
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* LdrGetProcedureAddress (NTDLL.@)
|
* LdrGetProcedureAddress (NTDLL.@)
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, PANSI_STRING name, ULONG ord, PVOID *address)
|
NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name,
|
||||||
|
ULONG ord, PVOID *address)
|
||||||
{
|
{
|
||||||
IMAGE_EXPORT_DIRECTORY *exports;
|
IMAGE_EXPORT_DIRECTORY *exports;
|
||||||
DWORD exp_size;
|
DWORD exp_size;
|
||||||
|
@ -996,7 +1056,7 @@ static void load_builtin_callback( void *module, const char *filename )
|
||||||
{
|
{
|
||||||
IMAGE_NT_HEADERS *nt;
|
IMAGE_NT_HEADERS *nt;
|
||||||
WINE_MODREF *wm;
|
WINE_MODREF *wm;
|
||||||
char *fullname;
|
WCHAR *fullname, *p;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
|
|
||||||
if (!module)
|
if (!module)
|
||||||
|
@ -1018,25 +1078,22 @@ static void load_builtin_callback( void *module, const char *filename )
|
||||||
return; /* don't create the modref here, will be done later on */
|
return; /* don't create the modref here, will be done later on */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (find_module( filename ))
|
|
||||||
MESSAGE( "Warning: loading builtin %s, but native version already present. "
|
|
||||||
"Expect trouble.\n", filename );
|
|
||||||
|
|
||||||
/* create the MODREF */
|
/* create the MODREF */
|
||||||
|
|
||||||
len = GetSystemDirectoryA( NULL, 0 );
|
len = GetSystemDirectoryW( NULL, 0 );
|
||||||
if (!(fullname = RtlAllocateHeap( ntdll_get_process_heap(), 0, len + strlen(filename) + 1 )))
|
if (!(fullname = RtlAllocateHeap( GetProcessHeap(), 0,
|
||||||
|
(len + strlen(filename) + 1) * sizeof(WCHAR) )))
|
||||||
{
|
{
|
||||||
ERR( "can't load %s\n", filename );
|
ERR( "can't load %s\n", filename );
|
||||||
last_builtin_status = STATUS_NO_MEMORY;
|
last_builtin_status = STATUS_NO_MEMORY;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GetSystemDirectoryA( fullname, len );
|
p = fullname + GetSystemDirectoryW( fullname, len );
|
||||||
strcat( fullname, "\\" );
|
*p++ = '\\';
|
||||||
strcat( fullname, filename );
|
ascii_to_unicode( p, filename, strlen(filename) + 1 );
|
||||||
|
|
||||||
wm = MODULE_AllocModRef( module, fullname );
|
wm = alloc_module( module, fullname );
|
||||||
RtlFreeHeap( ntdll_get_process_heap(), 0, fullname );
|
RtlFreeHeap( GetProcessHeap(), 0, fullname );
|
||||||
if (!wm)
|
if (!wm)
|
||||||
{
|
{
|
||||||
ERR( "can't load %s\n", filename );
|
ERR( "can't load %s\n", filename );
|
||||||
|
@ -1085,27 +1142,26 @@ static void load_builtin_callback( void *module, const char *filename )
|
||||||
* portion of the provided name and put the name in it.
|
* portion of the provided name and put the name in it.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static LPCSTR allocate_lib_dir(LPCSTR libname)
|
static WCHAR *allocate_lib_dir(LPCWSTR libname)
|
||||||
{
|
{
|
||||||
LPCSTR p, pmax;
|
LPCWSTR p, pmax;
|
||||||
LPSTR result;
|
LPWSTR result;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
pmax = libname;
|
pmax = libname;
|
||||||
if ((p = strrchr( pmax, '\\' ))) pmax = p + 1;
|
if ((p = strrchrW( pmax, '\\' ))) pmax = p + 1;
|
||||||
if ((p = strrchr( pmax, '/' ))) pmax = p + 1; /* Naughty. MSDN says don't */
|
if ((p = strrchrW( pmax, '/' ))) pmax = p + 1; /* Naughty. MSDN says don't */
|
||||||
if (pmax == libname && pmax[0] && pmax[1] == ':') pmax += 2;
|
if (pmax == libname && pmax[0] && pmax[1] == ':') pmax += 2;
|
||||||
|
|
||||||
length = pmax - libname;
|
length = pmax - libname;
|
||||||
|
|
||||||
result = RtlAllocateHeap (ntdll_get_process_heap(), 0, length+1);
|
result = RtlAllocateHeap (GetProcessHeap(), 0, (length+1) * sizeof(WCHAR) );
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
strncpy (result, libname, length);
|
memcpy( result, libname, length * sizeof(WCHAR) );
|
||||||
result [length] = '\0';
|
result [length] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1113,7 +1169,7 @@ static LPCSTR allocate_lib_dir(LPCSTR libname)
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* load_native_dll (internal)
|
* load_native_dll (internal)
|
||||||
*/
|
*/
|
||||||
static NTSTATUS load_native_dll( LPCSTR name, DWORD flags, WINE_MODREF** pwm )
|
static NTSTATUS load_native_dll( LPCWSTR name, DWORD flags, WINE_MODREF** pwm )
|
||||||
{
|
{
|
||||||
void *module;
|
void *module;
|
||||||
HANDLE file, mapping;
|
HANDLE file, mapping;
|
||||||
|
@ -1125,15 +1181,15 @@ static NTSTATUS load_native_dll( LPCSTR name, DWORD flags, WINE_MODREF** pwm )
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
UINT drive_type;
|
UINT drive_type;
|
||||||
|
|
||||||
file = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
|
file = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
|
||||||
if (file == INVALID_HANDLE_VALUE)
|
if (file == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
/* keep it that way until we transform CreateFile into NtCreateFile */
|
/* keep it that way until we transform CreateFile into NtCreateFile */
|
||||||
return (GetLastError() == ERROR_FILE_NOT_FOUND) ?
|
return (GetLastError() == ERROR_FILE_NOT_FOUND) ?
|
||||||
STATUS_NO_SUCH_FILE : STATUS_INTERNAL_ERROR;
|
STATUS_DLL_NOT_FOUND : STATUS_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE( "loading %s\n", debugstr_a(name) );
|
TRACE( "loading %s\n", debugstr_w(name) );
|
||||||
|
|
||||||
attr.Length = sizeof(attr);
|
attr.Length = sizeof(attr);
|
||||||
attr.RootDirectory = 0;
|
attr.RootDirectory = 0;
|
||||||
|
@ -1155,7 +1211,7 @@ static NTSTATUS load_native_dll( LPCSTR name, DWORD flags, WINE_MODREF** pwm )
|
||||||
|
|
||||||
/* create the MODREF */
|
/* create the MODREF */
|
||||||
|
|
||||||
if (!(wm = MODULE_AllocModRef( module, name )))
|
if (!(wm = alloc_module( module, name )))
|
||||||
{
|
{
|
||||||
status = STATUS_NO_MEMORY;
|
status = STATUS_NO_MEMORY;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -1186,7 +1242,7 @@ static NTSTATUS load_native_dll( LPCSTR name, DWORD flags, WINE_MODREF** pwm )
|
||||||
/* send DLL load event */
|
/* send DLL load event */
|
||||||
|
|
||||||
nt = RtlImageNtHeader( module );
|
nt = RtlImageNtHeader( module );
|
||||||
drive_type = GetDriveTypeA( wm->filename );
|
drive_type = GetDriveTypeW( wm->ldr.FullDllName.Buffer );
|
||||||
|
|
||||||
SERVER_START_REQ( load_dll )
|
SERVER_START_REQ( load_dll )
|
||||||
{
|
{
|
||||||
|
@ -1213,28 +1269,89 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* get_builtin_path
|
||||||
|
*
|
||||||
|
* Get the path of a builtin module when the native file does not exist.
|
||||||
|
*/
|
||||||
|
static BOOL get_builtin_path( const WCHAR *libname, WCHAR *filename, UINT size )
|
||||||
|
{
|
||||||
|
WCHAR *p;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
UINT len = GetSystemDirectoryW( filename, size );
|
||||||
|
|
||||||
|
if (contains_path( libname ))
|
||||||
|
{
|
||||||
|
WCHAR *tmp;
|
||||||
|
|
||||||
|
/* if the library name contains a path and can not be found,
|
||||||
|
* return an error.
|
||||||
|
* exception: if the path is the system directory, proceed,
|
||||||
|
* so that modules which are not PE modules can be loaded.
|
||||||
|
* If the library name does not contain a path and can not
|
||||||
|
* be found, assume the system directory is meant */
|
||||||
|
|
||||||
|
if (strlenW(libname) >= size) return FALSE; /* too long */
|
||||||
|
if (strchrW( libname, '/' )) /* need to convert slashes */
|
||||||
|
{
|
||||||
|
if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0,
|
||||||
|
(strlenW(libname)+1) * sizeof(WCHAR) ))) return FALSE;
|
||||||
|
strcpyW( tmp, libname );
|
||||||
|
for (p = tmp; *p; p++) if (*p == '/') *p = '\\';
|
||||||
|
}
|
||||||
|
else tmp = (WCHAR *)libname;
|
||||||
|
|
||||||
|
if (!strncmpiW( filename, tmp, len ) && tmp[len] == '\\')
|
||||||
|
{
|
||||||
|
strcpyW( filename, tmp );
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
if (tmp != libname) RtlFreeHeap( GetProcessHeap(), 0, tmp );
|
||||||
|
if (!ret) return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (strlenW(libname) >= size - len - 1) return FALSE;
|
||||||
|
filename[len] = '\\';
|
||||||
|
strcpyW( filename+len+1, libname );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if the filename doesn't have an extension, append ".dll" */
|
||||||
|
if (!(p = strrchrW( filename, '.')) || strchrW( p, '/' ) || strchrW( p, '\\'))
|
||||||
|
{
|
||||||
|
if (strlenW(filename) + 3 >= size) return FALSE;
|
||||||
|
strcatW( filename, dllW );
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* load_builtin_dll
|
* load_builtin_dll
|
||||||
*/
|
*/
|
||||||
static NTSTATUS load_builtin_dll( LPCSTR path, DWORD flags, WINE_MODREF** pwm )
|
static NTSTATUS load_builtin_dll( LPCWSTR path, DWORD flags, WINE_MODREF** pwm )
|
||||||
{
|
{
|
||||||
char error[256], dllname[MAX_PATH], *p;
|
char error[256], dllname[MAX_PATH];
|
||||||
int file_exists;
|
int file_exists;
|
||||||
LPCSTR name;
|
const WCHAR *name, *p;
|
||||||
|
DWORD len, i;
|
||||||
void *handle;
|
void *handle;
|
||||||
WINE_MODREF *wm;
|
WINE_MODREF *wm;
|
||||||
|
|
||||||
/* Fix the name in case we have a full path and extension */
|
/* Fix the name in case we have a full path and extension */
|
||||||
name = path;
|
name = path;
|
||||||
if ((p = strrchr( name, '\\' ))) name = p + 1;
|
if ((p = strrchrW( name, '\\' ))) name = p + 1;
|
||||||
if ((p = strrchr( name, '/' ))) name = p + 1;
|
if ((p = strrchrW( name, '/' ))) name = p + 1;
|
||||||
|
|
||||||
if (strlen(name) >= sizeof(dllname)-4) return STATUS_NO_SUCH_FILE;
|
/* we don't want to depend on the current codepage here */
|
||||||
|
len = strlenW( name ) + 1;
|
||||||
strcpy( dllname, name );
|
if (len >= sizeof(dllname)) return STATUS_NAME_TOO_LONG;
|
||||||
p = strrchr( dllname, '.' );
|
for (i = 0; i < len; i++)
|
||||||
if (!p) strcat( dllname, ".dll" );
|
{
|
||||||
for (p = dllname; *p; p++) *p = FILE_tolower(*p);
|
if (name[i] > 127) return STATUS_DLL_NOT_FOUND;
|
||||||
|
dllname[i] = (char)name[i];
|
||||||
|
if (dllname[i] >= 'A' && dllname[i] <= 'Z') dllname[i] += 'a' - 'A';
|
||||||
|
}
|
||||||
|
|
||||||
last_builtin_status = STATUS_SUCCESS;
|
last_builtin_status = STATUS_SUCCESS;
|
||||||
/* load_library will modify last_builtin_status. Note also that load_library can be
|
/* load_library will modify last_builtin_status. Note also that load_library can be
|
||||||
|
@ -1247,19 +1364,20 @@ static NTSTATUS load_builtin_dll( LPCSTR path, DWORD flags, WINE_MODREF** pwm )
|
||||||
if (!file_exists)
|
if (!file_exists)
|
||||||
{
|
{
|
||||||
/* The file does not exist -> WARN() */
|
/* The file does not exist -> WARN() */
|
||||||
WARN("cannot open .so lib for builtin %s: %s\n", name, error);
|
WARN("cannot open .so lib for builtin %s: %s\n", debugstr_w(name), error);
|
||||||
return STATUS_NO_SUCH_FILE;
|
return STATUS_DLL_NOT_FOUND;
|
||||||
}
|
}
|
||||||
/* ERR() for all other errors (missing functions, ...) */
|
/* ERR() for all other errors (missing functions, ...) */
|
||||||
ERR("failed to load .so lib for builtin %s: %s\n", name, error );
|
ERR("failed to load .so lib for builtin %s: %s\n", debugstr_w(name), error );
|
||||||
return STATUS_PROCEDURE_NOT_FOUND;
|
return STATUS_PROCEDURE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
if (last_builtin_status != STATUS_SUCCESS) return last_builtin_status;
|
if (last_builtin_status != STATUS_SUCCESS) return last_builtin_status;
|
||||||
|
|
||||||
if (!(wm = find_module( path ))) wm = find_module( dllname );
|
if (!(wm = find_module( path ))) wm = find_module( name );
|
||||||
if (!wm)
|
if (!wm)
|
||||||
{
|
{
|
||||||
ERR( "loaded .so but dll %s still not found - 16-bit dll or version conflict.\n", dllname );
|
ERR( "loaded .so but dll %s still not found - 16-bit dll or version conflict.\n",
|
||||||
|
debugstr_w(name) );
|
||||||
/* wine_dll_unload( handle );*/
|
/* wine_dll_unload( handle );*/
|
||||||
return STATUS_INVALID_IMAGE_FORMAT;
|
return STATUS_INVALID_IMAGE_FORMAT;
|
||||||
}
|
}
|
||||||
|
@ -1284,29 +1402,27 @@ static NTSTATUS load_builtin_dll( LPCSTR path, DWORD flags, WINE_MODREF** pwm )
|
||||||
* information from BUILTIN32_dlopen through dlopen and the builtin's
|
* information from BUILTIN32_dlopen through dlopen and the builtin's
|
||||||
* init function into load_library).
|
* init function into load_library).
|
||||||
* allocated_libdir is TRUE in the stack frame that allocated libdir
|
* allocated_libdir is TRUE in the stack frame that allocated libdir
|
||||||
|
*
|
||||||
|
* The loader_section must be locked while calling this function.
|
||||||
*/
|
*/
|
||||||
static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm )
|
static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
enum loadorder_type loadorder[LOADORDER_NTYPES];
|
enum loadorder_type loadorder[LOADORDER_NTYPES];
|
||||||
LPSTR filename;
|
WCHAR *filename;
|
||||||
const char *filetype = "";
|
const char *filetype = "";
|
||||||
DWORD found;
|
DWORD found;
|
||||||
WINE_MODREF *main_exe;
|
WINE_MODREF *main_exe;
|
||||||
BOOL allocated_libdir = FALSE;
|
BOOL allocated_libdir = FALSE;
|
||||||
static LPCSTR libdir = NULL; /* See above */
|
static WCHAR *libdir = NULL; /* See above */
|
||||||
NTSTATUS nts = STATUS_NO_SUCH_FILE;
|
NTSTATUS nts = STATUS_DLL_NOT_FOUND;
|
||||||
|
|
||||||
*pwm = NULL;
|
*pwm = NULL;
|
||||||
if ( !libname ) return STATUS_DLL_NOT_FOUND; /* FIXME ? */
|
filename = RtlAllocateHeap ( GetProcessHeap(), 0, (MAX_PATH + 1) * sizeof(WCHAR) );
|
||||||
|
|
||||||
filename = RtlAllocateHeap ( ntdll_get_process_heap(), 0, MAX_PATH + 1 );
|
|
||||||
if ( !filename ) return STATUS_NO_MEMORY;
|
if ( !filename ) return STATUS_NO_MEMORY;
|
||||||
*filename = 0; /* Just in case we don't set it before goto error */
|
*filename = 0; /* Just in case we don't set it before goto error */
|
||||||
|
|
||||||
RtlEnterCriticalSection( &loader_section );
|
if ((flags & LOAD_WITH_ALTERED_SEARCH_PATH) && contains_path(libname))
|
||||||
|
|
||||||
if ((flags & LOAD_WITH_ALTERED_SEARCH_PATH) && FILE_contains_path(libname))
|
|
||||||
{
|
{
|
||||||
if (!(libdir = allocate_lib_dir(libname)))
|
if (!(libdir = allocate_lib_dir(libname)))
|
||||||
{
|
{
|
||||||
|
@ -1317,14 +1433,14 @@ static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm )
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!libdir || allocated_libdir)
|
if (!libdir || allocated_libdir)
|
||||||
found = SearchPathA(NULL, libname, ".dll", MAX_PATH, filename, NULL);
|
found = SearchPathW(NULL, libname, dllW, MAX_PATH, filename, NULL);
|
||||||
else
|
else
|
||||||
found = DIR_SearchAlternatePath(libdir, libname, ".dll", MAX_PATH, filename, NULL);
|
found = DIR_SearchAlternatePath(libdir, libname, dllW, MAX_PATH, filename);
|
||||||
|
|
||||||
/* build the modules filename */
|
/* build the modules filename */
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
if (!MODULE_GetBuiltinPath( libname, ".dll", filename, MAX_PATH ))
|
if (!get_builtin_path( libname, filename, MAX_PATH ))
|
||||||
{
|
{
|
||||||
nts = STATUS_INTERNAL_ERROR;
|
nts = STATUS_INTERNAL_ERROR;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1332,9 +1448,9 @@ static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for already loaded module */
|
/* Check for already loaded module */
|
||||||
if (!(*pwm = find_module(filename)) && !FILE_contains_path(libname))
|
if (!(*pwm = find_module(filename)) && !contains_path(libname))
|
||||||
{
|
{
|
||||||
LPSTR fn = RtlAllocateHeap ( ntdll_get_process_heap(), 0, MAX_PATH + 1 );
|
LPWSTR fn = RtlAllocateHeap ( GetProcessHeap(), 0, (MAX_PATH + 1) * sizeof(WCHAR) );
|
||||||
if (fn)
|
if (fn)
|
||||||
{
|
{
|
||||||
/* since the default loading mechanism uses a more detailed algorithm
|
/* since the default loading mechanism uses a more detailed algorithm
|
||||||
|
@ -1344,14 +1460,15 @@ static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm )
|
||||||
* has already been loaded but with a different path. So do a specific
|
* has already been loaded but with a different path. So do a specific
|
||||||
* look-up with filename (without any path)
|
* look-up with filename (without any path)
|
||||||
*/
|
*/
|
||||||
strcpy ( fn, libname );
|
strcpyW ( fn, libname );
|
||||||
/* if the filename doesn't have an extension append .DLL */
|
/* if the filename doesn't have an extension append .DLL */
|
||||||
if (!strrchr( fn, '.')) strcat( fn, ".dll" );
|
if (!strrchrW( fn, '.')) strcatW( fn, dllW );
|
||||||
if ((*pwm = find_module( fn )) != NULL)
|
if ((*pwm = find_module( fn )) != NULL)
|
||||||
strcpy( filename, fn );
|
strcpyW( filename, fn );
|
||||||
RtlFreeHeap( ntdll_get_process_heap(), 0, fn );
|
RtlFreeHeap( GetProcessHeap(), 0, fn );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*pwm)
|
if (*pwm)
|
||||||
{
|
{
|
||||||
if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
|
if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
|
||||||
|
@ -1362,19 +1479,19 @@ static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm )
|
||||||
(*pwm)->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
|
(*pwm)->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
|
||||||
fixup_imports( *pwm );
|
fixup_imports( *pwm );
|
||||||
}
|
}
|
||||||
TRACE("Already loaded module '%s' at %p, count=%d\n", filename, (*pwm)->ldr.BaseAddress, (*pwm)->ldr.LoadCount);
|
|
||||||
if (allocated_libdir)
|
if (allocated_libdir)
|
||||||
{
|
{
|
||||||
RtlFreeHeap( ntdll_get_process_heap(), 0, (LPSTR)libdir );
|
RtlFreeHeap( GetProcessHeap(), 0, libdir );
|
||||||
libdir = NULL;
|
libdir = NULL;
|
||||||
}
|
}
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
TRACE("Already loaded module %s at %p, count=%d\n",
|
||||||
RtlFreeHeap( ntdll_get_process_heap(), 0, filename );
|
debugstr_w(filename), (*pwm)->ldr.BaseAddress, (*pwm)->ldr.LoadCount);
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
|
main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
|
||||||
MODULE_GetLoadOrderA( loadorder, main_exe->ldr.BaseDllName.Buffer, filename, TRUE);
|
MODULE_GetLoadOrderW( loadorder, main_exe->ldr.BaseDllName.Buffer, filename, TRUE);
|
||||||
|
|
||||||
for (i = 0; i < LOADORDER_NTYPES; i++)
|
for (i = 0; i < LOADORDER_NTYPES; i++)
|
||||||
{
|
{
|
||||||
|
@ -1383,12 +1500,12 @@ static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm )
|
||||||
switch (loadorder[i])
|
switch (loadorder[i])
|
||||||
{
|
{
|
||||||
case LOADORDER_DLL:
|
case LOADORDER_DLL:
|
||||||
TRACE("Trying native dll '%s'\n", filename);
|
TRACE("Trying native dll %s\n", debugstr_w(filename));
|
||||||
nts = load_native_dll(filename, flags, pwm);
|
nts = load_native_dll(filename, flags, pwm);
|
||||||
filetype = "native";
|
filetype = "native";
|
||||||
break;
|
break;
|
||||||
case LOADORDER_BI:
|
case LOADORDER_BI:
|
||||||
TRACE("Trying built-in '%s'\n", filename);
|
TRACE("Trying built-in %s\n", debugstr_w(filename));
|
||||||
nts = load_builtin_dll(filename, flags, pwm);
|
nts = load_builtin_dll(filename, flags, pwm);
|
||||||
filetype = "builtin";
|
filetype = "builtin";
|
||||||
break;
|
break;
|
||||||
|
@ -1400,27 +1517,27 @@ static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm )
|
||||||
if (nts == STATUS_SUCCESS)
|
if (nts == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Initialize DLL just loaded */
|
/* Initialize DLL just loaded */
|
||||||
TRACE("Loaded module '%s' (%s) at %p\n", filename, filetype, (*pwm)->ldr.BaseAddress);
|
TRACE("Loaded module %s (%s) at %p\n",
|
||||||
|
debugstr_w(filename), filetype, (*pwm)->ldr.BaseAddress);
|
||||||
if (!TRACE_ON(module))
|
if (!TRACE_ON(module))
|
||||||
TRACE_(loaddll)("Loaded module '%s' : %s\n", filename, filetype);
|
TRACE_(loaddll)("Loaded module %s : %s\n", debugstr_w(filename), filetype);
|
||||||
/* Set the ldr.LoadCount here so that an attach failure will */
|
/* Set the ldr.LoadCount here so that an attach failure will */
|
||||||
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
||||||
(*pwm)->ldr.LoadCount = 1;
|
(*pwm)->ldr.LoadCount = 1;
|
||||||
|
|
||||||
if (allocated_libdir)
|
if (allocated_libdir)
|
||||||
{
|
{
|
||||||
RtlFreeHeap( ntdll_get_process_heap(), 0, (LPSTR)libdir );
|
RtlFreeHeap( GetProcessHeap(), 0, libdir );
|
||||||
libdir = NULL;
|
libdir = NULL;
|
||||||
}
|
}
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||||
RtlFreeHeap( ntdll_get_process_heap(), 0, filename );
|
|
||||||
return nts;
|
return nts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nts != STATUS_NO_SUCH_FILE)
|
if (nts != STATUS_DLL_NOT_FOUND)
|
||||||
{
|
{
|
||||||
WARN("Loading of %s DLL %s failed (status %lx).\n",
|
WARN("Loading of %s DLL %s failed (status %lx).\n",
|
||||||
filetype, filename, nts);
|
filetype, debugstr_w(filename), nts);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1428,52 +1545,44 @@ static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm )
|
||||||
error:
|
error:
|
||||||
if (allocated_libdir)
|
if (allocated_libdir)
|
||||||
{
|
{
|
||||||
RtlFreeHeap( ntdll_get_process_heap(), 0, (LPSTR)libdir );
|
RtlFreeHeap( GetProcessHeap(), 0, libdir );
|
||||||
libdir = NULL;
|
libdir = NULL;
|
||||||
}
|
}
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
WARN("Failed to load module %s; status=%lx\n", debugstr_w(filename), nts);
|
||||||
WARN("Failed to load module '%s'; status=%lx\n", filename, nts);
|
RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||||
RtlFreeHeap( ntdll_get_process_heap(), 0, filename );
|
|
||||||
return nts;
|
return nts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* LdrLoadDll (NTDLL.@)
|
* LdrLoadDll (NTDLL.@)
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags, PUNICODE_STRING libname, HMODULE* hModule)
|
NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags,
|
||||||
|
const UNICODE_STRING *libname, HMODULE* hModule)
|
||||||
{
|
{
|
||||||
WINE_MODREF *wm;
|
WINE_MODREF *wm;
|
||||||
NTSTATUS nts = STATUS_SUCCESS;
|
NTSTATUS nts;
|
||||||
STRING str;
|
const WCHAR *prev_load_path;
|
||||||
|
|
||||||
RtlUnicodeStringToAnsiString(&str, libname, TRUE);
|
|
||||||
|
|
||||||
RtlEnterCriticalSection( &loader_section );
|
RtlEnterCriticalSection( &loader_section );
|
||||||
|
|
||||||
switch (nts = load_dll( str.Buffer, flags, &wm ))
|
prev_load_path = current_load_path;
|
||||||
|
current_load_path = path_name;
|
||||||
|
nts = load_dll( libname->Buffer, flags, &wm );
|
||||||
|
current_load_path = prev_load_path;
|
||||||
|
|
||||||
|
if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
|
||||||
{
|
{
|
||||||
case STATUS_SUCCESS:
|
|
||||||
nts = MODULE_DllProcessAttach( wm, NULL );
|
nts = MODULE_DllProcessAttach( wm, NULL );
|
||||||
if (nts != STATUS_SUCCESS)
|
if (nts != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
WARN("Attach failed for module '%s'.\n", str.Buffer);
|
WARN("Attach failed for module %s\n", debugstr_w(libname->Buffer));
|
||||||
LdrUnloadDll(wm->ldr.BaseAddress);
|
LdrUnloadDll(wm->ldr.BaseAddress);
|
||||||
wm = NULL;
|
wm = NULL;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case STATUS_NO_SUCH_FILE:
|
|
||||||
nts = STATUS_DLL_NOT_FOUND;
|
|
||||||
break;
|
|
||||||
default: /* keep error code as it is (memory...) */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*hModule = (wm) ? wm->ldr.BaseAddress : NULL;
|
*hModule = (wm) ? wm->ldr.BaseAddress : NULL;
|
||||||
|
|
||||||
RtlLeaveCriticalSection( &loader_section );
|
RtlLeaveCriticalSection( &loader_section );
|
||||||
|
|
||||||
RtlFreeAnsiString(&str);
|
|
||||||
|
|
||||||
return nts;
|
return nts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1595,27 +1704,29 @@ static void MODULE_FlushModrefs(void)
|
||||||
wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
|
wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
|
||||||
|
|
||||||
prev = entry->Blink;
|
prev = entry->Blink;
|
||||||
if (wm->ldr.LoadCount) continue;
|
if (mod->LoadCount) continue;
|
||||||
|
|
||||||
RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
|
RemoveEntryList(&mod->InLoadOrderModuleList);
|
||||||
RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
|
RemoveEntryList(&mod->InMemoryOrderModuleList);
|
||||||
RemoveEntryList(&wm->ldr.InInitializationOrderModuleList);
|
RemoveEntryList(&mod->InInitializationOrderModuleList);
|
||||||
|
|
||||||
TRACE(" unloading %s\n", wm->filename);
|
TRACE(" unloading %s\n", debugstr_w(mod->FullDllName.Buffer));
|
||||||
if (!TRACE_ON(module))
|
if (!TRACE_ON(module))
|
||||||
TRACE_(loaddll)("Unloaded module '%s' : %s\n", wm->filename,
|
TRACE_(loaddll)("Unloaded module %s : %s\n",
|
||||||
|
debugstr_w(mod->FullDllName.Buffer),
|
||||||
wm->dlhandle ? "builtin" : "native" );
|
wm->dlhandle ? "builtin" : "native" );
|
||||||
|
|
||||||
SERVER_START_REQ( unload_dll )
|
SERVER_START_REQ( unload_dll )
|
||||||
{
|
{
|
||||||
req->base = wm->ldr.BaseAddress;
|
req->base = mod->BaseAddress;
|
||||||
wine_server_call( req );
|
wine_server_call( req );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
if (wm->dlhandle) wine_dll_unload( wm->dlhandle );
|
if (wm->dlhandle) wine_dll_unload( wm->dlhandle );
|
||||||
else NtUnmapViewOfSection( GetCurrentProcess(), wm->ldr.BaseAddress );
|
else NtUnmapViewOfSection( GetCurrentProcess(), mod->BaseAddress );
|
||||||
if (cached_modref == wm) cached_modref = NULL;
|
if (cached_modref == wm) cached_modref = NULL;
|
||||||
|
RtlFreeUnicodeString( &mod->FullDllName );
|
||||||
RtlFreeHeap( ntdll_get_process_heap(), 0, wm->deps );
|
RtlFreeHeap( ntdll_get_process_heap(), 0, wm->deps );
|
||||||
RtlFreeHeap( ntdll_get_process_heap(), 0, wm );
|
RtlFreeHeap( ntdll_get_process_heap(), 0, wm );
|
||||||
}
|
}
|
||||||
|
@ -1637,7 +1748,7 @@ static void MODULE_DecRefCount( WINE_MODREF *wm )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
--wm->ldr.LoadCount;
|
--wm->ldr.LoadCount;
|
||||||
TRACE("(%s) ldr.LoadCount: %d\n", wm->modname, wm->ldr.LoadCount );
|
TRACE("(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
|
||||||
|
|
||||||
if ( wm->ldr.LoadCount == 0 )
|
if ( wm->ldr.LoadCount == 0 )
|
||||||
{
|
{
|
||||||
|
@ -1674,7 +1785,7 @@ NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
|
||||||
free_lib_count++;
|
free_lib_count++;
|
||||||
if ((wm = get_modref( hModule )) != NULL)
|
if ((wm = get_modref( hModule )) != NULL)
|
||||||
{
|
{
|
||||||
TRACE("(%s) - START\n", wm->modname);
|
TRACE("(%s) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer));
|
||||||
|
|
||||||
/* Recursively decrement reference counts */
|
/* Recursively decrement reference counts */
|
||||||
MODULE_DecRefCount( wm );
|
MODULE_DecRefCount( wm );
|
||||||
|
|
|
@ -41,7 +41,7 @@ extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handl
|
||||||
|
|
||||||
/* module handling */
|
/* module handling */
|
||||||
extern FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
|
extern FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
|
||||||
DWORD exp_size, FARPROC proc, const char *user );
|
DWORD exp_size, FARPROC proc, const WCHAR *user );
|
||||||
extern FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
|
extern FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size,
|
||||||
FARPROC origfun, DWORD ordinal );
|
FARPROC origfun, DWORD ordinal );
|
||||||
extern void RELAY_SetupDLL( HMODULE hmod );
|
extern void RELAY_SetupDLL( HMODULE hmod );
|
||||||
|
|
|
@ -41,46 +41,59 @@ WINE_DEFAULT_DEBUG_CHANNEL(relay);
|
||||||
WINE_DECLARE_DEBUG_CHANNEL(snoop);
|
WINE_DECLARE_DEBUG_CHANNEL(snoop);
|
||||||
WINE_DECLARE_DEBUG_CHANNEL(seh);
|
WINE_DECLARE_DEBUG_CHANNEL(seh);
|
||||||
|
|
||||||
const char **debug_relay_excludelist = NULL;
|
const WCHAR **debug_relay_excludelist = NULL;
|
||||||
const char **debug_relay_includelist = NULL;
|
const WCHAR **debug_relay_includelist = NULL;
|
||||||
const char **debug_snoop_excludelist = NULL;
|
const WCHAR **debug_snoop_excludelist = NULL;
|
||||||
const char **debug_snoop_includelist = NULL;
|
const WCHAR **debug_snoop_includelist = NULL;
|
||||||
|
|
||||||
static const char **debug_from_relay_excludelist;
|
static const WCHAR **debug_from_relay_excludelist;
|
||||||
static const char **debug_from_relay_includelist;
|
static const WCHAR **debug_from_relay_includelist;
|
||||||
|
|
||||||
|
/* compare an ASCII and a Unicode string without depending on the current codepage */
|
||||||
|
inline static int strcmpAW( const char *strA, const WCHAR *strW )
|
||||||
|
{
|
||||||
|
while (*strA && ((unsigned char)*strA == *strW)) { strA++; strW++; }
|
||||||
|
return (unsigned char)*strA - *strW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compare an ASCII and a Unicode string without depending on the current codepage */
|
||||||
|
inline static int strncmpiAW( const char *strA, const WCHAR *strW, int n )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
for ( ; n > 0; n--, strA++, strW++)
|
||||||
|
if ((ret = toupperW((unsigned char)*strA) - toupperW(*strW)) || !*strA) break;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* build_list
|
* build_list
|
||||||
*
|
*
|
||||||
* Build a function list from a ';'-separated string.
|
* Build a function list from a ';'-separated string.
|
||||||
*/
|
*/
|
||||||
static const char **build_list( const WCHAR *bufferW )
|
static const WCHAR **build_list( const WCHAR *buffer )
|
||||||
{
|
{
|
||||||
int count = 1;
|
int count = 1;
|
||||||
char buffer[1024];
|
const WCHAR *p = buffer;
|
||||||
const char *p = buffer;
|
const WCHAR **ret;
|
||||||
const char **ret;
|
|
||||||
|
|
||||||
RtlUnicodeToMultiByteN( buffer, sizeof(buffer), NULL,
|
while ((p = strchrW( p, ';' )))
|
||||||
bufferW, (strlenW(bufferW)+1) * sizeof(WCHAR) );
|
|
||||||
|
|
||||||
while ((p = strchr( p, ';' )))
|
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
/* allocate count+1 pointers, plus the space for a copy of the string */
|
/* allocate count+1 pointers, plus the space for a copy of the string */
|
||||||
if ((ret = RtlAllocateHeap( ntdll_get_process_heap(), 0, (count+1) * sizeof(char*) + strlen(buffer) + 1 )))
|
if ((ret = RtlAllocateHeap( GetProcessHeap(), 0,
|
||||||
|
(count+1) * sizeof(WCHAR*) + (strlenW(buffer)+1) * sizeof(WCHAR) )))
|
||||||
{
|
{
|
||||||
char *str = (char *)(ret + count + 1);
|
WCHAR *str = (WCHAR *)(ret + count + 1);
|
||||||
char *p = str;
|
WCHAR *p = str;
|
||||||
|
|
||||||
strcpy( str, buffer );
|
strcpyW( str, buffer );
|
||||||
count = 0;
|
count = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
ret[count++] = p;
|
ret[count++] = p;
|
||||||
if (!(p = strchr( p, ';' ))) break;
|
if (!(p = strchrW( p, ';' ))) break;
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
}
|
}
|
||||||
ret[count++] = NULL;
|
ret[count++] = NULL;
|
||||||
|
@ -253,7 +266,7 @@ static WINE_EXCEPTION_FILTER(page_fault)
|
||||||
*/
|
*/
|
||||||
static BOOL check_relay_include( const char *module, const char *func )
|
static BOOL check_relay_include( const char *module, const char *func )
|
||||||
{
|
{
|
||||||
const char **listitem;
|
const WCHAR **listitem;
|
||||||
BOOL show;
|
BOOL show;
|
||||||
|
|
||||||
if (!debug_relay_excludelist && !debug_relay_includelist) return TRUE;
|
if (!debug_relay_excludelist && !debug_relay_includelist) return TRUE;
|
||||||
|
@ -269,16 +282,17 @@ static BOOL check_relay_include( const char *module, const char *func )
|
||||||
}
|
}
|
||||||
for(; *listitem; listitem++)
|
for(; *listitem; listitem++)
|
||||||
{
|
{
|
||||||
char *p = strrchr( *listitem, '.' );
|
WCHAR *p = strrchrW( *listitem, '.' );
|
||||||
if (p && p > *listitem) /* check module and function */
|
if (p && p > *listitem) /* check module and function */
|
||||||
{
|
{
|
||||||
int len = p - *listitem;
|
int len = p - *listitem;
|
||||||
if (strncasecmp( *listitem, module, len-1 ) || module[len]) continue;
|
if (strncmpiAW( module, *listitem, len-1 ) || module[len]) continue;
|
||||||
if (!strcmp( p + 1, func ) || !strcmp( p + 1, "*" )) return !show;
|
if (p[1] == '*' && !p[2]) return !show;
|
||||||
|
if (!strcmpAW( func, p + 1 )) return !show;
|
||||||
}
|
}
|
||||||
else /* function only */
|
else /* function only */
|
||||||
{
|
{
|
||||||
if (!strcmp( *listitem, func )) return !show;
|
if (!strcmpAW( func, *listitem )) return !show;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return show;
|
return show;
|
||||||
|
@ -290,9 +304,10 @@ static BOOL check_relay_include( const char *module, const char *func )
|
||||||
*
|
*
|
||||||
* Check if calls from a given module must be included in the relay output.
|
* Check if calls from a given module must be included in the relay output.
|
||||||
*/
|
*/
|
||||||
static BOOL check_relay_from_module( const char *module )
|
static BOOL check_relay_from_module( const WCHAR *module )
|
||||||
{
|
{
|
||||||
const char **listitem;
|
static const WCHAR dllW[] = {'.','d','l','l',0 };
|
||||||
|
const WCHAR **listitem;
|
||||||
BOOL show;
|
BOOL show;
|
||||||
|
|
||||||
if (!debug_from_relay_excludelist && !debug_from_relay_includelist) return TRUE;
|
if (!debug_from_relay_excludelist && !debug_from_relay_includelist) return TRUE;
|
||||||
|
@ -310,9 +325,9 @@ static BOOL check_relay_from_module( const char *module )
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (!strcasecmp( *listitem, module )) return !show;
|
if (!strcmpiW( *listitem, module )) return !show;
|
||||||
len = strlen( *listitem );
|
len = strlenW( *listitem );
|
||||||
if (!strncasecmp( *listitem, module, len ) && !strcasecmp( module + len, ".dll" ))
|
if (!strncmpiW( *listitem, module, len ) && !strcmpiW( module + len, dllW ))
|
||||||
return !show;
|
return !show;
|
||||||
}
|
}
|
||||||
return show;
|
return show;
|
||||||
|
@ -676,7 +691,7 @@ static BOOL is_register_entry_point( const BYTE *addr )
|
||||||
* Return the proc address to use for a given function.
|
* Return the proc address to use for a given function.
|
||||||
*/
|
*/
|
||||||
FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
|
FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
|
||||||
DWORD exp_size, FARPROC proc, const char *user )
|
DWORD exp_size, FARPROC proc, const WCHAR *user )
|
||||||
{
|
{
|
||||||
DEBUG_ENTRY_POINT *debug = (DEBUG_ENTRY_POINT *)proc;
|
DEBUG_ENTRY_POINT *debug = (DEBUG_ENTRY_POINT *)proc;
|
||||||
DEBUG_ENTRY_POINT *list = (DEBUG_ENTRY_POINT *)((char *)exports + exp_size);
|
DEBUG_ENTRY_POINT *list = (DEBUG_ENTRY_POINT *)((char *)exports + exp_size);
|
||||||
|
@ -749,10 +764,10 @@ void RELAY_SetupDLL( HMODULE module )
|
||||||
* Simple function to decide if a particular debugging message is
|
* Simple function to decide if a particular debugging message is
|
||||||
* wanted.
|
* wanted.
|
||||||
*/
|
*/
|
||||||
int SNOOP_ShowDebugmsgSnoop(const char *dll, int ord, const char *fname) {
|
int SNOOP_ShowDebugmsgSnoop(const char *dll, int ord, const char *fname)
|
||||||
|
{
|
||||||
if(debug_snoop_excludelist || debug_snoop_includelist) {
|
if(debug_snoop_excludelist || debug_snoop_includelist) {
|
||||||
const char **listitem;
|
const WCHAR **listitem;
|
||||||
char buf[80];
|
char buf[80];
|
||||||
int len, len2, itemlen, show;
|
int len, len2, itemlen, show;
|
||||||
|
|
||||||
|
@ -767,14 +782,13 @@ int SNOOP_ShowDebugmsgSnoop(const char *dll, int ord, const char *fname) {
|
||||||
assert(len < 64);
|
assert(len < 64);
|
||||||
sprintf(buf, "%s.%d", dll, ord);
|
sprintf(buf, "%s.%d", dll, ord);
|
||||||
len2 = strlen(buf);
|
len2 = strlen(buf);
|
||||||
for(; *listitem; listitem++) {
|
for(; *listitem; listitem++)
|
||||||
itemlen = strlen(*listitem);
|
{
|
||||||
if((itemlen == len && !strncasecmp(*listitem, buf, len)) ||
|
itemlen = strlenW(*listitem);
|
||||||
(itemlen == len2 && !strncasecmp(*listitem, buf, len2)) ||
|
if((itemlen == len && !strncmpiAW( buf, *listitem, len)) ||
|
||||||
!strcasecmp(*listitem, fname)) {
|
(itemlen == len2 && !strncmpiAW(buf, *listitem, len2)) ||
|
||||||
show = !show;
|
!strcmpAW(fname, *listitem))
|
||||||
break;
|
return !show;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return show;
|
return show;
|
||||||
}
|
}
|
||||||
|
@ -1089,7 +1103,7 @@ __ASM_GLOBAL_FUNC( SNOOP_Return,
|
||||||
#else /* __i386__ */
|
#else /* __i386__ */
|
||||||
|
|
||||||
FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
|
FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
|
||||||
DWORD exp_size, FARPROC proc, const char *user )
|
DWORD exp_size, FARPROC proc, const WCHAR *user )
|
||||||
{
|
{
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1053,8 +1053,6 @@ static BOOL search_alternate_path(LPCWSTR dll_path, LPCWSTR name, LPCWSTR ext,
|
||||||
* contain an extension.
|
* contain an extension.
|
||||||
* buflen [I] size of buffer, in characters
|
* buflen [I] size of buffer, in characters
|
||||||
* buffer [O] buffer for found filename
|
* buffer [O] buffer for found filename
|
||||||
* lastpart [O] address of pointer to last used character in
|
|
||||||
* buffer (the final '\') (May be NULL)
|
|
||||||
*
|
*
|
||||||
* RETURNS
|
* RETURNS
|
||||||
* Success: length of string copied into buffer, not including
|
* Success: length of string copied into buffer, not including
|
||||||
|
@ -1068,39 +1066,20 @@ static BOOL search_alternate_path(LPCWSTR dll_path, LPCWSTR name, LPCWSTR ext,
|
||||||
*
|
*
|
||||||
* FIXME: convert to unicode
|
* FIXME: convert to unicode
|
||||||
*/
|
*/
|
||||||
DWORD DIR_SearchAlternatePath( LPCSTR dll_path, LPCSTR name, LPCSTR ext,
|
DWORD DIR_SearchAlternatePath( LPCWSTR dll_path, LPCWSTR name, LPCWSTR ext,
|
||||||
DWORD buflen, LPSTR buffer, LPSTR *lastpart )
|
DWORD buflen, LPWSTR buffer )
|
||||||
{
|
{
|
||||||
LPSTR p;
|
|
||||||
DOS_FULL_NAME full_name;
|
DOS_FULL_NAME full_name;
|
||||||
DWORD ret = 0;
|
DWORD ret = 0;
|
||||||
UNICODE_STRING dll_pathW, nameW, extW;
|
|
||||||
|
|
||||||
if (dll_path) RtlCreateUnicodeStringFromAsciiz(&dll_pathW, dll_path);
|
if (search_alternate_path( dll_path, name, ext, &full_name))
|
||||||
else dll_pathW.Buffer = NULL;
|
|
||||||
if (name) RtlCreateUnicodeStringFromAsciiz(&nameW, name);
|
|
||||||
else nameW.Buffer = NULL;
|
|
||||||
if (ext) RtlCreateUnicodeStringFromAsciiz(&extW, ext);
|
|
||||||
else extW.Buffer = NULL;
|
|
||||||
|
|
||||||
if (search_alternate_path( dll_pathW.Buffer, nameW.Buffer, extW.Buffer, &full_name))
|
|
||||||
{
|
{
|
||||||
ret = WideCharToMultiByte(CP_ACP, 0, full_name.short_name, -1, NULL, 0, NULL, NULL);
|
lstrcpynW( buffer, full_name.short_name, buflen );
|
||||||
if (buflen >= ret)
|
ret = strlenW(buffer);
|
||||||
{
|
|
||||||
WideCharToMultiByte(CP_ACP, 0, full_name.short_name, -1, buffer, buflen, NULL, NULL);
|
|
||||||
for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
|
|
||||||
if (lastpart) *lastpart = strrchr( buffer, '\\' ) + 1;
|
|
||||||
ret--; /* length without 0 */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||||
|
|
||||||
RtlFreeUnicodeString(&dll_pathW);
|
|
||||||
RtlFreeUnicodeString(&nameW);
|
|
||||||
RtlFreeUnicodeString(&extW);
|
|
||||||
|
|
||||||
TRACE("Returning %ld\n", ret );
|
TRACE("Returning %ld\n", ret );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,8 +91,8 @@ extern LONG WINAPI WIN16_hread(HFILE16,SEGPTR,LONG);
|
||||||
extern int DIR_Init(void);
|
extern int DIR_Init(void);
|
||||||
extern UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count );
|
extern UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count );
|
||||||
extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count );
|
extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count );
|
||||||
extern DWORD DIR_SearchAlternatePath( LPCSTR dll_path, LPCSTR name, LPCSTR ext,
|
extern DWORD DIR_SearchAlternatePath( LPCWSTR dll_path, LPCWSTR name, LPCWSTR ext,
|
||||||
DWORD buflen, LPSTR buffer, LPSTR *lastpart);
|
DWORD buflen, LPWSTR buffer);
|
||||||
extern DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
|
extern DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
|
||||||
DOS_FULL_NAME *full_name, BOOL win32 );
|
DOS_FULL_NAME *full_name, BOOL win32 );
|
||||||
|
|
||||||
|
|
|
@ -950,6 +950,9 @@ void WINAPIV DbgPrint(LPCSTR fmt, ...);
|
||||||
NTSTATUS WINAPI LdrAccessResource(HMODULE,const IMAGE_RESOURCE_DATA_ENTRY*,void**,PULONG);
|
NTSTATUS WINAPI LdrAccessResource(HMODULE,const IMAGE_RESOURCE_DATA_ENTRY*,void**,PULONG);
|
||||||
NTSTATUS WINAPI LdrFindResourceDirectory_U(HMODULE,const LDR_RESOURCE_INFO*,ULONG,const IMAGE_RESOURCE_DIRECTORY**);
|
NTSTATUS WINAPI LdrFindResourceDirectory_U(HMODULE,const LDR_RESOURCE_INFO*,ULONG,const IMAGE_RESOURCE_DIRECTORY**);
|
||||||
NTSTATUS WINAPI LdrFindResource_U(HMODULE,const LDR_RESOURCE_INFO*,ULONG,const IMAGE_RESOURCE_DATA_ENTRY**);
|
NTSTATUS WINAPI LdrFindResource_U(HMODULE,const LDR_RESOURCE_INFO*,ULONG,const IMAGE_RESOURCE_DATA_ENTRY**);
|
||||||
|
NTSTATUS WINAPI LdrGetDllHandle(ULONG, ULONG, const UNICODE_STRING*, HMODULE*);
|
||||||
|
NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, const ANSI_STRING*, ULONG, void**);
|
||||||
|
NTSTATUS WINAPI LdrLoadDll(LPCWSTR, DWORD, const UNICODE_STRING*, HMODULE*);
|
||||||
void WINAPI LdrShutdownProcess(void);
|
void WINAPI LdrShutdownProcess(void);
|
||||||
void WINAPI LdrShutdownThread(void);
|
void WINAPI LdrShutdownThread(void);
|
||||||
NTSTATUS WINAPI NtAccessCheck(PSECURITY_DESCRIPTOR,HANDLE,ACCESS_MASK,PGENERIC_MAPPING,PPRIVILEGE_SET,PULONG,PULONG,PBOOLEAN);
|
NTSTATUS WINAPI NtAccessCheck(PSECURITY_DESCRIPTOR,HANDLE,ACCESS_MASK,PGENERIC_MAPPING,PPRIVILEGE_SET,PULONG,PULONG,PBOOLEAN);
|
||||||
|
@ -1404,9 +1407,6 @@ typedef struct _SYSTEM_MODULE_INFORMATION
|
||||||
|
|
||||||
NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE);
|
NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE);
|
||||||
NTSTATUS WINAPI LdrFindEntryForAddress(const void*, PLDR_MODULE*);
|
NTSTATUS WINAPI LdrFindEntryForAddress(const void*, PLDR_MODULE*);
|
||||||
NTSTATUS WINAPI LdrGetDllHandle(ULONG, ULONG, PUNICODE_STRING, HMODULE*);
|
|
||||||
NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, PANSI_STRING, ULONG, void**);
|
|
||||||
NTSTATUS WINAPI LdrLoadDll(LPCWSTR, DWORD, PUNICODE_STRING, HMODULE*);
|
|
||||||
NTSTATUS WINAPI LdrLockLoaderLock(ULONG,ULONG*,ULONG*);
|
NTSTATUS WINAPI LdrLockLoaderLock(ULONG,ULONG*,ULONG*);
|
||||||
NTSTATUS WINAPI LdrQueryProcessModuleInformation(SYSTEM_MODULE_INFORMATION*, ULONG, ULONG*);
|
NTSTATUS WINAPI LdrQueryProcessModuleInformation(SYSTEM_MODULE_INFORMATION*, ULONG, ULONG*);
|
||||||
NTSTATUS WINAPI LdrUnloadDll(HMODULE);
|
NTSTATUS WINAPI LdrUnloadDll(HMODULE);
|
||||||
|
|
Loading…
Reference in New Issue