#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2009-2014, Mario Vilas # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice,this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of the copyright holder nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """ Wrapper for dbghelp.dll in ctypes. """ __revision__ = "$Id$" from winappdbg.win32.defines import * from winappdbg.win32.version import * from winappdbg.win32.kernel32 import * # DbgHelp versions and features list: # http://msdn.microsoft.com/en-us/library/windows/desktop/ms679294(v=vs.85).aspx #------------------------------------------------------------------------------ # Tries to load the newest version of dbghelp.dll if available. def _load_latest_dbghelp_dll(): from os import getenv from os.path import join, exists program_files_location = getenv("ProgramFiles") if not program_files_location: program_files_location = "C:\\Program Files" program_files_x86_location = getenv("ProgramFiles(x86)") if arch == ARCH_AMD64: if wow64: pathname = join( program_files_x86_location or program_files_location, "Debugging Tools for Windows (x86)", "dbghelp.dll") else: pathname = join( program_files_location, "Debugging Tools for Windows (x64)", "dbghelp.dll") elif arch == ARCH_I386: pathname = join( program_files_location, "Debugging Tools for Windows (x86)", "dbghelp.dll") else: pathname = None if pathname and exists(pathname): try: _dbghelp = ctypes.windll.LoadLibrary(pathname) ctypes.windll.dbghelp = _dbghelp except Exception: pass _load_latest_dbghelp_dll() # Recover the old binding of the "os" symbol. # XXX FIXME not sure if I really need to do this! ##from version import os #------------------------------------------------------------------------------ #============================================================================== # This is used later on to calculate the list of exported symbols. _all = None _all = set(vars().keys()) #============================================================================== # SymGetHomeDirectory "type" values hdBase = 0 hdSym = 1 hdSrc = 2 UNDNAME_32_BIT_DECODE = 0x0800 UNDNAME_COMPLETE = 0x0000 UNDNAME_NAME_ONLY = 0x1000 UNDNAME_NO_ACCESS_SPECIFIERS = 0x0080 UNDNAME_NO_ALLOCATION_LANGUAGE = 0x0010 UNDNAME_NO_ALLOCATION_MODEL = 0x0008 UNDNAME_NO_ARGUMENTS = 0x2000 UNDNAME_NO_CV_THISTYPE = 0x0040 UNDNAME_NO_FUNCTION_RETURNS = 0x0004 UNDNAME_NO_LEADING_UNDERSCORES = 0x0001 UNDNAME_NO_MEMBER_TYPE = 0x0200 UNDNAME_NO_MS_KEYWORDS = 0x0002 UNDNAME_NO_MS_THISTYPE = 0x0020 UNDNAME_NO_RETURN_UDT_MODEL = 0x0400 UNDNAME_NO_SPECIAL_SYMS = 0x4000 UNDNAME_NO_THISTYPE = 0x0060 UNDNAME_NO_THROW_SIGNATURES = 0x0100 #--- IMAGEHLP_MODULE structure and related ------------------------------------ SYMOPT_ALLOW_ABSOLUTE_SYMBOLS = 0x00000800 SYMOPT_ALLOW_ZERO_ADDRESS = 0x01000000 SYMOPT_AUTO_PUBLICS = 0x00010000 SYMOPT_CASE_INSENSITIVE = 0x00000001 SYMOPT_DEBUG = 0x80000000 SYMOPT_DEFERRED_LOADS = 0x00000004 SYMOPT_DISABLE_SYMSRV_AUTODETECT = 0x02000000 SYMOPT_EXACT_SYMBOLS = 0x00000400 SYMOPT_FAIL_CRITICAL_ERRORS = 0x00000200 SYMOPT_FAVOR_COMPRESSED = 0x00800000 SYMOPT_FLAT_DIRECTORY = 0x00400000 SYMOPT_IGNORE_CVREC = 0x00000080 SYMOPT_IGNORE_IMAGEDIR = 0x00200000 SYMOPT_IGNORE_NT_SYMPATH = 0x00001000 SYMOPT_INCLUDE_32BIT_MODULES = 0x00002000 SYMOPT_LOAD_ANYTHING = 0x00000040 SYMOPT_LOAD_LINES = 0x00000010 SYMOPT_NO_CPP = 0x00000008 SYMOPT_NO_IMAGE_SEARCH = 0x00020000 SYMOPT_NO_PROMPTS = 0x00080000 SYMOPT_NO_PUBLICS = 0x00008000 SYMOPT_NO_UNQUALIFIED_LOADS = 0x00000100 SYMOPT_OVERWRITE = 0x00100000 SYMOPT_PUBLICS_ONLY = 0x00004000 SYMOPT_SECURE = 0x00040000 SYMOPT_UNDNAME = 0x00000002 ##SSRVOPT_DWORD ##SSRVOPT_DWORDPTR ##SSRVOPT_GUIDPTR ## ##SSRVOPT_CALLBACK ##SSRVOPT_DOWNSTREAM_STORE ##SSRVOPT_FLAT_DEFAULT_STORE ##SSRVOPT_FAVOR_COMPRESSED ##SSRVOPT_NOCOPY ##SSRVOPT_OVERWRITE ##SSRVOPT_PARAMTYPE ##SSRVOPT_PARENTWIN ##SSRVOPT_PROXY ##SSRVOPT_RESET ##SSRVOPT_SECURE ##SSRVOPT_SETCONTEXT ##SSRVOPT_TRACE ##SSRVOPT_UNATTENDED # typedef enum # { # SymNone = 0, # SymCoff, # SymCv, # SymPdb, # SymExport, # SymDeferred, # SymSym, # SymDia, # SymVirtual, # NumSymTypes # } SYM_TYPE; SymNone = 0 SymCoff = 1 SymCv = 2 SymPdb = 3 SymExport = 4 SymDeferred = 5 SymSym = 6 SymDia = 7 SymVirtual = 8 NumSymTypes = 9 # typedef struct _IMAGEHLP_MODULE64 { # DWORD SizeOfStruct; # DWORD64 BaseOfImage; # DWORD ImageSize; # DWORD TimeDateStamp; # DWORD CheckSum; # DWORD NumSyms; # SYM_TYPE SymType; # TCHAR ModuleName[32]; # TCHAR ImageName[256]; # TCHAR LoadedImageName[256]; # TCHAR LoadedPdbName[256]; # DWORD CVSig; # TCHAR CVData[MAX_PATH*3]; # DWORD PdbSig; # GUID PdbSig70; # DWORD PdbAge; # BOOL PdbUnmatched; # BOOL DbgUnmatched; # BOOL LineNumbers; # BOOL GlobalSymbols; # BOOL TypeInfo; # BOOL SourceIndexed; # BOOL Publics; # } IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64; class IMAGEHLP_MODULE (Structure): _fields_ = [ ("SizeOfStruct", DWORD), ("BaseOfImage", DWORD), ("ImageSize", DWORD), ("TimeDateStamp", DWORD), ("CheckSum", DWORD), ("NumSyms", DWORD), ("SymType", DWORD), # SYM_TYPE ("ModuleName", CHAR * 32), ("ImageName", CHAR * 256), ("LoadedImageName", CHAR * 256), ] PIMAGEHLP_MODULE = POINTER(IMAGEHLP_MODULE) class IMAGEHLP_MODULE64 (Structure): _fields_ = [ ("SizeOfStruct", DWORD), ("BaseOfImage", DWORD64), ("ImageSize", DWORD), ("TimeDateStamp", DWORD), ("CheckSum", DWORD), ("NumSyms", DWORD), ("SymType", DWORD), # SYM_TYPE ("ModuleName", CHAR * 32), ("ImageName", CHAR * 256), ("LoadedImageName", CHAR * 256), ("LoadedPdbName", CHAR * 256), ("CVSig", DWORD), ("CVData", CHAR * (MAX_PATH * 3)), ("PdbSig", DWORD), ("PdbSig70", GUID), ("PdbAge", DWORD), ("PdbUnmatched", BOOL), ("DbgUnmatched", BOOL), ("LineNumbers", BOOL), ("GlobalSymbols", BOOL), ("TypeInfo", BOOL), ("SourceIndexed", BOOL), ("Publics", BOOL), ] PIMAGEHLP_MODULE64 = POINTER(IMAGEHLP_MODULE64) class IMAGEHLP_MODULEW (Structure): _fields_ = [ ("SizeOfStruct", DWORD), ("BaseOfImage", DWORD), ("ImageSize", DWORD), ("TimeDateStamp", DWORD), ("CheckSum", DWORD), ("NumSyms", DWORD), ("SymType", DWORD), # SYM_TYPE ("ModuleName", WCHAR * 32), ("ImageName", WCHAR * 256), ("LoadedImageName", WCHAR * 256), ] PIMAGEHLP_MODULEW = POINTER(IMAGEHLP_MODULEW) class IMAGEHLP_MODULEW64 (Structure): _fields_ = [ ("SizeOfStruct", DWORD), ("BaseOfImage", DWORD64), ("ImageSize", DWORD), ("TimeDateStamp", DWORD), ("CheckSum", DWORD), ("NumSyms", DWORD), ("SymType", DWORD), # SYM_TYPE ("ModuleName", WCHAR * 32), ("ImageName", WCHAR * 256), ("LoadedImageName", WCHAR * 256), ("LoadedPdbName", WCHAR * 256), ("CVSig", DWORD), ("CVData", WCHAR * (MAX_PATH * 3)), ("PdbSig", DWORD), ("PdbSig70", GUID), ("PdbAge", DWORD), ("PdbUnmatched", BOOL), ("DbgUnmatched", BOOL), ("LineNumbers", BOOL), ("GlobalSymbols", BOOL), ("TypeInfo", BOOL), ("SourceIndexed", BOOL), ("Publics", BOOL), ] PIMAGEHLP_MODULEW64 = POINTER(IMAGEHLP_MODULEW64) #--- dbghelp.dll -------------------------------------------------------------- # XXX the ANSI versions of these functions don't end in "A" as expected! # BOOL WINAPI MakeSureDirectoryPathExists( # _In_ PCSTR DirPath # ); def MakeSureDirectoryPathExistsA(DirPath): _MakeSureDirectoryPathExists = windll.dbghelp.MakeSureDirectoryPathExists _MakeSureDirectoryPathExists.argtypes = [LPSTR] _MakeSureDirectoryPathExists.restype = bool _MakeSureDirectoryPathExists.errcheck = RaiseIfZero return _MakeSureDirectoryPathExists(DirPath) MakeSureDirectoryPathExistsW = MakeWideVersion(MakeSureDirectoryPathExistsA) MakeSureDirectoryPathExists = GuessStringType(MakeSureDirectoryPathExistsA, MakeSureDirectoryPathExistsW) # BOOL WINAPI SymInitialize( # __in HANDLE hProcess, # __in_opt PCTSTR UserSearchPath, # __in BOOL fInvadeProcess # ); def SymInitializeA(hProcess, UserSearchPath = None, fInvadeProcess = False): _SymInitialize = windll.dbghelp.SymInitialize _SymInitialize.argtypes = [HANDLE, LPSTR, BOOL] _SymInitialize.restype = bool _SymInitialize.errcheck = RaiseIfZero if not UserSearchPath: UserSearchPath = None _SymInitialize(hProcess, UserSearchPath, fInvadeProcess) SymInitializeW = MakeWideVersion(SymInitializeA) SymInitialize = GuessStringType(SymInitializeA, SymInitializeW) # BOOL WINAPI SymCleanup( # __in HANDLE hProcess # ); def SymCleanup(hProcess): _SymCleanup = windll.dbghelp.SymCleanup _SymCleanup.argtypes = [HANDLE] _SymCleanup.restype = bool _SymCleanup.errcheck = RaiseIfZero _SymCleanup(hProcess) # BOOL WINAPI SymRefreshModuleList( # __in HANDLE hProcess # ); def SymRefreshModuleList(hProcess): _SymRefreshModuleList = windll.dbghelp.SymRefreshModuleList _SymRefreshModuleList.argtypes = [HANDLE] _SymRefreshModuleList.restype = bool _SymRefreshModuleList.errcheck = RaiseIfZero _SymRefreshModuleList(hProcess) # BOOL WINAPI SymSetParentWindow( # __in HWND hwnd # ); def SymSetParentWindow(hwnd): _SymSetParentWindow = windll.dbghelp.SymSetParentWindow _SymSetParentWindow.argtypes = [HWND] _SymSetParentWindow.restype = bool _SymSetParentWindow.errcheck = RaiseIfZero _SymSetParentWindow(hwnd) # DWORD WINAPI SymSetOptions( # __in DWORD SymOptions # ); def SymSetOptions(SymOptions): _SymSetOptions = windll.dbghelp.SymSetOptions _SymSetOptions.argtypes = [DWORD] _SymSetOptions.restype = DWORD _SymSetOptions.errcheck = RaiseIfZero _SymSetOptions(SymOptions) # DWORD WINAPI SymGetOptions(void); def SymGetOptions(): _SymGetOptions = windll.dbghelp.SymGetOptions _SymGetOptions.argtypes = [] _SymGetOptions.restype = DWORD return _SymGetOptions() # DWORD WINAPI SymLoadModule( # __in HANDLE hProcess, # __in_opt HANDLE hFile, # __in_opt PCSTR ImageName, # __in_opt PCSTR ModuleName, # __in DWORD BaseOfDll, # __in DWORD SizeOfDll # ); def SymLoadModuleA(hProcess, hFile = None, ImageName = None, ModuleName = None, BaseOfDll = None, SizeOfDll = None): _SymLoadModule = windll.dbghelp.SymLoadModule _SymLoadModule.argtypes = [HANDLE, HANDLE, LPSTR, LPSTR, DWORD, DWORD] _SymLoadModule.restype = DWORD if not ImageName: ImageName = None if not ModuleName: ModuleName = None if not BaseOfDll: BaseOfDll = 0 if not SizeOfDll: SizeOfDll = 0 SetLastError(ERROR_SUCCESS) lpBaseAddress = _SymLoadModule(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll) if lpBaseAddress == NULL: dwErrorCode = GetLastError() if dwErrorCode != ERROR_SUCCESS: raise ctypes.WinError(dwErrorCode) return lpBaseAddress SymLoadModuleW = MakeWideVersion(SymLoadModuleA) SymLoadModule = GuessStringType(SymLoadModuleA, SymLoadModuleW) # DWORD64 WINAPI SymLoadModule64( # __in HANDLE hProcess, # __in_opt HANDLE hFile, # __in_opt PCSTR ImageName, # __in_opt PCSTR ModuleName, # __in DWORD64 BaseOfDll, # __in DWORD SizeOfDll # ); def SymLoadModule64A(hProcess, hFile = None, ImageName = None, ModuleName = None, BaseOfDll = None, SizeOfDll = None): _SymLoadModule64 = windll.dbghelp.SymLoadModule64 _SymLoadModule64.argtypes = [HANDLE, HANDLE, LPSTR, LPSTR, DWORD64, DWORD] _SymLoadModule64.restype = DWORD64 if not ImageName: ImageName = None if not ModuleName: ModuleName = None if not BaseOfDll: BaseOfDll = 0 if not SizeOfDll: SizeOfDll = 0 SetLastError(ERROR_SUCCESS) lpBaseAddress = _SymLoadModule64(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll) if lpBaseAddress == NULL: dwErrorCode = GetLastError() if dwErrorCode != ERROR_SUCCESS: raise ctypes.WinError(dwErrorCode) return lpBaseAddress SymLoadModule64W = MakeWideVersion(SymLoadModule64A) SymLoadModule64 = GuessStringType(SymLoadModule64A, SymLoadModule64W) # BOOL WINAPI SymUnloadModule( # __in HANDLE hProcess, # __in DWORD BaseOfDll # ); def SymUnloadModule(hProcess, BaseOfDll): _SymUnloadModule = windll.dbghelp.SymUnloadModule _SymUnloadModule.argtypes = [HANDLE, DWORD] _SymUnloadModule.restype = bool _SymUnloadModule.errcheck = RaiseIfZero _SymUnloadModule(hProcess, BaseOfDll) # BOOL WINAPI SymUnloadModule64( # __in HANDLE hProcess, # __in DWORD64 BaseOfDll # ); def SymUnloadModule64(hProcess, BaseOfDll): _SymUnloadModule64 = windll.dbghelp.SymUnloadModule64 _SymUnloadModule64.argtypes = [HANDLE, DWORD64] _SymUnloadModule64.restype = bool _SymUnloadModule64.errcheck = RaiseIfZero _SymUnloadModule64(hProcess, BaseOfDll) # BOOL WINAPI SymGetModuleInfo( # __in HANDLE hProcess, # __in DWORD dwAddr, # __out PIMAGEHLP_MODULE ModuleInfo # ); def SymGetModuleInfoA(hProcess, dwAddr): _SymGetModuleInfo = windll.dbghelp.SymGetModuleInfo _SymGetModuleInfo.argtypes = [HANDLE, DWORD, PIMAGEHLP_MODULE] _SymGetModuleInfo.restype = bool _SymGetModuleInfo.errcheck = RaiseIfZero ModuleInfo = IMAGEHLP_MODULE() ModuleInfo.SizeOfStruct = sizeof(ModuleInfo) _SymGetModuleInfo(hProcess, dwAddr, byref(ModuleInfo)) return ModuleInfo def SymGetModuleInfoW(hProcess, dwAddr): _SymGetModuleInfoW = windll.dbghelp.SymGetModuleInfoW _SymGetModuleInfoW.argtypes = [HANDLE, DWORD, PIMAGEHLP_MODULEW] _SymGetModuleInfoW.restype = bool _SymGetModuleInfoW.errcheck = RaiseIfZero ModuleInfo = IMAGEHLP_MODULEW() ModuleInfo.SizeOfStruct = sizeof(ModuleInfo) _SymGetModuleInfoW(hProcess, dwAddr, byref(ModuleInfo)) return ModuleInfo SymGetModuleInfo = GuessStringType(SymGetModuleInfoA, SymGetModuleInfoW) # BOOL WINAPI SymGetModuleInfo64( # __in HANDLE hProcess, # __in DWORD64 dwAddr, # __out PIMAGEHLP_MODULE64 ModuleInfo # ); def SymGetModuleInfo64A(hProcess, dwAddr): _SymGetModuleInfo64 = windll.dbghelp.SymGetModuleInfo64 _SymGetModuleInfo64.argtypes = [HANDLE, DWORD64, PIMAGEHLP_MODULE64] _SymGetModuleInfo64.restype = bool _SymGetModuleInfo64.errcheck = RaiseIfZero ModuleInfo = IMAGEHLP_MODULE64() ModuleInfo.SizeOfStruct = sizeof(ModuleInfo) _SymGetModuleInfo64(hProcess, dwAddr, byref(ModuleInfo)) return ModuleInfo def SymGetModuleInfo64W(hProcess, dwAddr): _SymGetModuleInfo64W = windll.dbghelp.SymGetModuleInfo64W _SymGetModuleInfo64W.argtypes = [HANDLE, DWORD64, PIMAGEHLP_MODULE64W] _SymGetModuleInfo64W.restype = bool _SymGetModuleInfo64W.errcheck = RaiseIfZero ModuleInfo = IMAGEHLP_MODULE64W() ModuleInfo.SizeOfStruct = sizeof(ModuleInfo) _SymGetModuleInfo64W(hProcess, dwAddr, byref(ModuleInfo)) return ModuleInfo SymGetModuleInfo64 = GuessStringType(SymGetModuleInfo64A, SymGetModuleInfo64W) # BOOL CALLBACK SymEnumerateModulesProc( # __in PCTSTR ModuleName, # __in DWORD BaseOfDll, # __in_opt PVOID UserContext # ); PSYM_ENUMMODULES_CALLBACK = WINFUNCTYPE(BOOL, LPSTR, DWORD, PVOID) PSYM_ENUMMODULES_CALLBACKW = WINFUNCTYPE(BOOL, LPWSTR, DWORD, PVOID) # BOOL CALLBACK SymEnumerateModulesProc64( # __in PCTSTR ModuleName, # __in DWORD64 BaseOfDll, # __in_opt PVOID UserContext # ); PSYM_ENUMMODULES_CALLBACK64 = WINFUNCTYPE(BOOL, LPSTR, DWORD64, PVOID) PSYM_ENUMMODULES_CALLBACKW64 = WINFUNCTYPE(BOOL, LPWSTR, DWORD64, PVOID) # BOOL WINAPI SymEnumerateModules( # __in HANDLE hProcess, # __in PSYM_ENUMMODULES_CALLBACK EnumModulesCallback, # __in_opt PVOID UserContext # ); def SymEnumerateModulesA(hProcess, EnumModulesCallback, UserContext = None): _SymEnumerateModules = windll.dbghelp.SymEnumerateModules _SymEnumerateModules.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACK, PVOID] _SymEnumerateModules.restype = bool _SymEnumerateModules.errcheck = RaiseIfZero EnumModulesCallback = PSYM_ENUMMODULES_CALLBACK(EnumModulesCallback) if UserContext: UserContext = ctypes.pointer(UserContext) else: UserContext = LPVOID(NULL) _SymEnumerateModules(hProcess, EnumModulesCallback, UserContext) def SymEnumerateModulesW(hProcess, EnumModulesCallback, UserContext = None): _SymEnumerateModulesW = windll.dbghelp.SymEnumerateModulesW _SymEnumerateModulesW.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACKW, PVOID] _SymEnumerateModulesW.restype = bool _SymEnumerateModulesW.errcheck = RaiseIfZero EnumModulesCallback = PSYM_ENUMMODULES_CALLBACKW(EnumModulesCallback) if UserContext: UserContext = ctypes.pointer(UserContext) else: UserContext = LPVOID(NULL) _SymEnumerateModulesW(hProcess, EnumModulesCallback, UserContext) SymEnumerateModules = GuessStringType(SymEnumerateModulesA, SymEnumerateModulesW) # BOOL WINAPI SymEnumerateModules64( # __in HANDLE hProcess, # __in PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback, # __in_opt PVOID UserContext # ); def SymEnumerateModules64A(hProcess, EnumModulesCallback, UserContext = None): _SymEnumerateModules64 = windll.dbghelp.SymEnumerateModules64 _SymEnumerateModules64.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACK64, PVOID] _SymEnumerateModules64.restype = bool _SymEnumerateModules64.errcheck = RaiseIfZero EnumModulesCallback = PSYM_ENUMMODULES_CALLBACK64(EnumModulesCallback) if UserContext: UserContext = ctypes.pointer(UserContext) else: UserContext = LPVOID(NULL) _SymEnumerateModules64(hProcess, EnumModulesCallback, UserContext) def SymEnumerateModules64W(hProcess, EnumModulesCallback, UserContext = None): _SymEnumerateModules64W = windll.dbghelp.SymEnumerateModules64W _SymEnumerateModules64W.argtypes = [HANDLE, PSYM_ENUMMODULES_CALLBACK64W, PVOID] _SymEnumerateModules64W.restype = bool _SymEnumerateModules64W.errcheck = RaiseIfZero EnumModulesCallback = PSYM_ENUMMODULES_CALLBACK64W(EnumModulesCallback) if UserContext: UserContext = ctypes.pointer(UserContext) else: UserContext = LPVOID(NULL) _SymEnumerateModules64W(hProcess, EnumModulesCallback, UserContext) SymEnumerateModules64 = GuessStringType(SymEnumerateModules64A, SymEnumerateModules64W) # BOOL CALLBACK SymEnumerateSymbolsProc( # __in PCTSTR SymbolName, # __in DWORD SymbolAddress, # __in ULONG SymbolSize, # __in_opt PVOID UserContext # ); PSYM_ENUMSYMBOLS_CALLBACK = WINFUNCTYPE(BOOL, LPSTR, DWORD, ULONG, PVOID) PSYM_ENUMSYMBOLS_CALLBACKW = WINFUNCTYPE(BOOL, LPWSTR, DWORD, ULONG, PVOID) # BOOL CALLBACK SymEnumerateSymbolsProc64( # __in PCTSTR SymbolName, # __in DWORD64 SymbolAddress, # __in ULONG SymbolSize, # __in_opt PVOID UserContext # ); PSYM_ENUMSYMBOLS_CALLBACK64 = WINFUNCTYPE(BOOL, LPSTR, DWORD64, ULONG, PVOID) PSYM_ENUMSYMBOLS_CALLBACKW64 = WINFUNCTYPE(BOOL, LPWSTR, DWORD64, ULONG, PVOID) # BOOL WINAPI SymEnumerateSymbols( # __in HANDLE hProcess, # __in ULONG BaseOfDll, # __in PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback, # __in_opt PVOID UserContext # ); def SymEnumerateSymbolsA(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None): _SymEnumerateSymbols = windll.dbghelp.SymEnumerateSymbols _SymEnumerateSymbols.argtypes = [HANDLE, ULONG, PSYM_ENUMSYMBOLS_CALLBACK, PVOID] _SymEnumerateSymbols.restype = bool _SymEnumerateSymbols.errcheck = RaiseIfZero EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACK(EnumSymbolsCallback) if UserContext: UserContext = ctypes.pointer(UserContext) else: UserContext = LPVOID(NULL) _SymEnumerateSymbols(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext) def SymEnumerateSymbolsW(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None): _SymEnumerateSymbolsW = windll.dbghelp.SymEnumerateSymbolsW _SymEnumerateSymbolsW.argtypes = [HANDLE, ULONG, PSYM_ENUMSYMBOLS_CALLBACKW, PVOID] _SymEnumerateSymbolsW.restype = bool _SymEnumerateSymbolsW.errcheck = RaiseIfZero EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACKW(EnumSymbolsCallback) if UserContext: UserContext = ctypes.pointer(UserContext) else: UserContext = LPVOID(NULL) _SymEnumerateSymbolsW(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext) SymEnumerateSymbols = GuessStringType(SymEnumerateSymbolsA, SymEnumerateSymbolsW) # BOOL WINAPI SymEnumerateSymbols64( # __in HANDLE hProcess, # __in ULONG64 BaseOfDll, # __in PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback, # __in_opt PVOID UserContext # ); def SymEnumerateSymbols64A(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None): _SymEnumerateSymbols64 = windll.dbghelp.SymEnumerateSymbols64 _SymEnumerateSymbols64.argtypes = [HANDLE, ULONG64, PSYM_ENUMSYMBOLS_CALLBACK64, PVOID] _SymEnumerateSymbols64.restype = bool _SymEnumerateSymbols64.errcheck = RaiseIfZero EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACK64(EnumSymbolsCallback) if UserContext: UserContext = ctypes.pointer(UserContext) else: UserContext = LPVOID(NULL) _SymEnumerateSymbols64(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext) def SymEnumerateSymbols64W(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext = None): _SymEnumerateSymbols64W = windll.dbghelp.SymEnumerateSymbols64W _SymEnumerateSymbols64W.argtypes = [HANDLE, ULONG64, PSYM_ENUMSYMBOLS_CALLBACK64W, PVOID] _SymEnumerateSymbols64W.restype = bool _SymEnumerateSymbols64W.errcheck = RaiseIfZero EnumSymbolsCallback = PSYM_ENUMSYMBOLS_CALLBACK64W(EnumSymbolsCallback) if UserContext: UserContext = ctypes.pointer(UserContext) else: UserContext = LPVOID(NULL) _SymEnumerateSymbols64W(hProcess, BaseOfDll, EnumSymbolsCallback, UserContext) SymEnumerateSymbols64 = GuessStringType(SymEnumerateSymbols64A, SymEnumerateSymbols64W) # DWORD WINAPI UnDecorateSymbolName( # __in PCTSTR DecoratedName, # __out PTSTR UnDecoratedName, # __in DWORD UndecoratedLength, # __in DWORD Flags # ); def UnDecorateSymbolNameA(DecoratedName, Flags = UNDNAME_COMPLETE): _UnDecorateSymbolNameA = windll.dbghelp.UnDecorateSymbolName _UnDecorateSymbolNameA.argtypes = [LPSTR, LPSTR, DWORD, DWORD] _UnDecorateSymbolNameA.restype = DWORD _UnDecorateSymbolNameA.errcheck = RaiseIfZero UndecoratedLength = _UnDecorateSymbolNameA(DecoratedName, None, 0, Flags) UnDecoratedName = ctypes.create_string_buffer('', UndecoratedLength + 1) _UnDecorateSymbolNameA(DecoratedName, UnDecoratedName, UndecoratedLength, Flags) return UnDecoratedName.value def UnDecorateSymbolNameW(DecoratedName, Flags = UNDNAME_COMPLETE): _UnDecorateSymbolNameW = windll.dbghelp.UnDecorateSymbolNameW _UnDecorateSymbolNameW.argtypes = [LPWSTR, LPWSTR, DWORD, DWORD] _UnDecorateSymbolNameW.restype = DWORD _UnDecorateSymbolNameW.errcheck = RaiseIfZero UndecoratedLength = _UnDecorateSymbolNameW(DecoratedName, None, 0, Flags) UnDecoratedName = ctypes.create_unicode_buffer(u'', UndecoratedLength + 1) _UnDecorateSymbolNameW(DecoratedName, UnDecoratedName, UndecoratedLength, Flags) return UnDecoratedName.value UnDecorateSymbolName = GuessStringType(UnDecorateSymbolNameA, UnDecorateSymbolNameW) # BOOL WINAPI SymGetSearchPath( # __in HANDLE hProcess, # __out PTSTR SearchPath, # __in DWORD SearchPathLength # ); def SymGetSearchPathA(hProcess): _SymGetSearchPath = windll.dbghelp.SymGetSearchPath _SymGetSearchPath.argtypes = [HANDLE, LPSTR, DWORD] _SymGetSearchPath.restype = bool _SymGetSearchPath.errcheck = RaiseIfZero SearchPathLength = MAX_PATH SearchPath = ctypes.create_string_buffer("", SearchPathLength) _SymGetSearchPath(hProcess, SearchPath, SearchPathLength) return SearchPath.value def SymGetSearchPathW(hProcess): _SymGetSearchPathW = windll.dbghelp.SymGetSearchPathW _SymGetSearchPathW.argtypes = [HANDLE, LPWSTR, DWORD] _SymGetSearchPathW.restype = bool _SymGetSearchPathW.errcheck = RaiseIfZero SearchPathLength = MAX_PATH SearchPath = ctypes.create_unicode_buffer(u"", SearchPathLength) _SymGetSearchPathW(hProcess, SearchPath, SearchPathLength) return SearchPath.value SymGetSearchPath = GuessStringType(SymGetSearchPathA, SymGetSearchPathW) # BOOL WINAPI SymSetSearchPath( # __in HANDLE hProcess, # __in_opt PCTSTR SearchPath # ); def SymSetSearchPathA(hProcess, SearchPath = None): _SymSetSearchPath = windll.dbghelp.SymSetSearchPath _SymSetSearchPath.argtypes = [HANDLE, LPSTR] _SymSetSearchPath.restype = bool _SymSetSearchPath.errcheck = RaiseIfZero if not SearchPath: SearchPath = None _SymSetSearchPath(hProcess, SearchPath) def SymSetSearchPathW(hProcess, SearchPath = None): _SymSetSearchPathW = windll.dbghelp.SymSetSearchPathW _SymSetSearchPathW.argtypes = [HANDLE, LPWSTR] _SymSetSearchPathW.restype = bool _SymSetSearchPathW.errcheck = RaiseIfZero if not SearchPath: SearchPath = None _SymSetSearchPathW(hProcess, SearchPath) SymSetSearchPath = GuessStringType(SymSetSearchPathA, SymSetSearchPathW) # PTCHAR WINAPI SymGetHomeDirectory( # __in DWORD type, # __out PTSTR dir, # __in size_t size # ); def SymGetHomeDirectoryA(type): _SymGetHomeDirectoryA = windll.dbghelp.SymGetHomeDirectoryA _SymGetHomeDirectoryA.argtypes = [DWORD, LPSTR, SIZE_T] _SymGetHomeDirectoryA.restype = LPSTR _SymGetHomeDirectoryA.errcheck = RaiseIfZero size = MAX_PATH dir = ctypes.create_string_buffer("", size) _SymGetHomeDirectoryA(type, dir, size) return dir.value def SymGetHomeDirectoryW(type): _SymGetHomeDirectoryW = windll.dbghelp.SymGetHomeDirectoryW _SymGetHomeDirectoryW.argtypes = [DWORD, LPWSTR, SIZE_T] _SymGetHomeDirectoryW.restype = LPWSTR _SymGetHomeDirectoryW.errcheck = RaiseIfZero size = MAX_PATH dir = ctypes.create_unicode_buffer(u"", size) _SymGetHomeDirectoryW(type, dir, size) return dir.value SymGetHomeDirectory = GuessStringType(SymGetHomeDirectoryA, SymGetHomeDirectoryW) # PTCHAR WINAPI SymSetHomeDirectory( # __in HANDLE hProcess, # __in_opt PCTSTR dir # ); def SymSetHomeDirectoryA(hProcess, dir = None): _SymSetHomeDirectoryA = windll.dbghelp.SymSetHomeDirectoryA _SymSetHomeDirectoryA.argtypes = [HANDLE, LPSTR] _SymSetHomeDirectoryA.restype = LPSTR _SymSetHomeDirectoryA.errcheck = RaiseIfZero if not dir: dir = None _SymSetHomeDirectoryA(hProcess, dir) return dir def SymSetHomeDirectoryW(hProcess, dir = None): _SymSetHomeDirectoryW = windll.dbghelp.SymSetHomeDirectoryW _SymSetHomeDirectoryW.argtypes = [HANDLE, LPWSTR] _SymSetHomeDirectoryW.restype = LPWSTR _SymSetHomeDirectoryW.errcheck = RaiseIfZero if not dir: dir = None _SymSetHomeDirectoryW(hProcess, dir) return dir SymSetHomeDirectory = GuessStringType(SymSetHomeDirectoryA, SymSetHomeDirectoryW) #--- DbgHelp 5+ support, patch by Neitsa -------------------------------------- # XXX TODO # + use the GuessStringType decorator for ANSI/Wide versions # + replace hardcoded struct sizes with sizeof() calls # + StackWalk64 should raise on error, but something has to be done about it # not setting the last error code (maybe we should call SetLastError # ourselves with a default error code?) # /Mario #maximum length of a symbol name MAX_SYM_NAME = 2000 class SYM_INFO(Structure): _fields_ = [ ("SizeOfStruct", ULONG), ("TypeIndex", ULONG), ("Reserved", ULONG64 * 2), ("Index", ULONG), ("Size", ULONG), ("ModBase", ULONG64), ("Flags", ULONG), ("Value", ULONG64), ("Address", ULONG64), ("Register", ULONG), ("Scope", ULONG), ("Tag", ULONG), ("NameLen", ULONG), ("MaxNameLen", ULONG), ("Name", CHAR * (MAX_SYM_NAME + 1)), ] PSYM_INFO = POINTER(SYM_INFO) class SYM_INFOW(Structure): _fields_ = [ ("SizeOfStruct", ULONG), ("TypeIndex", ULONG), ("Reserved", ULONG64 * 2), ("Index", ULONG), ("Size", ULONG), ("ModBase", ULONG64), ("Flags", ULONG), ("Value", ULONG64), ("Address", ULONG64), ("Register", ULONG), ("Scope", ULONG), ("Tag", ULONG), ("NameLen", ULONG), ("MaxNameLen", ULONG), ("Name", WCHAR * (MAX_SYM_NAME + 1)), ] PSYM_INFOW = POINTER(SYM_INFOW) #=============================================================================== # BOOL WINAPI SymFromName( # __in HANDLE hProcess, # __in PCTSTR Name, # __inout PSYMBOL_INFO Symbol # ); #=============================================================================== def SymFromName(hProcess, Name): _SymFromNameA = windll.dbghelp.SymFromName _SymFromNameA.argtypes = [HANDLE, LPSTR, PSYM_INFO] _SymFromNameA.restype = bool _SymFromNameA.errcheck = RaiseIfZero SymInfo = SYM_INFO() SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFO) in C. SymInfo.MaxNameLen = MAX_SYM_NAME _SymFromNameA(hProcess, Name, byref(SymInfo)) return SymInfo def SymFromNameW(hProcess, Name): _SymFromNameW = windll.dbghelp.SymFromNameW _SymFromNameW.argtypes = [HANDLE, LPWSTR, PSYM_INFOW] _SymFromNameW.restype = bool _SymFromNameW.errcheck = RaiseIfZero SymInfo = SYM_INFOW() SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFOW) in C. SymInfo.MaxNameLen = MAX_SYM_NAME _SymFromNameW(hProcess, Name, byref(SymInfo)) return SymInfo #=============================================================================== # BOOL WINAPI SymFromAddr( # __in HANDLE hProcess, # __in DWORD64 Address, # __out_opt PDWORD64 Displacement, # __inout PSYMBOL_INFO Symbol # ); #=============================================================================== def SymFromAddr(hProcess, Address): _SymFromAddr = windll.dbghelp.SymFromAddr _SymFromAddr.argtypes = [HANDLE, DWORD64, PDWORD64, PSYM_INFO] _SymFromAddr.restype = bool _SymFromAddr.errcheck = RaiseIfZero SymInfo = SYM_INFO() SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFO) in C. SymInfo.MaxNameLen = MAX_SYM_NAME Displacement = DWORD64(0) _SymFromAddr(hProcess, Address, byref(Displacement), byref(SymInfo)) return (Displacement.value, SymInfo) def SymFromAddrW(hProcess, Address): _SymFromAddr = windll.dbghelp.SymFromAddrW _SymFromAddr.argtypes = [HANDLE, DWORD64, PDWORD64, PSYM_INFOW] _SymFromAddr.restype = bool _SymFromAddr.errcheck = RaiseIfZero SymInfo = SYM_INFOW() SymInfo.SizeOfStruct = 88 # *don't modify*: sizeof(SYMBOL_INFOW) in C. SymInfo.MaxNameLen = MAX_SYM_NAME Displacement = DWORD64(0) _SymFromAddr(hProcess, Address, byref(Displacement), byref(SymInfo)) return (Displacement.value, SymInfo) #=============================================================================== # typedef struct _IMAGEHLP_SYMBOL64 { # DWORD SizeOfStruct; # DWORD64 Address; # DWORD Size; # DWORD Flags; # DWORD MaxNameLength; # CHAR Name[1]; # } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; #=============================================================================== class IMAGEHLP_SYMBOL64 (Structure): _fields_ = [ ("SizeOfStruct", DWORD), ("Address", DWORD64), ("Size", DWORD), ("Flags", DWORD), ("MaxNameLength", DWORD), ("Name", CHAR * (MAX_SYM_NAME + 1)), ] PIMAGEHLP_SYMBOL64 = POINTER(IMAGEHLP_SYMBOL64) #=============================================================================== # typedef struct _IMAGEHLP_SYMBOLW64 { # DWORD SizeOfStruct; # DWORD64 Address; # DWORD Size; # DWORD Flags; # DWORD MaxNameLength; # WCHAR Name[1]; # } IMAGEHLP_SYMBOLW64, *PIMAGEHLP_SYMBOLW64; #=============================================================================== class IMAGEHLP_SYMBOLW64 (Structure): _fields_ = [ ("SizeOfStruct", DWORD), ("Address", DWORD64), ("Size", DWORD), ("Flags", DWORD), ("MaxNameLength", DWORD), ("Name", WCHAR * (MAX_SYM_NAME + 1)), ] PIMAGEHLP_SYMBOLW64 = POINTER(IMAGEHLP_SYMBOLW64) #=============================================================================== # BOOL WINAPI SymGetSymFromAddr64( # __in HANDLE hProcess, # __in DWORD64 Address, # __out_opt PDWORD64 Displacement, # __inout PIMAGEHLP_SYMBOL64 Symbol # ); #=============================================================================== def SymGetSymFromAddr64(hProcess, Address): _SymGetSymFromAddr64 = windll.dbghelp.SymGetSymFromAddr64 _SymGetSymFromAddr64.argtypes = [HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64] _SymGetSymFromAddr64.restype = bool _SymGetSymFromAddr64.errcheck = RaiseIfZero imagehlp_symbol64 = IMAGEHLP_SYMBOL64() imagehlp_symbol64.SizeOfStruct = 32 # *don't modify*: sizeof(IMAGEHLP_SYMBOL64) in C. imagehlp_symbol64.MaxNameLen = MAX_SYM_NAME Displacement = DWORD64(0) _SymGetSymFromAddr64(hProcess, Address, byref(Displacement), byref(imagehlp_symbol64)) return (Displacement.value, imagehlp_symbol64) #TODO: check for the 'W' version of SymGetSymFromAddr64() #=============================================================================== # typedef struct API_VERSION { # USHORT MajorVersion; # USHORT MinorVersion; # USHORT Revision; # USHORT Reserved; # } API_VERSION, *LPAPI_VERSION; #=============================================================================== class API_VERSION (Structure): _fields_ = [ ("MajorVersion", USHORT), ("MinorVersion", USHORT), ("Revision", USHORT), ("Reserved", USHORT), ] PAPI_VERSION = POINTER(API_VERSION) LPAPI_VERSION = PAPI_VERSION #=============================================================================== # LPAPI_VERSION WINAPI ImagehlpApiVersion(void); #=============================================================================== def ImagehlpApiVersion(): _ImagehlpApiVersion = windll.dbghelp.ImagehlpApiVersion _ImagehlpApiVersion.restype = LPAPI_VERSION api_version = _ImagehlpApiVersion() return api_version.contents #=============================================================================== # LPAPI_VERSION WINAPI ImagehlpApiVersionEx( # __in LPAPI_VERSION AppVersion # ); #=============================================================================== def ImagehlpApiVersionEx(MajorVersion, MinorVersion, Revision): _ImagehlpApiVersionEx = windll.dbghelp.ImagehlpApiVersionEx _ImagehlpApiVersionEx.argtypes = [LPAPI_VERSION] _ImagehlpApiVersionEx.restype = LPAPI_VERSION api_version = API_VERSION(MajorVersion, MinorVersion, Revision, 0) ret_api_version = _ImagehlpApiVersionEx(byref(api_version)) return ret_api_version.contents #=============================================================================== # typedef enum { # AddrMode1616, # AddrMode1632, # AddrModeReal, # AddrModeFlat # } ADDRESS_MODE; #=============================================================================== AddrMode1616 = 0 AddrMode1632 = 1 AddrModeReal = 2 AddrModeFlat = 3 ADDRESS_MODE = DWORD #needed for the size of an ADDRESS_MODE (see ADDRESS64) #=============================================================================== # typedef struct _tagADDRESS64 { # DWORD64 Offset; # WORD Segment; # ADDRESS_MODE Mode; # } ADDRESS64, *LPADDRESS64; #=============================================================================== class ADDRESS64 (Structure): _fields_ = [ ("Offset", DWORD64), ("Segment", WORD), ("Mode", ADDRESS_MODE), #it's a member of the ADDRESS_MODE enum. ] LPADDRESS64 = POINTER(ADDRESS64) #=============================================================================== # typedef struct _KDHELP64 { # DWORD64 Thread; # DWORD ThCallbackStack; # DWORD ThCallbackBStore; # DWORD NextCallback; # DWORD FramePointer; # DWORD64 KiCallUserMode; # DWORD64 KeUserCallbackDispatcher; # DWORD64 SystemRangeStart; # DWORD64 KiUserExceptionDispatcher; # DWORD64 StackBase; # DWORD64 StackLimit; # DWORD64 Reserved[5]; # } KDHELP64, *PKDHELP64; #=============================================================================== class KDHELP64 (Structure): _fields_ = [ ("Thread", DWORD64), ("ThCallbackStack", DWORD), ("ThCallbackBStore", DWORD), ("NextCallback", DWORD), ("FramePointer", DWORD), ("KiCallUserMode", DWORD64), ("KeUserCallbackDispatcher", DWORD64), ("SystemRangeStart", DWORD64), ("KiUserExceptionDispatcher", DWORD64), ("StackBase", DWORD64), ("StackLimit", DWORD64), ("Reserved", DWORD64 * 5), ] PKDHELP64 = POINTER(KDHELP64) #=============================================================================== # typedef struct _tagSTACKFRAME64 { # ADDRESS64 AddrPC; # ADDRESS64 AddrReturn; # ADDRESS64 AddrFrame; # ADDRESS64 AddrStack; # ADDRESS64 AddrBStore; # PVOID FuncTableEntry; # DWORD64 Params[4]; # BOOL Far; # BOOL Virtual; # DWORD64 Reserved[3]; # KDHELP64 KdHelp; # } STACKFRAME64, *LPSTACKFRAME64; #=============================================================================== class STACKFRAME64(Structure): _fields_ = [ ("AddrPC", ADDRESS64), ("AddrReturn", ADDRESS64), ("AddrFrame", ADDRESS64), ("AddrStack", ADDRESS64), ("AddrBStore", ADDRESS64), ("FuncTableEntry", PVOID), ("Params", DWORD64 * 4), ("Far", BOOL), ("Virtual", BOOL), ("Reserved", DWORD64 * 3), ("KdHelp", KDHELP64), ] LPSTACKFRAME64 = POINTER(STACKFRAME64) #=============================================================================== # BOOL CALLBACK ReadProcessMemoryProc64( # __in HANDLE hProcess, # __in DWORD64 lpBaseAddress, # __out PVOID lpBuffer, # __in DWORD nSize, # __out LPDWORD lpNumberOfBytesRead # ); #=============================================================================== PREAD_PROCESS_MEMORY_ROUTINE64 = WINFUNCTYPE(BOOL, HANDLE, DWORD64, PVOID, DWORD, LPDWORD) #=============================================================================== # PVOID CALLBACK FunctionTableAccessProc64( # __in HANDLE hProcess, # __in DWORD64 AddrBase # ); #=============================================================================== PFUNCTION_TABLE_ACCESS_ROUTINE64 = WINFUNCTYPE(PVOID, HANDLE, DWORD64) #=============================================================================== # DWORD64 CALLBACK GetModuleBaseProc64( # __in HANDLE hProcess, # __in DWORD64 Address # ); #=============================================================================== PGET_MODULE_BASE_ROUTINE64 = WINFUNCTYPE(DWORD64, HANDLE, DWORD64) #=============================================================================== # DWORD64 CALLBACK GetModuleBaseProc64( # __in HANDLE hProcess, # __in DWORD64 Address # ); #=============================================================================== PTRANSLATE_ADDRESS_ROUTINE64 = WINFUNCTYPE(DWORD64, HANDLE, DWORD64) # Valid machine types for StackWalk64 function IMAGE_FILE_MACHINE_I386 = 0x014c #Intel x86 IMAGE_FILE_MACHINE_IA64 = 0x0200 #Intel Itanium Processor Family (IPF) IMAGE_FILE_MACHINE_AMD64 = 0x8664 #x64 (AMD64 or EM64T) #=============================================================================== # BOOL WINAPI StackWalk64( # __in DWORD MachineType, # __in HANDLE hProcess, # __in HANDLE hThread, # __inout LPSTACKFRAME64 StackFrame, # __inout PVOID ContextRecord, # __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, # __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, # __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, # __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress # ); #=============================================================================== def StackWalk64(MachineType, hProcess, hThread, StackFrame, ContextRecord = None, ReadMemoryRoutine = None, FunctionTableAccessRoutine = None, GetModuleBaseRoutine = None, TranslateAddress = None): _StackWalk64 = windll.dbghelp.StackWalk64 _StackWalk64.argtypes = [DWORD, HANDLE, HANDLE, LPSTACKFRAME64, PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64] _StackWalk64.restype = bool pReadMemoryRoutine = None if ReadMemoryRoutine: pReadMemoryRoutine = PREAD_PROCESS_MEMORY_ROUTINE64(ReadMemoryRoutine) else: pReadMemoryRoutine = ctypes.cast(None, PREAD_PROCESS_MEMORY_ROUTINE64) pFunctionTableAccessRoutine = None if FunctionTableAccessRoutine: pFunctionTableAccessRoutine = PFUNCTION_TABLE_ACCESS_ROUTINE64(FunctionTableAccessRoutine) else: pFunctionTableAccessRoutine = ctypes.cast(None, PFUNCTION_TABLE_ACCESS_ROUTINE64) pGetModuleBaseRoutine = None if GetModuleBaseRoutine: pGetModuleBaseRoutine = PGET_MODULE_BASE_ROUTINE64(GetModuleBaseRoutine) else: pGetModuleBaseRoutine = ctypes.cast(None, PGET_MODULE_BASE_ROUTINE64) pTranslateAddress = None if TranslateAddress: pTranslateAddress = PTRANSLATE_ADDRESS_ROUTINE64(TranslateAddress) else: pTranslateAddress = ctypes.cast(None, PTRANSLATE_ADDRESS_ROUTINE64) pContextRecord = None if ContextRecord is None: ContextRecord = GetThreadContext(hThread, raw=True) pContextRecord = PCONTEXT(ContextRecord) #this function *DOESN'T* set last error [GetLastError()] properly most of the time. ret = _StackWalk64(MachineType, hProcess, hThread, byref(StackFrame), pContextRecord, pReadMemoryRoutine, pFunctionTableAccessRoutine, pGetModuleBaseRoutine, pTranslateAddress) return ret #============================================================================== # This calculates the list of exported symbols. _all = set(vars().keys()).difference(_all) __all__ = [_x for _x in _all if not _x.startswith('_')] __all__.sort() #==============================================================================