You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
747 lines
18 KiB
747 lines
18 KiB
/** |
|
* @file appfat.cpp |
|
* |
|
* Implementation of error dialogs. |
|
*/ |
|
#include "all.h" |
|
#include "../3rdParty/Storm/Source/storm.h" |
|
|
|
/** Buffer used by GetErrorStr for its return value */ |
|
char sz_error_buf[256]; |
|
/** Set to true when a fatal error is encountered and the application should shut down. */ |
|
BOOL terminating; |
|
/** Thread id of the last callee to FreeDlg(). */ |
|
int cleanup_thread_id; |
|
|
|
// delete overloads the delete operator. |
|
void __cdecl operator delete(void *ptr) |
|
{ |
|
if (ptr != NULL) { |
|
SMemFree(ptr, "delete", -1, 0); |
|
} |
|
} |
|
|
|
void TriggerBreak() |
|
{ |
|
#ifdef _DEBUG |
|
LPTOP_LEVEL_EXCEPTION_FILTER pFilter; |
|
|
|
pFilter = SetUnhandledExceptionFilter(BreakFilter); |
|
#ifdef USE_ASM |
|
__asm { |
|
int 3 |
|
} |
|
#else |
|
__debugbreak(); |
|
#endif |
|
SetUnhandledExceptionFilter(pFilter); |
|
#endif |
|
} |
|
|
|
#ifdef _DEBUG |
|
LONG __stdcall BreakFilter(PEXCEPTION_POINTERS pExc) |
|
{ |
|
if (pExc->ExceptionRecord == NULL) { |
|
return EXCEPTION_CONTINUE_SEARCH; |
|
} |
|
if (pExc->ExceptionRecord->ExceptionCode != EXCEPTION_BREAKPOINT) { |
|
return EXCEPTION_CONTINUE_SEARCH; |
|
} |
|
|
|
if (((BYTE *)pExc->ContextRecord->Eip)[0] == 0xCC) { // int 3 |
|
pExc->ContextRecord->Eip++; |
|
} |
|
|
|
return EXCEPTION_CONTINUE_EXECUTION; |
|
} |
|
#endif |
|
|
|
/** |
|
* @brief Returns a formatted error message based on the given error code. |
|
* @param error_code DirectX error code |
|
|
|
*/ |
|
char *GetErrorStr(DWORD error_code) |
|
{ |
|
int size; |
|
char *chr; |
|
|
|
if (HRESULT_FACILITY(error_code) == _FACDS) { |
|
TraceErrorDS(error_code, sz_error_buf, sizeof(sz_error_buf) / sizeof(sz_error_buf[0])); |
|
} else if (HRESULT_FACILITY(error_code) == _FACDD) { |
|
TraceErrorDD(error_code, sz_error_buf, sizeof(sz_error_buf) / sizeof(sz_error_buf[0])); |
|
} else if (!SErrGetErrorStr(error_code, sz_error_buf, sizeof(sz_error_buf) / sizeof(sz_error_buf[0])) |
|
&& !FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), sz_error_buf, sizeof(sz_error_buf) / sizeof(sz_error_buf[0]), NULL)) { |
|
wsprintf(sz_error_buf, "unknown error 0x%08x", error_code); |
|
} |
|
|
|
size = strlen(sz_error_buf); |
|
|
|
chr = &sz_error_buf[size - 1]; |
|
while (size-- > 0) { |
|
chr--; |
|
|
|
if (*chr != '\r' && *chr != '\n') |
|
break; |
|
|
|
*chr = 0x00; |
|
} |
|
|
|
return sz_error_buf; |
|
} |
|
|
|
/** |
|
* @brief Generate a textual message for DirectDraw error codes |
|
* @param hError DirectDraw error code |
|
* @param pszBuffer Buffer for the error message |
|
* @param dwMaxChars Length of pszBuffer |
|
*/ |
|
void TraceErrorDD(HRESULT hError, char *pszBuffer, DWORD dwMaxChars) |
|
{ |
|
const char *szError; |
|
|
|
switch (hError) { |
|
case DD_OK: |
|
szError = "DD_OK"; |
|
break; |
|
case DDERR_ALREADYINITIALIZED: |
|
szError = "DDERR_ALREADYINITIALIZED"; |
|
break; |
|
case DDERR_BLTFASTCANTCLIP: |
|
szError = "DDERR_BLTFASTCANTCLIP"; |
|
break; |
|
case DDERR_CANNOTATTACHSURFACE: |
|
szError = "DDERR_CANNOTATTACHSURFACE"; |
|
break; |
|
case DDERR_CANNOTDETACHSURFACE: |
|
szError = "DDERR_CANNOTDETACHSURFACE"; |
|
break; |
|
case DDERR_CANTCREATEDC: |
|
szError = "DDERR_CANTCREATEDC"; |
|
break; |
|
case DDERR_CANTDUPLICATE: |
|
szError = "DDERR_CANTDUPLICATE"; |
|
break; |
|
case DDERR_CLIPPERISUSINGHWND: |
|
szError = "DDERR_CLIPPERISUSINGHWND"; |
|
break; |
|
case DDERR_COLORKEYNOTSET: |
|
szError = "DDERR_COLORKEYNOTSET"; |
|
break; |
|
case DDERR_CURRENTLYNOTAVAIL: |
|
szError = "DDERR_CURRENTLYNOTAVAIL"; |
|
break; |
|
case DDERR_DIRECTDRAWALREADYCREATED: |
|
szError = "DDERR_DIRECTDRAWALREADYCREATED"; |
|
break; |
|
case DDERR_EXCEPTION: |
|
szError = "DDERR_EXCEPTION"; |
|
break; |
|
case DDERR_EXCLUSIVEMODEALREADYSET: |
|
szError = "DDERR_EXCLUSIVEMODEALREADYSET"; |
|
break; |
|
case DDERR_GENERIC: |
|
szError = "DDERR_GENERIC"; |
|
break; |
|
case DDERR_HEIGHTALIGN: |
|
szError = "DDERR_HEIGHTALIGN"; |
|
break; |
|
case DDERR_HWNDALREADYSET: |
|
szError = "DDERR_HWNDALREADYSET"; |
|
break; |
|
case DDERR_HWNDSUBCLASSED: |
|
szError = "DDERR_HWNDSUBCLASSED"; |
|
break; |
|
case DDERR_IMPLICITLYCREATED: |
|
szError = "DDERR_IMPLICITLYCREATED"; |
|
break; |
|
case DDERR_INCOMPATIBLEPRIMARY: |
|
szError = "DDERR_INCOMPATIBLEPRIMARY"; |
|
break; |
|
case DDERR_INVALIDCAPS: |
|
szError = "DDERR_INVALIDCAPS"; |
|
break; |
|
case DDERR_INVALIDCLIPLIST: |
|
szError = "DDERR_INVALIDCLIPLIST"; |
|
break; |
|
case DDERR_INVALIDDIRECTDRAWGUID: |
|
szError = "DDERR_INVALIDDIRECTDRAWGUID"; |
|
break; |
|
case DDERR_INVALIDMODE: |
|
szError = "DDERR_INVALIDMODE"; |
|
break; |
|
case DDERR_INVALIDOBJECT: |
|
szError = "DDERR_INVALIDOBJECT"; |
|
break; |
|
case DDERR_INVALIDPARAMS: |
|
szError = "DDERR_INVALIDPARAMS"; |
|
break; |
|
case DDERR_INVALIDPIXELFORMAT: |
|
szError = "DDERR_INVALIDPIXELFORMAT"; |
|
break; |
|
case DDERR_INVALIDPOSITION: |
|
szError = "DDERR_INVALIDPOSITION"; |
|
break; |
|
case DDERR_INVALIDRECT: |
|
szError = "DDERR_INVALIDRECT"; |
|
break; |
|
case DDERR_LOCKEDSURFACES: |
|
szError = "DDERR_LOCKEDSURFACES"; |
|
break; |
|
case DDERR_NO3D: |
|
szError = "DDERR_NO3D"; |
|
break; |
|
case DDERR_NOALPHAHW: |
|
szError = "DDERR_NOALPHAHW"; |
|
break; |
|
case DDERR_NOBLTHW: |
|
szError = "DDERR_NOBLTHW"; |
|
break; |
|
case DDERR_NOCLIPLIST: |
|
szError = "DDERR_NOCLIPLIST"; |
|
break; |
|
case DDERR_NOCLIPPERATTACHED: |
|
szError = "DDERR_NOCLIPPERATTACHED"; |
|
break; |
|
case DDERR_NOCOLORCONVHW: |
|
szError = "DDERR_NOCOLORCONVHW"; |
|
break; |
|
case DDERR_NOCOLORKEY: |
|
szError = "DDERR_NOCOLORKEY"; |
|
break; |
|
case DDERR_NOCOLORKEYHW: |
|
szError = "DDERR_NOCOLORKEYHW"; |
|
break; |
|
case DDERR_NOCOOPERATIVELEVELSET: |
|
szError = "DDERR_NOCOOPERATIVELEVELSET"; |
|
break; |
|
case DDERR_NODC: |
|
szError = "DDERR_NODC"; |
|
break; |
|
case DDERR_NODDROPSHW: |
|
szError = "DDERR_NODDROPSHW"; |
|
break; |
|
case DDERR_NODIRECTDRAWHW: |
|
szError = "DDERR_NODIRECTDRAWHW"; |
|
break; |
|
case DDERR_NOEMULATION: |
|
szError = "DDERR_NOEMULATION"; |
|
break; |
|
case DDERR_NOEXCLUSIVEMODE: |
|
szError = "DDERR_NOEXCLUSIVEMODE"; |
|
break; |
|
case DDERR_NOFLIPHW: |
|
szError = "DDERR_NOFLIPHW"; |
|
break; |
|
case DDERR_NOGDI: |
|
szError = "DDERR_NOGDI"; |
|
break; |
|
case DDERR_NOHWND: |
|
szError = "DDERR_NOHWND"; |
|
break; |
|
case DDERR_NOMIRRORHW: |
|
szError = "DDERR_NOMIRRORHW"; |
|
break; |
|
case DDERR_NOOVERLAYDEST: |
|
szError = "DDERR_NOOVERLAYDEST"; |
|
break; |
|
case DDERR_NOOVERLAYHW: |
|
szError = "DDERR_NOOVERLAYHW"; |
|
break; |
|
case DDERR_NOPALETTEATTACHED: |
|
szError = "DDERR_NOPALETTEATTACHED"; |
|
break; |
|
case DDERR_NOPALETTEHW: |
|
szError = "DDERR_NOPALETTEHW"; |
|
break; |
|
case DDERR_NORASTEROPHW: |
|
szError = "DDERR_NORASTEROPHW"; |
|
break; |
|
case DDERR_NOROTATIONHW: |
|
szError = "DDERR_NOROTATIONHW"; |
|
break; |
|
case DDERR_NOSTRETCHHW: |
|
szError = "DDERR_NOSTRETCHHW"; |
|
break; |
|
case DDERR_NOT4BITCOLOR: |
|
szError = "DDERR_NOT4BITCOLOR"; |
|
break; |
|
case DDERR_NOT4BITCOLORINDEX: |
|
szError = "DDERR_NOT4BITCOLORINDEX"; |
|
break; |
|
case DDERR_NOT8BITCOLOR: |
|
szError = "DDERR_NOT8BITCOLOR"; |
|
break; |
|
case DDERR_NOTAOVERLAYSURFACE: |
|
szError = "DDERR_NOTAOVERLAYSURFACE"; |
|
break; |
|
case DDERR_NOTEXTUREHW: |
|
szError = "DDERR_NOTEXTUREHW"; |
|
break; |
|
case DDERR_NOTFLIPPABLE: |
|
szError = "DDERR_NOTFLIPPABLE"; |
|
break; |
|
case DDERR_NOTFOUND: |
|
szError = "DDERR_NOTFOUND"; |
|
break; |
|
case DDERR_NOTLOCKED: |
|
szError = "DDERR_NOTLOCKED"; |
|
break; |
|
case DDERR_NOTPALETTIZED: |
|
szError = "DDERR_NOTPALETTIZED"; |
|
break; |
|
case DDERR_NOVSYNCHW: |
|
szError = "DDERR_NOVSYNCHW"; |
|
break; |
|
case DDERR_NOZBUFFERHW: |
|
szError = "DDERR_NOZBUFFERHW"; |
|
break; |
|
case DDERR_NOZOVERLAYHW: |
|
szError = "DDERR_NOZOVERLAYHW"; |
|
break; |
|
case DDERR_OUTOFCAPS: |
|
szError = "DDERR_OUTOFCAPS"; |
|
break; |
|
case DDERR_OUTOFMEMORY: |
|
szError = "DDERR_OUTOFMEMORY"; |
|
break; |
|
case DDERR_OUTOFVIDEOMEMORY: |
|
szError = "DDERR_OUTOFVIDEOMEMORY"; |
|
break; |
|
case DDERR_OVERLAYCANTCLIP: |
|
szError = "DDERR_OVERLAYCANTCLIP"; |
|
break; |
|
case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: |
|
szError = "DDERR_OVERLAYCOLORKEYONLYONEACTIVE"; |
|
break; |
|
case DDERR_OVERLAYNOTVISIBLE: |
|
szError = "DDERR_OVERLAYNOTVISIBLE"; |
|
break; |
|
case DDERR_PALETTEBUSY: |
|
szError = "DDERR_PALETTEBUSY"; |
|
break; |
|
case DDERR_PRIMARYSURFACEALREADYEXISTS: |
|
szError = "DDERR_PRIMARYSURFACEALREADYEXISTS"; |
|
break; |
|
case DDERR_REGIONTOOSMALL: |
|
szError = "DDERR_REGIONTOOSMALL"; |
|
break; |
|
case DDERR_SURFACEALREADYATTACHED: |
|
szError = "DDERR_SURFACEALREADYATTACHED"; |
|
break; |
|
case DDERR_SURFACEALREADYDEPENDENT: |
|
szError = "DDERR_SURFACEALREADYDEPENDENT"; |
|
break; |
|
case DDERR_SURFACEBUSY: |
|
szError = "DDERR_SURFACEBUSY"; |
|
break; |
|
case DDERR_SURFACEISOBSCURED: |
|
szError = "DDERR_SURFACEISOBSCURED"; |
|
break; |
|
case DDERR_SURFACELOST: |
|
szError = "DDERR_SURFACELOST"; |
|
break; |
|
case DDERR_SURFACENOTATTACHED: |
|
szError = "DDERR_SURFACENOTATTACHED"; |
|
break; |
|
case DDERR_TOOBIGHEIGHT: |
|
szError = "DDERR_TOOBIGHEIGHT"; |
|
break; |
|
case DDERR_TOOBIGSIZE: |
|
szError = "DDERR_TOOBIGSIZE"; |
|
break; |
|
case DDERR_TOOBIGWIDTH: |
|
szError = "DDERR_TOOBIGWIDTH"; |
|
break; |
|
case DDERR_UNSUPPORTED: |
|
szError = "DDERR_UNSUPPORTED"; |
|
break; |
|
case DDERR_UNSUPPORTEDFORMAT: |
|
szError = "DDERR_UNSUPPORTEDFORMAT"; |
|
break; |
|
case DDERR_UNSUPPORTEDMASK: |
|
szError = "DDERR_UNSUPPORTEDMASK"; |
|
break; |
|
case DDERR_VERTICALBLANKINPROGRESS: |
|
szError = "DDERR_VERTICALBLANKINPROGRESS"; |
|
break; |
|
case DDERR_WASSTILLDRAWING: |
|
szError = "DDERR_WASSTILLDRAWING"; |
|
break; |
|
case DDERR_WRONGMODE: |
|
szError = "DDERR_WRONGMODE"; |
|
break; |
|
case DDERR_XALIGN: |
|
szError = "DDERR_XALIGN"; |
|
break; |
|
case DDERR_CANTLOCKSURFACE: |
|
szError = "DDERR_CANTLOCKSURFACE"; |
|
break; |
|
case DDERR_CANTPAGELOCK: |
|
szError = "DDERR_CANTPAGELOCK"; |
|
break; |
|
case DDERR_CANTPAGEUNLOCK: |
|
szError = "DDERR_CANTPAGEUNLOCK"; |
|
break; |
|
case DDERR_DCALREADYCREATED: |
|
szError = "DDERR_DCALREADYCREATED"; |
|
break; |
|
case DDERR_INVALIDSURFACETYPE: |
|
szError = "DDERR_INVALIDSURFACETYPE"; |
|
break; |
|
case DDERR_NOMIPMAPHW: |
|
szError = "DDERR_NOMIPMAPHW"; |
|
break; |
|
case DDERR_NOTPAGELOCKED: |
|
szError = "DDERR_NOTPAGELOCKED"; |
|
break; |
|
default: { |
|
const char szUnknown[] = "DDERR unknown 0x%x"; |
|
assert(dwMaxChars >= sizeof(szUnknown) + 10); |
|
sprintf(pszBuffer, szUnknown, hError); |
|
return; |
|
} |
|
} |
|
|
|
strncpy(pszBuffer, szError, dwMaxChars); |
|
} |
|
|
|
/** |
|
* @brief Generate a textual message for DirectSound error codes |
|
* @param hError DirectSound error code |
|
* @param pszBuffer Buffer for the error message |
|
* @param dwMaxChars Length of pszBuffer |
|
*/ |
|
void TraceErrorDS(HRESULT hError, char *pszBuffer, DWORD dwMaxChars) |
|
{ |
|
const char *szError; |
|
|
|
switch (hError) { |
|
case DSERR_PRIOLEVELNEEDED: |
|
szError = "DSERR_PRIOLEVELNEEDED"; |
|
break; |
|
case DSERR_BADFORMAT: |
|
szError = "DSERR_BADFORMAT"; |
|
break; |
|
case DSERR_NODRIVER: |
|
szError = "DSERR_NODRIVER"; |
|
break; |
|
case DSERR_ALREADYINITIALIZED: |
|
szError = "DSERR_ALREADYINITIALIZED"; |
|
break; |
|
case DSERR_BUFFERLOST: |
|
szError = "DSERR_BUFFERLOST"; |
|
break; |
|
case DS_OK: |
|
szError = "DS_OK"; |
|
break; |
|
case DSERR_INVALIDCALL: |
|
szError = "DSERR_INVALIDCALL"; |
|
break; |
|
case E_NOINTERFACE: |
|
szError = "E_NOINTERFACE"; |
|
break; |
|
case DSERR_NOAGGREGATION: |
|
szError = "DSERR_NOAGGREGATION"; |
|
break; |
|
case DSERR_OUTOFMEMORY: |
|
szError = "DSERR_OUTOFMEMORY"; |
|
break; |
|
case DSERR_INVALIDPARAM: |
|
szError = "DSERR_INVALIDPARAM"; |
|
break; |
|
case DSERR_ALLOCATED: |
|
szError = "DSERR_ALLOCATED"; |
|
break; |
|
case DSERR_CONTROLUNAVAIL: |
|
szError = "DSERR_CONTROLUNAVAIL"; |
|
break; |
|
default: { |
|
const char szUnknown[] = "DSERR unknown 0x%x"; |
|
assert(dwMaxChars >= sizeof(szUnknown) + 10); |
|
sprintf(pszBuffer, szUnknown, hError); |
|
return; |
|
} |
|
} |
|
|
|
strncpy(pszBuffer, szError, dwMaxChars); |
|
} |
|
|
|
/** |
|
* @brief Returns a formatted error message of the last error. |
|
*/ |
|
char *TraceLastError() |
|
{ |
|
return GetErrorStr(GetLastError()); |
|
} |
|
|
|
/** |
|
* @brief Terminates the game and displays an error message box. |
|
* @param pszFmt Optional error message. |
|
* @param ... (see printf) |
|
*/ |
|
void __cdecl app_fatal(const char *pszFmt, ...) |
|
{ |
|
va_list va; |
|
|
|
va_start(va, pszFmt); |
|
FreeDlg(); |
|
#ifdef _DEBUG |
|
TriggerBreak(); |
|
#endif |
|
|
|
if (pszFmt) |
|
MsgBox(pszFmt, va); |
|
|
|
va_end(va); |
|
|
|
init_cleanup(FALSE); |
|
exit(1); |
|
ExitProcess(1); |
|
} |
|
|
|
/** |
|
* @brief Displays an error message box based on the given format string and variable argument list. |
|
* @param pszFmt Error message format |
|
* @param va Additional parameters for message format |
|
*/ |
|
void MsgBox(const char *pszFmt, va_list va) |
|
{ |
|
char Text[256]; |
|
|
|
wvsprintf(Text, pszFmt, va); |
|
if (ghMainWnd) |
|
SetWindowPos(ghMainWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); |
|
MessageBox(ghMainWnd, Text, "ERROR", MB_TASKMODAL | MB_ICONHAND); |
|
} |
|
|
|
/** |
|
* @brief Cleans up after a fatal application error. |
|
*/ |
|
void FreeDlg() |
|
{ |
|
if (terminating && cleanup_thread_id != GetCurrentThreadId()) |
|
Sleep(20000); |
|
|
|
terminating = TRUE; |
|
cleanup_thread_id = GetCurrentThreadId(); |
|
|
|
dx_cleanup(); |
|
|
|
if (gbMaxPlayers > 1) { |
|
if (SNetLeaveGame(3)) |
|
Sleep(2000); |
|
} |
|
|
|
SNetDestroy(); |
|
ShowCursor(TRUE); |
|
} |
|
|
|
/** |
|
* @brief Displays a warning message box based on the given formatted error message. |
|
* @param pszFmt Error message format |
|
* @param ... Additional parameters for message format |
|
*/ |
|
void __cdecl DrawDlg(const char *pszFmt, ...) |
|
{ |
|
char text[256]; |
|
va_list arglist; |
|
|
|
va_start(arglist, pszFmt); |
|
wvsprintf(text, pszFmt, arglist); |
|
va_end(arglist); |
|
SDrawMessageBox(text, APP_NAME, MB_TASKMODAL | MB_ICONEXCLAMATION); |
|
} |
|
|
|
#ifdef _DEBUG |
|
/** |
|
* @brief Show an error and exit the application. |
|
* @param nLineNo The line number of the assertion |
|
* @param pszFile File name where the assertion is located |
|
* @param pszFail Fail message |
|
*/ |
|
void assert_fail(int nLineNo, const char *pszFile, const char *pszFail) |
|
{ |
|
app_fatal("assertion failed (%d:%s)\n%s", nLineNo, pszFile, pszFail); |
|
} |
|
#endif |
|
|
|
/** |
|
* @brief Terminates the game with a DirectDraw assertion message box. |
|
*/ |
|
void DDErrMsg(DWORD error_code, int log_line_nr, const char *log_file_path) |
|
{ |
|
char *msg; |
|
|
|
if (error_code) { |
|
msg = GetErrorStr(error_code); |
|
app_fatal("Direct draw error (%s:%d)\n%s", log_file_path, log_line_nr, msg); |
|
} |
|
} |
|
|
|
/** |
|
* @brief Terminates the game with a DirectSound assertion message box. |
|
*/ |
|
void DSErrMsg(DWORD error_code, int log_line_nr, const char *log_file_path) |
|
{ |
|
char *msg; |
|
|
|
if (error_code) { |
|
msg = GetErrorStr(error_code); |
|
app_fatal("Direct sound error (%s:%d)\n%s", log_file_path, log_line_nr, msg); |
|
} |
|
} |
|
|
|
/** |
|
* @brief Centres the given dialog box. |
|
*/ |
|
void center_window(HWND hDlg) |
|
{ |
|
LONG w, h; |
|
int screenW, screenH; |
|
tagRECT Rect; |
|
HDC hdc; |
|
|
|
GetWindowRect(hDlg, &Rect); |
|
w = Rect.right - Rect.left; |
|
h = Rect.bottom - Rect.top; |
|
hdc = GetDC(hDlg); |
|
screenW = GetDeviceCaps(hdc, HORZRES); |
|
screenH = GetDeviceCaps(hdc, VERTRES); |
|
ReleaseDC(hDlg, hdc); |
|
|
|
if (!SetWindowPos(hDlg, HWND_TOP, (screenW - w) / 2, (screenH - h) / 2, 0, 0, SWP_NOZORDER | SWP_NOSIZE)) { |
|
app_fatal("center_window: %s", TraceLastError()); |
|
} |
|
} |
|
|
|
/** |
|
* @brief Callback function which processes messages sent to the given dialog box. |
|
*/ |
|
static BOOL CALLBACK FuncDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
switch (uMsg) { |
|
case WM_INITDIALOG: |
|
TextDlg(hDlg, (char *)lParam); |
|
break; |
|
case WM_COMMAND: |
|
if (LOWORD(wParam) == IDOK) { |
|
EndDialog(hDlg, TRUE); |
|
} else if (LOWORD(wParam) == IDCANCEL) { |
|
EndDialog(hDlg, FALSE); |
|
} |
|
break; |
|
default: |
|
return FALSE; |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
/** |
|
* @brief Terminates the game and displays an error dialog box based on the given dialog_id. |
|
*/ |
|
void ErrDlg(int dialog_id, DWORD error_code, const char *log_file_path, int log_line_nr) |
|
{ |
|
const char *size; |
|
LPARAM dwInitParam[128]; |
|
|
|
FreeDlg(); |
|
|
|
size = strrchr(log_file_path, '\\'); |
|
if (size) |
|
log_file_path = size + 1; |
|
|
|
wsprintf((LPSTR)dwInitParam, "%s\nat: %s line %d", GetErrorStr(error_code), log_file_path, log_line_nr); |
|
if (DialogBoxParam(ghInst, MAKEINTRESOURCE(dialog_id), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)dwInitParam) == -1) |
|
app_fatal("ErrDlg: %d", dialog_id); |
|
|
|
app_fatal(NULL); |
|
} |
|
|
|
/** |
|
* @brief Sets the text of the given dialog. |
|
*/ |
|
static void TextDlg(HWND hDlg, const char *text) |
|
{ |
|
center_window(hDlg); |
|
|
|
if (text) |
|
SetDlgItemText(hDlg, 1000, text); |
|
} |
|
|
|
/** |
|
* @brief Displays a warning dialog box based on the given dialog_id and error code. |
|
*/ |
|
void ErrOkDlg(int dialog_id, DWORD error_code, const char *log_file_path, int log_line_nr) |
|
{ |
|
const char *size; |
|
LPARAM dwInitParam[128]; |
|
|
|
size = strrchr(log_file_path, '\\'); |
|
if (size) |
|
log_file_path = size + 1; |
|
|
|
wsprintf((LPSTR)dwInitParam, "%s\nat: %s line %d", GetErrorStr(error_code), log_file_path, log_line_nr); |
|
DialogBoxParam(ghInst, MAKEINTRESOURCE(dialog_id), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)dwInitParam); |
|
} |
|
|
|
/** |
|
* @brief Terminates the game with a file not found error dialog. |
|
*/ |
|
void FileErrDlg(const char *error) |
|
{ |
|
FreeDlg(); |
|
|
|
if (!error) |
|
error = ""; |
|
|
|
if (DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_DIALOG3), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)error) == -1) |
|
app_fatal("FileErrDlg"); |
|
|
|
app_fatal(NULL); |
|
} |
|
|
|
/** |
|
* @brief Terminates the game with an out of disk space error dialog. |
|
*/ |
|
void DiskFreeDlg(const char *error) |
|
{ |
|
FreeDlg(); |
|
|
|
if (DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_DIALOG7), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)error) == -1) |
|
app_fatal("DiskFreeDlg"); |
|
|
|
app_fatal(NULL); |
|
} |
|
|
|
/** |
|
* @brief Terminates the game with an insert CD error dialog. |
|
*/ |
|
BOOL InsertCDDlg() |
|
{ |
|
int nResult; |
|
|
|
ShowCursor(TRUE); |
|
|
|
nResult = DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_DIALOG9), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM) ""); |
|
if (nResult == -1) |
|
app_fatal("InsertCDDlg"); |
|
|
|
ShowCursor(FALSE); |
|
|
|
return nResult == IDOK; |
|
} |
|
|
|
/** |
|
* @brief Terminates the game with a read-only directory error dialog. |
|
*/ |
|
void DirErrorDlg(const char *error) |
|
{ |
|
FreeDlg(); |
|
|
|
if (DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_DIALOG11), ghMainWnd, (DLGPROC)FuncDlg, (LPARAM)error) == -1) |
|
app_fatal("DirErrorDlg"); |
|
|
|
app_fatal(NULL); |
|
}
|
|
|