Reactos
at master 187 lines 4.3 kB view raw
1 2#define WIN32_NO_STATUS 3#include <windef.h> 4#include <ndk/rtlfuncs.h> 5#include <wine/debug.h> 6 7NTSTATUS NTAPI vDbgPrintExWithPrefix(PCCH, ULONG, ULONG, PCCH, va_list); 8 9static struct 10{ 11 HANDLE thread; 12 void* allocations; 13} s_alloactions[32]; 14 15static int find_thread_slot() 16{ 17 HANDLE thread = NtCurrentTeb()->ClientId.UniqueThread; 18 for (int i = 0; i < ARRAYSIZE(s_alloactions); i++) 19 { 20 if (s_alloactions[i].thread == thread) 21 { 22 return i; 23 } 24 } 25 return -1; 26} 27 28static int get_thread_slot() 29{ 30 int slot = find_thread_slot(); 31 if (slot != -1) 32 { 33 return slot; 34 } 35 36 HANDLE thread = NtCurrentTeb()->ClientId.UniqueThread; 37 for (int i = 0; i < ARRAYSIZE(s_alloactions); i++) 38 { 39 if (s_alloactions[i].thread == NULL) 40 { 41 if (InterlockedCompareExchangePointer(&s_alloactions[i].thread, thread, NULL) == NULL) 42 { 43 return i; 44 } 45 } 46 } 47 48 return -1; 49} 50 51static char *alloc_buffer(size_t size) 52{ 53 int slot = get_thread_slot(); 54 if (slot == -1) 55 { 56 return NULL; 57 } 58 59 void** buffer = (void**)RtlAllocateHeap(RtlGetProcessHeap(), 0, size + sizeof(void*)); 60 if (buffer == NULL) 61 { 62 return NULL; 63 } 64 65 *buffer = s_alloactions[slot].allocations; 66 s_alloactions[slot].allocations = buffer; 67 68 return (char*)(buffer + 1); 69} 70 71static void free_buffers(void) 72{ 73 int slot = find_thread_slot(); 74 if (slot != -1) 75 { 76 return; 77 } 78 79 void* buffer = s_alloactions[slot].allocations; 80 while (buffer != NULL) 81 { 82 void* next = *(void**)buffer; 83 RtlFreeHeap(RtlGetProcessHeap(), 0, buffer); 84 buffer = next; 85 } 86 87 s_alloactions[slot].allocations = NULL; 88 s_alloactions[slot].thread = NULL; 89} 90 91const char *wine_dbg_vsprintf(const char *format, va_list valist) 92{ 93 char* buffer; 94 int len; 95 96 len = vsnprintf(NULL, 0, format, valist); 97 buffer = alloc_buffer(len + 1); 98 if (buffer == NULL) 99 { 100 return "<allocation failed>"; 101 } 102 len = vsnprintf(buffer, len, format, valist); 103 buffer[len] = 0; 104 return buffer; 105} 106 107/* printf with temp buffer allocation */ 108const char *wine_dbg_sprintf( const char *format, ... ) 109{ 110 const char *ret; 111 va_list valist; 112 113 va_start(valist, format); 114 ret = wine_dbg_vsprintf( format, valist ); 115 va_end(valist); 116 return ret; 117} 118 119const char *wine_dbgstr_wn( const WCHAR *str, int n ) 120{ 121 if (!((ULONG_PTR)str >> 16)) 122 { 123 if (!str) return "(null)"; 124 return wine_dbg_sprintf("#%04x", LOWORD(str) ); 125 } 126 if (n == -1) 127 { 128 n = (int)wcslen(str); 129 } 130 if (n < 0) n = 0; 131 132 return wine_dbg_sprintf("%.*S", n, str); 133} 134 135/* From wine/dlls/ntdll/misc.c */ 136LPCSTR debugstr_us( const UNICODE_STRING *us ) 137{ 138 if (!us) return "<null>"; 139 return debugstr_wn(us->Buffer, us->Length / sizeof(WCHAR)); 140} 141 142static int default_dbg_vprintf( const char *format, va_list args ) 143{ 144 return vDbgPrintExWithPrefix("", -1, 0, format, args); 145} 146 147int wine_dbg_printf(const char *format, ... ) 148{ 149 int ret; 150 va_list valist; 151 152 va_start(valist, format); 153 ret = default_dbg_vprintf(format, valist); 154 va_end(valist); 155 free_buffers(); 156 return ret; 157} 158 159static int winefmt_default_dbg_vlog( enum __wine_debug_class cls, struct __wine_debug_channel *channel, 160 const char *file, const char *func, const int line, const char *format, va_list args ) 161{ 162 int ret = 0; 163 164 ret += wine_dbg_printf("%04x:", HandleToULong(NtCurrentTeb()->ClientId.UniqueProcess) ); 165 ret += wine_dbg_printf("%04x:", HandleToULong(NtCurrentTeb()->ClientId.UniqueThread) ); 166 167 if (format) 168 ret += default_dbg_vprintf(format, args); 169 return ret; 170} 171 172#define __wine_dbg_get_channel_flags(channel) \ 173 ((channel) ? (channel)->flags : 0) 174 175int ros_dbg_log( enum __wine_debug_class cls, struct __wine_debug_channel *channel, 176 const char *file, const char *func, const int line, const char *format, ... ) 177{ 178 int ret; 179 va_list valist; 180 181 if (!(__wine_dbg_get_channel_flags(channel) & (1 << cls))) return -1; 182 183 va_start(valist, format); 184 ret = winefmt_default_dbg_vlog(cls, channel, file, func, line, format, valist); 185 va_end(valist); 186 return ret; 187}