Implemented CoInternetCombineUrl and CoInternetCompareUrl.
[wine/testsucceed.git] / dlls / dbghelp / module.c
blob03ce14e0e057366399986771130598a8084e9706
1 /*
2 * File module.c - module handling for the wine debugger
4 * Copyright (C) 1993, Eric Youngdale.
5 * 2000-2004, Eric Pouech
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <assert.h>
28 #include "dbghelp_private.h"
29 #include "psapi.h"
30 #include "winreg.h"
31 #include "winternl.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
36 /***********************************************************************
37 * Creates and links a new module to a process
39 struct module* module_new(struct process* pcs, const char* name,
40 enum DbgModuleType type,
41 unsigned long mod_addr, unsigned long size,
42 unsigned long stamp, unsigned long checksum)
44 struct module* module;
45 const char* ptr;
47 if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
48 return NULL;
50 memset(module, 0, sizeof(*module));
52 module->next = pcs->lmodules;
53 pcs->lmodules = module;
55 TRACE("=> %s %08lx-%08lx %s\n",
56 type == DMT_ELF ? "ELF" : (type == DMT_PE ? "PE" : "---"),
57 mod_addr, mod_addr + size, name);
59 pool_init(&module->pool, 65536);
61 module->module.SizeOfStruct = sizeof(module->module);
62 module->module.BaseOfImage = mod_addr;
63 module->module.ImageSize = size;
64 for (ptr = name + strlen(name) - 1;
65 *ptr != '/' && *ptr != '\\' && ptr >= name;
66 ptr--);
67 if (ptr < name || *ptr == '/' || *ptr == '\\') ptr++;
68 strncpy(module->module.ModuleName, ptr, sizeof(module->module.ModuleName));
69 module->module.ModuleName[sizeof(module->module.ModuleName) - 1] = '\0';
70 module->module.ImageName[0] = '\0';
71 strncpy(module->module.LoadedImageName, name,
72 sizeof(module->module.LoadedImageName));
73 module->module.LoadedImageName[sizeof(module->module.LoadedImageName) - 1] = '\0';
74 module->module.SymType = SymNone;
75 module->module.NumSyms = 0;
76 module->module.TimeDateStamp = stamp;
77 module->module.CheckSum = checksum;
79 module->type = type;
80 module->sortlist_valid = FALSE;
81 module->addr_sorttab = NULL;
82 /* FIXME: this seems a bit too high (on a per module basis)
83 * need some statistics about this
85 hash_table_init(&module->pool, &module->ht_symbols, 4096);
86 hash_table_init(&module->pool, &module->ht_types, 4096);
88 module->sources_used = 0;
89 module->sources_alloc = 0;
90 module->sources = 0;
92 return module;
95 /***********************************************************************
96 * module_find_by_name
99 struct module* module_find_by_name(const struct process* pcs,
100 const char* name, enum DbgModuleType type)
102 struct module* module;
104 if (type == DMT_UNKNOWN)
106 if ((module = module_find_by_name(pcs, name, DMT_PE)) ||
107 (module = module_find_by_name(pcs, name, DMT_ELF)))
108 return module;
110 else
112 for (module = pcs->lmodules; module; module = module->next)
114 if (type == module->type && !strcasecmp(name, module->module.LoadedImageName))
115 return module;
117 for (module = pcs->lmodules; module; module = module->next)
119 if (type == module->type && !strcasecmp(name, module->module.ModuleName))
120 return module;
123 SetLastError(ERROR_INVALID_NAME);
124 return NULL;
127 /***********************************************************************
128 * module_has_container
131 static struct module* module_get_container(const struct process* pcs,
132 const struct module* inner)
134 struct module* module;
136 for (module = pcs->lmodules; module; module = module->next)
138 if (module != inner &&
139 module->module.BaseOfImage <= inner->module.BaseOfImage &&
140 module->module.BaseOfImage + module->module.ImageSize >=
141 inner->module.BaseOfImage + inner->module.ImageSize)
142 return module;
144 return NULL;
147 /******************************************************************
148 * module_get_debug
150 * get the debug information from a module:
151 * - if the module's type is deferred, then force loading of debug info (and return
152 * the module itself)
153 * - if the module has no debug info and has an ELF container, then return the ELF
154 * container (and also force the ELF container's debug info loading if deferred)
155 * - otherwise return the module itself if it has some debug info
157 struct module* module_get_debug(const struct process* pcs, struct module* module)
159 if (!module) return NULL;
160 switch (module->module.SymType)
162 case -1: break;
163 case SymNone:
164 module = module_get_container(pcs, module);
165 if (!module || module->module.SymType != SymDeferred) break;
166 /* fall through */
167 case SymDeferred:
168 switch (module->type)
170 case DMT_ELF:
171 elf_load_debug_info(module);
172 break;
173 case DMT_PE:
174 pe_load_debug_info(pcs, module);
175 break;
176 default: break;
178 break;
179 default: break;
181 return (module && module->module.SymType > SymNone) ? module : NULL;
184 /***********************************************************************
185 * module_find_by_addr
187 * either the addr where module is loaded, or any address inside the
188 * module
190 struct module* module_find_by_addr(const struct process* pcs, unsigned long addr,
191 enum DbgModuleType type)
193 struct module* module;
195 if (type == DMT_UNKNOWN)
197 if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
198 (module = module_find_by_addr(pcs, addr, DMT_ELF)))
199 return module;
201 else
203 for (module = pcs->lmodules; module; module = module->next)
205 if (type == module->type && addr >= module->module.BaseOfImage &&
206 addr < module->module.BaseOfImage + module->module.ImageSize)
207 return module;
210 SetLastError(ERROR_INVALID_ADDRESS);
211 return module;
214 /***********************************************************************
215 * SymLoadModule (DBGHELP.@)
217 DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
218 char* ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
220 struct process* pcs;
221 struct module* module = NULL;
223 TRACE("(%p %p %s %s %08lx %08lx)\n",
224 hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName),
225 BaseOfDll, SizeOfDll);
227 pcs = process_find_by_handle(hProcess);
228 if (!pcs) return FALSE;
230 if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
232 unsigned len = strlen(ImageName);
234 if (!strcmp(ImageName + len - 3, ".so") &&
235 (module = elf_load_module(pcs, ImageName))) goto done;
236 if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
237 goto done;
238 WARN("Couldn't locate %s\n", ImageName);
239 return 0;
242 done:
243 /* by default pe_load_module fills module.ModuleName from a derivation
244 * of ImageName. Overwrite it, if we have better information
246 if (ModuleName)
248 strncpy(module->module.ModuleName, ModuleName,
249 sizeof(module->module.ModuleName));
250 module->module.ModuleName[sizeof(module->module.ModuleName) - 1] = '\0';
252 strncpy(module->module.ImageName, ImageName, sizeof(module->module.ImageName));
253 module->module.ImageName[sizeof(module->module.ImageName) - 1] = '\0';
254 /* force transparent ELF loading / unloading */
255 if (module->type != DMT_ELF) elf_synchronize_module_list(pcs);
257 return module->module.BaseOfImage;
260 /******************************************************************
261 * module_remove
264 BOOL module_remove(struct process* pcs, struct module* module)
266 struct module** p;
268 TRACE("%s (%p)\n", module->module.ModuleName, module);
269 hash_table_destroy(&module->ht_symbols);
270 hash_table_destroy(&module->ht_types);
271 HeapFree(GetProcessHeap(), 0, (char*)module->sources);
272 HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
273 pool_destroy(&module->pool);
275 for (p = &pcs->lmodules; *p; p = &(*p)->next)
277 if (*p == module)
279 *p = module->next;
280 HeapFree(GetProcessHeap(), 0, module);
281 return TRUE;
284 FIXME("This shouldn't happen\n");
285 return FALSE;
288 /******************************************************************
289 * SymUnloadModule (DBGHELP.@)
292 BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll)
294 struct process* pcs;
295 struct module* module;
297 pcs = process_find_by_handle(hProcess);
298 if (!pcs) return FALSE;
299 module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
300 if (!module) return FALSE;
301 return module_remove(pcs, module);
304 /******************************************************************
305 * SymEnumerateModules (DBGHELP.@)
308 BOOL WINAPI SymEnumerateModules(HANDLE hProcess,
309 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,
310 PVOID UserContext)
312 struct process* pcs = process_find_by_handle(hProcess);
313 struct module* module;
315 if (!pcs) return FALSE;
317 for (module = pcs->lmodules; module; module = module->next)
319 if (module->type != DMT_PE) continue;
320 if (!EnumModulesCallback(module->module.ModuleName,
321 module->module.BaseOfImage, UserContext))
322 break;
324 return TRUE;
327 /******************************************************************
328 * EnumerateLoadedModules (DBGHELP.@)
331 BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess,
332 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
333 PVOID UserContext)
335 HMODULE* hMods;
336 char img[256], mod[256];
337 DWORD i, sz;
338 MODULEINFO mi;
340 hMods = HeapAlloc(GetProcessHeap(), 0, sz);
341 if (!hMods) return FALSE;
343 if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz))
345 /* hProcess should also be a valid process handle !! */
346 FIXME("If this happens, bump the number in mod\n");
347 HeapFree(GetProcessHeap(), 0, hMods);
348 return FALSE;
350 sz /= sizeof(HMODULE);
351 for (i = 0; i < sz; i++)
353 if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
354 !GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
355 !GetModuleBaseNameA(hProcess, hMods[i], mod, sizeof(mod)))
356 break;
357 EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage,
358 UserContext);
360 HeapFree(GetProcessHeap(), 0, hMods);
362 return sz != 0 && i == sz;
365 /******************************************************************
366 * SymGetModuleInfo (DBGHELP.@)
369 BOOL WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr,
370 PIMAGEHLP_MODULE ModuleInfo)
372 struct process* pcs = process_find_by_handle(hProcess);
373 struct module* module;
375 if (!pcs) return FALSE;
376 if (ModuleInfo->SizeOfStruct < sizeof(*ModuleInfo)) return FALSE;
377 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
378 if (!module) return FALSE;
380 *ModuleInfo = module->module;
381 if (module->module.SymType <= SymNone)
383 module = module_get_container(pcs, module);
384 if (module && module->module.SymType > SymNone)
385 ModuleInfo->SymType = module->module.SymType;
388 return TRUE;
391 /***********************************************************************
392 * SymGetModuleBase (IMAGEHLP.@)
394 DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
396 struct process* pcs = process_find_by_handle(hProcess);
397 struct module* module;
399 if (!pcs) return 0;
400 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
401 if (!module) return 0;
402 return module->module.BaseOfImage;