diff --git a/docs/changes.txt b/docs/changes.txt index 4079463a44..8707982594 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -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). diff --git a/include/wx/msw/debughlp.h b/include/wx/msw/debughlp.h index 3d94ee2168..d63a213cb9 100644 --- a/include/wx/msw/debughlp.h +++ b/include/wx/msw/debughlp.h @@ -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 // 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 diff --git a/include/wx/msw/seh.h b/include/wx/msw/seh.h index d00efd4962..7c3abba4e4 100644 --- a/include/wx/msw/seh.h +++ b/include/wx/msw/seh.h @@ -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__) diff --git a/include/wx/msw/stackwalk.h b/include/wx/msw/stackwalk.h index 6ff467205e..e068ea2d95 100644 --- a/include/wx/msw/stackwalk.h +++ b/include/wx/msw/stackwalk.h @@ -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(); diff --git a/samples/debugrpt/debugrpt.cpp b/samples/debugrpt/debugrpt.cpp index 235eafc227..48b69a6d70 100644 --- a/samples/debugrpt/debugrpt.cpp +++ b/samples/debugrpt/debugrpt.cpp @@ -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(static_cast(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) ) diff --git a/src/generic/dbgrptg.cpp b/src/generic/dbgrptg.cpp index 30f72a3a07..7651c00700 100644 --- a/src/generic/dbgrptg.cpp +++ b/src/generic/dbgrptg.cpp @@ -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); diff --git a/src/msw/debughlp.cpp b/src/msw/debughlp.cpp index 161a532933..592595d4a5 100644 --- a/src/msw/debughlp.cpp +++ b/src/msw/debughlp.cpp @@ -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 // 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 +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 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(static_cast(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(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(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(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 infoW; + if ( SymFromAddrW(hProcess, Address, &dwDisplacement, infoW) ) + { + *offset = dwDisplacement; + *name = infoW->Name; + return TRUE; + } + } +#endif // UNICODE + + if ( SymFromAddr ) + { + VarSizedStruct 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 lineW64; + if ( SymGetLineFromAddrW64(hProcess, dwAddr, &dwDisplacement, &lineW64) ) + { + *fileName = lineW64.FileName; + *line = lineW64.LineNumber; + return TRUE; + } + } +#endif // UNICODE + + if ( SymGetLineFromAddr64 ) + { + SizedStruct line64; + if ( SymGetLineFromAddr64(hProcess, dwAddr, &dwDisplacement, &line64) ) + { + *fileName = line64.FileName; + *line = line64.LineNumber; + return TRUE; + } + } + + if ( SymGetLineFromAddr ) + { + SizedStruct 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(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 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 // ---------------------------------------------------------------------------- diff --git a/src/msw/dlmsw.cpp b/src/msw/dlmsw.cpp index 9bdbae9c13..0118a3ff22 100644 --- a/src/msw/dlmsw.cpp +++ b/src/msw/dlmsw.cpp @@ -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 ) ) diff --git a/src/msw/headerctrl.cpp b/src/msw/headerctrl.cpp index 1fdebf74d8..359324b439 100644 --- a/src/msw/headerctrl.cpp +++ b/src/msw/headerctrl.cpp @@ -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); diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index 1e53d52128..29f9986bf0 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -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")); } // ---------------------------------------------------------------------------- diff --git a/src/msw/notebook.cpp b/src/msw/notebook.cpp index b3f42c5118..68a6ef46c9 100644 --- a/src/msw/notebook.cpp +++ b/src/msw/notebook.cpp @@ -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; diff --git a/src/msw/stackwalk.cpp b/src/msw/stackwalk.cpp index f9c8ca986e..4b59c4a381 100644 --- a/src/msw/stackwalk.cpp +++ b/src/msw/stackwalk.cpp @@ -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(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)) { } diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index 8bc7a6ac09..3112e1eb93 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -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; diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 85340d781f..a29b0b75bd 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -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; } diff --git a/src/stc/PlatWX.cpp b/src/stc/PlatWX.cpp index dbd2397134..3e44e8db78 100644 --- a/src/stc/PlatWX.cpp +++ b/src/stc/PlatWX.cpp @@ -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; iDrawPolygon(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(); } diff --git a/src/stc/ScintillaWX.cpp b/src/stc/ScintillaWX.cpp index a6c7d01aef..b639c0320d 100644 --- a/src/stc/ScintillaWX.cpp +++ b/src/stc/ScintillaWX.cpp @@ -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 diff --git a/src/tiff/libtiff/tif_unix.c b/src/tiff/libtiff/tif_unix.c index 5ae1934103..1db40cdfd0 100644 --- a/src/tiff/libtiff/tif_unix.c +++ b/src/tiff/libtiff/tif_unix.c @@ -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) { diff --git a/src/tiff/libtiff/tif_win32.c b/src/tiff/libtiff/tif_win32.c index b64dd8d5cf..479860c8d0 100644 --- a/src/tiff/libtiff/tif_win32.c +++ b/src/tiff/libtiff/tif_win32.c @@ -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 : "", mode); if(!tif) - CloseHandle(fd); + CloseHandle(fdh.h); _TIFFfree(mbname); diff --git a/src/tiff/libtiff/tiffiop.h b/src/tiff/libtiff/tiffiop.h index 3d9551a80b..748ed4598a 100644 --- a/src/tiff/libtiff/tiffiop.h +++ b/src/tiff/libtiff/tiffiop.h @@ -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