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.
|
||||
- Improve wxMimeTypesManager open command detection (Eric Jensen).
|
||||
- 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 setting menu item bitmaps after appending them (Artur Wieczorek).
|
||||
- Fix setting label of submenu items (Artur Wieczorek).
|
||||
|
@@ -1,8 +1,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/msw/debughlp.h
|
||||
// Purpose: wraps dbghelp.h standard file
|
||||
// Author: Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Author: Vadim Zeitlin, Suzumizaki-kimitaka
|
||||
// Created: 2005-01-08 (extracted from msw/crashrpt.cpp)
|
||||
// Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
|
||||
// Licence: wxWindows licence
|
||||
@@ -19,12 +18,19 @@
|
||||
#endif // __WXWINCE__
|
||||
#include "wx/msw/private.h"
|
||||
|
||||
// wxUSE_DBGHELP can be predefined as 0 to avoid the use of dbghelp.dll if this
|
||||
// is undesirable for some reason.
|
||||
// wxUSE_DBGHELP can be predefined on the compiler command line to force using
|
||||
// dbghelp.dll even if it's not detected or, on the contrary, avoid using even
|
||||
// if it's available.
|
||||
#ifndef wxUSE_DBGHELP
|
||||
// The only compiler which is known to have the necessary headers is MSVC.
|
||||
#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
|
||||
#define wxUSE_DBGHELP 0
|
||||
#endif
|
||||
@@ -32,6 +38,117 @@
|
||||
|
||||
#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
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -131,31 +248,61 @@ public:
|
||||
// function types
|
||||
typedef DWORD (WINAPI *SymGetOptions_t)();
|
||||
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,
|
||||
LPVOID, PREAD_PROCESS_MEMORY_ROUTINE,
|
||||
PFUNCTION_TABLE_ACCESS_ROUTINE,
|
||||
PGET_MODULE_BASE_ROUTINE,
|
||||
PTRANSLATE_ADDRESS_ROUTINE);
|
||||
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 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);
|
||||
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,
|
||||
PIMAGEHLP_CONTEXT);
|
||||
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,
|
||||
IMAGEHLP_SYMBOL_TYPE_INFO, PVOID);
|
||||
typedef BOOL (WINAPI *SymCleanup_t)(HANDLE);
|
||||
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,
|
||||
MINIDUMP_TYPE,
|
||||
CONST PMINIDUMP_EXCEPTION_INFORMATION,
|
||||
CONST PMINIDUMP_USER_STREAM_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 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"
|
||||
@@ -176,26 +323,56 @@ public:
|
||||
#define wxSYM_CALL_64(what, name) what(name, name)
|
||||
#endif
|
||||
|
||||
#define wxDO_FOR_ALL_SYM_FUNCS(what) \
|
||||
wxSYM_CALL_64(what, StackWalk); \
|
||||
wxSYM_CALL_64(what, SymFunctionTableAccess); \
|
||||
wxSYM_CALL_64(what, SymGetModuleBase); \
|
||||
wxSYM_CALL_64(what, SymGetLineFromAddr); \
|
||||
wxSYM_CALL_64(what, EnumerateLoadedModules); \
|
||||
\
|
||||
wxSYM_CALL(what, SymGetOptions); \
|
||||
wxSYM_CALL(what, SymSetOptions); \
|
||||
wxSYM_CALL(what, SymInitialize); \
|
||||
wxSYM_CALL(what, SymFromAddr); \
|
||||
wxSYM_CALL(what, SymSetContext); \
|
||||
wxSYM_CALL(what, SymEnumSymbols); \
|
||||
wxSYM_CALL(what, SymGetTypeInfo); \
|
||||
wxSYM_CALL(what, SymCleanup); \
|
||||
#define wxSYM_CALL_ALWAYS_W(what, name) what(name ## W, name ## W)
|
||||
|
||||
#define wxSYM_CALL_ALTERNATIVES(what, name) \
|
||||
what(name, name); \
|
||||
what(name ## 64, name ## 64); \
|
||||
what(name ## W64, name ## W64)
|
||||
|
||||
#define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(what) \
|
||||
wxSYM_CALL_64(what, StackWalk); \
|
||||
wxSYM_CALL_64(what, SymFunctionTableAccess); \
|
||||
wxSYM_CALL_64(what, SymGetModuleBase); \
|
||||
\
|
||||
wxSYM_CALL(what, SymGetOptions); \
|
||||
wxSYM_CALL(what, SymSetOptions); \
|
||||
wxSYM_CALL(what, SymSetContext); \
|
||||
wxSYM_CALL(what, SymGetTypeInfo); \
|
||||
wxSYM_CALL(what, SymCleanup); \
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
@@ -209,10 +386,10 @@ public:
|
||||
static void LogError(const wxChar *func);
|
||||
|
||||
// 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
|
||||
static wxString GetSymbolName(PSYMBOL_INFO pSymInfo);
|
||||
static wxString GetSymbolName(wxPSYMBOL_INFO pSymInfo);
|
||||
|
||||
private:
|
||||
// dereference the given symbol, i.e. return symbol which is not a
|
||||
@@ -222,17 +399,20 @@ private:
|
||||
// dereferenced the 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,
|
||||
unsigned level);
|
||||
|
||||
static wxString DumpBaseType(BasicType bt, DWORD64 length, void *pVariable);
|
||||
|
||||
static wxString DumpUDT(PSYMBOL_INFO pSymInfo,
|
||||
static wxString DumpUDT(wxPSYMBOL_INFO pSymInfo,
|
||||
void *pVariable,
|
||||
unsigned level = 0);
|
||||
|
||||
static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp);
|
||||
static bool DoInit();
|
||||
};
|
||||
|
||||
#endif // wxUSE_DBGHELP
|
||||
|
@@ -14,8 +14,8 @@
|
||||
|
||||
// the exception handler which should be called from the exception filter
|
||||
//
|
||||
// it calsl wxApp::OnFatalException() if possible
|
||||
extern unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs);
|
||||
// it calls wxApp::OnFatalException() if wxTheApp object exists
|
||||
WXDLLIMPEXP_BASE unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs);
|
||||
|
||||
// helper macro for wxSEH_HANDLE
|
||||
#if defined(__BORLANDC__)
|
||||
|
@@ -19,6 +19,13 @@ struct _EXCEPTION_POINTERS;
|
||||
|
||||
// and these in dbghelp.h
|
||||
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
|
||||
@@ -52,7 +59,7 @@ public:
|
||||
GetParam(size_t n, wxString *type, wxString *name, wxString *value) const;
|
||||
|
||||
// callback used by OnGetParam(), don't call directly
|
||||
void OnParam(_SYMBOL_INFO *pSymInfo);
|
||||
void OnParam(wxSYMBOL_INFO *pSymInfo);
|
||||
|
||||
protected:
|
||||
virtual void OnGetName();
|
||||
|
@@ -17,14 +17,17 @@
|
||||
#include "wx/frame.h"
|
||||
#include "wx/icon.h"
|
||||
#include "wx/menu.h"
|
||||
#include "wx/choicdlg.h"
|
||||
#include "wx/msgdlg.h"
|
||||
#include "wx/button.h"
|
||||
#include "wx/dcclient.h"
|
||||
#include "wx/timer.h"
|
||||
|
||||
#include "wx/datetime.h"
|
||||
#include "wx/ffile.h"
|
||||
#include "wx/filename.h"
|
||||
#include "wx/debugrpt.h"
|
||||
#include "wx/dynlib.h"
|
||||
|
||||
#if !wxUSE_DEBUGREPORT
|
||||
#error "This sample can't be built without wxUSE_DEBUGREPORT"
|
||||
@@ -141,10 +144,12 @@ void foo(int n)
|
||||
|
||||
enum
|
||||
{
|
||||
DebugRpt_ListLoadedDLLs = 50,
|
||||
DebugRpt_Quit = wxID_EXIT,
|
||||
DebugRpt_Crash = 100,
|
||||
DebugRpt_Current,
|
||||
DebugRpt_Paint,
|
||||
DebugRpt_Timer,
|
||||
DebugRpt_Upload,
|
||||
DebugRpt_About = wxID_ABOUT
|
||||
};
|
||||
@@ -155,15 +160,28 @@ public:
|
||||
MyFrame();
|
||||
|
||||
private:
|
||||
void OnListLoadedDLLs(wxCommandEvent& event);
|
||||
void OnQuit(wxCommandEvent& event);
|
||||
void OnReportForCrash(wxCommandEvent& event);
|
||||
void OnReportForCurrent(wxCommandEvent& event);
|
||||
void OnReportPaint(wxCommandEvent& event);
|
||||
void OnReportTimer(wxCommandEvent& event);
|
||||
void OnReportUpload(wxCommandEvent& event);
|
||||
void OnAbout(wxCommandEvent& 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()
|
||||
int m_numLines;
|
||||
@@ -217,10 +235,12 @@ wxIMPLEMENT_APP(MyApp);
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
||||
EVT_MENU(DebugRpt_ListLoadedDLLs, MyFrame::OnListLoadedDLLs)
|
||||
EVT_MENU(DebugRpt_Quit, MyFrame::OnQuit)
|
||||
EVT_MENU(DebugRpt_Crash, MyFrame::OnReportForCrash)
|
||||
EVT_MENU(DebugRpt_Current, MyFrame::OnReportForCurrent)
|
||||
EVT_MENU(DebugRpt_Paint, MyFrame::OnReportPaint)
|
||||
EVT_MENU(DebugRpt_Timer, MyFrame::OnReportTimer)
|
||||
EVT_MENU(DebugRpt_Upload, MyFrame::OnReportUpload)
|
||||
EVT_MENU(DebugRpt_About, MyFrame::OnAbout)
|
||||
|
||||
@@ -236,6 +256,8 @@ MyFrame::MyFrame()
|
||||
SetIcon(wxICON(sample));
|
||||
|
||||
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"));
|
||||
|
||||
wxMenu *menuReport = new wxMenu;
|
||||
@@ -245,6 +267,8 @@ MyFrame::MyFrame()
|
||||
wxT("Create report for the current program context"));
|
||||
menuReport->Append(DebugRpt_Paint, wxT("Report for &paint handler\tCtrl-P"),
|
||||
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->AppendCheckItem(DebugRpt_Upload, wxT("Up&load debug report"),
|
||||
wxT("You need to configure a web server accepting debug report uploads to use this function"));
|
||||
@@ -263,6 +287,47 @@ MyFrame::MyFrame()
|
||||
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))
|
||||
{
|
||||
Close(true);
|
||||
@@ -291,6 +356,12 @@ void MyFrame::OnReportPaint(wxCommandEvent& WXUNUSED(event))
|
||||
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)
|
||||
{
|
||||
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
|
||||
// automatically
|
||||
#ifdef __WXMSW__
|
||||
report->AddFile(wxT("c:\\autoexec.bat"), wxT("DOS startup file"));
|
||||
#else
|
||||
report->AddFile(wxT("/etc/motd"), wxT("Message of the day"));
|
||||
#endif
|
||||
wxString windir;
|
||||
if ( !wxGetEnv("WINDIR", &windir) )
|
||||
windir = "C:\\Windows";
|
||||
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
|
||||
if ( wxDebugReportPreviewStd().Show(*report) )
|
||||
|
@@ -332,7 +332,7 @@ wxDebugReportDialog::wxDebugReportDialog(wxDebugReport& dbgrpt)
|
||||
|
||||
wxSizer *sizerPreview =
|
||||
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
|
||||
wxSizer *sizerFileBtns = new wxBoxSizer(wxVERTICAL);
|
||||
|
@@ -1,8 +1,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/msw/debughlp.cpp
|
||||
// Purpose: various Win32 debug helpers
|
||||
// Author: Vadim Zeitlin
|
||||
// Modified by:
|
||||
// Author: Vadim Zeitlin, Suzumizaki-kimitaka
|
||||
// Created: 2005-01-08 (extracted from crashrpt.cpp)
|
||||
// Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
|
||||
// Licence: wxWindows licence
|
||||
@@ -26,6 +25,8 @@
|
||||
|
||||
#if wxUSE_DBGHELP && wxUSE_DYNLIB_CLASS
|
||||
|
||||
#include "wx/scopedarray.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -34,6 +35,59 @@
|
||||
// ourselves to that many levels of embedded fields inside structs
|
||||
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
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -62,7 +116,8 @@ wxDO_FOR_ALL_SYM_FUNCS(DEFINE_SYM_FUNCTION);
|
||||
|
||||
// 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) \
|
||||
wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \
|
||||
@@ -73,15 +128,27 @@ static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp)
|
||||
return false; \
|
||||
}
|
||||
|
||||
wxDO_FOR_ALL_SYM_FUNCS(LOAD_SYM_FUNCTION);
|
||||
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(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;
|
||||
}
|
||||
|
||||
// called by Init() if we hadn't done this before
|
||||
static bool DoInit()
|
||||
/* static */
|
||||
bool wxDbgHelpDLL::DoInit()
|
||||
{
|
||||
wxDynamicLibrary dllDbgHelp(wxT("dbghelp.dll"), wxDL_VERBATIM);
|
||||
if ( dllDbgHelp.IsLoaded() )
|
||||
@@ -170,13 +237,13 @@ DoGetTypeInfo(DWORD64 base, ULONG ti, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
|
||||
|
||||
static inline
|
||||
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);
|
||||
}
|
||||
|
||||
static inline
|
||||
wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym)
|
||||
wxDbgHelpDLL::BasicType GetBasicType(wxPSYMBOL_INFO pSym)
|
||||
{
|
||||
wxDbgHelpDLL::BasicType bt;
|
||||
return DoGetTypeInfo(pSym, TI_GET_BASETYPE, &bt)
|
||||
@@ -185,7 +252,7 @@ wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym)
|
||||
}
|
||||
|
||||
/* static */
|
||||
wxString wxDbgHelpDLL::GetSymbolName(PSYMBOL_INFO pSym)
|
||||
wxString wxDbgHelpDLL::GetSymbolName(wxPSYMBOL_INFO pSym)
|
||||
{
|
||||
wxString s;
|
||||
|
||||
@@ -289,7 +356,7 @@ wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress)
|
||||
}
|
||||
|
||||
wxString
|
||||
wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
||||
wxDbgHelpDLL::DumpField(wxPSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
||||
{
|
||||
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
|
||||
SYMBOL_INFO sym = *pSym;
|
||||
wxSYMBOL_INFO sym = *pSym;
|
||||
if ( !DoGetTypeInfo(pSym, TI_GET_TYPEID, &sym.TypeIndex) )
|
||||
break;
|
||||
|
||||
@@ -387,7 +454,7 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
||||
}
|
||||
|
||||
/* static */ wxString
|
||||
wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
||||
wxDbgHelpDLL::DumpUDT(wxPSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
||||
{
|
||||
wxString s;
|
||||
|
||||
@@ -454,7 +521,7 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
||||
s << wxT(" {\n");
|
||||
|
||||
// Iterate through all children
|
||||
SYMBOL_INFO sym;
|
||||
wxSYMBOL_INFO sym;
|
||||
wxZeroMemory(sym);
|
||||
sym.ModBase = pSym->ModBase;
|
||||
for ( unsigned i = 0; i < dwChildrenCount; i++ )
|
||||
@@ -486,7 +553,7 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
|
||||
|
||||
/* static */
|
||||
wxDbgHelpDLL::SymbolTag
|
||||
wxDbgHelpDLL::DereferenceSymbol(PSYMBOL_INFO pSym, void **ppData)
|
||||
wxDbgHelpDLL::DereferenceSymbol(wxPSYMBOL_INFO pSym, void **ppData)
|
||||
{
|
||||
SymbolTag tag = SYMBOL_TAG_NULL;
|
||||
for ( ;; )
|
||||
@@ -523,10 +590,10 @@ wxDbgHelpDLL::DereferenceSymbol(PSYMBOL_INFO pSym, void **ppData)
|
||||
}
|
||||
|
||||
/* static */ wxString
|
||||
wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable)
|
||||
wxDbgHelpDLL::DumpSymbol(wxPSYMBOL_INFO pSym, void *pVariable)
|
||||
{
|
||||
wxString s;
|
||||
SYMBOL_INFO symDeref = *pSym;
|
||||
wxSYMBOL_INFO symDeref = *pSym;
|
||||
switch ( DereferenceSymbol(&symDeref, &pVariable) )
|
||||
{
|
||||
default:
|
||||
@@ -552,6 +619,322 @@ wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable)
|
||||
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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -77,15 +77,8 @@ public:
|
||||
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
|
||||
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 */
|
||||
BOOL CALLBACK
|
||||
wxDynamicLibraryDetailsCreator::EnumModulesProc(PCSTR name,
|
||||
DWORD_32_64 base,
|
||||
wxDynamicLibraryDetailsCreator::EnumModulesProc(const wxChar* name,
|
||||
DWORD64 base,
|
||||
ULONG size,
|
||||
void *data)
|
||||
{
|
||||
@@ -276,15 +269,9 @@ wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded()
|
||||
params.dlls = &dlls;
|
||||
params.verDLL = &verDLL;
|
||||
|
||||
// Note that the cast of EnumModulesProc is needed because the type of
|
||||
// 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
|
||||
if ( !wxDbgHelpDLL::CallEnumerateLoadedModules
|
||||
(
|
||||
::GetCurrentProcess(),
|
||||
(PENUMLOADED_MODULES_CALLBACK)
|
||||
wxDynamicLibraryDetailsCreator::EnumModulesProc,
|
||||
¶ms
|
||||
) )
|
||||
|
@@ -90,7 +90,7 @@ bool wxHeaderCtrl::Create(wxWindow *parent,
|
||||
// use 0 here but this starts to look ugly)
|
||||
if ( wxApp::GetComCtl32Version() >= 600 )
|
||||
{
|
||||
Header_SetBitmapMargin(GetHwnd(), ::GetSystemMetrics(SM_CXEDGE));
|
||||
(void)Header_SetBitmapMargin(GetHwnd(), ::GetSystemMetrics(SM_CXEDGE));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -237,7 +237,8 @@ void wxHeaderCtrl::DoUpdate(unsigned int idx)
|
||||
if ( !m_isHidden[idx] )
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
@@ -252,7 +253,8 @@ void wxHeaderCtrl::DoUpdate(unsigned int idx)
|
||||
else // and it was shown before as well
|
||||
{
|
||||
// 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);
|
||||
|
@@ -505,7 +505,7 @@ bool wxListCtrl::SetForegroundColour(const wxColour& col)
|
||||
if ( !wxWindow::SetForegroundColour(col) )
|
||||
return false;
|
||||
|
||||
ListView_SetTextColor(GetHwnd(), wxColourToRGB(col));
|
||||
SetTextColour(col);
|
||||
|
||||
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
|
||||
// background
|
||||
COLORREF color = wxColourToRGB(col);
|
||||
ListView_SetBkColor(GetHwnd(), color);
|
||||
ListView_SetTextBkColor(GetHwnd(), color);
|
||||
if ( !ListView_SetBkColor(GetHwnd(), color) )
|
||||
wxLogLastError(wxS("ListView_SetBkColor()"));
|
||||
if ( !ListView_SetTextBkColor(GetHwnd(), color) )
|
||||
wxLogLastError(wxS("ListView_SetTextBkColor()"));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -936,7 +938,7 @@ bool wxListCtrl::SetItemState(long item, long state, long stateMask)
|
||||
// to, so do it explicitly
|
||||
if ( changingFocus && !HasFlag(wxLC_SINGLE_SEL) )
|
||||
{
|
||||
ListView_SetSelectionMark(GetHwnd(), item);
|
||||
(void)ListView_SetSelectionMark(GetHwnd(), item);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1225,7 +1227,8 @@ wxColour wxListCtrl::GetTextColour() const
|
||||
// Sets the text colour of the listview
|
||||
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
|
||||
@@ -2656,7 +2659,8 @@ bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
|
||||
it.iSubItem = col;
|
||||
it.pszText = text;
|
||||
it.cchTextMax = WXSIZEOF(text);
|
||||
ListView_GetItem(hwndList, &it);
|
||||
if ( !ListView_GetItem(hwndList, &it) )
|
||||
return false;
|
||||
|
||||
HIMAGELIST himl = ListView_GetImageList(hwndList, LVSIL_SMALL);
|
||||
if ( himl && ImageList_GetImageCount(himl) )
|
||||
@@ -3086,7 +3090,8 @@ void wxListCtrl::RefreshItem(long item)
|
||||
|
||||
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);
|
||||
|
||||
TabCtrl_SetCurSel(GetHwnd(), nPage);
|
||||
(void)TabCtrl_SetCurSel(GetHwnd(), nPage);
|
||||
|
||||
SendPageChangedEvent(selectionOld, nPage);
|
||||
}
|
||||
@@ -406,7 +406,7 @@ int wxNotebook::ChangeSelection(size_t nPage)
|
||||
|
||||
if ( m_selection == wxNOT_FOUND || nPage != (size_t)m_selection )
|
||||
{
|
||||
TabCtrl_SetCurSel(GetHwnd(), nPage);
|
||||
(void)TabCtrl_SetCurSel(GetHwnd(), nPage);
|
||||
|
||||
UpdateSelection(nPage);
|
||||
}
|
||||
@@ -508,7 +508,7 @@ wxRect wxNotebook::GetPageSize() const
|
||||
// The value of 20 is chosen arbitrarily but seems to work
|
||||
if ( rc.right > 20 && rc.bottom > 20 )
|
||||
{
|
||||
TabCtrl_AdjustRect(GetHwnd(), false, &rc);
|
||||
(void)TabCtrl_AdjustRect(GetHwnd(), false, &rc);
|
||||
|
||||
wxCopyRECTToRect(rc, r);
|
||||
}
|
||||
@@ -525,7 +525,7 @@ void wxNotebook::SetPageSize(const wxSize& size)
|
||||
rc.right = size.x;
|
||||
rc.bottom = size.y;
|
||||
|
||||
TabCtrl_AdjustRect(GetHwnd(), true, &rc);
|
||||
(void)TabCtrl_AdjustRect(GetHwnd(), true, &rc);
|
||||
|
||||
// and now set it
|
||||
SetSize(rc.right - rc.left, rc.bottom - rc.top);
|
||||
@@ -552,9 +552,11 @@ wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
|
||||
if ( GetPageCount() > 0 )
|
||||
{
|
||||
RECT rect;
|
||||
TabCtrl_GetItemRect(GetHwnd(), 0, &rect);
|
||||
tabSize.x = rect.right - rect.left;
|
||||
tabSize.y = rect.bottom - rect.top;
|
||||
if ( TabCtrl_GetItemRect(GetHwnd(), 0, &rect) )
|
||||
{
|
||||
tabSize.x = rect.right - rect.left;
|
||||
tabSize.y = rect.bottom - rect.top;
|
||||
}
|
||||
}
|
||||
|
||||
const int rows = GetRowCount();
|
||||
@@ -601,7 +603,8 @@ wxNotebookPage *wxNotebook::DoRemovePage(size_t nPage)
|
||||
// selected page is visible and others are hidden:
|
||||
pageRemoved->Show(false);
|
||||
|
||||
TabCtrl_DeleteItem(GetHwnd(), nPage);
|
||||
if ( !TabCtrl_DeleteItem(GetHwnd(), nPage) )
|
||||
wxLogLastError(wxS("TabCtrl_DeleteItem()"));
|
||||
|
||||
if ( m_pages.IsEmpty() )
|
||||
{
|
||||
@@ -654,7 +657,8 @@ bool wxNotebook::DeleteAllPages()
|
||||
|
||||
m_pages.Clear();
|
||||
|
||||
TabCtrl_DeleteAllItems(GetHwnd());
|
||||
if ( !TabCtrl_DeleteAllItems(GetHwnd()) )
|
||||
wxLogLastError(wxS("TabCtrl_DeleteAllItems()"));
|
||||
|
||||
m_selection = wxNOT_FOUND;
|
||||
|
||||
@@ -986,7 +990,7 @@ void wxNotebook::OnSize(wxSizeEvent& event)
|
||||
UpdateBgBrush();
|
||||
#endif // wxUSE_UXTHEME
|
||||
|
||||
TabCtrl_AdjustRect(GetHwnd(), false, &rc);
|
||||
(void)TabCtrl_AdjustRect(GetHwnd(), false, &rc);
|
||||
|
||||
int width = rc.right - rc.left,
|
||||
height = rc.bottom - rc.top;
|
||||
|
@@ -50,29 +50,16 @@ void wxStackFrame::OnGetName()
|
||||
m_hasName = true;
|
||||
|
||||
// get the name of the function for this stack frame entry
|
||||
static const size_t MAX_NAME_LEN = 1024;
|
||||
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
|
||||
if ( !wxDbgHelpDLL::CallSymFromAddr
|
||||
(
|
||||
::GetCurrentProcess(),
|
||||
GetSymAddr(),
|
||||
&symDisplacement,
|
||||
pSymbol
|
||||
&m_offset,
|
||||
&m_name
|
||||
) )
|
||||
{
|
||||
wxDbgHelpDLL::LogError(wxT("SymFromAddr"));
|
||||
return;
|
||||
}
|
||||
|
||||
m_name = wxString::FromAscii(pSymbol->Name);
|
||||
m_offset = symDisplacement;
|
||||
}
|
||||
|
||||
void wxStackFrame::OnGetLocation()
|
||||
@@ -82,25 +69,11 @@ void wxStackFrame::OnGetLocation()
|
||||
|
||||
m_hasLocation = true;
|
||||
|
||||
// get the source line for this stack frame entry
|
||||
IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
|
||||
DWORD dwLineDisplacement;
|
||||
if ( !wxDbgHelpDLL::SymGetLineFromAddr
|
||||
(
|
||||
::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;
|
||||
// get the source line for this stack frame entry ignoring possible errors
|
||||
// (it's normal that we don't have source info for some symbols, e.g. all
|
||||
// those from the system DLLs)
|
||||
wxDbgHelpDLL::CallSymGetLineFromAddr(::GetCurrentProcess(), GetSymAddr(),
|
||||
&m_filename, &m_line);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -125,11 +98,10 @@ wxStackFrame::GetParam(size_t n,
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxStackFrame::OnParam(PSYMBOL_INFO pSymInfo)
|
||||
void wxStackFrame::OnParam(wxSYMBOL_INFO *pSymInfo)
|
||||
{
|
||||
m_paramTypes.Add(wxEmptyString);
|
||||
|
||||
m_paramNames.Add(wxString::FromAscii(pSymInfo->Name));
|
||||
m_paramNames.Add(pSymInfo->Name);
|
||||
|
||||
// if symbol information is corrupted and we crash, the exception is going
|
||||
// to be ignored when we're called from WalkFromException() because of the
|
||||
@@ -158,7 +130,7 @@ void wxStackFrame::OnParam(PSYMBOL_INFO pSymInfo)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -195,11 +167,10 @@ void wxStackFrame::OnGetParam()
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !wxDbgHelpDLL::SymEnumSymbols
|
||||
if ( !wxDbgHelpDLL::CallSymEnumSymbols
|
||||
(
|
||||
::GetCurrentProcess(),
|
||||
NULL, // DLL base: use current context
|
||||
NULL, // no mask, get all symbols
|
||||
EnumSymbolsProc, // callback
|
||||
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
|
||||
const HANDLE hProcess = ::GetCurrentProcess();
|
||||
|
||||
if ( !wxDbgHelpDLL::SymInitialize
|
||||
if ( !wxDbgHelpDLL::CallSymInitialize
|
||||
(
|
||||
hProcess,
|
||||
NULL, // use default symbol search path
|
||||
TRUE // load symbols for all loaded modules
|
||||
) )
|
||||
{
|
||||
@@ -382,7 +352,7 @@ wxStackFrame::GetParam(size_t WXUNUSED(n),
|
||||
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
|
||||
// would do by default (TreeView_SelectItem unselects the
|
||||
// focused item)
|
||||
TreeView_SelectItem(hwndTV, 0);
|
||||
(void)TreeView_SelectItem(hwndTV, 0);
|
||||
SelectItem(hwndTV, htFocus);
|
||||
}
|
||||
|
||||
TreeView_SelectItem(hwndTV, htItem);
|
||||
(void)TreeView_SelectItem(hwndTV, htItem);
|
||||
|
||||
if ( !wasSelected )
|
||||
{
|
||||
@@ -359,7 +359,7 @@ static bool SetFocus(HWND hwndTV, HTREEITEM htItem)
|
||||
bool wasFocusSelected = IsItemSelected(hwndTV, htFocus);
|
||||
|
||||
// just clear the focus
|
||||
TreeView_SelectItem(hwndTV, 0);
|
||||
(void)TreeView_SelectItem(hwndTV, 0);
|
||||
|
||||
if ( wasFocusSelected )
|
||||
{
|
||||
@@ -873,7 +873,7 @@ unsigned int wxTreeCtrl::GetIndent() const
|
||||
|
||||
void wxTreeCtrl::SetIndent(unsigned int indent)
|
||||
{
|
||||
TreeView_SetIndent(GetHwnd(), indent);
|
||||
(void)TreeView_SetIndent(GetHwnd(), indent);
|
||||
}
|
||||
|
||||
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") );
|
||||
|
||||
// no error return
|
||||
TreeView_EnsureVisible(GetHwnd(), HITEM(item));
|
||||
(void)TreeView_EnsureVisible(GetHwnd(), HITEM(item));
|
||||
}
|
||||
|
||||
void wxTreeCtrl::ScrollTo(const wxTreeItemId& item)
|
||||
@@ -2031,7 +2031,8 @@ wxTextCtrl *wxTreeCtrl::EditLabel(const wxTreeItemId& item,
|
||||
// End label editing, optionally cancelling the edit
|
||||
void wxTreeCtrl::DoEndEditLabel(bool discardChanges)
|
||||
{
|
||||
TreeView_EndEditLabelNow(GetHwnd(), discardChanges);
|
||||
if ( !TreeView_EndEditLabelNow(GetHwnd(), discardChanges) )
|
||||
wxLogLastError(wxS("TreeView_EndEditLabelNow()"));
|
||||
|
||||
DeleteTextCtrl();
|
||||
}
|
||||
@@ -2170,7 +2171,8 @@ void wxTreeCtrl::SortChildren(const wxTreeItemId& item)
|
||||
// OnCompareItems
|
||||
if ( GetClassInfo() == wxCLASSINFO(wxTreeCtrl) )
|
||||
{
|
||||
TreeView_SortChildren(GetHwnd(), HITEM(item), 0);
|
||||
if ( !TreeView_SortChildren(GetHwnd(), HITEM(item), 0) )
|
||||
wxLogLastError(wxS("TreeView_SortChildren()"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2178,7 +2180,8 @@ void wxTreeCtrl::SortChildren(const wxTreeItemId& item)
|
||||
tvSort.hParent = HITEM(item);
|
||||
tvSort.lpfnCompare = wxTreeSortHelper::Compare;
|
||||
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.mask = TVIF_STATE | TVIF_PARAM;
|
||||
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.itemNew.lParam = tviAux.lParam;
|
||||
tv.ptDrag.x = x;
|
||||
tv.ptDrag.y = y;
|
||||
|
||||
tv.ptDrag.x = x;
|
||||
tv.ptDrag.y = y;
|
||||
// do it before SendMessage() call below to avoid
|
||||
// reentrancies here if there is another WM_MOUSEMOVE
|
||||
// in the queue already
|
||||
m_htClickedItem.Unset();
|
||||
|
||||
// do it before SendMessage() call below to avoid
|
||||
// reentrancies here if there is another WM_MOUSEMOVE
|
||||
// in the queue already
|
||||
m_htClickedItem.Unset();
|
||||
::SendMessage(GetHwndOf(GetParent()), WM_NOTIFY,
|
||||
tv.hdr.idFrom, (LPARAM)&tv );
|
||||
|
||||
::SendMessage(GetHwndOf(GetParent()), WM_NOTIFY,
|
||||
tv.hdr.idFrom, (LPARAM)&tv );
|
||||
|
||||
// don't pass it to the default window proc, it would
|
||||
// start dragging again
|
||||
processed = true;
|
||||
// don't pass it to the default window proc, it would
|
||||
// start dragging again
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // __WXWINCE__
|
||||
@@ -3028,7 +3032,8 @@ wxTreeCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
// highlight the item as target (hiding drag image is
|
||||
// necessary - otherwise the display will be corrupted)
|
||||
m_dragImage->Hide();
|
||||
TreeView_SelectDropTarget(GetHwnd(), htItem);
|
||||
if ( !TreeView_SelectDropTarget(GetHwnd(), htItem) )
|
||||
wxLogLastError(wxS("TreeView_SelectDropTarget()"));
|
||||
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
|
||||
// are selected simultaneously which is quite weird
|
||||
TreeView_SelectDropTarget(GetHwnd(), 0);
|
||||
if ( !TreeView_SelectDropTarget(GetHwnd(), 0) )
|
||||
wxLogLastError(wxS("TreeView_SelectDropTarget(0)"));
|
||||
}
|
||||
#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
|
||||
// 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) )
|
||||
{
|
||||
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_RIGHT_CLICK;
|
||||
|
||||
|
@@ -82,6 +82,7 @@
|
||||
#include "wx/msw/private.h"
|
||||
#include "wx/msw/private/keyboard.h"
|
||||
#include "wx/msw/dcclient.h"
|
||||
#include "wx/msw/seh.h"
|
||||
#include "wx/private/textmeasure.h"
|
||||
|
||||
#if wxUSE_TOOLTIPS
|
||||
@@ -2757,10 +2758,21 @@ wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
LRESULT rc;
|
||||
|
||||
if ( wnd && wxGUIEventLoop::AllowProcessing(wnd) )
|
||||
rc = wnd->MSWWindowProc(message, wParam, lParam);
|
||||
else
|
||||
rc = ::DefWindowProc(hWnd, message, wParam, lParam);
|
||||
// We have to catch unhandled Win32 exceptions here because otherwise they
|
||||
// would be simply lost if we're called from a kernel callback (as it
|
||||
// happens when we process WM_PAINT, for example under WOW64: the 32 bit
|
||||
// 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;
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#if wxUSE_STC
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/math.h"
|
||||
#include "wx/menu.h"
|
||||
#include "wx/dcmemory.h"
|
||||
#include "wx/settings.h"
|
||||
@@ -50,8 +51,8 @@ Point Point::FromLong(long lpoint) {
|
||||
}
|
||||
|
||||
wxRect wxRectFromPRectangle(PRectangle prc) {
|
||||
wxRect r(prc.left, prc.top,
|
||||
prc.Width(), prc.Height());
|
||||
wxRect r(wxRound(prc.left), wxRound(prc.top),
|
||||
wxRound(prc.Width()), wxRound(prc.Height()));
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -140,7 +141,7 @@ void Font::Create(const FontParameters &fp) {
|
||||
else
|
||||
weight = wxFONTWEIGHT_NORMAL;
|
||||
|
||||
wxFont font(fp.size,
|
||||
wxFont font(wxRound(fp.size),
|
||||
wxFONTFAMILY_DEFAULT,
|
||||
fp.italic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL,
|
||||
weight,
|
||||
@@ -320,8 +321,8 @@ void SurfaceImpl::Polygon(Point *pts, int npts, ColourDesired fore, ColourDesire
|
||||
wxPoint *p = new wxPoint[npts];
|
||||
|
||||
for (int i=0; i<npts; i++) {
|
||||
p[i].x = pts[i].x;
|
||||
p[i].y = pts[i].y;
|
||||
p[i].x = wxRound(pts[i].x);
|
||||
p[i].y = wxRound(pts[i].y);
|
||||
}
|
||||
hdc->DrawPolygon(npts, p);
|
||||
delete [] p;
|
||||
@@ -501,7 +502,7 @@ void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
|
||||
wxRect r = wxRectFromPRectangle(rc);
|
||||
hdc->Blit(r.x, r.y, r.width, r.height,
|
||||
((SurfaceImpl&)surfaceSource).hdc,
|
||||
from.x, from.y, wxCOPY);
|
||||
wxRound(from.x), wxRound(from.y), wxCOPY);
|
||||
}
|
||||
|
||||
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
|
||||
// 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,
|
||||
@@ -527,7 +528,7 @@ void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, XYPOSITION ybase,
|
||||
hdc->SetClippingRegion(wxRectFromPRectangle(rc));
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
// 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);
|
||||
}
|
||||
@@ -784,7 +785,7 @@ PRectangle Window::GetMonitorRect(Point pt) {
|
||||
if (! wid) return PRectangle();
|
||||
#if wxUSE_DISPLAY
|
||||
// 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);
|
||||
rect = dpy.GetGeometry();
|
||||
#else
|
||||
@@ -1428,7 +1429,7 @@ void Menu::Destroy() {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
@@ -24,6 +24,7 @@
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/scrolbar.h"
|
||||
#include "wx/math.h"
|
||||
#include "wx/menu.h"
|
||||
#include "wx/timer.h"
|
||||
#endif // WX_PRECOMP
|
||||
@@ -433,7 +434,7 @@ bool ScintillaWX::ModifyScrollBars(int nMax, int nPage) {
|
||||
horizEnd = 0;
|
||||
if (!horizontalScrollBarVisible || Wrapping())
|
||||
horizEnd = 0;
|
||||
int pageWidth = rcText.Width();
|
||||
int pageWidth = wxRound(rcText.Width());
|
||||
|
||||
if (stc->m_hScrollBar == NULL) { // Use built-in scrollbar
|
||||
int sbMax = stc->GetScrollRange(wxHORIZONTAL);
|
||||
@@ -664,7 +665,7 @@ void ScintillaWX::UpdateSystemCaret() {
|
||||
CreateSystemCaret();
|
||||
}
|
||||
Point pos = PointMainCaret();
|
||||
::SetCaretPos(pos.x, pos.y);
|
||||
::SetCaretPos(wxRound(pos.x), wxRound(pos.y));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -842,7 +843,7 @@ void ScintillaWX::FullPaintDC(wxDC* dc) {
|
||||
void ScintillaWX::DoHScroll(int type, int pos) {
|
||||
int xPos = xOffset;
|
||||
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)
|
||||
xPos -= H_SCROLL_STEP;
|
||||
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) {
|
||||
xPos += pageWidth;
|
||||
if (xPos > scrollWidth - rcText.Width()) {
|
||||
xPos = scrollWidth - rcText.Width();
|
||||
xPos = wxRound(scrollWidth - rcText.Width());
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
if (axis == wxMOUSE_WHEEL_HORIZONTAL) {
|
||||
wheelHRotation += rotation * (columnsPerAction * vs.spaceWidth);
|
||||
wheelHRotation += wxRound(rotation * (columnsPerAction * vs.spaceWidth));
|
||||
pixels = wheelHRotation / delta;
|
||||
wheelHRotation -= pixels * delta;
|
||||
if (pixels != 0) {
|
||||
xPos += pixels;
|
||||
PRectangle rcText = GetTextRectangle();
|
||||
if (xPos > scrollWidth - rcText.Width()) {
|
||||
xPos = scrollWidth - rcText.Width();
|
||||
xPos = wxRound(scrollWidth - rcText.Width());
|
||||
}
|
||||
HorizontalScrollTo(xPos);
|
||||
}
|
||||
@@ -1190,7 +1191,7 @@ void ScintillaWX::DoScrollToLine(int line) {
|
||||
|
||||
|
||||
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
|
||||
|
@@ -54,12 +54,6 @@
|
||||
|
||||
#include "tiffiop.h"
|
||||
|
||||
typedef union fd_as_handle_union
|
||||
{
|
||||
int fd;
|
||||
thandle_t h;
|
||||
} fd_as_handle_union_t;
|
||||
|
||||
static tmsize_t
|
||||
_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 m;
|
||||
fSuppressMap=0;
|
||||
fd_as_handle_union_t fdh;
|
||||
fdh.fd = ifd;
|
||||
for (m=0; mode[m]!=0; m++)
|
||||
{
|
||||
if (mode[m]=='u')
|
||||
@@ -218,7 +220,7 @@ TIFFFdOpen(int ifd, const char* name, const char* mode)
|
||||
break;
|
||||
}
|
||||
}
|
||||
tif = TIFFClientOpen(name, mode, (thandle_t)ifd,
|
||||
tif = TIFFClientOpen(name, mode, fdh.h,
|
||||
_tiffReadProc, _tiffWriteProc,
|
||||
_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
|
||||
fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
|
||||
@@ -237,7 +239,7 @@ TIFF*
|
||||
TIFFOpen(const char* name, const char* mode)
|
||||
{
|
||||
static const char module[] = "TIFFOpen";
|
||||
thandle_t fd;
|
||||
fd_as_handle_union_t fdh;
|
||||
int m;
|
||||
DWORD dwMode;
|
||||
TIFF* tif;
|
||||
@@ -253,19 +255,19 @@ TIFFOpen(const char* name, const char* mode)
|
||||
default: return ((TIFF*)0);
|
||||
}
|
||||
|
||||
fd = (thandle_t)CreateFileA(name,
|
||||
fdh.h = CreateFileA(name,
|
||||
(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE),
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
|
||||
(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (fd == INVALID_HANDLE_VALUE) {
|
||||
if (fdh.h == INVALID_HANDLE_VALUE) {
|
||||
TIFFErrorExt(0, module, "%s: Cannot open", name);
|
||||
return ((TIFF *)0);
|
||||
}
|
||||
|
||||
tif = TIFFFdOpen((int)fd, name, mode);
|
||||
tif = TIFFFdOpen(fdh.fd, name, mode);
|
||||
if(!tif)
|
||||
CloseHandle(fd);
|
||||
CloseHandle(fdh.h);
|
||||
return tif;
|
||||
}
|
||||
|
||||
@@ -276,7 +278,7 @@ TIFF*
|
||||
TIFFOpenW(const wchar_t* name, const char* mode)
|
||||
{
|
||||
static const char module[] = "TIFFOpenW";
|
||||
thandle_t fd;
|
||||
fd_as_handle_union_t fdh;
|
||||
int m;
|
||||
DWORD dwMode;
|
||||
int mbsize;
|
||||
@@ -294,12 +296,12 @@ TIFFOpenW(const wchar_t* name, const char* mode)
|
||||
default: return ((TIFF*)0);
|
||||
}
|
||||
|
||||
fd = (thandle_t)CreateFileW(name,
|
||||
fdh.h = CreateFileW(name,
|
||||
(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE),
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
|
||||
(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (fd == INVALID_HANDLE_VALUE) {
|
||||
if (fdh.h == INVALID_HANDLE_VALUE) {
|
||||
TIFFErrorExt(0, module, "%S: Cannot open", name);
|
||||
return ((TIFF *)0);
|
||||
}
|
||||
@@ -318,10 +320,10 @@ TIFFOpenW(const wchar_t* name, const char* mode)
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
tif = TIFFFdOpen((int)fd,
|
||||
tif = TIFFFdOpen(fdh.fd,
|
||||
(mbname != NULL) ? mbname : "<unknown>", mode);
|
||||
if(!tif)
|
||||
CloseHandle(fd);
|
||||
CloseHandle(fdh.h);
|
||||
|
||||
_TIFFfree(mbname);
|
||||
|
||||
|
@@ -77,6 +77,17 @@ typedef struct client_info {
|
||||
char *name;
|
||||
} 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.
|
||||
* these are depriciated and provided only for backwards compatibility
|
||||
|
Reference in New Issue
Block a user