mirror of
https://github.com/beefytech/Beef.git
synced 2025-07-14 12:13:51 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
198
BeefySysLib/platform/win/BFPlatform.h
Normal file
198
BeefySysLib/platform/win/BFPlatform.h
Normal file
|
@ -0,0 +1,198 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#if (defined __MINGW32__) && (!defined BF_MINGW)
|
||||
#define BF_MINGW
|
||||
#endif
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define BF_PLATFORM_WINDOWS
|
||||
#define BF_PLATFORM_NAME "BF_PLATFORM_WINDOWS"
|
||||
|
||||
#ifdef BF_MINGW
|
||||
#pragma clang diagnostic ignored "-Wunused-variable"
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
#pragma clang diagnostic ignored "-Wunknown-attributes"
|
||||
#pragma clang diagnostic ignored "-Wunused-member-function"
|
||||
#pragma clang diagnostic ignored "-Wunused-conversion-function"
|
||||
#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else
|
||||
#define BF_VC
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <wtypes.h>
|
||||
|
||||
#define DIR_SEP_CHAR '\\'
|
||||
#define DIR_SEP_CHAR_ALT '/'
|
||||
|
||||
#ifndef BF_NO_FFI
|
||||
extern "C"
|
||||
{
|
||||
#define FFI_BUILDING
|
||||
#include "libffi/i686-pc-cygwin/include/ffi.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
//#define BF_FORCE_SDL
|
||||
|
||||
#ifdef SDL_FORCE_OPENGL_ES2
|
||||
#define BF_PLATFORM_OPENGL_ES2
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER == 1800) && (!defined BFSYSLIB_STATIC)
|
||||
#define BF_WWISE_ENABLED
|
||||
#endif
|
||||
|
||||
#define CPP11
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define BF_DEBUG
|
||||
//#define DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef BF_MINGW
|
||||
#define NOP asm volatile("nop");
|
||||
extern "C" _CRTIMP int __cdecl __MINGW_NOTHROW _stricmp (const char*, const char*);
|
||||
#elif defined _WIN64
|
||||
#define BF64
|
||||
#define NOP GetTickCount()
|
||||
#else
|
||||
#define BF32
|
||||
#define NOP __asm nop;
|
||||
#endif
|
||||
|
||||
#define BF_HAS_TLS_DECLSPEC
|
||||
#ifdef BF_MINGW
|
||||
#define BF_TLS_DECLSPEC __thread
|
||||
#else
|
||||
#define BF_TLS_DECLSPEC __declspec(thread)
|
||||
#endif
|
||||
|
||||
#if defined _DEBUG || defined BF_DEBUG_ASSERTS
|
||||
#define BF_ASSERT(_Expression) (void)( (!!(_Expression)) || (Beefy::BFFatalError(#_Expression, __FILE__, __LINE__), 0) )
|
||||
#else
|
||||
#define BF_ASSERT(_Expression) (void)(0)
|
||||
#endif
|
||||
|
||||
#define BF_ASSERT_REL(_Expression) (void)( (!!(_Expression)) || (Beefy::BFFatalError(#_Expression, __FILE__, __LINE__), 0) )
|
||||
#define BF_FATAL(msg) (void) ((Beefy::BFFatalError(msg, __FILE__, __LINE__), 0) )
|
||||
|
||||
#if defined _DEBUG || defined BF_DEBUG_ASSERTS
|
||||
#define BF_DBG_FATAL(msg) (void) ((Beefy::BFFatalError(msg, __FILE__, __LINE__), 0) )
|
||||
#else
|
||||
#define BF_DBG_FATAL(msg)
|
||||
#endif
|
||||
|
||||
#define BFSTDCALL __stdcall
|
||||
|
||||
#define BF_IMPORT extern "C" __declspec(dllimport)
|
||||
|
||||
#ifdef BFSYSLIB_DYNAMIC
|
||||
#define BF_EXPORT extern "C" __declspec(dllexport)
|
||||
#define BF_CALLTYPE __stdcall
|
||||
#else
|
||||
#define BF_EXPORT extern "C"
|
||||
#define BF_CALLTYPE __stdcall
|
||||
#endif
|
||||
|
||||
#define BF_NOINLINE __declspec(noinline)
|
||||
#define BF_NAKED __declspec(naked)
|
||||
|
||||
#define BF_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
|
||||
#define BF_ALIGNED(x) __declspec(align(x))
|
||||
|
||||
#ifndef BF_MINGW
|
||||
#define strtoull _strtoui64
|
||||
#endif
|
||||
//#define snprintf _snprintf
|
||||
#define __func__ __FUNCTION__
|
||||
|
||||
typedef uint64_t uint64;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint8_t uint8;
|
||||
typedef int64_t int64;
|
||||
typedef int32_t int32;
|
||||
typedef int16_t int16;
|
||||
typedef int8_t int8;
|
||||
typedef unsigned int uint;
|
||||
|
||||
typedef intptr_t intptr;
|
||||
typedef uintptr_t uintptr;
|
||||
|
||||
typedef DWORD BF_THREADID;
|
||||
typedef HANDLE BF_THREADHANDLE;
|
||||
|
||||
#ifdef BF_MINGW
|
||||
#define BF_COMPILER_FENCE() __asm__ __volatile__("mfence" : : : "memory");
|
||||
#define BF_FULL_MEMORY_FENCE() __asm__ __volatile__("mfence" : : : "memory");
|
||||
#define BF_SPINWAIT_NOP() __asm__ __volatile__( "pause;" )
|
||||
#define BF_DEBUG_BREAK() __asm__ __volatile__( "int $0x03;" )
|
||||
#else
|
||||
#define BF_COMPILER_FENCE() _ReadWriteBarrier()
|
||||
//#define BF_FULL_MEMORY_FENCE() __asm { lock add dword ptr [esp],0 }
|
||||
|
||||
#ifdef BF32
|
||||
#define BF_FULL_MEMORY_FENCE() ::MemoryBarrier()
|
||||
#else
|
||||
#define BF_FULL_MEMORY_FENCE() _mm_mfence()
|
||||
#endif
|
||||
|
||||
//#define BF_SPINWAIT_NOP() _asm { pause }
|
||||
#define BF_SPINWAIT_NOP() _mm_pause()
|
||||
#define BF_DEBUG_BREAK() DebugBreak()
|
||||
#endif
|
||||
|
||||
typedef DWORD BfTLSKey;
|
||||
#define BfTLSGetValue ::TlsGetValue
|
||||
#define BfTLSSetValue ::TlsSetValue
|
||||
#define BfTLSAlloc ::TlsAlloc
|
||||
#define BfTLSFree ::TlsFree
|
||||
|
||||
#define BF_THREAD_YIELD() ::SwitchToThread()
|
||||
|
||||
#define BF_UNUSED
|
||||
#define BF_EXPLICIT explicit
|
||||
|
||||
#define BF_ENDIAN_LITTLE
|
||||
|
||||
#define WaitForSingleObject_Thread WaitForSingleObject
|
||||
#define CloseHandle_File CloseHandle
|
||||
#define CloseHandle_Event CloseHandle
|
||||
#define CloseHandle_Thread CloseHandle
|
||||
#define CloseHandle_Process CloseHandle
|
||||
|
||||
#ifdef BF32
|
||||
#define BF_REGISTER_COUNT 7
|
||||
#else
|
||||
#define BF_REGISTER_COUNT 15
|
||||
#endif
|
||||
|
||||
#ifndef BF_MINGW
|
||||
#define __thread __declspec(thread)
|
||||
#endif
|
||||
|
||||
#ifdef BF_MINGW
|
||||
//
|
||||
#else
|
||||
#define strcasecmp stricmp
|
||||
#endif
|
||||
|
||||
struct BfpEvent
|
||||
{
|
||||
CRITICAL_SECTION mCritSect;
|
||||
CONDITION_VARIABLE mCondVariable;
|
||||
bool mSet;
|
||||
bool mManualReset;
|
||||
};
|
||||
|
||||
#include "../PlatformInterface.h"
|
945
BeefySysLib/platform/win/CrashCatcher.cpp
Normal file
945
BeefySysLib/platform/win/CrashCatcher.cpp
Normal file
|
@ -0,0 +1,945 @@
|
|||
#include "CrashCatcher.h"
|
||||
#include "../util/CritSect.h"
|
||||
|
||||
USING_NS_BF;
|
||||
|
||||
#pragma warning(disable:4091)
|
||||
#pragma warning(disable:4996)
|
||||
#include <imagehlp.h>
|
||||
|
||||
#ifdef BF64
|
||||
typedef BOOL(__stdcall * SYMINITIALIZEPROC)(HANDLE, LPSTR, BOOL);
|
||||
typedef DWORD(__stdcall *SYMSETOPTIONSPROC)(DWORD);
|
||||
typedef BOOL(__stdcall *SYMCLEANUPPROC)(HANDLE);
|
||||
typedef LPCSTR(__stdcall *UNDECORATESYMBOLNAMEPROC)(LPCSTR, LPSTR, DWORD, DWORD);
|
||||
typedef BOOL(__stdcall * STACKWALKPROC)
|
||||
(DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID,
|
||||
PREAD_PROCESS_MEMORY_ROUTINE, PFUNCTION_TABLE_ACCESS_ROUTINE,
|
||||
PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE);
|
||||
typedef LPVOID(__stdcall *SYMFUNCTIONTABLEACCESSPROC)(HANDLE, DWORD64);
|
||||
typedef DWORD64 (__stdcall *SYMGETMODULEBASEPROC)(HANDLE, DWORD64);
|
||||
typedef BOOL(__stdcall *SYMGETSYMFROMADDRPROC)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
|
||||
typedef BOOL(__stdcall *SYMGETLINEFROMADDR)(HANDLE hProcess, DWORD64 qwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line64);
|
||||
#else
|
||||
typedef BOOL(__stdcall * SYMINITIALIZEPROC)(HANDLE, LPSTR, BOOL);
|
||||
typedef DWORD(__stdcall *SYMSETOPTIONSPROC)(DWORD);
|
||||
typedef BOOL(__stdcall *SYMCLEANUPPROC)(HANDLE);
|
||||
typedef LPCSTR(__stdcall *UNDECORATESYMBOLNAMEPROC)(LPCSTR, LPSTR, DWORD, DWORD);
|
||||
typedef BOOL(__stdcall * STACKWALKPROC)
|
||||
(DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID,
|
||||
PREAD_PROCESS_MEMORY_ROUTINE, PFUNCTION_TABLE_ACCESS_ROUTINE,
|
||||
PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE);
|
||||
typedef LPVOID(__stdcall *SYMFUNCTIONTABLEACCESSPROC)(HANDLE, DWORD);
|
||||
typedef DWORD(__stdcall *SYMGETMODULEBASEPROC)(HANDLE, DWORD);
|
||||
typedef BOOL(__stdcall *SYMGETSYMFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL);
|
||||
typedef BOOL(__stdcall *SYMGETLINEFROMADDR)(HANDLE hProcess, DWORD qwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line64);
|
||||
#endif
|
||||
|
||||
static HMODULE gImageHelpLib = NULL;
|
||||
static SYMINITIALIZEPROC gSymInitialize = NULL;
|
||||
static SYMSETOPTIONSPROC gSymSetOptions = NULL;
|
||||
static UNDECORATESYMBOLNAMEPROC gUnDecorateSymbolName = NULL;
|
||||
static SYMCLEANUPPROC gSymCleanup = NULL;
|
||||
static STACKWALKPROC gStackWalk = NULL;
|
||||
static SYMFUNCTIONTABLEACCESSPROC gSymFunctionTableAccess = NULL;
|
||||
static SYMGETMODULEBASEPROC gSymGetModuleBase = NULL;
|
||||
static SYMGETSYMFROMADDRPROC gSymGetSymFromAddr = NULL;
|
||||
static SYMGETLINEFROMADDR gSymGetLineFromAddr = NULL;
|
||||
static Array<CrashInfoFunc> gCrashInfoFuncs;
|
||||
static StringT<0> gCrashInfo;
|
||||
static bool gCrashed = false;
|
||||
extern CritSect gBfpCritSect;
|
||||
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER gPreviousFilter = NULL;
|
||||
|
||||
static bool gDebugError = false;
|
||||
|
||||
static bool LoadImageHelp()
|
||||
{
|
||||
gImageHelpLib = LoadLibraryA("IMAGEHLP.DLL");
|
||||
if (!gImageHelpLib)
|
||||
return false;
|
||||
|
||||
gSymInitialize = (SYMINITIALIZEPROC)GetProcAddress(gImageHelpLib, "SymInitialize");
|
||||
if (!gSymInitialize)
|
||||
return false;
|
||||
|
||||
gSymSetOptions = (SYMSETOPTIONSPROC)GetProcAddress(gImageHelpLib, "SymSetOptions");
|
||||
if (!gSymSetOptions)
|
||||
return false;
|
||||
|
||||
gSymCleanup = (SYMCLEANUPPROC)GetProcAddress(gImageHelpLib, "SymCleanup");
|
||||
if (!gSymCleanup)
|
||||
return false;
|
||||
|
||||
gUnDecorateSymbolName = (UNDECORATESYMBOLNAMEPROC)GetProcAddress(gImageHelpLib, "UnDecorateSymbolName");
|
||||
if (!gUnDecorateSymbolName)
|
||||
return false;
|
||||
|
||||
gStackWalk = (STACKWALKPROC)GetProcAddress(gImageHelpLib, "StackWalk");
|
||||
if (!gStackWalk)
|
||||
return false;
|
||||
|
||||
gSymFunctionTableAccess = (SYMFUNCTIONTABLEACCESSPROC)GetProcAddress(gImageHelpLib, "SymFunctionTableAccess");
|
||||
if (!gSymFunctionTableAccess)
|
||||
return false;
|
||||
|
||||
gSymGetModuleBase = (SYMGETMODULEBASEPROC)GetProcAddress(gImageHelpLib, "SymGetModuleBase");
|
||||
if (!gSymGetModuleBase)
|
||||
return false;
|
||||
|
||||
gSymGetSymFromAddr = (SYMGETSYMFROMADDRPROC)GetProcAddress(gImageHelpLib, "SymGetSymFromAddr");
|
||||
if (!gSymGetSymFromAddr)
|
||||
return false;
|
||||
|
||||
gSymGetLineFromAddr = (SYMGETLINEFROMADDR)GetProcAddress(gImageHelpLib, "SymGetLineFromAddr64");
|
||||
if (!gSymGetLineFromAddr)
|
||||
return false;
|
||||
|
||||
gSymSetOptions(SYMOPT_DEFERRED_LOADS);
|
||||
|
||||
// Get image filename of the main executable
|
||||
char filepath[MAX_PATH], *lastdir, *pPath;
|
||||
DWORD filepathlen = GetModuleFileNameA(NULL, filepath, sizeof(filepath));
|
||||
|
||||
lastdir = strrchr(filepath, '/');
|
||||
if (lastdir == NULL) lastdir = strrchr(filepath, '\\');
|
||||
if (lastdir != NULL) lastdir[0] = '\0';
|
||||
|
||||
// Initialize the symbol table routines, supplying a pointer to the path
|
||||
pPath = filepath;
|
||||
if (filepath[0] == 0) pPath = NULL;
|
||||
|
||||
if (!gSymInitialize(GetCurrentProcess(), pPath, TRUE))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct
|
||||
{
|
||||
DWORD dwExceptionCode;
|
||||
char *szMessage;
|
||||
} gMsgTable[] = {
|
||||
{ STATUS_SEGMENT_NOTIFICATION, "Segment Notification" },
|
||||
{ STATUS_BREAKPOINT, "Breakpoint" },
|
||||
{ STATUS_SINGLE_STEP, "Single step" },
|
||||
{ STATUS_WAIT_0, "Wait 0" },
|
||||
{ STATUS_ABANDONED_WAIT_0, "Abandoned Wait 0" },
|
||||
{ STATUS_USER_APC, "User APC" },
|
||||
{ STATUS_TIMEOUT, "Timeout" },
|
||||
{ STATUS_PENDING, "Pending" },
|
||||
{ STATUS_GUARD_PAGE_VIOLATION, "Guard Page Violation" },
|
||||
{ STATUS_DATATYPE_MISALIGNMENT, "Data Type Misalignment" },
|
||||
{ STATUS_ACCESS_VIOLATION, "Access Violation" },
|
||||
{ STATUS_IN_PAGE_ERROR, "In Page Error" },
|
||||
{ STATUS_NO_MEMORY, "No Memory" },
|
||||
{ STATUS_ILLEGAL_INSTRUCTION, "Illegal Instruction" },
|
||||
{ STATUS_NONCONTINUABLE_EXCEPTION, "Noncontinuable Exception" },
|
||||
{ STATUS_INVALID_DISPOSITION, "Invalid Disposition" },
|
||||
{ STATUS_ARRAY_BOUNDS_EXCEEDED, "Array Bounds Exceeded" },
|
||||
{ STATUS_FLOAT_DENORMAL_OPERAND, "Float Denormal Operand" },
|
||||
{ STATUS_FLOAT_DIVIDE_BY_ZERO, "Divide by Zero" },
|
||||
{ STATUS_FLOAT_INEXACT_RESULT, "Float Inexact Result" },
|
||||
{ STATUS_FLOAT_INVALID_OPERATION, "Float Invalid Operation" },
|
||||
{ STATUS_FLOAT_OVERFLOW, "Float Overflow" },
|
||||
{ STATUS_FLOAT_STACK_CHECK, "Float Stack Check" },
|
||||
{ STATUS_FLOAT_UNDERFLOW, "Float Underflow" },
|
||||
{ STATUS_INTEGER_DIVIDE_BY_ZERO, "Integer Divide by Zero" },
|
||||
{ STATUS_INTEGER_OVERFLOW, "Integer Overflow" },
|
||||
{ STATUS_PRIVILEGED_INSTRUCTION, "Privileged Instruction" },
|
||||
{ STATUS_STACK_OVERFLOW, "Stack Overflow" },
|
||||
{ STATUS_CONTROL_C_EXIT, "Ctrl+C Exit" },
|
||||
{ 0xFFFFFFFF, "" }
|
||||
};
|
||||
|
||||
static bool gUseDefaultFonts;
|
||||
static HFONT gDialogFont;
|
||||
static HFONT gBoldFont;
|
||||
static String gErrorTitle;
|
||||
static String gErrorText;
|
||||
static HWND gDebugButtonWindow = NULL;
|
||||
static HWND gYesButtonWindow = NULL;
|
||||
static HWND gNoButtonWindow = NULL;
|
||||
static bool gExiting = false;
|
||||
static BfpCrashReportKind gCrashReportKind = BfpCrashReportKind_Default;
|
||||
|
||||
static LRESULT CALLBACK SEHWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_COMMAND:
|
||||
{
|
||||
HWND hwndCtl = (HWND)lParam;
|
||||
if (hwndCtl == gYesButtonWindow)
|
||||
{
|
||||
// Hide current window and bring up score submitting stuff
|
||||
ShowWindow(hWnd, SW_HIDE);
|
||||
|
||||
//ShowSubmitInfoDialog();
|
||||
}
|
||||
else if (hwndCtl == gNoButtonWindow)
|
||||
{
|
||||
gExiting = true;
|
||||
}
|
||||
else if (hwndCtl == gDebugButtonWindow)
|
||||
{
|
||||
gDebugError = true;
|
||||
gExiting = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
gExiting = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
static void ShowErrorDialog(const StringImpl& errorTitle, const StringImpl& errorText)
|
||||
{
|
||||
HINSTANCE gHInstance = ::GetModuleHandle(NULL);
|
||||
|
||||
OSVERSIONINFO aVersionInfo;
|
||||
aVersionInfo.dwOSVersionInfoSize = sizeof(aVersionInfo);
|
||||
GetVersionEx(&aVersionInfo);
|
||||
|
||||
// Setting fonts on 98 causes weirdo crash things in GDI upon the second crash.
|
||||
// That's no good.
|
||||
gUseDefaultFonts = aVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT;
|
||||
|
||||
int aHeight = -MulDiv(8, 96, 72);
|
||||
gDialogFont = ::CreateFontA(aHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
|
||||
false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
||||
DEFAULT_PITCH | FF_DONTCARE, "Tahoma");
|
||||
|
||||
aHeight = -MulDiv(10, 96, 72);
|
||||
gBoldFont = ::CreateFontA(aHeight, 0, 0, 0, FW_BOLD, FALSE, FALSE,
|
||||
false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
||||
DEFAULT_PITCH | FF_DONTCARE, "Tahoma");
|
||||
|
||||
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
|
||||
|
||||
gErrorTitle = errorTitle;
|
||||
gErrorText = errorText;
|
||||
|
||||
|
||||
WNDCLASSW wc;
|
||||
wc.style = 0;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hbrBackground = ::GetSysColorBrush(COLOR_BTNFACE);
|
||||
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hIcon = ::LoadIcon(NULL, IDI_ERROR);
|
||||
wc.hInstance = gHInstance;
|
||||
wc.lpfnWndProc = SEHWindowProc;
|
||||
wc.lpszClassName = L"SEHWindow";
|
||||
wc.lpszMenuName = NULL;
|
||||
RegisterClassW(&wc);
|
||||
|
||||
RECT aRect;
|
||||
aRect.left = 0;
|
||||
aRect.top = 0;
|
||||
aRect.right = 500;
|
||||
aRect.bottom = 400;
|
||||
|
||||
DWORD aWindowStyle = WS_CLIPCHILDREN | WS_POPUP | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
|
||||
|
||||
RECT windowRect = aRect;
|
||||
BOOL worked = AdjustWindowRect(&windowRect, aWindowStyle, FALSE);
|
||||
|
||||
HWND aHWnd = ::CreateWindowExW(0, L"SEHWindow", L"Fatal Error!",
|
||||
aWindowStyle,
|
||||
64, 64,
|
||||
windowRect.right - windowRect.left,
|
||||
windowRect.bottom - windowRect.top,
|
||||
NULL,
|
||||
NULL,
|
||||
gHInstance,
|
||||
0);
|
||||
|
||||
int textHeight = 30;
|
||||
|
||||
HWND aLabelWindow = ::CreateWindowW(L"EDIT",
|
||||
L"An unexpected error has occured!",
|
||||
WS_VISIBLE | WS_CHILD | ES_MULTILINE | ES_READONLY,
|
||||
8, 8,
|
||||
aRect.right - 8 - 8,
|
||||
textHeight,
|
||||
aHWnd,
|
||||
NULL,
|
||||
gHInstance,
|
||||
0);
|
||||
|
||||
int aFontHeight = -MulDiv(9, 96, 72);
|
||||
HFONT aBoldArialFont = CreateFontA(aFontHeight, 0, 0, 0, FW_BOLD, 0, 0,
|
||||
false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
||||
DEFAULT_PITCH | FF_DONTCARE, "Arial");
|
||||
|
||||
if (!gUseDefaultFonts)
|
||||
SendMessage(aLabelWindow, WM_SETFONT, (WPARAM)aBoldArialFont, 0);
|
||||
|
||||
HWND anEditWindow = CreateWindowA("EDIT", errorText.c_str(),
|
||||
WS_VISIBLE | WS_CHILD | ES_MULTILINE | WS_BORDER | WS_HSCROLL | WS_VSCROLL | ES_READONLY,
|
||||
8, textHeight + 8,
|
||||
aRect.right - 8 - 8,
|
||||
aRect.bottom - textHeight - 24 - 8 - 8 - 8,
|
||||
aHWnd,
|
||||
NULL,
|
||||
gHInstance,
|
||||
0);
|
||||
|
||||
aFontHeight = -MulDiv(8, 96, 72);
|
||||
HFONT aCourierNewFont = CreateFontA(aFontHeight, 0, 0, 0, FW_NORMAL, 0, 0,
|
||||
false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
||||
DEFAULT_PITCH | FF_DONTCARE, "Courier New");
|
||||
if (!gUseDefaultFonts)
|
||||
SendMessage(anEditWindow, WM_SETFONT, (WPARAM)aCourierNewFont, 0);
|
||||
|
||||
aWindowStyle = WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | BS_PUSHBUTTON;
|
||||
|
||||
//if (mApp == NULL)
|
||||
//aWindowStyle |= WS_DISABLED;
|
||||
|
||||
//#ifdef _DEBUG
|
||||
bool doDebugButton = true;
|
||||
// #else
|
||||
// bool doDebugButton = false;
|
||||
// #endif
|
||||
|
||||
//bool canSubmit = mAllowSubmit && !mSubmitHost.empty();
|
||||
bool canSubmit = false;
|
||||
int aNumButtons = 1 + (doDebugButton ? 1 : 0) + (canSubmit ? 1 : 0);
|
||||
|
||||
int aButtonWidth = (aRect.right - 8 - 8 - (aNumButtons - 1) * 8) / aNumButtons;
|
||||
|
||||
int aCurX = 8;
|
||||
|
||||
if (canSubmit)
|
||||
{
|
||||
gYesButtonWindow = CreateWindowA("BUTTON", "Send Report",
|
||||
aWindowStyle,
|
||||
aCurX, aRect.bottom - 24 - 8,
|
||||
aButtonWidth,
|
||||
24,
|
||||
aHWnd,
|
||||
NULL,
|
||||
gHInstance,
|
||||
0);
|
||||
if (!gUseDefaultFonts)
|
||||
SendMessage(gYesButtonWindow, WM_SETFONT, (WPARAM)aBoldArialFont, 0);
|
||||
|
||||
aCurX += aButtonWidth + 8;
|
||||
}
|
||||
|
||||
if (doDebugButton)
|
||||
{
|
||||
gDebugButtonWindow = CreateWindowA("BUTTON", "Debug",
|
||||
aWindowStyle,
|
||||
aCurX, aRect.bottom - 24 - 8,
|
||||
aButtonWidth,
|
||||
24,
|
||||
aHWnd,
|
||||
NULL,
|
||||
gHInstance,
|
||||
0);
|
||||
if (!gUseDefaultFonts)
|
||||
SendMessage(gDebugButtonWindow, WM_SETFONT, (WPARAM)aBoldArialFont, 0);
|
||||
|
||||
aCurX += aButtonWidth + 8;
|
||||
}
|
||||
|
||||
gNoButtonWindow = CreateWindowA("BUTTON", "Close Now",
|
||||
WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | BS_PUSHBUTTON,
|
||||
aCurX, aRect.bottom - 24 - 8,
|
||||
aButtonWidth,
|
||||
24,
|
||||
aHWnd,
|
||||
NULL,
|
||||
gHInstance,
|
||||
0);
|
||||
|
||||
if (!gUseDefaultFonts)
|
||||
SendMessage(gNoButtonWindow, WM_SETFONT, (WPARAM)aBoldArialFont, 0);
|
||||
|
||||
ShowWindow(aHWnd, SW_NORMAL);
|
||||
|
||||
MSG msg;
|
||||
while ((GetMessage(&msg, NULL, 0, 0) > 0) && (!gExiting))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
DestroyWindow(aHWnd);
|
||||
|
||||
DeleteObject(gDialogFont);
|
||||
DeleteObject(gBoldFont);
|
||||
DeleteObject(aBoldArialFont);
|
||||
DeleteObject(aCourierNewFont);
|
||||
}
|
||||
|
||||
static bool GetLogicalAddress(void* addr, char* szModule, DWORD len, uintptr& section, uintptr& offset)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
||||
if (!VirtualQuery(addr, &mbi, sizeof(mbi)))
|
||||
return false;
|
||||
|
||||
uintptr hMod = (uintptr)mbi.AllocationBase;
|
||||
|
||||
if (hMod == NULL)
|
||||
{
|
||||
szModule[0] = 0;
|
||||
section = 0;
|
||||
offset = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetModuleFileNameA((HMODULE)hMod, szModule, len))
|
||||
return false;
|
||||
|
||||
// Point to the DOS header in memory
|
||||
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
|
||||
|
||||
// From the DOS header, find the NT (PE) header
|
||||
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((uint8*)hMod + pDosHdr->e_lfanew);
|
||||
|
||||
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHdr);
|
||||
|
||||
uintptr rva = (uintptr)addr - hMod; // RVA is offset from module load address
|
||||
|
||||
// Iterate through the section table, looking for the one that encompasses
|
||||
// the linear address.
|
||||
for (unsigned i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++, pSection++)
|
||||
{
|
||||
uintptr sectionStart = pSection->VirtualAddress;
|
||||
uintptr sectionEnd = sectionStart + BF_MAX(pSection->SizeOfRawData, pSection->Misc.VirtualSize);
|
||||
|
||||
// Is the address in this section???
|
||||
if ((rva >= sectionStart) && (rva <= sectionEnd))
|
||||
{
|
||||
// Yes, address is in the section. Calculate section and offset,
|
||||
// and store in the "section" & "offset" params, which were
|
||||
// passed by reference.
|
||||
section = i + 1;
|
||||
offset = rva - sectionStart;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false; // Should never get here!
|
||||
}
|
||||
|
||||
static BOOL CALLBACK MyMiniDumpCallback(
|
||||
PVOID pParam,
|
||||
const PMINIDUMP_CALLBACK_INPUT pInput,
|
||||
PMINIDUMP_CALLBACK_OUTPUT pOutput
|
||||
)
|
||||
{
|
||||
BOOL bRet = FALSE;
|
||||
|
||||
|
||||
// Check parameters
|
||||
|
||||
if (pInput == 0)
|
||||
return FALSE;
|
||||
|
||||
if (pOutput == 0)
|
||||
return FALSE;
|
||||
|
||||
|
||||
// Process the callbacks
|
||||
|
||||
switch (pInput->CallbackType)
|
||||
{
|
||||
case IncludeModuleCallback:
|
||||
{
|
||||
// Include the module into the dump
|
||||
bRet = TRUE;
|
||||
}
|
||||
break;
|
||||
case IncludeThreadCallback:
|
||||
{
|
||||
// Include the thread into the dump
|
||||
bRet = TRUE;
|
||||
}
|
||||
break;
|
||||
case ModuleCallback:
|
||||
{
|
||||
// Does the module have ModuleReferencedByMemory flag set ?
|
||||
|
||||
if (!(pOutput->ModuleWriteFlags & ModuleReferencedByMemory))
|
||||
{
|
||||
// No, it does not - exclude it
|
||||
|
||||
//wprintf(L"Excluding module: %s \n", pInput->Module.FullPath);
|
||||
|
||||
pOutput->ModuleWriteFlags &= (~ModuleWriteModule);
|
||||
}
|
||||
|
||||
bRet = TRUE;
|
||||
}
|
||||
break;
|
||||
case ThreadCallback:
|
||||
{
|
||||
// Include all thread information into the minidump
|
||||
bRet = TRUE;
|
||||
}
|
||||
break;
|
||||
case ThreadExCallback:
|
||||
{
|
||||
// Include this information
|
||||
bRet = TRUE;
|
||||
}
|
||||
break;
|
||||
case MemoryCallback:
|
||||
{
|
||||
// We do not include any information here -> return FALSE
|
||||
bRet = FALSE;
|
||||
}
|
||||
break;
|
||||
case CancelCallback:
|
||||
break;
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
void CreateMiniDump(EXCEPTION_POINTERS* pep)
|
||||
{
|
||||
// Open the file
|
||||
typedef BOOL(*PDUMPFN)(
|
||||
HANDLE hProcess,
|
||||
DWORD ProcessId,
|
||||
HANDLE hFile,
|
||||
MINIDUMP_TYPE DumpType,
|
||||
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
||||
PMINIDUMP_CALLBACK_INFORMATION CallbackParam
|
||||
);
|
||||
|
||||
|
||||
HANDLE hFile = CreateFileW(L"D:/temp/CrashDumps/dump.dmp", GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
HMODULE h = ::LoadLibrary(L"DbgHelp.dll");
|
||||
PDUMPFN pFn = (PDUMPFN)GetProcAddress(h, "MiniDumpWriteDump");
|
||||
|
||||
if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
|
||||
{
|
||||
// Create the minidump
|
||||
|
||||
MINIDUMP_EXCEPTION_INFORMATION mdei;
|
||||
|
||||
mdei.ThreadId = GetCurrentThreadId();
|
||||
mdei.ExceptionPointers = pep;
|
||||
mdei.ClientPointers = TRUE;
|
||||
|
||||
MINIDUMP_CALLBACK_INFORMATION mci;
|
||||
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback;
|
||||
mci.CallbackParam = 0;
|
||||
|
||||
MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory);
|
||||
|
||||
BOOL rv = (*pFn)(GetCurrentProcess(), GetCurrentProcessId(),
|
||||
hFile, mdt, (pep != 0) ? &mdei : 0, 0, &mci);
|
||||
|
||||
// Close the file
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//LONG WINAPI MyUnhandledExceptionFilter(
|
||||
// struct _EXCEPTION_POINTERS *ExceptionInfo
|
||||
//)
|
||||
//{
|
||||
// CreateMiniDump(ExceptionInfo);
|
||||
// return EXCEPTION_EXECUTE_HANDLER;
|
||||
//}
|
||||
|
||||
static String ImageHelpWalk(PCONTEXT theContext, int theSkipCount)
|
||||
{
|
||||
//char aBuffer[2048];
|
||||
String aDebugDump;
|
||||
|
||||
STACKFRAME sf;
|
||||
memset(&sf, 0, sizeof(sf));
|
||||
|
||||
// Initialize the STACKFRAME structure for the first call. This is only
|
||||
// necessary for Intel CPUs, and isn't mentioned in the documentation.
|
||||
#ifdef BF64
|
||||
sf.AddrPC.Offset = theContext->Rip;
|
||||
sf.AddrPC.Mode = AddrModeFlat;
|
||||
sf.AddrStack.Offset = theContext->Rsp;
|
||||
sf.AddrStack.Mode = AddrModeFlat;
|
||||
sf.AddrFrame.Offset = theContext->Rbp;
|
||||
sf.AddrFrame.Mode = AddrModeFlat;
|
||||
#else
|
||||
sf.AddrPC.Offset = theContext->Eip;
|
||||
sf.AddrPC.Mode = AddrModeFlat;
|
||||
sf.AddrStack.Offset = theContext->Esp;
|
||||
sf.AddrStack.Mode = AddrModeFlat;
|
||||
sf.AddrFrame.Offset = theContext->Ebp;
|
||||
sf.AddrFrame.Mode = AddrModeFlat;
|
||||
#endif
|
||||
|
||||
int aLevelCount = 0;
|
||||
|
||||
CONTEXT ctx = *theContext;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
#ifdef BF64
|
||||
DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
|
||||
PCONTEXT ctxPtr = &ctx;
|
||||
#else
|
||||
DWORD machineType = IMAGE_FILE_MACHINE_I386;
|
||||
PCONTEXT ctxPtr = NULL;
|
||||
#endif
|
||||
|
||||
if (!gStackWalk(machineType, GetCurrentProcess(), GetCurrentThread(),
|
||||
&sf, ctxPtr, NULL, gSymFunctionTableAccess, gSymGetModuleBase, 0))
|
||||
{
|
||||
//DWORD lastErr = GetLastError();
|
||||
//sprintf(aBuffer, "StackWalk failed (error %d)\r\n", lastErr);
|
||||
//aDebugDump += aBuffer;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((aLevelCount > 0) && ((sf.AddrFrame.Offset == 0) || (sf.AddrPC.Offset == 0)))
|
||||
break;
|
||||
|
||||
if (theSkipCount > 0)
|
||||
{
|
||||
theSkipCount--;
|
||||
continue;
|
||||
}
|
||||
|
||||
BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 512];
|
||||
PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
|
||||
pSymbol->SizeOfStruct = sizeof(symbolBuffer);
|
||||
pSymbol->MaxNameLength = 512;
|
||||
|
||||
// Displacement of the input address, relative to the start of the symbol
|
||||
#ifdef BF64
|
||||
DWORD64 symDisplacement = 0;
|
||||
#else
|
||||
DWORD symDisplacement = 0;
|
||||
#endif
|
||||
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
|
||||
if (gSymGetSymFromAddr(hProcess, sf.AddrPC.Offset, &symDisplacement, pSymbol))
|
||||
{
|
||||
char aUDName[256];
|
||||
gUnDecorateSymbolName(pSymbol->Name, aUDName, 256,
|
||||
UNDNAME_NO_ALLOCATION_MODEL | UNDNAME_NO_ALLOCATION_LANGUAGE |
|
||||
UNDNAME_NO_MS_THISTYPE | UNDNAME_NO_ACCESS_SPECIFIERS |
|
||||
UNDNAME_NO_THISTYPE | UNDNAME_NO_MEMBER_TYPE |
|
||||
UNDNAME_NO_RETURN_UDT_MODEL | UNDNAME_NO_THROW_SIGNATURES |
|
||||
UNDNAME_NO_SPECIAL_SYMS);
|
||||
|
||||
aDebugDump += StrFormat("%@ %@ %hs+%X\r\n",
|
||||
sf.AddrFrame.Offset, sf.AddrPC.Offset, aUDName, symDisplacement);
|
||||
|
||||
DWORD displacement = 0;
|
||||
#ifdef BF64
|
||||
IMAGEHLP_LINE64 lineInfo = { 0 };
|
||||
lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
#else
|
||||
IMAGEHLP_LINE lineInfo = { 0 };
|
||||
lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE);
|
||||
#endif
|
||||
if (gSymGetLineFromAddr(hProcess, sf.AddrPC.Offset, &displacement, &lineInfo))
|
||||
{
|
||||
aDebugDump += StrFormat(" at %s:%d\r\n", lineInfo.FileName, lineInfo.LineNumber);
|
||||
}
|
||||
}
|
||||
else // No symbol found. Print out the logical address instead.
|
||||
{
|
||||
char szModule[MAX_PATH];
|
||||
szModule[0] = 0;
|
||||
uintptr section = 0, offset = 0;
|
||||
|
||||
GetLogicalAddress((PVOID)sf.AddrPC.Offset, szModule, sizeof(szModule), section, offset);
|
||||
aDebugDump += StrFormat("%@ %@ %04X:%@ %s\r\n", sf.AddrFrame.Offset, sf.AddrPC.Offset, section, offset, GetFileName(szModule).c_str());
|
||||
}
|
||||
|
||||
aDebugDump += StrFormat(" Params: %@ %@ %@ %@\r\n", sf.Params[0], sf.Params[1], sf.Params[2], sf.Params[3]);
|
||||
aDebugDump += "\r\n";
|
||||
|
||||
aLevelCount++;
|
||||
}
|
||||
|
||||
return aDebugDump;
|
||||
}
|
||||
|
||||
static String GetSysInfo()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
|
||||
{
|
||||
if (gCrashed)
|
||||
return;
|
||||
gCrashed = true;
|
||||
|
||||
HMODULE hMod = GetModuleHandleA(NULL);
|
||||
|
||||
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
|
||||
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((uint8*)hMod + pDosHdr->e_lfanew);
|
||||
bool isCLI = pNtHdr->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||
if (gCrashReportKind == BfpCrashReportKind_GUI)
|
||||
isCLI = false;
|
||||
else if ((gCrashReportKind == BfpCrashReportKind_Console) || (gCrashReportKind == BfpCrashReportKind_PrintOnly))
|
||||
isCLI = true;
|
||||
|
||||
bool hasImageHelp = LoadImageHelp();
|
||||
|
||||
String anErrorTitle;
|
||||
String aDebugDump;
|
||||
|
||||
char aBuffer[2048];
|
||||
|
||||
if (isCLI)
|
||||
aDebugDump += "**** FATAL APPLICATION ERROR ****\n";
|
||||
|
||||
for (auto func : gCrashInfoFuncs)
|
||||
func();
|
||||
|
||||
aDebugDump.Append(gCrashInfo);
|
||||
|
||||
for (int i = 0; i < (int)aDebugDump.length(); i++)
|
||||
{
|
||||
char c = aDebugDump[i];
|
||||
if (c == '\n')
|
||||
{
|
||||
aDebugDump.Insert(i, '\r');
|
||||
i++;
|
||||
}
|
||||
else if (c == '\t')
|
||||
{
|
||||
aDebugDump[i] = ' ';
|
||||
aDebugDump.Insert(i, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
// aDebugDump.Replace("\n", "\r\n");
|
||||
// aDebugDump.Replace("\t", " ");
|
||||
|
||||
if (!aDebugDump.IsEmpty())
|
||||
{
|
||||
if (!aDebugDump.EndsWith("\n"))
|
||||
aDebugDump += "\r\n";
|
||||
|
||||
aDebugDump += "\r\n";
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// first name the exception
|
||||
char *szName = NULL;
|
||||
for (int i = 0; gMsgTable[i].dwExceptionCode != 0xFFFFFFFF; i++)
|
||||
{
|
||||
if (gMsgTable[i].dwExceptionCode == lpEP->ExceptionRecord->ExceptionCode)
|
||||
{
|
||||
szName = gMsgTable[i].szMessage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (szName != NULL)
|
||||
{
|
||||
aDebugDump += StrFormat("Exception: %s (code 0x%x) at address %@ in thread %X\r\n",
|
||||
szName, lpEP->ExceptionRecord->ExceptionCode,
|
||||
lpEP->ExceptionRecord->ExceptionAddress, GetCurrentThreadId());
|
||||
}
|
||||
else
|
||||
{
|
||||
aDebugDump += StrFormat("Unknown exception: (code 0x%x) at address %@ in thread %X\r\n",
|
||||
lpEP->ExceptionRecord->ExceptionCode,
|
||||
lpEP->ExceptionRecord->ExceptionAddress, GetCurrentThreadId());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Get logical address of the module where exception occurs
|
||||
uintptr section, offset;
|
||||
GetLogicalAddress(lpEP->ExceptionRecord->ExceptionAddress, aBuffer, sizeof(aBuffer), section, offset);
|
||||
|
||||
CHAR path[MAX_PATH];
|
||||
GetModuleFileNameA(NULL, path, MAX_PATH);
|
||||
aDebugDump += "Executable: ";
|
||||
aDebugDump += path;
|
||||
aDebugDump += "\r\n";
|
||||
|
||||
aDebugDump += "Module: " + GetFileName(aBuffer) + "\r\n";
|
||||
aDebugDump += StrFormat("Logical Address: %04X:%@\r\n", section, offset);
|
||||
|
||||
aDebugDump += "\r\n";
|
||||
|
||||
anErrorTitle = StrFormat("Exception at %04X:%08X", section, offset);
|
||||
|
||||
String aWalkString;
|
||||
|
||||
if (hasImageHelp)
|
||||
aWalkString = ImageHelpWalk(lpEP->ContextRecord, 0);
|
||||
|
||||
/*if (aWalkString.length() == 0)
|
||||
aWalkString = IntelWalk(lpEP->ContextRecord, 0);*/
|
||||
|
||||
aDebugDump += aWalkString;
|
||||
|
||||
aDebugDump += "\r\n";
|
||||
|
||||
#ifdef BF64
|
||||
aDebugDump += StrFormat("RAX:%@ RBX:%@ RCX:%@ RDX:%@ RSI:%@ RDI:%@\r\n",
|
||||
lpEP->ContextRecord->Rax, lpEP->ContextRecord->Rbx, lpEP->ContextRecord->Rcx, lpEP->ContextRecord->Rdx, lpEP->ContextRecord->Rsi, lpEP->ContextRecord->Rdi);
|
||||
aDebugDump += StrFormat("R8:%@ R9:%@ R10:%@ R11:%@\r\nR12:%@ R13:%@ R14:%@ R15:%@\r\n",
|
||||
lpEP->ContextRecord->R8, lpEP->ContextRecord->R9, lpEP->ContextRecord->R10, lpEP->ContextRecord->R11, lpEP->ContextRecord->R12, lpEP->ContextRecord->R13, lpEP->ContextRecord->R14, lpEP->ContextRecord->R15);
|
||||
aDebugDump += StrFormat("EIP:%@ ESP:%@ EBP:%@\r\n", lpEP->ContextRecord->Rip, lpEP->ContextRecord->Rsp, lpEP->ContextRecord->Rbp);
|
||||
aDebugDump += StrFormat("CS:%04X SS:%04X DS:%04X ES:%04X FS:%04X GS:%04X\r\n", lpEP->ContextRecord->SegCs, lpEP->ContextRecord->SegSs, lpEP->ContextRecord->SegDs, lpEP->ContextRecord->SegEs, lpEP->ContextRecord->SegFs, lpEP->ContextRecord->SegGs);
|
||||
aDebugDump += StrFormat("Flags:%@\r\n", lpEP->ContextRecord->EFlags);
|
||||
#else
|
||||
aDebugDump += StrFormat("EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X\r\n",
|
||||
lpEP->ContextRecord->Eax, lpEP->ContextRecord->Ebx, lpEP->ContextRecord->Ecx, lpEP->ContextRecord->Edx, lpEP->ContextRecord->Esi, lpEP->ContextRecord->Edi);
|
||||
aDebugDump += StrFormat("EIP:%08X ESP:%08X EBP:%08X\r\n", lpEP->ContextRecord->Eip, lpEP->ContextRecord->Esp, lpEP->ContextRecord->Ebp);
|
||||
aDebugDump += StrFormat("CS:%04X SS:%04X DS:%04X ES:%04X FS:%04X GS:%04X\r\n", lpEP->ContextRecord->SegCs, lpEP->ContextRecord->SegSs, lpEP->ContextRecord->SegDs, lpEP->ContextRecord->SegEs, lpEP->ContextRecord->SegFs, lpEP->ContextRecord->SegGs);
|
||||
aDebugDump += StrFormat("Flags:%08X\r\n", lpEP->ContextRecord->EFlags);
|
||||
#endif
|
||||
|
||||
aDebugDump += "\r\n";
|
||||
aDebugDump += GetSysInfo();
|
||||
|
||||
/*if (mApp != NULL)
|
||||
{
|
||||
String aGameSEHInfo = mApp->GetGameSEHInfo();
|
||||
if (aGameSEHInfo.length() > 0)
|
||||
{
|
||||
aDebugDump += "\r\n";
|
||||
aDebugDump += aGameSEHInfo;
|
||||
}
|
||||
|
||||
mApp->CopyToClipboard(aDebugDump);
|
||||
}
|
||||
|
||||
if (hasImageHelp)
|
||||
GetSymbolsFromMapFile(aDebugDump);*/
|
||||
|
||||
if (isCLI)
|
||||
{
|
||||
aDebugDump += "\n";
|
||||
//fwrite(aDebugDump.c_str(), 1, aDebugDump.length(), stderr);
|
||||
//fflush(stderr);
|
||||
DWORD bytesWritten;
|
||||
::WriteFile(::GetStdHandle(STD_ERROR_HANDLE), aDebugDump.c_str(), (DWORD)aDebugDump.length(), &bytesWritten, NULL);
|
||||
}
|
||||
else
|
||||
ShowErrorDialog(anErrorTitle, aDebugDump);
|
||||
}
|
||||
|
||||
CrashCatcher::CrashCatcher()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static long __stdcall SEHFilter(LPEXCEPTION_POINTERS lpExceptPtr)
|
||||
{
|
||||
//OutputDebugStrF("SEH Filter! CraskReportKind:%d\n", gCrashReportKind);
|
||||
|
||||
if (gCrashReportKind == BfpCrashReportKind_None)
|
||||
{
|
||||
OutputDebugStrF("Silent Exiting\n");
|
||||
::TerminateProcess(GetCurrentProcess(), lpExceptPtr->ExceptionRecord->ExceptionCode);
|
||||
}
|
||||
|
||||
AutoCrit autoCrit(gBfpCritSect);
|
||||
//::ExitProcess();
|
||||
//quick_exit(1);
|
||||
|
||||
if (!gCrashed)
|
||||
{
|
||||
CreateMiniDump(lpExceptPtr);
|
||||
DoHandleDebugEvent(lpExceptPtr);
|
||||
}
|
||||
|
||||
//if (!gDebugError)
|
||||
//SetErrorMode(SEM_NOGPFAULTERRORBOX);
|
||||
|
||||
if (gCrashReportKind == BfpCrashReportKind_PrintOnly)
|
||||
{
|
||||
::TerminateProcess(GetCurrentProcess(), lpExceptPtr->ExceptionRecord->ExceptionCode);
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
void CrashCatcher::Init()
|
||||
{
|
||||
gPreviousFilter = SetUnhandledExceptionFilter(SEHFilter);
|
||||
|
||||
//__try
|
||||
//{
|
||||
// // all of code normally inside of main or WinMain here...
|
||||
// int a = 123;
|
||||
// int b = 0;
|
||||
// a /= b;
|
||||
//}
|
||||
//__except (SEHFilter(GetExceptionInformation()))
|
||||
//{
|
||||
//
|
||||
//}
|
||||
}
|
||||
|
||||
void CrashCatcher::AddCrashInfoFunc(CrashInfoFunc crashInfoFunc)
|
||||
{
|
||||
AutoCrit autoCrit(gBfpCritSect);
|
||||
gCrashInfoFuncs.Add(crashInfoFunc);
|
||||
}
|
||||
|
||||
void CrashCatcher::AddInfo(const StringImpl& str)
|
||||
{
|
||||
AutoCrit autoCrit(gBfpCritSect);
|
||||
gCrashInfo.Append(str);
|
||||
}
|
||||
|
||||
void CrashCatcher::Crash(const StringImpl& str)
|
||||
{
|
||||
OutputDebugStrF("CrashCatcher::Crash\n");
|
||||
|
||||
gBfpCritSect.Lock();
|
||||
gCrashInfo.Append(str);
|
||||
|
||||
if (gPreviousFilter == NULL)
|
||||
{
|
||||
// A little late, but install handler now so we can catch this crash
|
||||
Init();
|
||||
}
|
||||
|
||||
gBfpCritSect.Unlock();
|
||||
|
||||
|
||||
__debugbreak();
|
||||
|
||||
// When we catch the exception information like this, it displays the dump correctly but
|
||||
// the minidump doesn't contain a valid callstack, so we need to rely on SetUnhandledExceptionFilter
|
||||
/*__try
|
||||
{
|
||||
::MessageBoxA(NULL, "A", "B", MB_ICONERROR);
|
||||
__debugbreak();
|
||||
}
|
||||
__except (SEHFilter(GetExceptionInformation()))
|
||||
{
|
||||
|
||||
}*/
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void CrashCatcher::SetCrashReportKind(BfpCrashReportKind crashReportKind)
|
||||
{
|
||||
gCrashReportKind = crashReportKind;
|
||||
}
|
22
BeefySysLib/platform/win/CrashCatcher.h
Normal file
22
BeefySysLib/platform/win/CrashCatcher.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../BeefySysLib/Common.h"
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
typedef void(*CrashInfoFunc)();
|
||||
|
||||
class CrashCatcher
|
||||
{
|
||||
public:
|
||||
CrashCatcher();
|
||||
|
||||
void Init();
|
||||
void AddCrashInfoFunc(CrashInfoFunc crashInfoFunc);
|
||||
void AddInfo(const StringImpl& str);
|
||||
|
||||
void Crash(const StringImpl& str);
|
||||
void SetCrashReportKind(BfpCrashReportKind crashReportKind);
|
||||
};
|
||||
|
||||
NS_BF_END
|
1756
BeefySysLib/platform/win/DXRenderDevice.cpp
Normal file
1756
BeefySysLib/platform/win/DXRenderDevice.cpp
Normal file
File diff suppressed because it is too large
Load diff
311
BeefySysLib/platform/win/DXRenderDevice.h
Normal file
311
BeefySysLib/platform/win/DXRenderDevice.h
Normal file
|
@ -0,0 +1,311 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef BF_MINGW
|
||||
#define D3D11_APPEND_ALIGNED_ELEMENT ( 0xffffffff )
|
||||
#ifndef __C89_NAMELESS
|
||||
#define __C89_NAMELESS
|
||||
#define __C89_NAMELESSUNIONNAME
|
||||
#endif
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma clang diagnostic ignored "-Wunknown-attributes"
|
||||
#pragma clang diagnostic ignored "-Wunused-member-function"
|
||||
#pragma clang diagnostic ignored "-Wunused-conversion-function"
|
||||
#define __in
|
||||
#define __in_opt
|
||||
#define __in_ecount(a)
|
||||
#define __in_ecount_opt(a)
|
||||
#define __in_bcount(a)
|
||||
#define __in_bcount_opt(a)
|
||||
#define __inout
|
||||
#define __inout_opt
|
||||
#define __out
|
||||
#define __out_opt
|
||||
#define __out_bcount(a)
|
||||
#define __out_bcount_opt(a)
|
||||
#define __out_ecount(a)
|
||||
#define __out_ecount_opt(a)
|
||||
#define __out_ecount_part_opt(a, b)
|
||||
#endif
|
||||
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable:4005)
|
||||
#include <d3d11.h>
|
||||
#pragma warning (pop)
|
||||
|
||||
#ifdef BF_MINGW
|
||||
#undef __in
|
||||
#undef __out
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
#include "gfx/Shader.h"
|
||||
#include "gfx/Texture.h"
|
||||
#include "gfx/RenderDevice.h"
|
||||
#include "gfx/DrawLayer.h"
|
||||
#include "gfx/ModelInstance.h"
|
||||
#include "util/HashSet.h"
|
||||
#include <map>
|
||||
|
||||
NS_BF_BEGIN;
|
||||
|
||||
class BFApp;
|
||||
class DXRenderDevice;
|
||||
|
||||
class DXTexture : public Texture
|
||||
{
|
||||
public:
|
||||
DXRenderDevice* mRenderDevice;
|
||||
ID3D11Texture2D* mD3DTexture;
|
||||
ID3D11ShaderResourceView* mD3DResourceView;
|
||||
ID3D11RenderTargetView* mD3DRenderTargetView;
|
||||
ID3D11Texture2D* mD3DDepthBuffer;
|
||||
ID3D11DepthStencilView* mD3DDepthStencilView;
|
||||
ImageData* mImageData;
|
||||
|
||||
public:
|
||||
DXTexture();
|
||||
~DXTexture();
|
||||
|
||||
void ReleaseNative();
|
||||
void ReinitNative();
|
||||
|
||||
virtual void PhysSetAsTarget() override;
|
||||
virtual void Blt(ImageData* imageData, int x, int y) override;
|
||||
virtual void SetBits(int destX, int destY, int destWidth, int destHeight, int srcPitch, uint32* bits) override;
|
||||
};
|
||||
|
||||
class DXShaderParam : public ShaderParam
|
||||
{
|
||||
public:
|
||||
ID3D10EffectVariable* mD3DVariable;
|
||||
|
||||
public:
|
||||
DXShaderParam();
|
||||
~DXShaderParam();
|
||||
|
||||
virtual void SetTexture(Texture* texture);
|
||||
virtual void SetFloat4(float x, float y, float z, float w) override;
|
||||
};
|
||||
|
||||
typedef std::map<String, DXShaderParam*> DXShaderParamMap;
|
||||
|
||||
class DXShader : public Shader
|
||||
{
|
||||
public:
|
||||
ID3D11InputLayout* mD3DLayout;
|
||||
ID3D11VertexShader* mD3DVertexShader;
|
||||
ID3D11PixelShader* mD3DPixelShader;
|
||||
DXShaderParamMap mParamsMap;
|
||||
ID3D11Buffer* mConstBuffer;
|
||||
bool mHas2DPosition;
|
||||
|
||||
public:
|
||||
DXShader();
|
||||
~DXShader();
|
||||
|
||||
virtual ShaderParam* GetShaderParam(const StringImpl& name) override;
|
||||
};
|
||||
|
||||
class DXDrawBatch : public DrawBatch
|
||||
{
|
||||
public:
|
||||
|
||||
public:
|
||||
DXDrawBatch();
|
||||
~DXDrawBatch();
|
||||
|
||||
virtual void Render(RenderDevice* renderDevice, RenderWindow* renderWindow) override;
|
||||
};
|
||||
|
||||
class DXDrawLayer : public DrawLayer
|
||||
{
|
||||
public:
|
||||
virtual DrawBatch* CreateDrawBatch();
|
||||
virtual RenderCmd* CreateSetTextureCmd(int textureIdx, Texture* texture) override;
|
||||
virtual void SetShaderConstantData(int slotIdx, void* constData, int size) override;
|
||||
virtual void SetShaderConstantDataTyped(int slotIdx, void* constData, int size, int* typeData, int typeCount) override;
|
||||
|
||||
public:
|
||||
DXDrawLayer();
|
||||
~DXDrawLayer();
|
||||
};
|
||||
|
||||
class DXRenderWindow : public RenderWindow
|
||||
{
|
||||
public:
|
||||
HWND mHWnd;
|
||||
DXRenderDevice* mDXRenderDevice;
|
||||
IDXGISwapChain* mDXSwapChain;
|
||||
ID3D11Texture2D* mD3DBackBuffer;
|
||||
ID3D11RenderTargetView* mD3DRenderTargetView;
|
||||
ID3D11Texture2D* mD3DDepthBuffer;
|
||||
ID3D11DepthStencilView* mD3DDepthStencilView;
|
||||
bool mResizePending;
|
||||
bool mWindowed;
|
||||
int mPendingWidth;
|
||||
int mPendingHeight;
|
||||
|
||||
public:
|
||||
virtual void PhysSetAsTarget();
|
||||
|
||||
public:
|
||||
DXRenderWindow(DXRenderDevice* renderDevice, HWND hWnd, bool windowed);
|
||||
~DXRenderWindow();
|
||||
|
||||
void ReleaseNative();
|
||||
void ReinitNative();
|
||||
|
||||
void SetAsTarget() override;
|
||||
void Resized() override;
|
||||
virtual void Present() override;
|
||||
|
||||
void CopyBitsTo(uint32* dest, int width, int height);
|
||||
};
|
||||
|
||||
typedef std::vector<DXDrawBatch*> DXDrawBatchVector;
|
||||
|
||||
#define DX_VTXBUFFER_SIZE 1024*1024
|
||||
#define DX_IDXBUFFER_SIZE 64*1024
|
||||
|
||||
class DXDrawBufferPool
|
||||
{
|
||||
public:
|
||||
std::vector<void*> mPooledIndexBuffers;
|
||||
int mIdxPoolIdx;
|
||||
std::vector<void*> mPooledVertexBuffers;
|
||||
int mVtxPoolIdx;
|
||||
|
||||
void* mIndexBuffer;
|
||||
void* mVertexBuffer;
|
||||
int mIdxByteIdx;
|
||||
int mVtxByteIdx;
|
||||
|
||||
void AllocateIndices(int minIndices);
|
||||
void AllocVertices(int minVertices);
|
||||
};
|
||||
|
||||
class DXRenderState : public RenderState
|
||||
{
|
||||
public:
|
||||
ID3D11RasterizerState* mD3DRasterizerState;
|
||||
ID3D11DepthStencilState* mD3DDepthStencilState;
|
||||
|
||||
public:
|
||||
DXRenderState();
|
||||
~DXRenderState();
|
||||
|
||||
void ReleaseNative();
|
||||
void ReinitNative();
|
||||
|
||||
void InvalidateRasterizerState();
|
||||
void IndalidateDepthStencilState();
|
||||
|
||||
virtual void SetClipped(bool clipped);
|
||||
virtual void SetClipRect(const Rect& rect);
|
||||
virtual void SetWriteDepthBuffer(bool writeDepthBuffer);
|
||||
virtual void SetDepthFunc(DepthFunc depthFunc);
|
||||
};
|
||||
|
||||
class DXModelMesh
|
||||
{
|
||||
public:
|
||||
int mNumIndices;
|
||||
int mNumVertices;
|
||||
DXTexture* mTexture;
|
||||
|
||||
ID3D11Buffer* mD3DIndexBuffer;
|
||||
//TODO: Split the vertex buffer up into static and dynamic buffers
|
||||
ID3D11Buffer* mD3DVertexBuffer;
|
||||
|
||||
public:
|
||||
DXModelMesh();
|
||||
~DXModelMesh();
|
||||
};
|
||||
|
||||
class DXModelInstance : public ModelInstance
|
||||
{
|
||||
public:
|
||||
DXRenderDevice* mD3DRenderDevice;
|
||||
std::vector<DXModelMesh> mDXModelMeshs;
|
||||
|
||||
public:
|
||||
DXModelInstance(ModelDef* modelDef);
|
||||
~DXModelInstance();
|
||||
|
||||
virtual void CommandQueued(DrawLayer* drawLayer) override;
|
||||
virtual void Render(RenderDevice* renderDevice, RenderWindow* renderWindow) override;
|
||||
};
|
||||
|
||||
class DXVertexDefinition : public VertexDefinition
|
||||
{
|
||||
public:
|
||||
~DXVertexDefinition();
|
||||
};
|
||||
|
||||
class DXSetTextureCmd : public RenderCmd
|
||||
{
|
||||
public:
|
||||
int mTextureIdx;
|
||||
Texture* mTexture;
|
||||
|
||||
public:
|
||||
virtual void Render(RenderDevice* renderDevice, RenderWindow* renderWindow) override;
|
||||
};
|
||||
|
||||
class DXSetConstantData : public RenderCmd
|
||||
{
|
||||
public:
|
||||
int mUsageIdx; // 0 = VS, 1 = PS
|
||||
int mSlotIdx;
|
||||
int mSize;
|
||||
uint8 mData[1];
|
||||
|
||||
public:
|
||||
virtual void Render(RenderDevice* renderDevice, RenderWindow* renderWindow) override;
|
||||
};
|
||||
|
||||
class DXRenderDevice : public RenderDevice
|
||||
{
|
||||
public:
|
||||
IDXGIFactory* mDXGIFactory;
|
||||
ID3D11Device* mD3DDevice;
|
||||
ID3D11DeviceContext* mD3DDeviceContext;
|
||||
ID3D11BlendState* mD3DNormalBlendState;
|
||||
ID3D11SamplerState* mD3DDefaultSamplerState;
|
||||
bool mHasVSync;
|
||||
|
||||
ID3D11Buffer* mD3DVertexBuffer;
|
||||
ID3D11Buffer* mD3DIndexBuffer;
|
||||
int mVtxByteIdx;
|
||||
int mIdxByteIdx;
|
||||
|
||||
HashSet<DXRenderState*> mRenderStates;
|
||||
HashSet<DXTexture*> mTextures;
|
||||
|
||||
public:
|
||||
virtual void PhysSetRenderState(RenderState* renderState) override;
|
||||
virtual void PhysSetRenderWindow(RenderWindow* renderWindow);
|
||||
virtual void PhysSetRenderTarget(Texture* renderTarget) override;
|
||||
virtual RenderState* CreateRenderState(RenderState* srcRenderState) override;
|
||||
virtual ModelInstance* CreateModelInstance(ModelDef* modelDef) override;
|
||||
|
||||
public:
|
||||
DXRenderDevice();
|
||||
virtual ~DXRenderDevice();
|
||||
bool Init(BFApp* app) override;
|
||||
|
||||
void ReleaseNative();
|
||||
void ReinitNative();
|
||||
|
||||
void FrameStart() override;
|
||||
void FrameEnd() override;
|
||||
|
||||
Texture* LoadTexture(ImageData* imageData, int flags) override;
|
||||
Texture* CreateDynTexture(int width, int height) override;
|
||||
Shader* LoadShader(const StringImpl& fileName, VertexDefinition* vertexDefinition) override;
|
||||
Texture* CreateRenderTarget(int width, int height, bool destAlpha) override;
|
||||
|
||||
void SetRenderState(RenderState* renderState) override;
|
||||
};
|
||||
|
||||
NS_BF_END;
|
3341
BeefySysLib/platform/win/Platform.cpp
Normal file
3341
BeefySysLib/platform/win/Platform.cpp
Normal file
File diff suppressed because it is too large
Load diff
17
BeefySysLib/platform/win/PlatformApp.h
Normal file
17
BeefySysLib/platform/win/PlatformApp.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef BF_FORCE_SDL
|
||||
#include "SdlBFApp.h"
|
||||
#else
|
||||
#include "WinBFApp.h"
|
||||
#endif
|
||||
|
||||
NS_BF_BEGIN;
|
||||
|
||||
#ifdef BF_FORCE_SDL
|
||||
typedef SdlBFApp PlatformBFApp;
|
||||
#else
|
||||
typedef WinBFApp PlatformBFApp;
|
||||
#endif
|
||||
|
||||
NS_BF_END;
|
1691
BeefySysLib/platform/win/WinBFApp.cpp
Normal file
1691
BeefySysLib/platform/win/WinBFApp.cpp
Normal file
File diff suppressed because it is too large
Load diff
117
BeefySysLib/platform/win/WinBFApp.h
Normal file
117
BeefySysLib/platform/win/WinBFApp.h
Normal file
|
@ -0,0 +1,117 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include "BFApp.h"
|
||||
#include "BFWindow.h"
|
||||
#include "util/Dictionary.h"
|
||||
|
||||
|
||||
NS_BF_BEGIN;
|
||||
|
||||
class RenderDevice;
|
||||
|
||||
typedef Dictionary<void*, HGLOBAL> PtrToHGlobalMap;
|
||||
typedef Dictionary<String, uint32> StringToUIntMap;
|
||||
|
||||
class WinBFMenu : public BFMenu
|
||||
{
|
||||
public:
|
||||
HMENU mMenu;
|
||||
uint32 mMenuId;
|
||||
static int mMenuCount;
|
||||
bool mIsPlaceholder;
|
||||
|
||||
public:
|
||||
WinBFMenu();
|
||||
};
|
||||
|
||||
typedef Dictionary<uint32, WinBFMenu*> WinMenuIDMap;
|
||||
typedef Dictionary<HMENU, WinBFMenu*> WinHMenuMap;
|
||||
|
||||
class WinBFWindow : public BFWindow
|
||||
{
|
||||
public:
|
||||
HWND mHWnd;
|
||||
bool mIsMouseInside;
|
||||
WinMenuIDMap mMenuIDMap;
|
||||
WinHMenuMap mHMenuMap;
|
||||
|
||||
int mModalCount;
|
||||
int mAlphaMaskWidth;
|
||||
int mAlphaMaskHeight;
|
||||
HBITMAP mAlphaMaskBitmap;
|
||||
HDC mAlphaMaskDC;
|
||||
uint32* mAlphaMaskPixels;
|
||||
bool mIsMenuKeyHandled;
|
||||
int mMinWidth;
|
||||
int mMinHeight;
|
||||
bool mMouseVisible;
|
||||
bool mHasFocus;
|
||||
bool mSoftHasFocus; // Mostly tracks mHasFocus except for when we get an explicit 'LostFocus' callback
|
||||
|
||||
bool mNeedsStateReset;
|
||||
|
||||
public:
|
||||
virtual LRESULT WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
static LRESULT CALLBACK WindowProcStub(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
void RehupMouseOver(bool isMouseOver);
|
||||
|
||||
public:
|
||||
WinBFWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags);
|
||||
~WinBFWindow();
|
||||
|
||||
virtual void* GetUnderlying() override;
|
||||
virtual void Destroy() override;
|
||||
virtual bool TryClose() override;
|
||||
virtual void SetTitle(const char* title) override;
|
||||
virtual void SetForeground() override;
|
||||
virtual void LostFocus(BFWindow* newFocus) override;
|
||||
virtual void SetMinimumSize(int minWidth, int minHeight, bool clientSized) override;
|
||||
virtual void GetPosition(int* x, int* y, int* width, int* height, int* clientX, int* clientY, int* clientWidth, int* clientHeight) override;
|
||||
virtual void Resize(int x, int y, int width, int height) override;
|
||||
virtual void SetClientPosition(int x, int y) override;
|
||||
virtual void SetMouseVisible(bool isMouseVisible) override;
|
||||
virtual void SetAlpha(float alpha, uint32 destAlphaSrcMask, bool isMouseVisible) override;
|
||||
virtual void CaptureMouse() override;
|
||||
virtual bool IsMouseCaptured() override;
|
||||
|
||||
virtual BFMenu* AddMenuItem(BFMenu* parent, int insertIdx, const char* text, const char* hotKey, BFSysBitmap* bitmap, bool enabled, int checkState, bool radioCheck) override;
|
||||
virtual void ModifyMenuItem(BFMenu* item, const char* text, const char* hotKey, BFSysBitmap* bitmap, bool enabled, int checkState, bool radioCheck) override;
|
||||
virtual void RemoveMenuItem(BFMenu* item) override;
|
||||
virtual void ModalsRemoved() override;
|
||||
};
|
||||
|
||||
class WinBFApp : public BFApp
|
||||
{
|
||||
public:
|
||||
bool mInMsgProc;
|
||||
PtrToHGlobalMap mLockedHGlobalMap;
|
||||
StringToUIntMap mClipboardFormatMap;
|
||||
|
||||
protected:
|
||||
virtual void Draw() override;
|
||||
virtual void PhysSetCursor() override;
|
||||
|
||||
uint32 GetClipboardFormat(const StringImpl& format);
|
||||
|
||||
public:
|
||||
WinBFApp();
|
||||
virtual ~WinBFApp();
|
||||
|
||||
virtual void Init() override;
|
||||
virtual void Run() override;
|
||||
|
||||
virtual void GetDesktopResolution(int& width, int& height);
|
||||
virtual void GetWorkspaceRect(int& x, int& y, int& width, int& height);
|
||||
virtual BFWindow* CreateNewWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags) override;
|
||||
virtual DrawLayer* CreateDrawLayer(BFWindow* window);
|
||||
|
||||
virtual void* GetClipboardData(const StringImpl& format, int* size) override;
|
||||
virtual void ReleaseClipboardData(void* ptr) override;
|
||||
virtual void SetClipboardData(const StringImpl& format, const void* ptr, int size, bool resetClipboard) override;
|
||||
virtual void RehupMouse() override;
|
||||
|
||||
virtual BFSysBitmap* LoadSysBitmap(const WCHAR* fileName) override;
|
||||
};
|
||||
|
||||
NS_BF_END;
|
Loading…
Add table
Add a link
Reference in a new issue