[INCLUDES/WINE] Update rbtree.h. [D3DCOMPILER_43][DBGHELP][WINED3D] Reflect the rbtre...
[reactos.git] / reactos / dll / win32 / dbghelp / source.c
1 /*
2 * File source.c - source files management
3 *
4 * Copyright (C) 2004, Eric Pouech.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 */
21
22 #include "dbghelp_private.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
25
26 static struct module* rb_module;
27 struct source_rb
28 {
29 struct wine_rb_entry entry;
30 unsigned source;
31 };
32
33 int source_rb_compare(const void *key, const struct wine_rb_entry *entry)
34 {
35 const struct source_rb *t = WINE_RB_ENTRY_VALUE(entry, const struct source_rb, entry);
36
37 return strcmp((const char*)key, rb_module->sources + t->source);
38 }
39
40 /******************************************************************
41 * source_find
42 *
43 * check whether a source file has already been stored
44 */
45 static unsigned source_find(const char* name)
46 {
47 struct wine_rb_entry* e;
48
49 e = wine_rb_get(&rb_module->sources_offsets_tree, name);
50 if (!e) return -1;
51 return WINE_RB_ENTRY_VALUE(e, struct source_rb, entry)->source;
52 }
53
54 /******************************************************************
55 * source_new
56 *
57 * checks if source exists. if not, add it
58 */
59 unsigned source_new(struct module* module, const char* base, const char* name)
60 {
61 unsigned ret = -1;
62 const char* full;
63 char* tmp = NULL;
64
65 if (!name) return ret;
66 if (!base || *name == '/')
67 full = name;
68 else
69 {
70 unsigned bsz = strlen(base);
71
72 tmp = HeapAlloc(GetProcessHeap(), 0, bsz + 1 + strlen(name) + 1);
73 if (!tmp) return ret;
74 full = tmp;
75 strcpy(tmp, base);
76 if (tmp[bsz - 1] != '/') tmp[bsz++] = '/';
77 strcpy(&tmp[bsz], name);
78 }
79 rb_module = module;
80 if (!module->sources || (ret = source_find(full)) == (unsigned)-1)
81 {
82 char* new;
83 int len = strlen(full) + 1;
84 struct source_rb* rb;
85
86 if (module->sources_used + len + 1 > module->sources_alloc)
87 {
88 if (!module->sources)
89 {
90 module->sources_alloc = (module->sources_used + len + 1 + 255) & ~255;
91 new = HeapAlloc(GetProcessHeap(), 0, module->sources_alloc);
92 }
93 else
94 {
95 module->sources_alloc = max( module->sources_alloc * 2,
96 (module->sources_used + len + 1 + 255) & ~255 );
97 new = HeapReAlloc(GetProcessHeap(), 0, module->sources,
98 module->sources_alloc);
99 }
100 if (!new) goto done;
101 module->sources = new;
102 }
103 ret = module->sources_used;
104 memcpy(module->sources + module->sources_used, full, len);
105 module->sources_used += len;
106 module->sources[module->sources_used] = '\0';
107 if ((rb = pool_alloc(&module->pool, sizeof(*rb))))
108 {
109 rb->source = ret;
110 wine_rb_put(&module->sources_offsets_tree, full, &rb->entry);
111 }
112 }
113 done:
114 HeapFree(GetProcessHeap(), 0, tmp);
115 return ret;
116 }
117
118 /******************************************************************
119 * source_get
120 *
121 * returns a stored source file name
122 */
123 const char* source_get(const struct module* module, unsigned idx)
124 {
125 if (idx == -1) return "";
126 assert(module->sources);
127 return module->sources + idx;
128 }
129
130 /******************************************************************
131 * SymEnumSourceFilesW (DBGHELP.@)
132 *
133 */
134 BOOL WINAPI SymEnumSourceFilesW(HANDLE hProcess, ULONG64 ModBase, PCWSTR Mask,
135 PSYM_ENUMSOURCEFILES_CALLBACKW cbSrcFiles,
136 PVOID UserContext)
137 {
138 struct module_pair pair;
139 SOURCEFILEW sf;
140 char* ptr;
141 WCHAR* conversion_buffer = NULL;
142 DWORD conversion_buffer_len = 0;
143
144 if (!cbSrcFiles) return FALSE;
145 pair.pcs = process_find_by_handle(hProcess);
146 if (!pair.pcs) return FALSE;
147
148 if (ModBase)
149 {
150 pair.requested = module_find_by_addr(pair.pcs, ModBase, DMT_UNKNOWN);
151 if (!module_get_debug(&pair)) return FALSE;
152 }
153 else
154 {
155 if (Mask[0] == '!')
156 {
157 pair.requested = module_find_by_nameW(pair.pcs, Mask + 1);
158 if (!module_get_debug(&pair)) return FALSE;
159 }
160 else
161 {
162 FIXME("Unsupported yet (should get info from current context)\n");
163 return FALSE;
164 }
165 }
166 if (!pair.effective->sources) return FALSE;
167 for (ptr = pair.effective->sources; *ptr; ptr += strlen(ptr) + 1)
168 {
169 DWORD len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
170
171 if (len > conversion_buffer_len)
172 {
173 HeapFree(GetProcessHeap(), 0, conversion_buffer);
174 conversion_buffer = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
175 if (!conversion_buffer) return FALSE;
176 conversion_buffer_len = len;
177 }
178
179 MultiByteToWideChar(CP_ACP, 0, ptr, -1, conversion_buffer, len);
180
181 /* FIXME: not using Mask */
182 sf.ModBase = ModBase;
183 sf.FileName = conversion_buffer;
184 if (!cbSrcFiles(&sf, UserContext)) break;
185 }
186
187 HeapFree(GetProcessHeap(), 0, conversion_buffer);
188 return TRUE;
189 }
190
191 struct enum_sources_files_context
192 {
193 PSYM_ENUMSOURCEFILES_CALLBACK callbackA;
194 PVOID caller_context;
195 char *conversion_buffer;
196 DWORD conversion_buffer_len;
197 DWORD callback_error;
198 };
199
200 static BOOL CALLBACK enum_source_files_W_to_A(PSOURCEFILEW source_file, PVOID context)
201 {
202 struct enum_sources_files_context *ctx = context;
203 SOURCEFILE source_fileA;
204 DWORD len;
205
206 len = WideCharToMultiByte(CP_ACP, 0, source_file->FileName, -1, NULL, 0, NULL, NULL);
207 if (len > ctx->conversion_buffer_len)
208 {
209 char *ptr = ctx->conversion_buffer ? HeapReAlloc(GetProcessHeap(), 0, ctx->conversion_buffer, len) :
210 HeapAlloc(GetProcessHeap(), 0, len);
211
212 if (!ptr)
213 {
214 ctx->callback_error = ERROR_OUTOFMEMORY;
215 return FALSE;
216 }
217
218 ctx->conversion_buffer = ptr;
219 ctx->conversion_buffer_len = len;
220 }
221
222 WideCharToMultiByte(CP_ACP, 0, source_file->FileName, -1, ctx->conversion_buffer, len, NULL, NULL);
223
224 source_fileA.ModBase = source_file->ModBase;
225 source_fileA.FileName = ctx->conversion_buffer;
226 return ctx->callbackA(&source_fileA, ctx->caller_context);
227 }
228
229 /******************************************************************
230 * SymEnumSourceFiles (DBGHELP.@)
231 *
232 */
233 BOOL WINAPI SymEnumSourceFiles(HANDLE hProcess, ULONG64 ModBase, PCSTR Mask,
234 PSYM_ENUMSOURCEFILES_CALLBACK cbSrcFiles,
235 PVOID UserContext)
236 {
237 WCHAR *maskW = NULL;
238 PSYM_ENUMSOURCEFILES_CALLBACKW callbackW;
239 PVOID context;
240 struct enum_sources_files_context callback_context = {cbSrcFiles, UserContext};
241 BOOL ret;
242
243 if (Mask)
244 {
245 DWORD len = MultiByteToWideChar(CP_ACP, 0, Mask, -1, NULL, 0);
246
247 maskW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
248 if (!maskW)
249 {
250 SetLastError(ERROR_OUTOFMEMORY);
251 return FALSE;
252 }
253
254 MultiByteToWideChar(CP_ACP, 0, Mask, -1, maskW, len);
255 }
256
257 if (cbSrcFiles)
258 {
259 callbackW = enum_source_files_W_to_A;
260 context = &callback_context;
261 }
262 else
263 {
264 callbackW = NULL;
265 context = UserContext;
266 }
267
268 ret = SymEnumSourceFilesW(hProcess, ModBase, maskW, callbackW, context);
269
270 if (callback_context.callback_error)
271 {
272 SetLastError(callback_context.callback_error);
273 ret = FALSE;
274 }
275
276 HeapFree(GetProcessHeap(), 0, callback_context.conversion_buffer);
277 HeapFree(GetProcessHeap(), 0, maskW);
278
279 return ret;
280 }
281
282 /******************************************************************
283 * SymEnumSourceLines (DBGHELP.@)
284 *
285 */
286 BOOL WINAPI SymEnumSourceLines(HANDLE hProcess, ULONG64 base, PCSTR obj,
287 PCSTR file, DWORD line, DWORD flags,
288 PSYM_ENUMLINES_CALLBACK EnumLinesCallback,
289 PVOID UserContext)
290 {
291 FIXME("%p %s %s %s %u %u %p %p: stub!\n",
292 hProcess, wine_dbgstr_longlong(base), debugstr_a(obj), debugstr_a(file),
293 line, flags, EnumLinesCallback, UserContext);
294 SetLastError(ERROR_NOT_SUPPORTED);
295 return FALSE;
296 }
297
298 /******************************************************************
299 * SymEnumSourceLinesW(DBGHELP.@)
300 *
301 */
302 BOOL WINAPI SymEnumSourceLinesW(HANDLE hProcess, ULONG64 base, PCWSTR obj,
303 PCWSTR file, DWORD line, DWORD flags,
304 PSYM_ENUMLINES_CALLBACKW EnumLinesCallback,
305 PVOID UserContext)
306 {
307 FIXME("%p %s %s %s %u %u %p %p: stub!\n",
308 hProcess, wine_dbgstr_longlong(base), debugstr_w(obj), debugstr_w(file),
309 line, flags, EnumLinesCallback, UserContext);
310 SetLastError(ERROR_NOT_SUPPORTED);
311 return FALSE;
312 }
313
314 /******************************************************************
315 * SymGetSourceFileToken (DBGHELP.@)
316 *
317 */
318 BOOL WINAPI SymGetSourceFileToken(HANDLE hProcess, ULONG64 base,
319 PCSTR src, PVOID* token, DWORD* size)
320 {
321 FIXME("%p %s %s %p %p: stub!\n",
322 hProcess, wine_dbgstr_longlong(base), debugstr_a(src), token, size);
323 SetLastError(ERROR_NOT_SUPPORTED);
324 return FALSE;
325 }
326
327 /******************************************************************
328 * SymGetSourceFileTokenW (DBGHELP.@)
329 *
330 */
331 BOOL WINAPI SymGetSourceFileTokenW(HANDLE hProcess, ULONG64 base,
332 PCWSTR src, PVOID* token, DWORD* size)
333 {
334 FIXME("%p %s %s %p %p: stub!\n",
335 hProcess, wine_dbgstr_longlong(base), debugstr_w(src), token, size);
336 SetLastError(ERROR_NOT_SUPPORTED);
337 return FALSE;
338 }