libwine: Remove __wine_main_arg* from the public header.
[wine/zf.git] / dlls / dbghelp / dbghelp.c
blobc3e4b2991ba16994d2222a4c34ba9e801ccf0039
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <unistd.h>
23 #include "dbghelp_private.h"
24 #include "winternl.h"
25 #include "winerror.h"
26 #include "psapi.h"
27 #include "wine/debug.h"
28 #include "wdbgexts.h"
29 #include "winnls.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
33 /* TODO
34 * - support for symbols' types is still partly missing
35 * + C++ support
36 * + we should store the underlying type for an enum in the symt_enum struct
37 * + for enums, we store the names & values (associated to the enum type),
38 * but those values are not directly usable from a debugger (that's why, I
39 * assume, that we have also to define constants for enum values, as
40 * Codeview does BTW.
41 * + SymEnumTypes should only return *user* defined types (UDT, typedefs...) not
42 * all the types stored/used in the modules (like char*)
43 * - SymGetLine{Next|Prev} don't work as expected (they don't seem to work across
44 * functions, and even across function blocks...). Basically, for *Next* to work
45 * it requires an address after the prolog of the func (the base address of the
46 * func doesn't work)
47 * - most options (dbghelp_options) are not used (loading lines...)
48 * - in symbol lookup by name, we don't use RE everywhere we should. Moreover, when
49 * we're supposed to use RE, it doesn't make use of our hash tables. Therefore,
50 * we could use hash if name isn't a RE, and fall back to a full search when we
51 * get a full RE
52 * - msc:
53 * + we should add parameters' types to the function's signature
54 * while processing a function's parameters
55 * + add support for function-less labels (as MSC seems to define them)
56 * + C++ management
57 * - stabs:
58 * + when, in a same module, the same definition is used in several compilation
59 * units, we get several definitions of the same object (especially
60 * struct/union). we should find a way not to duplicate them
61 * + in some cases (dlls/user/dialog16.c DIALOG_GetControl16), the same static
62 * global variable is defined several times (at different scopes). We are
63 * getting several of those while looking for a unique symbol. Part of the
64 * issue is that we don't give a scope to a static variable inside a function
65 * + C++ management
68 unsigned dbghelp_options = SYMOPT_UNDNAME;
69 BOOL dbghelp_opt_native = FALSE;
70 SYSTEM_INFO sysinfo;
72 static struct process* process_first /* = NULL */;
74 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
76 switch (reason)
78 case DLL_PROCESS_ATTACH:
79 GetSystemInfo(&sysinfo);
80 DisableThreadLibraryCalls(instance);
81 break;
83 return TRUE;
86 /******************************************************************
87 * process_find_by_handle
90 struct process* process_find_by_handle(HANDLE hProcess)
92 struct process* p;
94 for (p = process_first; p && p->handle != hProcess; p = p->next);
95 if (!p) SetLastError(ERROR_INVALID_HANDLE);
96 return p;
99 /******************************************************************
100 * validate_addr64 (internal)
103 BOOL validate_addr64(DWORD64 addr)
105 if (sizeof(void*) == sizeof(int) && (addr >> 32))
107 FIXME("Unsupported address %s\n", wine_dbgstr_longlong(addr));
108 SetLastError(ERROR_INVALID_PARAMETER);
109 return FALSE;
111 return TRUE;
114 /******************************************************************
115 * fetch_buffer
117 * Ensures process' internal buffer is large enough.
119 void* fetch_buffer(struct process* pcs, unsigned size)
121 if (size > pcs->buffer_size)
123 if (pcs->buffer)
124 pcs->buffer = HeapReAlloc(GetProcessHeap(), 0, pcs->buffer, size);
125 else
126 pcs->buffer = HeapAlloc(GetProcessHeap(), 0, size);
127 pcs->buffer_size = (pcs->buffer) ? size : 0;
129 return pcs->buffer;
132 const char* wine_dbgstr_addr(const ADDRESS64* addr)
134 if (!addr) return "(null)";
135 switch (addr->Mode)
137 case AddrModeFlat:
138 return wine_dbg_sprintf("flat<%s>", wine_dbgstr_longlong(addr->Offset));
139 case AddrMode1616:
140 return wine_dbg_sprintf("1616<%04x:%04x>", addr->Segment, (DWORD)addr->Offset);
141 case AddrMode1632:
142 return wine_dbg_sprintf("1632<%04x:%08x>", addr->Segment, (DWORD)addr->Offset);
143 case AddrModeReal:
144 return wine_dbg_sprintf("real<%04x:%04x>", addr->Segment, (DWORD)addr->Offset);
145 default:
146 return "unknown";
150 extern struct cpu cpu_i386, cpu_x86_64, cpu_ppc, cpu_arm, cpu_arm64;
152 static struct cpu* dbghelp_cpus[] = {&cpu_i386, &cpu_x86_64, &cpu_ppc, &cpu_arm, &cpu_arm64, NULL};
153 struct cpu* dbghelp_current_cpu =
154 #if defined(__i386__)
155 &cpu_i386
156 #elif defined(__x86_64__)
157 &cpu_x86_64
158 #elif defined(__powerpc__)
159 &cpu_ppc
160 #elif defined(__arm__)
161 &cpu_arm
162 #elif defined(__aarch64__)
163 &cpu_arm64
164 #else
165 #error define support for your CPU
166 #endif
169 struct cpu* cpu_find(DWORD machine)
171 struct cpu** cpu;
173 for (cpu = dbghelp_cpus ; *cpu; cpu++)
175 if (cpu[0]->machine == machine) return cpu[0];
177 return NULL;
180 /******************************************************************
181 * SymSetSearchPathW (DBGHELP.@)
184 BOOL WINAPI SymSetSearchPathW(HANDLE hProcess, PCWSTR searchPath)
186 struct process* pcs = process_find_by_handle(hProcess);
188 if (!pcs) return FALSE;
189 if (!searchPath) return FALSE;
191 HeapFree(GetProcessHeap(), 0, pcs->search_path);
192 pcs->search_path = lstrcpyW(HeapAlloc(GetProcessHeap(), 0,
193 (lstrlenW(searchPath) + 1) * sizeof(WCHAR)),
194 searchPath);
195 return TRUE;
198 /******************************************************************
199 * SymSetSearchPath (DBGHELP.@)
202 BOOL WINAPI SymSetSearchPath(HANDLE hProcess, PCSTR searchPath)
204 BOOL ret = FALSE;
205 unsigned len;
206 WCHAR* sp;
208 len = MultiByteToWideChar(CP_ACP, 0, searchPath, -1, NULL, 0);
209 if ((sp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
211 MultiByteToWideChar(CP_ACP, 0, searchPath, -1, sp, len);
213 ret = SymSetSearchPathW(hProcess, sp);
214 HeapFree(GetProcessHeap(), 0, sp);
216 return ret;
219 /***********************************************************************
220 * SymGetSearchPathW (DBGHELP.@)
222 BOOL WINAPI SymGetSearchPathW(HANDLE hProcess, PWSTR szSearchPath,
223 DWORD SearchPathLength)
225 struct process* pcs = process_find_by_handle(hProcess);
226 if (!pcs) return FALSE;
228 lstrcpynW(szSearchPath, pcs->search_path, SearchPathLength);
229 return TRUE;
232 /***********************************************************************
233 * SymGetSearchPath (DBGHELP.@)
235 BOOL WINAPI SymGetSearchPath(HANDLE hProcess, PSTR szSearchPath,
236 DWORD SearchPathLength)
238 WCHAR* buffer = HeapAlloc(GetProcessHeap(), 0, SearchPathLength * sizeof(WCHAR));
239 BOOL ret = FALSE;
241 if (buffer)
243 ret = SymGetSearchPathW(hProcess, buffer, SearchPathLength);
244 if (ret)
245 WideCharToMultiByte(CP_ACP, 0, buffer, SearchPathLength,
246 szSearchPath, SearchPathLength, NULL, NULL);
247 HeapFree(GetProcessHeap(), 0, buffer);
249 return ret;
252 /******************************************************************
253 * invade_process
255 * SymInitialize helper: loads in dbghelp all known (and loaded modules)
256 * this assumes that hProcess is a handle on a valid process
258 static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOID user)
260 WCHAR tmp[MAX_PATH];
261 HANDLE hProcess = user;
263 if (!GetModuleFileNameExW(hProcess, (HMODULE)(DWORD_PTR)base, tmp, ARRAY_SIZE(tmp)))
264 lstrcpynW(tmp, name, ARRAY_SIZE(tmp));
266 SymLoadModuleExW(hProcess, 0, tmp, name, base, size, NULL, 0);
267 return TRUE;
270 /******************************************************************
271 * check_live_target
274 static BOOL check_live_target(struct process* pcs)
276 PROCESS_BASIC_INFORMATION pbi;
277 ULONG_PTR base = 0;
279 if (!GetProcessId(pcs->handle)) return FALSE;
280 if (GetEnvironmentVariableA("DBGHELP_NOLIVE", NULL, 0)) return FALSE;
282 if (NtQueryInformationProcess( pcs->handle, ProcessBasicInformation,
283 &pbi, sizeof(pbi), NULL ))
284 return FALSE;
286 if (!pcs->is_64bit)
288 PEB32 *peb32 = (PEB32 *)pbi.PebBaseAddress;
289 DWORD base32 = 0;
290 ReadProcessMemory(pcs->handle, &peb32->Reserved[0], &base32, sizeof(base32), NULL);
291 base = base32;
293 else ReadProcessMemory(pcs->handle, &pbi.PebBaseAddress->Reserved[0], &base, sizeof(base), NULL);
294 if (!base) return FALSE;
296 TRACE("got debug info address %#lx from PEB %p\n", base, pbi.PebBaseAddress);
297 return elf_read_wine_loader_dbg_info(pcs, base) || macho_read_wine_loader_dbg_info(pcs, base);
300 /******************************************************************
301 * SymInitializeW (DBGHELP.@)
303 * The initialisation of a dbghelp's context.
304 * Note that hProcess doesn't need to be a valid process handle (except
305 * when fInvadeProcess is TRUE).
306 * Since we also allow loading ELF (pure) libraries and Wine ELF libraries
307 * containing PE (and NE) module(s), here's how we handle it:
308 * - we load every module (ELF, NE, PE) passed in SymLoadModule
309 * - in fInvadeProcess (in SymInitialize) is TRUE, we set up what is called ELF
310 * synchronization: hProcess should be a valid process handle, and we hook
311 * ourselves on hProcess's loaded ELF-modules, and keep this list in sync with
312 * our internal ELF modules representation (loading / unloading). This way,
313 * we'll pair every loaded builtin PE module with its ELF counterpart (and
314 * access its debug information).
315 * - if fInvadeProcess (in SymInitialize) is FALSE, we check anyway if the
316 * hProcess refers to a running process. We use some heuristics here, so YMMV.
317 * If we detect a live target, then we get the same handling as if
318 * fInvadeProcess is TRUE (except that the modules are not loaded). Otherwise,
319 * we won't be able to make the peering between a builtin PE module and its ELF
320 * counterpart. Hence we won't be able to provide the requested debug
321 * information. We'll however be able to load native PE modules (and their
322 * debug information) without any trouble.
323 * Note also that this scheme can be intertwined with the deferred loading
324 * mechanism (ie only load the debug information when we actually need it).
326 BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess)
328 struct process* pcs;
329 BOOL wow64, child_wow64;
331 TRACE("(%p %s %u)\n", hProcess, debugstr_w(UserSearchPath), fInvadeProcess);
333 if (process_find_by_handle(hProcess))
335 WARN("the symbols for this process have already been initialized!\n");
337 /* MSDN says to only call this function once unless SymCleanup() has been called since the last call.
338 It also says to call SymRefreshModuleList() instead if you just want the module list refreshed.
339 Native still returns TRUE even if the process has already been initialized. */
340 return TRUE;
343 IsWow64Process(GetCurrentProcess(), &wow64);
345 if (GetProcessId(hProcess) && !IsWow64Process(hProcess, &child_wow64))
346 return FALSE;
348 pcs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pcs));
349 if (!pcs) return FALSE;
351 pcs->handle = hProcess;
352 pcs->is_64bit = (sizeof(void *) == 8 || wow64) && !child_wow64;
353 pcs->loader = &no_loader_ops; /* platform-specific initialization will override it if loader debug info can be found */
355 if (UserSearchPath)
357 pcs->search_path = lstrcpyW(HeapAlloc(GetProcessHeap(), 0,
358 (lstrlenW(UserSearchPath) + 1) * sizeof(WCHAR)),
359 UserSearchPath);
361 else
363 unsigned size;
364 unsigned len;
365 static const WCHAR sym_path[] = {'_','N','T','_','S','Y','M','B','O','L','_','P','A','T','H',0};
366 static const WCHAR alt_sym_path[] = {'_','N','T','_','A','L','T','E','R','N','A','T','E','_','S','Y','M','B','O','L','_','P','A','T','H',0};
368 pcs->search_path = HeapAlloc(GetProcessHeap(), 0, (len = MAX_PATH) * sizeof(WCHAR));
369 while ((size = GetCurrentDirectoryW(len, pcs->search_path)) >= len)
370 pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, (len *= 2) * sizeof(WCHAR));
371 pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, (size + 1) * sizeof(WCHAR));
373 len = GetEnvironmentVariableW(sym_path, NULL, 0);
374 if (len)
376 pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, (size + 1 + len + 1) * sizeof(WCHAR));
377 pcs->search_path[size] = ';';
378 GetEnvironmentVariableW(sym_path, pcs->search_path + size + 1, len);
379 size += 1 + len;
381 len = GetEnvironmentVariableW(alt_sym_path, NULL, 0);
382 if (len)
384 pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, (size + 1 + len + 1) * sizeof(WCHAR));
385 pcs->search_path[size] = ';';
386 GetEnvironmentVariableW(alt_sym_path, pcs->search_path + size + 1, len);
390 pcs->lmodules = NULL;
391 pcs->dbg_hdr_addr = 0;
392 pcs->next = process_first;
393 process_first = pcs;
395 if (check_live_target(pcs))
397 if (fInvadeProcess)
398 EnumerateLoadedModulesW64(hProcess, process_invade_cb, hProcess);
399 pcs->loader->synchronize_module_list(pcs);
401 else if (fInvadeProcess)
403 SymCleanup(hProcess);
404 SetLastError(ERROR_INVALID_PARAMETER);
405 return FALSE;
408 return TRUE;
411 /******************************************************************
412 * SymInitialize (DBGHELP.@)
416 BOOL WINAPI SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess)
418 WCHAR* sp = NULL;
419 BOOL ret;
421 if (UserSearchPath)
423 unsigned len;
425 len = MultiByteToWideChar(CP_ACP, 0, UserSearchPath, -1, NULL, 0);
426 sp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
427 MultiByteToWideChar(CP_ACP, 0, UserSearchPath, -1, sp, len);
430 ret = SymInitializeW(hProcess, sp, fInvadeProcess);
431 HeapFree(GetProcessHeap(), 0, sp);
432 return ret;
435 /******************************************************************
436 * SymCleanup (DBGHELP.@)
439 BOOL WINAPI SymCleanup(HANDLE hProcess)
441 struct process** ppcs;
442 struct process* next;
444 for (ppcs = &process_first; *ppcs; ppcs = &(*ppcs)->next)
446 if ((*ppcs)->handle == hProcess)
448 while ((*ppcs)->lmodules) module_remove(*ppcs, (*ppcs)->lmodules);
450 HeapFree(GetProcessHeap(), 0, (*ppcs)->search_path);
451 next = (*ppcs)->next;
452 HeapFree(GetProcessHeap(), 0, *ppcs);
453 *ppcs = next;
454 return TRUE;
458 ERR("this process has not had SymInitialize() called for it!\n");
459 return FALSE;
462 /******************************************************************
463 * SymSetOptions (DBGHELP.@)
466 DWORD WINAPI SymSetOptions(DWORD opts)
468 struct process* pcs;
470 for (pcs = process_first; pcs; pcs = pcs->next)
472 pcs_callback(pcs, CBA_SET_OPTIONS, &opts);
474 return dbghelp_options = opts;
477 /******************************************************************
478 * SymGetOptions (DBGHELP.@)
481 DWORD WINAPI SymGetOptions(void)
483 return dbghelp_options;
486 /******************************************************************
487 * SymSetExtendedOption (DBGHELP.@)
490 BOOL WINAPI SymSetExtendedOption(IMAGEHLP_EXTENDED_OPTIONS option, BOOL value)
492 BOOL old = FALSE;
494 switch(option)
496 case SYMOPT_EX_WINE_NATIVE_MODULES:
497 old = dbghelp_opt_native;
498 dbghelp_opt_native = value;
499 break;
500 default:
501 FIXME("Unsupported option %d with value %d\n", option, value);
504 return old;
507 /******************************************************************
508 * SymGetExtendedOption (DBGHELP.@)
511 BOOL WINAPI SymGetExtendedOption(IMAGEHLP_EXTENDED_OPTIONS option)
513 switch(option)
515 case SYMOPT_EX_WINE_NATIVE_MODULES:
516 return dbghelp_opt_native;
517 default:
518 FIXME("Unsupported option %d\n", option);
521 return FALSE;
524 /******************************************************************
525 * SymSetParentWindow (DBGHELP.@)
528 BOOL WINAPI SymSetParentWindow(HWND hwnd)
530 /* Save hwnd so it can be used as parent window */
531 FIXME("(%p): stub\n", hwnd);
532 return TRUE;
535 /******************************************************************
536 * SymSetContext (DBGHELP.@)
539 BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame,
540 PIMAGEHLP_CONTEXT Context)
542 struct process* pcs = process_find_by_handle(hProcess);
543 if (!pcs) return FALSE;
545 if (pcs->ctx_frame.ReturnOffset == StackFrame->ReturnOffset &&
546 pcs->ctx_frame.FrameOffset == StackFrame->FrameOffset &&
547 pcs->ctx_frame.StackOffset == StackFrame->StackOffset)
549 TRACE("Setting same frame {rtn=%s frm=%s stk=%s}\n",
550 wine_dbgstr_longlong(pcs->ctx_frame.ReturnOffset),
551 wine_dbgstr_longlong(pcs->ctx_frame.FrameOffset),
552 wine_dbgstr_longlong(pcs->ctx_frame.StackOffset));
553 pcs->ctx_frame.InstructionOffset = StackFrame->InstructionOffset;
554 SetLastError(ERROR_ACCESS_DENIED); /* latest MSDN says ERROR_SUCCESS */
555 return FALSE;
558 pcs->ctx_frame = *StackFrame;
559 /* MSDN states that Context is not (no longer?) used */
560 return TRUE;
563 /******************************************************************
564 * reg_cb64to32 (internal)
566 * Registered callback for converting information from 64 bit to 32 bit
568 static BOOL CALLBACK reg_cb64to32(HANDLE hProcess, ULONG action, ULONG64 data, ULONG64 user)
570 struct process* pcs = process_find_by_handle(hProcess);
571 void* data32;
572 IMAGEHLP_DEFERRED_SYMBOL_LOAD64* idsl64;
573 IMAGEHLP_DEFERRED_SYMBOL_LOAD idsl;
575 if (!pcs) return FALSE;
576 switch (action)
578 case CBA_DEBUG_INFO:
579 case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
580 case CBA_SET_OPTIONS:
581 case CBA_SYMBOLS_UNLOADED:
582 data32 = (void*)(DWORD_PTR)data;
583 break;
584 case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
585 case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
586 case CBA_DEFERRED_SYMBOL_LOAD_PARTIAL:
587 case CBA_DEFERRED_SYMBOL_LOAD_START:
588 idsl64 = (IMAGEHLP_DEFERRED_SYMBOL_LOAD64*)(DWORD_PTR)data;
589 if (!validate_addr64(idsl64->BaseOfImage))
590 return FALSE;
591 idsl.SizeOfStruct = sizeof(idsl);
592 idsl.BaseOfImage = (DWORD)idsl64->BaseOfImage;
593 idsl.CheckSum = idsl64->CheckSum;
594 idsl.TimeDateStamp = idsl64->TimeDateStamp;
595 memcpy(idsl.FileName, idsl64->FileName, sizeof(idsl.FileName));
596 idsl.Reparse = idsl64->Reparse;
597 data32 = &idsl;
598 break;
599 case CBA_DUPLICATE_SYMBOL:
600 case CBA_EVENT:
601 case CBA_READ_MEMORY:
602 default:
603 FIXME("No mapping for action %u\n", action);
604 return FALSE;
606 return pcs->reg_cb32(hProcess, action, data32, (PVOID)(DWORD_PTR)user);
609 /******************************************************************
610 * pcs_callback (internal)
612 BOOL pcs_callback(const struct process* pcs, ULONG action, void* data)
614 IMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl;
616 TRACE("%p %u %p\n", pcs, action, data);
618 if (!pcs->reg_cb) return FALSE;
619 if (!pcs->reg_is_unicode)
621 IMAGEHLP_DEFERRED_SYMBOL_LOADW64* idslW;
623 switch (action)
625 case CBA_DEBUG_INFO:
626 case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
627 case CBA_SET_OPTIONS:
628 case CBA_SYMBOLS_UNLOADED:
629 break;
630 case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
631 case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
632 case CBA_DEFERRED_SYMBOL_LOAD_PARTIAL:
633 case CBA_DEFERRED_SYMBOL_LOAD_START:
634 idslW = data;
635 idsl.SizeOfStruct = sizeof(idsl);
636 idsl.BaseOfImage = idslW->BaseOfImage;
637 idsl.CheckSum = idslW->CheckSum;
638 idsl.TimeDateStamp = idslW->TimeDateStamp;
639 WideCharToMultiByte(CP_ACP, 0, idslW->FileName, -1,
640 idsl.FileName, sizeof(idsl.FileName), NULL, NULL);
641 idsl.Reparse = idslW->Reparse;
642 data = &idsl;
643 break;
644 case CBA_DUPLICATE_SYMBOL:
645 case CBA_EVENT:
646 case CBA_READ_MEMORY:
647 default:
648 FIXME("No mapping for action %u\n", action);
649 return FALSE;
652 return pcs->reg_cb(pcs->handle, action, (ULONG64)(DWORD_PTR)data, pcs->reg_user);
655 /******************************************************************
656 * sym_register_cb
658 * Helper for registering a callback.
660 static BOOL sym_register_cb(HANDLE hProcess,
661 PSYMBOL_REGISTERED_CALLBACK64 cb,
662 PSYMBOL_REGISTERED_CALLBACK cb32,
663 DWORD64 user, BOOL unicode)
665 struct process* pcs = process_find_by_handle(hProcess);
667 if (!pcs) return FALSE;
668 pcs->reg_cb = cb;
669 pcs->reg_cb32 = cb32;
670 pcs->reg_is_unicode = unicode;
671 pcs->reg_user = user;
673 return TRUE;
676 /***********************************************************************
677 * SymRegisterCallback (DBGHELP.@)
679 BOOL WINAPI SymRegisterCallback(HANDLE hProcess,
680 PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
681 PVOID UserContext)
683 TRACE("(%p, %p, %p)\n",
684 hProcess, CallbackFunction, UserContext);
685 return sym_register_cb(hProcess, reg_cb64to32, CallbackFunction, (DWORD_PTR)UserContext, FALSE);
688 /***********************************************************************
689 * SymRegisterCallback64 (DBGHELP.@)
691 BOOL WINAPI SymRegisterCallback64(HANDLE hProcess,
692 PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,
693 ULONG64 UserContext)
695 TRACE("(%p, %p, %s)\n",
696 hProcess, CallbackFunction, wine_dbgstr_longlong(UserContext));
697 return sym_register_cb(hProcess, CallbackFunction, NULL, UserContext, FALSE);
700 /***********************************************************************
701 * SymRegisterCallbackW64 (DBGHELP.@)
703 BOOL WINAPI SymRegisterCallbackW64(HANDLE hProcess,
704 PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,
705 ULONG64 UserContext)
707 TRACE("(%p, %p, %s)\n",
708 hProcess, CallbackFunction, wine_dbgstr_longlong(UserContext));
709 return sym_register_cb(hProcess, CallbackFunction, NULL, UserContext, TRUE);
712 /* This is imagehlp version not dbghelp !! */
713 static API_VERSION api_version = { 4, 0, 2, 0 };
715 /***********************************************************************
716 * ImagehlpApiVersion (DBGHELP.@)
718 LPAPI_VERSION WINAPI ImagehlpApiVersion(VOID)
720 return &api_version;
723 /***********************************************************************
724 * ImagehlpApiVersionEx (DBGHELP.@)
726 LPAPI_VERSION WINAPI ImagehlpApiVersionEx(LPAPI_VERSION AppVersion)
728 if (!AppVersion) return NULL;
730 AppVersion->MajorVersion = api_version.MajorVersion;
731 AppVersion->MinorVersion = api_version.MinorVersion;
732 AppVersion->Revision = api_version.Revision;
733 AppVersion->Reserved = api_version.Reserved;
735 return AppVersion;
738 /******************************************************************
739 * ExtensionApiVersion (DBGHELP.@)
741 LPEXT_API_VERSION WINAPI ExtensionApiVersion(void)
743 static EXT_API_VERSION eav = {5, 5, 5, 0};
744 return &eav;
747 /******************************************************************
748 * WinDbgExtensionDllInit (DBGHELP.@)
750 void WINAPI WinDbgExtensionDllInit(PWINDBG_EXTENSION_APIS lpExtensionApis,
751 unsigned short major, unsigned short minor)
755 DWORD calc_crc32(HANDLE handle)
757 BYTE buffer[8192];
758 DWORD crc = 0;
759 DWORD len;
761 SetFilePointer(handle, 0, 0, FILE_BEGIN);
762 while (ReadFile(handle, buffer, sizeof(buffer), &len, NULL) && len)
763 crc = RtlComputeCrc32(crc, buffer, len);
764 return crc;