From a061b84ee1cebe8e76743c6e93cda7deee9e9ef0 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Tue, 4 Jun 2002 17:48:41 +0000
Subject: [PATCH] Moved specification of relay and snoop include/exclude
 functions to the config file. Changed spy config a bit to follow the same
 scheme. Moved debug option parsing routine into libwine.

---
 documentation/samples/config |   7 +-
 if1632/relay.c               |  45 +++++++++-
 include/wine/library.h       |   1 +
 library/debug.c              |  57 ++++++++++++-
 misc/options.c               | 104 ++---------------------
 relay32/relay386.c           | 158 ++++++++++++++++++++++++++---------
 relay32/snoop.c              |   5 +-
 scheduler/process.c          |   3 +
 windows/spy.c                |  61 ++++++--------
 9 files changed, 261 insertions(+), 180 deletions(-)

diff --git a/documentation/samples/config b/documentation/samples/config
index 589f667f5eb..92498e1573d 100644
--- a/documentation/samples/config
+++ b/documentation/samples/config
@@ -201,8 +201,11 @@ WINE REGISTRY Version 2
 ;"read"  = "0x779,0x379,0x280-0x2a0"
 ;"write" = "0x779,0x379,0x280-0x2a0"
 
-[spy]
-"Exclude" = "WM_SIZE;WM_TIMER;"
+[Debug]
+;"RelayExclude" = "RtlEnterCriticalSection;RtlLeaveCriticalSection"
+;"RelayInclude" = "user32.CreateWindowA"
+;"SnoopExclude" = "RtlEnterCriticalSection;RtlLeaveCriticalSection"
+;"SpyExclude" = "WM_SIZE;WM_TIMER;"
 
 [registry]
 ;These are all booleans.  Y/y/T/t/1 are true, N/n/F/f/0 are false.
diff --git a/if1632/relay.c b/if1632/relay.c
index 1263cc24b59..159411c0e0d 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -140,9 +140,48 @@ DWORD WINAPI CALL32_CBClientEx( FARPROC proc, LPWORD args, DWORD *esi, INT *nArg
 #endif
 
 
-/* from relay32/relay386.c */
-extern char **debug_relay_excludelist,**debug_relay_includelist;
-extern int RELAY_ShowDebugmsgRelay(const char *func);
+/***********************************************************************
+ *           RELAY_ShowDebugmsgRelay
+ *
+ * Simple function to decide if a particular debugging message is
+ * wanted.
+ */
+static int RELAY_ShowDebugmsgRelay(const char *func)
+{
+  /* from relay32/relay386.c */
+  extern const char **debug_relay_excludelist,**debug_relay_includelist;
+
+  if(debug_relay_excludelist || debug_relay_includelist) {
+    const char *term = strchr(func, ':');
+    const char **listitem;
+    int len, len2, itemlen, show;
+
+    if(debug_relay_excludelist) {
+      show = 1;
+      listitem = debug_relay_excludelist;
+    } else {
+      show = 0;
+      listitem = debug_relay_includelist;
+    }
+    assert(term);
+    assert(strlen(term) > 2);
+    len = term - func;
+    len2 = strchr(func, '.') - func;
+    assert(len2 && len2 > 0 && len2 < 64);
+    term += 2;
+    for(; *listitem; listitem++) {
+      itemlen = strlen(*listitem);
+      if((itemlen == len && !strncasecmp(*listitem, func, len)) ||
+         (itemlen == len2 && !strncasecmp(*listitem, func, len2)) ||
+         !strcasecmp(*listitem, term)) {
+        show = !show;
+       break;
+      }
+    }
+    return show;
+  }
+  return 1;
+}
 
 
 /***********************************************************************
diff --git a/include/wine/library.h b/include/wine/library.h
index 515c4bb8007..b1d0407150a 100644
--- a/include/wine/library.h
+++ b/include/wine/library.h
@@ -50,6 +50,7 @@ extern int (*__wine_dbg_vlog)( int cls, const char *channel,
                                const char *function, const char *format, va_list args );
 
 extern void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear );
+extern int wine_dbg_parse_options( const char *str );
 
 /* portability */
 
diff --git a/library/debug.c b/library/debug.c
index 9bfa8786555..42926d053d7 100644
--- a/library/debug.c
+++ b/library/debug.c
@@ -53,6 +53,7 @@ struct debug_option
 static struct debug_option *first_option;
 static struct debug_option *last_option;
 
+static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" };
 
 static int cmp_name( const void *p1, const void *p2 )
 {
@@ -140,6 +141,57 @@ void wine_dbg_add_option( const char *name, unsigned char set, unsigned char cle
     }
 }
 
+/* parse a set of debugging option specifications and add them to the option list */
+int wine_dbg_parse_options( const char *str )
+{
+    char *p, *opt, *next, *options;
+    int i, errors = 0;
+
+    if (!(options = strdup(str))) return -1;
+    for (opt = options; opt; opt = next)
+    {
+        unsigned char set = 0, clear = 0;
+
+        if ((next = strchr( opt, ',' ))) *next++ = 0;
+
+        p = opt + strcspn( opt, "+-" );
+        if (!p[0] || !p[1])  /* bad option, skip it */
+        {
+            errors++;
+            continue;
+        }
+
+        if (p > opt)
+        {
+            for (i = 0; i < sizeof(debug_classes)/sizeof(debug_classes[0]); i++)
+            {
+                int len = strlen(debug_classes[i]);
+                if (len != (p - opt)) continue;
+                if (!memcmp( opt, debug_classes[i], len ))  /* found it */
+                {
+                    if (*p == '+') set |= 1 << i;
+                    else clear |= 1 << i;
+                    break;
+                }
+            }
+            if (i == sizeof(debug_classes)/sizeof(debug_classes[0])) /* bad class name, skip it */
+            {
+                errors++;
+                continue;
+            }
+        }
+        else
+        {
+            if (*p == '+') set = ~0;
+            else clear = ~0;
+        }
+        p++;
+        if (!strcmp( p, "all" )) p = "";  /* empty string means all */
+        wine_dbg_add_option( p, set, clear );
+    }
+    free( options );
+    return errors;
+}
 
 /* varargs wrapper for __wine_dbg_vprintf */
 int wine_dbg_printf( const char *format, ... )
@@ -318,11 +370,10 @@ static int default_dbg_vprintf( const char *format, va_list args )
 static int default_dbg_vlog( int cls, const char *channel, const char *func,
                              const char *format, va_list args )
 {
-    static const char * const classes[] = { "fixme", "err", "warn", "trace" };
     int ret = 0;
 
-    if (cls < sizeof(classes)/sizeof(classes[0]))
-        ret += wine_dbg_printf( "%s:%s:%s ", classes[cls], channel + 1, func );
+    if (cls < sizeof(debug_classes)/sizeof(debug_classes[0]))
+        ret += wine_dbg_printf( "%s:%s:%s ", debug_classes[cls], channel + 1, func );
     if (format)
         ret += __wine_dbg_vprintf( format, args );
     return ret;
diff --git a/misc/options.c b/misc/options.c
index 1c6c9cd7dce..3421d097e6b 100644
--- a/misc/options.c
+++ b/misc/options.c
@@ -83,104 +83,14 @@ static void do_version( const char *arg )
 
 static void do_debugmsg( const char *arg )
 {
-    static const char * const debug_class_names[__WINE_DBCL_COUNT] = { "fixme", "err", "warn", "trace" };
-
-    char *opt, *options = strdup(arg);
-    int i;
-    /* defined in relay32/relay386.c */
-    extern char **debug_relay_includelist;
-    extern char **debug_relay_excludelist;
-    /* defined in relay32/snoop.c */
-    extern char **debug_snoop_includelist;
-    extern char **debug_snoop_excludelist;
-
-    if (!(opt = strtok( options, "," ))) goto error;
-    do
+    if (wine_dbg_parse_options( arg ))
     {
-        unsigned char set = 0, clear = 0;
-        char *p = strchr( opt, '+' );
-        if (!p) p = strchr( opt, '-' );
-        if (!p || !p[1]) goto error;
-        if (p > opt)
-        {
-            for (i = 0; i < __WINE_DBCL_COUNT; i++)
-            {
-                int len = strlen(debug_class_names[i]);
-                if (len != (p - opt)) continue;
-                if (!memcmp( opt, debug_class_names[i], len ))  /* found it */
-                {
-                    if (*p == '+') set |= 1 << i;
-                    else clear |= 1 << i;
-                    break;
-                }
-            }
-            if (i == __WINE_DBCL_COUNT) goto error;  /* class name not found */
-        }
-        else
-        {
-            if (*p == '+') set = ~0;
-            else clear = ~0;
-	    if (!strncasecmp(p+1, "relay=", 6) ||
-		!strncasecmp(p+1, "snoop=", 6))
-		{
-		    int i, l;
-		    char *s, *s2, ***output, c;
-
-		    if (strchr(p,','))
-			l=strchr(p,',')-p;
-		    else
-			l=strlen(p);
-		    set = ~0;
-		    clear = 0;
-		    output = (*p == '+') ?
-			((*(p+1) == 'r') ?
-			 &debug_relay_includelist :
-			 &debug_snoop_includelist) :
-			((*(p+1) == 'r') ?
-			 &debug_relay_excludelist :
-			 &debug_snoop_excludelist);
-		    s = p + 7;
-		    /* if there are n ':', there are n+1 modules, and we need
-                       n+2 slots, last one being for the sentinel (NULL) */
-		    i = 2;
-		    while((s = strchr(s, ':'))) i++, s++;
-		    *output = malloc(sizeof(char **) * i);
-		    i = 0;
-		    s = p + 7;
-		    while((s2 = strchr(s, ':'))) {
-			c = *s2;
-			*s2 = '\0';
-			*((*output)+i) = _strupr(strdup(s));
-			*s2 = c;
-			s = s2 + 1;
-			i++;
-		    }
-		    c = *(p + l);
-		    *(p + l) = '\0';
-		    *((*output)+i) = _strupr(strdup(s));
-		    *(p + l) = c;
-		    *((*output)+i+1) = NULL;
-		    *(p + 6) = '\0';
-		}
-        }
-        p++;
-        if (!strcmp( p, "all" )) p = "";  /* empty string means all */
-        wine_dbg_add_option( p, set, clear );
-        opt = strtok( NULL, "," );
-    } while(opt);
-
-    free( options );
-    return;
-
- error:
-    MESSAGE("wine: Syntax: --debugmsg [class]+xxx,...  or "
-            "-debugmsg [class]-xxx,...\n");
-    MESSAGE("Example: --debugmsg +all,warn-heap\n"
-            "  turn on all messages except warning heap messages\n");
-    MESSAGE("Available message classes:\n");
-    for( i = 0; i < __WINE_DBCL_COUNT; i++) MESSAGE( "%-9s", debug_class_names[i] );
-    MESSAGE("\n\n");
-    ExitProcess(1);
+        MESSAGE("%s: Syntax: --debugmsg [class]+xxx,...  or -debugmsg [class]-xxx,...\n", argv0);
+        MESSAGE("Example: --debugmsg +all,warn-heap\n"
+                "  turn on all messages except warning heap messages\n");
+        MESSAGE("Available message classes: err, warn, fixme, trace\n\n");
+        ExitProcess(1);
+    }
 }
 
 
diff --git a/relay32/relay386.c b/relay32/relay386.c
index 671061d4914..8cfb3c57778 100644
--- a/relay32/relay386.c
+++ b/relay32/relay386.c
@@ -26,52 +26,97 @@
 #include <stdio.h>
 
 #include "winnt.h"
+#include "winreg.h"
 #include "stackframe.h"
 #include "module.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(relay);
+WINE_DECLARE_DEBUG_CHANNEL(snoop);
 
-char **debug_relay_excludelist = NULL, **debug_relay_includelist = NULL;
+const char **debug_relay_excludelist = NULL;
+const char **debug_relay_includelist = NULL;
+const char **debug_snoop_excludelist = NULL;
+const char **debug_snoop_includelist = NULL;
 
 /***********************************************************************
- *           RELAY_ShowDebugmsgRelay
+ *           build_list
  *
- * Simple function to decide if a particular debugging message is
- * wanted.  Called from RELAY_CallFrom32 and from in if1632/relay.c
+ * Build a function list from a ';'-separated string.
  */
-int RELAY_ShowDebugmsgRelay(const char *func) {
-
-  if(debug_relay_excludelist || debug_relay_includelist) {
-    const char *term = strchr(func, ':');
-    char **listitem;
-    int len, len2, itemlen, show;
-
-    if(debug_relay_excludelist) {
-      show = 1;
-      listitem = debug_relay_excludelist;
-    } else {
-      show = 0;
-      listitem = debug_relay_includelist;
+static const char **build_list( const char *buffer )
+{
+    int count = 1;
+    const char *p = buffer;
+    const char **ret;
+
+    while ((p = strchr( p, ';' )))
+    {
+        count++;
+        p++;
     }
-    assert(term);
-    assert(strlen(term) > 2);
-    len = term - func;
-    len2 = strchr(func, '.') - func;
-    assert(len2 && len2 > 0 && len2 < 64);
-    term += 2;
-    for(; *listitem; listitem++) {
-      itemlen = strlen(*listitem);
-      if((itemlen == len && !strncasecmp(*listitem, func, len)) ||
-         (itemlen == len2 && !strncasecmp(*listitem, func, len2)) ||
-         !strcasecmp(*listitem, term)) {
-        show = !show;
-       break;
-      }
+    /* allocate count+1 pointers, plus the space for a copy of the string */
+    if ((ret = HeapAlloc( GetProcessHeap(), 0, (count+1) * sizeof(char*) + strlen(buffer) + 1 )))
+    {
+        char *str = (char *)(ret + count + 1);
+        char *p = str;
+
+        strcpy( str, buffer );
+        count = 0;
+        for (;;)
+        {
+            ret[count++] = p;
+            if (!(p = strchr( p, ';' ))) break;
+            *p++ = 0;
+        }
+        ret[count++] = NULL;
     }
-    return show;
-  }
-  return 1;
+    return ret;
+}
+
+
+/***********************************************************************
+ *           RELAY_InitDebugLists
+ *
+ * Build the relay include/exclude function lists.
+ */
+void RELAY_InitDebugLists(void)
+{
+    char buffer[1024];
+    HKEY hkey;
+    DWORD count, type;
+
+    if (RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Debug", &hkey )) return;
+
+    count = sizeof(buffer);
+    if (!RegQueryValueExA( hkey, "RelayInclude", NULL, &type, buffer, &count ))
+    {
+        TRACE("RelayInclude = %s\n", buffer );
+        debug_relay_includelist = build_list( buffer );
+    }
+
+    count = sizeof(buffer);
+    if (!RegQueryValueExA( hkey, "RelayExclude", NULL, &type, buffer, &count ))
+    {
+        TRACE( "RelayExclude = %s\n", buffer );
+        debug_relay_excludelist = build_list( buffer );
+    }
+
+    count = sizeof(buffer);
+    if (!RegQueryValueExA( hkey, "SnoopInclude", NULL, &type, buffer, &count ))
+    {
+        TRACE_(snoop)( "SnoopInclude = %s\n", buffer );
+        debug_snoop_includelist = build_list( buffer );
+    }
+
+    count = sizeof(buffer);
+    if (!RegQueryValueExA( hkey, "SnoopExclude", NULL, &type, buffer, &count ))
+    {
+        TRACE_(snoop)( "SnoopExclude = %s\n", buffer );
+        debug_snoop_excludelist = build_list( buffer );
+    }
+
+    RegCloseKey( hkey );
 }
 
 
@@ -88,6 +133,45 @@ typedef struct
 } DEBUG_ENTRY_POINT;
 
 
+/***********************************************************************
+ *           check_relay_include
+ *
+ * Check if a given function must be included in the relay output.
+ */
+static BOOL check_relay_include( const char *module, const char *func )
+{
+    const char **listitem;
+    BOOL show;
+
+    if (!debug_relay_excludelist && !debug_relay_includelist) return TRUE;
+    if (debug_relay_excludelist)
+    {
+        show = TRUE;
+        listitem = debug_relay_excludelist;
+    }
+    else
+    {
+        show = FALSE;
+        listitem = debug_relay_includelist;
+    }
+    for(; *listitem; listitem++)
+    {
+        char *p = strchr( *listitem, '.' );
+        if (p && p > *listitem)  /* check module and function */
+        {
+            int len = p - *listitem;
+            if (strncasecmp( *listitem, module, len-1 ) || module[len]) continue;
+            if (!strcmp( p + 1, func )) return !show;
+        }
+        else  /* function only */
+        {
+            if (!strcmp( *listitem, func )) return !show;
+        }
+    }
+    return show;
+}
+
+
 /***********************************************************************
  *           find_exported_name
  *
@@ -430,11 +514,7 @@ void RELAY_SetupDLL( const char *module )
         if (debug->call != 0xe8 && debug->call != 0xe9) break; /* not a debug thunk at all */
 
         if ((name = find_exported_name( module, exports, i + exports->Base )))
-        {
-            char buffer[200];
-            sprintf( buffer, "%s.%d: %s", dllname, i, name );
-            on = RELAY_ShowDebugmsgRelay(buffer);
-        }
+            on = check_relay_include( dllname, name );
 
         if (on)
         {
diff --git a/relay32/snoop.c b/relay32/snoop.c
index 59f8ba32cca..109a8cf90fb 100644
--- a/relay32/snoop.c
+++ b/relay32/snoop.c
@@ -42,7 +42,8 @@ static WINE_EXCEPTION_FILTER(page_fault)
     return EXCEPTION_CONTINUE_SEARCH;
 }
 
-char **debug_snoop_excludelist = NULL, **debug_snoop_includelist = NULL;
+extern const char **debug_snoop_excludelist;
+extern const char **debug_snoop_includelist;
 
 #ifdef __i386__
 
@@ -113,7 +114,7 @@ static	SNOOP_RETURNENTRIES 	*firstrets = NULL;
 int SNOOP_ShowDebugmsgSnoop(const char *dll, int ord, const char *fname) {
 
   if(debug_snoop_excludelist || debug_snoop_includelist) {
-    char **listitem;
+    const char **listitem;
     char buf[80];
     int len, len2, itemlen, show;
 
diff --git a/scheduler/process.c b/scheduler/process.c
index 84399432fa4..c0b58ae0673 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -46,6 +46,7 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(process);
 WINE_DECLARE_DEBUG_CHANNEL(relay);
+WINE_DECLARE_DEBUG_CHANNEL(snoop);
 WINE_DECLARE_DEBUG_CHANNEL(win32);
 
 struct _ENVDB;
@@ -126,6 +127,7 @@ extern STARTUPINFOA current_startupinfo;
 /* scheduler/pthread.c */
 extern void PTHREAD_init_done(void);
 
+extern void RELAY_InitDebugLists(void);
 extern BOOL MAIN_MainInit(void);
 
 typedef WORD (WINAPI *pUserSignalProc)( UINT, DWORD, DWORD, HMODULE16 );
@@ -430,6 +432,7 @@ static BOOL process_init( char *argv[] )
     OPTIONS_ParseOptions( !info_size ? argv : NULL );
 
     ret = MAIN_MainInit();
+    if (TRACE_ON(relay) || TRACE_ON(snoop)) RELAY_InitDebugLists();
 
     return ret;
 }
diff --git a/windows/spy.c b/windows/spy.c
index 2467e426f4e..04665782b8e 100644
--- a/windows/spy.c
+++ b/windows/spy.c
@@ -2292,44 +2292,37 @@ int SPY_Init(void)
     if (!TRACE_ON(message)) return TRUE;
 
     indent_tls_index = TlsAlloc();
-    buffer[0] = 0;
-    if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Spy", &hkey))
+    if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Debug", &hkey))
     {
-	DWORD type, count = sizeof(buffer);
-	RegQueryValueExA(hkey, "Include", 0, &type, buffer, &count);
-	RegCloseKey(hkey);
-    }
-    if (buffer[0] && strcmp( buffer, "INCLUDEALL" ))
-    {
-        TRACE("Include=%s\n", buffer );
-        for (i = 0; i <= SPY_MAX_MSGNUM; i++)
-            SPY_Exclude[i] = (MessageTypeNames[i] && !strstr(buffer,MessageTypeNames[i]));
-    }
+        DWORD type, count = sizeof(buffer);
 
-    buffer[0] = 0;
-    if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Spy", &hkey))
-    {
-	DWORD type, count = sizeof(buffer);
-	RegQueryValueExA(hkey, "Exclude", 0, &type, buffer, &count);
-	RegCloseKey(hkey);
-    }
-    if (buffer[0])
-    {
-        TRACE("Exclude=%s\n", buffer );
-        if (!strcmp( buffer, "EXCLUDEALL" ))
-            for (i = 0; i <= SPY_MAX_MSGNUM; i++) SPY_Exclude[i] = TRUE;
-        else
+        buffer[0] = 0;
+        if (!RegQueryValueExA(hkey, "SpyInclude", 0, &type, buffer, &count) &&
+            strcmp( buffer, "INCLUDEALL" ))
+        {
+            TRACE("Include=%s\n", buffer );
             for (i = 0; i <= SPY_MAX_MSGNUM; i++)
-                SPY_Exclude[i] = (MessageTypeNames[i] && strstr(buffer,MessageTypeNames[i]));
-    }
+                SPY_Exclude[i] = (MessageTypeNames[i] && !strstr(buffer,MessageTypeNames[i]));
+        }
 
-    SPY_ExcludeDWP = 0;
-    if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Spy", &hkey))
-    {
-	DWORD type, count = sizeof(buffer);
-	if(!RegQueryValueExA(hkey, "ExcludeDWP", 0, &type, buffer, &count))
-	    SPY_ExcludeDWP = atoi(buffer);
-	RegCloseKey(hkey);
+        count = sizeof(buffer);
+        buffer[0] = 0;
+        if (!RegQueryValueExA(hkey, "SpyExclude", 0, &type, buffer, &count))
+        {
+            TRACE("Exclude=%s\n", buffer );
+            if (!strcmp( buffer, "EXCLUDEALL" ))
+                for (i = 0; i <= SPY_MAX_MSGNUM; i++) SPY_Exclude[i] = TRUE;
+            else
+                for (i = 0; i <= SPY_MAX_MSGNUM; i++)
+                    SPY_Exclude[i] = (MessageTypeNames[i] && strstr(buffer,MessageTypeNames[i]));
+        }
+
+        SPY_ExcludeDWP = 0;
+        count = sizeof(buffer);
+        if(!RegQueryValueExA(hkey, "SpyExcludeDWP", 0, &type, buffer, &count))
+            SPY_ExcludeDWP = atoi(buffer);
+
+        RegCloseKey(hkey);
     }
 
     /* find last good entry in spy notify array and save addr for b-search */
-- 
GitLab