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