Merge branch 'master' of https://github.com/wxWidgets/wxWidgets
This commit is contained in:
@@ -133,6 +133,8 @@ wxMSW:
|
|||||||
- Make default wxSizer border DPI-aware.
|
- Make default wxSizer border DPI-aware.
|
||||||
- Improve wxMimeTypesManager open command detection (Eric Jensen).
|
- Improve wxMimeTypesManager open command detection (Eric Jensen).
|
||||||
- Make wxFILTER_INCLUDE_LIST in wxTextValidator actually usable.
|
- Make wxFILTER_INCLUDE_LIST in wxTextValidator actually usable.
|
||||||
|
- Fix handling crashes in wxEVT_PAINT event handlers.
|
||||||
|
- Fix wxStackWalker to work with Unicode identifiers (Suzumizaki-kimitaka).
|
||||||
- Fix appearance of toggled wxToggleButtons with bitmap (tm).
|
- Fix appearance of toggled wxToggleButtons with bitmap (tm).
|
||||||
- Fix setting menu item bitmaps after appending them (Artur Wieczorek).
|
- Fix setting menu item bitmaps after appending them (Artur Wieczorek).
|
||||||
- Fix setting label of submenu items (Artur Wieczorek).
|
- Fix setting label of submenu items (Artur Wieczorek).
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Name: wx/msw/debughlp.h
|
// Name: wx/msw/debughlp.h
|
||||||
// Purpose: wraps dbghelp.h standard file
|
// Purpose: wraps dbghelp.h standard file
|
||||||
// Author: Vadim Zeitlin
|
// Author: Vadim Zeitlin, Suzumizaki-kimitaka
|
||||||
// Modified by:
|
|
||||||
// Created: 2005-01-08 (extracted from msw/crashrpt.cpp)
|
// Created: 2005-01-08 (extracted from msw/crashrpt.cpp)
|
||||||
// Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
|
// Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
|
||||||
// Licence: wxWindows licence
|
// Licence: wxWindows licence
|
||||||
@@ -19,12 +18,19 @@
|
|||||||
#endif // __WXWINCE__
|
#endif // __WXWINCE__
|
||||||
#include "wx/msw/private.h"
|
#include "wx/msw/private.h"
|
||||||
|
|
||||||
// wxUSE_DBGHELP can be predefined as 0 to avoid the use of dbghelp.dll if this
|
// wxUSE_DBGHELP can be predefined on the compiler command line to force using
|
||||||
// is undesirable for some reason.
|
// dbghelp.dll even if it's not detected or, on the contrary, avoid using even
|
||||||
|
// if it's available.
|
||||||
#ifndef wxUSE_DBGHELP
|
#ifndef wxUSE_DBGHELP
|
||||||
// The only compiler which is known to have the necessary headers is MSVC.
|
// The only compiler which is known to have the necessary headers is MSVC.
|
||||||
#ifdef __VISUALC__
|
#ifdef __VISUALC__
|
||||||
#define wxUSE_DBGHELP 1
|
// MSVC7.1 shipped with API v9 and we don't support anything earlier
|
||||||
|
// anyhow.
|
||||||
|
#if API_VERSION_NUMBER >= 9
|
||||||
|
#define wxUSE_DBGHELP 1
|
||||||
|
#else
|
||||||
|
#define wxUSE_DBGHELP 0
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define wxUSE_DBGHELP 0
|
#define wxUSE_DBGHELP 0
|
||||||
#endif
|
#endif
|
||||||
@@ -32,6 +38,117 @@
|
|||||||
|
|
||||||
#if wxUSE_DBGHELP
|
#if wxUSE_DBGHELP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
The table below shows which functions are exported by dbghelp.dll.
|
||||||
|
|
||||||
|
On 64 bit Windows, there seems to be no difference between 32bit dll and 64bit
|
||||||
|
one. Vista-64 and Win8-64 look the same, but "Ex" and "ExW" versions exist only
|
||||||
|
in Windows 8.
|
||||||
|
|
||||||
|
Note that SymGetLineFromAddrW and EnumerateLoadedModulesW DON'T exist at all.
|
||||||
|
|
||||||
|
function | Windows | XP-32 Vista-64 Win8-64
|
||||||
|
SymEnumSymbolsW n/a v v
|
||||||
|
SymFromAddrW n/a v v
|
||||||
|
SymInitializeW n/a v v
|
||||||
|
|
||||||
|
SymEnumSymbols v v v
|
||||||
|
SymFromAddr v v v
|
||||||
|
SymInitialize v v v
|
||||||
|
|
||||||
|
SymGetLineFromAddrW64 n/a v v
|
||||||
|
SymGetLineFromAddr64 v v v
|
||||||
|
SymGetLineFromAddrW n/a n/a n/a
|
||||||
|
SymGetLineFromAddr v v v
|
||||||
|
|
||||||
|
EnumerateLoadedModulesW64 n/a v v
|
||||||
|
EnumerateLoadedModules64 v v v
|
||||||
|
EnumerateLoadedModulesW n/a n/a n/a
|
||||||
|
EnumerateLoadedModules v v v
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// It's not really clear whether API v10 is used by anything as VC8 still used
|
||||||
|
// v9, just as MSVC7.1, while VC9 already used v11, but provide support for it
|
||||||
|
// just in case.
|
||||||
|
#if API_VERSION_NUMBER < 10/*{{{*/
|
||||||
|
|
||||||
|
typedef BOOL
|
||||||
|
(CALLBACK *PENUMLOADED_MODULES_CALLBACKW64)(PWSTR ModuleName,
|
||||||
|
DWORD64 ModuleBase,
|
||||||
|
ULONG ModuleSize,
|
||||||
|
PVOID UserContext);
|
||||||
|
|
||||||
|
typedef struct _IMAGEHLP_LINEW64
|
||||||
|
{
|
||||||
|
DWORD SizeOfStruct;
|
||||||
|
PVOID Key;
|
||||||
|
DWORD LineNumber;
|
||||||
|
PWSTR FileName;
|
||||||
|
DWORD64 Address;
|
||||||
|
} IMAGEHLP_LINEW64, *PIMAGEHLP_LINEW64;
|
||||||
|
|
||||||
|
typedef struct _SYMBOL_INFOW
|
||||||
|
{
|
||||||
|
ULONG SizeOfStruct;
|
||||||
|
ULONG TypeIndex;
|
||||||
|
ULONG64 Reserved[2];
|
||||||
|
ULONG Index;
|
||||||
|
ULONG Size;
|
||||||
|
ULONG64 ModBase;
|
||||||
|
ULONG Flags;
|
||||||
|
ULONG64 Value;
|
||||||
|
ULONG64 Address;
|
||||||
|
ULONG Register;
|
||||||
|
ULONG Scope;
|
||||||
|
ULONG Tag;
|
||||||
|
ULONG NameLen;
|
||||||
|
ULONG MaxNameLen;
|
||||||
|
WCHAR Name[1];
|
||||||
|
} SYMBOL_INFOW, *PSYMBOL_INFOW;
|
||||||
|
|
||||||
|
typedef BOOL
|
||||||
|
(CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACKW)(PSYMBOL_INFOW pSymInfo,
|
||||||
|
ULONG SymbolSize,
|
||||||
|
PVOID UserContext);
|
||||||
|
|
||||||
|
typedef BOOL
|
||||||
|
(CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)(PSYMBOL_INFO pSymInfo,
|
||||||
|
ULONG SymbolSize,
|
||||||
|
PVOID UserContext);
|
||||||
|
|
||||||
|
#endif // API_VERSION_NUMBER < 10/*}}}*/
|
||||||
|
|
||||||
|
// wx-prefixed types map to either the ANSI or Unicode ("W") version depending
|
||||||
|
// on the build of wx itself.
|
||||||
|
#ifdef UNICODE
|
||||||
|
#define wxPSYM_ENUMERATESYMBOLS_CALLBACK PSYM_ENUMERATESYMBOLS_CALLBACKW
|
||||||
|
#else // !UNICODE
|
||||||
|
#define wxPSYM_ENUMERATESYMBOLS_CALLBACK PSYM_ENUMERATESYMBOLS_CALLBACK
|
||||||
|
#endif // UNICODE/!UNICODE
|
||||||
|
|
||||||
|
// This one could be already defined by wx/msw/stackwalk.h
|
||||||
|
#ifndef wxSYMBOL_INFO
|
||||||
|
#ifdef UNICODE
|
||||||
|
#define wxSYMBOL_INFO SYMBOL_INFOW
|
||||||
|
#else // !UNICODE
|
||||||
|
#define wxSYMBOL_INFO SYMBOL_INFO
|
||||||
|
#endif // UNICODE/!UNICODE
|
||||||
|
#endif // !defined(wxSYMBOL_INFO)
|
||||||
|
|
||||||
|
typedef wxSYMBOL_INFO* wxPSYMBOL_INFO;
|
||||||
|
|
||||||
|
// This differs from PENUMLOADED_MODULES_CALLBACK[W]64 in that it always uses
|
||||||
|
// "const" for its first argument when the SDK used to pass a non-const string
|
||||||
|
// here until API_VERSION_NUMBER==11, so we can't just define it as an existing
|
||||||
|
// typedef.
|
||||||
|
typedef BOOL
|
||||||
|
(CALLBACK *wxPENUMLOADED_MODULES_CALLBACK)(const wxChar* moduleName,
|
||||||
|
DWORD64 moduleBase,
|
||||||
|
ULONG moduleSize,
|
||||||
|
void *userContext);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxDbgHelpDLL: dynamically load dbghelp.dll functions
|
// wxDbgHelpDLL: dynamically load dbghelp.dll functions
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -131,31 +248,61 @@ public:
|
|||||||
// function types
|
// function types
|
||||||
typedef DWORD (WINAPI *SymGetOptions_t)();
|
typedef DWORD (WINAPI *SymGetOptions_t)();
|
||||||
typedef DWORD (WINAPI *SymSetOptions_t)(DWORD);
|
typedef DWORD (WINAPI *SymSetOptions_t)(DWORD);
|
||||||
typedef BOOL (WINAPI *SymInitialize_t)(HANDLE, LPSTR, BOOL);
|
typedef BOOL (WINAPI *SymInitialize_t)(HANDLE, LPCSTR, BOOL);
|
||||||
|
typedef BOOL (WINAPI *SymInitializeW_t)(HANDLE, LPCWSTR, BOOL);
|
||||||
typedef BOOL (WINAPI *StackWalk_t)(DWORD, HANDLE, HANDLE, LPSTACKFRAME,
|
typedef BOOL (WINAPI *StackWalk_t)(DWORD, HANDLE, HANDLE, LPSTACKFRAME,
|
||||||
LPVOID, PREAD_PROCESS_MEMORY_ROUTINE,
|
LPVOID, PREAD_PROCESS_MEMORY_ROUTINE,
|
||||||
PFUNCTION_TABLE_ACCESS_ROUTINE,
|
PFUNCTION_TABLE_ACCESS_ROUTINE,
|
||||||
PGET_MODULE_BASE_ROUTINE,
|
PGET_MODULE_BASE_ROUTINE,
|
||||||
PTRANSLATE_ADDRESS_ROUTINE);
|
PTRANSLATE_ADDRESS_ROUTINE);
|
||||||
typedef BOOL (WINAPI *SymFromAddr_t)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO);
|
typedef BOOL (WINAPI *SymFromAddr_t)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO);
|
||||||
|
typedef BOOL (WINAPI *SymFromAddrW_t)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFOW);
|
||||||
typedef LPVOID (WINAPI *SymFunctionTableAccess_t)(HANDLE, DWORD_PTR);
|
typedef LPVOID (WINAPI *SymFunctionTableAccess_t)(HANDLE, DWORD_PTR);
|
||||||
typedef DWORD_PTR (WINAPI *SymGetModuleBase_t)(HANDLE, DWORD_PTR);
|
typedef DWORD_PTR (WINAPI *SymGetModuleBase_t)(HANDLE, DWORD_PTR);
|
||||||
typedef BOOL (WINAPI *SymGetLineFromAddr_t)(HANDLE, DWORD_PTR,
|
typedef BOOL (WINAPI *SymGetLineFromAddr_t)(HANDLE, DWORD,
|
||||||
PDWORD, PIMAGEHLP_LINE);
|
PDWORD, PIMAGEHLP_LINE);
|
||||||
|
typedef BOOL (WINAPI *SymGetLineFromAddr64_t)(HANDLE, DWORD64,
|
||||||
|
PDWORD, PIMAGEHLP_LINE64);
|
||||||
|
typedef BOOL (WINAPI *SymGetLineFromAddrW64_t)(HANDLE, DWORD64,
|
||||||
|
PDWORD, PIMAGEHLP_LINEW64);
|
||||||
typedef BOOL (WINAPI *SymSetContext_t)(HANDLE, PIMAGEHLP_STACK_FRAME,
|
typedef BOOL (WINAPI *SymSetContext_t)(HANDLE, PIMAGEHLP_STACK_FRAME,
|
||||||
PIMAGEHLP_CONTEXT);
|
PIMAGEHLP_CONTEXT);
|
||||||
typedef BOOL (WINAPI *SymEnumSymbols_t)(HANDLE, ULONG64, PCSTR,
|
typedef BOOL (WINAPI *SymEnumSymbols_t)(HANDLE, ULONG64, PCSTR,
|
||||||
PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID);
|
PSYM_ENUMERATESYMBOLS_CALLBACK,
|
||||||
|
const PVOID);
|
||||||
|
typedef BOOL (WINAPI *SymEnumSymbolsW_t)(HANDLE, ULONG64, PCWSTR,
|
||||||
|
PSYM_ENUMERATESYMBOLS_CALLBACKW,
|
||||||
|
const PVOID);
|
||||||
typedef BOOL (WINAPI *SymGetTypeInfo_t)(HANDLE, DWORD64, ULONG,
|
typedef BOOL (WINAPI *SymGetTypeInfo_t)(HANDLE, DWORD64, ULONG,
|
||||||
IMAGEHLP_SYMBOL_TYPE_INFO, PVOID);
|
IMAGEHLP_SYMBOL_TYPE_INFO, PVOID);
|
||||||
typedef BOOL (WINAPI *SymCleanup_t)(HANDLE);
|
typedef BOOL (WINAPI *SymCleanup_t)(HANDLE);
|
||||||
typedef BOOL (WINAPI *EnumerateLoadedModules_t)(HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID);
|
typedef BOOL (WINAPI *EnumerateLoadedModules_t)(HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID);
|
||||||
|
typedef BOOL (WINAPI *EnumerateLoadedModules64_t)(HANDLE, PENUMLOADED_MODULES_CALLBACK64, PVOID);
|
||||||
|
typedef BOOL (WINAPI *EnumerateLoadedModulesW64_t)(HANDLE, PENUMLOADED_MODULES_CALLBACKW64, PVOID);
|
||||||
typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE,
|
typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE,
|
||||||
MINIDUMP_TYPE,
|
MINIDUMP_TYPE,
|
||||||
CONST PMINIDUMP_EXCEPTION_INFORMATION,
|
CONST PMINIDUMP_EXCEPTION_INFORMATION,
|
||||||
CONST PMINIDUMP_USER_STREAM_INFORMATION,
|
CONST PMINIDUMP_USER_STREAM_INFORMATION,
|
||||||
CONST PMINIDUMP_CALLBACK_INFORMATION);
|
CONST PMINIDUMP_CALLBACK_INFORMATION);
|
||||||
|
|
||||||
|
// Higher level functions selecting the right debug help library function
|
||||||
|
// to call: for CallFoo(), it can be Foo(), Foo64(), FooW() or FooW64()
|
||||||
|
// depending on the build options and function availability.
|
||||||
|
//
|
||||||
|
// They also provide more convenient to use wx-specific API, e.g. work with
|
||||||
|
// wxString instead of char/wchar_t pointers and omit the arguments we
|
||||||
|
// don't need.
|
||||||
|
static BOOL CallSymInitialize(HANDLE, BOOL);
|
||||||
|
static BOOL CallEnumerateLoadedModules(HANDLE, wxPENUMLOADED_MODULES_CALLBACK, PVOID);
|
||||||
|
static BOOL CallSymFromAddr(HANDLE, DWORD64,
|
||||||
|
size_t* offset, wxString* name);
|
||||||
|
static BOOL CallSymGetLineFromAddr(HANDLE, DWORD64,
|
||||||
|
wxString* fileName, size_t* line);
|
||||||
|
static BOOL CallSymEnumSymbols(HANDLE hProcess,
|
||||||
|
ULONG64 baseOfDll,
|
||||||
|
wxPSYM_ENUMERATESYMBOLS_CALLBACK callback,
|
||||||
|
const PVOID callbackParam);
|
||||||
|
|
||||||
// The macro called by wxDO_FOR_ALL_SYM_FUNCS() below takes 2 arguments:
|
// The macro called by wxDO_FOR_ALL_SYM_FUNCS() below takes 2 arguments:
|
||||||
// the name of the function in the program code, which never has "64"
|
// the name of the function in the program code, which never has "64"
|
||||||
// suffix, and the name of the function in the DLL which can have "64"
|
// suffix, and the name of the function in the DLL which can have "64"
|
||||||
@@ -176,26 +323,56 @@ public:
|
|||||||
#define wxSYM_CALL_64(what, name) what(name, name)
|
#define wxSYM_CALL_64(what, name) what(name, name)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define wxDO_FOR_ALL_SYM_FUNCS(what) \
|
#define wxSYM_CALL_ALWAYS_W(what, name) what(name ## W, name ## W)
|
||||||
wxSYM_CALL_64(what, StackWalk); \
|
|
||||||
wxSYM_CALL_64(what, SymFunctionTableAccess); \
|
#define wxSYM_CALL_ALTERNATIVES(what, name) \
|
||||||
wxSYM_CALL_64(what, SymGetModuleBase); \
|
what(name, name); \
|
||||||
wxSYM_CALL_64(what, SymGetLineFromAddr); \
|
what(name ## 64, name ## 64); \
|
||||||
wxSYM_CALL_64(what, EnumerateLoadedModules); \
|
what(name ## W64, name ## W64)
|
||||||
\
|
|
||||||
wxSYM_CALL(what, SymGetOptions); \
|
#define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(what) \
|
||||||
wxSYM_CALL(what, SymSetOptions); \
|
wxSYM_CALL_64(what, StackWalk); \
|
||||||
wxSYM_CALL(what, SymInitialize); \
|
wxSYM_CALL_64(what, SymFunctionTableAccess); \
|
||||||
wxSYM_CALL(what, SymFromAddr); \
|
wxSYM_CALL_64(what, SymGetModuleBase); \
|
||||||
wxSYM_CALL(what, SymSetContext); \
|
\
|
||||||
wxSYM_CALL(what, SymEnumSymbols); \
|
wxSYM_CALL(what, SymGetOptions); \
|
||||||
wxSYM_CALL(what, SymGetTypeInfo); \
|
wxSYM_CALL(what, SymSetOptions); \
|
||||||
wxSYM_CALL(what, SymCleanup); \
|
wxSYM_CALL(what, SymSetContext); \
|
||||||
|
wxSYM_CALL(what, SymGetTypeInfo); \
|
||||||
|
wxSYM_CALL(what, SymCleanup); \
|
||||||
wxSYM_CALL(what, MiniDumpWriteDump)
|
wxSYM_CALL(what, MiniDumpWriteDump)
|
||||||
|
|
||||||
|
#define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(what) \
|
||||||
|
wxSYM_CALL(what, SymInitialize); \
|
||||||
|
wxSYM_CALL(what, SymFromAddr); \
|
||||||
|
wxSYM_CALL(what, SymEnumSymbols)
|
||||||
|
|
||||||
|
#define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(what) \
|
||||||
|
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(what); \
|
||||||
|
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(what)
|
||||||
|
|
||||||
|
// Alternation will work when the following functions are not found,
|
||||||
|
// therefore they are not included in REQUIRED version.
|
||||||
|
#define wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(what) \
|
||||||
|
wxSYM_CALL_ALTERNATIVES(what, SymGetLineFromAddr); \
|
||||||
|
wxSYM_CALL_ALTERNATIVES(what, EnumerateLoadedModules); \
|
||||||
|
wxSYM_CALL_ALWAYS_W(what, SymInitialize); \
|
||||||
|
wxSYM_CALL_ALWAYS_W(what, SymFromAddr); \
|
||||||
|
wxSYM_CALL_ALWAYS_W(what, SymEnumSymbols)
|
||||||
|
|
||||||
|
#define wxDO_FOR_ALL_SYM_FUNCS(what) \
|
||||||
|
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(what); \
|
||||||
|
wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(what)
|
||||||
|
|
||||||
#define wxDECLARE_SYM_FUNCTION(func, name) static func ## _t func
|
#define wxDECLARE_SYM_FUNCTION(func, name) static func ## _t func
|
||||||
|
|
||||||
wxDO_FOR_ALL_SYM_FUNCS(wxDECLARE_SYM_FUNCTION);
|
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(wxDECLARE_SYM_FUNCTION);
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(wxDECLARE_SYM_FUNCTION);
|
||||||
|
wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(wxDECLARE_SYM_FUNCTION);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
#undef wxDECLARE_SYM_FUNCTION
|
#undef wxDECLARE_SYM_FUNCTION
|
||||||
|
|
||||||
@@ -209,10 +386,10 @@ public:
|
|||||||
static void LogError(const wxChar *func);
|
static void LogError(const wxChar *func);
|
||||||
|
|
||||||
// return textual representation of the value of given symbol
|
// return textual representation of the value of given symbol
|
||||||
static wxString DumpSymbol(PSYMBOL_INFO pSymInfo, void *pVariable);
|
static wxString DumpSymbol(wxPSYMBOL_INFO pSymInfo, void *pVariable);
|
||||||
|
|
||||||
// return the name of the symbol with given type index
|
// return the name of the symbol with given type index
|
||||||
static wxString GetSymbolName(PSYMBOL_INFO pSymInfo);
|
static wxString GetSymbolName(wxPSYMBOL_INFO pSymInfo);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// dereference the given symbol, i.e. return symbol which is not a
|
// dereference the given symbol, i.e. return symbol which is not a
|
||||||
@@ -222,17 +399,20 @@ private:
|
|||||||
// dereferenced the symbol
|
// dereferenced the symbol
|
||||||
//
|
//
|
||||||
// return the tag of the dereferenced symbol
|
// return the tag of the dereferenced symbol
|
||||||
static SymbolTag DereferenceSymbol(PSYMBOL_INFO pSymInfo, void **ppData);
|
static SymbolTag DereferenceSymbol(wxPSYMBOL_INFO pSymInfo, void **ppData);
|
||||||
|
|
||||||
static wxString DumpField(PSYMBOL_INFO pSymInfo,
|
static wxString DumpField(wxPSYMBOL_INFO pSymInfo,
|
||||||
void *pVariable,
|
void *pVariable,
|
||||||
unsigned level);
|
unsigned level);
|
||||||
|
|
||||||
static wxString DumpBaseType(BasicType bt, DWORD64 length, void *pVariable);
|
static wxString DumpBaseType(BasicType bt, DWORD64 length, void *pVariable);
|
||||||
|
|
||||||
static wxString DumpUDT(PSYMBOL_INFO pSymInfo,
|
static wxString DumpUDT(wxPSYMBOL_INFO pSymInfo,
|
||||||
void *pVariable,
|
void *pVariable,
|
||||||
unsigned level = 0);
|
unsigned level = 0);
|
||||||
|
|
||||||
|
static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp);
|
||||||
|
static bool DoInit();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // wxUSE_DBGHELP
|
#endif // wxUSE_DBGHELP
|
||||||
|
@@ -14,8 +14,8 @@
|
|||||||
|
|
||||||
// the exception handler which should be called from the exception filter
|
// the exception handler which should be called from the exception filter
|
||||||
//
|
//
|
||||||
// it calsl wxApp::OnFatalException() if possible
|
// it calls wxApp::OnFatalException() if wxTheApp object exists
|
||||||
extern unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs);
|
WXDLLIMPEXP_BASE unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs);
|
||||||
|
|
||||||
// helper macro for wxSEH_HANDLE
|
// helper macro for wxSEH_HANDLE
|
||||||
#if defined(__BORLANDC__)
|
#if defined(__BORLANDC__)
|
||||||
|
@@ -19,6 +19,13 @@ struct _EXCEPTION_POINTERS;
|
|||||||
|
|
||||||
// and these in dbghelp.h
|
// and these in dbghelp.h
|
||||||
struct _SYMBOL_INFO;
|
struct _SYMBOL_INFO;
|
||||||
|
struct _SYMBOL_INFOW;
|
||||||
|
|
||||||
|
#if wxUSE_UNICODE
|
||||||
|
#define wxSYMBOL_INFO _SYMBOL_INFOW
|
||||||
|
#else // !wxUSE_UNICODE
|
||||||
|
#define wxSYMBOL_INFO _SYMBOL_INFO
|
||||||
|
#endif // wxUSE_UNICODE/!wxUSE_UNICODE
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxStackFrame
|
// wxStackFrame
|
||||||
@@ -52,7 +59,7 @@ public:
|
|||||||
GetParam(size_t n, wxString *type, wxString *name, wxString *value) const;
|
GetParam(size_t n, wxString *type, wxString *name, wxString *value) const;
|
||||||
|
|
||||||
// callback used by OnGetParam(), don't call directly
|
// callback used by OnGetParam(), don't call directly
|
||||||
void OnParam(_SYMBOL_INFO *pSymInfo);
|
void OnParam(wxSYMBOL_INFO *pSymInfo);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void OnGetName();
|
virtual void OnGetName();
|
||||||
|
@@ -17,14 +17,17 @@
|
|||||||
#include "wx/frame.h"
|
#include "wx/frame.h"
|
||||||
#include "wx/icon.h"
|
#include "wx/icon.h"
|
||||||
#include "wx/menu.h"
|
#include "wx/menu.h"
|
||||||
|
#include "wx/choicdlg.h"
|
||||||
#include "wx/msgdlg.h"
|
#include "wx/msgdlg.h"
|
||||||
#include "wx/button.h"
|
#include "wx/button.h"
|
||||||
#include "wx/dcclient.h"
|
#include "wx/dcclient.h"
|
||||||
|
#include "wx/timer.h"
|
||||||
|
|
||||||
#include "wx/datetime.h"
|
#include "wx/datetime.h"
|
||||||
#include "wx/ffile.h"
|
#include "wx/ffile.h"
|
||||||
#include "wx/filename.h"
|
#include "wx/filename.h"
|
||||||
#include "wx/debugrpt.h"
|
#include "wx/debugrpt.h"
|
||||||
|
#include "wx/dynlib.h"
|
||||||
|
|
||||||
#if !wxUSE_DEBUGREPORT
|
#if !wxUSE_DEBUGREPORT
|
||||||
#error "This sample can't be built without wxUSE_DEBUGREPORT"
|
#error "This sample can't be built without wxUSE_DEBUGREPORT"
|
||||||
@@ -141,10 +144,12 @@ void foo(int n)
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
DebugRpt_ListLoadedDLLs = 50,
|
||||||
DebugRpt_Quit = wxID_EXIT,
|
DebugRpt_Quit = wxID_EXIT,
|
||||||
DebugRpt_Crash = 100,
|
DebugRpt_Crash = 100,
|
||||||
DebugRpt_Current,
|
DebugRpt_Current,
|
||||||
DebugRpt_Paint,
|
DebugRpt_Paint,
|
||||||
|
DebugRpt_Timer,
|
||||||
DebugRpt_Upload,
|
DebugRpt_Upload,
|
||||||
DebugRpt_About = wxID_ABOUT
|
DebugRpt_About = wxID_ABOUT
|
||||||
};
|
};
|
||||||
@@ -155,15 +160,28 @@ public:
|
|||||||
MyFrame();
|
MyFrame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void OnListLoadedDLLs(wxCommandEvent& event);
|
||||||
void OnQuit(wxCommandEvent& event);
|
void OnQuit(wxCommandEvent& event);
|
||||||
void OnReportForCrash(wxCommandEvent& event);
|
void OnReportForCrash(wxCommandEvent& event);
|
||||||
void OnReportForCurrent(wxCommandEvent& event);
|
void OnReportForCurrent(wxCommandEvent& event);
|
||||||
void OnReportPaint(wxCommandEvent& event);
|
void OnReportPaint(wxCommandEvent& event);
|
||||||
|
void OnReportTimer(wxCommandEvent& event);
|
||||||
void OnReportUpload(wxCommandEvent& event);
|
void OnReportUpload(wxCommandEvent& event);
|
||||||
void OnAbout(wxCommandEvent& event);
|
void OnAbout(wxCommandEvent& event);
|
||||||
|
|
||||||
void OnPaint(wxPaintEvent& event);
|
void OnPaint(wxPaintEvent& event);
|
||||||
|
|
||||||
|
// a timer whose only purpose in life is to crash as soon as it's started
|
||||||
|
class BadTimer : public wxTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BadTimer() { }
|
||||||
|
|
||||||
|
virtual void Notify() wxOVERRIDE
|
||||||
|
{
|
||||||
|
foo(8);
|
||||||
|
}
|
||||||
|
} m_badTimer;
|
||||||
|
|
||||||
// number of lines drawn in OnPaint()
|
// number of lines drawn in OnPaint()
|
||||||
int m_numLines;
|
int m_numLines;
|
||||||
@@ -217,10 +235,12 @@ wxIMPLEMENT_APP(MyApp);
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
||||||
|
EVT_MENU(DebugRpt_ListLoadedDLLs, MyFrame::OnListLoadedDLLs)
|
||||||
EVT_MENU(DebugRpt_Quit, MyFrame::OnQuit)
|
EVT_MENU(DebugRpt_Quit, MyFrame::OnQuit)
|
||||||
EVT_MENU(DebugRpt_Crash, MyFrame::OnReportForCrash)
|
EVT_MENU(DebugRpt_Crash, MyFrame::OnReportForCrash)
|
||||||
EVT_MENU(DebugRpt_Current, MyFrame::OnReportForCurrent)
|
EVT_MENU(DebugRpt_Current, MyFrame::OnReportForCurrent)
|
||||||
EVT_MENU(DebugRpt_Paint, MyFrame::OnReportPaint)
|
EVT_MENU(DebugRpt_Paint, MyFrame::OnReportPaint)
|
||||||
|
EVT_MENU(DebugRpt_Timer, MyFrame::OnReportTimer)
|
||||||
EVT_MENU(DebugRpt_Upload, MyFrame::OnReportUpload)
|
EVT_MENU(DebugRpt_Upload, MyFrame::OnReportUpload)
|
||||||
EVT_MENU(DebugRpt_About, MyFrame::OnAbout)
|
EVT_MENU(DebugRpt_About, MyFrame::OnAbout)
|
||||||
|
|
||||||
@@ -236,6 +256,8 @@ MyFrame::MyFrame()
|
|||||||
SetIcon(wxICON(sample));
|
SetIcon(wxICON(sample));
|
||||||
|
|
||||||
wxMenu *menuFile = new wxMenu;
|
wxMenu *menuFile = new wxMenu;
|
||||||
|
menuFile->Append(DebugRpt_ListLoadedDLLs, wxT("&List loaded DLLs...\tCtrl-L"));
|
||||||
|
menuFile->AppendSeparator();
|
||||||
menuFile->Append(DebugRpt_Quit, wxT("E&xit\tAlt-X"));
|
menuFile->Append(DebugRpt_Quit, wxT("E&xit\tAlt-X"));
|
||||||
|
|
||||||
wxMenu *menuReport = new wxMenu;
|
wxMenu *menuReport = new wxMenu;
|
||||||
@@ -245,6 +267,8 @@ MyFrame::MyFrame()
|
|||||||
wxT("Create report for the current program context"));
|
wxT("Create report for the current program context"));
|
||||||
menuReport->Append(DebugRpt_Paint, wxT("Report for &paint handler\tCtrl-P"),
|
menuReport->Append(DebugRpt_Paint, wxT("Report for &paint handler\tCtrl-P"),
|
||||||
wxT("Provoke a repeatable crash in wxEVT_PAINT handler"));
|
wxT("Provoke a repeatable crash in wxEVT_PAINT handler"));
|
||||||
|
menuReport->Append(DebugRpt_Timer, wxT("Report for &timer handler\tCtrl-T"),
|
||||||
|
wxT("Provoke a crash in wxEVT_TIMER handler"));
|
||||||
menuReport->AppendSeparator();
|
menuReport->AppendSeparator();
|
||||||
menuReport->AppendCheckItem(DebugRpt_Upload, wxT("Up&load debug report"),
|
menuReport->AppendCheckItem(DebugRpt_Upload, wxT("Up&load debug report"),
|
||||||
wxT("You need to configure a web server accepting debug report uploads to use this function"));
|
wxT("You need to configure a web server accepting debug report uploads to use this function"));
|
||||||
@@ -263,6 +287,47 @@ MyFrame::MyFrame()
|
|||||||
Show();
|
Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyFrame::OnListLoadedDLLs(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
const wxDynamicLibraryDetailsArray loaded = wxDynamicLibrary::ListLoaded();
|
||||||
|
const size_t count = loaded.size();
|
||||||
|
if ( !count )
|
||||||
|
{
|
||||||
|
wxLogError("Failed to get the list of loaded dynamic libraries.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxArrayString names;
|
||||||
|
names.reserve(count);
|
||||||
|
for ( size_t n = 0; n < count; n++ )
|
||||||
|
{
|
||||||
|
names.push_back(loaded[n].GetName());
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ;; )
|
||||||
|
{
|
||||||
|
const int sel = wxGetSingleChoiceIndex
|
||||||
|
(
|
||||||
|
"Choose a library to show more information about it",
|
||||||
|
"List of loaded dynamic libraries",
|
||||||
|
names,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
if ( sel == wxNOT_FOUND )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const wxDynamicLibraryDetails& det = loaded[sel];
|
||||||
|
void *addr = 0;
|
||||||
|
size_t len = 0;
|
||||||
|
det.GetAddress(&addr, &len);
|
||||||
|
wxLogMessage("Full path is \"%s\", memory range %p:%p, version \"%s\"",
|
||||||
|
det.GetPath(),
|
||||||
|
addr,
|
||||||
|
static_cast<void*>(static_cast<char*>(addr) + len),
|
||||||
|
det.GetVersion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
Close(true);
|
Close(true);
|
||||||
@@ -291,6 +356,12 @@ void MyFrame::OnReportPaint(wxCommandEvent& WXUNUSED(event))
|
|||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyFrame::OnReportTimer(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
// this will result in a crash in BadTimer::OnNotify() soon
|
||||||
|
m_badTimer.StartOnce(100);
|
||||||
|
}
|
||||||
|
|
||||||
void MyFrame::OnReportUpload(wxCommandEvent& event)
|
void MyFrame::OnReportUpload(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
wxGetApp().UploadReport(event.IsChecked());
|
wxGetApp().UploadReport(event.IsChecked());
|
||||||
@@ -369,10 +440,20 @@ void MyApp::GenerateReport(wxDebugReport::Context ctx)
|
|||||||
// can also add an existing file directly, it will be copied
|
// can also add an existing file directly, it will be copied
|
||||||
// automatically
|
// automatically
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
report->AddFile(wxT("c:\\autoexec.bat"), wxT("DOS startup file"));
|
wxString windir;
|
||||||
#else
|
if ( !wxGetEnv("WINDIR", &windir) )
|
||||||
report->AddFile(wxT("/etc/motd"), wxT("Message of the day"));
|
windir = "C:\\Windows";
|
||||||
#endif
|
fn.AssignDir(windir);
|
||||||
|
fn.AppendDir("system32");
|
||||||
|
fn.AppendDir("drivers");
|
||||||
|
fn.AppendDir("etc");
|
||||||
|
#else // !__WXMSW__
|
||||||
|
fn.AssignDir("/etc");
|
||||||
|
#endif // __WXMSW__/!__WXMSW__
|
||||||
|
fn.SetFullName("hosts");
|
||||||
|
|
||||||
|
if ( fn.FileExists() )
|
||||||
|
report->AddFile(fn.GetFullPath(), "Local hosts file");
|
||||||
|
|
||||||
// calling Show() is not mandatory, but is more polite
|
// calling Show() is not mandatory, but is more polite
|
||||||
if ( wxDebugReportPreviewStd().Show(*report) )
|
if ( wxDebugReportPreviewStd().Show(*report) )
|
||||||
|
@@ -332,7 +332,7 @@ wxDebugReportDialog::wxDebugReportDialog(wxDebugReport& dbgrpt)
|
|||||||
|
|
||||||
wxSizer *sizerPreview =
|
wxSizer *sizerPreview =
|
||||||
new wxStaticBoxSizer(wxVERTICAL, this, _("&Debug report preview:"));
|
new wxStaticBoxSizer(wxVERTICAL, this, _("&Debug report preview:"));
|
||||||
sizerPreview->Add(CreateTextSizer(msg), SizerFlags(0).Centre());
|
sizerPreview->Add(CreateTextSizer(msg), wxSizerFlags().Centre().Border());
|
||||||
|
|
||||||
// ... and the list of files in this debug report with buttons to view them
|
// ... and the list of files in this debug report with buttons to view them
|
||||||
wxSizer *sizerFileBtns = new wxBoxSizer(wxVERTICAL);
|
wxSizer *sizerFileBtns = new wxBoxSizer(wxVERTICAL);
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Name: src/msw/debughlp.cpp
|
// Name: src/msw/debughlp.cpp
|
||||||
// Purpose: various Win32 debug helpers
|
// Purpose: various Win32 debug helpers
|
||||||
// Author: Vadim Zeitlin
|
// Author: Vadim Zeitlin, Suzumizaki-kimitaka
|
||||||
// Modified by:
|
|
||||||
// Created: 2005-01-08 (extracted from crashrpt.cpp)
|
// Created: 2005-01-08 (extracted from crashrpt.cpp)
|
||||||
// Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
|
// Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
|
||||||
// Licence: wxWindows licence
|
// Licence: wxWindows licence
|
||||||
@@ -26,6 +25,8 @@
|
|||||||
|
|
||||||
#if wxUSE_DBGHELP && wxUSE_DYNLIB_CLASS
|
#if wxUSE_DBGHELP && wxUSE_DYNLIB_CLASS
|
||||||
|
|
||||||
|
#include "wx/scopedarray.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// constants
|
// constants
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -34,6 +35,59 @@
|
|||||||
// ourselves to that many levels of embedded fields inside structs
|
// ourselves to that many levels of embedded fields inside structs
|
||||||
static const unsigned MAX_DUMP_DEPTH = 20;
|
static const unsigned MAX_DUMP_DEPTH = 20;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// local helpers
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
// Automatically initialize SizeOfStruct field of debug help structs to the
|
||||||
|
// correct value.
|
||||||
|
template <class T>
|
||||||
|
struct SizedStruct : public T
|
||||||
|
{
|
||||||
|
SizedStruct()
|
||||||
|
{
|
||||||
|
::ZeroMemory(this, sizeof(T));
|
||||||
|
this->SizeOfStruct = sizeof(T);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is used for working with variable-sized SYMBOL_INFO[W] structs that
|
||||||
|
// have a variable length array as their last field.
|
||||||
|
template <class T>
|
||||||
|
class VarSizedStruct
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VarSizedStruct()
|
||||||
|
{
|
||||||
|
::ZeroMemory(m_buffer, sizeof(T) + MAX_NAME_LEN);
|
||||||
|
|
||||||
|
(*this)->SizeOfStruct = sizeof(T);
|
||||||
|
(*this)->MaxNameLen = MAX_NAME_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T*()
|
||||||
|
{
|
||||||
|
return static_cast<T*>(static_cast<void*>(m_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
T* operator->()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Currently this is just a constant, we could make it a template parameter
|
||||||
|
// if we wanted.
|
||||||
|
enum { MAX_NAME_LEN = 1024 };
|
||||||
|
|
||||||
|
BYTE m_buffer[sizeof(T) + MAX_NAME_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// globals
|
// globals
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -62,7 +116,8 @@ wxDO_FOR_ALL_SYM_FUNCS(DEFINE_SYM_FUNCTION);
|
|||||||
|
|
||||||
// load all function we need from the DLL
|
// load all function we need from the DLL
|
||||||
|
|
||||||
static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp)
|
/* static */
|
||||||
|
bool wxDbgHelpDLL::BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp)
|
||||||
{
|
{
|
||||||
#define LOAD_SYM_FUNCTION(func, name) \
|
#define LOAD_SYM_FUNCTION(func, name) \
|
||||||
wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \
|
wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \
|
||||||
@@ -73,15 +128,27 @@ static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp)
|
|||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
wxDO_FOR_ALL_SYM_FUNCS(LOAD_SYM_FUNCTION);
|
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(LOAD_SYM_FUNCTION);
|
||||||
|
|
||||||
#undef LOAD_SYM_FUNCTION
|
#undef LOAD_SYM_FUNCTION
|
||||||
|
|
||||||
|
#define LOAD_SYM_FUNCTION_OPTIONAL(func, name) \
|
||||||
|
if ( dllDbgHelp.HasSymbol(wxT(#name)) ) \
|
||||||
|
{ \
|
||||||
|
wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \
|
||||||
|
dllDbgHelp.GetSymbol(wxT(#name)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(LOAD_SYM_FUNCTION_OPTIONAL);
|
||||||
|
|
||||||
|
#undef LOAD_SYM_FUNCTION_CAN_FAIL
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// called by Init() if we hadn't done this before
|
// called by Init() if we hadn't done this before
|
||||||
static bool DoInit()
|
/* static */
|
||||||
|
bool wxDbgHelpDLL::DoInit()
|
||||||
{
|
{
|
||||||
wxDynamicLibrary dllDbgHelp(wxT("dbghelp.dll"), wxDL_VERBATIM);
|
wxDynamicLibrary dllDbgHelp(wxT("dbghelp.dll"), wxDL_VERBATIM);
|
||||||
if ( dllDbgHelp.IsLoaded() )
|
if ( dllDbgHelp.IsLoaded() )
|
||||||
@@ -170,13 +237,13 @@ DoGetTypeInfo(DWORD64 base, ULONG ti, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
|
|||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool
|
bool
|
||||||
DoGetTypeInfo(PSYMBOL_INFO pSym, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
|
DoGetTypeInfo(wxPSYMBOL_INFO pSym, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
|
||||||
{
|
{
|
||||||
return DoGetTypeInfo(pSym->ModBase, pSym->TypeIndex, type, rc);
|
return DoGetTypeInfo(pSym->ModBase, pSym->TypeIndex, type, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym)
|
wxDbgHelpDLL::BasicType GetBasicType(wxPSYMBOL_INFO pSym)
|
||||||
{
|
{
|
||||||
wxDbgHelpDLL::BasicType bt;
|
wxDbgHelpDLL::BasicType bt;
|
||||||
return DoGetTypeInfo(pSym, TI_GET_BASETYPE, &bt)
|
return DoGetTypeInfo(pSym, TI_GET_BASETYPE, &bt)
|
||||||
@@ -185,7 +252,7 @@ wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
wxString wxDbgHelpDLL::GetSymbolName(PSYMBOL_INFO pSym)
|
wxString wxDbgHelpDLL::GetSymbolName(wxPSYMBOL_INFO pSym)
|
||||||
{
|
{
|
||||||
wxString s;
|
wxString s;
|
||||||
|
|
||||||
@@ -289,7 +356,7 @@ wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wxString
|
wxString
|
||||||
wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
wxDbgHelpDLL::DumpField(wxPSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
||||||
{
|
{
|
||||||
wxString s;
|
wxString s;
|
||||||
|
|
||||||
@@ -336,7 +403,7 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
|||||||
|
|
||||||
|
|
||||||
// now pass to the type representing the type of this member
|
// now pass to the type representing the type of this member
|
||||||
SYMBOL_INFO sym = *pSym;
|
wxSYMBOL_INFO sym = *pSym;
|
||||||
if ( !DoGetTypeInfo(pSym, TI_GET_TYPEID, &sym.TypeIndex) )
|
if ( !DoGetTypeInfo(pSym, TI_GET_TYPEID, &sym.TypeIndex) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -387,7 +454,7 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */ wxString
|
/* static */ wxString
|
||||||
wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
wxDbgHelpDLL::DumpUDT(wxPSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
||||||
{
|
{
|
||||||
wxString s;
|
wxString s;
|
||||||
|
|
||||||
@@ -454,7 +521,7 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
|||||||
s << wxT(" {\n");
|
s << wxT(" {\n");
|
||||||
|
|
||||||
// Iterate through all children
|
// Iterate through all children
|
||||||
SYMBOL_INFO sym;
|
wxSYMBOL_INFO sym;
|
||||||
wxZeroMemory(sym);
|
wxZeroMemory(sym);
|
||||||
sym.ModBase = pSym->ModBase;
|
sym.ModBase = pSym->ModBase;
|
||||||
for ( unsigned i = 0; i < dwChildrenCount; i++ )
|
for ( unsigned i = 0; i < dwChildrenCount; i++ )
|
||||||
@@ -486,7 +553,7 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
|||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
wxDbgHelpDLL::SymbolTag
|
wxDbgHelpDLL::SymbolTag
|
||||||
wxDbgHelpDLL::DereferenceSymbol(PSYMBOL_INFO pSym, void **ppData)
|
wxDbgHelpDLL::DereferenceSymbol(wxPSYMBOL_INFO pSym, void **ppData)
|
||||||
{
|
{
|
||||||
SymbolTag tag = SYMBOL_TAG_NULL;
|
SymbolTag tag = SYMBOL_TAG_NULL;
|
||||||
for ( ;; )
|
for ( ;; )
|
||||||
@@ -523,10 +590,10 @@ wxDbgHelpDLL::DereferenceSymbol(PSYMBOL_INFO pSym, void **ppData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */ wxString
|
/* static */ wxString
|
||||||
wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable)
|
wxDbgHelpDLL::DumpSymbol(wxPSYMBOL_INFO pSym, void *pVariable)
|
||||||
{
|
{
|
||||||
wxString s;
|
wxString s;
|
||||||
SYMBOL_INFO symDeref = *pSym;
|
wxSYMBOL_INFO symDeref = *pSym;
|
||||||
switch ( DereferenceSymbol(&symDeref, &pVariable) )
|
switch ( DereferenceSymbol(&symDeref, &pVariable) )
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
@@ -552,6 +619,322 @@ wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Helpers for selecting the best available function on the current platform.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Store the original callback and the data for it: objects of this type are
|
||||||
|
// used as bridges for the enumeration functions taking callbacks of different
|
||||||
|
// types.
|
||||||
|
struct wxEnumLoadedCallbackBridge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxEnumLoadedCallbackBridge(wxPENUMLOADED_MODULES_CALLBACK ptr, PVOID content)
|
||||||
|
: m_callback(ptr), m_data(content)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wxPENUMLOADED_MODULES_CALLBACK m_callback;
|
||||||
|
PVOID m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// As mentioned near wxPENUMLOADED_MODULES_CALLBACK definition, until v11 of
|
||||||
|
// the API the parameters were non-const.
|
||||||
|
#if API_VERSION_NUMBER < 11
|
||||||
|
#define wxHAS_NON_CONST_MODULE_NAME
|
||||||
|
|
||||||
|
#define wxMODULE_NAMEA PSTR
|
||||||
|
#else
|
||||||
|
#define wxMODULE_NAMEA PCSTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(UNICODE) && defined(wxHAS_NON_CONST_MODULE_NAME)
|
||||||
|
|
||||||
|
static BOOL CALLBACK
|
||||||
|
wxEnumLoadedW64Callback(PWSTR ModuleName,
|
||||||
|
DWORD64 ModuleBase,
|
||||||
|
ULONG ModuleSize,
|
||||||
|
PVOID UserContext)
|
||||||
|
{
|
||||||
|
wxEnumLoadedCallbackBridge&
|
||||||
|
bridge = *static_cast<wxEnumLoadedCallbackBridge*>(UserContext);
|
||||||
|
|
||||||
|
return (*bridge.m_callback)(ModuleName, ModuleBase, ModuleSize, bridge.m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNICODE && wxHAS_NON_CONST_MODULE_NAME
|
||||||
|
|
||||||
|
static BOOL CALLBACK
|
||||||
|
wxEnumLoaded64Callback(wxMODULE_NAMEA ModuleName,
|
||||||
|
DWORD64 ModuleBase,
|
||||||
|
ULONG ModuleSize,
|
||||||
|
PVOID UserContext)
|
||||||
|
{
|
||||||
|
wxEnumLoadedCallbackBridge&
|
||||||
|
bridge = *static_cast<wxEnumLoadedCallbackBridge*>(UserContext);
|
||||||
|
|
||||||
|
return (*bridge.m_callback)
|
||||||
|
(
|
||||||
|
#ifdef UNICODE
|
||||||
|
wxConvLocal.cMB2WC(ModuleName),
|
||||||
|
#else // !UNICODE
|
||||||
|
ModuleName,
|
||||||
|
#endif // UNICODE
|
||||||
|
ModuleBase, ModuleSize, bridge.m_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL CALLBACK
|
||||||
|
wxEnumLoadedCallback(wxMODULE_NAMEA ModuleName,
|
||||||
|
DWORD_PTR ModuleBase,
|
||||||
|
ULONG ModuleSize,
|
||||||
|
PVOID UserContext)
|
||||||
|
{
|
||||||
|
wxEnumLoadedCallbackBridge&
|
||||||
|
bridge = *static_cast<wxEnumLoadedCallbackBridge*>(UserContext);
|
||||||
|
|
||||||
|
return (*bridge.m_callback)
|
||||||
|
(
|
||||||
|
#ifdef UNICODE
|
||||||
|
wxConvLocal.cMB2WC(ModuleName),
|
||||||
|
#else // !UNICODE
|
||||||
|
ModuleName,
|
||||||
|
#endif // UNICODE
|
||||||
|
ModuleBase, ModuleSize, bridge.m_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
BOOL
|
||||||
|
wxDbgHelpDLL::CallEnumerateLoadedModules(HANDLE handle,
|
||||||
|
wxPENUMLOADED_MODULES_CALLBACK callback,
|
||||||
|
PVOID callbackParam)
|
||||||
|
{
|
||||||
|
#ifdef UNICODE
|
||||||
|
if ( EnumerateLoadedModulesW64 )
|
||||||
|
{
|
||||||
|
#ifdef wxHAS_NON_CONST_MODULE_NAME
|
||||||
|
// We need to pass by a bridge just to convert non-const module name to
|
||||||
|
// the const one taken by our callback.
|
||||||
|
wxEnumLoadedCallbackBridge br(callback, callbackParam);
|
||||||
|
if ( EnumerateLoadedModulesW64(handle, &wxEnumLoadedW64Callback, &br) )
|
||||||
|
return TRUE;
|
||||||
|
#else // new SDK
|
||||||
|
// We can use our callback directly.
|
||||||
|
if ( EnumerateLoadedModulesW64(handle, callback, callbackParam) )
|
||||||
|
return TRUE;
|
||||||
|
#endif // old/new SDK
|
||||||
|
}
|
||||||
|
#endif // UNICODE
|
||||||
|
|
||||||
|
if ( EnumerateLoadedModules64 )
|
||||||
|
{
|
||||||
|
// We need a bridge if we need to convert to Unicode or if we're using
|
||||||
|
// an older SDK with a non-const first argument, so just use it always
|
||||||
|
// to avoid having too many complicated preprocessor checks.
|
||||||
|
wxEnumLoadedCallbackBridge br(callback, callbackParam);
|
||||||
|
if ( EnumerateLoadedModules64(handle, &wxEnumLoaded64Callback, &br) )
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( EnumerateLoadedModules )
|
||||||
|
{
|
||||||
|
// With this function we need a bridge in any case because the type of
|
||||||
|
// module base argument used by EnumerateLoadedModules() differs from
|
||||||
|
// that used by EnumerateLoadedModules[W]64().
|
||||||
|
wxEnumLoadedCallbackBridge br(callback, callbackParam);
|
||||||
|
if ( EnumerateLoadedModules(handle, &wxEnumLoadedCallback, &br) )
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
BOOL
|
||||||
|
wxDbgHelpDLL::CallSymInitialize(HANDLE hProcess, BOOL fInvadeProcess)
|
||||||
|
{
|
||||||
|
#ifdef UNICODE
|
||||||
|
if ( SymInitializeW )
|
||||||
|
{
|
||||||
|
if ( SymInitializeW(hProcess, NULL, fInvadeProcess) )
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif // UNICODE
|
||||||
|
|
||||||
|
if ( SymInitialize )
|
||||||
|
{
|
||||||
|
if ( SymInitialize(hProcess, NULL, fInvadeProcess) )
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
BOOL
|
||||||
|
wxDbgHelpDLL::CallSymFromAddr(HANDLE hProcess,
|
||||||
|
DWORD64 Address,
|
||||||
|
size_t* offset,
|
||||||
|
wxString* name)
|
||||||
|
{
|
||||||
|
DWORD64 dwDisplacement;
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
if ( SymFromAddrW )
|
||||||
|
{
|
||||||
|
VarSizedStruct<SYMBOL_INFOW> infoW;
|
||||||
|
if ( SymFromAddrW(hProcess, Address, &dwDisplacement, infoW) )
|
||||||
|
{
|
||||||
|
*offset = dwDisplacement;
|
||||||
|
*name = infoW->Name;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // UNICODE
|
||||||
|
|
||||||
|
if ( SymFromAddr )
|
||||||
|
{
|
||||||
|
VarSizedStruct<SYMBOL_INFO> info;
|
||||||
|
if ( SymFromAddr(hProcess, Address, &dwDisplacement, info) )
|
||||||
|
{
|
||||||
|
*offset = dwDisplacement;
|
||||||
|
*name = info->Name;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
BOOL
|
||||||
|
wxDbgHelpDLL::CallSymGetLineFromAddr(HANDLE hProcess,
|
||||||
|
DWORD64 dwAddr,
|
||||||
|
wxString* fileName,
|
||||||
|
size_t* line)
|
||||||
|
{
|
||||||
|
DWORD dwDisplacement;
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
if ( SymGetLineFromAddrW64 )
|
||||||
|
{
|
||||||
|
SizedStruct<IMAGEHLP_LINEW64> lineW64;
|
||||||
|
if ( SymGetLineFromAddrW64(hProcess, dwAddr, &dwDisplacement, &lineW64) )
|
||||||
|
{
|
||||||
|
*fileName = lineW64.FileName;
|
||||||
|
*line = lineW64.LineNumber;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // UNICODE
|
||||||
|
|
||||||
|
if ( SymGetLineFromAddr64 )
|
||||||
|
{
|
||||||
|
SizedStruct<IMAGEHLP_LINE64> line64;
|
||||||
|
if ( SymGetLineFromAddr64(hProcess, dwAddr, &dwDisplacement, &line64) )
|
||||||
|
{
|
||||||
|
*fileName = line64.FileName;
|
||||||
|
*line = line64.LineNumber;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( SymGetLineFromAddr )
|
||||||
|
{
|
||||||
|
SizedStruct<IMAGEHLP_LINE> line32;
|
||||||
|
if ( SymGetLineFromAddr(hProcess, dwAddr, &dwDisplacement, &line32) )
|
||||||
|
{
|
||||||
|
*fileName = line32.FileName;
|
||||||
|
*line = line32.LineNumber;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
|
||||||
|
// Allow to adapt callback supposed to be used with SymEnumSymbolsW() with
|
||||||
|
// SymEnumSymbols().
|
||||||
|
struct wxEnumSymbolsCallbackBridge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxEnumSymbolsCallbackBridge(PSYM_ENUMERATESYMBOLS_CALLBACKW ptr, PVOID content)
|
||||||
|
: m_callback(ptr), m_data(content)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PSYM_ENUMERATESYMBOLS_CALLBACKW m_callback;
|
||||||
|
PVOID m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static BOOL CALLBACK
|
||||||
|
wxEnumSymbolsCallback(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
|
||||||
|
{
|
||||||
|
wxEnumSymbolsCallbackBridge&
|
||||||
|
bridge = *static_cast<wxEnumSymbolsCallbackBridge*>(UserContext);
|
||||||
|
|
||||||
|
const wxWCharBuffer buf = wxConvLocal.cMB2WC(pSymInfo->Name);
|
||||||
|
const size_t len = buf.length();
|
||||||
|
|
||||||
|
// Allocate enough space for the wide char version of the struct.
|
||||||
|
//
|
||||||
|
// Note that there is no +1 here because sizeof(SYMBOL_INFOW) already
|
||||||
|
// includes 1 byte of the name.
|
||||||
|
wxScopedArray<BYTE> symbolBuffer(sizeof(SYMBOL_INFOW) + len*sizeof(WCHAR));
|
||||||
|
|
||||||
|
SYMBOL_INFOW* const infoW = (SYMBOL_INFOW*)symbolBuffer.get();
|
||||||
|
|
||||||
|
// Copy the original struct contents except for the last byte, which is the
|
||||||
|
// first byte of its (narrow) name that we don't need.
|
||||||
|
CopyMemory(infoW, pSymInfo, sizeof(SYMBOL_INFO) - sizeof(CHAR));
|
||||||
|
|
||||||
|
// Size is different for narrow and wide variants of the struct, so fix it
|
||||||
|
// up now.
|
||||||
|
infoW->SizeOfStruct = sizeof(SYMBOL_INFOW);
|
||||||
|
|
||||||
|
// Finally copy the converted name, which is the reason for doing all this.
|
||||||
|
wxStrncpy(infoW->Name, buf.data(), len);
|
||||||
|
|
||||||
|
return (*bridge.m_callback)(infoW, SymbolSize, bridge.m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNICODE
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
BOOL
|
||||||
|
wxDbgHelpDLL::CallSymEnumSymbols(HANDLE hProcess,
|
||||||
|
ULONG64 baseOfDll,
|
||||||
|
wxPSYM_ENUMERATESYMBOLS_CALLBACK callback,
|
||||||
|
const PVOID callbackParam)
|
||||||
|
{
|
||||||
|
#ifdef UNICODE
|
||||||
|
if ( SymEnumSymbolsW )
|
||||||
|
{
|
||||||
|
if ( SymEnumSymbolsW(hProcess, baseOfDll, NULL, callback, callbackParam) )
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( SymEnumSymbols )
|
||||||
|
{
|
||||||
|
wxEnumSymbolsCallbackBridge br(callback, callbackParam);
|
||||||
|
|
||||||
|
if ( SymEnumSymbols(hProcess, baseOfDll, NULL, wxEnumSymbolsCallback, &br) )
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#else // !UNICODE
|
||||||
|
if ( SymEnumSymbols )
|
||||||
|
{
|
||||||
|
if ( SymEnumSymbols(hProcess, baseOfDll, NULL, callback, callbackParam) )
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif // UNICODE/!UNICODE
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// debugging helpers
|
// debugging helpers
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -77,15 +77,8 @@ public:
|
|||||||
wxVersionDLL *verDLL;
|
wxVersionDLL *verDLL;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: fix EnumerateLoadedModules() to use EnumerateLoadedModules64()
|
|
||||||
#ifdef __WIN64__
|
|
||||||
typedef DWORD64 DWORD_32_64;
|
|
||||||
#else
|
|
||||||
typedef DWORD DWORD_32_64;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static BOOL CALLBACK
|
static BOOL CALLBACK
|
||||||
EnumModulesProc(PCSTR name, DWORD_32_64 base, ULONG size, void *data);
|
EnumModulesProc(const wxChar* name, DWORD64 base, ULONG size, PVOID data);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -172,8 +165,8 @@ wxString wxVersionDLL::GetFileVersion(const wxString& filename) const
|
|||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
BOOL CALLBACK
|
BOOL CALLBACK
|
||||||
wxDynamicLibraryDetailsCreator::EnumModulesProc(PCSTR name,
|
wxDynamicLibraryDetailsCreator::EnumModulesProc(const wxChar* name,
|
||||||
DWORD_32_64 base,
|
DWORD64 base,
|
||||||
ULONG size,
|
ULONG size,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
@@ -276,15 +269,9 @@ wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded()
|
|||||||
params.dlls = &dlls;
|
params.dlls = &dlls;
|
||||||
params.verDLL = &verDLL;
|
params.verDLL = &verDLL;
|
||||||
|
|
||||||
// Note that the cast of EnumModulesProc is needed because the type of
|
if ( !wxDbgHelpDLL::CallEnumerateLoadedModules
|
||||||
// PENUMLOADED_MODULES_CALLBACK changed: in old SDK versions its first
|
|
||||||
// argument was non-const PSTR while now it's PCSTR. By explicitly
|
|
||||||
// casting to whatever the currently used headers require we ensure
|
|
||||||
// that the code compilers in any case.
|
|
||||||
if ( !wxDbgHelpDLL::EnumerateLoadedModules
|
|
||||||
(
|
(
|
||||||
::GetCurrentProcess(),
|
::GetCurrentProcess(),
|
||||||
(PENUMLOADED_MODULES_CALLBACK)
|
|
||||||
wxDynamicLibraryDetailsCreator::EnumModulesProc,
|
wxDynamicLibraryDetailsCreator::EnumModulesProc,
|
||||||
¶ms
|
¶ms
|
||||||
) )
|
) )
|
||||||
|
@@ -90,7 +90,7 @@ bool wxHeaderCtrl::Create(wxWindow *parent,
|
|||||||
// use 0 here but this starts to look ugly)
|
// use 0 here but this starts to look ugly)
|
||||||
if ( wxApp::GetComCtl32Version() >= 600 )
|
if ( wxApp::GetComCtl32Version() >= 600 )
|
||||||
{
|
{
|
||||||
Header_SetBitmapMargin(GetHwnd(), ::GetSystemMetrics(SM_CXEDGE));
|
(void)Header_SetBitmapMargin(GetHwnd(), ::GetSystemMetrics(SM_CXEDGE));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -237,7 +237,8 @@ void wxHeaderCtrl::DoUpdate(unsigned int idx)
|
|||||||
if ( !m_isHidden[idx] )
|
if ( !m_isHidden[idx] )
|
||||||
{
|
{
|
||||||
// but it wasn't hidden before, so remove it
|
// but it wasn't hidden before, so remove it
|
||||||
Header_DeleteItem(GetHwnd(), MSWToNativeIdx(idx));
|
if ( !Header_DeleteItem(GetHwnd(), MSWToNativeIdx(idx)) )
|
||||||
|
wxLogLastError(wxS("Header_DeleteItem()"));
|
||||||
|
|
||||||
m_isHidden[idx] = true;
|
m_isHidden[idx] = true;
|
||||||
}
|
}
|
||||||
@@ -252,7 +253,8 @@ void wxHeaderCtrl::DoUpdate(unsigned int idx)
|
|||||||
else // and it was shown before as well
|
else // and it was shown before as well
|
||||||
{
|
{
|
||||||
// we need to remove the old column
|
// we need to remove the old column
|
||||||
Header_DeleteItem(GetHwnd(), MSWToNativeIdx(idx));
|
if ( !Header_DeleteItem(GetHwnd(), MSWToNativeIdx(idx)) )
|
||||||
|
wxLogLastError(wxS("Header_DeleteItem()"));
|
||||||
}
|
}
|
||||||
|
|
||||||
DoInsertItem(col, idx);
|
DoInsertItem(col, idx);
|
||||||
|
@@ -505,7 +505,7 @@ bool wxListCtrl::SetForegroundColour(const wxColour& col)
|
|||||||
if ( !wxWindow::SetForegroundColour(col) )
|
if ( !wxWindow::SetForegroundColour(col) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ListView_SetTextColor(GetHwnd(), wxColourToRGB(col));
|
SetTextColour(col);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -519,8 +519,10 @@ bool wxListCtrl::SetBackgroundColour(const wxColour& col)
|
|||||||
// we set the same colour for both the "empty" background and the items
|
// we set the same colour for both the "empty" background and the items
|
||||||
// background
|
// background
|
||||||
COLORREF color = wxColourToRGB(col);
|
COLORREF color = wxColourToRGB(col);
|
||||||
ListView_SetBkColor(GetHwnd(), color);
|
if ( !ListView_SetBkColor(GetHwnd(), color) )
|
||||||
ListView_SetTextBkColor(GetHwnd(), color);
|
wxLogLastError(wxS("ListView_SetBkColor()"));
|
||||||
|
if ( !ListView_SetTextBkColor(GetHwnd(), color) )
|
||||||
|
wxLogLastError(wxS("ListView_SetTextBkColor()"));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -936,7 +938,7 @@ bool wxListCtrl::SetItemState(long item, long state, long stateMask)
|
|||||||
// to, so do it explicitly
|
// to, so do it explicitly
|
||||||
if ( changingFocus && !HasFlag(wxLC_SINGLE_SEL) )
|
if ( changingFocus && !HasFlag(wxLC_SINGLE_SEL) )
|
||||||
{
|
{
|
||||||
ListView_SetSelectionMark(GetHwnd(), item);
|
(void)ListView_SetSelectionMark(GetHwnd(), item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1225,7 +1227,8 @@ wxColour wxListCtrl::GetTextColour() const
|
|||||||
// Sets the text colour of the listview
|
// Sets the text colour of the listview
|
||||||
void wxListCtrl::SetTextColour(const wxColour& col)
|
void wxListCtrl::SetTextColour(const wxColour& col)
|
||||||
{
|
{
|
||||||
ListView_SetTextColor(GetHwnd(), PALETTERGB(col.Red(), col.Green(), col.Blue()));
|
if ( !ListView_SetTextColor(GetHwnd(), wxColourToPalRGB(col)) )
|
||||||
|
wxLogLastError(wxS("ListView_SetTextColor()"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the index of the topmost visible item when in
|
// Gets the index of the topmost visible item when in
|
||||||
@@ -2656,7 +2659,8 @@ bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
|
|||||||
it.iSubItem = col;
|
it.iSubItem = col;
|
||||||
it.pszText = text;
|
it.pszText = text;
|
||||||
it.cchTextMax = WXSIZEOF(text);
|
it.cchTextMax = WXSIZEOF(text);
|
||||||
ListView_GetItem(hwndList, &it);
|
if ( !ListView_GetItem(hwndList, &it) )
|
||||||
|
return false;
|
||||||
|
|
||||||
HIMAGELIST himl = ListView_GetImageList(hwndList, LVSIL_SMALL);
|
HIMAGELIST himl = ListView_GetImageList(hwndList, LVSIL_SMALL);
|
||||||
if ( himl && ImageList_GetImageCount(himl) )
|
if ( himl && ImageList_GetImageCount(himl) )
|
||||||
@@ -3086,7 +3090,8 @@ void wxListCtrl::RefreshItem(long item)
|
|||||||
|
|
||||||
void wxListCtrl::RefreshItems(long itemFrom, long itemTo)
|
void wxListCtrl::RefreshItems(long itemFrom, long itemTo)
|
||||||
{
|
{
|
||||||
ListView_RedrawItems(GetHwnd(), itemFrom, itemTo);
|
if ( !ListView_RedrawItems(GetHwnd(), itemFrom, itemTo) )
|
||||||
|
wxLogLastError(wxS("ListView_RedrawItems"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -360,7 +360,7 @@ int wxNotebook::SetSelection(size_t nPage)
|
|||||||
|
|
||||||
UpdateSelection(nPage);
|
UpdateSelection(nPage);
|
||||||
|
|
||||||
TabCtrl_SetCurSel(GetHwnd(), nPage);
|
(void)TabCtrl_SetCurSel(GetHwnd(), nPage);
|
||||||
|
|
||||||
SendPageChangedEvent(selectionOld, nPage);
|
SendPageChangedEvent(selectionOld, nPage);
|
||||||
}
|
}
|
||||||
@@ -406,7 +406,7 @@ int wxNotebook::ChangeSelection(size_t nPage)
|
|||||||
|
|
||||||
if ( m_selection == wxNOT_FOUND || nPage != (size_t)m_selection )
|
if ( m_selection == wxNOT_FOUND || nPage != (size_t)m_selection )
|
||||||
{
|
{
|
||||||
TabCtrl_SetCurSel(GetHwnd(), nPage);
|
(void)TabCtrl_SetCurSel(GetHwnd(), nPage);
|
||||||
|
|
||||||
UpdateSelection(nPage);
|
UpdateSelection(nPage);
|
||||||
}
|
}
|
||||||
@@ -508,7 +508,7 @@ wxRect wxNotebook::GetPageSize() const
|
|||||||
// The value of 20 is chosen arbitrarily but seems to work
|
// The value of 20 is chosen arbitrarily but seems to work
|
||||||
if ( rc.right > 20 && rc.bottom > 20 )
|
if ( rc.right > 20 && rc.bottom > 20 )
|
||||||
{
|
{
|
||||||
TabCtrl_AdjustRect(GetHwnd(), false, &rc);
|
(void)TabCtrl_AdjustRect(GetHwnd(), false, &rc);
|
||||||
|
|
||||||
wxCopyRECTToRect(rc, r);
|
wxCopyRECTToRect(rc, r);
|
||||||
}
|
}
|
||||||
@@ -525,7 +525,7 @@ void wxNotebook::SetPageSize(const wxSize& size)
|
|||||||
rc.right = size.x;
|
rc.right = size.x;
|
||||||
rc.bottom = size.y;
|
rc.bottom = size.y;
|
||||||
|
|
||||||
TabCtrl_AdjustRect(GetHwnd(), true, &rc);
|
(void)TabCtrl_AdjustRect(GetHwnd(), true, &rc);
|
||||||
|
|
||||||
// and now set it
|
// and now set it
|
||||||
SetSize(rc.right - rc.left, rc.bottom - rc.top);
|
SetSize(rc.right - rc.left, rc.bottom - rc.top);
|
||||||
@@ -552,9 +552,11 @@ wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
|
|||||||
if ( GetPageCount() > 0 )
|
if ( GetPageCount() > 0 )
|
||||||
{
|
{
|
||||||
RECT rect;
|
RECT rect;
|
||||||
TabCtrl_GetItemRect(GetHwnd(), 0, &rect);
|
if ( TabCtrl_GetItemRect(GetHwnd(), 0, &rect) )
|
||||||
tabSize.x = rect.right - rect.left;
|
{
|
||||||
tabSize.y = rect.bottom - rect.top;
|
tabSize.x = rect.right - rect.left;
|
||||||
|
tabSize.y = rect.bottom - rect.top;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int rows = GetRowCount();
|
const int rows = GetRowCount();
|
||||||
@@ -601,7 +603,8 @@ wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage)
|
|||||||
// selected page is visible and others are hidden:
|
// selected page is visible and others are hidden:
|
||||||
pageRemoved->Show(false);
|
pageRemoved->Show(false);
|
||||||
|
|
||||||
TabCtrl_DeleteItem(GetHwnd(), nPage);
|
if ( !TabCtrl_DeleteItem(GetHwnd(), nPage) )
|
||||||
|
wxLogLastError(wxS("TabCtrl_DeleteItem()"));
|
||||||
|
|
||||||
if ( m_pages.IsEmpty() )
|
if ( m_pages.IsEmpty() )
|
||||||
{
|
{
|
||||||
@@ -654,7 +657,8 @@ bool wxNotebook::DeleteAllPages()
|
|||||||
|
|
||||||
m_pages.Clear();
|
m_pages.Clear();
|
||||||
|
|
||||||
TabCtrl_DeleteAllItems(GetHwnd());
|
if ( !TabCtrl_DeleteAllItems(GetHwnd()) )
|
||||||
|
wxLogLastError(wxS("TabCtrl_DeleteAllItems()"));
|
||||||
|
|
||||||
m_selection = wxNOT_FOUND;
|
m_selection = wxNOT_FOUND;
|
||||||
|
|
||||||
@@ -986,7 +990,7 @@ void wxNotebook::OnSize(wxSizeEvent& event)
|
|||||||
UpdateBgBrush();
|
UpdateBgBrush();
|
||||||
#endif // wxUSE_UXTHEME
|
#endif // wxUSE_UXTHEME
|
||||||
|
|
||||||
TabCtrl_AdjustRect(GetHwnd(), false, &rc);
|
(void)TabCtrl_AdjustRect(GetHwnd(), false, &rc);
|
||||||
|
|
||||||
int width = rc.right - rc.left,
|
int width = rc.right - rc.left,
|
||||||
height = rc.bottom - rc.top;
|
height = rc.bottom - rc.top;
|
||||||
|
@@ -50,29 +50,16 @@ void wxStackFrame::OnGetName()
|
|||||||
m_hasName = true;
|
m_hasName = true;
|
||||||
|
|
||||||
// get the name of the function for this stack frame entry
|
// get the name of the function for this stack frame entry
|
||||||
static const size_t MAX_NAME_LEN = 1024;
|
if ( !wxDbgHelpDLL::CallSymFromAddr
|
||||||
BYTE symbolBuffer[sizeof(SYMBOL_INFO) + MAX_NAME_LEN];
|
|
||||||
wxZeroMemory(symbolBuffer);
|
|
||||||
|
|
||||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
|
|
||||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
|
||||||
pSymbol->MaxNameLen = MAX_NAME_LEN;
|
|
||||||
|
|
||||||
DWORD64 symDisplacement = 0;
|
|
||||||
if ( !wxDbgHelpDLL::SymFromAddr
|
|
||||||
(
|
(
|
||||||
::GetCurrentProcess(),
|
::GetCurrentProcess(),
|
||||||
GetSymAddr(),
|
GetSymAddr(),
|
||||||
&symDisplacement,
|
&m_offset,
|
||||||
pSymbol
|
&m_name
|
||||||
) )
|
) )
|
||||||
{
|
{
|
||||||
wxDbgHelpDLL::LogError(wxT("SymFromAddr"));
|
wxDbgHelpDLL::LogError(wxT("SymFromAddr"));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_name = wxString::FromAscii(pSymbol->Name);
|
|
||||||
m_offset = symDisplacement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxStackFrame::OnGetLocation()
|
void wxStackFrame::OnGetLocation()
|
||||||
@@ -82,25 +69,11 @@ void wxStackFrame::OnGetLocation()
|
|||||||
|
|
||||||
m_hasLocation = true;
|
m_hasLocation = true;
|
||||||
|
|
||||||
// get the source line for this stack frame entry
|
// get the source line for this stack frame entry ignoring possible errors
|
||||||
IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
|
// (it's normal that we don't have source info for some symbols, e.g. all
|
||||||
DWORD dwLineDisplacement;
|
// those from the system DLLs)
|
||||||
if ( !wxDbgHelpDLL::SymGetLineFromAddr
|
wxDbgHelpDLL::CallSymGetLineFromAddr(::GetCurrentProcess(), GetSymAddr(),
|
||||||
(
|
&m_filename, &m_line);
|
||||||
::GetCurrentProcess(),
|
|
||||||
GetSymAddr(),
|
|
||||||
&dwLineDisplacement,
|
|
||||||
&lineInfo
|
|
||||||
) )
|
|
||||||
{
|
|
||||||
// it is normal that we don't have source info for some symbols,
|
|
||||||
// notably all the ones from the system DLLs...
|
|
||||||
//wxDbgHelpDLL::LogError(wxT("SymGetLineFromAddr"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_filename = wxString::FromAscii(lineInfo.FileName);
|
|
||||||
m_line = lineInfo.LineNumber;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -125,11 +98,10 @@ wxStackFrame::GetParam(size_t n,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxStackFrame::OnParam(PSYMBOL_INFO pSymInfo)
|
void wxStackFrame::OnParam(wxSYMBOL_INFO *pSymInfo)
|
||||||
{
|
{
|
||||||
m_paramTypes.Add(wxEmptyString);
|
m_paramTypes.Add(wxEmptyString);
|
||||||
|
m_paramNames.Add(pSymInfo->Name);
|
||||||
m_paramNames.Add(wxString::FromAscii(pSymInfo->Name));
|
|
||||||
|
|
||||||
// if symbol information is corrupted and we crash, the exception is going
|
// if symbol information is corrupted and we crash, the exception is going
|
||||||
// to be ignored when we're called from WalkFromException() because of the
|
// to be ignored when we're called from WalkFromException() because of the
|
||||||
@@ -158,7 +130,7 @@ void wxStackFrame::OnParam(PSYMBOL_INFO pSymInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOL CALLBACK
|
BOOL CALLBACK
|
||||||
EnumSymbolsProc(PSYMBOL_INFO pSymInfo, ULONG WXUNUSED(SymSize), PVOID data)
|
EnumSymbolsProc(wxPSYMBOL_INFO pSymInfo, ULONG WXUNUSED(SymSize), PVOID data)
|
||||||
{
|
{
|
||||||
wxStackFrame *frame = static_cast<wxStackFrame *>(data);
|
wxStackFrame *frame = static_cast<wxStackFrame *>(data);
|
||||||
|
|
||||||
@@ -195,11 +167,10 @@ void wxStackFrame::OnGetParam()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !wxDbgHelpDLL::SymEnumSymbols
|
if ( !wxDbgHelpDLL::CallSymEnumSymbols
|
||||||
(
|
(
|
||||||
::GetCurrentProcess(),
|
::GetCurrentProcess(),
|
||||||
NULL, // DLL base: use current context
|
NULL, // DLL base: use current context
|
||||||
NULL, // no mask, get all symbols
|
|
||||||
EnumSymbolsProc, // callback
|
EnumSymbolsProc, // callback
|
||||||
this // data to pass to it
|
this // data to pass to it
|
||||||
) )
|
) )
|
||||||
@@ -232,10 +203,9 @@ void wxStackWalker::WalkFrom(const CONTEXT *pCtx, size_t skip, size_t maxDepth)
|
|||||||
// below which should be a real handle... so this is what we use
|
// below which should be a real handle... so this is what we use
|
||||||
const HANDLE hProcess = ::GetCurrentProcess();
|
const HANDLE hProcess = ::GetCurrentProcess();
|
||||||
|
|
||||||
if ( !wxDbgHelpDLL::SymInitialize
|
if ( !wxDbgHelpDLL::CallSymInitialize
|
||||||
(
|
(
|
||||||
hProcess,
|
hProcess,
|
||||||
NULL, // use default symbol search path
|
|
||||||
TRUE // load symbols for all loaded modules
|
TRUE // load symbols for all loaded modules
|
||||||
) )
|
) )
|
||||||
{
|
{
|
||||||
@@ -382,7 +352,7 @@ wxStackFrame::GetParam(size_t WXUNUSED(n),
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxStackFrame::OnParam(_SYMBOL_INFO * WXUNUSED(pSymInfo))
|
void wxStackFrame::OnParam(wxSYMBOL_INFO * WXUNUSED(pSymInfo))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -340,11 +340,11 @@ static bool SetFocus(HWND hwndTV, HTREEITEM htItem)
|
|||||||
// prevent the tree from unselecting the old focus which it
|
// prevent the tree from unselecting the old focus which it
|
||||||
// would do by default (TreeView_SelectItem unselects the
|
// would do by default (TreeView_SelectItem unselects the
|
||||||
// focused item)
|
// focused item)
|
||||||
TreeView_SelectItem(hwndTV, 0);
|
(void)TreeView_SelectItem(hwndTV, 0);
|
||||||
SelectItem(hwndTV, htFocus);
|
SelectItem(hwndTV, htFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeView_SelectItem(hwndTV, htItem);
|
(void)TreeView_SelectItem(hwndTV, htItem);
|
||||||
|
|
||||||
if ( !wasSelected )
|
if ( !wasSelected )
|
||||||
{
|
{
|
||||||
@@ -359,7 +359,7 @@ static bool SetFocus(HWND hwndTV, HTREEITEM htItem)
|
|||||||
bool wasFocusSelected = IsItemSelected(hwndTV, htFocus);
|
bool wasFocusSelected = IsItemSelected(hwndTV, htFocus);
|
||||||
|
|
||||||
// just clear the focus
|
// just clear the focus
|
||||||
TreeView_SelectItem(hwndTV, 0);
|
(void)TreeView_SelectItem(hwndTV, 0);
|
||||||
|
|
||||||
if ( wasFocusSelected )
|
if ( wasFocusSelected )
|
||||||
{
|
{
|
||||||
@@ -873,7 +873,7 @@ unsigned int wxTreeCtrl::GetIndent() const
|
|||||||
|
|
||||||
void wxTreeCtrl::SetIndent(unsigned int indent)
|
void wxTreeCtrl::SetIndent(unsigned int indent)
|
||||||
{
|
{
|
||||||
TreeView_SetIndent(GetHwnd(), indent);
|
(void)TreeView_SetIndent(GetHwnd(), indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxTreeCtrl::SetAnyImageList(wxImageList *imageList, int which)
|
void wxTreeCtrl::SetAnyImageList(wxImageList *imageList, int which)
|
||||||
@@ -1969,7 +1969,7 @@ void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
|
|||||||
wxCHECK_RET( !IsHiddenRoot(item), wxT("can't show hidden root item") );
|
wxCHECK_RET( !IsHiddenRoot(item), wxT("can't show hidden root item") );
|
||||||
|
|
||||||
// no error return
|
// no error return
|
||||||
TreeView_EnsureVisible(GetHwnd(), HITEM(item));
|
(void)TreeView_EnsureVisible(GetHwnd(), HITEM(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxTreeCtrl::ScrollTo(const wxTreeItemId& item)
|
void wxTreeCtrl::ScrollTo(const wxTreeItemId& item)
|
||||||
@@ -2031,7 +2031,8 @@ wxTextCtrl *wxTreeCtrl::EditLabel(const wxTreeItemId& item,
|
|||||||
// End label editing, optionally cancelling the edit
|
// End label editing, optionally cancelling the edit
|
||||||
void wxTreeCtrl::DoEndEditLabel(bool discardChanges)
|
void wxTreeCtrl::DoEndEditLabel(bool discardChanges)
|
||||||
{
|
{
|
||||||
TreeView_EndEditLabelNow(GetHwnd(), discardChanges);
|
if ( !TreeView_EndEditLabelNow(GetHwnd(), discardChanges) )
|
||||||
|
wxLogLastError(wxS("TreeView_EndEditLabelNow()"));
|
||||||
|
|
||||||
DeleteTextCtrl();
|
DeleteTextCtrl();
|
||||||
}
|
}
|
||||||
@@ -2170,7 +2171,8 @@ void wxTreeCtrl::SortChildren(const wxTreeItemId& item)
|
|||||||
// OnCompareItems
|
// OnCompareItems
|
||||||
if ( GetClassInfo() == wxCLASSINFO(wxTreeCtrl) )
|
if ( GetClassInfo() == wxCLASSINFO(wxTreeCtrl) )
|
||||||
{
|
{
|
||||||
TreeView_SortChildren(GetHwnd(), HITEM(item), 0);
|
if ( !TreeView_SortChildren(GetHwnd(), HITEM(item), 0) )
|
||||||
|
wxLogLastError(wxS("TreeView_SortChildren()"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2178,7 +2180,8 @@ void wxTreeCtrl::SortChildren(const wxTreeItemId& item)
|
|||||||
tvSort.hParent = HITEM(item);
|
tvSort.hParent = HITEM(item);
|
||||||
tvSort.lpfnCompare = wxTreeSortHelper::Compare;
|
tvSort.lpfnCompare = wxTreeSortHelper::Compare;
|
||||||
tvSort.lParam = (LPARAM)this;
|
tvSort.lParam = (LPARAM)this;
|
||||||
TreeView_SortChildrenCB(GetHwnd(), &tvSort, 0 /* reserved */);
|
if ( !TreeView_SortChildrenCB(GetHwnd(), &tvSort, 0 /* reserved */) )
|
||||||
|
wxLogLastError(wxS("TreeView_SortChildrenCB()"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2996,25 +2999,26 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
|||||||
tviAux.hItem = HITEM(m_htClickedItem);
|
tviAux.hItem = HITEM(m_htClickedItem);
|
||||||
tviAux.mask = TVIF_STATE | TVIF_PARAM;
|
tviAux.mask = TVIF_STATE | TVIF_PARAM;
|
||||||
tviAux.stateMask = 0xffffffff;
|
tviAux.stateMask = 0xffffffff;
|
||||||
TreeView_GetItem(GetHwnd(), &tviAux);
|
if ( TreeView_GetItem(GetHwnd(), &tviAux) )
|
||||||
|
{
|
||||||
|
tv.itemNew.state = tviAux.state;
|
||||||
|
tv.itemNew.lParam = tviAux.lParam;
|
||||||
|
|
||||||
tv.itemNew.state = tviAux.state;
|
tv.ptDrag.x = x;
|
||||||
tv.itemNew.lParam = tviAux.lParam;
|
tv.ptDrag.y = y;
|
||||||
|
|
||||||
tv.ptDrag.x = x;
|
// do it before SendMessage() call below to avoid
|
||||||
tv.ptDrag.y = y;
|
// reentrancies here if there is another WM_MOUSEMOVE
|
||||||
|
// in the queue already
|
||||||
|
m_htClickedItem.Unset();
|
||||||
|
|
||||||
// do it before SendMessage() call below to avoid
|
::SendMessage(GetHwndOf(GetParent()), WM_NOTIFY,
|
||||||
// reentrancies here if there is another WM_MOUSEMOVE
|
tv.hdr.idFrom, (LPARAM)&tv );
|
||||||
// in the queue already
|
|
||||||
m_htClickedItem.Unset();
|
|
||||||
|
|
||||||
::SendMessage(GetHwndOf(GetParent()), WM_NOTIFY,
|
// don't pass it to the default window proc, it would
|
||||||
tv.hdr.idFrom, (LPARAM)&tv );
|
// start dragging again
|
||||||
|
processed = true;
|
||||||
// don't pass it to the default window proc, it would
|
}
|
||||||
// start dragging again
|
|
||||||
processed = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // __WXWINCE__
|
#endif // __WXWINCE__
|
||||||
@@ -3028,7 +3032,8 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
|||||||
// highlight the item as target (hiding drag image is
|
// highlight the item as target (hiding drag image is
|
||||||
// necessary - otherwise the display will be corrupted)
|
// necessary - otherwise the display will be corrupted)
|
||||||
m_dragImage->Hide();
|
m_dragImage->Hide();
|
||||||
TreeView_SelectDropTarget(GetHwnd(), htItem);
|
if ( !TreeView_SelectDropTarget(GetHwnd(), htItem) )
|
||||||
|
wxLogLastError(wxS("TreeView_SelectDropTarget()"));
|
||||||
m_dragImage->Show();
|
m_dragImage->Show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3101,7 +3106,8 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
|||||||
|
|
||||||
// if we don't do it, the tree seems to think that 2 items
|
// if we don't do it, the tree seems to think that 2 items
|
||||||
// are selected simultaneously which is quite weird
|
// are selected simultaneously which is quite weird
|
||||||
TreeView_SelectDropTarget(GetHwnd(), 0);
|
if ( !TreeView_SelectDropTarget(GetHwnd(), 0) )
|
||||||
|
wxLogLastError(wxS("TreeView_SelectDropTarget(0)"));
|
||||||
}
|
}
|
||||||
#endif // wxUSE_DRAGIMAGE
|
#endif // wxUSE_DRAGIMAGE
|
||||||
|
|
||||||
@@ -3235,7 +3241,8 @@ wxTreeCtrl::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
|||||||
|
|
||||||
// if we don't do it, the tree seems to think that 2 items
|
// if we don't do it, the tree seems to think that 2 items
|
||||||
// are selected simultaneously which is quite weird
|
// are selected simultaneously which is quite weird
|
||||||
TreeView_SelectDropTarget(GetHwnd(), 0);
|
if ( !TreeView_SelectDropTarget(GetHwnd(), 0) )
|
||||||
|
wxLogLastError(wxS("TreeView_SelectDropTarget(0)"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3645,7 +3652,10 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
|
|||||||
if ( MSWIsOnItem(tvhti.flags) )
|
if ( MSWIsOnItem(tvhti.flags) )
|
||||||
{
|
{
|
||||||
event.m_item = tvhti.hItem;
|
event.m_item = tvhti.hItem;
|
||||||
eventType = hdr->code == NM_DBLCLK
|
// Cast is needed for the very old (gcc 3.4.5) MinGW
|
||||||
|
// headers which didn't define NM_DBLCLK as unsigned,
|
||||||
|
// resulting in signed/unsigned comparison warning.
|
||||||
|
eventType = hdr->code == (UINT)NM_DBLCLK
|
||||||
? wxEVT_TREE_ITEM_ACTIVATED
|
? wxEVT_TREE_ITEM_ACTIVATED
|
||||||
: wxEVT_TREE_ITEM_RIGHT_CLICK;
|
: wxEVT_TREE_ITEM_RIGHT_CLICK;
|
||||||
|
|
||||||
|
@@ -82,6 +82,7 @@
|
|||||||
#include "wx/msw/private.h"
|
#include "wx/msw/private.h"
|
||||||
#include "wx/msw/private/keyboard.h"
|
#include "wx/msw/private/keyboard.h"
|
||||||
#include "wx/msw/dcclient.h"
|
#include "wx/msw/dcclient.h"
|
||||||
|
#include "wx/msw/seh.h"
|
||||||
#include "wx/private/textmeasure.h"
|
#include "wx/private/textmeasure.h"
|
||||||
|
|
||||||
#if wxUSE_TOOLTIPS
|
#if wxUSE_TOOLTIPS
|
||||||
@@ -2757,10 +2758,21 @@ wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
|
|
||||||
LRESULT rc;
|
LRESULT rc;
|
||||||
|
|
||||||
if ( wnd && wxGUIEventLoop::AllowProcessing(wnd) )
|
// We have to catch unhandled Win32 exceptions here because otherwise they
|
||||||
rc = wnd->MSWWindowProc(message, wParam, lParam);
|
// would be simply lost if we're called from a kernel callback (as it
|
||||||
else
|
// happens when we process WM_PAINT, for example under WOW64: the 32 bit
|
||||||
rc = ::DefWindowProc(hWnd, message, wParam, lParam);
|
// exceptions can't pass through the 64 bit kernel in this case and so are
|
||||||
|
// mostly just suppressed, although the exact behaviour differs across
|
||||||
|
// Windows versions, see the "Remarks" section of WindowProc documentation
|
||||||
|
// at https://msdn.microsoft.com/en-us/library/ms633573.aspx
|
||||||
|
wxSEH_TRY
|
||||||
|
{
|
||||||
|
if ( wnd && wxGUIEventLoop::AllowProcessing(wnd) )
|
||||||
|
rc = wnd->MSWWindowProc(message, wParam, lParam);
|
||||||
|
else
|
||||||
|
rc = ::DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
wxSEH_HANDLE(0)
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#if wxUSE_STC
|
#if wxUSE_STC
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
|
#include "wx/math.h"
|
||||||
#include "wx/menu.h"
|
#include "wx/menu.h"
|
||||||
#include "wx/dcmemory.h"
|
#include "wx/dcmemory.h"
|
||||||
#include "wx/settings.h"
|
#include "wx/settings.h"
|
||||||
@@ -50,8 +51,8 @@ Point Point::FromLong(long lpoint) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wxRect wxRectFromPRectangle(PRectangle prc) {
|
wxRect wxRectFromPRectangle(PRectangle prc) {
|
||||||
wxRect r(prc.left, prc.top,
|
wxRect r(wxRound(prc.left), wxRound(prc.top),
|
||||||
prc.Width(), prc.Height());
|
wxRound(prc.Width()), wxRound(prc.Height()));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ void Font::Create(const FontParameters &fp) {
|
|||||||
else
|
else
|
||||||
weight = wxFONTWEIGHT_NORMAL;
|
weight = wxFONTWEIGHT_NORMAL;
|
||||||
|
|
||||||
wxFont font(fp.size,
|
wxFont font(wxRound(fp.size),
|
||||||
wxFONTFAMILY_DEFAULT,
|
wxFONTFAMILY_DEFAULT,
|
||||||
fp.italic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL,
|
fp.italic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL,
|
||||||
weight,
|
weight,
|
||||||
@@ -320,8 +321,8 @@ void SurfaceImpl::Polygon(Point *pts, int npts, ColourDesired fore, ColourDesire
|
|||||||
wxPoint *p = new wxPoint[npts];
|
wxPoint *p = new wxPoint[npts];
|
||||||
|
|
||||||
for (int i=0; i<npts; i++) {
|
for (int i=0; i<npts; i++) {
|
||||||
p[i].x = pts[i].x;
|
p[i].x = wxRound(pts[i].x);
|
||||||
p[i].y = pts[i].y;
|
p[i].y = wxRound(pts[i].y);
|
||||||
}
|
}
|
||||||
hdc->DrawPolygon(npts, p);
|
hdc->DrawPolygon(npts, p);
|
||||||
delete [] p;
|
delete [] p;
|
||||||
@@ -501,7 +502,7 @@ void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
|
|||||||
wxRect r = wxRectFromPRectangle(rc);
|
wxRect r = wxRectFromPRectangle(rc);
|
||||||
hdc->Blit(r.x, r.y, r.width, r.height,
|
hdc->Blit(r.x, r.y, r.width, r.height,
|
||||||
((SurfaceImpl&)surfaceSource).hdc,
|
((SurfaceImpl&)surfaceSource).hdc,
|
||||||
from.x, from.y, wxCOPY);
|
wxRound(from.x), wxRound(from.y), wxCOPY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, XYPOSITION ybase,
|
void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, XYPOSITION ybase,
|
||||||
@@ -514,7 +515,7 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, XYPOSITION ybase,
|
|||||||
|
|
||||||
// ybase is where the baseline should be, but wxWin uses the upper left
|
// ybase is where the baseline should be, but wxWin uses the upper left
|
||||||
// corner, so I need to calculate the real position for the text...
|
// corner, so I need to calculate the real position for the text...
|
||||||
hdc->DrawText(stc2wx(s, len), rc.left, ybase - GetAscent(font));
|
hdc->DrawText(stc2wx(s, len), wxRound(rc.left), wxRound(ybase - GetAscent(font)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, XYPOSITION ybase,
|
void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, XYPOSITION ybase,
|
||||||
@@ -527,7 +528,7 @@ void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, XYPOSITION ybase,
|
|||||||
hdc->SetClippingRegion(wxRectFromPRectangle(rc));
|
hdc->SetClippingRegion(wxRectFromPRectangle(rc));
|
||||||
|
|
||||||
// see comments above
|
// see comments above
|
||||||
hdc->DrawText(stc2wx(s, len), rc.left, ybase - GetAscent(font));
|
hdc->DrawText(stc2wx(s, len), wxRound(rc.left), wxRound(ybase - GetAscent(font)));
|
||||||
hdc->DestroyClippingRegion();
|
hdc->DestroyClippingRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,7 +543,7 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font, XYPOSITION ybas
|
|||||||
|
|
||||||
// ybase is where the baseline should be, but wxWin uses the upper left
|
// ybase is where the baseline should be, but wxWin uses the upper left
|
||||||
// corner, so I need to calculate the real position for the text...
|
// corner, so I need to calculate the real position for the text...
|
||||||
hdc->DrawText(stc2wx(s, len), rc.left, ybase - GetAscent(font));
|
hdc->DrawText(stc2wx(s, len), wxRound(rc.left), wxRound(ybase - GetAscent(font)));
|
||||||
|
|
||||||
hdc->SetBackgroundMode(wxBRUSHSTYLE_SOLID);
|
hdc->SetBackgroundMode(wxBRUSHSTYLE_SOLID);
|
||||||
}
|
}
|
||||||
@@ -784,7 +785,7 @@ PRectangle Window::GetMonitorRect(Point pt) {
|
|||||||
if (! wid) return PRectangle();
|
if (! wid) return PRectangle();
|
||||||
#if wxUSE_DISPLAY
|
#if wxUSE_DISPLAY
|
||||||
// Get the display the point is found on
|
// Get the display the point is found on
|
||||||
int n = wxDisplay::GetFromPoint(wxPoint(pt.x, pt.y));
|
int n = wxDisplay::GetFromPoint(wxPoint(wxRound(pt.x), wxRound(pt.y)));
|
||||||
wxDisplay dpy(n == wxNOT_FOUND ? 0 : n);
|
wxDisplay dpy(n == wxNOT_FOUND ? 0 : n);
|
||||||
rect = dpy.GetGeometry();
|
rect = dpy.GetGeometry();
|
||||||
#else
|
#else
|
||||||
@@ -1428,7 +1429,7 @@ void Menu::Destroy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Menu::Show(Point pt, Window &w) {
|
void Menu::Show(Point pt, Window &w) {
|
||||||
GETWIN(w.GetID())->PopupMenu((wxMenu*)mid, pt.x - 4, pt.y);
|
GETWIN(w.GetID())->PopupMenu((wxMenu*)mid, wxRound(pt.x - 4), wxRound(pt.y));
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include "wx/scrolbar.h"
|
#include "wx/scrolbar.h"
|
||||||
|
#include "wx/math.h"
|
||||||
#include "wx/menu.h"
|
#include "wx/menu.h"
|
||||||
#include "wx/timer.h"
|
#include "wx/timer.h"
|
||||||
#endif // WX_PRECOMP
|
#endif // WX_PRECOMP
|
||||||
@@ -433,7 +434,7 @@ bool ScintillaWX::ModifyScrollBars(int nMax, int nPage) {
|
|||||||
horizEnd = 0;
|
horizEnd = 0;
|
||||||
if (!horizontalScrollBarVisible || Wrapping())
|
if (!horizontalScrollBarVisible || Wrapping())
|
||||||
horizEnd = 0;
|
horizEnd = 0;
|
||||||
int pageWidth = rcText.Width();
|
int pageWidth = wxRound(rcText.Width());
|
||||||
|
|
||||||
if (stc->m_hScrollBar == NULL) { // Use built-in scrollbar
|
if (stc->m_hScrollBar == NULL) { // Use built-in scrollbar
|
||||||
int sbMax = stc->GetScrollRange(wxHORIZONTAL);
|
int sbMax = stc->GetScrollRange(wxHORIZONTAL);
|
||||||
@@ -664,7 +665,7 @@ void ScintillaWX::UpdateSystemCaret() {
|
|||||||
CreateSystemCaret();
|
CreateSystemCaret();
|
||||||
}
|
}
|
||||||
Point pos = PointMainCaret();
|
Point pos = PointMainCaret();
|
||||||
::SetCaretPos(pos.x, pos.y);
|
::SetCaretPos(wxRound(pos.x), wxRound(pos.y));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -842,7 +843,7 @@ void ScintillaWX::FullPaintDC(wxDC* dc) {
|
|||||||
void ScintillaWX::DoHScroll(int type, int pos) {
|
void ScintillaWX::DoHScroll(int type, int pos) {
|
||||||
int xPos = xOffset;
|
int xPos = xOffset;
|
||||||
PRectangle rcText = GetTextRectangle();
|
PRectangle rcText = GetTextRectangle();
|
||||||
int pageWidth = rcText.Width() * 2 / 3;
|
int pageWidth = wxRound(rcText.Width() * 2 / 3);
|
||||||
if (type == wxEVT_SCROLLWIN_LINEUP || type == wxEVT_SCROLL_LINEUP)
|
if (type == wxEVT_SCROLLWIN_LINEUP || type == wxEVT_SCROLL_LINEUP)
|
||||||
xPos -= H_SCROLL_STEP;
|
xPos -= H_SCROLL_STEP;
|
||||||
else if (type == wxEVT_SCROLLWIN_LINEDOWN || type == wxEVT_SCROLL_LINEDOWN)
|
else if (type == wxEVT_SCROLLWIN_LINEDOWN || type == wxEVT_SCROLL_LINEDOWN)
|
||||||
@@ -852,7 +853,7 @@ void ScintillaWX::DoHScroll(int type, int pos) {
|
|||||||
else if (type == wxEVT_SCROLLWIN_PAGEDOWN || type == wxEVT_SCROLL_PAGEDOWN) {
|
else if (type == wxEVT_SCROLLWIN_PAGEDOWN || type == wxEVT_SCROLL_PAGEDOWN) {
|
||||||
xPos += pageWidth;
|
xPos += pageWidth;
|
||||||
if (xPos > scrollWidth - rcText.Width()) {
|
if (xPos > scrollWidth - rcText.Width()) {
|
||||||
xPos = scrollWidth - rcText.Width();
|
xPos = wxRound(scrollWidth - rcText.Width());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == wxEVT_SCROLLWIN_TOP || type == wxEVT_SCROLL_TOP)
|
else if (type == wxEVT_SCROLLWIN_TOP || type == wxEVT_SCROLL_TOP)
|
||||||
@@ -894,14 +895,14 @@ void ScintillaWX::DoMouseWheel(wxMouseWheelAxis axis, int rotation, int delta,
|
|||||||
int pixels;
|
int pixels;
|
||||||
|
|
||||||
if (axis == wxMOUSE_WHEEL_HORIZONTAL) {
|
if (axis == wxMOUSE_WHEEL_HORIZONTAL) {
|
||||||
wheelHRotation += rotation * (columnsPerAction * vs.spaceWidth);
|
wheelHRotation += wxRound(rotation * (columnsPerAction * vs.spaceWidth));
|
||||||
pixels = wheelHRotation / delta;
|
pixels = wheelHRotation / delta;
|
||||||
wheelHRotation -= pixels * delta;
|
wheelHRotation -= pixels * delta;
|
||||||
if (pixels != 0) {
|
if (pixels != 0) {
|
||||||
xPos += pixels;
|
xPos += pixels;
|
||||||
PRectangle rcText = GetTextRectangle();
|
PRectangle rcText = GetTextRectangle();
|
||||||
if (xPos > scrollWidth - rcText.Width()) {
|
if (xPos > scrollWidth - rcText.Width()) {
|
||||||
xPos = scrollWidth - rcText.Width();
|
xPos = wxRound(scrollWidth - rcText.Width());
|
||||||
}
|
}
|
||||||
HorizontalScrollTo(xPos);
|
HorizontalScrollTo(xPos);
|
||||||
}
|
}
|
||||||
@@ -1190,7 +1191,7 @@ void ScintillaWX::DoScrollToLine(int line) {
|
|||||||
|
|
||||||
|
|
||||||
void ScintillaWX::DoScrollToColumn(int column) {
|
void ScintillaWX::DoScrollToColumn(int column) {
|
||||||
HorizontalScrollTo(column * vs.spaceWidth);
|
HorizontalScrollTo(wxRound(column * vs.spaceWidth));
|
||||||
}
|
}
|
||||||
|
|
||||||
// wxGTK doesn't appear to need this explicit clipping code any longer, but I
|
// wxGTK doesn't appear to need this explicit clipping code any longer, but I
|
||||||
|
@@ -54,12 +54,6 @@
|
|||||||
|
|
||||||
#include "tiffiop.h"
|
#include "tiffiop.h"
|
||||||
|
|
||||||
typedef union fd_as_handle_union
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
thandle_t h;
|
|
||||||
} fd_as_handle_union_t;
|
|
||||||
|
|
||||||
static tmsize_t
|
static tmsize_t
|
||||||
_tiffReadProc(thandle_t fd, void* buf, tmsize_t size)
|
_tiffReadProc(thandle_t fd, void* buf, tmsize_t size)
|
||||||
{
|
{
|
||||||
|
@@ -210,6 +210,8 @@ TIFFFdOpen(int ifd, const char* name, const char* mode)
|
|||||||
int fSuppressMap;
|
int fSuppressMap;
|
||||||
int m;
|
int m;
|
||||||
fSuppressMap=0;
|
fSuppressMap=0;
|
||||||
|
fd_as_handle_union_t fdh;
|
||||||
|
fdh.fd = ifd;
|
||||||
for (m=0; mode[m]!=0; m++)
|
for (m=0; mode[m]!=0; m++)
|
||||||
{
|
{
|
||||||
if (mode[m]=='u')
|
if (mode[m]=='u')
|
||||||
@@ -218,7 +220,7 @@ TIFFFdOpen(int ifd, const char* name, const char* mode)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tif = TIFFClientOpen(name, mode, (thandle_t)ifd,
|
tif = TIFFClientOpen(name, mode, fdh.h,
|
||||||
_tiffReadProc, _tiffWriteProc,
|
_tiffReadProc, _tiffWriteProc,
|
||||||
_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
|
_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
|
||||||
fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
|
fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
|
||||||
@@ -237,7 +239,7 @@ TIFF*
|
|||||||
TIFFOpen(const char* name, const char* mode)
|
TIFFOpen(const char* name, const char* mode)
|
||||||
{
|
{
|
||||||
static const char module[] = "TIFFOpen";
|
static const char module[] = "TIFFOpen";
|
||||||
thandle_t fd;
|
fd_as_handle_union_t fdh;
|
||||||
int m;
|
int m;
|
||||||
DWORD dwMode;
|
DWORD dwMode;
|
||||||
TIFF* tif;
|
TIFF* tif;
|
||||||
@@ -253,19 +255,19 @@ TIFFOpen(const char* name, const char* mode)
|
|||||||
default: return ((TIFF*)0);
|
default: return ((TIFF*)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = (thandle_t)CreateFileA(name,
|
fdh.h = CreateFileA(name,
|
||||||
(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE),
|
(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE),
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
|
||||||
(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
|
(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
|
||||||
NULL);
|
NULL);
|
||||||
if (fd == INVALID_HANDLE_VALUE) {
|
if (fdh.h == INVALID_HANDLE_VALUE) {
|
||||||
TIFFErrorExt(0, module, "%s: Cannot open", name);
|
TIFFErrorExt(0, module, "%s: Cannot open", name);
|
||||||
return ((TIFF *)0);
|
return ((TIFF *)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tif = TIFFFdOpen((int)fd, name, mode);
|
tif = TIFFFdOpen(fdh.fd, name, mode);
|
||||||
if(!tif)
|
if(!tif)
|
||||||
CloseHandle(fd);
|
CloseHandle(fdh.h);
|
||||||
return tif;
|
return tif;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +278,7 @@ TIFF*
|
|||||||
TIFFOpenW(const wchar_t* name, const char* mode)
|
TIFFOpenW(const wchar_t* name, const char* mode)
|
||||||
{
|
{
|
||||||
static const char module[] = "TIFFOpenW";
|
static const char module[] = "TIFFOpenW";
|
||||||
thandle_t fd;
|
fd_as_handle_union_t fdh;
|
||||||
int m;
|
int m;
|
||||||
DWORD dwMode;
|
DWORD dwMode;
|
||||||
int mbsize;
|
int mbsize;
|
||||||
@@ -294,12 +296,12 @@ TIFFOpenW(const wchar_t* name, const char* mode)
|
|||||||
default: return ((TIFF*)0);
|
default: return ((TIFF*)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = (thandle_t)CreateFileW(name,
|
fdh.h = CreateFileW(name,
|
||||||
(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE),
|
(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE),
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
|
||||||
(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
|
(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
|
||||||
NULL);
|
NULL);
|
||||||
if (fd == INVALID_HANDLE_VALUE) {
|
if (fdh.h == INVALID_HANDLE_VALUE) {
|
||||||
TIFFErrorExt(0, module, "%S: Cannot open", name);
|
TIFFErrorExt(0, module, "%S: Cannot open", name);
|
||||||
return ((TIFF *)0);
|
return ((TIFF *)0);
|
||||||
}
|
}
|
||||||
@@ -318,10 +320,10 @@ TIFFOpenW(const wchar_t* name, const char* mode)
|
|||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
tif = TIFFFdOpen((int)fd,
|
tif = TIFFFdOpen(fdh.fd,
|
||||||
(mbname != NULL) ? mbname : "<unknown>", mode);
|
(mbname != NULL) ? mbname : "<unknown>", mode);
|
||||||
if(!tif)
|
if(!tif)
|
||||||
CloseHandle(fd);
|
CloseHandle(fdh.h);
|
||||||
|
|
||||||
_TIFFfree(mbname);
|
_TIFFfree(mbname);
|
||||||
|
|
||||||
|
@@ -77,6 +77,17 @@ typedef struct client_info {
|
|||||||
char *name;
|
char *name;
|
||||||
} TIFFClientInfoLink;
|
} TIFFClientInfoLink;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Union allowing to cast between the OS-specific handles and integer file
|
||||||
|
* descriptors without triggering compiler warnings, even if their types are
|
||||||
|
* not the same.
|
||||||
|
*/
|
||||||
|
typedef union fd_as_handle_union
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
thandle_t h;
|
||||||
|
} fd_as_handle_union_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Typedefs for ``method pointers'' used internally.
|
* Typedefs for ``method pointers'' used internally.
|
||||||
* these are depriciated and provided only for backwards compatibility
|
* these are depriciated and provided only for backwards compatibility
|
||||||
|
Reference in New Issue
Block a user