diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index fb0a60dcc0d..668744c1ecb 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -57,6 +57,7 @@ static WINE_EXCEPTION_FILTER(page_fault) static CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" ); static WINE_MODREF *cached_modref; +static WINE_MODREF *current_modref; static NTSTATUS load_dll( LPCSTR libname, DWORD flags, WINE_MODREF** pwm ); static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports, @@ -114,8 +115,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward ) if (!(wm = MODULE_FindModule( mod_name ))) { - WINE_MODREF *user = get_modref( module ); - ERR("module not found for forward '%s' used by '%s'\n", forward, user->filename ); + ERR("module not found for forward '%s' used by '%s'\n", forward, current_modref->filename ); return NULL; } if ((exports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE, @@ -124,10 +124,9 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward ) if (!proc) { - WINE_MODREF *user = get_modref( module ); ERR("function not found for forward '%s' used by '%s'." " If you are using builtin '%s', try using the native one instead.\n", - forward, user->filename, user->modname ); + forward, current_modref->filename, current_modref->modname ); } return proc; } @@ -144,7 +143,6 @@ static FARPROC find_ordinal_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *expo DWORD exp_size, int ordinal ) { FARPROC proc; - WORD *ordinals = get_rva( module, exports->AddressOfNameOrdinals ); DWORD *functions = get_rva( module, exports->AddressOfFunctions ); if (ordinal >= exports->NumberOfFunctions) @@ -162,19 +160,11 @@ static FARPROC find_ordinal_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *expo if (TRACE_ON(snoop)) { - /* try to find a name for it */ - int i; - char *ename = "@"; - DWORD *name = get_rva( module, exports->AddressOfNames ); - if (name) for (i = 0; i < exports->NumberOfNames; i++) - { - if (ordinals[i] == ordinal) - { - ename = get_rva( module, name[i] ); - break; - } - } - proc = SNOOP_GetProcAddress( module, ename, ordinal, proc ); + proc = SNOOP_GetProcAddress( module, exports, exp_size, proc, ordinal ); + } + if (TRACE_ON(relay) && current_modref) + { + proc = RELAY_GetProcAddress( module, exports, exp_size, proc, current_modref->modname ); } return proc; } @@ -235,12 +225,12 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr ) status = load_dll( name, 0, &wmImp ); if (status) { - WINE_MODREF *user = get_modref( module ); if (status == STATUS_NO_SUCH_FILE) - ERR("Module (file) %s (which is needed by %s) not found\n", name, user->filename); + ERR("Module (file) %s (which is needed by %s) not found\n", + name, current_modref->filename); else ERR("Loading module (file) %s (which is needed by %s) failed (error %ld).\n", - name, user->filename, status); + name, current_modref->filename, status); return NULL; } @@ -266,9 +256,8 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr ) ordinal - exports->Base ); if (!thunk_list->u1.Function) { - WINE_MODREF *user = get_modref( module ); ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n", - name, ordinal, user->filename ); + name, ordinal, current_modref->filename ); thunk_list->u1.Function = (PDWORD)0xdeadbeef; } } @@ -281,9 +270,8 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr ) pe_name->Name, pe_name->Hint ); if (!thunk_list->u1.Function) { - WINE_MODREF *user = get_modref( module ); ERR("No implementation for %s.%s imported from %s, setting to 0xdeadbeef\n", - name, pe_name->Name, user->filename ); + name, pe_name->Name, current_modref->filename ); thunk_list->u1.Function = (PDWORD)0xdeadbeef; } } @@ -304,6 +292,7 @@ DWORD PE_fixup_imports( WINE_MODREF *wm ) { int i, nb_imports; IMAGE_IMPORT_DESCRIPTOR *imports; + WINE_MODREF *prev; DWORD size; if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE, @@ -328,11 +317,14 @@ DWORD PE_fixup_imports( WINE_MODREF *wm ) /* load the imported modules. They are automatically * added to the modref list of the process. */ + prev = current_modref; + current_modref = wm; for (i = 0; i < nb_imports; i++) { - if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i] ))) return 1; + if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i] ))) break; } - return 0; + current_modref = prev; + return (i < nb_imports); } @@ -403,6 +395,7 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) { static const char * const typeName[] = { "PROCESS_DETACH", "PROCESS_ATTACH", "THREAD_ATTACH", "THREAD_DETACH" }; + char mod_name[32]; BOOL retv = TRUE; DLLENTRYPROC entry = wm->ldr.EntryPoint; void *module = wm->ldr.BaseAddress; @@ -412,22 +405,25 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) if (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS) return TRUE; if (!entry || !(wm->ldr.Flags & LDR_IMAGE_IS_DLL)) return TRUE; - TRACE("(%p (%s),%s,%p) - CALL\n", module, wm->modname, typeName[type], lpReserved ); - if (TRACE_ON(relay)) - DPRINTF("%04lx:Call PE DLL (proc=%p,module=%p,type=%ld,res=%p)\n", - GetCurrentThreadId(), entry, module, type, lpReserved ); + { + size_t len = max( strlen(wm->modname), sizeof(mod_name)-1 ); + memcpy( mod_name, wm->modname, len ); + mod_name[len] = 0; + DPRINTF("%04lx:Call PE DLL (proc=%p,module=%p (%s),type=%ld,res=%p)\n", + GetCurrentThreadId(), entry, module, mod_name, type, lpReserved ); + } + else TRACE("(%p (%s),%s,%p) - CALL\n", module, wm->modname, typeName[type], lpReserved ); retv = entry( module, type, lpReserved ); - if (TRACE_ON(relay)) - DPRINTF("%04lx:Ret PE DLL (proc=%p,module=%p,type=%ld,res=%p) retval=%x\n", - GetCurrentThreadId(), entry, module, type, lpReserved, retv ); - /* The state of the module list may have changed due to the call to the dll. We cannot assume that this module has not been deleted. */ - TRACE("(%p,%s,%p) - RETURN %d\n", module, typeName[type], lpReserved, retv ); + if (TRACE_ON(relay)) + DPRINTF("%04lx:Ret PE DLL (proc=%p,module=%p (%s),type=%ld,res=%p) retval=%x\n", + GetCurrentThreadId(), entry, module, mod_name, type, lpReserved, retv ); + else TRACE("(%p,%s,%p) - RETURN %d\n", module, typeName[type], lpReserved, retv ); return retv; } @@ -494,9 +490,11 @@ BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved ) /* Call DLL entry point */ if ( retv ) { + WINE_MODREF *prev = current_modref; + current_modref = wm; retv = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved ); - if ( retv ) - wm->ldr.Flags |= LDR_PROCESS_ATTACHED; + if (retv) wm->ldr.Flags |= LDR_PROCESS_ATTACHED; + current_modref = prev; } /* Re-insert MODREF at head of list */ diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 3eb22faa3a2..a8aa6dffda4 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -34,6 +34,12 @@ extern void NTDLL_get_server_timeout( abs_time_t *when, const LARGE_INTEGER *tim /* module handling */ extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename ); +extern FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports, + DWORD exp_size, FARPROC proc, const char *user ); +extern FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, + FARPROC origfun, DWORD ordinal ); +extern void RELAY_SetupDLL( const char *module ); + static inline HANDLE ntdll_get_process_heap(void) { HANDLE *pdb = (HANDLE *)NtCurrentTeb()->process; diff --git a/documentation/samples/config b/documentation/samples/config index 6baa06cc865..041b1f86e97 100644 --- a/documentation/samples/config +++ b/documentation/samples/config @@ -207,6 +207,8 @@ WINE REGISTRY Version 2 [Debug] ;"RelayExclude" = "RtlEnterCriticalSection;RtlLeaveCriticalSection" ;"RelayInclude" = "user32.CreateWindowA" +;"RelayFromExclude" = "user32;x11drv" +;"RelayFromInclude" = "sol.exe" ;"SnoopExclude" = "RtlEnterCriticalSection;RtlLeaveCriticalSection" ;"SpyExclude" = "WM_SIZE;WM_TIMER;" diff --git a/documentation/wine.conf.man b/documentation/wine.conf.man index 75ccc506b96..e53b942f2a2 100644 --- a/documentation/wine.conf.man +++ b/documentation/wine.conf.man @@ -277,28 +277,40 @@ default: none .br default: none .br -Used to specify which function will be excluded from a relay debuglog. +Used to specify which functions will be excluded from a relay debug log. .PP -.I format: """RelayInclude""=""""" +.I format: """RelayInclude""=""""" +.br +default: include all functions +.br +Used to specify which functions will be included in a relay debug log. +.PP +.I format: """RelayFromExclude""=""""" .br default: none +.br +Used to specify a set of modules whose calls are excluded from a relay debug log. +.PP +.I format: """RelayFromInclude""=""""" +.br +default: include all modules .br -Used to specify which function will be included in relay debuglog. +Used to specify the set of modules whose calls are included in a relay debug log. .PP .I format: """SnoopExclude""=""""" .br default: none .br -Used to specify which function will be included in snoop debuglog. +Used to specify which functions will be included in snoop debug log. .PP .I format: """SnoopInclude""=""""" .br -default: none +default: include all functions .br -Used to specify which function will be included in snoop debuglog. +Used to specify which functions will be included in snoop debug log. .PP For Relay and Snoop .* includes or excludes the whole dll. Exclude -entries overwrite Include Entries. +entries overwrite Include entries. .br .PP .B [Tweak.Layout] diff --git a/include/snoop.h b/include/snoop.h index d950258b23e..115125a6fb3 100644 --- a/include/snoop.h +++ b/include/snoop.h @@ -24,7 +24,6 @@ #include "module.h" extern void SNOOP_RegisterDLL(HMODULE,LPCSTR,DWORD,DWORD); -extern FARPROC SNOOP_GetProcAddress(HMODULE,LPCSTR,DWORD,FARPROC); extern void SNOOP16_RegisterDLL(NE_MODULE*,LPCSTR); extern FARPROC16 SNOOP16_GetProcAddress16(HMODULE16,DWORD,FARPROC16); extern int SNOOP_ShowDebugmsgSnoop(const char *dll,int ord,const char *fname); diff --git a/relay32/builtin32.c b/relay32/builtin32.c index 0b93b619b4f..3bcbb1be76b 100644 --- a/relay32/builtin32.c +++ b/relay32/builtin32.c @@ -42,8 +42,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(module); WINE_DECLARE_DEBUG_CHANNEL(relay); -extern void RELAY_SetupDLL( const char *module ); - static HMODULE main_module; static NTSTATUS last_status; /* use to gather all errors in callback */ diff --git a/relay32/relay386.c b/relay32/relay386.c index 35f1c2f2c85..9b54308958b 100644 --- a/relay32/relay386.c +++ b/relay32/relay386.c @@ -40,6 +40,9 @@ const char **debug_relay_includelist = NULL; const char **debug_snoop_excludelist = NULL; const char **debug_snoop_includelist = NULL; +static const char **debug_from_relay_excludelist; +static const char **debug_from_relay_includelist; + /*********************************************************************** * build_list * @@ -103,6 +106,8 @@ void RELAY_InitDebugLists(void) static const WCHAR RelayExcludeW[] = {'R','e','l','a','y','E','x','c','l','u','d','e',0}; static const WCHAR SnoopIncludeW[] = {'S','n','o','o','p','I','n','c','l','u','d','e',0}; static const WCHAR SnoopExcludeW[] = {'S','n','o','o','p','E','x','c','l','u','d','e',0}; + static const WCHAR RelayFromIncludeW[] = {'R','e','l','a','y','F','r','o','m','I','n','c','l','u','d','e',0}; + static const WCHAR RelayFromExcludeW[] = {'R','e','l','a','y','F','r','o','m','E','x','c','l','u','d','e',0}; attr.Length = sizeof(attr); attr.RootDirectory = 0; @@ -143,6 +148,20 @@ void RELAY_InitDebugLists(void) debug_snoop_excludelist = build_list( str ); } + RtlInitUnicodeString( &name, RelayFromIncludeW ); + if (!NtQueryValueKey( hkey, &name, KeyValuePartialInformation, buffer, sizeof(buffer), &count )) + { + TRACE("RelayFromInclude = %s\n", debugstr_w(str) ); + debug_from_relay_includelist = build_list( str ); + } + + RtlInitUnicodeString( &name, RelayFromExcludeW ); + if (!NtQueryValueKey( hkey, &name, KeyValuePartialInformation, buffer, sizeof(buffer), &count )) + { + TRACE( "RelayFromExclude = %s\n", debugstr_w(str) ); + debug_from_relay_excludelist = build_list( str ); + } + NtClose( hkey ); } @@ -199,6 +218,40 @@ static BOOL check_relay_include( const char *module, const char *func ) } +/*********************************************************************** + * check_relay_from_module + * + * Check if calls from a given module must be included in the relay output. + */ +static BOOL check_relay_from_module( const char *module ) +{ + const char **listitem; + BOOL show; + + if (!debug_from_relay_excludelist && !debug_from_relay_includelist) return TRUE; + if (debug_from_relay_excludelist) + { + show = TRUE; + listitem = debug_from_relay_excludelist; + } + else + { + show = FALSE; + listitem = debug_from_relay_includelist; + } + for(; *listitem; listitem++) + { + int len; + + if (!strcasecmp( *listitem, module )) return !show; + len = strlen( *listitem ); + if (!strncasecmp( *listitem, module, len ) && !strcasecmp( module + len, ".dll" )) + return !show; + } + return show; +} + + /*********************************************************************** * find_exported_name * @@ -547,6 +600,26 @@ static BOOL is_register_entry_point( const BYTE *addr ) } +/*********************************************************************** + * RELAY_GetProcAddress + * + * Return the proc address to use for a given function. + */ +FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports, + DWORD exp_size, FARPROC proc, const char *user ) +{ + DEBUG_ENTRY_POINT *debug = (DEBUG_ENTRY_POINT *)proc; + DEBUG_ENTRY_POINT *list = (DEBUG_ENTRY_POINT *)((char *)exports + exp_size); + + if (debug < list || debug >= list + exports->NumberOfFunctions) return proc; + if (list + (debug - list) != debug) return proc; /* not a valid address */ + if (check_relay_from_module( user )) return proc; /* we want to relay it */ + if (!debug->call) return proc; /* not a normal function */ + if (debug->call != 0xe8 && debug->call != 0xe9) return proc; /* not a debug thunk at all */ + return debug->orig; +} + + /*********************************************************************** * RELAY_SetupDLL * @@ -602,6 +675,12 @@ void RELAY_SetupDLL( const char *module ) #else /* __i386__ */ +FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports, + DWORD exp_size, FARPROC proc, const char *user ) +{ + return proc; +} + void RELAY_SetupDLL( const char *module ) { } diff --git a/relay32/snoop.c b/relay32/snoop.c index b09ce591aff..c36eb209558 100644 --- a/relay32/snoop.c +++ b/relay32/snoop.c @@ -62,7 +62,7 @@ typedef struct tagSNOOP_FUN { /* unreached */ int nrofargs; FARPROC origfun; - char *name; + const char *name; } SNOOP_FUN; typedef struct tagSNOOP_DLL { @@ -180,8 +180,13 @@ SNOOP_RegisterDLL(HMODULE hmod,LPCSTR name,DWORD ordbase,DWORD nrofordinals) { memset((*dll)->funs,0,size); } -FARPROC -SNOOP_GetProcAddress(HMODULE hmod,LPCSTR name,DWORD ordinal,FARPROC origfun) { +FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, + FARPROC origfun, DWORD ordinal ) +{ + int i; + const char *ename; + WORD *ordinals; + DWORD *names; SNOOP_DLL *dll = firstdll; SNOOP_FUN *fun; IMAGE_SECTION_HEADER *sec; @@ -202,14 +207,26 @@ SNOOP_GetProcAddress(HMODULE hmod,LPCSTR name,DWORD ordinal,FARPROC origfun) { } if (!dll) /* probably internal */ return origfun; - if (!SNOOP_ShowDebugmsgSnoop(dll->name,ordinal,name)) + + /* try to find a name for it */ + ename = NULL; + names = (DWORD *)((char *)hmod + exports->AddressOfNames); + ordinals = (WORD *)((char *)hmod + exports->AddressOfNameOrdinals); + if (names) for (i = 0; i < exports->NumberOfNames; i++) + { + if (ordinals[i] == ordinal) + { + ename = (char *)hmod + names[i]; + break; + } + } + if (!SNOOP_ShowDebugmsgSnoop(dll->name,ordinal,ename)) return origfun; assert(ordinal < dll->nrofordinals); fun = dll->funs+ordinal; if (!fun->name) { - fun->name = RtlAllocateHeap(ntdll_get_process_heap(),0,strlen(name)+1); - strcpy( fun->name, name ); + fun->name = ename; fun->lcall = 0xe8; /* NOTE: origreturn struct member MUST come directly after snoopentry */ fun->snoopentry = (char*)SNOOP_Entry-((char*)(&fun->nrofargs)); @@ -330,7 +347,8 @@ void WINAPI SNOOP_DoEntry( CONTEXT86 *context ) context->Eip = (DWORD)fun->origfun; - DPRINTF("%04lx:CALL %s.%ld: %s(",GetCurrentThreadId(),dll->name,dll->ordbase+ordinal,fun->name); + if (fun->name) DPRINTF("%04lx:CALL %s.%s(",GetCurrentThreadId(),dll->name,fun->name); + else DPRINTF("%04lx:CALL %s.%ld(",GetCurrentThreadId(),dll->name,dll->ordbase+ordinal); if (fun->nrofargs>0) { max = fun->nrofargs; if (max>16) max=16; for (i=0;iEip - 5); + SNOOP_FUN *fun = &ret->dll->funs[ret->ordinal]; /* We haven't found out the nrofargs yet. If we called a cdecl * function it is too late anyway and we can just set '0' (which @@ -365,10 +384,13 @@ void WINAPI SNOOP_DoReturn( CONTEXT86 *context ) if (ret->args) { int i,max; - DPRINTF("%04lx:RET %s.%ld: %s(", - GetCurrentThreadId(), - ret->dll->name,ret->dll->ordbase+ret->ordinal,ret->dll->funs[ret->ordinal].name); - max = ret->dll->funs[ret->ordinal].nrofargs; + if (fun->name) + DPRINTF("%04lx:RET %s.%s(", GetCurrentThreadId(), ret->dll->name, fun->name); + else + DPRINTF("%04lx:RET %s.%ld(", GetCurrentThreadId(), + ret->dll->name,ret->dll->ordbase+ret->ordinal); + + max = fun->nrofargs; if (max>16) max=16; for (i=0;iargs[i]); if (iEax,(DWORD)ret->origreturn ); RtlFreeHeap(ntdll_get_process_heap(),0,ret->args); ret->args = NULL; - } else - DPRINTF("%04lx:RET %s.%ld: %s() retval = %08lx ret=%08lx\n", + } + else + { + if (fun->name) + DPRINTF("%04lx:RET %s.%s() retval=%08lx ret=%08lx\n", GetCurrentThreadId(), - ret->dll->name,ret->dll->ordbase+ret->ordinal,ret->dll->funs[ret->ordinal].name, + ret->dll->name, fun->name, context->Eax, (DWORD)ret->origreturn); + else + DPRINTF("%04lx:RET %s.%ld() retval=%08lx ret=%08lx\n", + GetCurrentThreadId(), + ret->dll->name,ret->dll->ordbase+ret->ordinal, context->Eax, (DWORD)ret->origreturn); + } ret->origreturn = NULL; /* mark as empty */ } @@ -402,7 +432,9 @@ void SNOOP_RegisterDLL(HMODULE hmod,LPCSTR name,DWORD nrofordinals, DWORD dw) { FIXME("snooping works only on i386 for now.\n"); } -FARPROC SNOOP_GetProcAddress(HMODULE hmod,LPCSTR name,DWORD ordinal,FARPROC origfun) { - return origfun; +FARPROC SNOOP_GetProcAddress( HMODULE hmod, IMAGE_EXPORT_DIRECTORY *exports, DWORD exp_size, + FARPROC origfun, DWORD ordinal ) +{ + return origfun; } #endif /* !__i386__ */