393 lines
9.5 KiB
C++
393 lines
9.5 KiB
C++
#include "stdafx.h"
|
|
#include "Resource.h"
|
|
//#include "mymem.h"
|
|
#include "utils.h"
|
|
#include "Logger.h"
|
|
// lists
|
|
#include "CharArray.h"
|
|
#include "ClanList.h"
|
|
#include "NpcArray.h"
|
|
#include "GIArray.h"
|
|
#include "WorldObjectTree.h"
|
|
// listeners
|
|
#include "LoginListener.h"
|
|
#include "GameListener.h"
|
|
#include "GameClient.h"
|
|
// windows
|
|
#include "RadarDllWnd.h"
|
|
#include "ConfigIni.h"
|
|
// net hook
|
|
#include "net_hook.h"
|
|
// scripting
|
|
#include "ScriptEngine.h"
|
|
|
|
|
|
// global app instance handle
|
|
HINSTANCE g_hinst;
|
|
|
|
// global app configuration
|
|
CConfig g_cfg;
|
|
FILE *g_errorLogFile = NULL; // log file
|
|
|
|
// global listeners
|
|
LoginListener *g_plogin;
|
|
GameListener *g_pgame;
|
|
GameClient *g_game_client;
|
|
|
|
int int_dll_was_init = 0;
|
|
|
|
/** Initializes DLL. returns 0 on success **/
|
|
int InitDLL();
|
|
/** Uninitializes DLL **/
|
|
int UninitDLL();
|
|
/** */
|
|
void DllThreadStart();
|
|
|
|
extern void CleanupDirectDraw();
|
|
|
|
BOOL WINAPI DllMain( HINSTANCE hInstDLL, ULONG reason, LPVOID lpvReserved )
|
|
{
|
|
lpvReserved = NULL;
|
|
if( reason == DLL_PROCESS_ATTACH )
|
|
{
|
|
//MessageBox( 0, TEXT("DLL_PROCESS_ATTACH"), NULL, 0 );
|
|
if( int_dll_was_init ) return TRUE;
|
|
InterlockedIncrement( (LONG *)&int_dll_was_init );
|
|
g_hinst = hInstDLL;
|
|
DisableThreadLibraryCalls( hInstDLL );
|
|
//
|
|
DllThreadStart();
|
|
}
|
|
else if( reason == DLL_PROCESS_DETACH )
|
|
{
|
|
//MessageBox( 0, TEXT("DLL_PROCESS_DETTACH"), NULL, 0 );
|
|
if( int_dll_was_init == 0 ) return TRUE;
|
|
InterlockedDecrement( (LONG *)&int_dll_was_init );
|
|
UninitDLL();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
void test_GetClassInfoEx()
|
|
{
|
|
WNDCLASSEXW wc;
|
|
if( GetClassInfoExW( NULL, WC_TABCONTROLW, &wc ) )
|
|
{
|
|
MessageBox( NULL, TEXT("GetClassInfoExW() OK"), TEXT("Test"), 0 );
|
|
}
|
|
else
|
|
{
|
|
TCHAR tstr[128];
|
|
wsprintf( tstr, TEXT("GetClassInfoExW() failed! Error %u"), (unsigned int)GetLastError() );
|
|
MessageBox( NULL, tstr, TEXT("Test"), 0 );
|
|
}
|
|
}
|
|
#endif /* _DEBUG */
|
|
|
|
DWORD WINAPI DllThread(LPVOID lpParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(lpParam);
|
|
#ifdef _DEBUG
|
|
//test_GetClassInfoEx();
|
|
#endif /* _DEBUG */
|
|
if( InitDLL() )
|
|
{
|
|
return 12345;
|
|
}
|
|
#ifdef _DEBUG
|
|
//test_GetClassInfoEx();
|
|
#endif /* _DEBUG */
|
|
|
|
if( !Hook_ValidateAlign() )
|
|
{
|
|
MessageBox( NULL, TEXT("Structure alignment error!"), TEXT("Alignment error!"), MB_ICONSTOP );
|
|
RaiseException( EXCEPTION_DATATYPE_MISALIGNMENT, 0, 0, NULL );
|
|
return 123456;
|
|
}
|
|
|
|
// install hook over ws2_32.dll!connect()
|
|
// SEH only under msvc
|
|
#ifdef _MSC_VER
|
|
__try
|
|
{
|
|
#endif
|
|
if( !Hook_IsWinsockConnectOrig() )
|
|
{
|
|
log_error( LOG_WARNING, "Seems like ws2_32.dll!connect() is already hooked by someone...\n" );
|
|
log_error( LOG_WARNING, "Some firewall/protection sofware?\n" );
|
|
log_error( LOG_WARNING, "I'll try to set up my hook, but program may not function correctly later.\n" );
|
|
}
|
|
if( !Hook_CheckVirtualProtect() )
|
|
{
|
|
log_error( LOG_WARNING, "Seems like kernel32.dll!VirtualProtectEx() is hooked, so...\n" );
|
|
log_error( LOG_WARNING, "Maybe we're running in GameGuard protected program?\n" );
|
|
log_error( LOG_WARNING, "Be careful!\n" );
|
|
}
|
|
Hook_InterceptConnect_my();
|
|
if( !Hook_ValidateInterception_my() )
|
|
{
|
|
log_error( LOG_ERROR, "Seems like my try to intercept ws2_32.dll!connect() failed.\n" );
|
|
log_error( LOG_ERROR, "All network connections will not be intercepted!\n" );
|
|
}
|
|
//Hook_InterceptConnect_Dis(); // this unused..
|
|
#ifdef _MSC_VER
|
|
}
|
|
__except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
ErrorLogger_LogLastError( "Exception occured during call to Hook_InterceptConnect_my()", GetLastError() );
|
|
log_error( LOG_ERROR, "We will try to continue execution...\n" );
|
|
ErrorLogger_FlushLogFile();
|
|
}
|
|
#endif
|
|
|
|
L2PNet_setFunction( L2PFUNC_CONNECT, (void *)connect_l2packets_my );
|
|
|
|
/*int i;
|
|
i = 6;
|
|
while( i >= 0 )
|
|
{
|
|
Hook_ValidateInterception_my();
|
|
Sleep( 10000 );
|
|
i--;
|
|
}*/
|
|
|
|
//UninitDLL();
|
|
return 0;
|
|
}
|
|
|
|
|
|
void DllThreadStart()
|
|
{
|
|
HANDLE hThread = NULL;
|
|
DWORD dwTID = 0;
|
|
hThread = (HANDLE)_beginthreadex( NULL, 0,
|
|
(unsigned int (__stdcall *)(void *))DllThread, NULL, 0,
|
|
(unsigned int *)&dwTID );
|
|
if( hThread != NULL ) CloseHandle( hThread );
|
|
}
|
|
|
|
#ifdef L2D_INIT_SSL_LIBRARY
|
|
bool InitSSL()
|
|
{
|
|
SSL_load_error_strings();
|
|
SSL_library_init();
|
|
void *rndbuf = malloc(1024);
|
|
if( rndbuf )
|
|
{
|
|
RAND_seed( rndbuf, 1024 );
|
|
free( rndbuf );
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
//#define L2D_INIT_COMMON_CONTROLS
|
|
#ifdef L2D_INIT_COMMON_CONTROLS
|
|
#pragma comment( lib, "comctl32" )
|
|
#endif
|
|
|
|
void AreWeInIngameMode()
|
|
{
|
|
TCHAR tszEvtName[256];
|
|
wsprintf( tszEvtName, TEXT("L2Detect Outgame Event_%d"), (unsigned)GetCurrentProcessId() );
|
|
HANDLE hEvtDbg = OpenEvent( EVENT_MODIFY_STATE, FALSE, tszEvtName );
|
|
if( hEvtDbg == NULL ) // ingame
|
|
{
|
|
g_cfg.isInGameMode = true;
|
|
CloseHandle( hEvtDbg );
|
|
log_error( LOG_OK, "Running in ingame mode...\n" );
|
|
}
|
|
else
|
|
{
|
|
g_cfg.isInGameMode = false;
|
|
log_error( LOG_OK, "Running in outgame mode...\n" );
|
|
}
|
|
}
|
|
|
|
/** Initializes DLL. returns 0 on success **/
|
|
int InitDLL()
|
|
{
|
|
// init common controls?
|
|
//MyInitCommonControls();
|
|
#ifdef L2D_INIT_COMMON_CONTROLS
|
|
//MyInitCommonControlsEx();
|
|
#endif
|
|
|
|
// read global app config
|
|
g_cfg.SetDefault();
|
|
if( !g_cfg.ReadConfig( _T("L2Detect.ini") ) ) g_cfg.SetDefault();
|
|
// determine INGAME or OUTGAME mode. NOW
|
|
AreWeInIngameMode();
|
|
|
|
// setup L2Packets Net Layer
|
|
L2PNet_InitDefault();
|
|
L2PacketNames_Init();
|
|
|
|
// setup Logger
|
|
ErrorLogger_Init();
|
|
ErrorLogger_SetLogFile( NULL );
|
|
#ifdef _DEBUG
|
|
ErrorLogger_SetAutoPrependErrorType( true );
|
|
g_errorLogFile = fopen( "L2Detect.log", "wt" );
|
|
ErrorLogger_SetLogFile( g_errorLogFile );
|
|
ErrorLogger_Enable( true );
|
|
//ErrorLogger_EnableLoggingToConsole( true );
|
|
log_error( LOG_DEBUG, "InitDLL() called! int_dll_was_init = %d\n", int_dll_was_init );
|
|
ErrorLogger_FlushLogFile();
|
|
#endif
|
|
|
|
// Init COM
|
|
HRESULT comRes = CoInitialize( NULL );
|
|
if( comRes != S_OK )
|
|
{
|
|
log_error( LOG_ERROR, "CoInitialize() failed: HRESULT = %d (GetLastError() = %u)\n",
|
|
comRes, (unsigned int)GetLastError() );
|
|
}
|
|
|
|
// init MyMem after logger
|
|
//MyMem_Init();
|
|
|
|
// init OpenSSL
|
|
#ifdef L2D_INIT_SSL_LIBRARY
|
|
InitSSL();
|
|
#endif
|
|
|
|
// init L2 Data
|
|
char outErrMsg[512] = {0};
|
|
L2Data_init();
|
|
L2Data_DB_Init( outErrMsg, "L2Detect_items.sqlite3db", "L2Detect_mobs.sqlite3db", "L2Detect_skills.sqlite3db" );
|
|
if( outErrMsg[0] ) MessageBoxA( NULL, outErrMsg, "L2Data_DB_Init() error!", MB_ICONSTOP );
|
|
L2Data_SM_init();
|
|
|
|
// setup binTrees
|
|
CharArray_Init();
|
|
ClanList_Init();
|
|
NpcArray_Init();
|
|
GIArray::getInstance();
|
|
WorldObjectTree_Init();
|
|
|
|
// create listeners
|
|
// create LoginListener only in outgame mode
|
|
g_plogin = NULL;
|
|
if( g_cfg.isInGameMode == false )
|
|
{
|
|
g_plogin = new LoginListener();
|
|
if( !g_plogin->start() )
|
|
{
|
|
log_error( LOG_ERROR, "Login server listener creation failed!\n" );
|
|
MessageBox( NULL, TEXT("Login server listener creation failed!"),
|
|
TEXT("Init error!"), MB_ICONSTOP );
|
|
return 1;
|
|
}
|
|
} // create LoginListener only in outgame mode
|
|
|
|
g_pgame = new GameListener();
|
|
if( !g_pgame->start() )
|
|
{
|
|
log_error( LOG_ERROR, "Game server listener creation failed!\n" );
|
|
MessageBox( NULL, TEXT("Game server listener creation failed!"),
|
|
TEXT("Init error!"), MB_ICONSTOP );
|
|
return 1;
|
|
}
|
|
|
|
// create global GameClient object (important!!!!!)
|
|
g_game_client = new GameClient();
|
|
|
|
// instantiate ScriptEngine
|
|
ScriptEngine::getInstance()->init();
|
|
|
|
#ifdef _DEBUG
|
|
ErrorLogger_FlushLogFile();
|
|
#endif
|
|
|
|
RadarDllWindowStart( g_hinst );
|
|
|
|
return 0; // ALL OK
|
|
}
|
|
|
|
|
|
/** Uninitializes DLL **/
|
|
int UninitDLL()
|
|
{
|
|
log_error( LOG_DEBUG, "UninitDLL() called! int_dll_was_init = %d\n", int_dll_was_init );
|
|
// delete ScriptEngine
|
|
ScriptEngine::freeInstance();
|
|
// stop listeners
|
|
log_error( LOG_DEBUG, "Signaling listeners to exit...\n" );
|
|
if( g_plogin ) g_plogin->signalStop(); // LoginListener may not be started in ingame mode at all
|
|
g_pgame->signalStop();
|
|
// wait for stop
|
|
if( g_plogin ) // LoginListener may not be started in ingame mode at all
|
|
{
|
|
log_error( LOG_DEBUG, "Waiting for login listener to stop (10 secs)...\n" );
|
|
if( !g_plogin->waitStopped( 10000 ) )
|
|
{
|
|
log_error( LOG_WARNING, "Login listener wait timeout expired... :( \n" );
|
|
g_plogin->terminateThread();
|
|
}
|
|
else log_error( LOG_DEBUG, "Login listener wait OK\n" );
|
|
delete g_plogin;
|
|
g_plogin = NULL;
|
|
}
|
|
|
|
log_error( LOG_DEBUG, "Waiting for game listener to stop (10 secs)...\n" );
|
|
if( !g_pgame->waitStopped( 10000 ) )
|
|
{
|
|
log_error( LOG_WARNING, "Game listener wait timeout expired... :( \n" );
|
|
g_pgame->terminateThread();
|
|
}
|
|
else log_error( LOG_DEBUG, "Game listener wait OK\n" );
|
|
delete g_pgame;
|
|
g_pgame = NULL;
|
|
|
|
delete g_game_client;
|
|
|
|
#ifdef _DEBUG
|
|
ErrorLogger_FlushLogFile();
|
|
#endif
|
|
|
|
|
|
//
|
|
// Cleanup
|
|
//
|
|
|
|
// close database
|
|
L2Data_DB_Free();
|
|
L2Data_SM_free();
|
|
|
|
// save global app config
|
|
g_cfg.SaveConfig();
|
|
// clean binTrees
|
|
CharArray_Free();
|
|
ClanList_Free();
|
|
NpcArray_Free();
|
|
GIArray::freeInstance();
|
|
WorldObjectTree_Free();
|
|
|
|
// close MyMem before logger
|
|
//MyMem_Free();
|
|
|
|
if( g_cfg.isInGameMode ) CleanupDirectDraw();
|
|
|
|
// Uninitialize COM
|
|
CoUninitialize();
|
|
|
|
// close log
|
|
#ifdef _DEBUG
|
|
log_error( LOG_OK, "Closing log. Last message.. Bye!\n" );
|
|
ErrorLogger_FlushLogFile();
|
|
ErrorLogger_SetLogFile( NULL );
|
|
if( g_errorLogFile ) fclose( g_errorLogFile );
|
|
g_errorLogFile = NULL;
|
|
#endif
|
|
// shutdown winsock
|
|
//WSACleanup();
|
|
//L2PNet_Cleanup();
|
|
|
|
return 0;
|
|
}
|