diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index 9dfbccf1b19..1d7450fd7b9 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -7,6 +7,7 @@ SOVERSION = 1.0 C_SRCS = \ critsection.c \ + debugtools.c \ exception.c \ error.c \ file.c \ diff --git a/dlls/ntdll/debugtools.c b/dlls/ntdll/debugtools.c new file mode 100644 index 00000000000..22ceb34c15c --- /dev/null +++ b/dlls/ntdll/debugtools.c @@ -0,0 +1,238 @@ +/* + * Debugging functions + */ + +#include +#include +#include +#include +#include + +#include "debugtools.h" +#include "thread.h" +#include "winbase.h" +#include "winnt.h" +#include "wtypes.h" + +/* ---------------------------------------------------------------------- */ + +struct debug_info +{ + char *str_pos; /* current position in strings buffer */ + char *out_pos; /* current position in output buffer */ + char strings[504]; /* buffer for temporary strings */ + char output[504]; /* current output line */ +}; + +static struct debug_info tmp; + +/* get the debug info pointer for the current thread */ +static inline struct debug_info *get_info(void) +{ + struct debug_info *info = NtCurrentTeb()->debug_info; + if (!info) + { + /* setup the temp structure in case HeapAlloc wants to print something */ + NtCurrentTeb()->debug_info = &tmp; + tmp.str_pos = tmp.strings; + tmp.out_pos = tmp.output; + info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) ); + info->str_pos = info->strings; + info->out_pos = info->output; + NtCurrentTeb()->debug_info = info; + } + return info; +} + +/* allocate some tmp space for a string */ +static void *gimme1(int n) +{ + struct debug_info *info = get_info(); + char *res = info->str_pos; + + if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings; + info->str_pos = res + n; + return res; +} + +/* release extra space that we requested in gimme1() */ +static inline void release( void *ptr ) +{ + struct debug_info *info = NtCurrentTeb()->debug_info; + info->str_pos = ptr; +} + +/* ---------------------------------------------------------------------- */ + +const char *debugstr_an( const char *src, int n ) +{ + char *dst, *res; + + if (!HIWORD(src)) + { + if (!src) return "(null)"; + res = gimme1(6); + sprintf(res, "#%04x", LOWORD(src) ); + return res; + } + if (n < 0) n = 0; + dst = res = gimme1 (n * 4 + 6); + *dst++ = '"'; + while (n-- > 0 && *src) + { + unsigned char c = *src++; + switch (c) + { + case '\n': *dst++ = '\\'; *dst++ = 'n'; break; + case '\r': *dst++ = '\\'; *dst++ = 'r'; break; + case '\t': *dst++ = '\\'; *dst++ = 't'; break; + case '"': *dst++ = '\\'; *dst++ = '"'; break; + case '\\': *dst++ = '\\'; *dst++ = '\\'; break; + default: + if (c >= ' ' && c <= 126) + *dst++ = c; + else + { + *dst++ = '\\'; + *dst++ = '0' + ((c >> 6) & 7); + *dst++ = '0' + ((c >> 3) & 7); + *dst++ = '0' + ((c >> 0) & 7); + } + } + } + *dst++ = '"'; + if (*src) + { + *dst++ = '.'; + *dst++ = '.'; + *dst++ = '.'; + } + *dst++ = '\0'; + release( dst ); + return res; +} + +/* ---------------------------------------------------------------------- */ + +const char *debugstr_wn( const WCHAR *src, int n ) +{ + char *dst, *res; + + if (!HIWORD(src)) + { + if (!src) return "(null)"; + res = gimme1(6); + sprintf(res, "#%04x", LOWORD(src) ); + return res; + } + if (n < 0) n = 0; + dst = res = gimme1 (n * 5 + 7); + *dst++ = 'L'; + *dst++ = '"'; + while (n-- > 0 && *src) + { + WCHAR c = *src++; + switch (c) + { + case '\n': *dst++ = '\\'; *dst++ = 'n'; break; + case '\r': *dst++ = '\\'; *dst++ = 'r'; break; + case '\t': *dst++ = '\\'; *dst++ = 't'; break; + case '"': *dst++ = '\\'; *dst++ = '"'; break; + case '\\': *dst++ = '\\'; *dst++ = '\\'; break; + default: + if (c >= ' ' && c <= 126) + *dst++ = c; + else + { + *dst++ = '\\'; + sprintf(dst,"%04x",c); + dst+=4; + } + } + } + *dst++ = '"'; + if (*src) + { + *dst++ = '.'; + *dst++ = '.'; + *dst++ = '.'; + } + *dst++ = '\0'; + release( dst ); + return res; +} + +/* ---------------------------------------------------------------------- */ + +const char *debugstr_guid( const GUID *id ) +{ + char *str; + + if (!id) return "(null)"; + if (!HIWORD(id)) + { + str = gimme1(12); + sprintf( str, "", LOWORD(id) ); + } + else + { + str = gimme1(40); + sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + id->Data1, id->Data2, id->Data3, + id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3], + id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] ); + } + return str; +} + +/* ---------------------------------------------------------------------- */ + +int wine_dbg_vprintf( const char *format, va_list args ) +{ + struct debug_info *info = get_info(); + + int ret = vsprintf( info->out_pos, format, args ); + char *p = strrchr( info->out_pos, '\n' ); + if (!p) info->out_pos += ret; + else + { + char *pos = info->output; + p++; + write( 2, pos, p - pos ); + /* move beginning of next line to start of buffer */ + while ((*pos = *p++)) pos++; + info->out_pos = pos; + } + return ret; +} + +int wine_dbg_printf(const char *format, ...) +{ + int ret; + va_list valist; + + va_start(valist, format); + ret = wine_dbg_vprintf( format, valist); + va_end(valist); + return ret; +} + +int __wine_dbg_header_err( const char *dbg_channel, const char *func ) +{ + return wine_dbg_printf( "err:%s:%s ", dbg_channel + 1, func ); +} + +int __wine_dbg_header_fixme( const char *dbg_channel, const char *func ) +{ + return wine_dbg_printf( "fixme:%s:%s ", dbg_channel + 1, func ); +} + +int __wine_dbg_header_warn( const char *dbg_channel, const char *func ) +{ + return wine_dbg_printf( "warn:%s:%s ", dbg_channel + 1, func ); +} + +int __wine_dbg_header_trace( const char *dbg_channel, const char *func ) +{ + return wine_dbg_printf( "trace:%s:%s ", dbg_channel + 1, func ); +} diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 77994993d41..1c66a3cd4cf 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1,6 +1,12 @@ name ntdll type win32 +debug_channels (aspi atom cdrom console ddraw debug delayhlp dll dosfs dosmem + elfdll file fixup global heap int int10 int16 int17 int19 int21 + int31 io ldt local module ntdll process profile reg relay resource + segment seh selector server snoop string system tape task thread + thunk timer toolhelp tweak ver virtual vxd win32) + #note that the Zw... functions are alternate names for the #Nt... functions. (see www.sysinternals.com for details) #if you change a Nt.. function DON'T FORGET to change the @@ -1000,6 +1006,20 @@ type win32 @ stub RtlSetPropertySetClassId @ stdcall NtPowerInformation(long long long long long) NtPowerInformation +################## # Wine extensions +# +# All functions must be prefixed with '__wine_' (for internal functions) +# or 'wine_' (for user-visible functions) to avoid namespace conflicts. + +# Exception handling @ cdecl __wine_exception_handler(ptr ptr ptr ptr) __wine_exception_handler @ cdecl __wine_finally_handler(ptr ptr ptr ptr) __wine_finally_handler + +# Debugging interface +@ cdecl __wine_dbg_header_err(ptr str) __wine_dbg_header_err +@ cdecl __wine_dbg_header_fixme(ptr str) __wine_dbg_header_fixme +@ cdecl __wine_dbg_header_warn(ptr str) __wine_dbg_header_warn +@ cdecl __wine_dbg_header_trace(ptr str) __wine_dbg_header_trace +@ cdecl wine_dbg_vprintf(str ptr) wine_dbg_vprintf +@ varargs wine_dbg_printf(str) wine_dbg_printf diff --git a/include/debugdefs.h b/include/debugdefs.h deleted file mode 100644 index 67941f48a20..00000000000 --- a/include/debugdefs.h +++ /dev/null @@ -1,365 +0,0 @@ -/* Do not modify this file -- it is automatically generated! */ - -#include "debugtools.h" - -#define DEBUG_CLASS_COUNT __DBCL_COUNT - -static const char * const debug_cl_name[] = { "fixme", "err", "warn", "trace" }; - -char dbch_accel[] = "\003accel"; -char dbch_advapi[] = "\003advapi"; -char dbch_animate[] = "\003animate"; -char dbch_aspi[] = "\003aspi"; -char dbch_atom[] = "\003atom"; -char dbch_avifile[] = "\003avifile"; -char dbch_bitblt[] = "\003bitblt"; -char dbch_bitmap[] = "\003bitmap"; -char dbch_caret[] = "\003caret"; -char dbch_cdrom[] = "\003cdrom"; -char dbch_class[] = "\003class"; -char dbch_clipboard[] = "\003clipboard"; -char dbch_clipping[] = "\003clipping"; -char dbch_combo[] = "\003combo"; -char dbch_comboex[] = "\003comboex"; -char dbch_comm[] = "\003comm"; -char dbch_commctrl[] = "\003commctrl"; -char dbch_commdlg[] = "\003commdlg"; -char dbch_console[] = "\003console"; -char dbch_crtdll[] = "\003crtdll"; -char dbch_cursor[] = "\003cursor"; -char dbch_datetime[] = "\003datetime"; -char dbch_dc[] = "\003dc"; -char dbch_ddeml[] = "\003ddeml"; -char dbch_ddraw[] = "\003ddraw"; -char dbch_debug[] = "\003debug"; -char dbch_debugstr[] = "\003debugstr"; -char dbch_delayhlp[] = "\003delayhlp"; -char dbch_dialog[] = "\003dialog"; -char dbch_dinput[] = "\003dinput"; -char dbch_dll[] = "\003dll"; -char dbch_dosfs[] = "\003dosfs"; -char dbch_dosmem[] = "\003dosmem"; -char dbch_dplay[] = "\003dplay"; -char dbch_driver[] = "\003driver"; -char dbch_dsound[] = "\003dsound"; -char dbch_edit[] = "\003edit"; -char dbch_elfdll[] = "\003elfdll"; -char dbch_enhmetafile[] = "\003enhmetafile"; -char dbch_event[] = "\003event"; -char dbch_exec[] = "\003exec"; -char dbch_file[] = "\003file"; -char dbch_fixup[] = "\003fixup"; -char dbch_font[] = "\003font"; -char dbch_gdi[] = "\003gdi"; -char dbch_global[] = "\003global"; -char dbch_graphics[] = "\003graphics"; -char dbch_header[] = "\003header"; -char dbch_heap[] = "\003heap"; -char dbch_hook[] = "\003hook"; -char dbch_hotkey[] = "\003hotkey"; -char dbch_icmp[] = "\003icmp"; -char dbch_icon[] = "\003icon"; -char dbch_imagehlp[] = "\003imagehlp"; -char dbch_imagelist[] = "\003imagelist"; -char dbch_imm[] = "\003imm"; -char dbch_int[] = "\003int"; -char dbch_int10[] = "\003int10"; -char dbch_int16[] = "\003int16"; -char dbch_int17[] = "\003int17"; -char dbch_int19[] = "\003int19"; -char dbch_int21[] = "\003int21"; -char dbch_int31[] = "\003int31"; -char dbch_io[] = "\003io"; -char dbch_ipaddress[] = "\003ipaddress"; -char dbch_joystick[] = "\003joystick"; -char dbch_key[] = "\003key"; -char dbch_keyboard[] = "\003keyboard"; -char dbch_ldt[] = "\003ldt"; -char dbch_listbox[] = "\003listbox"; -char dbch_listview[] = "\003listview"; -char dbch_local[] = "\003local"; -char dbch_mci[] = "\003mci"; -char dbch_mcianim[] = "\003mcianim"; -char dbch_mciavi[] = "\003mciavi"; -char dbch_mcicda[] = "\003mcicda"; -char dbch_mcimidi[] = "\003mcimidi"; -char dbch_mciwave[] = "\003mciwave"; -char dbch_mdi[] = "\003mdi"; -char dbch_menu[] = "\003menu"; -char dbch_message[] = "\003message"; -char dbch_metafile[] = "\003metafile"; -char dbch_midi[] = "\003midi"; -char dbch_mmaux[] = "\003mmaux"; -char dbch_mmio[] = "\003mmio"; -char dbch_mmsys[] = "\003mmsys"; -char dbch_mmtime[] = "\003mmtime"; -char dbch_module[] = "\003module"; -char dbch_monthcal[] = "\003monthcal"; -char dbch_mpr[] = "\003mpr"; -char dbch_msacm[] = "\003msacm"; -char dbch_msg[] = "\003msg"; -char dbch_msvideo[] = "\003msvideo"; -char dbch_nativefont[] = "\003nativefont"; -char dbch_nonclient[] = "\003nonclient"; -char dbch_ntdll[] = "\003ntdll"; -char dbch_odbc[] = "\003odbc"; -char dbch_ole[] = "\003ole"; -char dbch_opengl[] = "\003opengl"; -char dbch_pager[] = "\003pager"; -char dbch_palette[] = "\003palette"; -char dbch_pidl[] = "\003pidl"; -char dbch_print[] = "\003print"; -char dbch_process[] = "\003process"; -char dbch_profile[] = "\003profile"; -char dbch_progress[] = "\003progress"; -char dbch_prop[] = "\003prop"; -char dbch_propsheet[] = "\003propsheet"; -char dbch_psapi[] = "\003psapi"; -char dbch_psdrv[] = "\003psdrv"; -char dbch_ras[] = "\003ras"; -char dbch_rebar[] = "\003rebar"; -char dbch_reg[] = "\003reg"; -char dbch_region[] = "\003region"; -char dbch_relay[] = "\003relay"; -char dbch_resource[] = "\003resource"; -char dbch_richedit[] = "\003richedit"; -char dbch_scroll[] = "\003scroll"; -char dbch_segment[] = "\003segment"; -char dbch_seh[] = "\003seh"; -char dbch_selector[] = "\003selector"; -char dbch_sendmsg[] = "\003sendmsg"; -char dbch_server[] = "\003server"; -char dbch_setupapi[] = "\003setupapi"; -char dbch_setupx[] = "\003setupx"; -char dbch_shell[] = "\003shell"; -char dbch_snoop[] = "\003snoop"; -char dbch_sound[] = "\003sound"; -char dbch_static[] = "\003static"; -char dbch_statusbar[] = "\003statusbar"; -char dbch_storage[] = "\003storage"; -char dbch_stress[] = "\003stress"; -char dbch_string[] = "\003string"; -char dbch_syscolor[] = "\003syscolor"; -char dbch_system[] = "\003system"; -char dbch_tab[] = "\003tab"; -char dbch_tape[] = "\003tape"; -char dbch_tapi[] = "\003tapi"; -char dbch_task[] = "\003task"; -char dbch_text[] = "\003text"; -char dbch_thread[] = "\003thread"; -char dbch_thunk[] = "\003thunk"; -char dbch_timer[] = "\003timer"; -char dbch_toolbar[] = "\003toolbar"; -char dbch_toolhelp[] = "\003toolhelp"; -char dbch_tooltips[] = "\003tooltips"; -char dbch_trackbar[] = "\003trackbar"; -char dbch_treeview[] = "\003treeview"; -char dbch_ttydrv[] = "\003ttydrv"; -char dbch_tweak[] = "\003tweak"; -char dbch_typelib[] = "\003typelib"; -char dbch_updown[] = "\003updown"; -char dbch_ver[] = "\003ver"; -char dbch_virtual[] = "\003virtual"; -char dbch_vxd[] = "\003vxd"; -char dbch_wave[] = "\003wave"; -char dbch_win[] = "\003win"; -char dbch_win16drv[] = "\003win16drv"; -char dbch_win32[] = "\003win32"; -char dbch_wing[] = "\003wing"; -char dbch_wininet[] = "\003wininet"; -char dbch_winsock[] = "\003winsock"; -char dbch_winspool[] = "\003winspool"; -char dbch_wnet[] = "\003wnet"; -char dbch_x11[] = "\003x11"; -char dbch_x11drv[] = "\003x11drv"; - -#define DEBUG_CHANNEL_COUNT 166 - -static char * const debug_channels[DEBUG_CHANNEL_COUNT] = { - dbch_accel, - dbch_advapi, - dbch_animate, - dbch_aspi, - dbch_atom, - dbch_avifile, - dbch_bitblt, - dbch_bitmap, - dbch_caret, - dbch_cdrom, - dbch_class, - dbch_clipboard, - dbch_clipping, - dbch_combo, - dbch_comboex, - dbch_comm, - dbch_commctrl, - dbch_commdlg, - dbch_console, - dbch_crtdll, - dbch_cursor, - dbch_datetime, - dbch_dc, - dbch_ddeml, - dbch_ddraw, - dbch_debug, - dbch_debugstr, - dbch_delayhlp, - dbch_dialog, - dbch_dinput, - dbch_dll, - dbch_dosfs, - dbch_dosmem, - dbch_dplay, - dbch_driver, - dbch_dsound, - dbch_edit, - dbch_elfdll, - dbch_enhmetafile, - dbch_event, - dbch_exec, - dbch_file, - dbch_fixup, - dbch_font, - dbch_gdi, - dbch_global, - dbch_graphics, - dbch_header, - dbch_heap, - dbch_hook, - dbch_hotkey, - dbch_icmp, - dbch_icon, - dbch_imagehlp, - dbch_imagelist, - dbch_imm, - dbch_int, - dbch_int10, - dbch_int16, - dbch_int17, - dbch_int19, - dbch_int21, - dbch_int31, - dbch_io, - dbch_ipaddress, - dbch_joystick, - dbch_key, - dbch_keyboard, - dbch_ldt, - dbch_listbox, - dbch_listview, - dbch_local, - dbch_mci, - dbch_mcianim, - dbch_mciavi, - dbch_mcicda, - dbch_mcimidi, - dbch_mciwave, - dbch_mdi, - dbch_menu, - dbch_message, - dbch_metafile, - dbch_midi, - dbch_mmaux, - dbch_mmio, - dbch_mmsys, - dbch_mmtime, - dbch_module, - dbch_monthcal, - dbch_mpr, - dbch_msacm, - dbch_msg, - dbch_msvideo, - dbch_nativefont, - dbch_nonclient, - dbch_ntdll, - dbch_odbc, - dbch_ole, - dbch_opengl, - dbch_pager, - dbch_palette, - dbch_pidl, - dbch_print, - dbch_process, - dbch_profile, - dbch_progress, - dbch_prop, - dbch_propsheet, - dbch_psapi, - dbch_psdrv, - dbch_ras, - dbch_rebar, - dbch_reg, - dbch_region, - dbch_relay, - dbch_resource, - dbch_richedit, - dbch_scroll, - dbch_segment, - dbch_seh, - dbch_selector, - dbch_sendmsg, - dbch_server, - dbch_setupapi, - dbch_setupx, - dbch_shell, - dbch_snoop, - dbch_sound, - dbch_static, - dbch_statusbar, - dbch_storage, - dbch_stress, - dbch_string, - dbch_syscolor, - dbch_system, - dbch_tab, - dbch_tape, - dbch_tapi, - dbch_task, - dbch_text, - dbch_thread, - dbch_thunk, - dbch_timer, - dbch_toolbar, - dbch_toolhelp, - dbch_tooltips, - dbch_trackbar, - dbch_treeview, - dbch_ttydrv, - dbch_tweak, - dbch_typelib, - dbch_updown, - dbch_ver, - dbch_virtual, - dbch_vxd, - dbch_wave, - dbch_win, - dbch_win16drv, - dbch_win32, - dbch_wing, - dbch_wininet, - dbch_winsock, - dbch_winspool, - dbch_wnet, - dbch_x11, - dbch_x11drv -}; - -int dbg_header_err( const char *dbg_channel, const char *func ) -{ - return dbg_printf( "err:%s:%s ", dbg_channel + 1, func ); -} - -int dbg_header_fixme( const char *dbg_channel, const char *func ) -{ - return dbg_printf( "fixme:%s:%s ", dbg_channel + 1, func ); -} - -int dbg_header_warn( const char *dbg_channel, const char *func ) -{ - return dbg_printf( "warn:%s:%s ", dbg_channel + 1, func ); -} - -int dbg_header_trace( const char *dbg_channel, const char *func ) -{ - return dbg_printf( "trace:%s:%s ", dbg_channel + 1, func ); -} diff --git a/include/debugtools.h b/include/debugtools.h index 3624b4bcdd7..01c450372e8 100644 --- a/include/debugtools.h +++ b/include/debugtools.h @@ -40,59 +40,60 @@ enum __DEBUG_CLASS { __DBCL_FIXME, __DBCL_ERR, __DBCL_WARN, __DBCL_TRACE, __DBCL #endif #define __DPRINTF(dbcl,dbch) \ - (!__GET_DEBUGGING(dbcl,(dbch)) || (dbg_header_##dbcl((dbch),__FUNCTION__),0)) ? \ - (void)0 : (void)dbg_printf + (!__GET_DEBUGGING(dbcl,(dbch)) || (__wine_dbg_header_##dbcl((dbch),__FUNCTION__),0)) ? \ + (void)0 : (void)wine_dbg_printf + +extern int __wine_dbg_header_err( const char *dbg_channel, const char *func ); +extern int __wine_dbg_header_warn( const char *dbg_channel, const char *func ); +extern int __wine_dbg_header_fixme( const char *dbg_channel, const char *func ); +extern int __wine_dbg_header_trace( const char *dbg_channel, const char *func ); /* Exported definitions and macros */ /* These function return a printable version of a string, including quotes. The string will be valid for some time, but not indefinitely as strings are re-used. */ -extern LPCSTR debugstr_an (LPCSTR s, int n); -extern LPCSTR debugstr_wn (LPCWSTR s, int n); -extern LPCSTR debugres_a (LPCSTR res); -extern LPCSTR debugres_w (LPCWSTR res); -extern LPCSTR debugstr_guid( const struct _GUID *id ); -extern LPCSTR debugstr_hex_dump (const void *ptr, int len); -extern int dbg_header_err( const char *dbg_channel, const char *func ); -extern int dbg_header_warn( const char *dbg_channel, const char *func ); -extern int dbg_header_fixme( const char *dbg_channel, const char *func ); -extern int dbg_header_trace( const char *dbg_channel, const char *func ); -extern int dbg_vprintf( const char *format, va_list args ); +extern const char *debugstr_an (const char * s, int n); +extern const char *debugstr_wn (const WCHAR *s, int n); +extern const char *debugstr_guid( const struct _GUID *id ); -static inline LPCSTR debugstr_a( LPCSTR s ) { return debugstr_an( s, 80 ); } -static inline LPCSTR debugstr_w( LPCWSTR s ) { return debugstr_wn( s, 80 ); } +extern int wine_dbg_vprintf( const char *format, va_list args ); + +inline static const char *debugstr_a( const char *s ) { return debugstr_an( s, 80 ); } +inline static const char *debugstr_w( const WCHAR *s ) { return debugstr_wn( s, 80 ); } +inline static const char *debugres_a( const char *s ) { return debugstr_an( s, 80 ); } +inline static const char *debugres_w( const WCHAR *s ) { return debugstr_wn( s, 80 ); } #ifdef __GNUC__ -extern int dbg_printf(const char *format, ...) __attribute__((format (printf,1,2))); +extern int wine_dbg_printf(const char *format, ...) __attribute__((format (printf,1,2))); #else -extern int dbg_printf(const char *format, ...); +extern int wine_dbg_printf(const char *format, ...); #endif -#define TRACE __DPRINTF(trace,__dbch_default) -#define TRACE_(ch) __DPRINTF(trace,dbch_##ch) -#define TRACE_ON(ch) __GET_DEBUGGING(trace,dbch_##ch) +#define TRACE __DPRINTF(trace,__wine_dbch___default) +#define TRACE_(ch) __DPRINTF(trace,__wine_dbch_##ch) +#define TRACE_ON(ch) __GET_DEBUGGING(trace,__wine_dbch_##ch) -#define WARN __DPRINTF(warn,__dbch_default) -#define WARN_(ch) __DPRINTF(warn,dbch_##ch) -#define WARN_ON(ch) __GET_DEBUGGING(warn,dbch_##ch) +#define WARN __DPRINTF(warn,__wine_dbch___default) +#define WARN_(ch) __DPRINTF(warn,__wine_dbch_##ch) +#define WARN_ON(ch) __GET_DEBUGGING(warn,__wine_dbch_##ch) -#define FIXME __DPRINTF(fixme,__dbch_default) -#define FIXME_(ch) __DPRINTF(fixme,dbch_##ch) -#define FIXME_ON(ch) __GET_DEBUGGING(fixme,dbch_##ch) +#define FIXME __DPRINTF(fixme,__wine_dbch___default) +#define FIXME_(ch) __DPRINTF(fixme,__wine_dbch_##ch) +#define FIXME_ON(ch) __GET_DEBUGGING(fixme,__wine_dbch_##ch) #undef ERR /* Solaris got an 'ERR' define in */ -#define ERR __DPRINTF(err,__dbch_default) -#define ERR_(ch) __DPRINTF(err,dbch_##ch) -#define ERR_ON(ch) __GET_DEBUGGING(err,dbch_##ch) +#define ERR __DPRINTF(err,__wine_dbch___default) +#define ERR_(ch) __DPRINTF(err,__wine_dbch_##ch) +#define ERR_ON(ch) __GET_DEBUGGING(err,__wine_dbch_##ch) #define DECLARE_DEBUG_CHANNEL(ch) \ - extern char dbch_##ch[]; + extern char __wine_dbch_##ch[]; #define DEFAULT_DEBUG_CHANNEL(ch) \ - extern char dbch_##ch[]; static char * const __dbch_default = dbch_##ch; + extern char __wine_dbch_##ch[]; static char * const __wine_dbch___default = __wine_dbch_##ch; -#define DPRINTF dbg_printf -#define MESSAGE dbg_printf +#define DPRINTF wine_dbg_printf +#define MESSAGE wine_dbg_printf #endif /* __WINE__ */ diff --git a/include/main.h b/include/main.h index 447207203aa..3a90d17df91 100644 --- a/include/main.h +++ b/include/main.h @@ -9,7 +9,6 @@ extern BOOL MAIN_MainInit(void); extern void MAIN_WineInit(void); -extern void MAIN_ParseDebugOptions(const char *options); extern BOOL RELAY_Init(void); extern int RELAY_ShowDebugmsgRelay(const char *func); diff --git a/library/Makefile.in b/library/Makefile.in index a6d68837a1d..224f1fd2200 100644 --- a/library/Makefile.in +++ b/library/Makefile.in @@ -9,6 +9,7 @@ SOVERSION = 1.0 SONAME = libwine.so C_SRCS = \ + debug.c \ port.c all: libwine.$(LIBEXT) diff --git a/library/debug.c b/library/debug.c new file mode 100644 index 00000000000..3f38487b4a5 --- /dev/null +++ b/library/debug.c @@ -0,0 +1,118 @@ +/* + * Management of the debugging channels + * + * Copyright 2000 Alexandre Julliard + */ + +#include +#include +#include +#include + +struct dll +{ + struct dll *next; /* linked list of dlls */ + struct dll *prev; + char * const *channels; /* array of channels */ + int nb_channels; /* number of channels in array */ +}; + +static struct dll *first_dll; + +struct option +{ + struct option *next; /* next option in list */ + unsigned char set; /* bits to set */ + unsigned char clear; /* bits to clear */ + char name[14]; /* channel name, or empty for "all" */ +}; + +static struct option *first_option; +static struct option *last_option; + + +static int cmp_name( const void *p1, const void *p2 ) +{ + const char *name = p1; + const char * const *chan = p2; + return strcmp( name, *chan + 1 ); +} + +/* apply a debug option to the channels of a given dll */ +static void apply_option( struct dll *dll, const struct option *opt ) +{ + if (opt->name[0]) + { + char **dbch = bsearch( opt->name, dll->channels, dll->nb_channels, + sizeof(*dll->channels), cmp_name ); + if (dbch) **dbch = (**dbch & ~opt->clear) | opt->set; + } + else /* all */ + { + int i; + for (i = 0; i < dll->nb_channels; i++) + dll->channels[i][0] = (dll->channels[i][0] & ~opt->clear) | opt->set; + } +} + +/* register a new set of channels for a dll */ +void *wine_dbg_register( char * const *channels, int nb ) +{ + struct option *opt = first_option; + struct dll *dll = malloc( sizeof(*dll) ); + if (dll) + { + dll->channels = channels; + dll->nb_channels = nb; + dll->prev = NULL; + if ((dll->next = first_dll)) dll->next->prev = dll; + first_dll = dll; + + /* apply existing options to this dll */ + while (opt) + { + apply_option( dll, opt ); + opt = opt->next; + } + } + return dll; +} + + +/* unregister a set of channels; must pass the pointer obtained from wine_dbg_register */ +void wine_dbg_unregister( void *channel ) +{ + struct dll *dll = channel; + if (dll) + { + if (dll->next) dll->next->prev = dll->prev; + if (dll->prev) dll->prev->next = dll->next; + else first_dll = dll->next; + free( dll ); + } +} + + +/* add a new debug option at the end of the option list */ +void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear ) +{ + struct dll *dll = first_dll; + struct option *opt; + + if (!(opt = malloc( sizeof(*opt) ))) return; + opt->next = NULL; + opt->set = set; + opt->clear = clear; + strncpy( opt->name, name, sizeof(opt->name) ); + opt->name[sizeof(opt->name)-1] = 0; + if (last_option) last_option->next = opt; + else first_option = opt; + last_option = opt; + + /* apply option to all existing dlls */ + while (dll) + { + apply_option( dll, opt ); + dll = dll->next; + } +} diff --git a/misc/Makefile.in b/misc/Makefile.in index 90f1dda65d5..84eaf586b21 100644 --- a/misc/Makefile.in +++ b/misc/Makefile.in @@ -9,7 +9,6 @@ MODULE = misc C_SRCS = \ cdrom.c \ cpu.c \ - debugstr.c \ error.c \ ext_debugger.c \ lstr.c \ diff --git a/misc/debugstr.c b/misc/debugstr.c deleted file mode 100644 index 021007ab6e0..00000000000 --- a/misc/debugstr.c +++ /dev/null @@ -1,332 +0,0 @@ -#include -#include -#include -#include -#include - -#include "debugtools.h" -#include "thread.h" -#include "winbase.h" -#include "winnt.h" -#include "wtypes.h" - -/* ---------------------------------------------------------------------- */ - -struct debug_info -{ - char *str_pos; /* current position in strings buffer */ - char *out_pos; /* current position in output buffer */ - char strings[500]; /* buffer for temporary strings */ - char output[500]; /* current output line */ -}; - -static struct debug_info tmp; - -static inline struct debug_info *get_info(void) -{ - struct debug_info *info = NtCurrentTeb()->debug_info; - if (!info) - { - /* setup the temp structure in case HeapAlloc wants to print something */ - NtCurrentTeb()->debug_info = &tmp; - tmp.str_pos = tmp.strings; - tmp.out_pos = tmp.output; - info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) ); - info->str_pos = info->strings; - info->out_pos = info->output; - NtCurrentTeb()->debug_info = info; - } - return info; -} - -/* ---------------------------------------------------------------------- */ - -static void * -gimme1 (int n) -{ - struct debug_info *info = get_info(); - char *res = info->str_pos; - - if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings; - info->str_pos = res + n; - return res; -} - -/* ---------------------------------------------------------------------- */ - -/* release extra space that we requested in gimme1() */ -static inline void release( void *ptr ) -{ - struct debug_info *info = NtCurrentTeb()->debug_info; - info->str_pos = ptr; -} - -/* ---------------------------------------------------------------------- */ - -LPCSTR debugstr_an (LPCSTR src, int n) -{ - LPSTR dst, res; - - if (!src) return "(null)"; - if (n < 0) n = 0; - dst = res = gimme1 (n * 4 + 6); - *dst++ = '"'; - while (n-- > 0 && *src) - { - BYTE c = *src++; - switch (c) - { - case '\n': *dst++ = '\\'; *dst++ = 'n'; break; - case '\r': *dst++ = '\\'; *dst++ = 'r'; break; - case '\t': *dst++ = '\\'; *dst++ = 't'; break; - case '"': *dst++ = '\\'; *dst++ = '"'; break; - case '\\': *dst++ = '\\'; *dst++ = '\\'; break; - default: - if (c >= ' ' && c <= 126) - *dst++ = c; - else - { - *dst++ = '\\'; - *dst++ = '0' + ((c >> 6) & 7); - *dst++ = '0' + ((c >> 3) & 7); - *dst++ = '0' + ((c >> 0) & 7); - } - } - } - *dst++ = '"'; - if (*src) - { - *dst++ = '.'; - *dst++ = '.'; - *dst++ = '.'; - } - *dst++ = '\0'; - release( dst ); - return res; -} - -/* ---------------------------------------------------------------------- */ - -LPCSTR debugstr_wn (LPCWSTR src, int n) -{ - LPSTR dst, res; - - if (!src) return "(null)"; - if (n < 0) n = 0; - dst = res = gimme1 (n * 5 + 7); - *dst++ = 'L'; - *dst++ = '"'; - while (n-- > 0 && *src) - { - WORD c = *src++; - switch (c) - { - case '\n': *dst++ = '\\'; *dst++ = 'n'; break; - case '\r': *dst++ = '\\'; *dst++ = 'r'; break; - case '\t': *dst++ = '\\'; *dst++ = 't'; break; - case '"': *dst++ = '\\'; *dst++ = '"'; break; - case '\\': *dst++ = '\\'; *dst++ = '\\'; break; - default: - if (c >= ' ' && c <= 126) - *dst++ = c; - else - { - *dst++ = '\\'; - sprintf(dst,"%04x",c); - dst+=4; - } - } - } - *dst++ = '"'; - if (*src) - { - *dst++ = '.'; - *dst++ = '.'; - *dst++ = '.'; - } - *dst++ = '\0'; - release( dst ); - return res; -} - -/* ---------------------------------------------------------------------- */ -/* This routine returns a nicely formated name of the resource res - If the resource name is a string, it will return '' - If it is a number, it will return #<4-digit-hex-number> */ -LPCSTR debugres_a( LPCSTR res ) -{ - char *resname; - if (HIWORD(res)) return debugstr_a(res); - resname = gimme1(6); - sprintf(resname, "#%04x", LOWORD(res) ); - return resname; -} - -LPCSTR debugres_w( LPCWSTR res ) -{ - char *resname; - if (HIWORD(res)) return debugstr_w(res); - resname = gimme1(6); - sprintf( resname, "#%04x", LOWORD(res) ); - return resname; -} - -/* ---------------------------------------------------------------------- */ - -LPCSTR debugstr_guid( const GUID *id ) -{ - LPSTR str; - - if (!id) return "(null)"; - if (!HIWORD(id)) - { - str = gimme1(12); - sprintf( str, "", LOWORD(id) ); - } - else - { - str = gimme1(40); - sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", - id->Data1, id->Data2, id->Data3, - id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3], - id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] ); - } - return str; -} - -/* ---------------------------------------------------------------------- */ - -int dbg_vprintf( const char *format, va_list args ) -{ - struct debug_info *info = get_info(); - - int ret = vsprintf( info->out_pos, format, args ); - char *p = strrchr( info->out_pos, '\n' ); - if (!p) info->out_pos += ret; - else - { - char *pos = info->output; - p++; - write( 2, pos, p - pos ); - /* move beginning of next line to start of buffer */ - while ((*pos = *p++)) pos++; - info->out_pos = pos; - } - return ret; -} - -/* ---------------------------------------------------------------------- */ - -int dbg_printf(const char *format, ...) -{ - int ret; - va_list valist; - - va_start(valist, format); - ret = dbg_vprintf( format, valist); - va_end(valist); - return ret; -} - - -/*--< Function >--------------------------------------------------------- -** -** debugstr_hex_dump -** -** Description: -** This function creates a hex dump, with a readable ascii -** section, for displaying memory. -** -** Parameters: -** 1. ptr Pointer to memory -** 2. len How much to dump. -** -** Returns: -** Temporarily allocated buffer, with the hex dump in it. -** Don't rely on this pointer being around for very long, just -** long enough to use it in a TRACE statement; e.g.: -** TRACE("struct dump is \n%s", debugstr_hex_dump(&x, sizeof(x))); -** -**-------------------------------------------------------------------------*/ -LPCSTR debugstr_hex_dump (const void *ptr, int len) -{ - /* Locals */ - char dumpbuf[59]; - char charbuf[20]; - char tempbuf[8]; - const char *p; - int i; - unsigned int nosign; - LPSTR dst; - LPSTR outptr; - -/* Begin function dbg_hex_dump */ - - /*----------------------------------------------------------------------- - ** Allocate an output buffer - ** A reasonable value is one line overhand (80 chars), and - ** then one line (80) for every 16 bytes. - **---------------------------------------------------------------------*/ - outptr = dst = gimme1 ((len * (80 / 16)) + 80); - - /*----------------------------------------------------------------------- - ** Loop throught the input buffer, one character at a time - **---------------------------------------------------------------------*/ - for (i = 0, p = ptr; (i < len); i++, p++) - { - - /*------------------------------------------------------------------- - ** If we're just starting a line, - ** we need to possibly flush the old line, and then - ** intialize the line buffer. - **-----------------------------------------------------------------*/ - if ((i % 16) == 0) - { - if (i) - { - sprintf(outptr, " %-43.43s %-16.16s\n", dumpbuf, charbuf); - outptr += strlen(outptr); - } - sprintf (dumpbuf, "%04x: ", i); - strcpy (charbuf, ""); - } - - /*------------------------------------------------------------------- - ** Add the current data byte to the dump section. - **-----------------------------------------------------------------*/ - nosign = (unsigned char) *p; - sprintf (tempbuf, "%02X", nosign); - - /*------------------------------------------------------------------- - ** If we're two DWORDS through, add a hyphen for readability, - ** if it's a DWORD boundary, add a space for more - ** readability. - **-----------------------------------------------------------------*/ - if ((i % 16) == 7) - strcat(tempbuf, " - "); - else if ( (i % 4) == 3) - strcat(tempbuf, " "); - strcat (dumpbuf, tempbuf); - - /*------------------------------------------------------------------- - ** Add the current byte to the character display part of the - ** hex dump - **-----------------------------------------------------------------*/ - sprintf (tempbuf, "%c", isprint(*p) ? *p : '.'); - strcat (charbuf, tempbuf); - } - - /*----------------------------------------------------------------------- - ** Flush the last line, if any - **---------------------------------------------------------------------*/ - if (i > 0) - { - sprintf(outptr, " %-43.43s %-16.16s\n", dumpbuf, charbuf); - outptr += strlen(outptr); - } - - return(dst); -} /* End function dbg_hex_dump */ - - - diff --git a/misc/main.c b/misc/main.c index 6233840eaf8..357db380417 100644 --- a/misc/main.c +++ b/misc/main.c @@ -27,11 +27,13 @@ #include "msdos.h" #include "options.h" #include "debugtools.h" -#include "debugdefs.h" #include "module.h" #include "tweak.h" +DECLARE_DEBUG_CHANNEL(file); + +#if 0 /*********************************************************************** * MAIN_ParseDebugOptions * @@ -176,6 +178,7 @@ void MAIN_ParseDebugOptions( const char *arg ) MESSAGE("\n\n"); ExitProcess(1); } +#endif /*********************************************************************** * MAIN_WineInit diff --git a/misc/options.c b/misc/options.c index e1e715495b3..575067f7ac8 100644 --- a/misc/options.c +++ b/misc/options.c @@ -60,6 +60,7 @@ static char *xstrdup( const char *str ) } static void do_config( const char *arg ); +static void do_debugmsg( const char *arg ); static void do_desktop( const char *arg ); static void do_display( const char *arg ); static void do_dll( const char *arg ); @@ -73,7 +74,7 @@ static const struct option option_table[] = { { "config", 0, 1, 0, do_config, "--config name Specify config file to use" }, - { "debugmsg", 0, 1, 1, MAIN_ParseDebugOptions, + { "debugmsg", 0, 1, 1, do_debugmsg, "--debugmsg name Turn debugging-messages on or off" }, { "desktop", 0, 1, 1, do_desktop, "--desktop geom Use a desktop window of the given geometry" }, @@ -157,6 +158,62 @@ static void do_config( const char *arg ) Options.configFileName = xstrdup( arg ); } +static void do_debugmsg( const char *arg ) +{ + extern void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear ); + static const char * const debug_class_names[__DBCL_COUNT] = { "fixme", "err", "warn", "trace" }; + + char *opt, *options = strdup(arg); + int i; + + if (!(opt = strtok( options, "," ))) goto error; + do + { + 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 < __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 == __DBCL_COUNT) goto error; /* class name not found */ + } + 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 ); + 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 < __DBCL_COUNT; i++) MESSAGE( "%-9s", debug_class_names[i] ); + MESSAGE("\n\n"); + ExitProcess(1); +} + + static void remove_options( char *argv[], int pos, int count, int inherit ) { if (inherit) diff --git a/relay32/builtin32.c b/relay32/builtin32.c index cdb288c098f..e741bc98139 100644 --- a/relay32/builtin32.c +++ b/relay32/builtin32.c @@ -249,7 +249,7 @@ static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr ) fixup_rva_ptrs( &exports->AddressOfNameOrdinals, addr, 1 ); /* Setup relay debugging entry points */ - if (WARN_ON(relay) || TRACE_ON(relay)) RELAY_SetupDLL( addr ); + if (TRACE_ON(relay)) RELAY_SetupDLL( addr ); } return (HMODULE)addr; diff --git a/tools/find_debug_channels b/tools/find_debug_channels deleted file mode 100755 index 05377e82c96..00000000000 --- a/tools/find_debug_channels +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh -# -# This script scans the whole source code for symbols of the form -# 'xxx(yyy' where: -# xxx is either DECLARE_DEBUG_CHANNEL or DEFAULT_DEBUG_CHANNEL -# yyy is a C identifier -# It outputs on the standard output a sorted list of the -# yyy identifiers found in the .c files. -# Each identifier is reported once. Header files are not scanned. -# -# The script can be given an argument that specifies the files to be -# searched according to the following scheme: -# - if the argument does not contain a slash (/), the script -# will search the tree rooted in the current directory for -# files that match that description. You can also pass -# wildcard arguments, but remember to quote them to prevent -# expansion by the shell -# - if the argument does contain a slash, only that file is -# searched -# - if no argument is given, the argument defaults to "*.c" -# that is, all C files are searched. -# - if more than one argument is given, only the listed files are -# searched. Note that in this case, the script will not -# attempt to find them in some subdirectories, but rather -# it will try to open them in the current directory. -# Thus, if you want to disable the automatic searching when the file -# name does not contain a /, either prefix the filename with ./ -# or add /dev/null as another argument. -# -# Dimitrie O. Paun -# Patrik Stridvall -# - -case "$#" in - 0 | 1) files="${1:-*.c}" - if [ "`echo "$files" | sed 's/^\(.*\)\/$/\1/g'`" = "$files" ]; then - files=`find . -name "$files" -print` - fi;; - * ) files="$@";; -esac - -( -grep -h "DECLARE_DEBUG_CHANNEL *(" $files /dev/null | \ - sed 's/.*DECLARE_DEBUG_CHANNEL( *\([A-Za-z0-9_]*\) *).*/\1/g' -grep -h "DEFAULT_DEBUG_CHANNEL *(" $files /dev/null | \ - sed 's/.*DEFAULT_DEBUG_CHANNEL( *\([A-Za-z0-9_]*\) *).*/\1/g' -) | sort | uniq diff --git a/tools/make_debug b/tools/make_debug index e5a59f0044a..7916f8ec529 100755 --- a/tools/make_debug +++ b/tools/make_debug @@ -1,60 +1,56 @@ -#!/bin/sh +#!/usr/bin/perl # -# This script generates the required file for supporting the debug -# channels used throught the code. -# The generated file is -# include/debugdefs.h -# The script must be run in the root directory of the project. +# Update the list of debug channels of a given spec file # -# Dimitrie O. Paun -# Patrik Stridvall +# Copyright 2000 Alexandre Julliard +# +# Usage: make_debug spec_file [source_files...] # -DEBUG_CHANNELS=`tools/find_debug_channels` +die "Usage: make_debug spec_file [source]\n" unless @ARGV; -exec > include/debugdefs.h +$SPEC = shift @ARGV; -cat <) + { + if (/DECLARE_DEBUG_CHANNEL\s*\(\s*([A-Za-z0-9_]+)\s*\)/) { $channels{$1} = 1; } + if (/DEFAULT_DEBUG_CHANNEL\s*\(\s*([A-Za-z0-9_]+)\s*\)/) { $channels{$1} = 1; } + } } -EOF -done +@dbg_channels = sort keys %channels; + +# read the whole spec file +undef $/; +open SPEC or die "Cannot open $SPEC\n"; +$spec = ; +close SPEC; + +# build the new channel list +$channel_str = "debug_channels ("; +$pos = length($channel_str); +for ($i = 0; $i <= $#dbg_channels; $i++) +{ + $channel_str .= $dbg_channels[$i]; + $pos += length($dbg_channels[$i]); + if ($i < $#dbg_channels) + { + if ($pos >= 75) { $pos = 16; $channel_str .= "\n" . (" " x $pos); } + else { $channel_str .= " "; $pos++; } + } +} +$channel_str .= ")"; + +# replace the list in the spec file +if (!($spec =~ s/debug_channels\s*\(([^)]*)\)/$channel_str/)) +{ + die "Could not replace debug_channels\n" if @dbg_channels; + exit 0; +} + +# output the modified spec file +open OUTPUT, ">$SPEC" or die "Cannot modify $SPEC\n"; +print OUTPUT $spec; +close OUTPUT;