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