2016-07-12 12:33:25 -04:00
# include "STDInclude.hpp"
namespace Components
{
std : : mutex Logger : : MessageMutex ;
std : : vector < std : : string > Logger : : MessageQueue ;
2016-09-01 15:52:00 -04:00
std : : vector < Game : : netadr_t > Logger : : addresses ;
std : : vector < Game : : netadr_t > Logger : : gaddresses ;
static char * writeFile ;
static char * writeFolder ;
//static DWORD fsBuildOSPathForThreadHookLoc = 0x642139;
DWORD fsBuildOSPathForThreadHookLocRet = 0x64213F ;
2016-09-02 16:28:51 -04:00
Game : : dvar_t * iw4m_onelog ;
2016-09-01 15:52:00 -04:00
2016-07-12 12:33:25 -04:00
void ( * Logger : : PipeCallback ) ( std : : string ) = nullptr ;
2016-09-02 16:28:51 -04:00
void ( * Logger : : GLogCallback ) ( std : : string ) = nullptr ;
2016-07-12 12:33:25 -04:00
bool Logger : : IsConsoleReady ( )
{
2016-07-22 06:12:11 -04:00
return ( IsWindow ( * reinterpret_cast < HWND * > ( 0x64A3288 ) ) ! = FALSE | | ( Dedicated : : IsEnabled ( ) & & ! Flags : : HasFlag ( " console " ) ) ) ;
2016-07-12 12:33:25 -04:00
}
void Logger : : Print ( const char * message , . . . )
{
return Logger : : MessagePrint ( 0 , Logger : : Format ( & message ) ) ;
}
void Logger : : Print ( int channel , const char * message , . . . )
{
return Logger : : MessagePrint ( channel , Logger : : Format ( & message ) ) ;
}
void Logger : : MessagePrint ( int channel , std : : string message )
{
if ( Flags : : HasFlag ( " stdout " ) | | Loader : : PerformingUnitTests ( ) )
{
printf ( " %s " , message . data ( ) ) ;
2016-09-01 15:52:00 -04:00
/*if (Logger::addresses.size()) {
for ( size_t i = 0 ; i < Logger : : addresses . size ( ) ; i + + ) {
const char * toSend = Utils : : String : : VA ( " %i %s " , channel , message ) ;
Network : : Send ( Logger : : addresses [ i ] , toSend ) ;
}
} */
2016-07-12 12:33:25 -04:00
fflush ( stdout ) ;
2016-09-02 16:28:51 -04:00
2016-07-12 12:33:25 -04:00
return ;
}
if ( ! Logger : : IsConsoleReady ( ) )
{
OutputDebugStringA ( message . data ( ) ) ;
2016-09-01 15:52:00 -04:00
/*if (Logger::addresses.size()) {
for ( size_t i = 0 ; i < Logger : : addresses . size ( ) ; i + + ) {
const char * toSend = Utils : : String : : VA ( " %i %s " , channel , message ) ;
Network : : Send ( Logger : : addresses [ i ] , toSend ) ;
}
} */
2016-07-12 12:33:25 -04:00
}
if ( ! Game : : Sys_IsMainThread ( ) )
{
Logger : : EnqueueMessage ( message ) ;
2016-09-01 15:52:00 -04:00
/*if (Logger::addresses.size()) {
for ( size_t i = 0 ; i < Logger : : addresses . size ( ) ; i + + ) {
const char * toSend = Utils : : String : : VA ( " %i %s " , channel , message ) ;
Network : : Send ( Logger : : addresses [ i ] , toSend ) ;
}
} */
2016-07-12 12:33:25 -04:00
}
else
{
2016-09-01 15:52:00 -04:00
/*if (Logger::addresses.size()) {
for ( size_t i = 0 ; i < Logger : : addresses . size ( ) ; i + + ) {
const char * toSend = Utils : : String : : VA ( " %i %s " , channel , message ) ;
Network : : Send ( Logger : : addresses [ i ] , toSend ) ;
}
} */
2016-08-17 20:18:45 -04:00
Game : : Com_PrintMessage ( channel , message . data ( ) , 0 ) ;
2016-07-12 12:33:25 -04:00
}
}
void Logger : : ErrorPrint ( int error , std : : string message )
{
return Game : : Com_Error ( error , " %s " , message . data ( ) ) ;
}
void Logger : : Error ( int error , const char * message , . . . )
{
return Logger : : ErrorPrint ( error , Logger : : Format ( & message ) ) ;
}
void Logger : : Error ( const char * message , . . . )
{
return Logger : : ErrorPrint ( 0 , Logger : : Format ( & message ) ) ;
}
void Logger : : SoftError ( const char * message , . . . )
{
return Logger : : ErrorPrint ( 2 , Logger : : Format ( & message ) ) ;
}
std : : string Logger : : Format ( const char * * message )
{
char buffer [ 0x1000 ] = { 0 } ;
va_list ap = reinterpret_cast < char * > ( const_cast < char * * > ( & message [ 1 ] ) ) ;
//va_start(ap, *message);
_vsnprintf_s ( buffer , sizeof ( buffer ) , * message , ap ) ;
va_end ( ap ) ;
return buffer ;
}
void Logger : : Frame ( )
{
Logger : : MessageMutex . lock ( ) ;
for ( unsigned int i = 0 ; i < Logger : : MessageQueue . size ( ) ; + + i )
{
2016-09-02 16:28:51 -04:00
2016-07-12 12:33:25 -04:00
Game : : Com_PrintMessage ( 0 , Logger : : MessageQueue [ i ] . data ( ) , 0 ) ;
if ( ! Logger : : IsConsoleReady ( ) )
{
OutputDebugStringA ( Logger : : MessageQueue [ i ] . data ( ) ) ;
}
}
Logger : : MessageQueue . clear ( ) ;
Logger : : MessageMutex . unlock ( ) ;
}
void Logger : : PipeOutput ( void ( * callback ) ( std : : string ) )
{
Logger : : PipeCallback = callback ;
}
2016-09-02 16:28:51 -04:00
void Logger : : GLogOutput ( void ( * callback ) ( std : : string ) )
{
Logger : : GLogCallback = callback ;
}
2016-07-12 12:33:25 -04:00
void Logger : : PrintMessagePipe ( const char * data )
{
if ( Logger : : PipeCallback )
{
Logger : : PipeCallback ( data ) ;
}
}
2016-09-02 16:28:51 -04:00
void Logger : : GLogMessagePipe ( const char * data )
{
if ( Logger : : GLogCallback )
{
Logger : : GLogCallback ( data ) ;
}
}
2016-08-07 19:57:00 -04:00
__declspec ( naked ) void Logger : : PrintMessageStub ( )
2016-07-12 12:33:25 -04:00
{
__asm
{
mov eax , Logger : : PipeCallback
test eax , eax
jz returnPrint
2016-09-01 15:52:00 -04:00
push [ esp + 8 h ]
2016-07-12 12:33:25 -04:00
call Logger : : PrintMessagePipe
add esp , 4 h
2016-09-02 16:28:51 -04:00
2016-07-12 12:33:25 -04:00
2016-09-01 15:52:00 -04:00
returnPrint :
2016-07-12 12:33:25 -04:00
push esi
2016-09-01 15:52:00 -04:00
mov esi , [ esp + 0 Ch ]
2016-07-12 12:33:25 -04:00
2016-09-01 15:52:00 -04:00
mov eax , 4 AA835h
jmp eax
2016-07-12 12:33:25 -04:00
}
}
2016-09-02 16:28:51 -04:00
__declspec ( naked ) void Logger : : GLogPrintfHookStub ( ) {
_asm
{
mov eax , Logger : : GLogCallback
test eax , eax
jz returnPrint
call Logger : : GLogMessagePipe
returnPrint :
mov eax , 4576 C0h
jmp eax
}
}
2016-07-12 12:33:25 -04:00
void Logger : : EnqueueMessage ( std : : string message )
{
Logger : : MessageMutex . lock ( ) ;
Logger : : MessageQueue . push_back ( message ) ;
Logger : : MessageMutex . unlock ( ) ;
}
2016-09-01 15:54:46 -04:00
void Logger : : PipeOutputStub ( std : : string message )
2016-09-01 15:52:00 -04:00
{
2016-09-02 16:28:51 -04:00
2016-09-01 15:52:00 -04:00
if ( Logger : : addresses . size ( ) ) {
for ( size_t i = 0 ; i < Logger : : addresses . size ( ) ; i + + ) {
const char * toSend = Utils : : String : : VA ( " %i %s " , 0 , message ) ;
Network : : Send ( Logger : : addresses [ i ] , toSend ) ;
}
}
//Logger::PrintMessagePipe(message.c_str());
2016-09-02 16:28:51 -04:00
2016-09-01 15:52:00 -04:00
}
2016-09-02 16:28:51 -04:00
void Logger : : GPipeOutputStub ( std : : string message )
{
OutputDebugStringA ( " Worked " ) ;
if ( Logger : : gaddresses . size ( ) ) {
for ( size_t i = 0 ; i < Logger : : gaddresses . size ( ) ; i + + ) {
const char * toSend = Utils : : String : : VA ( " %s " , message ) ;
Network : : Send ( Logger : : gaddresses [ i ] , toSend ) ;
}
}
//Logger::PrintMessagePipe(message.c_str());
2016-09-01 15:52:00 -04:00
2016-09-02 16:28:51 -04:00
}
2016-09-01 15:52:00 -04:00
2016-07-12 12:33:25 -04:00
Logger : : Logger ( )
{
2016-09-01 15:54:46 -04:00
Logger : : PipeOutput ( & PipeOutputStub ) ;
2016-09-02 16:28:51 -04:00
Logger : : GLogOutput ( & GPipeOutputStub ) ;
2016-07-12 12:33:25 -04:00
2016-09-02 16:28:51 -04:00
//Logger::PipeOutput(nullptr);
//Logger::GLogOutput(nullptr);
2016-07-12 12:33:25 -04:00
QuickPatch : : OnFrame ( Logger : : Frame ) ;
Utils : : Hook ( Game : : Com_PrintMessage , Logger : : PrintMessageStub , HOOK_JUMP ) . Install ( ) - > Quick ( ) ;
2016-09-02 16:28:51 -04:00
Utils : : Hook ( Logger : : glogprintfHookLoc , Logger : : GLogPrintfHookStub , HOOK_CALL ) . Install ( ) - > Quick ( ) ;
2016-09-01 15:52:00 -04:00
//Logging over network stuff
Game : : Cmd_AddCommand ( " log_add " , Game : : Cbuf_AddServerText , & sv_log_add , 0 ) ;
Game : : Cmd_AddServerCommand ( " log_add " , Logger : : SV_Log_Add_f , & sv_log_add2 ) ;
Game : : Cmd_AddCommand ( " log_del " , Game : : Cbuf_AddServerText , & sv_log_del , 0 ) ;
Game : : Cmd_AddServerCommand ( " log_del " , Logger : : SV_Log_Del_f , & sv_log_del2 ) ;
Game : : Cmd_AddCommand ( " log_list " , Game : : Cbuf_AddServerText , & sv_log_list , 0 ) ;
Game : : Cmd_AddServerCommand ( " log_list " , Logger : : SV_Log_List_f , & sv_log_list2 ) ;
Game : : Cmd_AddCommand ( " g_log_add " , Game : : Cbuf_AddServerText , & sv_glog_add , 0 ) ;
Game : : Cmd_AddServerCommand ( " g_log_add " , Logger : : SV_GLog_Add_f , & sv_glog_add2 ) ;
Game : : Cmd_AddCommand ( " g_log_del " , Game : : Cbuf_AddServerText , & sv_glog_del , 0 ) ;
Game : : Cmd_AddServerCommand ( " g_log_del " , Logger : : SV_GLog_Del_f , & sv_glog_del2 ) ;
Game : : Cmd_AddCommand ( " g_log_list " , Game : : Cbuf_AddServerText , & sv_glog_list , 0 ) ;
Game : : Cmd_AddServerCommand ( " g_log_list " , Logger : : SV_GLog_List_f , & sv_glog_list2 ) ;
2016-09-02 16:28:51 -04:00
//Utils::Hook(Logger::fsBuildOSPathForThreadHookLoc, FS_BuildOSPathForThreadHookFunc, HOOK_JUMP).Install()->Quick();
//Logger::FS_BuildOSPathForThreadHookTest();
//iw4m_onelog = (Game::dvar_t*)Game::Dvar_RegisterBool("iw4x_onelog", false, Game::DVAR_FLAG_LATCHED || Game::DVAR_FLAG_SAVED, "Only write the game log to the '" BASEGAME "' OS folder");
2016-09-01 15:52:00 -04:00
2016-07-12 12:33:25 -04:00
}
Logger : : ~ Logger ( )
{
Logger : : MessageMutex . lock ( ) ;
Logger : : MessageQueue . clear ( ) ;
Logger : : MessageMutex . unlock ( ) ;
}
2016-09-01 15:52:00 -04:00
//Logging over network stuff
void Logger : : SV_GLog_Add_f ( ) {
if ( Game : : Cmd_Argc ( ) ! = 2 ) {
Game : : Com_Printf ( 0 , " USAGE: %s <IP[:Port]/Hostname[:Port]> \n " , Game : : Cmd_Argv ( 0 ) ) ;
return ;
}
Game : : netadr_t ip ;
if ( ! Game : : NET_StringToAdr ( Game : : Cmd_Argv ( 1 ) , & ip ) ) {
Game : : Com_Printf ( 0 , " Invalid address: %s \n " , Game : : Cmd_Argv ( 1 ) ) ;
return ;
}
for ( size_t i = 0 ; i < Logger : : gaddresses . size ( ) ; i + + ) {
if ( Game : : NET_CompareAdr ( Logger : : gaddresses [ i ] , ip ) ) {
Game : : Com_Printf ( 0 , " Address %s already exists (#%i) \n " , Game : : Cmd_Argv ( 1 ) , i ) ;
return ;
}
}
//all good
Logger : : gaddresses . push_back ( ip ) ;
int size = Logger : : gaddresses . size ( ) ;
Game : : Com_Printf ( 101 , " Address %s (#%i) added to games_mp.log stream list \n " , Game : : NET_AdrToString ( Logger : : gaddresses [ size - 1 ] ) , size - 1 ) ;
}
void Logger : : SV_Log_Add_f ( ) {
if ( Game : : Cmd_Argc ( ) ! = 2 ) {
Game : : Com_Printf ( 0 , " USAGE: %s <IP[:Port]/Hostname[:Port]> \n " , Game : : Cmd_Argv ( 0 ) ) ;
return ;
}
Game : : netadr_t ip ;
if ( ! Game : : NET_StringToAdr ( Game : : Cmd_Argv ( 1 ) , & ip ) ) {
Game : : Com_Printf ( 0 , " Invalid address: %s \n " , Game : : Cmd_Argv ( 1 ) ) ;
return ;
}
for ( size_t i = 0 ; i < Logger : : addresses . size ( ) ; i + + ) {
if ( Game : : NET_CompareAdr ( Logger : : addresses [ i ] , ip ) ) {
Game : : Com_Printf ( 0 , " Address %s already exists (#%i) \n " , Game : : Cmd_Argv ( 1 ) , i ) ;
return ;
}
}
//all good
Logger : : addresses . push_back ( ip ) ;
int size = Logger : : addresses . size ( ) ;
Game : : Com_Printf ( 101 , " Address %s (#%i) added to console_mp.log stream list \n " , Game : : NET_AdrToString ( Logger : : addresses [ size - 1 ] ) , size - 1 ) ;
}
void Logger : : SV_GLog_Del_f ( ) {
if ( Game : : Cmd_Argc ( ) ! = 2 ) {
Game : : Com_Printf ( 0 , " USAGE: %s <ID> \n " , Game : : Cmd_Argv ( 0 ) ) ;
return ;
}
int index = 0 ;
if ( ! Logger : : validInt ( Game : : Cmd_Argv ( 1 ) ) ) {
Game : : Com_Printf ( 0 , " %s is NaN \n " , Game : : Cmd_Argv ( 1 ) ) ;
return ;
}
index = atoi ( Game : : Cmd_Argv ( 1 ) ) ;
if ( index > - 1 & & index < ( int ) Logger : : gaddresses . size ( ) ) {
Game : : Com_Printf ( 0 , " Address %s (ID %i) removed \n " , Game : : NET_AdrToString ( Logger : : gaddresses [ index ] ) , index ) ;
Logger : : gaddresses . erase ( Logger : : gaddresses . begin ( ) + index ) ;
}
else {
Game : : Com_Printf ( 0 , " ID %i is not valid \n " , index ) ;
}
}
void Logger : : SV_Log_Del_f ( ) {
if ( Game : : Cmd_Argc ( ) ! = 2 ) {
Game : : Com_Printf ( 0 , " USAGE: %s <ID> \n " , Game : : Cmd_Argv ( 0 ) ) ;
return ;
}
int index = 0 ;
if ( ! Logger : : validInt ( Game : : Cmd_Argv ( 1 ) ) ) {
Game : : Com_Printf ( 0 , " %s is NaN \n " , Game : : Cmd_Argv ( 1 ) ) ;
return ;
}
index = atoi ( Game : : Cmd_Argv ( 1 ) ) ;
if ( index > - 1 & & index < ( int ) Logger : : addresses . size ( ) ) {
Game : : Com_Printf ( 0 , " Address %s (ID %i) removed \n " , Game : : NET_AdrToString ( Logger : : addresses [ index ] ) , index ) ;
Logger : : addresses . erase ( Logger : : addresses . begin ( ) + index ) ;
}
else {
Game : : Com_Printf ( 0 , " ID %i is not valid \n " , index ) ;
}
}
void Logger : : SV_GLog_List_f ( ) {
Game : : Com_Printf ( 0 , " # ID: Address \n " ) ;
Game : : Com_Printf ( 0 , " ------------- \n " ) ;
for ( size_t i = 0 ; i < Logger : : gaddresses . size ( ) ; i + + ) {
Game : : Com_Printf ( 0 , " #%03d: %5s \n " , i , Game : : NET_AdrToString ( Logger : : gaddresses [ i ] ) ) ;
}
}
void Logger : : SV_Log_List_f ( ) {
Game : : Com_Printf ( 0 , " # ID: Address \n " ) ;
Game : : Com_Printf ( 0 , " ------------- \n " ) ;
for ( size_t i = 0 ; i < Logger : : addresses . size ( ) ; i + + ) {
Game : : Com_Printf ( 0 , " #%03d: %5s \n " , i , Game : : NET_AdrToString ( Logger : : addresses [ i ] ) ) ;
}
}
bool Logger : : validInt ( char * str ) {
for ( size_t i = 0 ; i < strlen ( str ) ; i + + ) {
if ( str [ i ] < ' 0 ' | | str [ i ] > ' 9 ' ) {
return false ;
}
}
return true ;
}
2016-09-02 16:28:51 -04:00
2016-09-01 15:52:00 -04:00
void Logger : : FS_BuildOSPathForThreadHookTest ( )
{
Game : : dvar_t * g_log = * ( Game : : dvar_t * * ) 0x1A45D9C ;
if ( g_log & & strcmp ( writeFile , g_log - > current . string ) = = 0 )
{
if ( strcmp ( writeFolder , BASEGAME ) ! = 0 )
{
if ( iw4m_onelog - > current . boolean )
{
strcpy_s ( writeFolder , 256 , BASEGAME ) ;
}
}
}
}
void __declspec ( naked ) Logger : : FS_BuildOSPathForThreadHookFunc ( )
{
__asm
{
mov eax , [ esp + 8 h ]
mov writeFolder , eax
mov eax , [ esp + 0 Ch ]
mov writeFile , eax
mov eax , [ esp + 8 h ]
push ebp
push esi
mov esi , [ esp + 0 Ch ]
2016-09-02 16:28:51 -04:00
2016-09-01 15:52:00 -04:00
jmp fsBuildOSPathForThreadHookLocRet
}
}
2016-07-12 12:33:25 -04:00
}