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

View File

@@ -1,8 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
// Name: wx/msw/debughlp.h
// Purpose: wraps dbghelp.h standard file
// Author: Vadim Zeitlin
// Modified by:
// Author: Vadim Zeitlin, Suzumizaki-kimitaka
// Created: 2005-01-08 (extracted from msw/crashrpt.cpp)
// Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
// Licence: wxWindows licence
@@ -19,12 +18,19 @@
#endif // __WXWINCE__
#include "wx/msw/private.h"
// wxUSE_DBGHELP can be predefined as 0 to avoid the use of dbghelp.dll if this
// is undesirable for some reason.
// wxUSE_DBGHELP can be predefined on the compiler command line to force using
// dbghelp.dll even if it's not detected or, on the contrary, avoid using even
// if it's available.
#ifndef wxUSE_DBGHELP
// The only compiler which is known to have the necessary headers is MSVC.
#ifdef __VISUALC__
#define wxUSE_DBGHELP 1
// MSVC7.1 shipped with API v9 and we don't support anything earlier
// anyhow.
#if API_VERSION_NUMBER >= 9
#define wxUSE_DBGHELP 1
#else
#define wxUSE_DBGHELP 0
#endif
#else
#define wxUSE_DBGHELP 0
#endif
@@ -32,6 +38,117 @@
#if wxUSE_DBGHELP
/*
The table below shows which functions are exported by dbghelp.dll.
On 64 bit Windows, there seems to be no difference between 32bit dll and 64bit
one. Vista-64 and Win8-64 look the same, but "Ex" and "ExW" versions exist only
in Windows 8.
Note that SymGetLineFromAddrW and EnumerateLoadedModulesW DON'T exist at all.
function | Windows | XP-32 Vista-64 Win8-64
SymEnumSymbolsW n/a v v
SymFromAddrW n/a v v
SymInitializeW n/a v v
SymEnumSymbols v v v
SymFromAddr v v v
SymInitialize v v v
SymGetLineFromAddrW64 n/a v v
SymGetLineFromAddr64 v v v
SymGetLineFromAddrW n/a n/a n/a
SymGetLineFromAddr v v v
EnumerateLoadedModulesW64 n/a v v
EnumerateLoadedModules64 v v v
EnumerateLoadedModulesW n/a n/a n/a
EnumerateLoadedModules v v v
*/
// It's not really clear whether API v10 is used by anything as VC8 still used
// v9, just as MSVC7.1, while VC9 already used v11, but provide support for it
// just in case.
#if API_VERSION_NUMBER < 10/*{{{*/
typedef BOOL
(CALLBACK *PENUMLOADED_MODULES_CALLBACKW64)(PWSTR ModuleName,
DWORD64 ModuleBase,
ULONG ModuleSize,
PVOID UserContext);
typedef struct _IMAGEHLP_LINEW64
{
DWORD SizeOfStruct;
PVOID Key;
DWORD LineNumber;
PWSTR FileName;
DWORD64 Address;
} IMAGEHLP_LINEW64, *PIMAGEHLP_LINEW64;
typedef struct _SYMBOL_INFOW
{
ULONG SizeOfStruct;
ULONG TypeIndex;
ULONG64 Reserved[2];
ULONG Index;
ULONG Size;
ULONG64 ModBase;
ULONG Flags;
ULONG64 Value;
ULONG64 Address;
ULONG Register;
ULONG Scope;
ULONG Tag;
ULONG NameLen;
ULONG MaxNameLen;
WCHAR Name[1];
} SYMBOL_INFOW, *PSYMBOL_INFOW;
typedef BOOL
(CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACKW)(PSYMBOL_INFOW pSymInfo,
ULONG SymbolSize,
PVOID UserContext);
typedef BOOL
(CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)(PSYMBOL_INFO pSymInfo,
ULONG SymbolSize,
PVOID UserContext);
#endif // API_VERSION_NUMBER < 10/*}}}*/
// wx-prefixed types map to either the ANSI or Unicode ("W") version depending
// on the build of wx itself.
#ifdef UNICODE
#define wxPSYM_ENUMERATESYMBOLS_CALLBACK PSYM_ENUMERATESYMBOLS_CALLBACKW
#else // !UNICODE
#define wxPSYM_ENUMERATESYMBOLS_CALLBACK PSYM_ENUMERATESYMBOLS_CALLBACK
#endif // UNICODE/!UNICODE
// This one could be already defined by wx/msw/stackwalk.h
#ifndef wxSYMBOL_INFO
#ifdef UNICODE
#define wxSYMBOL_INFO SYMBOL_INFOW
#else // !UNICODE
#define wxSYMBOL_INFO SYMBOL_INFO
#endif // UNICODE/!UNICODE
#endif // !defined(wxSYMBOL_INFO)
typedef wxSYMBOL_INFO* wxPSYMBOL_INFO;
// This differs from PENUMLOADED_MODULES_CALLBACK[W]64 in that it always uses
// "const" for its first argument when the SDK used to pass a non-const string
// here until API_VERSION_NUMBER==11, so we can't just define it as an existing
// typedef.
typedef BOOL
(CALLBACK *wxPENUMLOADED_MODULES_CALLBACK)(const wxChar* moduleName,
DWORD64 moduleBase,
ULONG moduleSize,
void *userContext);
// ----------------------------------------------------------------------------
// wxDbgHelpDLL: dynamically load dbghelp.dll functions
// ----------------------------------------------------------------------------
@@ -131,31 +248,61 @@ public:
// function types
typedef DWORD (WINAPI *SymGetOptions_t)();
typedef DWORD (WINAPI *SymSetOptions_t)(DWORD);
typedef BOOL (WINAPI *SymInitialize_t)(HANDLE, LPSTR, BOOL);
typedef BOOL (WINAPI *SymInitialize_t)(HANDLE, LPCSTR, BOOL);
typedef BOOL (WINAPI *SymInitializeW_t)(HANDLE, LPCWSTR, BOOL);
typedef BOOL (WINAPI *StackWalk_t)(DWORD, HANDLE, HANDLE, LPSTACKFRAME,
LPVOID, PREAD_PROCESS_MEMORY_ROUTINE,
PFUNCTION_TABLE_ACCESS_ROUTINE,
PGET_MODULE_BASE_ROUTINE,
PTRANSLATE_ADDRESS_ROUTINE);
typedef BOOL (WINAPI *SymFromAddr_t)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO);
typedef BOOL (WINAPI *SymFromAddrW_t)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFOW);
typedef LPVOID (WINAPI *SymFunctionTableAccess_t)(HANDLE, DWORD_PTR);
typedef DWORD_PTR (WINAPI *SymGetModuleBase_t)(HANDLE, DWORD_PTR);
typedef BOOL (WINAPI *SymGetLineFromAddr_t)(HANDLE, DWORD_PTR,
typedef BOOL (WINAPI *SymGetLineFromAddr_t)(HANDLE, DWORD,
PDWORD, PIMAGEHLP_LINE);
typedef BOOL (WINAPI *SymGetLineFromAddr64_t)(HANDLE, DWORD64,
PDWORD, PIMAGEHLP_LINE64);
typedef BOOL (WINAPI *SymGetLineFromAddrW64_t)(HANDLE, DWORD64,
PDWORD, PIMAGEHLP_LINEW64);
typedef BOOL (WINAPI *SymSetContext_t)(HANDLE, PIMAGEHLP_STACK_FRAME,
PIMAGEHLP_CONTEXT);
typedef BOOL (WINAPI *SymEnumSymbols_t)(HANDLE, ULONG64, PCSTR,
PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID);
PSYM_ENUMERATESYMBOLS_CALLBACK,
const PVOID);
typedef BOOL (WINAPI *SymEnumSymbolsW_t)(HANDLE, ULONG64, PCWSTR,
PSYM_ENUMERATESYMBOLS_CALLBACKW,
const PVOID);
typedef BOOL (WINAPI *SymGetTypeInfo_t)(HANDLE, DWORD64, ULONG,
IMAGEHLP_SYMBOL_TYPE_INFO, PVOID);
typedef BOOL (WINAPI *SymCleanup_t)(HANDLE);
typedef BOOL (WINAPI *EnumerateLoadedModules_t)(HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID);
typedef BOOL (WINAPI *EnumerateLoadedModules64_t)(HANDLE, PENUMLOADED_MODULES_CALLBACK64, PVOID);
typedef BOOL (WINAPI *EnumerateLoadedModulesW64_t)(HANDLE, PENUMLOADED_MODULES_CALLBACKW64, PVOID);
typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE,
MINIDUMP_TYPE,
CONST PMINIDUMP_EXCEPTION_INFORMATION,
CONST PMINIDUMP_USER_STREAM_INFORMATION,
CONST PMINIDUMP_CALLBACK_INFORMATION);
// Higher level functions selecting the right debug help library function
// to call: for CallFoo(), it can be Foo(), Foo64(), FooW() or FooW64()
// depending on the build options and function availability.
//
// They also provide more convenient to use wx-specific API, e.g. work with
// wxString instead of char/wchar_t pointers and omit the arguments we
// don't need.
static BOOL CallSymInitialize(HANDLE, BOOL);
static BOOL CallEnumerateLoadedModules(HANDLE, wxPENUMLOADED_MODULES_CALLBACK, PVOID);
static BOOL CallSymFromAddr(HANDLE, DWORD64,
size_t* offset, wxString* name);
static BOOL CallSymGetLineFromAddr(HANDLE, DWORD64,
wxString* fileName, size_t* line);
static BOOL CallSymEnumSymbols(HANDLE hProcess,
ULONG64 baseOfDll,
wxPSYM_ENUMERATESYMBOLS_CALLBACK callback,
const PVOID callbackParam);
// The macro called by wxDO_FOR_ALL_SYM_FUNCS() below takes 2 arguments:
// the name of the function in the program code, which never has "64"
// suffix, and the name of the function in the DLL which can have "64"
@@ -176,26 +323,56 @@ public:
#define wxSYM_CALL_64(what, name) what(name, name)
#endif
#define wxDO_FOR_ALL_SYM_FUNCS(what) \
wxSYM_CALL_64(what, StackWalk); \
wxSYM_CALL_64(what, SymFunctionTableAccess); \
wxSYM_CALL_64(what, SymGetModuleBase); \
wxSYM_CALL_64(what, SymGetLineFromAddr); \
wxSYM_CALL_64(what, EnumerateLoadedModules); \
\
wxSYM_CALL(what, SymGetOptions); \
wxSYM_CALL(what, SymSetOptions); \
wxSYM_CALL(what, SymInitialize); \
wxSYM_CALL(what, SymFromAddr); \
wxSYM_CALL(what, SymSetContext); \
wxSYM_CALL(what, SymEnumSymbols); \
wxSYM_CALL(what, SymGetTypeInfo); \
wxSYM_CALL(what, SymCleanup); \
#define wxSYM_CALL_ALWAYS_W(what, name) what(name ## W, name ## W)
#define wxSYM_CALL_ALTERNATIVES(what, name) \
what(name, name); \
what(name ## 64, name ## 64); \
what(name ## W64, name ## W64)
#define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(what) \
wxSYM_CALL_64(what, StackWalk); \
wxSYM_CALL_64(what, SymFunctionTableAccess); \
wxSYM_CALL_64(what, SymGetModuleBase); \
\
wxSYM_CALL(what, SymGetOptions); \
wxSYM_CALL(what, SymSetOptions); \
wxSYM_CALL(what, SymSetContext); \
wxSYM_CALL(what, SymGetTypeInfo); \
wxSYM_CALL(what, SymCleanup); \
wxSYM_CALL(what, MiniDumpWriteDump)
#define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(what) \
wxSYM_CALL(what, SymInitialize); \
wxSYM_CALL(what, SymFromAddr); \
wxSYM_CALL(what, SymEnumSymbols)
#define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(what) \
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(what); \
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(what)
// Alternation will work when the following functions are not found,
// therefore they are not included in REQUIRED version.
#define wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(what) \
wxSYM_CALL_ALTERNATIVES(what, SymGetLineFromAddr); \
wxSYM_CALL_ALTERNATIVES(what, EnumerateLoadedModules); \
wxSYM_CALL_ALWAYS_W(what, SymInitialize); \
wxSYM_CALL_ALWAYS_W(what, SymFromAddr); \
wxSYM_CALL_ALWAYS_W(what, SymEnumSymbols)
#define wxDO_FOR_ALL_SYM_FUNCS(what) \
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(what); \
wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(what)
#define wxDECLARE_SYM_FUNCTION(func, name) static func ## _t func
wxDO_FOR_ALL_SYM_FUNCS(wxDECLARE_SYM_FUNCTION);
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(wxDECLARE_SYM_FUNCTION);
private:
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(wxDECLARE_SYM_FUNCTION);
wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(wxDECLARE_SYM_FUNCTION);
public:
#undef wxDECLARE_SYM_FUNCTION
@@ -209,10 +386,10 @@ public:
static void LogError(const wxChar *func);
// return textual representation of the value of given symbol
static wxString DumpSymbol(PSYMBOL_INFO pSymInfo, void *pVariable);
static wxString DumpSymbol(wxPSYMBOL_INFO pSymInfo, void *pVariable);
// return the name of the symbol with given type index
static wxString GetSymbolName(PSYMBOL_INFO pSymInfo);
static wxString GetSymbolName(wxPSYMBOL_INFO pSymInfo);
private:
// dereference the given symbol, i.e. return symbol which is not a
@@ -222,17 +399,20 @@ private:
// dereferenced the symbol
//
// return the tag of the dereferenced symbol
static SymbolTag DereferenceSymbol(PSYMBOL_INFO pSymInfo, void **ppData);
static SymbolTag DereferenceSymbol(wxPSYMBOL_INFO pSymInfo, void **ppData);
static wxString DumpField(PSYMBOL_INFO pSymInfo,
static wxString DumpField(wxPSYMBOL_INFO pSymInfo,
void *pVariable,
unsigned level);
static wxString DumpBaseType(BasicType bt, DWORD64 length, void *pVariable);
static wxString DumpUDT(PSYMBOL_INFO pSymInfo,
static wxString DumpUDT(wxPSYMBOL_INFO pSymInfo,
void *pVariable,
unsigned level = 0);
static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp);
static bool DoInit();
};
#endif // wxUSE_DBGHELP

View File

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

View File

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

View File

@@ -17,14 +17,17 @@
#include "wx/frame.h"
#include "wx/icon.h"
#include "wx/menu.h"
#include "wx/choicdlg.h"
#include "wx/msgdlg.h"
#include "wx/button.h"
#include "wx/dcclient.h"
#include "wx/timer.h"
#include "wx/datetime.h"
#include "wx/ffile.h"
#include "wx/filename.h"
#include "wx/debugrpt.h"
#include "wx/dynlib.h"
#if !wxUSE_DEBUGREPORT
#error "This sample can't be built without wxUSE_DEBUGREPORT"
@@ -141,10 +144,12 @@ void foo(int n)
enum
{
DebugRpt_ListLoadedDLLs = 50,
DebugRpt_Quit = wxID_EXIT,
DebugRpt_Crash = 100,
DebugRpt_Current,
DebugRpt_Paint,
DebugRpt_Timer,
DebugRpt_Upload,
DebugRpt_About = wxID_ABOUT
};
@@ -155,15 +160,28 @@ public:
MyFrame();
private:
void OnListLoadedDLLs(wxCommandEvent& event);
void OnQuit(wxCommandEvent& event);
void OnReportForCrash(wxCommandEvent& event);
void OnReportForCurrent(wxCommandEvent& event);
void OnReportPaint(wxCommandEvent& event);
void OnReportTimer(wxCommandEvent& event);
void OnReportUpload(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnPaint(wxPaintEvent& event);
// a timer whose only purpose in life is to crash as soon as it's started
class BadTimer : public wxTimer
{
public:
BadTimer() { }
virtual void Notify() wxOVERRIDE
{
foo(8);
}
} m_badTimer;
// number of lines drawn in OnPaint()
int m_numLines;
@@ -217,10 +235,12 @@ wxIMPLEMENT_APP(MyApp);
// ----------------------------------------------------------------------------
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(DebugRpt_ListLoadedDLLs, MyFrame::OnListLoadedDLLs)
EVT_MENU(DebugRpt_Quit, MyFrame::OnQuit)
EVT_MENU(DebugRpt_Crash, MyFrame::OnReportForCrash)
EVT_MENU(DebugRpt_Current, MyFrame::OnReportForCurrent)
EVT_MENU(DebugRpt_Paint, MyFrame::OnReportPaint)
EVT_MENU(DebugRpt_Timer, MyFrame::OnReportTimer)
EVT_MENU(DebugRpt_Upload, MyFrame::OnReportUpload)
EVT_MENU(DebugRpt_About, MyFrame::OnAbout)
@@ -236,6 +256,8 @@ MyFrame::MyFrame()
SetIcon(wxICON(sample));
wxMenu *menuFile = new wxMenu;
menuFile->Append(DebugRpt_ListLoadedDLLs, wxT("&List loaded DLLs...\tCtrl-L"));
menuFile->AppendSeparator();
menuFile->Append(DebugRpt_Quit, wxT("E&xit\tAlt-X"));
wxMenu *menuReport = new wxMenu;
@@ -245,6 +267,8 @@ MyFrame::MyFrame()
wxT("Create report for the current program context"));
menuReport->Append(DebugRpt_Paint, wxT("Report for &paint handler\tCtrl-P"),
wxT("Provoke a repeatable crash in wxEVT_PAINT handler"));
menuReport->Append(DebugRpt_Timer, wxT("Report for &timer handler\tCtrl-T"),
wxT("Provoke a crash in wxEVT_TIMER handler"));
menuReport->AppendSeparator();
menuReport->AppendCheckItem(DebugRpt_Upload, wxT("Up&load debug report"),
wxT("You need to configure a web server accepting debug report uploads to use this function"));
@@ -263,6 +287,47 @@ MyFrame::MyFrame()
Show();
}
void MyFrame::OnListLoadedDLLs(wxCommandEvent& WXUNUSED(event))
{
const wxDynamicLibraryDetailsArray loaded = wxDynamicLibrary::ListLoaded();
const size_t count = loaded.size();
if ( !count )
{
wxLogError("Failed to get the list of loaded dynamic libraries.");
return;
}
wxArrayString names;
names.reserve(count);
for ( size_t n = 0; n < count; n++ )
{
names.push_back(loaded[n].GetName());
}
for ( ;; )
{
const int sel = wxGetSingleChoiceIndex
(
"Choose a library to show more information about it",
"List of loaded dynamic libraries",
names,
this
);
if ( sel == wxNOT_FOUND )
return;
const wxDynamicLibraryDetails& det = loaded[sel];
void *addr = 0;
size_t len = 0;
det.GetAddress(&addr, &len);
wxLogMessage("Full path is \"%s\", memory range %p:%p, version \"%s\"",
det.GetPath(),
addr,
static_cast<void*>(static_cast<char*>(addr) + len),
det.GetVersion());
}
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close(true);
@@ -291,6 +356,12 @@ void MyFrame::OnReportPaint(wxCommandEvent& WXUNUSED(event))
Refresh();
}
void MyFrame::OnReportTimer(wxCommandEvent& WXUNUSED(event))
{
// this will result in a crash in BadTimer::OnNotify() soon
m_badTimer.StartOnce(100);
}
void MyFrame::OnReportUpload(wxCommandEvent& event)
{
wxGetApp().UploadReport(event.IsChecked());
@@ -369,10 +440,20 @@ void MyApp::GenerateReport(wxDebugReport::Context ctx)
// can also add an existing file directly, it will be copied
// automatically
#ifdef __WXMSW__
report->AddFile(wxT("c:\\autoexec.bat"), wxT("DOS startup file"));
#else
report->AddFile(wxT("/etc/motd"), wxT("Message of the day"));
#endif
wxString windir;
if ( !wxGetEnv("WINDIR", &windir) )
windir = "C:\\Windows";
fn.AssignDir(windir);
fn.AppendDir("system32");
fn.AppendDir("drivers");
fn.AppendDir("etc");
#else // !__WXMSW__
fn.AssignDir("/etc");
#endif // __WXMSW__/!__WXMSW__
fn.SetFullName("hosts");
if ( fn.FileExists() )
report->AddFile(fn.GetFullPath(), "Local hosts file");
// calling Show() is not mandatory, but is more polite
if ( wxDebugReportPreviewStd().Show(*report) )

View File

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

View File

@@ -1,8 +1,7 @@
/////////////////////////////////////////////////////////////////////////////
// Name: src/msw/debughlp.cpp
// Purpose: various Win32 debug helpers
// Author: Vadim Zeitlin
// Modified by:
// Author: Vadim Zeitlin, Suzumizaki-kimitaka
// Created: 2005-01-08 (extracted from crashrpt.cpp)
// Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
// Licence: wxWindows licence
@@ -26,6 +25,8 @@
#if wxUSE_DBGHELP && wxUSE_DYNLIB_CLASS
#include "wx/scopedarray.h"
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
@@ -34,6 +35,59 @@
// ourselves to that many levels of embedded fields inside structs
static const unsigned MAX_DUMP_DEPTH = 20;
// ----------------------------------------------------------------------------
// local helpers
// ----------------------------------------------------------------------------
namespace
{
// Automatically initialize SizeOfStruct field of debug help structs to the
// correct value.
template <class T>
struct SizedStruct : public T
{
SizedStruct()
{
::ZeroMemory(this, sizeof(T));
this->SizeOfStruct = sizeof(T);
}
};
// This is used for working with variable-sized SYMBOL_INFO[W] structs that
// have a variable length array as their last field.
template <class T>
class VarSizedStruct
{
public:
VarSizedStruct()
{
::ZeroMemory(m_buffer, sizeof(T) + MAX_NAME_LEN);
(*this)->SizeOfStruct = sizeof(T);
(*this)->MaxNameLen = MAX_NAME_LEN;
}
operator T*()
{
return static_cast<T*>(static_cast<void*>(m_buffer));
}
T* operator->()
{
return *this;
}
private:
// Currently this is just a constant, we could make it a template parameter
// if we wanted.
enum { MAX_NAME_LEN = 1024 };
BYTE m_buffer[sizeof(T) + MAX_NAME_LEN];
};
} // anonymous namespace
// ----------------------------------------------------------------------------
// globals
// ----------------------------------------------------------------------------
@@ -62,7 +116,8 @@ wxDO_FOR_ALL_SYM_FUNCS(DEFINE_SYM_FUNCTION);
// load all function we need from the DLL
static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp)
/* static */
bool wxDbgHelpDLL::BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp)
{
#define LOAD_SYM_FUNCTION(func, name) \
wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \
@@ -73,15 +128,27 @@ static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp)
return false; \
}
wxDO_FOR_ALL_SYM_FUNCS(LOAD_SYM_FUNCTION);
wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(LOAD_SYM_FUNCTION);
#undef LOAD_SYM_FUNCTION
#define LOAD_SYM_FUNCTION_OPTIONAL(func, name) \
if ( dllDbgHelp.HasSymbol(wxT(#name)) ) \
{ \
wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \
dllDbgHelp.GetSymbol(wxT(#name)); \
}
wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(LOAD_SYM_FUNCTION_OPTIONAL);
#undef LOAD_SYM_FUNCTION_CAN_FAIL
return true;
}
// called by Init() if we hadn't done this before
static bool DoInit()
/* static */
bool wxDbgHelpDLL::DoInit()
{
wxDynamicLibrary dllDbgHelp(wxT("dbghelp.dll"), wxDL_VERBATIM);
if ( dllDbgHelp.IsLoaded() )
@@ -170,13 +237,13 @@ DoGetTypeInfo(DWORD64 base, ULONG ti, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
static inline
bool
DoGetTypeInfo(PSYMBOL_INFO pSym, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
DoGetTypeInfo(wxPSYMBOL_INFO pSym, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc)
{
return DoGetTypeInfo(pSym->ModBase, pSym->TypeIndex, type, rc);
}
static inline
wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym)
wxDbgHelpDLL::BasicType GetBasicType(wxPSYMBOL_INFO pSym)
{
wxDbgHelpDLL::BasicType bt;
return DoGetTypeInfo(pSym, TI_GET_BASETYPE, &bt)
@@ -185,7 +252,7 @@ wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym)
}
/* static */
wxString wxDbgHelpDLL::GetSymbolName(PSYMBOL_INFO pSym)
wxString wxDbgHelpDLL::GetSymbolName(wxPSYMBOL_INFO pSym)
{
wxString s;
@@ -289,7 +356,7 @@ wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress)
}
wxString
wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
wxDbgHelpDLL::DumpField(wxPSYMBOL_INFO pSym, void *pVariable, unsigned level)
{
wxString s;
@@ -336,7 +403,7 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
// now pass to the type representing the type of this member
SYMBOL_INFO sym = *pSym;
wxSYMBOL_INFO sym = *pSym;
if ( !DoGetTypeInfo(pSym, TI_GET_TYPEID, &sym.TypeIndex) )
break;
@@ -387,7 +454,7 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
}
/* static */ wxString
wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
wxDbgHelpDLL::DumpUDT(wxPSYMBOL_INFO pSym, void *pVariable, unsigned level)
{
wxString s;
@@ -454,7 +521,7 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
s << wxT(" {\n");
// Iterate through all children
SYMBOL_INFO sym;
wxSYMBOL_INFO sym;
wxZeroMemory(sym);
sym.ModBase = pSym->ModBase;
for ( unsigned i = 0; i < dwChildrenCount; i++ )
@@ -486,7 +553,7 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
/* static */
wxDbgHelpDLL::SymbolTag
wxDbgHelpDLL::DereferenceSymbol(PSYMBOL_INFO pSym, void **ppData)
wxDbgHelpDLL::DereferenceSymbol(wxPSYMBOL_INFO pSym, void **ppData)
{
SymbolTag tag = SYMBOL_TAG_NULL;
for ( ;; )
@@ -523,10 +590,10 @@ wxDbgHelpDLL::DereferenceSymbol(PSYMBOL_INFO pSym, void **ppData)
}
/* static */ wxString
wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable)
wxDbgHelpDLL::DumpSymbol(wxPSYMBOL_INFO pSym, void *pVariable)
{
wxString s;
SYMBOL_INFO symDeref = *pSym;
wxSYMBOL_INFO symDeref = *pSym;
switch ( DereferenceSymbol(&symDeref, &pVariable) )
{
default:
@@ -552,6 +619,322 @@ wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable)
return s;
}
// ----------------------------------------------------------------------------
// Helpers for selecting the best available function on the current platform.
// ----------------------------------------------------------------------------
// Store the original callback and the data for it: objects of this type are
// used as bridges for the enumeration functions taking callbacks of different
// types.
struct wxEnumLoadedCallbackBridge
{
public:
wxEnumLoadedCallbackBridge(wxPENUMLOADED_MODULES_CALLBACK ptr, PVOID content)
: m_callback(ptr), m_data(content)
{
}
wxPENUMLOADED_MODULES_CALLBACK m_callback;
PVOID m_data;
};
// As mentioned near wxPENUMLOADED_MODULES_CALLBACK definition, until v11 of
// the API the parameters were non-const.
#if API_VERSION_NUMBER < 11
#define wxHAS_NON_CONST_MODULE_NAME
#define wxMODULE_NAMEA PSTR
#else
#define wxMODULE_NAMEA PCSTR
#endif
#if defined(UNICODE) && defined(wxHAS_NON_CONST_MODULE_NAME)
static BOOL CALLBACK
wxEnumLoadedW64Callback(PWSTR ModuleName,
DWORD64 ModuleBase,
ULONG ModuleSize,
PVOID UserContext)
{
wxEnumLoadedCallbackBridge&
bridge = *static_cast<wxEnumLoadedCallbackBridge*>(UserContext);
return (*bridge.m_callback)(ModuleName, ModuleBase, ModuleSize, bridge.m_data);
}
#endif // UNICODE && wxHAS_NON_CONST_MODULE_NAME
static BOOL CALLBACK
wxEnumLoaded64Callback(wxMODULE_NAMEA ModuleName,
DWORD64 ModuleBase,
ULONG ModuleSize,
PVOID UserContext)
{
wxEnumLoadedCallbackBridge&
bridge = *static_cast<wxEnumLoadedCallbackBridge*>(UserContext);
return (*bridge.m_callback)
(
#ifdef UNICODE
wxConvLocal.cMB2WC(ModuleName),
#else // !UNICODE
ModuleName,
#endif // UNICODE
ModuleBase, ModuleSize, bridge.m_data
);
}
static BOOL CALLBACK
wxEnumLoadedCallback(wxMODULE_NAMEA ModuleName,
DWORD_PTR ModuleBase,
ULONG ModuleSize,
PVOID UserContext)
{
wxEnumLoadedCallbackBridge&
bridge = *static_cast<wxEnumLoadedCallbackBridge*>(UserContext);
return (*bridge.m_callback)
(
#ifdef UNICODE
wxConvLocal.cMB2WC(ModuleName),
#else // !UNICODE
ModuleName,
#endif // UNICODE
ModuleBase, ModuleSize, bridge.m_data
);
}
/* static */
BOOL
wxDbgHelpDLL::CallEnumerateLoadedModules(HANDLE handle,
wxPENUMLOADED_MODULES_CALLBACK callback,
PVOID callbackParam)
{
#ifdef UNICODE
if ( EnumerateLoadedModulesW64 )
{
#ifdef wxHAS_NON_CONST_MODULE_NAME
// We need to pass by a bridge just to convert non-const module name to
// the const one taken by our callback.
wxEnumLoadedCallbackBridge br(callback, callbackParam);
if ( EnumerateLoadedModulesW64(handle, &wxEnumLoadedW64Callback, &br) )
return TRUE;
#else // new SDK
// We can use our callback directly.
if ( EnumerateLoadedModulesW64(handle, callback, callbackParam) )
return TRUE;
#endif // old/new SDK
}
#endif // UNICODE
if ( EnumerateLoadedModules64 )
{
// We need a bridge if we need to convert to Unicode or if we're using
// an older SDK with a non-const first argument, so just use it always
// to avoid having too many complicated preprocessor checks.
wxEnumLoadedCallbackBridge br(callback, callbackParam);
if ( EnumerateLoadedModules64(handle, &wxEnumLoaded64Callback, &br) )
return TRUE;
}
if ( EnumerateLoadedModules )
{
// With this function we need a bridge in any case because the type of
// module base argument used by EnumerateLoadedModules() differs from
// that used by EnumerateLoadedModules[W]64().
wxEnumLoadedCallbackBridge br(callback, callbackParam);
if ( EnumerateLoadedModules(handle, &wxEnumLoadedCallback, &br) )
return TRUE;
}
return FALSE;
}
/* static */
BOOL
wxDbgHelpDLL::CallSymInitialize(HANDLE hProcess, BOOL fInvadeProcess)
{
#ifdef UNICODE
if ( SymInitializeW )
{
if ( SymInitializeW(hProcess, NULL, fInvadeProcess) )
return TRUE;
}
#endif // UNICODE
if ( SymInitialize )
{
if ( SymInitialize(hProcess, NULL, fInvadeProcess) )
return TRUE;
}
return FALSE;
}
/* static */
BOOL
wxDbgHelpDLL::CallSymFromAddr(HANDLE hProcess,
DWORD64 Address,
size_t* offset,
wxString* name)
{
DWORD64 dwDisplacement;
#ifdef UNICODE
if ( SymFromAddrW )
{
VarSizedStruct<SYMBOL_INFOW> infoW;
if ( SymFromAddrW(hProcess, Address, &dwDisplacement, infoW) )
{
*offset = dwDisplacement;
*name = infoW->Name;
return TRUE;
}
}
#endif // UNICODE
if ( SymFromAddr )
{
VarSizedStruct<SYMBOL_INFO> info;
if ( SymFromAddr(hProcess, Address, &dwDisplacement, info) )
{
*offset = dwDisplacement;
*name = info->Name;
return TRUE;
}
}
return FALSE;
}
/* static */
BOOL
wxDbgHelpDLL::CallSymGetLineFromAddr(HANDLE hProcess,
DWORD64 dwAddr,
wxString* fileName,
size_t* line)
{
DWORD dwDisplacement;
#ifdef UNICODE
if ( SymGetLineFromAddrW64 )
{
SizedStruct<IMAGEHLP_LINEW64> lineW64;
if ( SymGetLineFromAddrW64(hProcess, dwAddr, &dwDisplacement, &lineW64) )
{
*fileName = lineW64.FileName;
*line = lineW64.LineNumber;
return TRUE;
}
}
#endif // UNICODE
if ( SymGetLineFromAddr64 )
{
SizedStruct<IMAGEHLP_LINE64> line64;
if ( SymGetLineFromAddr64(hProcess, dwAddr, &dwDisplacement, &line64) )
{
*fileName = line64.FileName;
*line = line64.LineNumber;
return TRUE;
}
}
if ( SymGetLineFromAddr )
{
SizedStruct<IMAGEHLP_LINE> line32;
if ( SymGetLineFromAddr(hProcess, dwAddr, &dwDisplacement, &line32) )
{
*fileName = line32.FileName;
*line = line32.LineNumber;
return TRUE;
}
}
return FALSE;
}
#ifdef UNICODE
// Allow to adapt callback supposed to be used with SymEnumSymbolsW() with
// SymEnumSymbols().
struct wxEnumSymbolsCallbackBridge
{
public:
wxEnumSymbolsCallbackBridge(PSYM_ENUMERATESYMBOLS_CALLBACKW ptr, PVOID content)
: m_callback(ptr), m_data(content)
{
}
PSYM_ENUMERATESYMBOLS_CALLBACKW m_callback;
PVOID m_data;
};
static BOOL CALLBACK
wxEnumSymbolsCallback(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
{
wxEnumSymbolsCallbackBridge&
bridge = *static_cast<wxEnumSymbolsCallbackBridge*>(UserContext);
const wxWCharBuffer buf = wxConvLocal.cMB2WC(pSymInfo->Name);
const size_t len = buf.length();
// Allocate enough space for the wide char version of the struct.
//
// Note that there is no +1 here because sizeof(SYMBOL_INFOW) already
// includes 1 byte of the name.
wxScopedArray<BYTE> symbolBuffer(sizeof(SYMBOL_INFOW) + len*sizeof(WCHAR));
SYMBOL_INFOW* const infoW = (SYMBOL_INFOW*)symbolBuffer.get();
// Copy the original struct contents except for the last byte, which is the
// first byte of its (narrow) name that we don't need.
CopyMemory(infoW, pSymInfo, sizeof(SYMBOL_INFO) - sizeof(CHAR));
// Size is different for narrow and wide variants of the struct, so fix it
// up now.
infoW->SizeOfStruct = sizeof(SYMBOL_INFOW);
// Finally copy the converted name, which is the reason for doing all this.
wxStrncpy(infoW->Name, buf.data(), len);
return (*bridge.m_callback)(infoW, SymbolSize, bridge.m_data);
}
#endif // UNICODE
/* static */
BOOL
wxDbgHelpDLL::CallSymEnumSymbols(HANDLE hProcess,
ULONG64 baseOfDll,
wxPSYM_ENUMERATESYMBOLS_CALLBACK callback,
const PVOID callbackParam)
{
#ifdef UNICODE
if ( SymEnumSymbolsW )
{
if ( SymEnumSymbolsW(hProcess, baseOfDll, NULL, callback, callbackParam) )
return TRUE;
}
if ( SymEnumSymbols )
{
wxEnumSymbolsCallbackBridge br(callback, callbackParam);
if ( SymEnumSymbols(hProcess, baseOfDll, NULL, wxEnumSymbolsCallback, &br) )
return TRUE;
}
#else // !UNICODE
if ( SymEnumSymbols )
{
if ( SymEnumSymbols(hProcess, baseOfDll, NULL, callback, callbackParam) )
return TRUE;
}
#endif // UNICODE/!UNICODE
return FALSE;
}
// ----------------------------------------------------------------------------
// debugging helpers
// ----------------------------------------------------------------------------

View File

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

View File

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

View File

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

View File

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

View File

@@ -50,29 +50,16 @@ void wxStackFrame::OnGetName()
m_hasName = true;
// get the name of the function for this stack frame entry
static const size_t MAX_NAME_LEN = 1024;
BYTE symbolBuffer[sizeof(SYMBOL_INFO) + MAX_NAME_LEN];
wxZeroMemory(symbolBuffer);
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_NAME_LEN;
DWORD64 symDisplacement = 0;
if ( !wxDbgHelpDLL::SymFromAddr
if ( !wxDbgHelpDLL::CallSymFromAddr
(
::GetCurrentProcess(),
GetSymAddr(),
&symDisplacement,
pSymbol
&m_offset,
&m_name
) )
{
wxDbgHelpDLL::LogError(wxT("SymFromAddr"));
return;
}
m_name = wxString::FromAscii(pSymbol->Name);
m_offset = symDisplacement;
}
void wxStackFrame::OnGetLocation()
@@ -82,25 +69,11 @@ void wxStackFrame::OnGetLocation()
m_hasLocation = true;
// get the source line for this stack frame entry
IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
DWORD dwLineDisplacement;
if ( !wxDbgHelpDLL::SymGetLineFromAddr
(
::GetCurrentProcess(),
GetSymAddr(),
&dwLineDisplacement,
&lineInfo
) )
{
// it is normal that we don't have source info for some symbols,
// notably all the ones from the system DLLs...
//wxDbgHelpDLL::LogError(wxT("SymGetLineFromAddr"));
return;
}
m_filename = wxString::FromAscii(lineInfo.FileName);
m_line = lineInfo.LineNumber;
// get the source line for this stack frame entry ignoring possible errors
// (it's normal that we don't have source info for some symbols, e.g. all
// those from the system DLLs)
wxDbgHelpDLL::CallSymGetLineFromAddr(::GetCurrentProcess(), GetSymAddr(),
&m_filename, &m_line);
}
bool
@@ -125,11 +98,10 @@ wxStackFrame::GetParam(size_t n,
return true;
}
void wxStackFrame::OnParam(PSYMBOL_INFO pSymInfo)
void wxStackFrame::OnParam(wxSYMBOL_INFO *pSymInfo)
{
m_paramTypes.Add(wxEmptyString);
m_paramNames.Add(wxString::FromAscii(pSymInfo->Name));
m_paramNames.Add(pSymInfo->Name);
// if symbol information is corrupted and we crash, the exception is going
// to be ignored when we're called from WalkFromException() because of the
@@ -158,7 +130,7 @@ void wxStackFrame::OnParam(PSYMBOL_INFO pSymInfo)
}
BOOL CALLBACK
EnumSymbolsProc(PSYMBOL_INFO pSymInfo, ULONG WXUNUSED(SymSize), PVOID data)
EnumSymbolsProc(wxPSYMBOL_INFO pSymInfo, ULONG WXUNUSED(SymSize), PVOID data)
{
wxStackFrame *frame = static_cast<wxStackFrame *>(data);
@@ -195,11 +167,10 @@ void wxStackFrame::OnGetParam()
return;
}
if ( !wxDbgHelpDLL::SymEnumSymbols
if ( !wxDbgHelpDLL::CallSymEnumSymbols
(
::GetCurrentProcess(),
NULL, // DLL base: use current context
NULL, // no mask, get all symbols
EnumSymbolsProc, // callback
this // data to pass to it
) )
@@ -232,10 +203,9 @@ void wxStackWalker::WalkFrom(const CONTEXT *pCtx, size_t skip, size_t maxDepth)
// below which should be a real handle... so this is what we use
const HANDLE hProcess = ::GetCurrentProcess();
if ( !wxDbgHelpDLL::SymInitialize
if ( !wxDbgHelpDLL::CallSymInitialize
(
hProcess,
NULL, // use default symbol search path
TRUE // load symbols for all loaded modules
) )
{
@@ -382,7 +352,7 @@ wxStackFrame::GetParam(size_t WXUNUSED(n),
return false;
}
void wxStackFrame::OnParam(_SYMBOL_INFO * WXUNUSED(pSymInfo))
void wxStackFrame::OnParam(wxSYMBOL_INFO * WXUNUSED(pSymInfo))
{
}

View File

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

View File

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

View File

@@ -14,6 +14,7 @@
#if wxUSE_STC
#ifndef WX_PRECOMP
#include "wx/math.h"
#include "wx/menu.h"
#include "wx/dcmemory.h"
#include "wx/settings.h"
@@ -50,8 +51,8 @@ Point Point::FromLong(long lpoint) {
}
wxRect wxRectFromPRectangle(PRectangle prc) {
wxRect r(prc.left, prc.top,
prc.Width(), prc.Height());
wxRect r(wxRound(prc.left), wxRound(prc.top),
wxRound(prc.Width()), wxRound(prc.Height()));
return r;
}
@@ -140,7 +141,7 @@ void Font::Create(const FontParameters &fp) {
else
weight = wxFONTWEIGHT_NORMAL;
wxFont font(fp.size,
wxFont font(wxRound(fp.size),
wxFONTFAMILY_DEFAULT,
fp.italic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL,
weight,
@@ -320,8 +321,8 @@ void SurfaceImpl::Polygon(Point *pts, int npts, ColourDesired fore, ColourDesire
wxPoint *p = new wxPoint[npts];
for (int i=0; i<npts; i++) {
p[i].x = pts[i].x;
p[i].y = pts[i].y;
p[i].x = wxRound(pts[i].x);
p[i].y = wxRound(pts[i].y);
}
hdc->DrawPolygon(npts, p);
delete [] p;
@@ -501,7 +502,7 @@ void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
wxRect r = wxRectFromPRectangle(rc);
hdc->Blit(r.x, r.y, r.width, r.height,
((SurfaceImpl&)surfaceSource).hdc,
from.x, from.y, wxCOPY);
wxRound(from.x), wxRound(from.y), wxCOPY);
}
void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, XYPOSITION ybase,
@@ -514,7 +515,7 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, XYPOSITION ybase,
// ybase is where the baseline should be, but wxWin uses the upper left
// corner, so I need to calculate the real position for the text...
hdc->DrawText(stc2wx(s, len), rc.left, ybase - GetAscent(font));
hdc->DrawText(stc2wx(s, len), wxRound(rc.left), wxRound(ybase - GetAscent(font)));
}
void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, XYPOSITION ybase,
@@ -527,7 +528,7 @@ void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, XYPOSITION ybase,
hdc->SetClippingRegion(wxRectFromPRectangle(rc));
// see comments above
hdc->DrawText(stc2wx(s, len), rc.left, ybase - GetAscent(font));
hdc->DrawText(stc2wx(s, len), wxRound(rc.left), wxRound(ybase - GetAscent(font)));
hdc->DestroyClippingRegion();
}
@@ -542,7 +543,7 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font, XYPOSITION ybas
// ybase is where the baseline should be, but wxWin uses the upper left
// corner, so I need to calculate the real position for the text...
hdc->DrawText(stc2wx(s, len), rc.left, ybase - GetAscent(font));
hdc->DrawText(stc2wx(s, len), wxRound(rc.left), wxRound(ybase - GetAscent(font)));
hdc->SetBackgroundMode(wxBRUSHSTYLE_SOLID);
}
@@ -784,7 +785,7 @@ PRectangle Window::GetMonitorRect(Point pt) {
if (! wid) return PRectangle();
#if wxUSE_DISPLAY
// Get the display the point is found on
int n = wxDisplay::GetFromPoint(wxPoint(pt.x, pt.y));
int n = wxDisplay::GetFromPoint(wxPoint(wxRound(pt.x), wxRound(pt.y)));
wxDisplay dpy(n == wxNOT_FOUND ? 0 : n);
rect = dpy.GetGeometry();
#else
@@ -1428,7 +1429,7 @@ void Menu::Destroy() {
}
void Menu::Show(Point pt, Window &w) {
GETWIN(w.GetID())->PopupMenu((wxMenu*)mid, pt.x - 4, pt.y);
GETWIN(w.GetID())->PopupMenu((wxMenu*)mid, wxRound(pt.x - 4), wxRound(pt.y));
Destroy();
}

View File

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

View File

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

View File

@@ -210,6 +210,8 @@ TIFFFdOpen(int ifd, const char* name, const char* mode)
int fSuppressMap;
int m;
fSuppressMap=0;
fd_as_handle_union_t fdh;
fdh.fd = ifd;
for (m=0; mode[m]!=0; m++)
{
if (mode[m]=='u')
@@ -218,7 +220,7 @@ TIFFFdOpen(int ifd, const char* name, const char* mode)
break;
}
}
tif = TIFFClientOpen(name, mode, (thandle_t)ifd,
tif = TIFFClientOpen(name, mode, fdh.h,
_tiffReadProc, _tiffWriteProc,
_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
@@ -237,7 +239,7 @@ TIFF*
TIFFOpen(const char* name, const char* mode)
{
static const char module[] = "TIFFOpen";
thandle_t fd;
fd_as_handle_union_t fdh;
int m;
DWORD dwMode;
TIFF* tif;
@@ -253,19 +255,19 @@ TIFFOpen(const char* name, const char* mode)
default: return ((TIFF*)0);
}
fd = (thandle_t)CreateFileA(name,
fdh.h = CreateFileA(name,
(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE),
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
NULL);
if (fd == INVALID_HANDLE_VALUE) {
if (fdh.h == INVALID_HANDLE_VALUE) {
TIFFErrorExt(0, module, "%s: Cannot open", name);
return ((TIFF *)0);
}
tif = TIFFFdOpen((int)fd, name, mode);
tif = TIFFFdOpen(fdh.fd, name, mode);
if(!tif)
CloseHandle(fd);
CloseHandle(fdh.h);
return tif;
}
@@ -276,7 +278,7 @@ TIFF*
TIFFOpenW(const wchar_t* name, const char* mode)
{
static const char module[] = "TIFFOpenW";
thandle_t fd;
fd_as_handle_union_t fdh;
int m;
DWORD dwMode;
int mbsize;
@@ -294,12 +296,12 @@ TIFFOpenW(const wchar_t* name, const char* mode)
default: return ((TIFF*)0);
}
fd = (thandle_t)CreateFileW(name,
fdh.h = CreateFileW(name,
(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE),
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
NULL);
if (fd == INVALID_HANDLE_VALUE) {
if (fdh.h == INVALID_HANDLE_VALUE) {
TIFFErrorExt(0, module, "%S: Cannot open", name);
return ((TIFF *)0);
}
@@ -318,10 +320,10 @@ TIFFOpenW(const wchar_t* name, const char* mode)
NULL, NULL);
}
tif = TIFFFdOpen((int)fd,
tif = TIFFFdOpen(fdh.fd,
(mbname != NULL) ? mbname : "<unknown>", mode);
if(!tif)
CloseHandle(fd);
CloseHandle(fdh.h);
_TIFFfree(mbname);

View File

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