1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2009-2014, Mario Vilas
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10#     * Redistributions of source code must retain the above copyright notice,
11#       this list of conditions and the following disclaimer.
12#     * Redistributions in binary form must reproduce the above copyright
13#       notice,this list of conditions and the following disclaimer in the
14#       documentation and/or other materials provided with the distribution.
15#     * Neither the name of the copyright holder nor the names of its
16#       contributors may be used to endorse or promote products derived from
17#       this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29# POSSIBILITY OF SUCH DAMAGE.
30
31"""
32Wrapper for dbghelp.dll in ctypes.
33"""
34
35__revision__ = "$Id$"
36
37from winappdbg.win32.defines import *
38from winappdbg.win32.version import *
39from winappdbg.win32.kernel32 import *
40
41# DbgHelp versions and features list:
42# http://msdn.microsoft.com/en-us/library/windows/desktop/ms679294(v=vs.85).aspx
43
44#------------------------------------------------------------------------------
45# Tries to load the newest version of dbghelp.dll if available.
46
47def _load_latest_dbghelp_dll():
48
49    from os import getenv
50    from os.path import join, exists
51
52    program_files_location = getenv("ProgramFiles")
53    if not program_files_location:
54        program_files_location = "C:\\Program Files"
55
56    program_files_x86_location = getenv("ProgramFiles(x86)")
57
58    if arch == ARCH_AMD64:
59        if wow64:
60            pathname = join(
61                            program_files_x86_location or program_files_location,
62                            "Debugging Tools for Windows (x86)",
63                            "dbghelp.dll")
64        else:
65            pathname = join(
66                            program_files_location,
67                            "Debugging Tools for Windows (x64)",
68                            "dbghelp.dll")
69    elif arch == ARCH_I386:
70        pathname = join(
71                        program_files_location,
72                        "Debugging Tools for Windows (x86)",
73                        "dbghelp.dll")
74    else:
75        pathname = None
76
77    if pathname and exists(pathname):
78        try:
79            _dbghelp = ctypes.windll.LoadLibrary(pathname)
80            ctypes.windll.dbghelp = _dbghelp
81        except Exception:
82            pass
83
84_load_latest_dbghelp_dll()
85
86# Recover the old binding of the "os" symbol.
87# XXX FIXME not sure if I really need to do this!
88##from version import os
89
90#------------------------------------------------------------------------------
91
92#==============================================================================
93# This is used later on to calculate the list of exported symbols.
94_all = None
95_all = set(vars().keys())
96#==============================================================================
97
98# SymGetHomeDirectory "type" values
99hdBase = 0
100hdSym  = 1
101hdSrc  = 2
102
103UNDNAME_32_BIT_DECODE           = 0x0800
104UNDNAME_COMPLETE                = 0x0000
105UNDNAME_NAME_ONLY               = 0x1000
106UNDNAME_NO_ACCESS_SPECIFIERS    = 0x0080
107UNDNAME_NO_ALLOCATION_LANGUAGE  = 0x0010
108UNDNAME_NO_ALLOCATION_MODEL     = 0x0008
109UNDNAME_NO_ARGUMENTS            = 0x2000
110UNDNAME_NO_CV_THISTYPE          = 0x0040
111UNDNAME_NO_FUNCTION_RETURNS     = 0x0004
112UNDNAME_NO_LEADING_UNDERSCORES  = 0x0001
113UNDNAME_NO_MEMBER_TYPE          = 0x0200
114UNDNAME_NO_MS_KEYWORDS          = 0x0002
115UNDNAME_NO_MS_THISTYPE          = 0x0020
116UNDNAME_NO_RETURN_UDT_MODEL     = 0x0400
117UNDNAME_NO_SPECIAL_SYMS         = 0x4000
118UNDNAME_NO_THISTYPE             = 0x0060
119UNDNAME_NO_THROW_SIGNATURES     = 0x0100
120
121#--- IMAGEHLP_MODULE structure and related ------------------------------------
122
123SYMOPT_ALLOW_ABSOLUTE_SYMBOLS       = 0x00000800
124SYMOPT_ALLOW_ZERO_ADDRESS           = 0x01000000
125SYMOPT_AUTO_PUBLICS                 = 0x00010000
126SYMOPT_CASE_INSENSITIVE             = 0x00000001
127SYMOPT_DEBUG                        = 0x80000000
128SYMOPT_DEFERRED_LOADS               = 0x00000004
129SYMOPT_DISABLE_SYMSRV_AUTODETECT    = 0x02000000
130SYMOPT_EXACT_SYMBOLS                = 0x00000400
131SYMOPT_FAIL_CRITICAL_ERRORS         = 0x00000200
132SYMOPT_FAVOR_COMPRESSED             = 0x00800000
133SYMOPT_FLAT_DIRECTORY               = 0x00400000
134SYMOPT_IGNORE_CVREC                 = 0x00000080
135SYMOPT_IGNORE_IMAGEDIR              = 0x00200000
136SYMOPT_IGNORE_NT_SYMPATH            = 0x00001000
137SYMOPT_INCLUDE_32BIT_MODULES        = 0x00002000
138SYMOPT_LOAD_ANYTHING                = 0x00000040
139SYMOPT_LOAD_LINES                   = 0x00000010
140SYMOPT_NO_CPP                       = 0x00000008
141SYMOPT_NO_IMAGE_SEARCH              = 0x00020000
142SYMOPT_NO_PROMPTS                   = 0x00080000
143SYMOPT_NO_PUBLICS                   = 0x00008000
144SYMOPT_NO_UNQUALIFIED_LOADS         = 0x00000100
145SYMOPT_OVERWRITE                    = 0x00100000
146SYMOPT_PUBLICS_ONLY                 = 0x00004000
147SYMOPT_SECURE                       = 0x00040000
148SYMOPT_UNDNAME                      = 0x00000002
149
150##SSRVOPT_DWORD
151##SSRVOPT_DWORDPTR
152##SSRVOPT_GUIDPTR
153##
154##SSRVOPT_CALLBACK
155##SSRVOPT_DOWNSTREAM_STORE
156##SSRVOPT_FLAT_DEFAULT_STORE
157##SSRVOPT_FAVOR_COMPRESSED
158##SSRVOPT_NOCOPY
159##SSRVOPT_OVERWRITE
160##SSRVOPT_PARAMTYPE
161##SSRVOPT_PARENTWIN
162##SSRVOPT_PROXY
163##SSRVOPT_RESET
164##SSRVOPT_SECURE
165##SSRVOPT_SETCONTEXT
166##SSRVOPT_TRACE
167##SSRVOPT_UNATTENDED
168
169#    typedef enum
170#    {
171#        SymNone = 0,
172#        SymCoff,
173#        SymCv,
174#        SymPdb,
175#        SymExport,
176#        SymDeferred,
177#        SymSym,
178#        SymDia,
179#        SymVirtual,
180#        NumSymTypes
181#    } SYM_TYPE;
182SymNone     = 0
183SymCoff     = 1
184SymCv       = 2
185SymPdb      = 3
186SymExport   = 4
187SymDeferred = 5
188SymSym      = 6
189SymDia      = 7
190SymVirtual  = 8
191NumSymTypes = 9
192
193#    typedef struct _IMAGEHLP_MODULE64 {
194#      DWORD    SizeOfStruct;
195#      DWORD64  BaseOfImage;
196#      DWORD    ImageSize;
197#      DWORD    TimeDateStamp;
198#      DWORD    CheckSum;
199#      DWORD    NumSyms;
200#      SYM_TYPE SymType;
201#      TCHAR    ModuleName[32];
202#      TCHAR    ImageName[256];
203#      TCHAR    LoadedImageName[256];
204#      TCHAR    LoadedPdbName[256];
205#      DWORD    CVSig;
206#      TCHAR    CVData[MAX_PATH*3];
207#      DWORD    PdbSig;
208#      GUID     PdbSig70;
209#      DWORD    PdbAge;
210#      BOOL     PdbUnmatched;
211#      BOOL     DbgUnmatched;
212#      BOOL     LineNumbers;
213#      BOOL     GlobalSymbols;
214#      BOOL     TypeInfo;
215#      BOOL     SourceIndexed;
216#      BOOL     Publics;
217#    } IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64;
218
219class IMAGEHLP_MODULE (Structure):
220    _fields_ = [
221        ("SizeOfStruct",    DWORD),
222        ("BaseOfImage",     DWORD),
223        ("ImageSize",       DWORD),
224        ("TimeDateStamp",   DWORD),
225        ("CheckSum",        DWORD),
226        ("NumSyms",         DWORD),
227        ("SymType",         DWORD),         # SYM_TYPE
228        ("ModuleName",      CHAR * 32),
229        ("ImageName",       CHAR * 256),
230        ("LoadedImageName", CHAR * 256),
231    ]
232PIMAGEHLP_MODULE = POINTER(IMAGEHLP_MODULE)
233
234class IMAGEHLP_MODULE64 (Structure):
235    _fields_ = [
236        ("SizeOfStruct",    DWORD),
237        ("BaseOfImage",     DWORD64),
238        ("ImageSize",       DWORD),
239        ("TimeDateStamp",   DWORD),
240        ("CheckSum",        DWORD),
241        ("NumSyms",         DWORD),
242        ("SymType",         DWORD),         # SYM_TYPE
243        ("ModuleName",      CHAR * 32),
244        ("ImageName",       CHAR * 256),
245        ("LoadedImageName", CHAR * 256),
246        ("LoadedPdbName",   CHAR * 256),
247        ("CVSig",           DWORD),
248        ("CVData",          CHAR * (MAX_PATH * 3)),
249        ("PdbSig",          DWORD),
250        ("PdbSig70",        GUID),
251        ("PdbAge",          DWORD),
252        ("PdbUnmatched",    BOOL),
253        ("DbgUnmatched",    BOOL),
254        ("LineNumbers",     BOOL),
255        ("GlobalSymbols",   BOOL),
256        ("TypeInfo",        BOOL),
257        ("SourceIndexed",   BOOL),
258        ("Publics",         BOOL),
259    ]
260PIMAGEHLP_MODULE64 = POINTER(IMAGEHLP_MODULE64)
261
262class IMAGEHLP_MODULEW (Structure):
263    _fields_ = [
264        ("SizeOfStruct",    DWORD),
265        ("BaseOfImage",     DWORD),
266        ("ImageSize",       DWORD),
267        ("TimeDateStamp",   DWORD),
268        ("CheckSum",        DWORD),
269        ("NumSyms",         DWORD),
270        ("SymType",         DWORD),         # SYM_TYPE
271        ("ModuleName",      WCHAR * 32),
272        ("ImageName",       WCHAR * 256),
273        ("LoadedImageName", WCHAR * 256),
274    ]
275PIMAGEHLP_MODULEW = POINTER(IMAGEHLP_MODULEW)
276
277class IMAGEHLP_MODULEW64 (Structure):
278    _fields_ = [
279        ("SizeOfStruct",    DWORD),
280        ("BaseOfImage",     DWORD64),
281        ("ImageSize",       DWORD),
282        ("TimeDateStamp",   DWORD),
283        ("CheckSum",        DWORD),
284        ("NumSyms",         DWORD),
285        ("SymType",         DWORD),         # SYM_TYPE
286        ("ModuleName",      WCHAR * 32),
287        ("ImageName",       WCHAR * 256),
288        ("LoadedImageName", WCHAR * 256),
289        ("LoadedPdbName",   WCHAR * 256),
290        ("CVSig",           DWORD),
291        ("CVData",          WCHAR * (MAX_PATH * 3)),
292        ("PdbSig",          DWORD),
293        ("PdbSig70",        GUID),
294        ("PdbAge",          DWORD),
295        ("PdbUnmatched",    BOOL),
296        ("DbgUnmatched",    BOOL),
297        ("LineNumbers",     BOOL),
298        ("GlobalSymbols",   BOOL),
299        ("TypeInfo",        BOOL),
300        ("SourceIndexed",   BOOL),
301        ("Publics",         BOOL),
302    ]
303PIMAGEHLP_MODULEW64 = POINTER(IMAGEHLP_MODULEW64)
304
305#--- dbghelp.dll --------------------------------------------------------------
306
307# XXX the ANSI versions of these functions don't end in "A" as expected!
308
309# BOOL WINAPI MakeSureDirectoryPathExists(
310#   _In_  PCSTR DirPath
311# );
312def MakeSureDirectoryPathExistsA(DirPath):
313    _MakeSureDirectoryPathExists = windll.dbghelp.MakeSureDirectoryPathExists
314    _MakeSureDirectoryPathExists.argtypes = [LPSTR]
315    _MakeSureDirectoryPathExists.restype  = bool
316    _MakeSureDirectoryPathExists.errcheck = RaiseIfZero
317    return _MakeSureDirectoryPathExists(DirPath)
318
319MakeSureDirectoryPathExistsW = MakeWideVersion(MakeSureDirectoryPathExistsA)
320MakeSureDirectoryPathExists = GuessStringType(MakeSureDirectoryPathExistsA, MakeSureDirectoryPathExistsW)
321
322# BOOL WINAPI SymInitialize(
323#   __in      HANDLE hProcess,
324#   __in_opt  PCTSTR UserSearchPath,
325#   __in      BOOL fInvadeProcess
326# );
327def SymInitializeA(hProcess, UserSearchPath = None, fInvadeProcess = False):
328    _SymInitialize = windll.dbghelp.SymInitialize
329    _SymInitialize.argtypes = [HANDLE, LPSTR, BOOL]
330    _SymInitialize.restype  = bool
331    _SymInitialize.errcheck = RaiseIfZero
332    if not UserSearchPath:
333        UserSearchPath = None
334    _SymInitialize(hProcess, UserSearchPath, fInvadeProcess)
335
336SymInitializeW = MakeWideVersion(SymInitializeA)
337SymInitialize = GuessStringType(SymInitializeA, SymInitializeW)
338
339# BOOL WINAPI SymCleanup(
340#   __in  HANDLE hProcess
341# );
342def SymCleanup(hProcess):
343    _SymCleanup = windll.dbghelp.SymCleanup
344    _SymCleanup.argtypes = [HANDLE]
345    _SymCleanup.restype  = bool
346    _SymCleanup.errcheck = RaiseIfZero
347    _SymCleanup(hProcess)
348
349# BOOL WINAPI SymRefreshModuleList(
350#   __in  HANDLE hProcess
351# );
352def SymRefreshModuleList(hProcess):
353    _SymRefreshModuleList = windll.dbghelp.SymRefreshModuleList
354    _SymRefreshModuleList.argtypes = [HANDLE]
355    _SymRefreshModuleList.restype  = bool
356    _SymRefreshModuleList.errcheck = RaiseIfZero
357    _SymRefreshModuleList(hProcess)
358
359# BOOL WINAPI SymSetParentWindow(
360#   __in  HWND hwnd
361# );
362def SymSetParentWindow(hwnd):
363    _SymSetParentWindow = windll.dbghelp.SymSetParentWindow
364    _SymSetParentWindow.argtypes = [HWND]
365    _SymSetParentWindow.restype  = bool
366    _SymSetParentWindow.errcheck = RaiseIfZero
367    _SymSetParentWindow(hwnd)
368
369# DWORD WINAPI SymSetOptions(
370#   __in  DWORD SymOptions
371# );
372def SymSetOptions(SymOptions):
373    _SymSetOptions = windll.dbghelp.SymSetOptions
374    _SymSetOptions.argtypes = [DWORD]
375    _SymSetOptions.restype  = DWORD
376    _SymSetOptions.errcheck = RaiseIfZero
377    _SymSetOptions(SymOptions)
378
379# DWORD WINAPI SymGetOptions(void);
380def SymGetOptions():
381    _SymGetOptions = windll.dbghelp.SymGetOptions
382    _SymGetOptions.argtypes = []
383    _SymGetOptions.restype  = DWORD
384    return _SymGetOptions()
385
386# DWORD WINAPI SymLoadModule(
387#   __in      HANDLE hProcess,
388#   __in_opt  HANDLE hFile,
389#   __in_opt  PCSTR ImageName,
390#   __in_opt  PCSTR ModuleName,
391#   __in      DWORD BaseOfDll,
392#   __in      DWORD SizeOfDll
393# );
394def SymLoadModuleA(hProcess, hFile = None, ImageName = None, ModuleName = None, BaseOfDll = None, SizeOfDll = None):
395    _SymLoadModule = windll.dbghelp.SymLoadModule
396    _SymLoadModule.argtypes = [HANDLE, HANDLE, LPSTR, LPSTR, DWORD, DWORD]
397    _SymLoadModule.restype  = DWORD
398
399    if not ImageName:
400        ImageName = None
401    if not ModuleName:
402        ModuleName = None
403    if not BaseOfDll:
404        BaseOfDll = 0
405    if not SizeOfDll:
406        SizeOfDll = 0
407    SetLastError(ERROR_SUCCESS)
408    lpBaseAddress = _SymLoadModule(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll)
409    if lpBaseAddress == NULL:
410        dwErrorCode = GetLastError()
411        if dwErrorCode != ERROR_SUCCESS:
412            raise ctypes.WinError(dwErrorCode)
413    return lpBaseAddress
414
415SymLoadModuleW = MakeWideVersion(SymLoadModuleA)
416SymLoadModule = GuessStringType(SymLoadModuleA, SymLoadModuleW)
417
418# DWORD64 WINAPI SymLoadModule64(
419#   __in      HANDLE hProcess,
420#   __in_opt  HANDLE hFile,
421#   __in_opt  PCSTR ImageName,
422#   __in_opt  PCSTR ModuleName,
423#   __in      DWORD64 BaseOfDll,
424#   __in      DWORD SizeOfDll
425# );
426def SymLoadModule64A(hProcess, hFile = None, ImageName = None, ModuleName = None, BaseOfDll = None, SizeOfDll = None):
427    _SymLoadModule64 = windll.dbghelp.SymLoadModule64
428    _SymLoadModule64.argtypes = [HANDLE, HANDLE, LPSTR, LPSTR, DWORD64, DWORD]
429    _SymLoadModule64.restype  = DWORD64
430
431    if not ImageName:
432        ImageName = None
433    if not ModuleName:
434        ModuleName = None
435    if not BaseOfDll:
436        BaseOfDll = 0
437    if not SizeOfDll:
438        SizeOfDll = 0
439    SetLastError(ERROR_SUCCESS)
440    lpBaseAddress = _SymLoadModule64(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll)
441    if lpBaseAddress == NULL:
442        dwErrorCode = GetLastError()
443        if dwErrorCode != ERROR_SUCCESS:
444            raise ctypes.WinError(dwErrorCode)
445    return lpBaseAddress
446
447SymLoadModule64W = MakeWideVersion(SymLoadModule64A)
448SymLoadModule64 = GuessStringType(SymLoadModule64A, SymLoadModule64W)
449
450# BOOL WINAPI SymUnloadModule(
451#   __in  HANDLE hProcess,
452#   __in  DWORD BaseOfDll
453# );
454def SymUnloadModule(hProcess, BaseOfDll):
455    _SymUnloadModule = windll.dbghelp.SymUnloadModule
456    _SymUnloadModule.argtypes = [HANDLE, DWORD]
457    _SymUnloadModule.restype  = bool
458    _SymUnloadModule.errcheck = RaiseIfZero
459    _SymUnloadModule(hProcess, BaseOfDll)
460
461# BOOL WINAPI SymUnloadModule64(
462#   __in  HANDLE hProcess,
463#   __in  DWORD64 BaseOfDll
464# );
465def SymUnloadModule64(hProcess, BaseOfDll):
466    _SymUnloadModule64 = windll.dbghelp.SymUnloadModule64
467    _SymUnloadModule64.argtypes = [HANDLE, DWORD64]
468    _SymUnloadModule64.restype  = bool
469    _SymUnloadModule64.errcheck = RaiseIfZero
470    _SymUnloadModule64(hProcess, BaseOfDll)
471
472# BOOL WINAPI SymGetModuleInfo(
473#   __in   HANDLE hProcess,
474#   __in   DWORD dwAddr,
475#   __out  PIMAGEHLP_MODULE ModuleInfo
476# );
477def SymGetModuleInfoA(hProcess, dwAddr):
478    _SymGetModuleInfo = windll.dbghelp.SymGetModuleInfo
479    _SymGetModuleInfo.argtypes = [HANDLE, DWORD, PIMAGEHLP_MODULE]
480    _SymGetModuleInfo.restype  = bool
481    _SymGetModuleInfo.errcheck = RaiseIfZero
482
483    ModuleInfo = IMAGEHLP_MODULE()
484    ModuleInfo.SizeOfStruct = sizeof(ModuleInfo)
485    _SymGetModuleInfo(hProcess, dwAddr, byref(ModuleInfo))
486    return ModuleInfo
487
488def SymGetModuleInfoW(hProcess, dwAddr):
489    _SymGetModuleInfoW = windll.dbghelp.SymGetModuleInfoW
490    _SymGetModuleInfoW.argtypes = [HANDLE, DWORD, PIMAGEHLP_MODULEW]
491    _SymGetModuleInfoW.restype  = bool
492    _SymGetModuleInfoW.errcheck = RaiseIfZero
493
494    ModuleInfo = IMAGEHLP_MODULEW()
495    ModuleInfo.SizeOfStruct = sizeof(ModuleInfo)
496    _SymGetModuleInfoW(hProcess, dwAddr, byref(ModuleInfo))
497    return ModuleInfo
498
499SymGetModuleInfo = GuessStringType(SymGetModuleInfoA, SymGetModuleInfoW)
500
501# BOOL WINAPI SymGetModuleInfo64(
502#   __in   HANDLE hProcess,
503#   __in   DWORD64 dwAddr,
504#   __out  PIMAGEHLP_MODULE64 ModuleInfo
505# );
506def SymGetModuleInfo64A(hProcess, dwAddr):
507    _SymGetModuleInfo64 = windll.dbghelp.SymGetModuleInfo64
508    _SymGetModuleInfo64.argtypes = [HANDLE, DWORD64, PIMAGEHLP_MODULE64]
509    _SymGetModuleInfo64.restype  = bool
510    _SymGetModuleInfo64.errcheck = RaiseIfZero
511
512    ModuleInfo = IMAGEHLP_MODULE64()
513    ModuleInfo.SizeOfStruct = sizeof(ModuleInfo)
514    _SymGetModuleInfo64(hProcess, dwAddr, byref(ModuleInfo))
515    return ModuleInfo
516
517def SymGetModuleInfo64W(hProcess, dwAddr):
518    _SymGetModuleInfo64W = windll.dbghelp.SymGetModuleInfo64W
519    _SymGetModuleInfo64W.argtypes = [HANDLE, DWORD64, PIMAGEHLP_MODULE64W]
520    _SymGetModuleInfo64W.restype  = bool
521    _SymGetModuleInfo64W.errcheck = RaiseIfZero
522
523    ModuleInfo = IMAGEHLP_MODULE64W()
524    ModuleInfo.SizeOfStruct = sizeof(ModuleInfo)
525    _SymGetModuleInfo64W(hProcess, dwAddr, byref(ModuleInfo))
526    return ModuleInfo
527
528SymGetModuleInfo64 = GuessStringType(SymGetModuleInfo64A, SymGetModuleInfo64W)
529
530# BOOL CALLBACK SymEnumerateModulesProc(
531#   __in      PCTSTR ModuleName,
532#   __in      DWORD BaseOfDll,
533#   __in_opt  PVOID UserContext
534# );
535PSYM_ENUMMODULES_CALLBACK    = WINFUNCTYPE(BOOL, LPSTR,  DWORD,   PVOID)
536PSYM_ENUMMODULES_CALLBACKW   = WINFUNCTYPE(BOOL, LPWSTR, DWORD,   PVOID)
537
538# BOOL CALLBACK SymEnumerateModulesProc64(
539#   __in      PCTSTR ModuleName,
540#   __in      DWORD64 BaseOfDll,
541#   __in_opt  PVOID UserContext
542# );
543PSYM_ENUMMODULES_CALLBACK64  = WINFUNCTYPE(BOOL, LPSTR,  DWORD64, PVOID)
544PSYM_ENUMMODULES_CALLBACKW64 = WINFUNCTYPE(BOOL, LPWSTR, DWORD64, PVOID)
545
546# BOOL WINAPI SymEnumerateModules(
547#   __in      HANDLE hProcess,
548#   __in      PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,
549#   __in_opt  PVOID UserContext
550# );
551def SymEnumerateModulesA(hProcess, EnumModulesCallback, UserContext = None):
552    _SymEnumerateModules = windll.dbghelp.SymEnumerateModules
553    _SymEnumerateModules.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACK, PVOID]
554    _SymEnumerateModules.restype  = bool
555    _SymEnumerateModules.errcheck = RaiseIfZero
556
557    EnumModulesCallback = PSYM_ENUMMODULES_CALLBACK(EnumModulesCallback)
558    if UserContext:
559        UserContext = ctypes.pointer(UserContext)
560    else:
561        UserContext = LPVOID(NULL)
562    _SymEnumerateModules(hProcess, EnumModulesCallback, UserContext)
563
564def SymEnumerateModulesW(hProcess, EnumModulesCallback, UserContext = None):
565    _SymEnumerateModulesW = windll.dbghelp.SymEnumerateModulesW
566    _SymEnumerateModulesW.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACKW, PVOID]
567    _SymEnumerateModulesW.restype  = bool
568    _SymEnumerateModulesW.errcheck = RaiseIfZero
569
570    EnumModulesCallback = PSYM_ENUMMODULES_CALLBACKW(EnumModulesCallback)
571    if UserContext:
572        UserContext = ctypes.pointer(UserContext)
573    else:
574        UserContext = LPVOID(NULL)
575    _SymEnumerateModulesW(hProcess, EnumModulesCallback, UserContext)
576
577SymEnumerateModules = GuessStringType(SymEnumerateModulesA, SymEnumerateModulesW)
578
579# BOOL WINAPI SymEnumerateModules64(
580#   __in      HANDLE hProcess,
581#   __in      PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,
582#   __in_opt  PVOID UserContext
583# );
584def SymEnumerateModules64A(hProcess, EnumModulesCallback, UserContext = None):
585    _SymEnumerateModules64 = windll.dbghelp.SymEnumerateModules64
586    _SymEnumerateModules64.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACK64, PVOID]
587    _SymEnumerateModules64.restype  = bool
588    _SymEnumerateModules64.errcheck = RaiseIfZero
589
590    EnumModulesCallback = PSYM_ENUMMODULES_CALLBACK64(EnumModulesCallback)
591    if UserContext:
592        UserContext = ctypes.pointer(UserContext)
593    else:
594        UserContext = LPVOID(NULL)
595    _SymEnumerateModules64(hProcess, EnumModulesCallback, UserContext)
596
597def SymEnumerateModules64W(hProcess, EnumModulesCallback, UserContext = None):
598    _SymEnumerateModules64W = windll.dbghelp.SymEnumerateModules64W
599    _SymEnumerateModules64W.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACK64W, PVOID]
600    _SymEnumerateModules64W.restype  = bool
601    _SymEnumerateModules64W.errcheck = RaiseIfZero
602
603    EnumModulesCallback = PSYM_ENUMMODULES_CALLBACK64W(EnumModulesCallback)
604    if UserContext:
605        UserContext = ctypes.pointer(UserContext)
606    else:
607        UserContext = LPVOID(NULL)
608    _SymEnumerateModules64W(hProcess, EnumModulesCallback, UserContext)
609
610SymEnumerateModules64 = GuessStringType(SymEnumerateModules64A, SymEnumerateModules64W)
611
612# BOOL CALLBACK SymEnumerateSymbolsProc(
613#   __in      PCTSTR SymbolName,
614#   __in      DWORD SymbolAddress,
615#   __in      ULONG SymbolSize,
616#   __in_opt  PVOID UserContext
617# );
618PSYM_ENUMSYMBOLS_CALLBACK    = WINFUNCTYPE(BOOL, LPSTR,  DWORD,   ULONG, PVOID)
619PSYM_ENUMSYMBOLS_CALLBACKW   = WINFUNCTYPE(BOOL, LPWSTR, DWORD,   ULONG, PVOID)
620
621# BOOL CALLBACK SymEnumerateSymbolsProc64(
622#   __in      PCTSTR SymbolName,
623#   __in      DWORD64 SymbolAddress,
624#   __in      ULONG SymbolSize,
625#   __in_opt  PVOID UserContext
626# );
627PSYM_ENUMSYMBOLS_CALLBACK64  = WINFUNCTYPE(BOOL, LPSTR,  DWORD64, ULONG, PVOID)
628PSYM_ENUMSYMBOLS_CALLBACKW64 = WINFUNCTYPE(BOOL, LPWSTR, DWORD64, ULONG, PVOID)
629
630# BOOL WINAPI SymEnumerateSymbols(
631#   __in      HANDLE hProcess,
632#   __in      ULONG BaseOfDll,
633#   __in      PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback,
634#   __in_opt  PVOID UserContext
635# );
636def SymEnumerateSymbolsA(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None):
637    _SymEnumerateSymbols = windll.dbghelp.SymEnumerateSymbols
638    _SymEnumerateSymbols.argtypes = [HANDLE, ULONG, PSYM_ENUMSYMBOLS_CALLBACK, PVOID]
639    _SymEnumerateSymbols.restype  = bool
640    _SymEnumerateSymbols.errcheck = RaiseIfZero
641
642    EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACK(EnumSymbolsCallback)
643    if UserContext:
644        UserContext = ctypes.pointer(UserContext)
645    else:
646        UserContext = LPVOID(NULL)
647    _SymEnumerateSymbols(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext)
648
649def SymEnumerateSymbolsW(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None):
650    _SymEnumerateSymbolsW = windll.dbghelp.SymEnumerateSymbolsW
651    _SymEnumerateSymbolsW.argtypes = [HANDLE, ULONG, PSYM_ENUMSYMBOLS_CALLBACKW, PVOID]
652    _SymEnumerateSymbolsW.restype  = bool
653    _SymEnumerateSymbolsW.errcheck = RaiseIfZero
654
655    EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACKW(EnumSymbolsCallback)
656    if UserContext:
657        UserContext = ctypes.pointer(UserContext)
658    else:
659        UserContext = LPVOID(NULL)
660    _SymEnumerateSymbolsW(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext)
661
662SymEnumerateSymbols = GuessStringType(SymEnumerateSymbolsA, SymEnumerateSymbolsW)
663
664# BOOL WINAPI SymEnumerateSymbols64(
665#   __in      HANDLE hProcess,
666#   __in      ULONG64 BaseOfDll,
667#   __in      PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,
668#   __in_opt  PVOID UserContext
669# );
670def SymEnumerateSymbols64A(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None):
671    _SymEnumerateSymbols64 = windll.dbghelp.SymEnumerateSymbols64
672    _SymEnumerateSymbols64.argtypes = [HANDLE, ULONG64, PSYM_ENUMSYMBOLS_CALLBACK64, PVOID]
673    _SymEnumerateSymbols64.restype  = bool
674    _SymEnumerateSymbols64.errcheck = RaiseIfZero
675
676    EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACK64(EnumSymbolsCallback)
677    if UserContext:
678        UserContext = ctypes.pointer(UserContext)
679    else:
680        UserContext = LPVOID(NULL)
681    _SymEnumerateSymbols64(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext)
682
683def SymEnumerateSymbols64W(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None):
684    _SymEnumerateSymbols64W = windll.dbghelp.SymEnumerateSymbols64W
685    _SymEnumerateSymbols64W.argtypes = [HANDLE, ULONG64, PSYM_ENUMSYMBOLS_CALLBACK64W, PVOID]
686    _SymEnumerateSymbols64W.restype  = bool
687    _SymEnumerateSymbols64W.errcheck = RaiseIfZero
688
689    EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACK64W(EnumSymbolsCallback)
690    if UserContext:
691        UserContext = ctypes.pointer(UserContext)
692    else:
693        UserContext = LPVOID(NULL)
694    _SymEnumerateSymbols64W(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext)
695
696SymEnumerateSymbols64 = GuessStringType(SymEnumerateSymbols64A, SymEnumerateSymbols64W)
697
698# DWORD WINAPI UnDecorateSymbolName(
699#   __in   PCTSTR DecoratedName,
700#   __out  PTSTR UnDecoratedName,
701#   __in   DWORD UndecoratedLength,
702#   __in   DWORD Flags
703# );
704def UnDecorateSymbolNameA(DecoratedName, Flags = UNDNAME_COMPLETE):
705    _UnDecorateSymbolNameA = windll.dbghelp.UnDecorateSymbolName
706    _UnDecorateSymbolNameA.argtypes = [LPSTR, LPSTR, DWORD, DWORD]
707    _UnDecorateSymbolNameA.restype  = DWORD
708    _UnDecorateSymbolNameA.errcheck = RaiseIfZero
709
710    UndecoratedLength = _UnDecorateSymbolNameA(DecoratedName, None, 0, Flags)
711    UnDecoratedName = ctypes.create_string_buffer('', UndecoratedLength + 1)
712    _UnDecorateSymbolNameA(DecoratedName, UnDecoratedName, UndecoratedLength, Flags)
713    return UnDecoratedName.value
714
715def UnDecorateSymbolNameW(DecoratedName, Flags = UNDNAME_COMPLETE):
716    _UnDecorateSymbolNameW = windll.dbghelp.UnDecorateSymbolNameW
717    _UnDecorateSymbolNameW.argtypes = [LPWSTR, LPWSTR, DWORD, DWORD]
718    _UnDecorateSymbolNameW.restype  = DWORD
719    _UnDecorateSymbolNameW.errcheck = RaiseIfZero
720
721    UndecoratedLength = _UnDecorateSymbolNameW(DecoratedName, None, 0, Flags)
722    UnDecoratedName = ctypes.create_unicode_buffer(u'', UndecoratedLength + 1)
723    _UnDecorateSymbolNameW(DecoratedName, UnDecoratedName, UndecoratedLength, Flags)
724    return UnDecoratedName.value
725
726UnDecorateSymbolName = GuessStringType(UnDecorateSymbolNameA, UnDecorateSymbolNameW)
727
728# BOOL WINAPI SymGetSearchPath(
729#   __in   HANDLE hProcess,
730#   __out  PTSTR SearchPath,
731#   __in   DWORD SearchPathLength
732# );
733def SymGetSearchPathA(hProcess):
734    _SymGetSearchPath = windll.dbghelp.SymGetSearchPath
735    _SymGetSearchPath.argtypes = [HANDLE, LPSTR, DWORD]
736    _SymGetSearchPath.restype  = bool
737    _SymGetSearchPath.errcheck = RaiseIfZero
738
739    SearchPathLength = MAX_PATH
740    SearchPath = ctypes.create_string_buffer("", SearchPathLength)
741    _SymGetSearchPath(hProcess, SearchPath, SearchPathLength)
742    return SearchPath.value
743
744def SymGetSearchPathW(hProcess):
745    _SymGetSearchPathW = windll.dbghelp.SymGetSearchPathW
746    _SymGetSearchPathW.argtypes = [HANDLE, LPWSTR, DWORD]
747    _SymGetSearchPathW.restype  = bool
748    _SymGetSearchPathW.errcheck = RaiseIfZero
749
750    SearchPathLength = MAX_PATH
751    SearchPath = ctypes.create_unicode_buffer(u"", SearchPathLength)
752    _SymGetSearchPathW(hProcess, SearchPath, SearchPathLength)
753    return SearchPath.value
754
755SymGetSearchPath = GuessStringType(SymGetSearchPathA, SymGetSearchPathW)
756
757# BOOL WINAPI SymSetSearchPath(
758#   __in      HANDLE hProcess,
759#   __in_opt  PCTSTR SearchPath
760# );
761def SymSetSearchPathA(hProcess, SearchPath = None):
762    _SymSetSearchPath = windll.dbghelp.SymSetSearchPath
763    _SymSetSearchPath.argtypes = [HANDLE, LPSTR]
764    _SymSetSearchPath.restype  = bool
765    _SymSetSearchPath.errcheck = RaiseIfZero
766    if not SearchPath:
767        SearchPath = None
768    _SymSetSearchPath(hProcess, SearchPath)
769
770def SymSetSearchPathW(hProcess, SearchPath = None):
771    _SymSetSearchPathW = windll.dbghelp.SymSetSearchPathW
772    _SymSetSearchPathW.argtypes = [HANDLE, LPWSTR]
773    _SymSetSearchPathW.restype  = bool
774    _SymSetSearchPathW.errcheck = RaiseIfZero
775    if not SearchPath:
776        SearchPath = None
777    _SymSetSearchPathW(hProcess, SearchPath)
778
779SymSetSearchPath = GuessStringType(SymSetSearchPathA, SymSetSearchPathW)
780
781# PTCHAR WINAPI SymGetHomeDirectory(
782#   __in   DWORD type,
783#   __out  PTSTR dir,
784#   __in   size_t size
785# );
786def SymGetHomeDirectoryA(type):
787    _SymGetHomeDirectoryA = windll.dbghelp.SymGetHomeDirectoryA
788    _SymGetHomeDirectoryA.argtypes = [DWORD, LPSTR, SIZE_T]
789    _SymGetHomeDirectoryA.restype  = LPSTR
790    _SymGetHomeDirectoryA.errcheck = RaiseIfZero
791
792    size = MAX_PATH
793    dir  = ctypes.create_string_buffer("", size)
794    _SymGetHomeDirectoryA(type, dir, size)
795    return dir.value
796
797def SymGetHomeDirectoryW(type):
798    _SymGetHomeDirectoryW = windll.dbghelp.SymGetHomeDirectoryW
799    _SymGetHomeDirectoryW.argtypes = [DWORD, LPWSTR, SIZE_T]
800    _SymGetHomeDirectoryW.restype  = LPWSTR
801    _SymGetHomeDirectoryW.errcheck = RaiseIfZero
802
803    size = MAX_PATH
804    dir  = ctypes.create_unicode_buffer(u"", size)
805    _SymGetHomeDirectoryW(type, dir, size)
806    return dir.value
807
808SymGetHomeDirectory = GuessStringType(SymGetHomeDirectoryA, SymGetHomeDirectoryW)
809
810# PTCHAR WINAPI SymSetHomeDirectory(
811#   __in      HANDLE hProcess,
812#   __in_opt  PCTSTR dir
813# );
814def SymSetHomeDirectoryA(hProcess, dir = None):
815    _SymSetHomeDirectoryA = windll.dbghelp.SymSetHomeDirectoryA
816    _SymSetHomeDirectoryA.argtypes = [HANDLE, LPSTR]
817    _SymSetHomeDirectoryA.restype  = LPSTR
818    _SymSetHomeDirectoryA.errcheck = RaiseIfZero
819    if not dir:
820        dir = None
821    _SymSetHomeDirectoryA(hProcess, dir)
822    return dir
823
824def SymSetHomeDirectoryW(hProcess, dir = None):
825    _SymSetHomeDirectoryW = windll.dbghelp.SymSetHomeDirectoryW
826    _SymSetHomeDirectoryW.argtypes = [HANDLE, LPWSTR]
827    _SymSetHomeDirectoryW.restype  = LPWSTR
828    _SymSetHomeDirectoryW.errcheck = RaiseIfZero
829    if not dir:
830        dir = None
831    _SymSetHomeDirectoryW(hProcess, dir)
832    return dir
833
834SymSetHomeDirectory = GuessStringType(SymSetHomeDirectoryA, SymSetHomeDirectoryW)
835
836#--- DbgHelp 5+ support, patch by Neitsa --------------------------------------
837
838# XXX TODO
839# + use the GuessStringType decorator for ANSI/Wide versions
840# + replace hardcoded struct sizes with sizeof() calls
841# + StackWalk64 should raise on error, but something has to be done about it
842#   not setting the last error code (maybe we should call SetLastError
843#   ourselves with a default error code?)
844# /Mario
845
846#maximum length of a symbol name
847MAX_SYM_NAME = 2000
848
849class SYM_INFO(Structure):
850    _fields_ = [
851        ("SizeOfStruct",    ULONG),
852        ("TypeIndex",       ULONG),
853        ("Reserved",        ULONG64 * 2),
854        ("Index",           ULONG),
855        ("Size",            ULONG),
856        ("ModBase",         ULONG64),
857        ("Flags",           ULONG),
858        ("Value",           ULONG64),
859        ("Address",         ULONG64),
860        ("Register",        ULONG),
861        ("Scope",           ULONG),
862        ("Tag",             ULONG),
863        ("NameLen",         ULONG),
864        ("MaxNameLen",      ULONG),
865        ("Name",            CHAR * (MAX_SYM_NAME + 1)),
866    ]
867PSYM_INFO = POINTER(SYM_INFO)
868
869class SYM_INFOW(Structure):
870    _fields_ = [
871        ("SizeOfStruct",    ULONG),
872        ("TypeIndex",       ULONG),
873        ("Reserved",        ULONG64 * 2),
874        ("Index",           ULONG),
875        ("Size",            ULONG),
876        ("ModBase",         ULONG64),
877        ("Flags",           ULONG),
878        ("Value",           ULONG64),
879        ("Address",         ULONG64),
880        ("Register",        ULONG),
881        ("Scope",           ULONG),
882        ("Tag",             ULONG),
883        ("NameLen",         ULONG),
884        ("MaxNameLen",      ULONG),
885        ("Name",            WCHAR * (MAX_SYM_NAME + 1)),
886    ]
887PSYM_INFOW = POINTER(SYM_INFOW)
888
889#===============================================================================
890# BOOL WINAPI SymFromName(
891#  __in     HANDLE hProcess,
892#  __in     PCTSTR Name,
893#  __inout  PSYMBOL_INFO Symbol
894# );
895#===============================================================================
896def SymFromName(hProcess, Name):
897    _SymFromNameA = windll.dbghelp.SymFromName
898    _SymFromNameA.argtypes = [HANDLE, LPSTR, PSYM_INFO]
899    _SymFromNameA.restype = bool
900    _SymFromNameA.errcheck = RaiseIfZero
901
902    SymInfo = SYM_INFO()
903    SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFO) in C.
904    SymInfo.MaxNameLen = MAX_SYM_NAME
905
906    _SymFromNameA(hProcess, Name, byref(SymInfo))
907
908    return SymInfo
909
910def SymFromNameW(hProcess, Name):
911    _SymFromNameW = windll.dbghelp.SymFromNameW
912    _SymFromNameW.argtypes = [HANDLE, LPWSTR, PSYM_INFOW]
913    _SymFromNameW.restype = bool
914    _SymFromNameW.errcheck = RaiseIfZero
915
916    SymInfo = SYM_INFOW()
917    SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFOW) in C.
918    SymInfo.MaxNameLen = MAX_SYM_NAME
919
920    _SymFromNameW(hProcess, Name, byref(SymInfo))
921
922    return SymInfo
923
924#===============================================================================
925# BOOL WINAPI SymFromAddr(
926#  __in       HANDLE hProcess,
927#  __in       DWORD64 Address,
928#  __out_opt  PDWORD64 Displacement,
929#  __inout    PSYMBOL_INFO Symbol
930# );
931#===============================================================================
932def SymFromAddr(hProcess, Address):
933    _SymFromAddr = windll.dbghelp.SymFromAddr
934    _SymFromAddr.argtypes = [HANDLE, DWORD64, PDWORD64, PSYM_INFO]
935    _SymFromAddr.restype = bool
936    _SymFromAddr.errcheck = RaiseIfZero
937
938    SymInfo = SYM_INFO()
939    SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFO) in C.
940    SymInfo.MaxNameLen = MAX_SYM_NAME
941
942    Displacement = DWORD64(0)
943    _SymFromAddr(hProcess, Address, byref(Displacement), byref(SymInfo))
944
945    return (Displacement.value, SymInfo)
946
947def SymFromAddrW(hProcess, Address):
948    _SymFromAddr = windll.dbghelp.SymFromAddrW
949    _SymFromAddr.argtypes = [HANDLE, DWORD64, PDWORD64, PSYM_INFOW]
950    _SymFromAddr.restype = bool
951    _SymFromAddr.errcheck = RaiseIfZero
952
953    SymInfo = SYM_INFOW()
954    SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFOW) in C.
955    SymInfo.MaxNameLen = MAX_SYM_NAME
956
957    Displacement = DWORD64(0)
958    _SymFromAddr(hProcess, Address, byref(Displacement), byref(SymInfo))
959
960    return (Displacement.value, SymInfo)
961
962#===============================================================================
963# typedef struct _IMAGEHLP_SYMBOL64 {
964#  DWORD   SizeOfStruct;
965#  DWORD64 Address;
966#  DWORD   Size;
967#  DWORD   Flags;
968#  DWORD   MaxNameLength;
969#  CHAR   Name[1];
970# } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
971#===============================================================================
972class IMAGEHLP_SYMBOL64 (Structure):
973    _fields_ = [
974        ("SizeOfStruct",    DWORD),
975        ("Address",         DWORD64),
976        ("Size",            DWORD),
977        ("Flags",           DWORD),
978        ("MaxNameLength",   DWORD),
979        ("Name",            CHAR * (MAX_SYM_NAME + 1)),
980    ]
981PIMAGEHLP_SYMBOL64 = POINTER(IMAGEHLP_SYMBOL64)
982
983#===============================================================================
984# typedef struct _IMAGEHLP_SYMBOLW64 {
985#  DWORD   SizeOfStruct;
986#  DWORD64 Address;
987#  DWORD   Size;
988#  DWORD   Flags;
989#  DWORD   MaxNameLength;
990#  WCHAR   Name[1];
991# } IMAGEHLP_SYMBOLW64, *PIMAGEHLP_SYMBOLW64;
992#===============================================================================
993class IMAGEHLP_SYMBOLW64 (Structure):
994    _fields_ = [
995        ("SizeOfStruct",    DWORD),
996        ("Address",         DWORD64),
997        ("Size",            DWORD),
998        ("Flags",           DWORD),
999        ("MaxNameLength",   DWORD),
1000        ("Name",            WCHAR * (MAX_SYM_NAME + 1)),
1001    ]
1002PIMAGEHLP_SYMBOLW64 = POINTER(IMAGEHLP_SYMBOLW64)
1003
1004#===============================================================================
1005# BOOL WINAPI SymGetSymFromAddr64(
1006#  __in       HANDLE hProcess,
1007#  __in       DWORD64 Address,
1008#  __out_opt  PDWORD64 Displacement,
1009#  __inout    PIMAGEHLP_SYMBOL64 Symbol
1010# );
1011#===============================================================================
1012def SymGetSymFromAddr64(hProcess, Address):
1013    _SymGetSymFromAddr64 = windll.dbghelp.SymGetSymFromAddr64
1014    _SymGetSymFromAddr64.argtypes = [HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64]
1015    _SymGetSymFromAddr64.restype = bool
1016    _SymGetSymFromAddr64.errcheck = RaiseIfZero
1017
1018    imagehlp_symbol64 = IMAGEHLP_SYMBOL64()
1019    imagehlp_symbol64.SizeOfStruct = 32 # *don't modify*: sizeof(IMAGEHLP_SYMBOL64) in C.
1020    imagehlp_symbol64.MaxNameLen = MAX_SYM_NAME
1021
1022    Displacement = DWORD64(0)
1023    _SymGetSymFromAddr64(hProcess, Address, byref(Displacement), byref(imagehlp_symbol64))
1024
1025    return (Displacement.value, imagehlp_symbol64)
1026
1027#TODO: check for the 'W' version of SymGetSymFromAddr64()
1028
1029
1030#===============================================================================
1031# typedef struct API_VERSION {
1032#  USHORT MajorVersion;
1033#  USHORT MinorVersion;
1034#  USHORT Revision;
1035#  USHORT Reserved;
1036# } API_VERSION, *LPAPI_VERSION;
1037#===============================================================================
1038class API_VERSION (Structure):
1039    _fields_ = [
1040        ("MajorVersion",    USHORT),
1041        ("MinorVersion",    USHORT),
1042        ("Revision",        USHORT),
1043        ("Reserved",        USHORT),
1044    ]
1045PAPI_VERSION = POINTER(API_VERSION)
1046LPAPI_VERSION = PAPI_VERSION
1047
1048#===============================================================================
1049# LPAPI_VERSION WINAPI ImagehlpApiVersion(void);
1050#===============================================================================
1051def ImagehlpApiVersion():
1052    _ImagehlpApiVersion = windll.dbghelp.ImagehlpApiVersion
1053    _ImagehlpApiVersion.restype = LPAPI_VERSION
1054
1055    api_version = _ImagehlpApiVersion()
1056    return api_version.contents
1057
1058
1059#===============================================================================
1060# LPAPI_VERSION WINAPI ImagehlpApiVersionEx(
1061#  __in  LPAPI_VERSION AppVersion
1062# );
1063#===============================================================================
1064def ImagehlpApiVersionEx(MajorVersion, MinorVersion, Revision):
1065    _ImagehlpApiVersionEx = windll.dbghelp.ImagehlpApiVersionEx
1066    _ImagehlpApiVersionEx.argtypes = [LPAPI_VERSION]
1067    _ImagehlpApiVersionEx.restype = LPAPI_VERSION
1068
1069    api_version = API_VERSION(MajorVersion, MinorVersion, Revision, 0)
1070
1071    ret_api_version = _ImagehlpApiVersionEx(byref(api_version))
1072
1073    return ret_api_version.contents
1074
1075#===============================================================================
1076# typedef enum {
1077#     AddrMode1616,
1078#     AddrMode1632,
1079#     AddrModeReal,
1080#     AddrModeFlat
1081# } ADDRESS_MODE;
1082#===============================================================================
1083AddrMode1616 = 0
1084AddrMode1632 = 1
1085AddrModeReal = 2
1086AddrModeFlat = 3
1087
1088ADDRESS_MODE = DWORD #needed for the size of an ADDRESS_MODE (see ADDRESS64)
1089
1090#===============================================================================
1091# typedef struct _tagADDRESS64 {
1092#  DWORD64      Offset;
1093#  WORD         Segment;
1094#  ADDRESS_MODE Mode;
1095# } ADDRESS64, *LPADDRESS64;
1096#===============================================================================
1097class ADDRESS64 (Structure):
1098    _fields_ = [
1099        ("Offset",      DWORD64),
1100        ("Segment",     WORD),
1101        ("Mode",        ADDRESS_MODE),  #it's a member of the ADDRESS_MODE enum.
1102    ]
1103LPADDRESS64 = POINTER(ADDRESS64)
1104
1105#===============================================================================
1106# typedef struct _KDHELP64 {
1107#    DWORD64   Thread;
1108#    DWORD   ThCallbackStack;
1109#    DWORD   ThCallbackBStore;
1110#    DWORD   NextCallback;
1111#    DWORD   FramePointer;
1112#    DWORD64   KiCallUserMode;
1113#    DWORD64   KeUserCallbackDispatcher;
1114#    DWORD64   SystemRangeStart;
1115#    DWORD64   KiUserExceptionDispatcher;
1116#    DWORD64   StackBase;
1117#    DWORD64   StackLimit;
1118#    DWORD64   Reserved[5];
1119# } KDHELP64, *PKDHELP64;
1120#===============================================================================
1121class KDHELP64 (Structure):
1122    _fields_ = [
1123        ("Thread",              DWORD64),
1124        ("ThCallbackStack",     DWORD),
1125        ("ThCallbackBStore",    DWORD),
1126        ("NextCallback",        DWORD),
1127        ("FramePointer",        DWORD),
1128        ("KiCallUserMode",      DWORD64),
1129        ("KeUserCallbackDispatcher",    DWORD64),
1130        ("SystemRangeStart",    DWORD64),
1131        ("KiUserExceptionDispatcher",   DWORD64),
1132        ("StackBase",           DWORD64),
1133        ("StackLimit",          DWORD64),
1134        ("Reserved",            DWORD64 * 5),
1135    ]
1136PKDHELP64 = POINTER(KDHELP64)
1137
1138#===============================================================================
1139# typedef struct _tagSTACKFRAME64 {
1140#  ADDRESS64 AddrPC;
1141#  ADDRESS64 AddrReturn;
1142#  ADDRESS64 AddrFrame;
1143#  ADDRESS64 AddrStack;
1144#  ADDRESS64 AddrBStore;
1145#  PVOID     FuncTableEntry;
1146#  DWORD64   Params[4];
1147#  BOOL      Far;
1148#  BOOL      Virtual;
1149#  DWORD64   Reserved[3];
1150#  KDHELP64  KdHelp;
1151# } STACKFRAME64, *LPSTACKFRAME64;
1152#===============================================================================
1153class STACKFRAME64(Structure):
1154    _fields_ = [
1155        ("AddrPC",          ADDRESS64),
1156        ("AddrReturn",      ADDRESS64),
1157        ("AddrFrame",       ADDRESS64),
1158        ("AddrStack",       ADDRESS64),
1159        ("AddrBStore",      ADDRESS64),
1160        ("FuncTableEntry",  PVOID),
1161        ("Params",          DWORD64 * 4),
1162        ("Far",             BOOL),
1163        ("Virtual",         BOOL),
1164        ("Reserved",        DWORD64 * 3),
1165        ("KdHelp",          KDHELP64),
1166    ]
1167LPSTACKFRAME64 = POINTER(STACKFRAME64)
1168
1169#===============================================================================
1170# BOOL CALLBACK ReadProcessMemoryProc64(
1171#  __in   HANDLE hProcess,
1172#  __in   DWORD64 lpBaseAddress,
1173#  __out  PVOID lpBuffer,
1174#  __in   DWORD nSize,
1175#  __out  LPDWORD lpNumberOfBytesRead
1176# );
1177#===============================================================================
1178PREAD_PROCESS_MEMORY_ROUTINE64 = WINFUNCTYPE(BOOL, HANDLE, DWORD64, PVOID, DWORD, LPDWORD)
1179
1180#===============================================================================
1181# PVOID CALLBACK FunctionTableAccessProc64(
1182#  __in  HANDLE hProcess,
1183#  __in  DWORD64 AddrBase
1184# );
1185#===============================================================================
1186PFUNCTION_TABLE_ACCESS_ROUTINE64 = WINFUNCTYPE(PVOID, HANDLE, DWORD64)
1187
1188#===============================================================================
1189# DWORD64 CALLBACK GetModuleBaseProc64(
1190#  __in  HANDLE hProcess,
1191#  __in  DWORD64 Address
1192# );
1193#===============================================================================
1194PGET_MODULE_BASE_ROUTINE64 = WINFUNCTYPE(DWORD64, HANDLE, DWORD64)
1195
1196#===============================================================================
1197# DWORD64 CALLBACK GetModuleBaseProc64(
1198#  __in  HANDLE hProcess,
1199#  __in  DWORD64 Address
1200# );
1201#===============================================================================
1202PTRANSLATE_ADDRESS_ROUTINE64 = WINFUNCTYPE(DWORD64, HANDLE, DWORD64)
1203
1204# Valid machine types for StackWalk64 function
1205IMAGE_FILE_MACHINE_I386 = 0x014c    #Intel x86
1206IMAGE_FILE_MACHINE_IA64 = 0x0200    #Intel Itanium Processor Family (IPF)
1207IMAGE_FILE_MACHINE_AMD64 = 0x8664   #x64 (AMD64 or EM64T)
1208
1209#===============================================================================
1210# BOOL WINAPI StackWalk64(
1211#  __in      DWORD MachineType,
1212#  __in      HANDLE hProcess,
1213#  __in      HANDLE hThread,
1214#  __inout   LPSTACKFRAME64 StackFrame,
1215#  __inout   PVOID ContextRecord,
1216#  __in_opt  PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
1217#  __in_opt  PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
1218#  __in_opt  PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
1219#  __in_opt  PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
1220# );
1221#===============================================================================
1222def StackWalk64(MachineType, hProcess, hThread, StackFrame,
1223                ContextRecord = None, ReadMemoryRoutine = None,
1224                FunctionTableAccessRoutine = None, GetModuleBaseRoutine = None,
1225                TranslateAddress = None):
1226
1227    _StackWalk64 = windll.dbghelp.StackWalk64
1228    _StackWalk64.argtypes = [DWORD, HANDLE, HANDLE, LPSTACKFRAME64, PVOID,
1229                             PREAD_PROCESS_MEMORY_ROUTINE64,
1230                             PFUNCTION_TABLE_ACCESS_ROUTINE64,
1231                             PGET_MODULE_BASE_ROUTINE64,
1232                             PTRANSLATE_ADDRESS_ROUTINE64]
1233    _StackWalk64.restype = bool
1234
1235    pReadMemoryRoutine = None
1236    if ReadMemoryRoutine:
1237        pReadMemoryRoutine = PREAD_PROCESS_MEMORY_ROUTINE64(ReadMemoryRoutine)
1238    else:
1239        pReadMemoryRoutine = ctypes.cast(None, PREAD_PROCESS_MEMORY_ROUTINE64)
1240
1241    pFunctionTableAccessRoutine = None
1242    if FunctionTableAccessRoutine:
1243        pFunctionTableAccessRoutine = PFUNCTION_TABLE_ACCESS_ROUTINE64(FunctionTableAccessRoutine)
1244    else:
1245        pFunctionTableAccessRoutine = ctypes.cast(None, PFUNCTION_TABLE_ACCESS_ROUTINE64)
1246
1247    pGetModuleBaseRoutine = None
1248    if GetModuleBaseRoutine:
1249        pGetModuleBaseRoutine = PGET_MODULE_BASE_ROUTINE64(GetModuleBaseRoutine)
1250    else:
1251        pGetModuleBaseRoutine = ctypes.cast(None, PGET_MODULE_BASE_ROUTINE64)
1252
1253    pTranslateAddress = None
1254    if TranslateAddress:
1255        pTranslateAddress =  PTRANSLATE_ADDRESS_ROUTINE64(TranslateAddress)
1256    else:
1257        pTranslateAddress = ctypes.cast(None, PTRANSLATE_ADDRESS_ROUTINE64)
1258
1259    pContextRecord = None
1260    if ContextRecord is None:
1261        ContextRecord = GetThreadContext(hThread, raw=True)
1262    pContextRecord = PCONTEXT(ContextRecord)
1263
1264    #this function *DOESN'T* set last error [GetLastError()] properly most of the time.
1265    ret = _StackWalk64(MachineType, hProcess, hThread, byref(StackFrame),
1266                       pContextRecord, pReadMemoryRoutine,
1267                       pFunctionTableAccessRoutine, pGetModuleBaseRoutine,
1268                       pTranslateAddress)
1269
1270    return ret
1271
1272#==============================================================================
1273# This calculates the list of exported symbols.
1274_all = set(vars().keys()).difference(_all)
1275__all__ = [_x for _x in _all if not _x.startswith('_')]
1276__all__.sort()
1277#==============================================================================
1278