fix Wx ABI check for Win32/MinGW

Fix error dialog boxes popping up when the Wx ABI compat tests are run
from cmake.

Wx 3.x is hardcoded to use MessageBox for wxLogFatalError(), even in a
console app, so use the minhook trampoline lib (added to dependencies)
to hook the Win32 API MessageBoxW and MessageBoxA (the second just in
case) so that no error dialogs pop up.

Details here:

https://www.codeproject.com/Articles/44326/MinHook-The-Minimalistic-x-x-API-Hooking-Libra
This commit is contained in:
Rafael Kitover 2017-09-10 11:00:24 -07:00
parent 42f6c446ea
commit de95c70547
2 changed files with 73 additions and 7 deletions

@ -1 +1 @@
Subproject commit 76e2d57b891b11aeb203d906fc6c171d7d8b739e Subproject commit aa2499de8fdf2f804c4ed624b4d8f17c1e304fb0

View File

@ -81,6 +81,11 @@ ENDFOREACH()
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${MY_CXX_FLAGS} ${MY_C_FLAGS} ${MY_CXX_LINKER_FLAGS} ${MY_C_LINKER_FLAGS} ${wxWidgets_LIBRARIES}) SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${MY_CXX_FLAGS} ${MY_C_FLAGS} ${MY_CXX_LINKER_FLAGS} ${MY_C_LINKER_FLAGS} ${wxWidgets_LIBRARIES})
SET(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${wxWidgets_CXX_FLAGS} ${MY_CXX_FLAGS} ${MY_C_FLAGS}) SET(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${wxWidgets_CXX_FLAGS} ${MY_CXX_FLAGS} ${MY_C_FLAGS})
IF(WIN32)
SET(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} "-Wl,--subsystem,console")
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} "-Wl,--subsystem,console")
ENDIF()
SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${wxWidgets_INCLUDE_DIRS}) SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${wxWidgets_INCLUDE_DIRS})
FOREACH(DEF ${wxWidgets_DEFINITIONS}) FOREACH(DEF ${wxWidgets_DEFINITIONS})
@ -109,13 +114,40 @@ IF(NOT WX_HAS_OPENGL)
ENDIF() ENDIF()
IF(CMAKE_COMPILER_IS_GNUCXX) IF(CMAKE_COMPILER_IS_GNUCXX)
SET(WX_ABI_FOUND_MATCH FALSE)
INCLUDE(CheckCXXSourceRuns) INCLUDE(CheckCXXSourceRuns)
SET(WX_TEST_CONSOLE_APP " SET(WX_TEST_CONSOLE_APP "
#include <cstdlib> #include <cstdlib>
#include <iostream>
#include <wx/wxprec.h> #include <wx/wxprec.h>
#include <wx/wx.h> #include <wx/wx.h>
#ifdef _WIN32
#include <windows.h>
#include \"MinHook.h\"
typedef int (WINAPI *MESSAGEBOXW)(HWND, LPCWSTR, LPCWSTR, UINT);
typedef int (WINAPI *MESSAGEBOXA)(HWND, LPCSTR, LPCSTR, UINT);
// Pointers for calling original MessageBoxW/A.
MESSAGEBOXW fpMessageBoxW = NULL;
MESSAGEBOXA fpMessageBoxA = NULL;
// Detour function which overrides MessageBoxW.
int WINAPI DetourMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
std::wcerr << lpCaption << \": \" << lpText << std::endl;
}
// Detour function which overrides MessageBoxA.
int WINAPI DetourMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
std::cerr << lpCaption << \": \" << lpText << std::endl;
}
#endif
class MyApp : public wxAppConsole { class MyApp : public wxAppConsole {
public: public:
virtual bool OnInit(); virtual bool OnInit();
@ -125,9 +157,42 @@ bool MyApp::OnInit() {
exit(0); exit(0);
} }
wxIMPLEMENT_APP(MyApp); wxIMPLEMENT_APP_NO_MAIN(MyApp);
int main(int argc, char** argv)
{
#ifdef _WIN32
// just in case (this does nothing though)
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
// we need to install a trampoline for messageboxes, because Wx is
// hard-coded to show a messagebox on wxLogFatalError()
// Initialize MinHook (for trampoline).
if (MH_Initialize() != MH_OK) return 1;
// Create a hook for MessageBoxW and MessageBoxA
if (MH_CreateHook(&MessageBoxW, &DetourMessageBoxW, reinterpret_cast<LPVOID*>(&fpMessageBoxW)) != MH_OK)
return 1;
if (MH_CreateHook(&MessageBoxA, &DetourMessageBoxA, reinterpret_cast<LPVOID*>(&fpMessageBoxA)) != MH_OK)
return 1;
if (MH_EnableHook(&MessageBoxW) != MH_OK) return 1;
if (MH_EnableHook(&MessageBoxA) != MH_OK) return 1;
#endif
wxEntry(argc, argv);
wxEntryCleanup();
return 0;
}
") ")
# on windows we need the trampoline library from dependencies
IF(WIN32)
SET(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -w -fpermissive "-I${CMAKE_SOURCE_DIR}/dependencies/minhook/include")
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} -Wl,--subsystem,console "${CMAKE_SOURCE_DIR}/dependencies/minhook/libMinHook.a")
ENDIF()
CHECK_CXX_SOURCE_RUNS("${WX_TEST_CONSOLE_APP}" WX_DEFAULT_ABI_VERSION_COMPATIBLE) CHECK_CXX_SOURCE_RUNS("${WX_TEST_CONSOLE_APP}" WX_DEFAULT_ABI_VERSION_COMPATIBLE)
IF(NOT WX_DEFAULT_ABI_VERSION_COMPATIBLE) IF(NOT WX_DEFAULT_ABI_VERSION_COMPATIBLE)
@ -146,6 +211,7 @@ wxIMPLEMENT_APP(MyApp);
CHECK_CXX_SOURCE_RUNS("${WX_TEST_CONSOLE_APP}" ${WX_ABI_VAR}) CHECK_CXX_SOURCE_RUNS("${WX_TEST_CONSOLE_APP}" ${WX_ABI_VAR})
IF(${${WX_ABI_VAR}}) IF(${${WX_ABI_VAR}})
SET(WX_ABI_FOUND_MATCH TRUE)
BREAK() BREAK()
ENDIF() ENDIF()
@ -154,12 +220,12 @@ wxIMPLEMENT_APP(MyApp);
SET(CMAKE_REQUIRED_DEFINITIONS ${CURRENT_DEFS}) SET(CMAKE_REQUIRED_DEFINITIONS ${CURRENT_DEFS})
SET(CMAKE_REQUIRED_LIBRARIES ${CURRENT_LIBS}) SET(CMAKE_REQUIRED_LIBRARIES ${CURRENT_LIBS})
ENDIF()
IF(${${WX_ABI_VAR}}) IF(WX_ABI_FOUND_MATCH)
# add C++ flags # add C++ flags
STRING(REGEX REPLACE "<FLAGS>" "<FLAGS> -fabi-version=${WX_ABI_VERSION} " CMAKE_CXX_COMPILE_OBJECT ${CMAKE_CXX_COMPILE_OBJECT}) STRING(REGEX REPLACE "<FLAGS>" "<FLAGS> -fabi-version=${WX_ABI_VERSION} " CMAKE_CXX_COMPILE_OBJECT ${CMAKE_CXX_COMPILE_OBJECT})
SET(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -fabi-version=${WX_ABI_VERSION}") SET(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -fabi-version=${WX_ABI_VERSION}")
ENDIF()
ENDIF() ENDIF()
ENDIF() ENDIF()