2013-05-16 08:18:31 +02:00
/*
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* Accelerator Extension
* Copyright ( C ) 2011 Asher Baker ( asherkin ) . All rights reserved .
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* This program is free software ; you can redistribute it and / or modify it under
* the terms of the GNU General Public License , version 3.0 , as published by the
* Free Software Foundation .
*
* 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/>.
*/
# include "extension.h"
# include <IWebternet.h>
# include "MemoryDownloader.h"
2013-05-18 01:46:46 +02:00
# if defined _LINUX
2013-05-16 08:18:31 +02:00
# include "client/linux/handler/exception_handler.h"
2015-10-23 13:10:09 +02:00
# include "common/linux/linux_libc_support.h"
2015-10-22 18:18:17 +02:00
# include "third_party/lss/linux_syscall_support.h"
2013-05-16 08:18:31 +02:00
# include <signal.h>
# include <dirent.h>
# include <unistd.h>
2013-05-18 01:46:46 +02:00
# elif defined _WINDOWS
# define _STDINT // ~.~
# include "client/windows/handler/exception_handler.h"
2014-11-08 02:45:19 +01:00
# else
# error Bad platform.
2013-05-18 01:46:46 +02:00
# endif
2013-05-16 08:18:31 +02:00
Accelerator g_accelerator ;
SMEXT_LINK ( & g_accelerator ) ;
IWebternet * webternet ;
2016-01-13 17:25:03 +01:00
IGameConfig * gameconfig ;
typedef void ( * GetSpew_t ) ( char * buffer , unsigned int length ) ;
GetSpew_t GetSpew ;
char spewBuffer [ 65536 ] ; // Hi.
2013-05-16 08:18:31 +02:00
2016-01-25 16:38:43 +01:00
char crashMap [ 256 ] ;
char crashGamePath [ 512 ] ;
char crashCommandLine [ 1024 ] ;
char crashSourceModPath [ 512 ] ;
char crashGameDirectory [ 256 ] ;
char crashExtensionVersion [ 32 ] ;
2016-01-14 12:18:10 +01:00
char dumpStoragePath [ 512 ] ;
char logPath [ 512 ] ;
2013-05-16 08:18:31 +02:00
google_breakpad : : ExceptionHandler * handler = NULL ;
2016-01-14 17:53:16 +01:00
# if 0
2015-10-22 18:18:17 +02:00
struct PluginInfo {
2015-10-23 13:10:09 +02:00
unsigned int serial ;
PluginStatus status ;
char filename [ 256 ] ;
2015-10-22 18:18:17 +02:00
char name [ 256 ] ;
char author [ 256 ] ;
char description [ 256 ] ;
char version [ 256 ] ;
char url [ 256 ] ;
} ;
unsigned int plugin_count ;
PluginInfo plugins [ 256 ] ;
2016-01-14 17:53:16 +01:00
# endif
2015-10-22 18:18:17 +02:00
2013-05-18 01:46:46 +02:00
# if defined _LINUX
2013-05-16 08:18:31 +02:00
void ( * SignalHandler ) ( int , siginfo_t * , void * ) ;
const int kExceptionSignals [ ] = {
SIGSEGV , SIGABRT , SIGFPE , SIGILL , SIGBUS
} ;
const int kNumHandledSignals = sizeof ( kExceptionSignals ) / sizeof ( kExceptionSignals [ 0 ] ) ;
static bool dumpCallback ( const google_breakpad : : MinidumpDescriptor & descriptor , void * context , bool succeeded )
{
2015-10-22 18:18:17 +02:00
//printf("Wrote minidump to: %s\n", descriptor.path());
2016-01-13 17:25:03 +01:00
if ( succeeded ) {
sys_write ( STDOUT_FILENO , " Wrote minidump to: " , 19 ) ;
} else {
sys_write ( STDOUT_FILENO , " Failed to write minidump to: " , 29 ) ;
}
2015-10-23 13:10:09 +02:00
sys_write ( STDOUT_FILENO , descriptor . path ( ) , my_strlen ( descriptor . path ( ) ) ) ;
2015-10-22 18:18:17 +02:00
sys_write ( STDOUT_FILENO , " \n " , 1 ) ;
2016-01-13 17:25:03 +01:00
if ( ! succeeded ) {
return succeeded ;
}
2016-01-14 12:18:10 +01:00
my_strlcpy ( dumpStoragePath , descriptor . path ( ) , sizeof ( dumpStoragePath ) ) ;
my_strlcat ( dumpStoragePath , " .txt " , sizeof ( dumpStoragePath ) ) ;
2015-10-22 18:18:17 +02:00
2016-01-14 12:18:10 +01:00
int extra = sys_open ( dumpStoragePath , O_WRONLY | O_CREAT , S_IRUSR | S_IWUSR ) ;
2015-10-22 18:18:17 +02:00
if ( extra = = - 1 ) {
sys_write ( STDOUT_FILENO , " Failed to open metadata file! \n " , 30 ) ;
return succeeded ;
}
2016-01-25 16:38:43 +01:00
sys_write ( extra , " -------- CONFIG BEGIN -------- " , 30 ) ;
sys_write ( extra , " \n Map= " , 5 ) ;
sys_write ( extra , crashMap , my_strlen ( crashMap ) ) ;
sys_write ( extra , " \n GamePath= " , 10 ) ;
sys_write ( extra , crashGamePath , my_strlen ( crashGamePath ) ) ;
sys_write ( extra , " \n CommandLine= " , 13 ) ;
sys_write ( extra , crashCommandLine , my_strlen ( crashCommandLine ) ) ;
sys_write ( extra , " \n SourceModPath= " , 15 ) ;
sys_write ( extra , crashSourceModPath , my_strlen ( crashSourceModPath ) ) ;
sys_write ( extra , " \n GameDirectory= " , 15 ) ;
sys_write ( extra , crashGameDirectory , my_strlen ( crashGameDirectory ) ) ;
sys_write ( extra , " \n ExtensionVersion= " , 18 ) ;
sys_write ( extra , crashExtensionVersion , my_strlen ( crashExtensionVersion ) ) ;
sys_write ( extra , " \n -------- CONFIG END -------- \n " , 30 ) ;
2016-01-13 17:25:03 +01:00
if ( GetSpew ) {
GetSpew ( spewBuffer , sizeof ( spewBuffer ) ) ;
sys_write ( extra , " -------- CONSOLE HISTORY BEGIN -------- \n " , 40 ) ;
sys_write ( extra , spewBuffer , my_strlen ( spewBuffer ) ) ;
sys_write ( extra , " -------- CONSOLE HISTORY END -------- \n " , 38 ) ;
}
2016-01-14 17:53:16 +01:00
#if 0
2015-10-23 13:10:09 +02:00
char pis [ 64 ] ;
char pds [ 32 ] ;
2015-10-22 18:18:17 +02:00
for ( unsigned i = 0 ; i < plugin_count ; + + i ) {
PluginInfo * p = & plugins [ i ] ;
if ( p - > serial = = 0 ) continue ;
2015-10-23 13:10:09 +02:00
my_uitos ( pds , i , my_uint_len ( i ) ) ;
pds [ my_uint_len ( i ) ] = ' \0 ' ;
my_strlcpy ( pis , " plugin[ " , sizeof ( pis ) ) ;
my_strlcat ( pis , pds , sizeof ( pis ) ) ;
my_strlcat ( pis , " ]. " , sizeof ( pis ) ) ;
sys_write ( extra , pis , my_strlen ( pis ) ) ;
sys_write ( extra , " filename= " , 9 ) ;
sys_write ( extra , p - > filename , my_strlen ( p - > filename ) ) ;
2015-10-22 18:18:17 +02:00
sys_write ( extra , " \n " , 1 ) ;
2015-10-23 13:10:09 +02:00
sys_write ( extra , pis , my_strlen ( pis ) ) ;
sys_write ( extra , " name= " , 5 ) ;
sys_write ( extra , p - > name , my_strlen ( p - > name ) ) ;
2015-10-22 18:18:17 +02:00
sys_write ( extra , " \n " , 1 ) ;
2015-10-23 13:10:09 +02:00
sys_write ( extra , pis , my_strlen ( pis ) ) ;
sys_write ( extra , " author= " , 7 ) ;
sys_write ( extra , p - > author , my_strlen ( p - > author ) ) ;
2015-10-22 18:18:17 +02:00
sys_write ( extra , " \n " , 1 ) ;
2015-10-23 13:10:09 +02:00
sys_write ( extra , pis , my_strlen ( pis ) ) ;
sys_write ( extra , " description= " , 12 ) ;
sys_write ( extra , p - > description , my_strlen ( p - > description ) ) ;
2015-10-22 18:18:17 +02:00
sys_write ( extra , " \n " , 1 ) ;
2015-10-23 13:10:09 +02:00
sys_write ( extra , pis , my_strlen ( pis ) ) ;
sys_write ( extra , " version= " , 8 ) ;
sys_write ( extra , p - > version , my_strlen ( p - > version ) ) ;
2015-10-22 18:18:17 +02:00
sys_write ( extra , " \n " , 1 ) ;
2015-10-23 13:10:09 +02:00
sys_write ( extra , pis , my_strlen ( pis ) ) ;
sys_write ( extra , " url= " , 4 ) ;
sys_write ( extra , p - > url , my_strlen ( p - > url ) ) ;
2015-10-22 18:18:17 +02:00
sys_write ( extra , " \n " , 1 ) ;
}
2016-01-14 17:53:16 +01:00
# endif
2015-10-22 18:18:17 +02:00
sys_close ( extra ) ;
2013-05-16 08:18:31 +02:00
return succeeded ;
}
void OnGameFrame ( bool simulating )
{
bool weHaveBeenFuckedOver = false ;
struct sigaction oact ;
for ( int i = 0 ; i < kNumHandledSignals ; + + i ) {
sigaction ( kExceptionSignals [ i ] , NULL , & oact ) ;
if ( oact . sa_sigaction ! = SignalHandler ) {
weHaveBeenFuckedOver = true ;
break ;
}
}
if ( ! weHaveBeenFuckedOver ) {
return ;
}
struct sigaction act ;
memset ( & act , 0 , sizeof ( act ) ) ;
sigemptyset ( & act . sa_mask ) ;
for ( int i = 0 ; i < kNumHandledSignals ; + + i ) {
sigaddset ( & act . sa_mask , kExceptionSignals [ i ] ) ;
}
act . sa_sigaction = SignalHandler ;
act . sa_flags = SA_ONSTACK | SA_SIGINFO ;
for ( int i = 0 ; i < kNumHandledSignals ; + + i ) {
sigaction ( kExceptionSignals [ i ] , & act , NULL ) ;
}
}
2013-05-18 01:46:46 +02:00
# elif defined _WINDOWS
2014-11-08 03:00:40 +01:00
void * vectoredHandler = NULL ;
2013-05-18 01:46:46 +02:00
LONG CALLBACK BreakpadVectoredHandler ( _In_ PEXCEPTION_POINTERS ExceptionInfo )
{
2013-05-19 04:28:09 +02:00
switch ( ExceptionInfo - > ExceptionRecord - > ExceptionCode )
2013-05-18 01:46:46 +02:00
{
2013-05-19 04:28:09 +02:00
case EXCEPTION_ACCESS_VIOLATION :
2015-02-14 04:36:17 +01:00
case EXCEPTION_INVALID_HANDLE :
2013-05-19 04:28:09 +02:00
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED :
case EXCEPTION_DATATYPE_MISALIGNMENT :
case EXCEPTION_ILLEGAL_INSTRUCTION :
2014-10-31 23:42:09 +01:00
case EXCEPTION_INT_DIVIDE_BY_ZERO :
2013-05-19 04:28:09 +02:00
case EXCEPTION_STACK_OVERFLOW :
2015-02-14 16:58:07 +01:00
case 0xC0000409 : // STATUS_STACK_BUFFER_OVERRUN
case 0xC0000374 : // STATUS_HEAP_CORRUPTION
2013-05-19 04:28:09 +02:00
break ;
2014-10-31 23:42:09 +01:00
case 0 : // Valve use this for Sys_Error.
if ( ( ExceptionInfo - > ExceptionRecord - > ExceptionFlags & EXCEPTION_NONCONTINUABLE ) = = 0 )
return EXCEPTION_CONTINUE_SEARCH ;
break ;
2013-05-19 04:28:09 +02:00
default :
return EXCEPTION_CONTINUE_SEARCH ;
2013-05-18 01:46:46 +02:00
}
if ( handler - > WriteMinidumpForException ( ExceptionInfo ) )
{
// Stop the handler thread from deadlocking us.
delete handler ;
// Stop Valve's handler being called.
ExceptionInfo - > ExceptionRecord - > ExceptionCode = EXCEPTION_BREAKPOINT ;
return EXCEPTION_EXECUTE_HANDLER ;
} else {
return EXCEPTION_CONTINUE_SEARCH ;
}
}
static bool dumpCallback ( const wchar_t * dump_path ,
const wchar_t * minidump_id ,
void * context ,
EXCEPTION_POINTERS * exinfo ,
MDRawAssertionInfo * assertion ,
bool succeeded )
{
2016-01-13 17:49:19 +01:00
if ( ! succeeded ) {
printf ( " Failed to write minidump to: %ls \\ %ls.dmp \n " , dump_path , minidump_id ) ;
return succeeded ;
}
2013-05-18 01:46:46 +02:00
printf ( " Wrote minidump to: %ls \\ %ls.dmp \n " , dump_path , minidump_id ) ;
2016-01-13 17:49:19 +01:00
2016-01-14 15:18:01 +01:00
sprintf ( dumpStoragePath , " %ls \\ %ls.dmp.txt " , dump_path , minidump_id ) ;
2016-01-13 17:49:19 +01:00
2016-01-14 14:10:57 +01:00
FILE * extra = fopen ( dumpStoragePath , " wb " ) ;
2016-01-13 17:49:19 +01:00
if ( ! extra ) {
printf ( " Failed to open metadata file! \n " ) ;
return succeeded ;
}
if ( GetSpew ) {
GetSpew ( spewBuffer , sizeof ( spewBuffer ) ) ;
fprintf ( extra , " -------- CONSOLE HISTORY BEGIN -------- \n %s-------- CONSOLE HISTORY END -------- \n " , spewBuffer ) ;
}
fclose ( extra ) ;
2013-05-18 01:46:46 +02:00
return succeeded ;
}
2014-11-08 02:45:19 +01:00
# else
# error Bad platform.
2013-05-18 01:46:46 +02:00
# endif
2013-05-16 08:18:31 +02:00
2016-01-14 12:18:10 +01:00
bool UploadAndDeleteCrashDump ( const char * path , char * response , int maxlen )
2013-05-16 08:18:31 +02:00
{
IWebForm * form = webternet - > CreateForm ( ) ;
2016-01-20 18:59:41 +01:00
const char * minidumpAccount = g_pSM - > GetCoreConfigValue ( " MinidumpAccount " ) ;
if ( minidumpAccount ) form - > AddString ( " UserID " , minidumpAccount ) ;
2014-11-08 03:04:17 +01:00
form - > AddString ( " GameDirectory " , g_pSM - > GetGameFolderName ( ) ) ;
2014-11-08 02:50:04 +01:00
form - > AddString ( " ExtensionVersion " , SMEXT_CONF_VERSION ) ;
2013-05-16 08:18:31 +02:00
form - > AddFile ( " upload_file_minidump " , path ) ;
2015-10-22 18:18:17 +02:00
char metapath [ 512 ] ;
2016-01-14 12:18:10 +01:00
g_pSM - > Format ( metapath , sizeof ( metapath ) , " %s.txt " , path ) ;
2015-10-22 18:18:17 +02:00
if ( libsys - > PathExists ( metapath ) ) {
form - > AddFile ( " upload_file_metadata " , metapath ) ;
}
2013-05-16 08:18:31 +02:00
MemoryDownloader data ;
IWebTransfer * xfer = webternet - > CreateSession ( ) ;
xfer - > SetFailOnHTTPError ( true ) ;
2016-03-15 13:06:50 +01:00
const char * minidumpUrl = g_pSM - > GetCoreConfigValue ( " MinidumpUrl " ) ;
if ( ! minidumpUrl ) minidumpUrl = " http://crash.limetech.org/submit " ;
bool uploaded = xfer - > PostAndDownload ( minidumpUrl , form , & data , NULL ) ;
2016-01-14 12:18:10 +01:00
if ( response ) {
if ( uploaded ) {
2016-03-15 13:06:50 +01:00
int responseSize = data . GetSize ( ) ;
if ( responseSize > = maxlen ) responseSize = maxlen - 1 ;
strncpy ( response , data . GetBuffer ( ) , responseSize ) ;
response [ responseSize ] = ' \0 ' ;
2016-01-14 12:18:10 +01:00
} else {
g_pSM - > Format ( response , maxlen , " %s (%d) " , xfer - > LastErrorMessage ( ) , xfer - > LastErrorCode ( ) ) ;
}
2013-05-16 08:18:31 +02:00
}
2015-10-23 13:11:16 +02:00
if ( libsys - > PathExists ( metapath ) ) {
unlink ( metapath ) ;
}
2016-01-14 12:18:10 +01:00
unlink ( path ) ;
return uploaded ;
2013-05-16 08:18:31 +02:00
}
2016-01-14 12:18:10 +01:00
class UploadThread : public IThread
2013-05-16 08:18:31 +02:00
{
2016-01-14 12:18:10 +01:00
void RunThread ( IThreadHandle * pHandle ) {
rootconsole - > ConsolePrint ( " Accelerator upload thread started. " ) ;
2016-01-13 18:37:20 +01:00
2016-01-14 12:18:10 +01:00
FILE * log = fopen ( logPath , " a " ) ;
if ( ! log ) {
g_pSM - > LogError ( myself , " Failed to open Accelerator log file: %s " , logPath ) ;
}
2013-05-16 08:18:31 +02:00
2016-01-14 12:18:10 +01:00
IDirectory * dumps = libsys - > OpenDirectory ( dumpStoragePath ) ;
2013-05-16 08:18:31 +02:00
2016-01-14 12:18:10 +01:00
int count = 0 ;
int failed = 0 ;
char path [ 512 ] ;
char response [ 512 ] ;
while ( dumps - > MoreFiles ( ) ) {
if ( ! dumps - > IsEntryFile ( ) ) {
dumps - > NextEntry ( ) ;
continue ;
}
2015-10-22 18:18:17 +02:00
2016-01-14 12:18:10 +01:00
const char * name = dumps - > GetEntryName ( ) ;
int namelen = strlen ( name ) ;
if ( namelen < 4 | | strcmp ( & name [ namelen - 4 ] , " .dmp " ) ! = 0 ) {
dumps - > NextEntry ( ) ;
continue ;
}
g_pSM - > Format ( path , sizeof ( path ) , " %s/%s " , dumpStoragePath , name ) ;
bool uploaded = UploadAndDeleteCrashDump ( path , response , sizeof ( response ) ) ;
if ( uploaded ) {
count + + ;
g_pSM - > LogError ( myself , " Accelerator uploaded crash dump: %s " , response ) ;
if ( log ) fprintf ( log , " Uploaded crash dump: %s \n " , response ) ;
} else {
failed + + ;
g_pSM - > LogError ( myself , " Accelerator failed to upload crash dump: %s " , response ) ;
if ( log ) fprintf ( log , " Failed to upload crash dump: %s \n " , response ) ;
}
2015-10-22 18:18:17 +02:00
dumps - > NextEntry ( ) ;
}
2016-01-14 12:18:10 +01:00
libsys - > CloseDirectory ( dumps ) ;
if ( log ) {
fclose ( log ) ;
2014-11-08 02:45:19 +01:00
}
2013-05-18 01:46:46 +02:00
2016-01-14 12:18:10 +01:00
rootconsole - > ConsolePrint ( " Accelerator upload thread finished. (%d uploaded, %d failed) " , count , failed ) ;
2013-05-16 08:18:31 +02:00
}
2016-01-14 12:18:10 +01:00
void OnTerminate ( IThreadHandle * pHandle , bool cancel ) {
rootconsole - > ConsolePrint ( " Accelerator upload thread terminated. (canceled = %s) " , ( cancel ? " true " : " false " ) ) ;
2014-11-08 02:45:19 +01:00
}
2013-05-16 08:18:31 +02:00
2016-01-13 18:37:20 +01:00
} uploadThread ;
2013-05-16 08:18:31 +02:00
bool Accelerator : : SDK_OnLoad ( char * error , size_t maxlength , bool late )
{
sharesys - > AddDependency ( myself , " webternet.ext " , true , true ) ;
SM_GET_IFACE ( WEBTERNET , webternet ) ;
2016-01-14 12:18:10 +01:00
g_pSM - > BuildPath ( Path_SM , dumpStoragePath , sizeof ( dumpStoragePath ) , " data/dumps " ) ;
2013-05-16 08:18:31 +02:00
2016-01-14 12:18:10 +01:00
if ( ! libsys - > IsPathDirectory ( dumpStoragePath ) )
2013-05-17 15:48:52 +02:00
{
2016-01-14 12:18:10 +01:00
if ( ! libsys - > CreateFolder ( dumpStoragePath ) )
2013-05-17 15:48:52 +02:00
{
if ( error )
2016-01-14 12:18:10 +01:00
g_pSM - > Format ( error , maxlength , " %s didn't exist and we couldn't create it :( " , dumpStoragePath ) ;
2013-05-17 15:48:52 +02:00
return false ;
}
}
2016-01-14 12:18:10 +01:00
g_pSM - > BuildPath ( Path_SM , logPath , sizeof ( logPath ) , " logs/accelerator.log " ) ;
2016-01-13 18:37:20 +01:00
threader - > MakeThread ( & uploadThread ) ;
2016-05-18 10:11:04 +02:00
char gameconfigError [ 256 ] ;
if ( ! gameconfs - > LoadGameConfigFile ( " accelerator.games " , & gameconfig , gameconfigError , sizeof ( gameconfigError ) ) ) {
smutils - > LogError ( myself , " WARNING: Failed to load gamedata file, console output and command line will not be included in crash reports: %s " , gameconfigError ) ;
} else if ( ! gameconfig - > GetMemSig ( " GetSpew " , ( void * * ) & GetSpew ) ) {
2016-01-13 17:25:03 +01:00
smutils - > LogError ( myself , " WARNING: GetSpew not found in gamedata, console output will not be included in crash reports. " ) ;
} else if ( ! GetSpew ) {
smutils - > LogError ( myself , " WARNING: Sigscan for GetSpew failed, console output will not be included in crash reports. " ) ;
}
2013-05-18 01:46:46 +02:00
# if defined _LINUX
2016-01-14 12:18:10 +01:00
google_breakpad : : MinidumpDescriptor descriptor ( dumpStoragePath ) ;
2013-05-16 08:18:31 +02:00
handler = new google_breakpad : : ExceptionHandler ( descriptor , NULL , dumpCallback , NULL , true , - 1 ) ;
struct sigaction oact ;
sigaction ( SIGSEGV , NULL , & oact ) ;
SignalHandler = oact . sa_sigaction ;
2013-05-18 01:46:46 +02:00
2013-05-16 08:18:31 +02:00
g_pSM - > AddGameFrameHook ( OnGameFrame ) ;
2013-05-18 01:46:46 +02:00
# elif defined _WINDOWS
2016-01-14 12:18:10 +01:00
wchar_t * buf = new wchar_t [ sizeof ( dumpStoragePath ) ] ;
size_t num_chars = mbstowcs ( buf , dumpStoragePath , sizeof ( dumpStoragePath ) ) ;
2013-05-18 01:46:46 +02:00
handler = new google_breakpad : : ExceptionHandler ( std : : wstring ( buf , num_chars ) , NULL , dumpCallback , NULL , google_breakpad : : ExceptionHandler : : HANDLER_ALL ) ;
2014-11-08 03:00:40 +01:00
vectoredHandler = AddVectoredExceptionHandler ( 0 , BreakpadVectoredHandler ) ;
2013-05-18 01:46:46 +02:00
delete buf ;
2014-11-08 02:45:19 +01:00
# else
# error Bad platform.
2013-05-18 01:46:46 +02:00
# endif
2016-01-14 17:53:16 +01:00
#if 0
2015-10-22 18:18:17 +02:00
IPluginIterator * i = plsys - > GetPluginIterator ( ) ;
while ( i - > MorePlugins ( ) ) {
IPlugin * p = i - > GetPlugin ( ) ;
const sm_plugininfo_t * pmi = p - > GetPublicInfo ( ) ;
PluginInfo * pi = & plugins [ plugin_count + + ] ;
pi - > serial = p - > GetSerial ( ) ;
pi - > status = p - > GetStatus ( ) ;
strncpy ( pi - > filename , p - > GetFilename ( ) , sizeof ( pi - > filename ) - 1 ) ;
strncpy ( pi - > name , pmi - > name , sizeof ( pi - > name ) - 1 ) ;
strncpy ( pi - > author , pmi - > author , sizeof ( pi - > author ) - 1 ) ;
strncpy ( pi - > description , pmi - > description , sizeof ( pi - > description ) - 1 ) ;
strncpy ( pi - > version , pmi - > version , sizeof ( pi - > version ) - 1 ) ;
strncpy ( pi - > url , pmi - > url , sizeof ( pi - > url ) - 1 ) ;
i - > NextPlugin ( ) ;
}
delete i ;
2016-01-14 17:53:16 +01:00
# endif
2015-10-22 18:18:17 +02:00
2016-01-25 16:38:43 +01:00
if ( late ) {
this - > OnCoreMapStart ( NULL , 0 , 0 ) ;
}
2013-05-16 08:18:31 +02:00
return true ;
}
void Accelerator : : SDK_OnUnload ( )
{
2013-05-18 01:46:46 +02:00
# if defined _LINUX
2013-05-16 08:18:31 +02:00
g_pSM - > RemoveGameFrameHook ( OnGameFrame ) ;
2013-05-18 01:46:46 +02:00
# elif defined _WINDOWS
2014-11-08 03:00:40 +01:00
if ( vectoredHandler ) {
RemoveVectoredExceptionHandler ( vectoredHandler ) ;
}
2014-11-08 02:45:19 +01:00
# else
# error Bad platform.
2013-05-18 01:46:46 +02:00
# endif
delete handler ;
2013-05-16 08:18:31 +02:00
}
2016-01-25 16:38:43 +01:00
class VFuncEmptyClass { } ;
const char * GetCmdLine ( )
{
static int getCmdLineOffset = 0 ;
if ( getCmdLineOffset = = 0 ) {
2016-05-18 10:11:04 +02:00
if ( ! gameconfig | | ! gameconfig - > GetOffset ( " GetCmdLine " , & getCmdLineOffset ) ) {
2016-01-25 16:38:43 +01:00
return " " ;
}
if ( getCmdLineOffset = = 0 ) {
return " " ;
}
}
void * cmdline = gamehelpers - > GetValveCommandLine ( ) ;
void * * vtable = * ( void * * * ) cmdline ;
void * vfunc = vtable [ getCmdLineOffset ] ;
union {
const char * ( VFuncEmptyClass : : * mfpnew ) ( ) ;
# ifndef WIN32
struct {
void * addr ;
intptr_t adjustor ;
} s ;
} u ;
u . s . addr = vfunc ;
u . s . adjustor = 0 ;
# else
void * addr ;
} u ;
u . addr = vfunc ;
# endif
return ( const char * ) ( reinterpret_cast < VFuncEmptyClass * > ( cmdline ) - > * u . mfpnew ) ( ) ;
}
void Accelerator : : OnCoreMapStart ( edict_t * pEdictList , int edictCount , int clientMax )
{
strncpy ( crashMap , gamehelpers - > GetCurrentMap ( ) , sizeof ( crashMap ) - 1 ) ;
strncpy ( crashGamePath , g_pSM - > GetGamePath ( ) , sizeof ( crashGamePath ) - 1 ) ;
strncpy ( crashCommandLine , GetCmdLine ( ) , sizeof ( crashCommandLine ) - 1 ) ;
strncpy ( crashSourceModPath , g_pSM - > GetSourceModPath ( ) , sizeof ( crashSourceModPath ) - 1 ) ;
strncpy ( crashGameDirectory , g_pSM - > GetGameFolderName ( ) , sizeof ( crashGameDirectory ) - 1 ) ;
strncpy ( crashExtensionVersion , SMEXT_CONF_VERSION , sizeof ( crashExtensionVersion ) - 1 ) ;
}