Skip to content

Commit d2753d6

Browse files
committed
[RTL] Add minimal wine debug support functions
1 parent 626b06b commit d2753d6

File tree

3 files changed

+189
-1
lines changed

3 files changed

+189
-1
lines changed

modules/rostests/apitests/rtl/testlist.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#define __ROS_LONG64__
2-
2+
#define wine_dbgstr_wn wine_dbgstr_wn_
33
#define STANDALONE
44
#include <apitest.h>
55

sdk/lib/rtl/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ endif()
2323

2424
list(APPEND SOURCE
2525
${RTL_WINE_SOURCE}
26+
wine_debug.c
2627
access.c
2728
acl.c
2829
appverifier.c

sdk/lib/rtl/wine_debug.c

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
2+
#define WIN32_NO_STATUS
3+
#include <windef.h>
4+
#include <ndk/rtlfuncs.h>
5+
#include <wine/debug.h>
6+
7+
NTSTATUS NTAPI vDbgPrintExWithPrefix(PCCH, ULONG, ULONG, PCCH, va_list);
8+
9+
static struct
10+
{
11+
HANDLE thread;
12+
void* allocations;
13+
} s_alloactions[32];
14+
15+
static 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+
28+
static 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+
51+
static 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+
71+
static 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+
91+
const 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 */
108+
const 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+
119+
const 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 */
136+
LPCSTR debugstr_us( const UNICODE_STRING *us )
137+
{
138+
if (!us) return "<null>";
139+
return debugstr_wn(us->Buffer, us->Length / sizeof(WCHAR));
140+
}
141+
142+
static int default_dbg_vprintf( const char *format, va_list args )
143+
{
144+
return vDbgPrintExWithPrefix("", -1, 0, format, args);
145+
}
146+
147+
int 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+
159+
static 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+
175+
int 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+
}

0 commit comments

Comments
 (0)