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.
This commit is contained in:
Alexandre Julliard 2002-06-04 17:48:41 +00:00
parent 78b041cf52
commit a061b84ee1
9 changed files with 259 additions and 178 deletions

View file

@ -201,8 +201,11 @@ WINE REGISTRY Version 2
;"read" = "0x779,0x379,0x280-0x2a0" ;"read" = "0x779,0x379,0x280-0x2a0"
;"write" = "0x779,0x379,0x280-0x2a0" ;"write" = "0x779,0x379,0x280-0x2a0"
[spy] [Debug]
"Exclude" = "WM_SIZE;WM_TIMER;" ;"RelayExclude" = "RtlEnterCriticalSection;RtlLeaveCriticalSection"
;"RelayInclude" = "user32.CreateWindowA"
;"SnoopExclude" = "RtlEnterCriticalSection;RtlLeaveCriticalSection"
;"SpyExclude" = "WM_SIZE;WM_TIMER;"
[registry] [registry]
;These are all booleans. Y/y/T/t/1 are true, N/n/F/f/0 are false. ;These are all booleans. Y/y/T/t/1 are true, N/n/F/f/0 are false.

View file

@ -140,9 +140,48 @@ DWORD WINAPI CALL32_CBClientEx( FARPROC proc, LPWORD args, DWORD *esi, INT *nArg
#endif #endif
/* from relay32/relay386.c */ /***********************************************************************
extern char **debug_relay_excludelist,**debug_relay_includelist; * RELAY_ShowDebugmsgRelay
extern int RELAY_ShowDebugmsgRelay(const char *func); *
* 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;
}
/*********************************************************************** /***********************************************************************

View file

@ -50,6 +50,7 @@ extern int (*__wine_dbg_vlog)( int cls, const char *channel,
const char *function, const char *format, va_list args ); 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 void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear );
extern int wine_dbg_parse_options( const char *str );
/* portability */ /* portability */

View file

@ -53,6 +53,7 @@ struct debug_option
static struct debug_option *first_option; static struct debug_option *first_option;
static struct debug_option *last_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 ) 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 */ /* varargs wrapper for __wine_dbg_vprintf */
int wine_dbg_printf( const char *format, ... ) 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, static int default_dbg_vlog( int cls, const char *channel, const char *func,
const char *format, va_list args ) const char *format, va_list args )
{ {
static const char * const classes[] = { "fixme", "err", "warn", "trace" };
int ret = 0; int ret = 0;
if (cls < sizeof(classes)/sizeof(classes[0])) if (cls < sizeof(debug_classes)/sizeof(debug_classes[0]))
ret += wine_dbg_printf( "%s:%s:%s ", classes[cls], channel + 1, func ); ret += wine_dbg_printf( "%s:%s:%s ", debug_classes[cls], channel + 1, func );
if (format) if (format)
ret += __wine_dbg_vprintf( format, args ); ret += __wine_dbg_vprintf( format, args );
return ret; return ret;

View file

@ -83,104 +83,14 @@ static void do_version( const char *arg )
static void do_debugmsg( const char *arg ) static void do_debugmsg( const char *arg )
{ {
static const char * const debug_class_names[__WINE_DBCL_COUNT] = { "fixme", "err", "warn", "trace" }; if (wine_dbg_parse_options( arg ))
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
{ {
unsigned char set = 0, clear = 0; MESSAGE("%s: Syntax: --debugmsg [class]+xxx,... or -debugmsg [class]-xxx,...\n", argv0);
char *p = strchr( opt, '+' ); MESSAGE("Example: --debugmsg +all,warn-heap\n"
if (!p) p = strchr( opt, '-' ); " turn on all messages except warning heap messages\n");
if (!p || !p[1]) goto error; MESSAGE("Available message classes: err, warn, fixme, trace\n\n");
if (p > opt) ExitProcess(1);
{ }
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);
} }

View file

@ -26,52 +26,97 @@
#include <stdio.h> #include <stdio.h>
#include "winnt.h" #include "winnt.h"
#include "winreg.h"
#include "stackframe.h" #include "stackframe.h"
#include "module.h" #include "module.h"
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(relay); 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 * Build a function list from a ';'-separated string.
* wanted. Called from RELAY_CallFrom32 and from in if1632/relay.c
*/ */
int RELAY_ShowDebugmsgRelay(const char *func) { static const char **build_list( const char *buffer )
{
int count = 1;
const char *p = buffer;
const char **ret;
if(debug_relay_excludelist || debug_relay_includelist) { while ((p = strchr( p, ';' )))
const char *term = strchr(func, ':'); {
char **listitem; count++;
int len, len2, itemlen, show; p++;
}
/* 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;
if(debug_relay_excludelist) { strcpy( str, buffer );
show = 1; count = 0;
listitem = debug_relay_excludelist; for (;;)
} else { {
show = 0; ret[count++] = p;
listitem = debug_relay_includelist; if (!(p = strchr( p, ';' ))) break;
*p++ = 0;
}
ret[count++] = NULL;
} }
assert(term); return ret;
assert(strlen(term) > 2); }
len = term - func;
len2 = strchr(func, '.') - func;
assert(len2 && len2 > 0 && len2 < 64); /***********************************************************************
term += 2; * RELAY_InitDebugLists
for(; *listitem; listitem++) { *
itemlen = strlen(*listitem); * Build the relay include/exclude function lists.
if((itemlen == len && !strncasecmp(*listitem, func, len)) || */
(itemlen == len2 && !strncasecmp(*listitem, func, len2)) || void RELAY_InitDebugLists(void)
!strcasecmp(*listitem, term)) { {
show = !show; char buffer[1024];
break; 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 );
} }
return show;
} count = sizeof(buffer);
return 1; 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; } 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 * 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 (debug->call != 0xe8 && debug->call != 0xe9) break; /* not a debug thunk at all */
if ((name = find_exported_name( module, exports, i + exports->Base ))) if ((name = find_exported_name( module, exports, i + exports->Base )))
{ on = check_relay_include( dllname, name );
char buffer[200];
sprintf( buffer, "%s.%d: %s", dllname, i, name );
on = RELAY_ShowDebugmsgRelay(buffer);
}
if (on) if (on)
{ {

View file

@ -42,7 +42,8 @@ static WINE_EXCEPTION_FILTER(page_fault)
return EXCEPTION_CONTINUE_SEARCH; 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__ #ifdef __i386__
@ -113,7 +114,7 @@ static SNOOP_RETURNENTRIES *firstrets = NULL;
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) {
char **listitem; const char **listitem;
char buf[80]; char buf[80];
int len, len2, itemlen, show; int len, len2, itemlen, show;

View file

@ -46,6 +46,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(process); WINE_DEFAULT_DEBUG_CHANNEL(process);
WINE_DECLARE_DEBUG_CHANNEL(relay); WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(snoop);
WINE_DECLARE_DEBUG_CHANNEL(win32); WINE_DECLARE_DEBUG_CHANNEL(win32);
struct _ENVDB; struct _ENVDB;
@ -126,6 +127,7 @@ extern STARTUPINFOA current_startupinfo;
/* scheduler/pthread.c */ /* scheduler/pthread.c */
extern void PTHREAD_init_done(void); extern void PTHREAD_init_done(void);
extern void RELAY_InitDebugLists(void);
extern BOOL MAIN_MainInit(void); extern BOOL MAIN_MainInit(void);
typedef WORD (WINAPI *pUserSignalProc)( UINT, DWORD, DWORD, HMODULE16 ); typedef WORD (WINAPI *pUserSignalProc)( UINT, DWORD, DWORD, HMODULE16 );
@ -430,6 +432,7 @@ static BOOL process_init( char *argv[] )
OPTIONS_ParseOptions( !info_size ? argv : NULL ); OPTIONS_ParseOptions( !info_size ? argv : NULL );
ret = MAIN_MainInit(); ret = MAIN_MainInit();
if (TRACE_ON(relay) || TRACE_ON(snoop)) RELAY_InitDebugLists();
return ret; return ret;
} }

View file

@ -2292,44 +2292,37 @@ int SPY_Init(void)
if (!TRACE_ON(message)) return TRUE; if (!TRACE_ON(message)) return TRUE;
indent_tls_index = TlsAlloc(); indent_tls_index = TlsAlloc();
buffer[0] = 0; if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Debug", &hkey))
if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Spy", &hkey))
{ {
DWORD type, count = sizeof(buffer); 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]));
}
buffer[0] = 0; buffer[0] = 0;
if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Spy", &hkey)) if (!RegQueryValueExA(hkey, "SpyInclude", 0, &type, buffer, &count) &&
{ strcmp( buffer, "INCLUDEALL" ))
DWORD type, count = sizeof(buffer); {
RegQueryValueExA(hkey, "Exclude", 0, &type, buffer, &count); TRACE("Include=%s\n", buffer );
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
for (i = 0; i <= SPY_MAX_MSGNUM; i++) 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; count = sizeof(buffer);
if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Spy", &hkey)) buffer[0] = 0;
{ if (!RegQueryValueExA(hkey, "SpyExclude", 0, &type, buffer, &count))
DWORD type, count = sizeof(buffer); {
if(!RegQueryValueExA(hkey, "ExcludeDWP", 0, &type, buffer, &count)) TRACE("Exclude=%s\n", buffer );
SPY_ExcludeDWP = atoi(buffer); if (!strcmp( buffer, "EXCLUDEALL" ))
RegCloseKey(hkey); 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 */ /* find last good entry in spy notify array and save addr for b-search */