Added possibility to filter relay traces based on the module that
called the function. Cleaned up a few traces.

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index fb0a60d..668744c 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -57,6 +57,7 @@
 
 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 @@
 
     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 @@
 
     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 @@
                                     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 @@
 
     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 @@
     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 @@
                                                                    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 @@
                                                                  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 @@
 {
     int i, nb_imports;
     IMAGE_IMPORT_DESCRIPTOR *imports;
+    WINE_MODREF *prev;
     DWORD size;
 
     if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
@@ -328,11 +317,14 @@
     /* 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 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 @@
     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 @@
     /* 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 3eb22fa..a8aa6df 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -34,6 +34,12 @@
 /* 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 6baa06c..041b1f8 100644
--- a/documentation/samples/config
+++ b/documentation/samples/config
@@ -207,6 +207,8 @@
 [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 75ccc50..e53b942 100644
--- a/documentation/wine.conf.man
+++ b/documentation/wine.conf.man
@@ -277,28 +277,40 @@
 .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""=""<message names separated by semicolons>"""
+.I format: """RelayInclude""=""<function or dll.functions separated by semicolons>"""
+.br
+default: include all functions
+.br 
+Used to specify which functions will be included in a relay debug log.
+.PP
+.I format: """RelayFromExclude""=""<module names separated by semicolons>"""
 .br
 default: none
+.br
+Used to specify a set of modules whose calls are excluded from a relay debug log.
+.PP
+.I format: """RelayFromInclude""=""<module names separated by semicolons>"""
+.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""=""<message names separated by semicolons>"""
 .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""=""<message names separated by semicolons>"""
 .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 <dllname>.* 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 d950258..115125a 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 0b93b61..3bcbb1b 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 35f1c2f..9b54308 100644
--- a/relay32/relay386.c
+++ b/relay32/relay386.c
@@ -40,6 +40,9 @@
 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 @@
     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 @@
         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 );
 }
 
@@ -200,6 +219,40 @@
 
 
 /***********************************************************************
+ *           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
  *
  * Find the name of an exported function.
@@ -548,6 +601,26 @@
 
 
 /***********************************************************************
+ *           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
  *
  * Setup relay debugging for a built-in dll.
@@ -602,6 +675,12 @@
 
 #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 b09ce59..c36eb20 100644
--- a/relay32/snoop.c
+++ b/relay32/snoop.c
@@ -62,7 +62,7 @@
 	/* unreached */
 	int		nrofargs;
 	FARPROC	origfun;
-	char		*name;
+	const char *name;
 } SNOOP_FUN;
 
 typedef struct tagSNOOP_DLL {
@@ -180,8 +180,13 @@
 	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 @@
 	}
 	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 @@
 
 	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;i<max;i++)
@@ -353,6 +371,7 @@
 void WINAPI SNOOP_DoReturn( CONTEXT86 *context )
 {
 	SNOOP_RETURNENTRY	*ret = (SNOOP_RETURNENTRY*)(context->Eip - 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 @@
 	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;i<max;i++)
@@ -376,15 +398,23 @@
                     SNOOP_PrintArg(ret->args[i]);
                     if (i<max-1) DPRINTF(",");
                 }
-		DPRINTF(") retval = %08lx ret=%08lx\n",
+		DPRINTF(") retval=%08lx ret=%08lx\n",
 			context->Eax,(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 @@
 	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__ */