Reactos
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}