Browse Source

Merge pull request #184 from Hoikas/minidump

Improved Crash Handling
Branan Purvine-Riley 13 years ago
parent
commit
670576bf67
  1. 9
      README.rst
  2. 1
      Sources/Plasma/Apps/CMakeLists.txt
  3. 2
      Sources/Plasma/Apps/plClient/CMakeLists.txt
  4. 130
      Sources/Plasma/Apps/plClient/res/plClient.rc
  5. 2
      Sources/Plasma/Apps/plClient/res/resource.h
  6. 93
      Sources/Plasma/Apps/plClient/winmain.cpp
  7. 22
      Sources/Plasma/Apps/plCrashHandler/CMakeLists.txt
  8. 72
      Sources/Plasma/Apps/plCrashHandler/main.cpp
  9. 1
      Sources/Plasma/CoreLib/hsThread.h
  10. 12
      Sources/Plasma/CoreLib/hsThread_Unix.cpp
  11. 7
      Sources/Plasma/CoreLib/hsThread_Win.cpp
  12. 2
      Sources/Plasma/FeatureLib/CMakeLists.txt
  13. 21
      Sources/Plasma/FeatureLib/pfCrashHandler/CMakeLists.txt
  14. 60
      Sources/Plasma/FeatureLib/pfCrashHandler/plCrashBase.cpp
  15. 58
      Sources/Plasma/FeatureLib/pfCrashHandler/plCrashBase.h
  16. 138
      Sources/Plasma/FeatureLib/pfCrashHandler/plCrashCli.cpp
  17. 70
      Sources/Plasma/FeatureLib/pfCrashHandler/plCrashCli.h
  18. 52
      Sources/Plasma/FeatureLib/pfCrashHandler/plCrashCommon.h
  19. 117
      Sources/Plasma/FeatureLib/pfCrashHandler/plCrashSrv.cpp
  20. 68
      Sources/Plasma/FeatureLib/pfCrashHandler/plCrashSrv.h
  21. 70
      Sources/Plasma/FeatureLib/pfCrashHandler/plCrash_Private.h
  22. 27
      Sources/Plasma/FeatureLib/pfStackTrace/CMakeLists.txt
  23. 128
      Sources/Plasma/FeatureLib/pfStackTrace/pfArray.h
  24. 334
      Sources/Plasma/FeatureLib/pfStackTrace/pfMapFile.cpp
  25. 94
      Sources/Plasma/FeatureLib/pfStackTrace/pfMapFile.h
  26. 70
      Sources/Plasma/FeatureLib/pfStackTrace/pfMapFileEntry.cpp
  27. 64
      Sources/Plasma/FeatureLib/pfStackTrace/pfMapFileEntry.h
  28. 70
      Sources/Plasma/FeatureLib/pfStackTrace/pfPrintStackTrace.cpp
  29. 26
      Sources/Plasma/FeatureLib/pfStackTrace/pfPrintStackTrace.h
  30. 190
      Sources/Plasma/FeatureLib/pfStackTrace/pfStackTrace.cpp
  31. 49
      Sources/Plasma/FeatureLib/pfStackTrace/pfStackTrace.h
  32. 261
      Sources/Plasma/FeatureLib/pfStackTrace/pfTextFile.cpp
  33. 102
      Sources/Plasma/FeatureLib/pfStackTrace/pfTextFile.h
  34. 1
      Sources/Tools/MaxMain/CMakeLists.txt
  35. 1
      Sources/Tools/MaxPlasmaLights/CMakeLists.txt

9
README.rst

@ -119,12 +119,3 @@ Independent JPEG Group (IJG) JPEG Library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This software is based in part on the work of the Independent JPEG Group. This software is based in part on the work of the Independent JPEG Group.
Jani Kajala
~~~~~~~~~~~
Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting documentation. Jani
Kajala makes no representations about the suitability of this software for
any purpose. It is provided "as is" without express or implied warranty.

1
Sources/Plasma/Apps/CMakeLists.txt

@ -1,5 +1,6 @@
add_subdirectory(plClient) add_subdirectory(plClient)
add_subdirectory(plClientPatcher) add_subdirectory(plClientPatcher)
add_subdirectory(plCrashHandler)
add_subdirectory(plPythonPack) add_subdirectory(plPythonPack)
add_subdirectory(plUruLauncher) add_subdirectory(plUruLauncher)
add_subdirectory(plFileSecure) add_subdirectory(plFileSecure)

2
Sources/Plasma/Apps/plClient/CMakeLists.txt

@ -79,6 +79,7 @@ target_link_libraries(plClient pfCharacter)
target_link_libraries(plClient pfConditional) target_link_libraries(plClient pfConditional)
target_link_libraries(plClient pfConsole) target_link_libraries(plClient pfConsole)
target_link_libraries(plClient pfConsoleCore) target_link_libraries(plClient pfConsoleCore)
target_link_libraries(plClient pfCrashHandler)
target_link_libraries(plClient pfCsrSrv) target_link_libraries(plClient pfCsrSrv)
target_link_libraries(plClient pfGameGUIMgr) target_link_libraries(plClient pfGameGUIMgr)
target_link_libraries(plClient pfGameMgr) target_link_libraries(plClient pfGameMgr)
@ -88,7 +89,6 @@ target_link_libraries(plClient pfLocalizationMgr)
target_link_libraries(plClient pfMessage) target_link_libraries(plClient pfMessage)
target_link_libraries(plClient pfPython) target_link_libraries(plClient pfPython)
target_link_libraries(plClient pfSecurePreloader) target_link_libraries(plClient pfSecurePreloader)
target_link_libraries(plClient pfStackTrace)
target_link_libraries(plClient pfSurface) target_link_libraries(plClient pfSurface)
target_link_libraries(plClient plAgeDescription) target_link_libraries(plClient plAgeDescription)
target_link_libraries(plClient plAgeLoader) target_link_libraries(plClient plAgeLoader)

130
Sources/Plasma/Apps/plClient/res/plClient.rc

@ -6,14 +6,22 @@
#include <windows.h> #include <windows.h>
#define IDC_STATIC (-1) // all static controls #define IDC_STATIC (-1) // all static controls
#define APSTUDIO_READONLY_SYMBOLS
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources //
// Generated from the TEXTINCLUDE 2 resource.
//
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252) #pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@ -32,6 +40,12 @@ BEGIN
"\0" "\0"
END END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED
@ -57,27 +71,21 @@ IDI_ICON_DIRT ICON "Dirt.ICO"
// //
IDD_LOADING DIALOGEX 0, 0, 161, 26 IDD_LOADING DIALOGEX 0, 0, 161, 26
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE
WS_POPUP | WS_VISIBLE
FONT 8, "MS Sans Serif", 0, 0, 0x0 FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN BEGIN
LTEXT "Starting URU. Please wait...",IDC_STARTING_TEXT,32,9, LTEXT "Starting URU. Please wait...",IDC_STARTING_TEXT,32,9,127,8
127,8
ICON IDI_ICON_DIRT,IDC_STATIC,5,3,20,20 ICON IDI_ICON_DIRT,IDC_STATIC,5,3,20,20
END END
IDD_EXCEPTION DIALOGEX 0, 0, 296, 183 IDD_EXCEPTION DIALOGEX 0, 0, 297, 33
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Error" CAPTION "Error"
FONT 8, "MS Sans Serif", 0, 0, 0x0 FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN BEGIN
ICON IDI_ICON_DIRT,IDC_STATIC,7,7,21,20
LTEXT "URU has experienced a serious error and needs to close.\nPlease submit your log folder to the developer.",IDC_MSG,38,7,189,22
DEFPUSHBUTTON "OK",IDOK,239,7,50,14 DEFPUSHBUTTON "OK",IDOK,239,7,50,14
ICON IDI_ICON_DIRT,IDC_STATIC,7,7,20,20
LTEXT " URU has experienced a serious error. Please report the information below.\n\nWe apologize for any inconvenience. ",
IDC_MSG,38,7,189,37
EDITTEXT IDC_CRASHINFO,7,45,282,131,ES_MULTILINE | ES_AUTOVSCROLL |
ES_AUTOHSCROLL | ES_READONLY
PUSHBUTTON "Copy",IDC_COPY,239,26,50,14
END END
IDD_URULOGIN_MAIN DIALOGEX 0, 0, 302, 246 IDD_URULOGIN_MAIN DIALOGEX 0, 0, 302, 246
@ -114,37 +122,29 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Accept",IDOK,89,297,50,14 DEFPUSHBUTTON "Accept",IDOK,89,297,50,14
PUSHBUTTON "Decline",IDCANCEL,160,297,50,14 PUSHBUTTON "Decline",IDCANCEL,160,297,50,14
CONTROL 151,IDC_STATIC,"Static",SS_BITMAP,7,7,287,36, CONTROL 151,IDC_STATIC,"Static",SS_BITMAP,7,7,287,36,WS_EX_CLIENTEDGE
WS_EX_CLIENTEDGE CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,9,46,284,242
CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,9,46,
284,242
CTEXT "End User License Agreement",IDC_STATIC,46,55,207,10 CTEXT "End User License Agreement",IDC_STATIC,46,55,207,10
GROUPBOX "",IDC_STATIC,17,66,266,212 GROUPBOX "",IDC_STATIC,17,66,266,212
CONTROL "",IDC_URULOGIN_EULATEXT,"RichEdit20A",ES_MULTILINE | CONTROL "",IDC_URULOGIN_EULATEXT,"RichEdit20A",ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP,25,75,250,197
ES_AUTOHSCROLL | ES_READONLY | WS_BORDER | WS_VSCROLL |
WS_HSCROLL | WS_TABSTOP,25,75,250,197
END END
IDD_AUTHFAILED DIALOGEX 0, 0, 177, 89 IDD_AUTHFAILED DIALOGEX 0, 0, 177, 89
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE
WS_POPUP | WS_VISIBLE
FONT 8, "MS Sans Serif", 0, 0, 0x0 FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN BEGIN
LTEXT "Authentication failed. Please try again.", LTEXT "Authentication failed. Please try again.",IDC_AUTH_TEXT,38,17,127,8
IDC_AUTH_TEXT,38,17,127,8
ICON IDI_ICON_DIRT,IDC_STATIC,6,11,21,20 ICON IDI_ICON_DIRT,IDC_STATIC,6,11,21,20
PUSHBUTTON "Ok",IDOK,67,73,42,14 PUSHBUTTON "Ok",IDOK,67,73,42,14
CTEXT "",IDC_AUTH_MESSAGE,0,37,175,32 CTEXT "",IDC_AUTH_MESSAGE,0,37,175,32
END END
IDD_AUTHENTICATING DIALOGEX 0, 0, 177, 60 IDD_AUTHENTICATING DIALOGEX 0, 0, 177, 60
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE
WS_POPUP | WS_VISIBLE
FONT 8, "MS Sans Serif", 0, 0, 0x0 FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN BEGIN
ICON IDI_ICON_DIRT,IDC_STATIC,6,11,21,20 ICON IDI_ICON_DIRT,IDC_STATIC,6,11,21,20
LTEXT "Logging in to URU. Please wait...",IDC_AUTH_TEXT,38,17, LTEXT "Logging in to URU. Please wait...",IDC_AUTH_TEXT,38,17,137,8
137,8
PUSHBUTTON "Cancel",IDCANCEL,64,42,49,15 PUSHBUTTON "Cancel",IDCANCEL,64,42,49,15
END END
@ -159,67 +159,45 @@ GUIDELINES DESIGNINFO
BEGIN BEGIN
IDD_LOADING, DIALOG IDD_LOADING, DIALOG
BEGIN BEGIN
RIGHTMARGIN, 159 , 4096
, 458752
END END
IDD_EXCEPTION, DIALOG IDD_EXCEPTION, DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 RIGHTMARGIN, 296
RIGHTMARGIN, 289
TOPMARGIN, 7
BOTTOMMARGIN, 176
END
IDD_URUTAP_LOGIN, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 181
TOPMARGIN, 7
BOTTOMMARGIN, 104
END
IDD_URU_LOGIN, DIALOG
BEGIN
LEFTMARGIN, 4
RIGHTMARGIN, 168
TOPMARGIN, 7
BOTTOMMARGIN, 128
END
IDD_URU_EULA, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 194
TOPMARGIN, 7
BOTTOMMARGIN, 151
END END
IDD_URULOGIN_MAIN, DIALOG IDD_URULOGIN_MAIN, DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 , 71, 295
RIGHTMARGIN, 295 , 1029, 7
TOPMARGIN, 7 , 1031, 223
BOTTOMMARGIN, 223 , 4096
, 458752, 1348403200
END END
IDD_URULOGIN_EULA, DIALOG IDD_URULOGIN_EULA, DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 , 71, 293
RIGHTMARGIN, 293 , 1029, 7
TOPMARGIN, 7 , 1031, 311
BOTTOMMARGIN, 311 , 4096
, 11468800, 1430585344
END END
IDD_AUTHFAILED, DIALOG IDD_AUTHFAILED, DIALOG
BEGIN BEGIN
RIGHTMARGIN, 175 , 1031, 87
BOTTOMMARGIN, 87 , 4096
, 11468800, 1348206592
END END
IDD_AUTHENTICATING, DIALOG IDD_AUTHENTICATING, DIALOG
BEGIN BEGIN
RIGHTMARGIN, 175 , 1031, 57
BOTTOMMARGIN, 57 , 4096
, 4653129, 131144
END END
END END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED
@ -231,7 +209,7 @@ END
// //
IDR_CNSL1 CNSL "cnsl1.bin" IDR_CNSL1 CNSL "cnsl1.bin"
#endif // English (U.S.) resources #endif // English (United States) resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@ -241,17 +219,7 @@ IDR_CNSL1 CNSL "cnsl1.bin"
// //
// Generated from the TEXTINCLUDE 3 resource. // Generated from the TEXTINCLUDE 3 resource.
// //
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#endif
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED #endif // not APSTUDIO_INVOKED

2
Sources/Plasma/Apps/plClient/res/resource.h

@ -11,8 +11,6 @@
#define IDD_URULOGIN_EULA 154 #define IDD_URULOGIN_EULA 154
#define IDD_AUTHFAILED 155 #define IDD_AUTHFAILED 155
#define IDD_AUTHENTICATING 156 #define IDD_AUTHENTICATING 156
#define IDC_CRASHINFO 1001
#define IDC_COPY 1002
#define IDC_MSG 1003 #define IDC_MSG 1003
#define IDC_STARTING_TEXT 1004 #define IDC_STARTING_TEXT 1004
#define IDC_URULOGIN_REMEMBERPASS 1022 #define IDC_URULOGIN_REMEMBERPASS 1022

93
Sources/Plasma/Apps/plClient/winmain.cpp

@ -60,6 +60,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plClient.h" #include "plClient.h"
#include "plClientResMgr/plClientResMgr.h" #include "plClientResMgr/plClientResMgr.h"
#include "pfCrashHandler/plCrashCli.h"
#include "plNetClient/plNetClientMgr.h" #include "plNetClient/plNetClientMgr.h"
#include "plNetClient/plNetLinkingMgr.h" #include "plNetClient/plNetLinkingMgr.h"
#include "plInputCore/plInputManager.h" #include "plInputCore/plInputManager.h"
@ -124,6 +125,10 @@ plClient *gClient;
bool gPendingActivate = false; bool gPendingActivate = false;
bool gPendingActivateFlag = false; bool gPendingActivateFlag = false;
#ifndef HS_DEBUGGING
static plCrashCli s_crash;
#endif
static bool s_loginDlgRunning = false; static bool s_loginDlgRunning = false;
static hsSemaphore s_statusEvent(0); // Start non-signalled static hsSemaphore s_statusEvent(0); // Start non-signalled
static UINT s_WmTaskbarList = RegisterWindowMessage("TaskbarButtonCreated"); static UINT s_WmTaskbarList = RegisterWindowMessage("TaskbarButtonCreated");
@ -1346,103 +1351,33 @@ BOOL CALLBACK SplashDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM l
return 0; return 0;
} }
static char sStackTraceMsg[ 10240 ] = "";
void printStackTrace( char* buffer, int bufferSize, unsigned long stackPtr = 0, unsigned long opPtr = 0 );
//void StackTraceFromContext( HANDLE hThread, CONTEXT *context, char *outputBuffer );
BOOL CALLBACK ExceptionDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) BOOL CALLBACK ExceptionDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{ {
static char *sLastMsg = nil; static char *sLastMsg = nil;
switch( uMsg ) switch( uMsg )
{ {
case WM_INITDIALOG:
sLastMsg = (char *)lParam;
::SetDlgItemText( hwndDlg, IDC_CRASHINFO, sLastMsg );
return true;
case WM_COMMAND: case WM_COMMAND:
if( wParam == IDC_COPY && sLastMsg != nil )
{
HGLOBAL copyText = GlobalAlloc( GMEM_DDESHARE, sizeof( TCHAR ) * ( strlen( sLastMsg ) + 1 ) );
if( copyText != nil )
{
LPTSTR copyPtr = (LPTSTR)GlobalLock( copyText );
memcpy( copyPtr, sLastMsg, ( strlen( sLastMsg ) + 1 ) * sizeof( TCHAR ) );
GlobalUnlock( copyText );
::OpenClipboard( hwndDlg );
::EmptyClipboard();
::SetClipboardData( CF_TEXT, copyText );
::CloseClipboard();
}
return true;
}
else if( wParam == IDOK )
EndDialog( hwndDlg, IDOK ); EndDialog( hwndDlg, IDOK );
else
break;
} }
return 0; return 0;
} }
#ifndef HS_DEBUGGING
LONG WINAPI plCustomUnhandledExceptionFilter( struct _EXCEPTION_POINTERS *ExceptionInfo ) LONG WINAPI plCustomUnhandledExceptionFilter( struct _EXCEPTION_POINTERS *ExceptionInfo )
{ {
const char *type = nil; // Before we do __ANYTHING__, pass the exception to plCrashHandler
switch( ExceptionInfo->ExceptionRecord->ExceptionCode ) s_crash.ReportCrash(ExceptionInfo);
{
case EXCEPTION_ACCESS_VIOLATION: type = "Access violation"; break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: type = "Array bounds exceeded"; break;
case EXCEPTION_BREAKPOINT: type = "Breakpoint"; break;
case EXCEPTION_DATATYPE_MISALIGNMENT: type = "Datatype misalignment"; break;
case EXCEPTION_FLT_DENORMAL_OPERAND: type = "Floating operand denormal"; break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO: type = "Floating-point divide-by-zero"; break;
case EXCEPTION_FLT_INEXACT_RESULT: type = "Floating-point inexact result"; break;
case EXCEPTION_FLT_INVALID_OPERATION: type = "Floating-point invalid operation"; break;
case EXCEPTION_FLT_OVERFLOW: type = "Floating-point overflow"; break;
case EXCEPTION_FLT_STACK_CHECK: type = "Floating-point stack error"; break;
case EXCEPTION_FLT_UNDERFLOW: type = "Floating-point underflow"; break;
case EXCEPTION_ILLEGAL_INSTRUCTION: type = "Illegal instruction"; break;
case EXCEPTION_IN_PAGE_ERROR: type = "Exception in page"; break;
case EXCEPTION_INT_DIVIDE_BY_ZERO: type = "Integer divide-by-zero"; break;
case EXCEPTION_INT_OVERFLOW: type = "Integer overflow"; break;
case EXCEPTION_INVALID_DISPOSITION: type = "Invalid disposition"; break;
case EXCEPTION_NONCONTINUABLE_EXCEPTION: type = "Noncontinuable exception"; break;
case EXCEPTION_PRIV_INSTRUCTION: type = "Private instruction"; break;
case EXCEPTION_SINGLE_STEP: type = "Single-step"; break;
case EXCEPTION_STACK_OVERFLOW: type = "Stack overflow"; break;
}
char prodName[256];
wchar_t productString[256];
ProductString(productString, arrsize(productString));
StrToAnsi(prodName, productString, arrsize(prodName));
sprintf( sStackTraceMsg, "%s\r\nException type: %s\r\n", prodName, ( type != nil ) ? type : "(unknown)" ); // Now, try to create a nice exception dialog after plCrashHandler is done.
s_crash.WaitForHandle();
printStackTrace( sStackTraceMsg, sizeof( sStackTraceMsg ), ExceptionInfo->ContextRecord->Ebp, (unsigned long)ExceptionInfo->ExceptionRecord->ExceptionAddress ); HWND parentHwnd = (gClient == nil) ? GetActiveWindow() : gClient->GetWindowHandle();
DialogBoxParam(gHInst, MAKEINTRESOURCE(IDD_EXCEPTION), parentHwnd, ExceptionDialogProc, NULL);
/// Print the info out to a log file as well
hsUNIXStream log;
wchar_t fileAndPath[MAX_PATH];
PathGetLogDirectory(fileAndPath, arrsize(fileAndPath));
PathAddFilename(fileAndPath, fileAndPath, L"stackDump.log", arrsize(fileAndPath));
if( log.Open( fileAndPath, L"wt" ) )
{
log.WriteString( sStackTraceMsg );
log.Close();
}
/// Hopefully we can access this resource, even given the exception (i.e. very-bad-error) we just experienced // Trickle up the handlers
if(TGIsCider || (::DialogBoxParam( gHInst, MAKEINTRESOURCE( IDD_EXCEPTION ), ( gClient != nil ) ? gClient->GetWindowHandle() : nil,
ExceptionDialogProc, (LPARAM)sStackTraceMsg ) == -1) )
{
// The dialog failed, so just fallback to a standard message box
hsMessageBox( sStackTraceMsg, "UruExplorer Exception", hsMessageBoxNormal );
}
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;
} }
#endif
bool CheckCPU() bool CheckCPU()
{ {

22
Sources/Plasma/Apps/plCrashHandler/CMakeLists.txt

@ -0,0 +1,22 @@
include_directories("../../CoreLib")
include_directories("../../NucleusLib")
include_directories("../../FeatureLib")
set(plCrashHandler_SOURCES
main.cpp
)
add_executable(plCrashHandler ${plCrashHandler_SOURCES})
if(PLASMA_EXTERNAL_RELEASE)
set_target_properties(plClient PROPERTIES OUTPUT_NAME "UruCrashHandler")
endif(PLASMA_EXTERNAL_RELEASE)
target_link_libraries(plCrashHandler CoreLib)
target_link_libraries(plCrashHandler pfCrashHandler)
target_link_libraries(plCrashHandler plFile)
target_link_libraries(plCrashHandler pnProduct)
target_link_libraries(plCrashHandler pnUtils)
# Platform specific libs
if(WIN32)
target_link_libraries(plCrashHandler Dbghelp)
endif(WIN32)

72
Sources/Plasma/Apps/plCrashHandler/main.cpp

@ -0,0 +1,72 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "pfCrashHandler/plCrashSrv.h"
#include "pnUtils/pnUtils.h"
enum
{
kArgMemFile
};
static const CmdArgDef s_cmdLineArgs[] =
{
{ (kCmdArgRequired | kCmdTypeString), nil, kArgMemFile },
};
int main(int argc, char* argv[])
{
// Parse command line arguments. We MUST have the file argument
CCmdParser cmdParser(s_cmdLineArgs, arrsize(s_cmdLineArgs));
if (!cmdParser.Parse())
{
hsMessageBox("You should never run this manually.", "Error", hsMessageBoxNormal, hsMessageBoxIconExclamation);
return 1;
}
char* file = hsWStringToString(cmdParser.GetString(kArgMemFile));
plCrashSrv srv(file);
delete[] file;
srv.HandleCrash();
return 0;
}

1
Sources/Plasma/CoreLib/hsThread.h

@ -157,6 +157,7 @@ public:
hsSemaphore(int initialValue=0, const char* name=nil); hsSemaphore(int initialValue=0, const char* name=nil);
~hsSemaphore(); ~hsSemaphore();
hsBool TryWait();
hsBool Wait(hsMilliseconds timeToWait = kPosInfinity32); hsBool Wait(hsMilliseconds timeToWait = kPosInfinity32);
void Signal(); void Signal();
}; };

12
Sources/Plasma/CoreLib/hsThread_Unix.cpp

@ -316,6 +316,18 @@ hsSemaphore::~hsSemaphore()
#endif #endif
} }
hsBool hsSemaphore::TryWait()
{
#ifdef USE_SEMA
int status = ::sem_trywait(fPSema);
return status != E_AGAIN;
#else
int status = ::pthread_mutex_trylock(&fPMutex);
hsThrowIfOSErr(status);
return status==EBUSY ? false : true;
#endif
}
hsBool hsSemaphore::Wait(hsMilliseconds timeToWait) hsBool hsSemaphore::Wait(hsMilliseconds timeToWait)
{ {
#ifdef USE_SEMA // SHOULDN'T THIS USE timeToWait??!?!? -rje #ifdef USE_SEMA // SHOULDN'T THIS USE timeToWait??!?!? -rje

7
Sources/Plasma/CoreLib/hsThread_Win.cpp

@ -170,6 +170,13 @@ hsSemaphore::~hsSemaphore()
::CloseHandle(fSemaH); ::CloseHandle(fSemaH);
} }
hsBool hsSemaphore::TryWait()
{
DWORD result = ::WaitForSingleObject(fSemaH, 0);
hsAssert(result != WAIT_ABANDONED, "hsSemaphore -> Abandoned Semaphore");
return result == WAIT_OBJECT_0;
}
hsBool hsSemaphore::Wait(hsMilliseconds timeToWait) hsBool hsSemaphore::Wait(hsMilliseconds timeToWait)
{ {
if (timeToWait == kPosInfinity32) if (timeToWait == kPosInfinity32)

2
Sources/Plasma/FeatureLib/CMakeLists.txt

@ -8,6 +8,7 @@ add_subdirectory(pfCharacter)
add_subdirectory(pfConditional) add_subdirectory(pfConditional)
add_subdirectory(pfConsole) add_subdirectory(pfConsole)
add_subdirectory(pfConsoleCore) add_subdirectory(pfConsoleCore)
add_subdirectory(pfCrashHandler)
add_subdirectory(pfCsrSrv) add_subdirectory(pfCsrSrv)
add_subdirectory(pfGameGUIMgr) add_subdirectory(pfGameGUIMgr)
add_subdirectory(pfGameMgr) add_subdirectory(pfGameMgr)
@ -22,5 +23,4 @@ add_subdirectory(pfLocalizationMgr)
add_subdirectory(pfMessage) add_subdirectory(pfMessage)
add_subdirectory(pfPython) add_subdirectory(pfPython)
add_subdirectory(pfSecurePreloader) add_subdirectory(pfSecurePreloader)
add_subdirectory(pfStackTrace)
add_subdirectory(pfSurface) add_subdirectory(pfSurface)

21
Sources/Plasma/FeatureLib/pfCrashHandler/CMakeLists.txt

@ -0,0 +1,21 @@
include_directories(../../CoreLib)
include_directories(../../NucleusLib)
include_directories(../../PubUtilLib)
set(pfCrashHandler_HEADERS
plCrashCli.h
plCrashBase.h
plCrash_Private.h
plCrashSrv.h
)
set(pfCrashHandler_SOURCES
plCrashCli.cpp
plCrashBase.cpp
plCrashSrv.cpp
)
add_library(pfCrashHandler STATIC ${pfCrashHandler_SOURCES} ${pfCrashHandler_HEADERS})
source_group("Source Files" FILES ${pfCrashHandler_SOURCES})
source_group("Header Files" FILES ${pfCrashHandler_HEADERS})

60
Sources/Plasma/FeatureLib/pfCrashHandler/plCrashBase.cpp

@ -0,0 +1,60 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plCrashBase.h"
#include "plCrash_Private.h"
plCrashBase::~plCrashBase()
{
delete fCrashed;
delete fHandled;
}
void plCrashBase::IInit(const char* file)
{
char sema[128];
snprintf(sema, arrsize(sema), "%s-%s", file, CRASH_NOTIFY_SUFFIX);
fCrashed = new hsSemaphore(0, sema);
snprintf(sema, arrsize(sema), "%s-%s", file, CRASH_HANDLE_SUFFIX);
fHandled = new hsSemaphore(0, sema);
}

58
Sources/Plasma/FeatureLib/pfCrashHandler/plCrashBase.h

@ -0,0 +1,58 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef _pfCrashBase_h_
#define _pfCrashBase_h_
#include "hsThread.h"
class plCrashBase
{
protected:
hsSemaphore* fCrashed;
hsSemaphore* fHandled;
~plCrashBase();
void IInit(const char* file);
};
#endif // _pfCrashBase_h_

138
Sources/Plasma/FeatureLib/pfCrashHandler/plCrashCli.cpp

@ -0,0 +1,138 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plCrashCli.h"
#include "plCrash_Private.h"
#include "plString.h"
#ifdef HS_BUILD_FOR_WIN32
plCrashCli::plCrashCli()
: fLink(nil), fLinkH(nil)
{
char mapname[128];
char cmdline[128];
snprintf(mapname, arrsize(mapname), "Plasma20CrashHandler-%u", GetCurrentProcessId());
snprintf(cmdline, arrsize(cmdline), "%s %s", CRASH_HANDLER_EXE, mapname);
memset(&fCrashSrv, 0, sizeof(PROCESS_INFORMATION));
// Initialize the semas
IInit(mapname);
// Initialize the shared memory
fLinkH = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(plCrashMemLink), mapname);
hsAssert(fLinkH, "Failed to create plCrashHandler mapping");
if (!fLinkH)
return;
// Map the shared memory
fLink = (plCrashMemLink*)MapViewOfFile(fLinkH, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(plCrashMemLink));
hsAssert(fLink, "Failed to map plCrashLinkedMem");
if (!fLink)
return;
memset(fLink, 0, sizeof(plCrashMemLink));
fLink->fClientProcessID = GetCurrentProcessId();
// Start the plCrashHandler before a crash
STARTUPINFOA info; memset(&info, 0, sizeof(info));
info.cb = sizeof(STARTUPINFOA);
CreateProcessA(
CRASH_HANDLER_EXE, // plCrashHandler.exe
cmdline, // plCrashHandler.exe Plasma20CrashHandler-%u
NULL,
NULL,
FALSE,
CREATE_NO_WINDOW, // Don't create any new windows or consoles
NULL,
NULL, // Use the directory of the current plClient
&info,
&fCrashSrv // Save the CrashSrv handles
);
HANDLE curProc = GetCurrentProcess();
DuplicateHandle(curProc, // Handle to the source process
curProc, // Handle that we want duplicated
fCrashSrv.hProcess, // Handle to target process
&fLink->fClientProcess, // Pointer to Handle to dupliicate to
0, // Ignored
FALSE,
DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS
);
}
plCrashCli::~plCrashCli()
{
fCrashed->Signal(); // forces the CrashSrv to exit, if it's still running
if (fCrashSrv.hProcess)
{
TerminateProcess(fCrashSrv.hProcess, 0);
CloseHandle(fCrashSrv.hProcess);
}
if (fCrashSrv.hThread)
CloseHandle(fCrashSrv.hThread);
if (fLink)
UnmapViewOfFile((LPCVOID)fLink);
if (fLinkH)
CloseHandle(fLinkH);
}
void plCrashCli::ReportCrash(PEXCEPTION_POINTERS e)
{
hsAssert(fLink, "plCrashMemLink is nil");
if (fLink)
{
fLink->fClientThreadID = GetCurrentThreadId();
fLink->fCrashed = true;
fLink->fExceptionPtrs = e;
}
fCrashed->Signal();
}
#else
# error "Implement plCrashCli for this platform"
#endif
void plCrashCli::WaitForHandle()
{
fHandled->Wait();
}

70
Sources/Plasma/FeatureLib/pfCrashHandler/plCrashCli.h

@ -0,0 +1,70 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef _pfCrashCli_h_
#define _pfCrashCli_h_
#include "HeadSpin.h"
#include "plCrashBase.h"
struct plCrashMemLink;
class plCrashCli : public plCrashBase
{
plCrashMemLink* fLink;
#ifdef HS_BUILD_FOR_WIN32
PROCESS_INFORMATION fCrashSrv;
HANDLE fLinkH;
#endif
public:
plCrashCli();
~plCrashCli();
#ifdef HS_BUILD_FOR_WIN32
void ReportCrash(PEXCEPTION_POINTERS);
#endif
void WaitForHandle();
};
#endif // _pfCrashCli_h_

52
Sources/Plasma/FeatureLib/pfCrashHandler/plCrashCommon.h

@ -0,0 +1,52 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef _pnCrashCommon_h_
#define _pnCrashCommon_h_
#include "HeadSpin.h"
struct plCrashLink
{
};
#endif // _pnCrashCommon_h_

117
Sources/Plasma/FeatureLib/pfCrashHandler/plCrashSrv.cpp

@ -0,0 +1,117 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plCrashSrv.h"
#include "plCrash_Private.h"
#include "plFile/plFileUtils.h"
#include "pnProduct/pnProduct.h"
#ifdef HS_BUILD_FOR_WIN32
#include <DbgHelp.h>
#include <ShlObj.h>
plCrashSrv::plCrashSrv(const char* file)
: fLink(nil), fLinkH(nil)
{
// Init semas
IInit(file);
// Open the linked memory
fLinkH = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, file);
hsAssert(fLinkH, "Failed to open plCrashHandler mapping");
if (!fLinkH)
return;
// Try to map it
fLink = (plCrashMemLink*)MapViewOfFile(fLinkH, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(plCrashMemLink));
hsAssert(fLink, "Failed to map plCrashMemLink");
}
plCrashSrv::~plCrashSrv()
{
if (fLink)
UnmapViewOfFile((LPCVOID)fLink);
if (fLinkH)
CloseHandle(fLinkH);
}
void plCrashSrv::IHandleCrash()
{
// Begin Hackiness
wchar_t dumpPath[1024];
SHGetSpecialFolderPathW(NULL, dumpPath, CSIDL_LOCAL_APPDATA, TRUE);
plFileUtils::ConcatFileName(dumpPath, ProductLongName());
plFileUtils::ConcatFileName(dumpPath, L"Log");
plFileUtils::EnsureFilePathExists(dumpPath);
plFileUtils::ConcatFileName(dumpPath, L"crash.dmp");
HANDLE file = CreateFileW(dumpPath,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
// End Hackiness
MINIDUMP_EXCEPTION_INFORMATION e;
e.ClientPointers = TRUE;
e.ExceptionPointers = fLink->fExceptionPtrs;
e.ThreadId = fLink->fClientThreadID;
MiniDumpWriteDump(fLink->fClientProcess, fLink->fClientProcessID, file, MiniDumpNormal, &e, NULL, NULL);
CloseHandle(file);
}
#else
# error "Implement plCrashSrv for this platform"
#endif
void plCrashSrv::HandleCrash()
{
fCrashed->Wait(); // Wait for a crash
if (!fLink)
FATAL("plCrashMemLink is nil!");
else if (fLink->fCrashed)
IHandleCrash();
fHandled->Signal(); // Tell CrashCli we handled it
}

68
Sources/Plasma/FeatureLib/pfCrashHandler/plCrashSrv.h

@ -0,0 +1,68 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef _pfCrashSrv_h_
#define _pfCrashSrv_h_
#include "HeadSpin.h"
#include "plCrashBase.h"
struct plCrashMemLink;
class plCrashSrv : public plCrashBase
{
plCrashMemLink* fLink;
#ifdef HS_BUILD_FOR_WIN32
HANDLE fLinkH;
#endif
void IHandleCrash();
public:
plCrashSrv(const char* file);
~plCrashSrv();
void HandleCrash();
};
#endif // _pfCrashSrv_h_

70
Sources/Plasma/FeatureLib/pfCrashHandler/plCrash_Private.h

@ -0,0 +1,70 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef _pfCrash_Private_h_
#define _pfCrash_Private_h_
#include "HeadSpin.h"
#define CRASH_NOTIFY_SUFFIX "CrashNotify"
#define CRASH_HANDLE_SUFFIX "CrashHandled"
#ifdef HS_BUILD_FOR_WIN32
# ifdef PLASMA_EXTERNAL_RELEASE
# define CRASH_HANDLER_EXE "UruCrashHandler.exe"
# else
# define CRASH_HANDLER_EXE "plCrashHandler.exe"
# endif // PLASMA_EXTERNAL_RELEASE
#endif // HS_BUILD_FOR_WIN32
struct plCrashMemLink
{
bool fCrashed;
#ifdef HS_BUILD_FOR_WIN32
HANDLE fClientProcess;
uint32_t fClientProcessID;
uint32_t fClientThreadID;
PEXCEPTION_POINTERS fExceptionPtrs;
#endif
};
#endif // _pfCrash_Private_h_

27
Sources/Plasma/FeatureLib/pfStackTrace/CMakeLists.txt

@ -1,27 +0,0 @@
include_directories(../../CoreLib)
if(WIN32)
add_definitions(-DWIN32)
endif(WIN32)
set(pfStackTrace_SOURCES
pfMapFile.cpp
pfMapFileEntry.cpp
pfPrintStackTrace.cpp
pfStackTrace.cpp
pfTextFile.cpp
)
set(pfStackTrace_HEADERS
pfArray.h
pfMapFile.h
pfMapFileEntry.h
pfPrintStackTrace.h
pfStackTrace.h
pfTextFile.h
)
add_library(pfStackTrace STATIC ${pfStackTrace_SOURCES} ${pfStackTrace_HEADERS})
source_group("Source Files" FILES ${pfStackTrace_SOURCES})
source_group("Header Files" FILES ${pfStackTrace_HEADERS})

128
Sources/Plasma/FeatureLib/pfStackTrace/pfArray.h

@ -1,128 +0,0 @@
#ifndef _DEV_ARRAY_H
#define _DEV_ARRAY_H
namespace dev
{
/** Very simple dynamic array. */
template <class T> class Array
{
public:
/** Creates an empty array. */
Array() :
m_data(0), m_len(0), m_cap(0)
{
}
/** Creates an array of specified size. */
explicit Array( int size ) :
m_data(0), m_len(0), m_cap(0)
{
setSize( size );
}
///
~Array()
{
delete[] m_data;
}
/** Appends an item at the end of the array. */
void add( const T& item )
{
if ( m_len+1 > m_cap )
setCapacity( m_len + 1 );
m_data[m_len++] = item;
}
/** Resizes the array. */
void setSize( int size )
{
if ( size > m_cap )
setCapacity( size );
m_len = size;
}
/** Returns ith item. */
T& operator[]( int i )
{
return m_data[i];
}
/** Returns pointer to the first element in the vector. */
T* begin()
{
return m_data;
}
/** Returns pointer to one beyond the last element in the vector. */
T* end()
{
return m_data + m_len;
}
/** Returns number of items in the array. */
int size() const
{
return m_len;
}
/** Returns ith item. */
const T& operator[]( int i ) const
{
return m_data[i];
}
/** Returns pointer to the first element in the vector. */
const T* begin() const
{
return m_data;
}
/** Returns pointer to one beyond the last element in the vector. */
const T* end() const
{
return m_data + m_len;
}
private:
T* m_data;
int m_len;
int m_cap;
void setCapacity( int cap )
{
++cap;
if ( cap < 8 )
cap = 8;
else if ( cap < m_cap*2 )
cap = m_cap*2;
m_cap = cap;
T* data = new T[cap];
for ( int i = 0 ; i < m_len ; ++i )
data[i] = m_data[i];
delete[] m_data;
m_data = data;
}
};
} // dev
#endif // _DEV_ARRAY_H
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

334
Sources/Plasma/FeatureLib/pfStackTrace/pfMapFile.cpp

@ -1,334 +0,0 @@
#include "HeadSpin.h"
#include "pfMapFile.h"
#include "pfMapFileEntry.h"
#include "pfTextFile.h"
#include "pfArray.h"
#include <algorithm>
#include <string.h>
#include <ctype.h>
//-----------------------------------------------------------------------------
namespace dev
{
class MapFile::MapFileImpl
{
public:
long loadAddr;
char name[256];
Array<MapFileEntry> segments;
Array<MapFileEntry> entries;
MapFileImpl( const char* filename ) :
loadAddr(0), m_file( filename ), m_err( MapFile::ERROR_NONE )
{
m_file.readString( name, sizeof(name) );
char buf[1024];
while ( m_file.readString(buf,sizeof(buf)) )
{
if ( !strcmp("Preferred",buf) )
parseLoadAddress();
else if ( !strcmp("Start",buf) )
parseSegments();
else if ( !strcmp("Address",buf) )
parseEntries();
else
m_file.skipLine();
}
std::sort( segments.begin(), segments.end() );
std::sort( entries.begin(), entries.end() );
}
~MapFileImpl()
{
}
ErrorType error() const
{
if ( m_err != MapFile::ERROR_NONE )
return m_err;
switch ( m_file.error() )
{
case TextFile::ERROR_OPEN: return MapFile::ERROR_OPEN;
case TextFile::ERROR_READ: return MapFile::ERROR_READ;
case TextFile::ERROR_PARSE: return MapFile::ERROR_PARSE;
default: return MapFile::ERROR_NONE;
}
}
int line() const
{
if ( m_err != MapFile::ERROR_NONE )
return m_errLine;
return m_file.line();
}
private:
TextFile m_file;
MapFile::ErrorType m_err;
int m_errLine;
/**
* Returns true if the next line is empty.
*/
bool nextLineEmpty()
{
m_file.skipLine();
char ch;
while ( m_file.peekChar(&ch) && isspace(ch) && ch != '\n' )
m_file.readChar( &ch );
if ( m_file.peekChar(&ch) && ch == '\n' )
return true;
return false;
}
/**
* Parses specified string.
* Sets error if parsed string doesnt match.
*/
void parse( const char* str )
{
char buf[256];
m_file.readString( buf, sizeof(buf) );
if ( strcmp(str,buf) )
{
m_err = MapFile::ERROR_PARSE;
m_errLine = m_file.line();
}
}
/**
* Parses specified character.
* Sets error if parsed character doesnt match.
*/
void parse( char ch )
{
char ch2;
if ( !m_file.readChar(&ch2) || ch2 != ch )
{
m_err = MapFile::ERROR_PARSE;
m_errLine = m_file.line();
}
}
/**
* Example:
* (Preferred) load address is 00400000
*/
void parseLoadAddress()
{
parse( "load" ); parse( "address" ); parse( "is" );
loadAddr = m_file.readHex();
}
/**
* Example:
* (Start) Length Name Class
* 0001:00000000 00002c05H .text CODE
*/
void parseSegments()
{
parse( "Length" );
parse( "Name" );
parse( "Class" );
m_file.skipWhitespace();
while ( !error() )
{
int seg = m_file.readHex();
parse( ':' );
int offs = m_file.readHex();
int len = m_file.readHex();
parse( 'H' );
char buf[256];
m_file.readString( buf, sizeof(buf) );
segments.add( MapFileEntry(seg,offs,len,buf) );
// break at empty line
if ( nextLineEmpty() )
break;
}
}
/**
* Example:
* (Address) Publics by Value Rva+Base Lib:Object
* 0001:000001a0 ?stackTrace@@YAXXZ 004011a0 f main.obj
*/
void parseEntries()
{
parse( "Publics" ); parse( "by" ); parse( "Value" );
parse( "Rva+Base" );
parse( "Lib:Object" );
m_file.skipWhitespace();
while ( !error() )
{
int seg = m_file.readHex();
parse( ':' );
int offs = m_file.readHex();
char buf[256];
m_file.readString( buf, sizeof(buf) );
char* entryname = buf;
// chop entry name at @@
char* end = strstr( entryname, "@@" );
if ( end )
*end = 0;
// skip preceding ?01..
while ( isdigit(*entryname) || *entryname == '?' || *entryname == '$' )
++entryname;
// conv @ -> .
for ( char* str = entryname ; *str ; ++str )
if ( *str == '@' )
*str = '.';
// Added 9.5.02 mcn - Reverse the order of the symbols to be more natural
if( strlen( entryname ) < 512 )
{
static char newName[ 512 ];
char *search;
newName[ 0 ] = 0;
while( ( search = strrchr( entryname, '.' ) ) != 0 )
{
*search = 0;
if( newName[ 0 ] != 0 )
strcat( newName, "::" );
strcat( newName, search + 1 );
}
if( newName[ 0 ] != 0 )
strcat( newName, "::" );
strcat( newName, entryname );
entryname = newName;
}
entries.add( MapFileEntry(seg,offs,0,entryname) );
// break at empty line
if ( nextLineEmpty() )
break;
}
}
};
//-----------------------------------------------------------------------------
MapFile::MapFile( const char* filename )
{
m_this = new MapFileImpl( filename );
}
MapFile::~MapFile()
{
delete m_this;
}
long MapFile::loadAddress() const
{
return m_this->loadAddr;
}
const MapFileEntry& MapFile::getSegment( int i ) const
{
return m_this->segments[i];
}
const MapFileEntry& MapFile::getEntry( int i ) const
{
return m_this->entries[i];
}
int MapFile::segments() const
{
return m_this->segments.size();
}
int MapFile::entries() const
{
return m_this->entries.size();
}
MapFile::ErrorType MapFile::error() const
{
return m_this->error();
}
int MapFile::line() const
{
return m_this->line();
}
int MapFile::findEntry( long addr ) const
{
for ( int j = 0 ; j < segments() ; ++j )
{
const MapFileEntry& segment = getSegment( j );
long section = segment.section();
long segmentBegin = loadAddress() + (segment.section() << 12) + segment.offset();
long segmentEnd = segmentBegin + segment.length();
if ( addr >= segmentBegin && addr < segmentEnd )
{
for ( int i = entries()-1 ; i >= 0 ; --i )
{
const MapFileEntry entry = getEntry( i );
if ( entry.section() == section )
{
long entryAddr = loadAddress() + (entry.section() << 12) + entry.offset();
if ( entryAddr <= addr )
return i;
}
}
}
}
return -1;
}
void MapFile::getModuleMapFilename( char* buffer, int bufferSize )
{
int len = 0;
buffer[len] = 0;
#ifdef WIN32
// get name of the exe/dll
len = GetModuleFileName( GetModuleHandle(0), buffer, bufferSize-1 );
buffer[len] = 0;
#endif
// remove .exe or .dll extension
if ( len > 3 &&
(!strcmp(buffer+len-4,".exe") || !strcmp(buffer+len-4,".EXE") ||
!strcmp(buffer+len-4,".DLL") || !strcmp(buffer+len-4,".dll")) )
{
buffer[len-4] = 0;
}
// append .map extension
if ( (int)strlen(buffer)+4 < bufferSize )
{
strcat( buffer, ".map" );
}
}
} // dev
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

94
Sources/Plasma/FeatureLib/pfStackTrace/pfMapFile.h

@ -1,94 +0,0 @@
#ifndef _DEV_MAPFILE_H
#define _DEV_MAPFILE_H
namespace dev
{
class MapFileEntry;
/**
* Linker generated module map file parser.
*/
class MapFile
{
public:
/** Error code. */
enum ErrorType
{
/** No error. */
ERROR_NONE,
/** File open failed. */
ERROR_OPEN,
/** File reading failed. */
ERROR_READ,
/** Syntax error. */
ERROR_PARSE
};
/** Reads a map file. */
explicit MapFile( const char* filename );
///
~MapFile();
/** Returns preferred load address. */
long loadAddress() const;
/** Returns ith entry from the map file. */
const MapFileEntry& getEntry( int i ) const;
/** Returns ith segment from the map file. */
const MapFileEntry& getSegment( int i ) const;
/** Returns number of segments in the map file. */
int segments() const;
/** Returns number of entries in the map file. */
int entries() const;
/** Returns error code or 0 (ERROR_NONE) if no error. */
ErrorType error() const;
/** Returns line number of last successful read character. */
int line() const;
/**
* Finds entry which contains specified address.
* @return Entry index or -1 if not found.
*/
int findEntry( long addr ) const;
/**
* Returns current module name, with map extension.
* The output buffer is always 0-terminated.
*/
static void getModuleMapFilename( char* buffer, int bufferSize );
private:
class MapFileImpl;
MapFileImpl* m_this;
MapFile( const MapFile& );
MapFile& operator=( const MapFile& );
};
} // dev
#endif // _DEV_MAPFILE_H
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

70
Sources/Plasma/FeatureLib/pfStackTrace/pfMapFileEntry.cpp

@ -1,70 +0,0 @@
#include "pfMapFileEntry.h"
#include <string.h>
//-----------------------------------------------------------------------------
namespace dev
{
MapFileEntry::MapFileEntry()
{
m_sec = 0;
m_addr = 0;
m_len = 0;
m_name[0] = 0;
}
MapFileEntry::MapFileEntry( long section, long offset, long length, const char* name )
{
m_sec = section;
m_addr = offset;
m_len = length;
strncpy( m_name, name, MAX_NAME );
m_name[MAX_NAME] = 0;
}
long MapFileEntry::section() const
{
return m_sec;
}
long MapFileEntry::offset() const
{
return m_addr;
}
long MapFileEntry::length() const
{
return m_len;
}
const char* MapFileEntry::name() const
{
return m_name;
}
bool MapFileEntry::operator<( const MapFileEntry& other ) const
{
if ( m_sec < other.m_sec )
return true;
if ( m_sec > other.m_sec )
return false;
return m_addr < other.m_addr;
}
} // dev
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

64
Sources/Plasma/FeatureLib/pfStackTrace/pfMapFileEntry.h

@ -1,64 +0,0 @@
#ifndef _DEV_MAPFILEENTRY_H
#define _DEV_MAPFILEENTRY_H
namespace dev
{
/** An entry in the map file. */
class MapFileEntry
{
public:
/** Class constants. */
enum Constants
{
/** Maximum number of characters in map file entry name. */
MAX_NAME = 256
};
///
MapFileEntry();
/** Creates an entry with specified section, offset, length and name. */
MapFileEntry( long section, long offset, long length, const char* name );
/** Returns section of the entry. */
long section() const;
/** Returns offset of the entry. */
long offset() const;
/** Returns length of the entry (only defined for segments). */
long length() const;
/** Returns name of the entry. */
const char* name() const;
/** Returns true if the offset of this entry is before the other one. */
bool operator<( const MapFileEntry& other ) const;
private:
long m_sec;
long m_addr;
long m_len;
char m_name[MAX_NAME+1];
};
} // dev
#endif // _DEV_MAPFILEENTRY_H
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

70
Sources/Plasma/FeatureLib/pfStackTrace/pfPrintStackTrace.cpp

@ -1,70 +0,0 @@
#include "pfPrintStackTrace.h"
#include "pfStackTrace.h"
#include "pfMapFile.h"
#include <stdio.h>
#include <string.h>
#pragma optimize( "y", off )
//-----------------------------------------------------------------------------
using namespace dev;
//-----------------------------------------------------------------------------
/**
* Prints stack trace to user defined buffer.
* Always terminates the buffer with 0.
*/
void printStackTrace( char* buffer, int bufferSize, unsigned long stackPtr, unsigned long opPtr )
{
// find out map file name
char modname[500];
MapFile::getModuleMapFilename( modname, sizeof(modname) );
// parse map file
static char buf[5000];
MapFile map( modname );
switch ( map.error() )
{
case MapFile::ERROR_OPEN: sprintf( buf, "Failed to open map file %s\n", modname ); break;
case MapFile::ERROR_READ: sprintf( buf, "Error while reading map file %s(%i)\n", modname, map.line() ); break;
case MapFile::ERROR_PARSE: sprintf( buf, "Parse error in map file %s(%i)\n", modname, map.line() ); break;
default: break;
}
// print stack trace to buffer
if ( !map.error() )
{
MapFile* maps[] = {&map};
StackTrace::printStackTrace( maps, 1, 1, 16, buf, sizeof(buf), stackPtr, opPtr );
}
else
{
// 9.5.2002 mcn - Even if we can't open the map file, still print out the stack trace for later reference
StackTrace::printStackTrace( 0, 0, 1, 16, buf, sizeof(buf), stackPtr, opPtr );
}
// copy to user buffer
if ( bufferSize > 0 )
{
if( buffer[ 0 ] == 0 )
strncpy( buffer, buf, bufferSize );
else
strncat( buffer, buf, bufferSize );
buffer[bufferSize-1] = 0;
}
}
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

26
Sources/Plasma/FeatureLib/pfStackTrace/pfPrintStackTrace.h

@ -1,26 +0,0 @@
#ifndef _PRINTSTACKTRACE_H
#define _PRINTSTACKTRACE_H
/**
* Prints formatted call stack to the user defined buffer,
* always terminating the buffer with 0.
* Uses stack frame to find out the caller function address and
* the map file to find out the function name.
*/
void printStackTrace( char* buffer, int bufferSize, unsigned long stackPtr = 0, unsigned long opPtr = 0 );
#endif // _PRINTSTACKTRACE_H
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

190
Sources/Plasma/FeatureLib/pfStackTrace/pfStackTrace.cpp

@ -1,190 +0,0 @@
#include "pfStackTrace.h"
#include "pfMapFile.h"
#include "pfMapFileEntry.h"
#include <string.h>
#include <stdio.h>
#pragma optimize( "y", off )
//-----------------------------------------------------------------------------
#define MAX_DEPTH 32
//-----------------------------------------------------------------------------
namespace dev
{
static long getCallerFromStack( unsigned long stackPtr, int index )
{
#if /*defined(_DEBUG) && */defined(_MSC_VER) && defined(_M_IX86)
long caller = 0;
__asm
{
mov ebx, stackPtr
mov ecx, index
inc ecx
xor eax, eax
StackTrace_getCaller_next:
mov eax, [ebx+4]
mov ebx, [ebx]
test eax,eax
jz StackTrace_getCallerFromStack_done
dec ecx
jnz StackTrace_getCaller_next
StackTrace_getCallerFromStack_done:
mov caller, eax
}
return caller;
#else
return 0;
#endif
}
static long getCaller( int index )
{
#if /*defined(_DEBUG) && */defined(_MSC_VER) && defined(_M_IX86)
long caller = 0;
__asm
{
mov ebx, ebp
mov ecx, index
inc ecx
xor eax, eax
StackTrace_getCaller_next:
mov eax, [ebx+4]
mov ebx, [ebx]
test eax,eax
jz StackTrace_getCaller_done
dec ecx
jnz StackTrace_getCaller_next
StackTrace_getCaller_done:
mov caller, eax
}
return caller;
#else
return 0;
#endif
}
int StackTrace::printStackTrace( MapFile** map, int maps,
int initLevel, int maxDepth,
char* buffer, int bufferSize, unsigned long stackPtr, unsigned long opPtr )
{
if ( maxDepth > MAX_DEPTH )
maxDepth = MAX_DEPTH;
bool sucks = false;
// list callers
long callersAddr[MAX_DEPTH];
int callers = 0;
int i;
for ( i = initLevel ; i < maxDepth ; ++i )
{
long addr;
if( stackPtr != 0 )
{
if( i == initLevel )
addr = opPtr;
else
addr = getCallerFromStack( stackPtr, i - initLevel - 1 );
}
else
addr = getCaller( i );
callersAddr[callers++] = addr;
// end tracing here if the entry is not in a map file
if( map != 0 )
{
int entry = -1;
for ( int j = 0 ; j < maps ; ++j )
{
entry = map[j]->findEntry( addr );
if ( -1 != entry )
break;
}
if ( -1 == entry )
{
sucks = true;
break;
}
}
}
int needed = 0;
if ( bufferSize > 0 )
*buffer = 0;
sprintf( buffer, "Call stack (%d levels%s):\r\n", callers - initLevel, sucks ? ", truncated" : "" );
needed = strlen( buffer );
// output call stack
for ( i = initLevel ; i < callers ; ++i )
{
long addr = callersAddr[callers-i-1];
// find entry info
int entry = -1;
const MapFile* entryMap = 0;
for ( int j = 0 ; j < maps ; ++j )
{
entry = map[j]->findEntry( addr );
if ( -1 != entry )
{
entryMap = map[j];
break;
}
}
// format entry to tempory buf
char buf[MapFileEntry::MAX_NAME+MAX_DEPTH+20]; // name + margin + hex number
buf[0] = 0;
for ( int k = initLevel-1 ; k < i ; ++k )
strcat( buf, " " );
if ( !entryMap )
sprintf( buf+strlen(buf), "0x%08X\r\n", addr );
else
{
const MapFileEntry &en = entryMap->getEntry( entry );
long entryAddr = entryMap->loadAddress() + (en.section() << 12) + en.offset();
sprintf( buf+strlen(buf), "%s (0x%08X + 0x%08X)\r\n", en.name(), entryAddr, addr - entryAddr );
}
// append temporary buf to output buffer if space left
needed += strlen( buf );
if ( needed < bufferSize )
strcat( buffer, buf );
}
// terminate output buffer
if ( needed < bufferSize )
buffer[needed] = 0;
else if ( bufferSize > 0 )
buffer[bufferSize-1] = 0;
return needed;
}
} // dev
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

49
Sources/Plasma/FeatureLib/pfStackTrace/pfStackTrace.h

@ -1,49 +0,0 @@
#ifndef _DEV_STACKTRACE_H
#define _DEV_STACKTRACE_H
namespace dev
{
class MapFile;
/** Stack tracing utility. */
class StackTrace
{
public:
/**
* Prints formatted call stack to the user buffer.
* Always terminates the user buffer with 0.
*
* @param map Array of pointers to map files.
* @param maps Number of map files.
* @param initLevel Number of functions to skip before starting the tracing.
* @param maxDepth Maximum number of levels in the stack trace.
* @param buffer [out] Output buffer for the formatted stack trace.
* @param bufferSize Size of the output buffer.
* @return Needed buffer size.
*/
static int printStackTrace( MapFile** map, int maps,
int initLevel, int maxDepth,
char* buffer, int bufferSize, unsigned long stackPtr = 0, unsigned long opPtr = 0 );
};
} // dev
#endif // _DEV_STACKTRACE_H
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

261
Sources/Plasma/FeatureLib/pfStackTrace/pfTextFile.cpp

@ -1,261 +0,0 @@
#include "HeadSpin.h"
#include "pfTextFile.h"
#include <stdio.h>
#include <ctype.h>
//-----------------------------------------------------------------------------
namespace dev
{
class TextFile::TextFileImpl
{
public:
TextFile::ErrorType err;
int line;
explicit TextFileImpl( const char* filename )
{
err = TextFile::ERROR_NONE;
line = 1;
m_peeked = false;
m_peekedChar = 0;
m_file = fopen( filename, "rt" );
if ( !m_file )
err = TextFile::ERROR_OPEN;
}
~TextFileImpl()
{
if ( m_file )
{
fclose( m_file );
m_file = 0;
}
}
bool eof() const
{
if ( err )
return true;
return 0 != feof(m_file);
}
bool peekChar( char* ch )
{
if ( err )
return false;
if ( !m_peeked )
{
int c = getc( m_file );
if ( EOF != c )
{
m_peeked = true;
m_peekedChar = (char)c;
}
else
{
if ( ferror(m_file) )
err = TextFile::ERROR_READ;
}
}
if ( m_peeked )
*ch = m_peekedChar;
return m_peeked;
}
bool readChar( char* ch )
{
if ( err )
return false;
bool more = peekChar( ch );
m_peeked = false;
if ( more && *ch == '\n' )
++line;
return more;
}
bool skipWhitespace()
{
if ( err )
return false;
char ch;
while ( peekChar(&ch) )
{
if ( !isspace(ch) )
break;
readChar( &ch );
}
return !eof();
}
bool readString( char* buf, int size )
{
if ( err )
return false;
skipWhitespace();
int count = 0;
char ch;
while ( peekChar(&ch) )
{
if ( isspace(ch) )
break;
if ( count+1 < size )
buf[count++] = ch;
readChar( &ch );
}
if ( size > 0 )
buf[count] = 0;
return count > 0;
}
void skipLine()
{
if ( err )
return;
char ch;
while ( readChar(&ch) )
{
if ( ch == '\n' )
break;
}
}
long readHex()
{
if ( err )
return 0;
skipWhitespace();
// hex must start with alphanumeric character
char ch;
if ( !peekChar(&ch) || !isalnum(ch) )
{
err = TextFile::ERROR_PARSE;
return 0;
}
long x = 0;
while ( peekChar(&ch) )
{
switch ( ch )
{
case '0': x <<= 4; x += 0; break;
case '1': x <<= 4; x += 1; break;
case '2': x <<= 4; x += 2; break;
case '3': x <<= 4; x += 3; break;
case '4': x <<= 4; x += 4; break;
case '5': x <<= 4; x += 5; break;
case '6': x <<= 4; x += 6; break;
case '7': x <<= 4; x += 7; break;
case '8': x <<= 4; x += 8; break;
case '9': x <<= 4; x += 9; break;
case 'a':
case 'A': x <<= 4; x += 0xA; break;
case 'b':
case 'B': x <<= 4; x += 0xB; break;
case 'c':
case 'C': x <<= 4; x += 0xC; break;
case 'd':
case 'D': x <<= 4; x += 0xD; break;
case 'e':
case 'E': x <<= 4; x += 0xE; break;
case 'f':
case 'F': x <<= 4; x += 0xF; break;
default: return x;
}
readChar( &ch );
}
return x;
}
private:
bool m_peeked;
char m_peekedChar;
FILE* m_file;
TextFileImpl( const TextFileImpl& );
TextFileImpl& operator=( const TextFileImpl& );
};
//-----------------------------------------------------------------------------
TextFile::TextFile( const char* filename )
{
m_this = new TextFileImpl( filename );
}
TextFile::~TextFile()
{
delete m_this;
}
bool TextFile::readString( char* buf, int size )
{
return m_this->readString( buf, size );
}
void TextFile::skipLine()
{
m_this->skipLine();
}
long TextFile::readHex()
{
return m_this->readHex();
}
bool TextFile::skipWhitespace()
{
return m_this->skipWhitespace();
}
TextFile::ErrorType TextFile::error() const
{
return m_this->err;
}
bool TextFile::readChar( char* ch )
{
return m_this->readChar( ch );
}
bool TextFile::peekChar( char* ch )
{
return m_this->peekChar( ch );
}
bool TextFile::eof() const
{
return m_this->eof();
}
int TextFile::line() const
{
return m_this->line;
}
} // dev
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

102
Sources/Plasma/FeatureLib/pfStackTrace/pfTextFile.h

@ -1,102 +0,0 @@
#ifndef _DEV_TEXTFILE_H
#define _DEV_TEXTFILE_H
namespace dev
{
/**
* ASCII-7 text file parser. Doesnt throw exceptions.
*/
class TextFile
{
public:
/** Error code. */
enum ErrorType
{
/** No error. */
ERROR_NONE,
/** File open failed. */
ERROR_OPEN,
/** File reading failed. */
ERROR_READ,
/** Syntax error. */
ERROR_PARSE
};
/** Opens a file. */
explicit TextFile( const char* filename );
///
~TextFile();
/**
* Reads a single character.
* @return true if read ok.
*/
bool readChar( char* ch );
/**
* Peeks a single character.
* @return true if peek ok.
*/
bool peekChar( char* ch );
/**
* Reads whitespace delimited string.
* If the string doesnt fit to the buffer then
* the rest of the string is skipped. Buffer
* is always 0-terminated.
* @param buf [out] Pointer to string buffer.
* @param size String buffer size. Must be larger than 0.
* @return false if end-of-file reached before any characters was read.
*/
bool readString( char* buf, int size );
/** Skips the rest of the line. */
void skipLine();
/** Reads hex integer. Skips preceding whitespace. */
long readHex();
/**
* Skips whitespace characters.
* @return false if end-of-file reached.
*/
bool skipWhitespace();
/** Returns true if end-of-file have been reached. */
bool eof() const;
/** Returns error code or 0 (ERROR_NONE) if no error. */
ErrorType error() const;
/** Returns line number of last successful read character. */
int line() const;
private:
class TextFileImpl;
TextFileImpl* m_this;
TextFile( const TextFile& );
TextFile& operator=( const TextFile& );
};
} // dev
#endif // _DEV_TEXTFILE_H
/*
* Copyright (c) 2001 Jani Kajala
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation.
* Jani Kajala makes no representations about the suitability
* of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/

1
Sources/Tools/MaxMain/CMakeLists.txt

@ -126,7 +126,6 @@ target_link_libraries(MaxMain pfLocalizationMgr)
target_link_libraries(MaxMain pfMessage) target_link_libraries(MaxMain pfMessage)
target_link_libraries(MaxMain pfPython) target_link_libraries(MaxMain pfPython)
target_link_libraries(MaxMain pfSecurePreloader) target_link_libraries(MaxMain pfSecurePreloader)
target_link_libraries(MaxMain pfStackTrace)
target_link_libraries(MaxMain pfSurface) target_link_libraries(MaxMain pfSurface)
target_link_libraries(MaxMain plAgeDescription) target_link_libraries(MaxMain plAgeDescription)
target_link_libraries(MaxMain plAgeLoader) target_link_libraries(MaxMain plAgeLoader)

1
Sources/Tools/MaxPlasmaLights/CMakeLists.txt

@ -62,7 +62,6 @@ target_link_libraries(MaxPlasmaLights pfLocalizationMgr)
target_link_libraries(MaxPlasmaLights pfMessage) target_link_libraries(MaxPlasmaLights pfMessage)
target_link_libraries(MaxPlasmaLights pfPython) target_link_libraries(MaxPlasmaLights pfPython)
target_link_libraries(MaxPlasmaLights pfSecurePreloader) target_link_libraries(MaxPlasmaLights pfSecurePreloader)
target_link_libraries(MaxPlasmaLights pfStackTrace)
target_link_libraries(MaxPlasmaLights pfSurface) target_link_libraries(MaxPlasmaLights pfSurface)
target_link_libraries(MaxPlasmaLights plAgeDescription) target_link_libraries(MaxPlasmaLights plAgeDescription)
target_link_libraries(MaxPlasmaLights plAgeLoader) target_link_libraries(MaxPlasmaLights plAgeLoader)

Loading…
Cancel
Save