Update German resources.
[wine/multimedia.git] / dlls / dbghelp / dbghelp.c
blob982956e5aeda70a24ea1c78d4512838fb5e9b791
1 /*
2 * File dbghelp.c - generic routines (process) for dbghelp DLL
4 * Copyright (C) 2004, Eric Pouech
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include "dbghelp_private.h"
24 #include "winerror.h"
25 #include "psapi.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
30 /* TODO
31 * - support for symbols' types is still partly missing
32 * + C++ support
33 * + funcargtype:s are (partly) wrong: they should be a specific struct (like
34 * typedef) pointing to the actual type (and not a direct access)
35 * + we should store the underlying type for an enum in the symt_enum struct
36 * + for enums, we store the names & values (associated to the enum type),
37 * but those values are not directly usable from a debugger (that's why, I
38 * assume, that we have also to define constants for enum values, as
39 * Codeview does BTW.
40 * - most options (dbghelp_options) are not used (loading lines...)
41 * - in symbol lookup by name, we don't use RE everywhere we should. Moreover, when
42 * we're supposed to use RE, it doesn't make use of our hash tables. Therefore,
43 * we could use hash if name isn't a RE, and fall back to a full search when we
44 * get a full RE
45 * - msc:
46 * + we should add parameters' types to the function's signature
47 * while processing a function's parameters
48 * + get rid of MSC reading FIXME:s (lots of types are not defined)
49 * + C++ management
50 * - stabs:
51 * + when, in a same module, the same definition is used in several compilation
52 * units, we get several definitions of the same object (especially
53 * struct/union). we should find a way not to duplicate them
54 * + in some cases (dlls/user/dialog16.c DIALOG_GetControl16), the same static
55 * global variable is defined several times (at different scopes). We are
56 * getting several of those while looking for a unique symbol. Part of the
57 * issue is that we don't give a scope to a static variable inside a function
58 * + C++ management
59 * - implement the callback notification mechanism
62 unsigned dbghelp_options = SYMOPT_UNDNAME;
63 HANDLE hMsvcrt = NULL;
65 /***********************************************************************
66 * DllMain (DEBUGHLP.@)
68 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
70 switch (fdwReason)
72 case DLL_PROCESS_ATTACH: break;
73 case DLL_PROCESS_DETACH:
74 if (hMsvcrt) FreeLibrary(hMsvcrt);
75 break;
76 case DLL_THREAD_ATTACH: break;
77 case DLL_THREAD_DETACH: break;
78 default: break;
80 return TRUE;
83 static struct process* process_first /* = NULL */;
85 /******************************************************************
86 * process_find_by_handle
89 struct process* process_find_by_handle(HANDLE hProcess)
91 struct process* p;
93 for (p = process_first; p && p->handle != hProcess; p = p->next);
94 if (!p) SetLastError(ERROR_INVALID_HANDLE);
95 return p;
98 /******************************************************************
99 * SymSetSearchPath (DBGHELP.@)
102 BOOL WINAPI SymSetSearchPath(HANDLE hProcess, PSTR searchPath)
104 struct process* pcs = process_find_by_handle(hProcess);
106 if (!pcs) return FALSE;
107 if (!searchPath) return FALSE;
109 HeapFree(GetProcessHeap(), 0, pcs->search_path);
110 pcs->search_path = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(searchPath) + 1),
111 searchPath);
112 return TRUE;
115 /***********************************************************************
116 * SymGetSearchPath (DBGHELP.@)
118 BOOL WINAPI SymGetSearchPath(HANDLE hProcess, LPSTR szSearchPath,
119 DWORD SearchPathLength)
121 struct process* pcs = process_find_by_handle(hProcess);
122 if (!pcs) return FALSE;
124 strncpy(szSearchPath, pcs->search_path, SearchPathLength);
125 szSearchPath[SearchPathLength - 1] = '\0';
126 return TRUE;
129 /******************************************************************
130 * invade_process
132 * SymInitialize helper: loads in dbghelp all known (and loaded modules)
133 * this assumes that hProcess is a handle on a valid process
135 static BOOL process_invade(HANDLE hProcess)
137 HMODULE hMods[256];
138 char img[256];
139 DWORD i, sz;
140 MODULEINFO mi;
142 if (!EnumProcessModules(hProcess, hMods, sizeof(hMods), &sz))
143 return FALSE; /* FIXME should grow hMods */
145 for (i = 0; i < sz / sizeof(HMODULE); i++)
147 if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
148 !GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
149 !SymLoadModule(hProcess, 0, img, NULL, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage))
150 return FALSE;
153 return sz != 0;
156 /******************************************************************
157 * SymInitialize (DBGHELP.@)
159 * The initialisation of a dbghelp's context.
160 * Note that hProcess doesn't need to be a valid process handle (except
161 * when fInvadeProcess is TRUE).
162 * Since, we're also allow to load ELF (pure) libraries and Wine ELF libraries
163 * containing PE (and NE) module(s), here's how we handle it:
164 * - we load every module (ELF, NE, PE) passed in SymLoadModule
165 * - in fInvadeProcess (in SymInitialize) is TRUE, we set up what is called ELF
166 * synchronization: hProcess should be a valid process handle, and we hook
167 * ourselves on hProcess's loaded ELF-modules, and keep this list in sync with
168 * our internal ELF modules representation (loading / unloading). This way,
169 * we'll pair every loaded builtin PE module with its ELF counterpart (and
170 * access its debug information).
171 * - if fInvadeProcess (in SymInitialize) is FALSE, we won't be able to
172 * make the peering between a builtin PE module and its ELF counterpart, hence
173 * we won't be able to provide the requested debug information. We'll
174 * however be able to load native PE modules (and their debug information)
175 * without any trouble.
176 * Note also that this scheme can be intertwined with the deferred loading
177 * mechanism (ie only load the debug information when we actually need it).
179 BOOL WINAPI SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess)
181 struct process* pcs;
183 TRACE("(%p %s %u)\n", hProcess, debugstr_a(UserSearchPath), fInvadeProcess);
185 if (process_find_by_handle(hProcess))
186 FIXME("what to do ??\n");
188 pcs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pcs));
189 if (!pcs) return FALSE;
191 pcs->handle = hProcess;
193 if (UserSearchPath)
195 pcs->search_path = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(UserSearchPath) + 1),
196 UserSearchPath);
198 else
200 unsigned size;
201 unsigned len;
203 pcs->search_path = HeapAlloc(GetProcessHeap(), 0, len = MAX_PATH);
204 while ((size = GetCurrentDirectoryA(len, pcs->search_path)) >= len)
205 pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, len *= 2);
206 pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, size + 1);
208 len = GetEnvironmentVariableA("_NT_SYMBOL_PATH", NULL, 0);
209 if (len)
211 pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, size + 1 + len + 1);
212 pcs->search_path[size] = ';';
213 GetEnvironmentVariableA("_NT_SYMBOL_PATH", pcs->search_path + size + 1, len);
214 size += 1 + len;
216 len = GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", NULL, 0);
217 if (len)
219 pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, size + 1 + len + 1);
220 pcs->search_path[size] = ';';
221 GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", pcs->search_path + size + 1, len);
222 size += 1 + len;
226 pcs->lmodules = NULL;
227 pcs->dbg_hdr_addr = 0;
228 pcs->next = process_first;
229 process_first = pcs;
231 if (fInvadeProcess)
233 if (!elf_read_wine_loader_dbg_info(pcs))
235 SymCleanup(hProcess);
236 return FALSE;
238 process_invade(hProcess);
239 elf_synchronize_module_list(pcs);
241 return TRUE;
244 /******************************************************************
245 * SymCleanup (DBGHELP.@)
248 BOOL WINAPI SymCleanup(HANDLE hProcess)
250 struct process** ppcs;
251 struct process* next;
253 for (ppcs = &process_first; *ppcs; ppcs = &(*ppcs)->next)
255 if ((*ppcs)->handle == hProcess)
257 while ((*ppcs)->lmodules) module_remove(*ppcs, (*ppcs)->lmodules);
259 HeapFree(GetProcessHeap(), 0, (*ppcs)->search_path);
260 next = (*ppcs)->next;
261 HeapFree(GetProcessHeap(), 0, *ppcs);
262 *ppcs = next;
263 return TRUE;
266 return FALSE;
269 /******************************************************************
270 * SymSetOptions (DBGHELP.@)
273 DWORD WINAPI SymSetOptions(DWORD opts)
275 return dbghelp_options = opts;
278 /******************************************************************
279 * SymGetOptions (DBGHELP.@)
282 DWORD WINAPI SymGetOptions(void)
284 return dbghelp_options;
287 /******************************************************************
288 * SymSetContext (DBGHELP.@)
291 BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame,
292 PIMAGEHLP_CONTEXT Context)
294 struct process* pcs = process_find_by_handle(hProcess);
295 if (!pcs) return FALSE;
297 pcs->ctx_frame = *StackFrame;
298 /* MSDN states that Context is not (no longer?) used */
299 return TRUE;
302 /***********************************************************************
303 * SymRegisterCallback (DBGHELP.@)
305 BOOL WINAPI SymRegisterCallback(HANDLE hProcess,
306 PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
307 PVOID UserContext)
309 FIXME("(%p, %p, %p): stub\n", hProcess, CallbackFunction, UserContext);
310 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
311 return FALSE;
314 /* This is imagehlp version not dbghelp !! */
315 static API_VERSION api_version = { 4, 0, 2, 0 };
317 /***********************************************************************
318 * ImagehlpApiVersion (DBGHELP.@)
320 LPAPI_VERSION WINAPI ImagehlpApiVersion(VOID)
322 return &api_version;
325 /***********************************************************************
326 * ImagehlpApiVersionEx (DBGHELP.@)
328 LPAPI_VERSION WINAPI ImagehlpApiVersionEx(LPAPI_VERSION AppVersion)
330 if (!AppVersion) return NULL;
332 AppVersion->MajorVersion = api_version.MajorVersion;
333 AppVersion->MinorVersion = api_version.MinorVersion;
334 AppVersion->Revision = api_version.Revision;
335 AppVersion->Reserved = api_version.Reserved;
337 return AppVersion;