This commit is contained in:
Paul Cornett
2015-07-27 10:35:01 -07:00
19 changed files with 851 additions and 199 deletions

View File

@@ -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).

View File

@@ -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

View File

@@ -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__)

View File

@@ -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();

View File

@@ -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) )

View File

@@ -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);

View File

@@ -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
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -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,
&params &params
) ) ) )

View File

@@ -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);

View File

@@ -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"));
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -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;

View File

@@ -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))
{ {
} }

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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();
} }

View File

@@ -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

View File

@@ -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)
{ {

View File

@@ -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);

View File

@@ -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