FreeRDP
Loading...
Searching...
No Matches
windows/debug.c
1
21#include <stdio.h>
22#include <fcntl.h>
23
24#include <io.h>
25#include <windows.h>
26#include <dbghelp.h>
27
28#include "debug.h"
29
30#ifndef MIN
31#define MIN(a, b) (a) < (b) ? (a) : (b)
32#endif
33
34typedef struct
35{
36 PVOID* stack;
37 ULONG used;
38 ULONG max;
39} t_win_stack;
40
41void winpr_win_backtrace_free(void* buffer)
42{
43 t_win_stack* data = (t_win_stack*)buffer;
44 if (!data)
45 return;
46
47 free(data->stack);
48 free(data);
49}
50
51void* winpr_win_backtrace(DWORD size)
52{
53 HANDLE process = GetCurrentProcess();
54 t_win_stack* data = calloc(1, sizeof(t_win_stack));
55
56 if (!data)
57 return NULL;
58
59 data->max = size;
60 data->stack = calloc(data->max, sizeof(PVOID));
61
62 if (!data->stack)
63 {
64 free(data);
65 return NULL;
66 }
67
68 SymInitialize(process, NULL, TRUE);
69 data->used = RtlCaptureStackBackTrace(2, size, data->stack, NULL);
70 return data;
71}
72
73char** winpr_win_backtrace_symbols(void* buffer, size_t* used)
74{
75 if (used)
76 *used = 0;
77
78 if (!buffer)
79 return NULL;
80
81 {
82 size_t line_len = 1024;
83 HANDLE process = GetCurrentProcess();
84 t_win_stack* data = (t_win_stack*)buffer;
85 size_t array_size = data->used * sizeof(char*);
86 size_t lines_size = data->used * line_len;
87 char** vlines = calloc(1, array_size + lines_size);
88 SYMBOL_INFO* symbol = calloc(1, sizeof(SYMBOL_INFO) + line_len * sizeof(char));
89 IMAGEHLP_LINE64* line = (IMAGEHLP_LINE64*)calloc(1, sizeof(IMAGEHLP_LINE64));
90
91 if (!vlines || !symbol || !line)
92 {
93 free(vlines);
94 free(symbol);
95 free(line);
96 return NULL;
97 }
98
99 line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
100 symbol->MaxNameLen = (ULONG)line_len;
101 symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
102
103 /* Set the pointers in the allocated buffer's initial array section */
104 for (size_t i = 0; i < data->used; i++)
105 vlines[i] = (char*)vlines + array_size + i * line_len;
106
107 for (size_t i = 0; i < data->used; i++)
108 {
109 DWORD64 address = (DWORD64)(data->stack[i]);
110 DWORD displacement;
111 SymFromAddr(process, address, 0, symbol);
112
113 if (SymGetLineFromAddr64(process, address, &displacement, line))
114 {
115 sprintf_s(vlines[i], line_len, "%016" PRIx64 ": %s in %s:%" PRIu32, symbol->Address,
116 symbol->Name, line->FileName, line->LineNumber);
117 }
118 else
119 sprintf_s(vlines[i], line_len, "%016" PRIx64 ": %s", symbol->Address, symbol->Name);
120 }
121
122 if (used)
123 *used = data->used;
124
125 free(symbol);
126 free(line);
127 return vlines;
128 }
129}
130
131char* winpr_win_strerror(DWORD dw, char* dmsg, size_t size)
132{
133 DWORD nSize = 0;
134 DWORD dwFlags = 0;
135 LPTSTR msg = NULL;
136 BOOL alloc = FALSE;
137 dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
138#ifdef FORMAT_MESSAGE_ALLOCATE_BUFFER
139 alloc = TRUE;
140 dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
141#else
142 nSize = (DWORD)(size * sizeof(WCHAR));
143 msg = (LPTSTR)calloc(nSize, sizeof(WCHAR));
144#endif
145 const DWORD rc = FormatMessage(dwFlags, NULL, dw, 0, alloc ? (LPTSTR)&msg : msg, nSize, NULL);
146
147 if (rc > 0)
148 {
149#if defined(UNICODE)
150 (void)WideCharToMultiByte(CP_ACP, 0, msg, (int)rc, dmsg, (int)(MIN(size - 1, INT_MAX)),
151 NULL, NULL);
152#else /* defined(UNICODE) */
153 memcpy(dmsg, msg, MIN(rc, size - 1));
154#endif /* defined(UNICODE) */
155 dmsg[MIN(rc, size - 1)] = 0;
156#ifdef FORMAT_MESSAGE_ALLOCATE_BUFFER
157 LocalFree(msg);
158#else
159 free(msg);
160#endif
161 }
162 else
163 {
164 _snprintf(dmsg, size, "FAILURE: 0x%08" PRIX32 "", GetLastError());
165 }
166
167 return dmsg;
168}