]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/debughlp.cpp
Show full screen windows with WS_POPUP style in wxMSW.
[wxWidgets.git] / src / msw / debughlp.cpp
index c0a0a560d9c479bea244f496477892ad9723d006..8a76027c76411d87ddc772519618b955a1281476 100644 (file)
@@ -1,10 +1,9 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        msw/debughlp.cpp
+// Name:        src/msw/debughlp.cpp
 // Purpose:     various Win32 debug helpers
 // Author:      Vadim Zeitlin
-// Modified by:
+// Modified by: Suzumizaki-kimitaka 2013-04-10
 // Created:     2005-01-08 (extracted from crashrpt.cpp)
-// RCS-ID:      $Id$
 // Copyright:   (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org>
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
@@ -50,7 +49,8 @@ static wxString gs_errMsg;
 // static members
 // ----------------------------------------------------------------------------
 
-#define DEFINE_SYM_FUNCTION(func) wxDbgHelpDLL::func ## _t wxDbgHelpDLL::func = 0
+#define DEFINE_SYM_FUNCTION(func, name) \
+    wxDbgHelpDLL::func ## _t wxDbgHelpDLL::func = 0
 
 wxDO_FOR_ALL_SYM_FUNCS(DEFINE_SYM_FUNCTION);
 
@@ -62,26 +62,39 @@ 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(name)                                           \
-        wxDbgHelpDLL::name = (wxDbgHelpDLL::name ## _t)                       \
-                                dllDbgHelp.GetSymbol(wxT(#name));              \
-        if ( !wxDbgHelpDLL::name )                                            \
+    #define LOAD_SYM_FUNCTION(func, name)                                     \
+        wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t)                       \
+            dllDbgHelp.GetSymbol(wxT(#name));                                 \
+        if ( !wxDbgHelpDLL::func )                                            \
         {                                                                     \
-            gs_errMsg += wxT("Function ") wxT(#name) wxT("() not found.\n");     \
+            gs_errMsg += wxT("Function ") wxT(#name) wxT("() not found.\n");  \
             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() )
@@ -145,7 +158,7 @@ const wxString& wxDbgHelpDLL::GetErrorMessage()
 void wxDbgHelpDLL::LogError(const wxChar *func)
 {
     ::OutputDebugString(wxString::Format(wxT("dbghelp: %s() failed: %s\r\n"),
-                        func, wxSysErrorMsg(::GetLastError())).wx_str());
+                        func, wxSysErrorMsg(::GetLastError())).t_str());
 }
 
 // ----------------------------------------------------------------------------
@@ -170,13 +183,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 +198,7 @@ wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym)
 }
 
 /* static */
-wxString wxDbgHelpDLL::GetSymbolName(PSYMBOL_INFO pSym)
+wxString wxDbgHelpDLL::GetSymbolName(wxPSYMBOL_INFO pSym)
 {
     wxString s;
 
@@ -281,7 +294,7 @@ wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress)
         }
         else // opaque 64 bit value
         {
-            s.Printf(wxT("%#" wxLongLongFmtSpec wxT("x")), *(PDWORD *)pAddress);
+            s.Printf("%#" wxLongLongFmtSpec "x", *(wxLongLong_t *)pAddress);
         }
     }
 
@@ -289,7 +302,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 +349,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;
 
@@ -359,6 +372,10 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
                     case SYMBOL_TAG_BASE_CLASS:
                         s = DumpUDT(&sym, pVariable, level);
                         break;
+
+                    default:
+                        // Suppress gcc warnings about unhandled enum values.
+                        break;
                 }
             }
 
@@ -367,6 +384,11 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
                 s = GetSymbolName(pSym) + wxT(" = ") + s;
             }
             break;
+
+        default:
+            // Suppress gcc warnings about unhandled enum values, don't assert
+            // to avoid problems during fatal crash generation.
+            break;
     }
 
     if ( !s.empty() )
@@ -378,7 +400,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;
 
@@ -445,7 +467,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++ )
@@ -477,7 +499,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 ( ;; )
@@ -514,12 +536,17 @@ 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:
+            // Suppress gcc warnings about unhandled enum values, don't assert
+            // to avoid problems during fatal crash generation.
+            break;
+
         case SYMBOL_TAG_UDT:
             // show UDT recursively
             s = DumpUDT(&symDeref, pVariable);
@@ -538,6 +565,316 @@ wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable)
     return s;
 }
 
+// ----------------------------------------------------------------------------
+// do the best functions and structures
+// ----------------------------------------------------------------------------
+
+struct wxMswEnmLddMdlsHelperStruct
+{
+public:
+    wxMswEnmLddMdlsHelperStruct(wxPENUMLOADED_MODULES_CALLBACK64 ptr, PVOID content)
+        : m_pointer_to_callback(ptr), m_user_content(content)
+    { }
+    wxPENUMLOADED_MODULES_CALLBACK64 m_pointer_to_callback;
+    PVOID m_user_content;
+};
+
+#ifdef UNICODE
+
+static BOOL CALLBACK wxMswEnmLddMdlsCallback1(
+    PCSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext)
+{
+    wxMswEnmLddMdlsHelperStruct& alternate =
+        *(wxMswEnmLddMdlsHelperStruct*)(UserContext);
+
+    const wxWCharBuffer buf = wxConvLocal.cMB2WC(ModuleName, wxNO_LEN, NULL);
+    return (*alternate.m_pointer_to_callback)
+        (buf.data(), ModuleBase, ModuleSize, alternate.m_user_content);
+}
+
+static BOOL CALLBACK wxMswEnmLddMdlsCallback2(
+    PCSTR ModuleName, DWORD_PTR ModuleBase, ULONG ModuleSize, PVOID UserContext)
+{
+    wxMswEnmLddMdlsHelperStruct& alternate =
+        *(wxMswEnmLddMdlsHelperStruct*)(UserContext);
+
+    const wxWCharBuffer buf = wxConvLocal.cMB2WC(ModuleName, wxNO_LEN, NULL);
+    return (*alternate.m_pointer_to_callback)
+        (buf.data(), ModuleBase, ModuleSize, alternate.m_user_content);
+}
+
+#else
+
+static BOOL CALLBACK wxMswEnmLddMdlsCallback(
+    PCSTR ModuleName, DWORD_PTR ModuleBase, ULONG ModuleSize, PVOID UserContext)
+{
+    wxMswEnmLddMdlsHelperStruct& alternate =
+        *(wxMswEnmLddMdlsHelperStruct*)(UserContext);
+
+    return (*alternate.m_pointer_to_callback)
+        (ModuleName, ModuleBase, ModuleSize, alternate.m_user_content);
+}
+
+#endif // UNICODE
+
+/* static */
+BOOL wxDbgHelpDLL::EnumerateLoadedModulesT(
+    HANDLE handle, wxPENUMLOADED_MODULES_CALLBACK64 callback, PVOID pvoid)
+{
+#ifdef UNICODE
+    if (EnumerateLoadedModulesW64)
+    {
+        const BOOL retVal = (*EnumerateLoadedModulesW64)(handle, callback, pvoid);
+        if (retVal)
+            return retVal;
+    }
+    if (EnumerateLoadedModules64)
+    {
+        wxMswEnmLddMdlsHelperStruct p(callback, pvoid);
+        const BOOL retVal =
+            (*EnumerateLoadedModules64)
+                (handle, &wxMswEnmLddMdlsCallback1, (PVOID)(&p));
+        if (retVal)
+            return retVal;
+    }
+    if (EnumerateLoadedModules)
+    {
+        wxMswEnmLddMdlsHelperStruct p(callback, pvoid);
+        const BOOL retVal =
+            (*EnumerateLoadedModules)
+                (handle, &wxMswEnmLddMdlsCallback2, (PVOID)(&p));
+        if (retVal)
+            return retVal;
+    }
+    return FALSE;
+#else
+    if (EnumerateLoadedModules64)
+    {
+        const BOOL retVal = (*EnumerateLoadedModules64)(handle, callback, pvoid);
+        if (retVal)
+            return retVal;
+    }
+    if (EnumerateLoadedModules)
+    {
+        wxMswEnmLddMdlsHelperStruct p(callback, pvoid);
+        const BOOL retVal =
+            (*EnumerateLoadedModules)
+                (handle, &wxMswEnmLddMdlsCallback, (PVOID)(&p));
+        if (retVal)
+            return retVal;
+    }
+    return FALSE;
+#endif
+}
+
+/* static */
+BOOL wxDbgHelpDLL::SymInitializeT(HANDLE hProcess, LPCTSTR UserSearchPath, BOOL fInvadeProcess)
+{
+#ifdef UNICODE
+    if (SymInitializeW)
+    {
+        const BOOL retVal = (*SymInitializeW)(hProcess, UserSearchPath, fInvadeProcess);
+        if (retVal)
+            return retVal;
+    }
+    if (SymInitialize)
+    {
+        BOOL retVal;
+        if (UserSearchPath)
+        {
+            const wxCharBuffer buf = wxConvLocal.cWC2MB(UserSearchPath, wxNO_LEN, NULL);
+            retVal = (*SymInitialize)(hProcess, buf.data(), fInvadeProcess);
+        }
+        else
+        {
+            retVal = (*SymInitialize)(hProcess, NULL, fInvadeProcess);
+        }
+        return retVal;
+    }
+    return FALSE;
+#else
+    if (SymInitialize)
+    {
+        return (*SymInitialize)(hProcess, UserSearchPath, fInvadeProcess);
+    }
+    return FALSE;
+#endif
+}
+
+/* static */
+BOOL wxDbgHelpDLL::SymFromAddrT(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, wxPSYMBOL_INFO Symbol)
+{
+#ifdef UNICODE
+    if (SymFromAddrW)
+    {
+        const BOOL retVal = (*SymFromAddrW)(hProcess, Address, Displacement, Symbol);
+        if (retVal)
+            return retVal;
+    }
+    if (SymFromAddr)
+    {
+        BYTE* symbolBuffer = new BYTE[sizeof(SYMBOL_INFO) + Symbol->MaxNameLen*sizeof(CHAR)];
+        PSYMBOL_INFO data = (SYMBOL_INFO*)(symbolBuffer);
+        wxZeroMemory(*data);
+        data->SizeOfStruct = sizeof(SYMBOL_INFO);
+        data->MaxNameLen = Symbol->MaxNameLen;
+        if (! (*SymFromAddr)(hProcess, Address, Displacement, data))
+        {
+            delete [] symbolBuffer;
+            return FALSE;
+        }
+
+        // We can't refer data->NameLen. It seems to be unmodified.
+        const wxWCharBuffer buf = wxConvLocal.cMB2WC(data->Name, wxNO_LEN, NULL);
+
+        // FIXME: I know too brute but some header names SYMBOL_INFO::Index
+        // and the other one defines it as SYMBOL_INFO::info.
+        const ULONG dstSize = Symbol->SizeOfStruct;
+        CopyMemory(Symbol, data, sizeof(SYMBOL_INFO)-sizeof(CHAR));
+        Symbol->SizeOfStruct = dstSize;
+        Symbol->NameLen = buf.length();
+        wxStrncpy(Symbol->Name, buf.data(), Symbol->MaxNameLen);
+        delete [] symbolBuffer;
+        return TRUE;
+    }
+    return FALSE;
+#else
+    if (SymFromAddr)
+    {
+        return (*SymFromAddr)(hProcess, Address, Displacement, Symbol);
+    }
+    return FALSE;
+#endif
+}
+
+/* static */
+BOOL wxDbgHelpDLL::SymGetLineFromAddrT(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdrDisplacement, wxPIMAGEHLP_LINE Line)
+{
+#ifdef UNICODE
+    if (SymGetLineFromAddrW64)
+    {
+        const BOOL retVal = (*SymGetLineFromAddrW64)(hProcess, dwAddr, pdrDisplacement, Line);
+        if (retVal)
+            return retVal;
+        // TODO: seems always fail with GetLastError() returns 487 with 32bit binary on 64 bit Windows.
+    }
+    static WCHAR staticBuf[MAX_PATH];
+    if (SymGetLineFromAddr64)
+    {
+        IMAGEHLP_LINE64 LineAlternate;
+        LineAlternate.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+        if ((*SymGetLineFromAddr64)(hProcess, dwAddr, pdrDisplacement, &LineAlternate))
+        {
+            const wxWCharBuffer ConvBuf =
+                wxConvLocal.cMB2WC(LineAlternate.FileName, wxNO_LEN, NULL);
+            wxStrncpy(staticBuf, ConvBuf.data(), MAX_PATH);
+            Line->Key = LineAlternate.Key;
+            Line->LineNumber = LineAlternate.LineNumber;
+            Line->FileName = staticBuf;
+            Line->Address = LineAlternate.Address;
+            return TRUE;
+        }
+    }
+    if (SymGetLineFromAddr)
+    {
+        IMAGEHLP_LINE LineAlternate;
+        LineAlternate.SizeOfStruct = sizeof(IMAGEHLP_LINE);
+        if ((*SymGetLineFromAddr)(hProcess, dwAddr, pdrDisplacement, &LineAlternate))
+        {
+            const wxWCharBuffer ConvBuf =
+                wxConvLocal.cMB2WC(LineAlternate.FileName, wxNO_LEN, NULL);
+            wxStrncpy(staticBuf, ConvBuf.data(), MAX_PATH);
+            Line->Key = LineAlternate.Key;
+            Line->LineNumber = LineAlternate.LineNumber;
+            Line->FileName = staticBuf;
+            Line->Address = LineAlternate.Address;
+            return TRUE;
+        }
+    }
+    return FALSE;
+#else
+    if (SymGetLineFromAddr64)
+    {
+        return (*SymGetLineFromAddr64)(hProcess, dwAddr, pdrDisplacement, Line);
+    }
+    if (SymGetLineFromAddr)
+    {
+        IMAGEHLP_LINE LineAlternate;
+        LineAlternate.SizeOfStruct = sizeof(IMAGEHLP_LINE);
+        if ((*SymGetLineFromAddr)(hProcess, dwAddr, pdrDisplacement, &LineAlternate))
+        {
+            Line->Key = LineAlternate.Key;
+            Line->LineNumber = LineAlternate.LineNumber;
+            Line->FileName = LineAlternate.FileName;
+            Line->Address = LineAlternate.Address;
+            return TRUE;
+        }
+    }
+    return FALSE;
+#endif
+}
+
+struct wxMswSymEnumSymbolsHelperStruct
+{
+public:
+    wxMswSymEnumSymbolsHelperStruct(PSYM_ENUMERATESYMBOLS_CALLBACKW ptr, PVOID content)
+        : m_pointer_to_callback(ptr), m_user_content(content)
+    { }
+    PSYM_ENUMERATESYMBOLS_CALLBACKW m_pointer_to_callback;
+    PVOID m_user_content;
+};
+
+#ifdef UNICODE
+
+static BOOL CALLBACK wxMswSymEnumSymbolsHelperCallback(
+    PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
+{
+    wxMswSymEnumSymbolsHelperStruct& alternate =
+        *(wxMswSymEnumSymbolsHelperStruct*)(UserContext);
+    const wxWCharBuffer buf = wxConvLocal.cMB2WC(pSymInfo->Name, pSymInfo->MaxNameLen, NULL);
+    BYTE* symbolBuffer = new BYTE[sizeof(SYMBOL_INFOW) + buf.length()*sizeof(WCHAR)];
+    SYMBOL_INFOW* data = (SYMBOL_INFOW*)(symbolBuffer);
+
+    // FIXME: I know too brute but some header names SYMBOL_INFO::Index
+    // and the other one defines it as SYMBOL_INFO::info.
+    CopyMemory(data, pSymInfo, sizeof(SYMBOL_INFO)-sizeof(CHAR));
+    data->SizeOfStruct = sizeof(SYMBOL_INFOW);
+    wxStrncpy(data->Name, buf.data(), buf.length());
+    BOOL retVal = (*alternate.m_pointer_to_callback)(data, SymbolSize, alternate.m_user_content);
+    delete [] symbolBuffer;
+    return retVal;
+}
+
+#endif // UNICODE
+
+/* static */
+BOOL wxDbgHelpDLL::SymEnumSymbolsT(HANDLE hProcess, ULONG64 baseOfDll, PCTSTR Mask,
+                    wxPSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, const PVOID UserContext)
+{
+#ifdef UNICODE
+    if (SymEnumSymbolsW)
+    {
+        const BOOL retVal = (*SymEnumSymbolsW)(hProcess, baseOfDll, Mask, EnumSymbolsCallback, UserContext);
+        if (retVal)
+            return retVal;
+    }
+    if (SymEnumSymbols)
+    {
+        wxMswSymEnumSymbolsHelperStruct p(EnumSymbolsCallback, UserContext);
+        const wxCharBuffer buf = wxConvLocal.cWC2MB(Mask ? Mask : L"", wxNO_LEN, NULL);
+        return (*SymEnumSymbols)(hProcess, baseOfDll, buf.data(),
+                                 wxMswSymEnumSymbolsHelperCallback, (PVOID)(&p));
+    }
+    return FALSE;
+#else
+    if (SymEnumSymbols)
+    {
+        return (*SymEnumSymbols)(hProcess, baseOfDll, Mask, EnumSymbolsCallback, UserContext);
+    }
+    return FALSE;
+#endif
+}
+
 // ----------------------------------------------------------------------------
 // debugging helpers
 // ----------------------------------------------------------------------------