5386 lines
147 KiB
C++
5386 lines
147 KiB
C++
// SFrame.cpp : Defines the entry point for the application.
|
|
// Bypassed Bypassed Bypassed Damn
|
|
|
|
|
|
// Do not delete
|
|
// Runtime Error!
|
|
// Program : c:\Program Files\NFLAVOR\Rappelz_cut\SFrame.exe R6002
|
|
// -floating point not loaded
|
|
// Forced loading
|
|
volatile float a = 1.f;
|
|
extern "C"
|
|
{
|
|
extern int _fltused;
|
|
volatile int _AVOID_FP_BUG = _fltused;
|
|
};
|
|
// The issue above is related.
|
|
//
|
|
#include "stdafx.h"
|
|
|
|
//#define VLD_FORCE_ENABLE
|
|
//#include <vld/vld.h>
|
|
//#pragma message( ">>>>>>VLD is activated<<<<<" )
|
|
|
|
//#include "Windows.h"
|
|
//#include <stdio.h>
|
|
#include "SFrame.h"
|
|
#include "w32_util.h"
|
|
#include "SBotManager.h"
|
|
#include "LuaVM.h"
|
|
#include "SGameScript.h"
|
|
#include "SBotScript.h"
|
|
#include "SSystemScript.h"
|
|
#include <kfile/KRealFileSystem.h>
|
|
#include <kfile/XFileBasedFS.h>
|
|
#include <kfile/KFileNameCipher.h>
|
|
#include <kfile/KOldEncodedFS.h>
|
|
#include <kfile/KPackingFileSystem.h>
|
|
#include <toolkit/XMemoryPool.h>
|
|
#include <toolkit/c_unimempool.h>
|
|
#include <mmo/ArTime.h>
|
|
#include "SSkillDB.H"
|
|
#include "SMotionDB.H"
|
|
#include "STenacityDB.H"
|
|
#include "SItemDB.h"
|
|
#include "GameUrlDefine.h"
|
|
#include "KUIWndManager.h"
|
|
#include "KUIWnd.h"
|
|
#include <dump/XExceptionHandler.h>
|
|
#include <toolkit/XModuleInfo.h>
|
|
#include <toolkit/XEnv.h>
|
|
#include <toolkit/XFileUtil.h>
|
|
#include <kfile/KFileManager.h>
|
|
#include "KThreadLoader.h"
|
|
#include "GameDefine.h"
|
|
#include "SGameOption.h"
|
|
#include "SGameManager.h"
|
|
#include "KCommandBuilder.h"
|
|
#include "KTextRender.h"
|
|
#include "KTextParser.h"
|
|
#include "KTextEmoticonRender.h"
|
|
#include "KUIControlEdit.h"
|
|
#include <toolkit/nsl.h>
|
|
#include <toolkit/nsluni.h>
|
|
#include <toolkit/nslreg.h>
|
|
#include "SStringDB.h"
|
|
#include "SLocalCommandDB.h"
|
|
#include <internet/XInternet.h>
|
|
//#include "Util.h"
|
|
#include "CEditBoxInfo.h"
|
|
#include <exdisp.h>
|
|
#include <comutil.h>
|
|
#include <mshtmhst.h>
|
|
#include "SWebCtrlInterface.h"
|
|
#include "shellapi.h"
|
|
#include "SDebug_Util.h"
|
|
#include "KResourceManager.h"
|
|
#include "SplashLoading/SplashLoading.h"
|
|
#include "SCreatureEnhanceDB.h"
|
|
#include "SEnhanceEffectDB.h"
|
|
#include "Hooking.h"
|
|
#include "STitleDB.h"
|
|
#include "SMonsterCreatureDB.h"
|
|
#ifdef CLOUD_LUA
|
|
#include "SGameCloud.h"
|
|
#endif
|
|
#include <network/XNetworkUtil.h>
|
|
#include <toolkit/XVerifyProcessSigner.h>
|
|
#include <toolkit/XThread.h>
|
|
|
|
#include <internal_render_include.h>
|
|
#include <internal_utility_include.h>
|
|
#include <external_lib_include.h>
|
|
|
|
//#include <crtdbg.h>
|
|
//#ifdef _DEBUG
|
|
//#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
|
|
//#endif
|
|
|
|
#ifdef _COUNTRY_TL_
|
|
#include "./Localization/Thailand.h"
|
|
#endif
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
#include "./Localization/MiddleEast.h"
|
|
#endif
|
|
|
|
#ifdef _USE_XTRAP_MODULE
|
|
#include <xtrap/090628_513_Xtrap_C_Interface.h>
|
|
#include <xtrap/090109_009_XTrap4Launcher.h>
|
|
#endif
|
|
|
|
#ifdef _EDIT_ENVIRONMENT_
|
|
#include "EditParameterDialog.h"
|
|
#endif
|
|
|
|
using namespace XSEH;
|
|
|
|
#define MAX_LOADSTRING 100
|
|
|
|
// 전역 변수입니다.
|
|
TCHAR szTitle[256]; // 제목 표시줄 텍스트입니다.
|
|
TCHAR szWindowClass[MAX_LOADSTRING]; // 기본 창 클래스 이름입니다.
|
|
TCHAR szFPS[32];
|
|
|
|
TCHAR BuildDate[16];
|
|
TCHAR BuildTime[16];
|
|
|
|
std::string g_strModulePath;
|
|
|
|
//Bot Manager
|
|
SBotManager * g_pSBotMng = NULL;
|
|
|
|
|
|
bool g_bUserCamMode = false; // Manual mode for video recording support camera (toggled by typing //camera in the chat window)
|
|
|
|
|
|
#ifdef _DEBUG
|
|
bool g_bDebugMode = true;
|
|
#else
|
|
// 2010.11.10: Modified to allow setting g_bDebugMode if the account, which is not in developer mode, contains '@' - prodongi
|
|
#ifdef _DEV
|
|
bool g_bDebugMode = true; // Check if it is in developer mode or not. (It toggles when typing //debug in the chat window)
|
|
#else
|
|
bool g_bDebugMode = false; // Check if it is in developer mode or not. (It toggles when typing //debug in the chat window)
|
|
#endif
|
|
#endif
|
|
|
|
bool g_bRenderUI = true;
|
|
HHOOK g_hKeyBoardHook = NULL;
|
|
HWND g_hWnd = NULL;
|
|
HWND g_hWnd_Explorer = NULL;
|
|
|
|
FILE* g_pFLog = NULL;
|
|
|
|
HINSTANCE g_hInstance;
|
|
|
|
extern const char * CLIENT_VER;
|
|
|
|
DWORD g_dwFPS = 0;
|
|
DWORD g_dwCount = 0;
|
|
DWORD g_dwFPSTime = 0;
|
|
bool g_bLogStringRate = false;
|
|
|
|
DWORD g_dwKeyResumeTime = 0;
|
|
bool g_bCheckHook = false;
|
|
|
|
#ifdef _HACK_SHIELD_
|
|
bool g_bAhnHS = false;
|
|
#endif
|
|
|
|
bool g_bWindowFPS = false;
|
|
int g_DP_Count[3];
|
|
int g_UsedMeshEXPoolCount[3];
|
|
int g_Poly_Count;
|
|
int g_TexMem;
|
|
bool g_bActiveRender = false;
|
|
IWebBrowser2* g_pWebBrowser = NULL;
|
|
bool g_bServerListFocus = false;
|
|
bool g_bServerListSeen = false;
|
|
bool g_bCharListSeen = false;
|
|
|
|
bool g_bCleanupCOM = false;
|
|
|
|
std::string g_strGuildFullDir;
|
|
const char * g_pGuildDir = ".\\Guild_Icon\\";
|
|
|
|
//#define DISABLE_DEBUGGER_DETECTOR
|
|
|
|
KPoint g_Help_url;
|
|
KPoint g_Cash_url;
|
|
KPoint g_Cash_add_url;
|
|
|
|
DEVMODE g_dm;
|
|
DEVMODE g_dm_apply;
|
|
|
|
#ifdef _DEBUG
|
|
int g_nMemAllocCnt[128];
|
|
#endif
|
|
|
|
// This is the forward declaration of the functions in this code module.
|
|
ATOM MyRegisterClass(HINSTANCE hInstance);
|
|
HWND InitInstance(HINSTANCE, int);
|
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
|
// { [sonador][1.5.1] Improved keyboard input
|
|
#ifdef _USE_KEYBOARD_HOOK
|
|
LRESULT CALLBACK KeyboardProc( int code, WPARAM wParam, LPARAM lParam );
|
|
#else
|
|
void ResetHotKeys();
|
|
LRESULT CALLBACK HotKeyProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
|
|
#endif
|
|
// }
|
|
|
|
void SetURLNavigate( IWebBrowser2* pWebBrowser, const char * pURL );
|
|
void SetWebBrowserVisible( IWebBrowser2* pWebBrowser, bool bVisible );
|
|
|
|
bool ChangeDisplay();
|
|
bool RestoreDisplay();
|
|
void CheckDisplay();
|
|
void SetWindowStyle( bool bFullScreen );
|
|
BOOL CheckOSVersion();
|
|
|
|
#ifdef _HACK_SHIELD_
|
|
|
|
#include <hack_shield/HShield.h>
|
|
#include <hack_shield/HSUpChk.h> // sonador 7.4.4 핵쉴드 270 적용
|
|
#include "SGameVM.h"
|
|
|
|
int __stdcall _AhnHS_Callback( long lCode, long lParamSize, void* pParam );
|
|
bool UpdateHackShieldService(); // sonador 7.4.4 핵쉴드 270 적용
|
|
bool StartHackShieldService();
|
|
void StopHackShieldService();
|
|
void PauseHackShieldService();
|
|
void ResumeHackShieldService();
|
|
|
|
bool g_bStartingHSService = false;
|
|
|
|
#endif
|
|
|
|
|
|
// #2.3.2.7 sonador
|
|
#ifdef _DEV
|
|
#define NO_GAMEGUARD
|
|
#endif
|
|
#include <game_guard/NPGameLib.h>
|
|
|
|
//CNPGameLib *g_pNpgl = NULL;
|
|
CNPGameLib *g_pNpgl;
|
|
|
|
|
|
bool StartnProtectService();
|
|
DWORD g_dwCheckGameMon = 0;
|
|
bool g_bConnGameMon = true;
|
|
|
|
|
|
std::vector< GameSecurityMsg* > g_SecurityMsg;
|
|
DWORD g_dwhkTime = 0;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// External function-prototypes
|
|
//-----------------------------------------------------------------------------
|
|
extern HRESULT GetDXVersion( DWORD* pdwDirectXVersion, TCHAR* strDirectXVersion, int cchDirectXVersion, TCHAR & cDXVerLetter );
|
|
|
|
extern HWND g_hWnd;
|
|
|
|
VARIANT_BOOL g_IsShowWebBrowser = false;
|
|
bool g_IsShowWebBrowserChanged = false;
|
|
std::string g_strDebugInfo_SUN("START");
|
|
|
|
BOOL CALLBACK About(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)
|
|
{
|
|
switch(iMessage)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return TRUE;
|
|
case WM_COMMAND:
|
|
switch (wParam)
|
|
{
|
|
case IDOK:
|
|
//ShellExecute( NULL, "open", "http://rappelz.nefficient.co.kr/rappelz/directx9c/dxwebsetup.exe", NULL, NULL, 0 );
|
|
ShellExecute( NULL, "open", "http://127.0.0.1/rappelz/directx9c/dxwebsetup.exe", NULL, NULL, 0 ); // Fraun 7/12/2025 nullifying gala spyware
|
|
EndDialog(hDlg,0);
|
|
return TRUE;
|
|
|
|
case ID_CANCEL:
|
|
EndDialog(hDlg,0);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// 1번째 네트웤 아답터의 맥어드레스를 돌려 준다
|
|
// 6바이트 짜리 unsigned char 로 구성되어져 있다.
|
|
// 출력 함수는 아래 참조
|
|
// 터키 요청으로 추가 예정
|
|
// 서버랑 페킷이 완료 되면 추가 예정
|
|
|
|
//2009-08-12 : hunee
|
|
// Prints the MAC address stored in a 6 byte array to stdout
|
|
/*
|
|
static void printMACaddress(unsigned char MACData[])
|
|
{
|
|
printf("MAC Address: %02X-%02X-%02X-%02X-%02X-%02X\n",
|
|
MACData[0], MACData[1], MACData[2], MACData[3], MACData[4],
|
|
MACData[5]);
|
|
}*/
|
|
|
|
|
|
/*#include <Iphlpapi.h>
|
|
#include <assert.h>
|
|
#pragma comment(lib, "iphlpapi.lib")
|
|
/*
|
|
static unsigned char * getMACAddress()
|
|
{
|
|
// Fetches the MAC address and prints it
|
|
static IP_ADAPTER_INFO adapterInfo[16];
|
|
|
|
DWORD bufLen = sizeof(adapterInfo);
|
|
DWORD status = GetAdaptersInfo(adapterInfo, &bufLen);
|
|
assert(status == ERROR_SUCCESS);
|
|
|
|
PIP_ADAPTER_INFO pAdapterInfo = adapterInfo;
|
|
|
|
return pAdapterInfo->Address;
|
|
}*/
|
|
|
|
|
|
void InitWebBrowser( IWebBrowser2* pWebBrowser )
|
|
{
|
|
if( pWebBrowser )
|
|
{
|
|
//gmpbigsun( 20130321 ) : 유럽 페이지 이상으로 아래기능 제거
|
|
// pWebBrowser->put_ToolBar(VARIANT_FALSE); // 익스플로어 툴바 없앰
|
|
// pWebBrowser->put_MenuBar(VARIANT_FALSE); // 메뉴바 없앰
|
|
// pWebBrowser->put_AddressBar(VARIANT_FALSE);// 주소창 없앰
|
|
// pWebBrowser->put_StatusBar(VARIANT_FALSE); // 상태바 없앰
|
|
}
|
|
}
|
|
|
|
void SetWebWindowStyle( HWND hWebBrowser )
|
|
{
|
|
// Window Style 변경
|
|
DWORD dwStyle = GetWindowLong(hWebBrowser, GWL_STYLE);
|
|
dwStyle = WS_CHILD;
|
|
//dwStyle &= ~WS_BORDER;
|
|
//dwStyle &= ~WS_THICKFRAME;
|
|
//dwStyle &= ~WS_CAPTION;
|
|
//dwStyle &= ~WS_SYSMENU;
|
|
//dwStyle &= ~WS_MINIMIZE;
|
|
//dwStyle &= ~WS_VSCROLL;
|
|
//dwStyle &= ~WS_HSCROLL;
|
|
|
|
if( SetWindowLong((HWND)hWebBrowser, GWL_STYLE, dwStyle) == 0 )
|
|
{
|
|
std::string strErr = CStringUtil::StringFormat( "Failed Explorer SetWindowStyle : %d", GetLastError() );
|
|
MessageBox( g_hWnd, strErr.c_str(), "Rappelz-Error", MB_ICONERROR|MB_OK );
|
|
}
|
|
|
|
HWND hr_hWnd = ::SetParent( hWebBrowser, g_hWnd );
|
|
}
|
|
|
|
#include <atlbase.h>
|
|
#include <atlcom.h>
|
|
#include <atlhost.h>
|
|
|
|
|
|
typedef struct _web_browser_info_
|
|
{
|
|
int nIndex;
|
|
HWND hWnd;
|
|
HWND hWndIE;
|
|
IWebBrowser2* pWebBrowser;
|
|
|
|
} _WEB_BROWSER_INFO_;
|
|
|
|
static int g_nWebBrowserIndex = 0;
|
|
std::vector<_WEB_BROWSER_INFO_> g_vWebBrowserInfoList;
|
|
|
|
|
|
void DeleteAllWebBrowserInfo()
|
|
{
|
|
for( unsigned int i(0); g_vWebBrowserInfoList.size()>i; i++ )
|
|
{
|
|
DestroyWindow( g_vWebBrowserInfoList[i].hWndIE );
|
|
DestroyWindow( g_vWebBrowserInfoList[i].hWnd );
|
|
}
|
|
}
|
|
|
|
IWebBrowser2* GetWebBrowser( int nWidth, int nHeight, int nAddWidth, int nAddHeight )
|
|
{
|
|
CComQIPtr<IWebBrowser2> pWebBrowser;
|
|
|
|
HWND hWnd=g_hWnd;
|
|
RECT rcWnd, rWnd;
|
|
GetClientRect(hWnd, &rcWnd);
|
|
GetWindowRect(hWnd, &rWnd);
|
|
|
|
rcWnd.left = 0;
|
|
rcWnd.top = 0;
|
|
|
|
int nAppWidth = rcWnd.right - rcWnd.left;
|
|
int nAppHeight = rcWnd.bottom - rcWnd.top;
|
|
|
|
int nCenterX = (nAppWidth - nWidth)/2 + nAddWidth;
|
|
int nCenterY = (nAppHeight - nHeight)/2 + nAddHeight;
|
|
|
|
// 자식창은 WS_POPUP으로 띄워야 한다.
|
|
HWND hChild = CreateWindow( "static", NULL, WS_VISIBLE | WS_CHILD, nCenterX, nCenterY, nWidth, nHeight,
|
|
g_hWnd, (HMENU)0, g_hInstance, (LPVOID) NULL);
|
|
|
|
// 비주얼 스튜디오 7.1이라 AtlAxWin71 -> 2010(100)
|
|
HWND hwndIE = CreateWindow( "AtlAxWin100", "Shell.Explorer.2", WS_CHILD|WS_VISIBLE, 0, 0, nWidth, nHeight,
|
|
hChild, (HMENU)0, GetModuleHandle(NULL), NULL);
|
|
|
|
if(!hwndIE)
|
|
{
|
|
if( hChild ) DestroyWindow( hChild );
|
|
return NULL;
|
|
}
|
|
|
|
CComPtr<IUnknown> punkIE;
|
|
|
|
if (AtlAxGetControl(hwndIE, &punkIE) == S_OK)
|
|
{
|
|
pWebBrowser = punkIE;
|
|
if( pWebBrowser )
|
|
{
|
|
pWebBrowser->put_Top( 0 );
|
|
pWebBrowser->put_Left( 0 );
|
|
pWebBrowser->put_Width( nWidth );
|
|
pWebBrowser->put_Height( nHeight );
|
|
|
|
// 2008.5.30 floyd #2.3.1.21 웹브라우저 창에 Drag&Drop으로 다른 페이지를 볼수 있게 하는 기능 제거
|
|
pWebBrowser->put_RegisterAsDropTarget( FALSE );
|
|
|
|
IOleObject *pIOleObj = NULL;
|
|
HRESULT hResult = pWebBrowser->QueryInterface(IID_IOleObject, (void**)&pIOleObj);
|
|
if (pIOleObj != NULL)
|
|
{
|
|
CWebCtrlInterFace* pWebCtrlInterFace = new CWebCtrlInterFace( hwndIE );
|
|
pWebCtrlInterFace->SetContextMenuMode( kNoContextMenu );
|
|
|
|
IOleClientSite *oldClientSite = NULL;
|
|
|
|
hResult = pIOleObj->GetClientSite(&oldClientSite);
|
|
if ( hResult == S_OK )
|
|
{
|
|
if( oldClientSite )
|
|
{
|
|
pWebCtrlInterFace->SetDefaultClientSite(oldClientSite);
|
|
oldClientSite->Release();
|
|
}
|
|
}
|
|
hResult = pIOleObj->SetClientSite(pWebCtrlInterFace);
|
|
}
|
|
|
|
_WEB_BROWSER_INFO_ web_browser_info;
|
|
web_browser_info.nIndex = g_nWebBrowserIndex++;
|
|
web_browser_info.hWnd = hChild;
|
|
web_browser_info.hWndIE = hwndIE;
|
|
web_browser_info.pWebBrowser = pWebBrowser;
|
|
|
|
g_vWebBrowserInfoList.push_back( web_browser_info );
|
|
|
|
return pWebBrowser;
|
|
}
|
|
}
|
|
|
|
if( hChild ) DestroyWindow( hChild );
|
|
if( hwndIE ) DestroyWindow( hwndIE );
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CloseWebBrowser( IWebBrowser2* pWebBrowser )
|
|
{
|
|
HWND hMoveWnd = NULL;
|
|
for( unsigned int i(0); g_vWebBrowserInfoList.size()>i; i++ )
|
|
{
|
|
if( g_vWebBrowserInfoList[i].pWebBrowser == pWebBrowser )
|
|
{
|
|
hMoveWnd = g_vWebBrowserInfoList[i].hWnd;
|
|
|
|
g_vWebBrowserInfoList[i].pWebBrowser->Stop();
|
|
g_vWebBrowserInfoList[i].pWebBrowser->Quit();
|
|
DestroyWindow( g_vWebBrowserInfoList[i].hWndIE );
|
|
DestroyWindow( g_vWebBrowserInfoList[i].hWnd );
|
|
|
|
g_vWebBrowserInfoList.erase( g_vWebBrowserInfoList.begin()+i );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetWebBrowserMovePos( IWebBrowser2* pWebBrowser, int nX, int nY )
|
|
{
|
|
HWND hMoveWnd = NULL;
|
|
for( unsigned int i(0); g_vWebBrowserInfoList.size()>i; i++ )
|
|
{
|
|
if( g_vWebBrowserInfoList[i].pWebBrowser == pWebBrowser )
|
|
{
|
|
hMoveWnd = g_vWebBrowserInfoList[i].hWnd;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( hMoveWnd )
|
|
SetWindowPos(hMoveWnd,NULL,nX,nY,0,0,SWP_NOSIZE);
|
|
}
|
|
|
|
//가운데 위치
|
|
void SetWebBrowserCenterPos( IWebBrowser2* pWebBrowser, int nW, int nH )
|
|
{
|
|
HWND hMoveWnd = NULL;
|
|
for( unsigned int i(0); g_vWebBrowserInfoList.size()>i; i++ )
|
|
{
|
|
if( g_vWebBrowserInfoList[i].pWebBrowser == pWebBrowser )
|
|
{
|
|
hMoveWnd = g_vWebBrowserInfoList[i].hWnd;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( hMoveWnd )
|
|
{
|
|
HWND hWnd=g_hWnd;
|
|
RECT rcWnd, rWnd;
|
|
GetClientRect(hWnd, &rcWnd);
|
|
GetWindowRect(hWnd, &rWnd);
|
|
|
|
rcWnd.left = 0;
|
|
rcWnd.top = 0;
|
|
|
|
int nAppWidth = rcWnd.right - rcWnd.left;
|
|
int nAppHeight = rcWnd.bottom - rcWnd.top;
|
|
|
|
int nCenterX = (nAppWidth - nW)/2;
|
|
int nCenterY = (nAppHeight - nH)/2;
|
|
|
|
if( hMoveWnd )
|
|
SetWindowPos(hMoveWnd,NULL,nCenterX+2,nCenterY,0,0,SWP_NOSIZE);
|
|
}
|
|
}
|
|
|
|
void SetWebBrowserVisible( IWebBrowser2* pWebBrowser, bool bVisible )
|
|
{
|
|
if( bVisible )
|
|
{
|
|
g_IsShowWebBrowser = VARIANT_BOOL(true);
|
|
}
|
|
else
|
|
{
|
|
g_IsShowWebBrowser = VARIANT_BOOL(false);
|
|
}
|
|
|
|
g_IsShowWebBrowserChanged = true;
|
|
if( pWebBrowser ) pWebBrowser->put_Visible( g_IsShowWebBrowser );
|
|
|
|
if( !g_IsShowWebBrowser )
|
|
::SetFocus( g_hWnd );
|
|
}
|
|
|
|
void SetVisibleNavigate( bool bVisible )
|
|
{
|
|
if( !g_pWebBrowser ) return;
|
|
|
|
if( bVisible )
|
|
{
|
|
g_IsShowWebBrowser = VARIANT_BOOL(true);
|
|
g_pWebBrowser->put_Visible( g_IsShowWebBrowser );
|
|
}
|
|
else
|
|
{
|
|
g_pWebBrowser->put_Visible( g_IsShowWebBrowser );
|
|
CloseWebBrowser( g_pWebBrowser );
|
|
|
|
if( g_vWebBrowserInfoList.empty() )
|
|
g_IsShowWebBrowser = VARIANT_BOOL(false);
|
|
|
|
g_pWebBrowser = NULL;
|
|
}
|
|
|
|
g_IsShowWebBrowserChanged = true;
|
|
|
|
if( !g_IsShowWebBrowser )
|
|
::SetFocus( g_hWnd );
|
|
}
|
|
|
|
void CurURLRefresh( IWebBrowser2* pWebBrowser )
|
|
{
|
|
if( pWebBrowser )
|
|
{
|
|
BSTR url;
|
|
if( pWebBrowser->get_LocationURL( &url ) == S_OK )
|
|
{
|
|
/* static _variant_t vars = _variant_t( "http://rion:8080/client/guild/leader.aspx" );
|
|
_variant_t varurl = _variant_t(url);
|
|
|
|
if( varurl == vars )
|
|
return;*/
|
|
|
|
char urlName [ 1024 ];
|
|
//AziaMafia Fix CODEPAGE CP_UTF8 // CP_ACP
|
|
WideCharToMultiByte (CP_ACP, 0, url, -1, urlName, 1024, NULL, NULL );
|
|
SysFreeString ( url );
|
|
|
|
if ( strstr( urlName, "leader.aspx" ) )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
//BSTR url;
|
|
//HRESULT hr = pWebBrowser->get_LocationURL( &url );
|
|
//if( hr == S_OK )
|
|
//{
|
|
// _variant_t vars, null;
|
|
// VariantInit(&vars);
|
|
// VariantInit(&null);
|
|
// null.vt = VT_NULL;
|
|
// vars = _variant_t(url);
|
|
|
|
// pWebBrowser->Navigate2(&vars,&null,&null,&null,&null);
|
|
|
|
// VariantClear(&vars);
|
|
// VariantClear(&null);
|
|
|
|
// SysFreeString( url );
|
|
//}
|
|
|
|
pWebBrowser->Refresh();
|
|
}
|
|
}
|
|
|
|
void SetURLNavigate( IWebBrowser2* pWebBrowser, const char * pURL )
|
|
{
|
|
if( pWebBrowser && pURL )
|
|
{
|
|
//Google Page
|
|
_variant_t vars, null;
|
|
VariantInit(&vars);
|
|
VariantInit(&null);
|
|
null.vt = VT_NULL;
|
|
|
|
vars = _variant_t(pURL);
|
|
pWebBrowser->Navigate2(&vars,&null,&null,&null,&null);
|
|
VariantClear(&vars);
|
|
VariantClear(&null);
|
|
}
|
|
}
|
|
|
|
void SetNavigate( const char * pURL, bool bVisible, int nAddWidth, int nAddHeight )
|
|
{
|
|
if( g_pWebBrowser == NULL )
|
|
{
|
|
g_pWebBrowser = GetWebBrowser( g_Cash_url.x, g_Cash_url.y, nAddWidth, nAddHeight );
|
|
if( g_pWebBrowser )
|
|
{
|
|
HRESULT hrGetHWN = g_pWebBrowser->get_HWND( (long*)&g_hWnd_Explorer );
|
|
if( hrGetHWN == S_OK )
|
|
{
|
|
SetWebWindowStyle( g_hWnd_Explorer );
|
|
}
|
|
InitWebBrowser( g_pWebBrowser );
|
|
}
|
|
}
|
|
|
|
if( g_pWebBrowser && bVisible )
|
|
{
|
|
//Google Page
|
|
_variant_t vars, null;
|
|
VariantInit(&vars);
|
|
VariantInit(&null);
|
|
null.vt = VT_NULL;
|
|
|
|
vars = _variant_t(pURL);
|
|
g_pWebBrowser->Navigate2(&vars,&null,&null,&null,&null);
|
|
VariantClear(&vars);
|
|
VariantClear(&null);
|
|
}
|
|
|
|
SetVisibleNavigate( bVisible );
|
|
}
|
|
|
|
//INT_PTR CALLBACK ExplorerDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
//{
|
|
// switch( uMsg )
|
|
// {
|
|
// case WM_COMMAND :
|
|
// {
|
|
// switch ( LOWORD( wParam ) )
|
|
// {
|
|
// case IDC_BUTTON1:
|
|
// { //Close
|
|
// if( g_pWebBrowser )
|
|
// {
|
|
// VARIANT_BOOL pBool=false; //The browser is invisible
|
|
// g_pWebBrowser->put_Visible( pBool );
|
|
// }
|
|
// ShowWindow( hwndDlg, SW_HIDE );
|
|
// }
|
|
// break;
|
|
// case IDC_BUTTON2:
|
|
// { //Shop : Item
|
|
// SetNavigate( "http://itemshop.rappelz.com/" );
|
|
// }
|
|
// break;
|
|
// case IDC_BUTTON3:
|
|
// { //Cache 충전
|
|
// SetNavigate( "http://itemshop.rappelz.com/" );
|
|
// }
|
|
// break;
|
|
// }
|
|
// }
|
|
// break;
|
|
// }
|
|
//
|
|
// return DefWindowProc(hwndDlg, uMsg, wParam, lParam);
|
|
//}
|
|
|
|
void InitScript();
|
|
|
|
//XCriticalSection xCS;
|
|
|
|
//#define _WEB_DISP_MODE
|
|
|
|
#define _EXCEPTION_PROCESS
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void WINAPI UserFunc( HANDLE hFile )
|
|
{
|
|
#ifdef _WEB_DISP_MODE
|
|
RestoreDisplay(); //강제 종료시 복구
|
|
#endif
|
|
|
|
#ifdef _HACK_SHIELD_
|
|
if( g_bStartingHSService ) StopHackShieldService();
|
|
#endif
|
|
|
|
#ifdef _EXCEPTION_PROCESS
|
|
if( IDYES == MessageBox( g_hWnd, S( 828 ), "Rappelz-Client error", MB_YESNO ) )
|
|
{
|
|
XModuleInfo cModuleInfo;
|
|
cModuleInfo.Load( ::GetCurrentProcess() );
|
|
char szMyVersion[64] = "";
|
|
const WORD* pFileVerion = cModuleInfo.FileVersion();
|
|
s_sprintf( szMyVersion, _countof( szMyVersion ), "%d.%d.%d.%d", pFileVerion[0], pFileVerion[1], pFileVerion[2], pFileVerion[3] );
|
|
|
|
std::string strErr;
|
|
|
|
std::string strPost;
|
|
|
|
strPost += "exception=";
|
|
strErr = XSEH::GetExceptionInfo();
|
|
nsl::replace( &strErr, "=", "-" );
|
|
nsl::replace( &strErr, "&", "." );
|
|
strPost += strErr;
|
|
strPost += "&";
|
|
|
|
strPost += "address=";
|
|
strErr = XSEH::GetExceptionAddress();
|
|
nsl::replace( &strErr, "=", "-" );
|
|
nsl::replace( &strErr, "&", "." );
|
|
strPost += strErr;
|
|
strPost += "&";
|
|
|
|
strPost += "detail=";
|
|
strErr = "Client Version: ";
|
|
strErr += "v";
|
|
strErr += szMyVersion;
|
|
strErr += XSEH::GetExceptionDetail();
|
|
nsl::replace( &strErr, "=", "-" );
|
|
nsl::replace( &strErr, "&", "." );
|
|
strPost += strErr;
|
|
|
|
strErr = "SLog:";
|
|
strErr += g_strDebugInfo_SUN;
|
|
strPost += strErr;
|
|
|
|
/// 2010.11.30 - prodongi
|
|
//XInternet::QueryHTTPRequest( "http://www.rappelz.com/clientErrLog.aspx", NULL, 0, strPost.c_str() );
|
|
//XInternet::QueryHTTPRequest( "http://api.rappelz-equation.fr/api/game/exception", NULL, 0, strPost.c_str() );
|
|
|
|
// Fraun 7/11/2025 nullrouting error report, to avoid sending extra info to galalab; changing it directly to rappelz.log
|
|
XInternet::QueryHTTPRequest("http://127.0.0.1/nothing", NULL, 0, strPost.c_str());
|
|
SLOG(strPost.c_str());
|
|
}
|
|
|
|
if( g_bCleanupCOM )
|
|
CoUninitialize();
|
|
#endif
|
|
// WriteFile( hFile, "다운 된다. 대략 안 좋다~~~", (DWORD)strlen("다운 된다. 대략 안 좋다~~~"), &tmp, NULL );
|
|
}
|
|
|
|
bool IsFile( const char *szFileName )
|
|
{
|
|
FILE* pack_fp = fopen( szFileName, "rb" );
|
|
if( pack_fp )
|
|
{
|
|
fclose(pack_fp);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/// 2010.11.03 Retrieve the GameGuard INI file for either the live server or test server
|
|
/// First, try to find the file for the live server. If not found, look for the test server file.
|
|
/// If neither is found, return the live server file, because CNPGameLib handles the error.
|
|
char const* getNProtectIniFileName(char const* oriFileName)
|
|
{
|
|
static std::string str;
|
|
|
|
// Live server
|
|
str = oriFileName;
|
|
str += ".ini";
|
|
if (IsFile(str.c_str()))
|
|
{
|
|
return oriFileName;
|
|
}
|
|
// 테섭
|
|
str = oriFileName;
|
|
str += "Test.ini";
|
|
if (IsFile(str.c_str()))
|
|
{
|
|
str = oriFileName;
|
|
str += "Test";
|
|
return str.c_str();
|
|
}
|
|
|
|
return oriFileName;
|
|
}
|
|
|
|
|
|
bool CheckAuthServerIP( const std::string& strAuthServerAddress )
|
|
{
|
|
if( strAuthServerAddress.empty() == true )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (strAuthServerAddress == "127.0.0.1") return true; // Alucard machine
|
|
|
|
XNetworkUtil::XNetworkInitHelper netInitHelper;
|
|
|
|
// Change the authentication server address to an IP
|
|
XAddr addr( strAuthServerAddress.c_str(), 0 );
|
|
struct sockaddr_in addr_in;
|
|
if( XNetworkUtil::ConvAddr( addr, addr_in ) == false )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if( XNetworkUtil::ConvAddr( addr_in, addr ) == false )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::string strAuthIP = addr.GetAddr();
|
|
|
|
// Fraun IP set 7/20/2025
|
|
ENV().Set( "auth_ip", strAuthIP );
|
|
std::set<std::string> authIPsSet;
|
|
authIPsSet.emplace("127.0.0.1"); // Localhost
|
|
|
|
// Only IPs from authIPsSet and all local routing IPs (Starts from 192.168.xxx.xxx) are allowed
|
|
if ( (authIPsSet.find(strAuthIP) != authIPsSet.end()) || strAuthIP.rfind("192.168.", 0) == 0 )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool InitResource()
|
|
{
|
|
// 2011.06.15 Dual client setup - prodongi
|
|
std::string default_encoding = ENV().GetString( "locale", "CP949" );
|
|
nsl::uni::init( default_encoding.c_str() );
|
|
nsl::uni::set_resource_encoding( ENV().GetString( "res_locale", default_encoding.c_str()).c_str());
|
|
|
|
bool bExistOldPackingFile = false;
|
|
bool bExistNewPackingFile1 = false;
|
|
bExistOldPackingFile = IsFile( "data.dat" );
|
|
bExistNewPackingFile1 = IsFile( "data.000" );
|
|
|
|
if( bExistNewPackingFile1 == false /*&& bExistNewPackingFile2 == false*/ )
|
|
return false;
|
|
|
|
#ifdef _HACK_SHIELD_
|
|
if( ENV().IsExist( "ahnhs" ) ) g_bAhnHS = true;
|
|
#endif
|
|
if( ENV().IsExist( "winfps" ) ) g_bWindowFPS = true;
|
|
if( ENV().IsExist( "string_log" ) ) g_bLogStringRate = true;
|
|
if( ENV().IsExist( "font_ratio" ) ) KTextRender::SetFreeTypeRatio( ENV().GetFloat( "font_ratio", 1.3f ) );
|
|
|
|
KTextParser::SetUseWordWrap( true );
|
|
|
|
KTextRender::GenerateRandColor();
|
|
|
|
// Make text consisting of only English/Numbers larger in Chinese... (Temporary until the font is found.) Southeast Asia exception
|
|
if( stricmp( ENV().GetString( "locale" ).c_str(), "BIG5" ) == 0 &&
|
|
stricmp( ENV().GetString( "country" ).c_str(), "MASG" ) != 0 )
|
|
{
|
|
KTextRender::SetFreeTypeYOffset( -1 );
|
|
KTextRender::EnableEnglishGrow();
|
|
}
|
|
|
|
// Second resource
|
|
if( ENV().IsExist( "secondres" ) )
|
|
{
|
|
static KRealFileSystem _secondRes;
|
|
std::string strSecond = ENV().GetString( "secondres" ).c_str();
|
|
|
|
XFileUtil::NomalizeDirectoryName( strSecond );
|
|
|
|
_secondRes.Init( strSecond.c_str() );
|
|
KFileManager::Instance().AddResourceSource( &_secondRes );
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
// }
|
|
// { 웹서버 주소
|
|
// if( ENV().IsExist( "web" ) )
|
|
// {
|
|
// static KRealFileSystem _web;
|
|
// std::string strWeb = ENV().GetString( "web" ).c_str();
|
|
//
|
|
// XFileUtil::NomalizeDirectoryName( strWeb );
|
|
//
|
|
// _web.Init( strWeb.c_str() );
|
|
// KFileManager::Instance().AddResourceSource( &_web );
|
|
// }
|
|
// }
|
|
#endif
|
|
// }
|
|
{ //서비스 지역
|
|
if( ENV().IsExist( "country" ) )
|
|
{
|
|
static KRealFileSystem _web;
|
|
std::string strWeb = ENV().GetString( "country" ).c_str();
|
|
|
|
XFileUtil::NomalizeDirectoryName( strWeb );
|
|
|
|
_web.Init( strWeb.c_str() );
|
|
KFileManager::Instance().AddResourceSource( &_web );
|
|
}
|
|
}
|
|
// { 개발용 메인 리소스
|
|
if( ENV().IsExist( "notenc" ) )
|
|
{
|
|
static KRealFileSystem _mainRes;
|
|
_mainRes.Init( ENV().GetString( "res", "./Resource/" ).c_str() );
|
|
KFileManager::Instance().AddResourceSource( &_mainRes );
|
|
}
|
|
// }
|
|
if( ENV().IsExist( "tserver" ) )
|
|
{
|
|
static KRealFileSystem _server;
|
|
std::string strServer = ENV().GetString( "tserver" ).c_str();
|
|
_server.Init( strServer.c_str() );
|
|
KFileManager::Instance().AddResourceSource( &_server );
|
|
}
|
|
|
|
if( ENV().IsExist( "chat_mode" ) )
|
|
{
|
|
static KRealFileSystem _chat;
|
|
std::string strChatMode = ENV().GetString( "chat_mode" ).c_str();
|
|
_chat.Init( strChatMode.c_str() );
|
|
KFileManager::Instance().AddResourceSource( &_chat );
|
|
}
|
|
|
|
struct _NEW_CIPHER : KFileSystemWrapper::NameCipher
|
|
{
|
|
virtual bool is_encoded_file_name( std::string & strFileName ) { return KFileNameCipher::IsEncodedName( strFileName ); };
|
|
virtual void encode_file_name( std::string & strFileName ) { KFileNameCipher::EncodeFileName( strFileName ); };
|
|
virtual void decode_file_name( std::string & strFileName ) { KFileNameCipher::DecodeFileName( strFileName ); };
|
|
}; static _NEW_CIPHER _new_cipher;
|
|
|
|
if( !ENV().IsExist( "notenc" ) )
|
|
{
|
|
static KRealFileSystem _encodedMainRes;
|
|
static KFileSystemWrapper _newEncodedFS;
|
|
_encodedMainRes.Init( ENV().GetString( "res", "./Resource/" ).c_str() );
|
|
_newEncodedFS.Init( &_encodedMainRes, &_new_cipher, false );
|
|
KFileManager::Instance().AddResourceSource( &_newEncodedFS );
|
|
}
|
|
|
|
// { 신버젼 패킹 파일
|
|
if( bExistNewPackingFile1 )
|
|
{
|
|
static KPackingFileSystem _newPacking( 8, 3, true );
|
|
static KFileSystemWrapper _packedEncodedFS;
|
|
_newPacking.Init( "data.000", "data" );
|
|
_packedEncodedFS.Init( &_newPacking, &_new_cipher, true, true );
|
|
KFileManager::Instance().AddResourceSource( &_packedEncodedFS );
|
|
}
|
|
|
|
if(GameRule::GetCurrentLocalBitSet() == GameRule::LOCAL_BITSET::JP)
|
|
{
|
|
g_Help_url.x = 900;
|
|
g_Help_url.y = 700;
|
|
}
|
|
else if(GameRule::GetCurrentLocalBitSet() == GameRule::LOCAL_BITSET::CN)
|
|
{
|
|
g_Help_url.x = 620;
|
|
g_Help_url.y = 633;
|
|
}
|
|
else
|
|
{
|
|
g_Help_url.x = 900;
|
|
g_Help_url.y = 670;
|
|
}
|
|
if(GameRule::GetCurrentLocalBitSet() == GameRule::LOCAL_BITSET::KR)
|
|
{
|
|
g_Cash_url.x = 710;
|
|
g_Cash_url.y = 654;
|
|
g_Cash_add_url.x = 44;
|
|
g_Cash_add_url.y = 0;
|
|
}
|
|
else if(GameRule::GetCurrentLocalBitSet() == GameRule::LOCAL_BITSET::CN)
|
|
{
|
|
g_Cash_url.x = 620;
|
|
g_Cash_url.y = 634;
|
|
g_Cash_add_url.x = 44;
|
|
g_Cash_add_url.y = 0;
|
|
}
|
|
else if(GameRule::GetCurrentLocalBitSet() == GameRule::LOCAL_BITSET::JP)
|
|
{
|
|
g_Cash_url.x = 900;
|
|
g_Cash_url.y = 700;
|
|
g_Cash_add_url.x = 44;
|
|
g_Cash_add_url.y = 0;
|
|
}
|
|
else
|
|
{
|
|
g_Cash_url.x = 620;
|
|
g_Cash_url.y = 634;
|
|
g_Cash_add_url.x = 0;
|
|
g_Cash_add_url.y = 0;
|
|
}
|
|
|
|
if( ENV().IsExist( "help_url_w" ) ) g_Help_url.x = ENV().GetInt( "help_url_w", g_Help_url.x );
|
|
if( ENV().IsExist( "help_url_h" ) ) g_Help_url.y = ENV().GetInt( "help_url_h", g_Help_url.y );
|
|
if( ENV().IsExist( "cash_url_w" ) ) g_Cash_url.x = ENV().GetInt( "cash_url_w", g_Cash_url.x );
|
|
if( ENV().IsExist( "cash_url_h" ) ) g_Cash_url.y = ENV().GetInt( "cash_url_h", g_Cash_url.y );
|
|
if( ENV().IsExist( "cash_add_url_w" ) ) g_Cash_add_url.x = ENV().GetInt( "cash_add_url_w", g_Cash_add_url.x );
|
|
if( ENV().IsExist( "cash_add_url_h" ) ) g_Cash_add_url.y = ENV().GetInt( "cash_add_url_h", g_Cash_add_url.y );
|
|
|
|
|
|
// Preload some RDBs
|
|
::GetStringDB();
|
|
::GetSkillDB();
|
|
::GetSkillStageDB();
|
|
::GetSkillTreeDisplayDB();
|
|
::GetCharacterMotionEventDB();
|
|
::GetMotionEventHanderDB();
|
|
::GetMotionFxSetDB();
|
|
::GetMotionSetDB();
|
|
::GetTenacityDB();
|
|
::GetLocalCommandDB();
|
|
// 2010.05.07 - prodongi
|
|
::GetCreatureEnhanceDB();
|
|
::GetTitleDB();
|
|
#ifdef _EDIT_ENVIRONMENT_
|
|
::GetEditParameterDialog();
|
|
#endif
|
|
KSpriteManager::GetManager()->LoadSpriteSet("ui_frame.spr");
|
|
|
|
//KStream *pTp = KFileManager::Instance().CreateStreamFromResource( "m001_003.nfs" );
|
|
//KFileStream tmp( "temp.tmp", KFileStream::wronly );
|
|
//char buf[65535];
|
|
//pTp->Read( buf, pTp->GetLength() );
|
|
//tmp.Write( buf, pTp->GetLength() );
|
|
|
|
// UI caption handler
|
|
static struct myUICaptionHandler : public KUIWnd::CaptionHandler
|
|
{
|
|
virtual void onSetCaption( std::string & caption )
|
|
{
|
|
if( caption.empty() ) return;
|
|
|
|
caption = GetStringDB().GetString( caption.c_str() );
|
|
|
|
std::vector< std::string > vList;
|
|
while( nsl::regex::match( "#@([0-9]+)@#", caption.c_str(), &vList ) )
|
|
{
|
|
nsl::replace( &caption, vList[0].c_str(), GetStringDB().GetString(atoi(vList[1].c_str() ) ) );
|
|
vList.clear();
|
|
}
|
|
}
|
|
} _handler;
|
|
|
|
KUIWnd::SetCaptionHandler( &_handler );
|
|
|
|
return true;
|
|
}
|
|
|
|
#include <toolkit/XStringUtil.h>
|
|
|
|
volatile int m_nDummyInt = 0;
|
|
|
|
// For now, only handle two
|
|
const short c_nFontTagCnt = 68;
|
|
const char* g_szFontTag[] =
|
|
{
|
|
"<FONT:>" ,//01
|
|
"<#" ,//02
|
|
"<BR>" ,//03
|
|
"<P>" ,//04
|
|
"<$L>" ,//05
|
|
"<$>" ,//06
|
|
"<B>" ,//07
|
|
"</B>" ,//08
|
|
"<U>" ,//09
|
|
"</U>" ,//10
|
|
"<STRIKE>" ,//11
|
|
"</STRIKE>",//12
|
|
"<INV>" ,//13
|
|
"</INV>" ,//14
|
|
"<SHD>" ,//15
|
|
"</SHD>" ,//16
|
|
"<%%>" ,//17
|
|
"<%>" ,//18
|
|
"<SIZE:>" ,//19
|
|
"<LEFT>" ,//20
|
|
"<TOP>" ,//21
|
|
"<RIGHT>" ,//22
|
|
"<BOTTOM>" ,//23
|
|
"<HCENTER>",//24
|
|
"<VCENTER>",//25
|
|
"<OUT>" ,//26
|
|
"</OUT>" ,//27
|
|
"<GLOW>" ,//28
|
|
"</GLOW>" ,//29
|
|
"<SHADOW>" ,//30
|
|
"</SHADOW>",//31
|
|
"<@>" ,//32
|
|
"<2XGLOW>" ,//33
|
|
"</2XGLOW>",//34
|
|
"<OFFSET>" ,//35
|
|
"<size:>" ,//36
|
|
|
|
"<font:>" ,//37
|
|
"<p>" ,//38
|
|
"<$l>" ,//39
|
|
"<$>" ,//40
|
|
"<b>" ,//41
|
|
"</b>" ,//42
|
|
"<u>" ,//43
|
|
"</u>" ,//44
|
|
"<strike>" ,//45
|
|
"</strike>",//46
|
|
"<inv>" ,//47
|
|
"</inv>" ,//48
|
|
"<shd>" ,//49
|
|
"</shd>" ,//50
|
|
"<left>" ,//51
|
|
"<top>" ,//52
|
|
"<right>" ,//53
|
|
"<bottom>" ,//54
|
|
"<hcenter>",//55
|
|
"<vcenter>",//56
|
|
"<out>" ,//57
|
|
"</out>" ,//58
|
|
"<glow>" ,//59
|
|
"</glow>" ,//60
|
|
"<shadow>" ,//61
|
|
"</shadow>",//62
|
|
"<2xglow>" ,//63
|
|
"</2xglow>",//64
|
|
"<offset>" ,//65
|
|
|
|
"<bR>" ,//66
|
|
"<Br>" ,//67
|
|
"<br>" ,//68
|
|
};
|
|
|
|
const short c_nEmoticonCnt = 228;
|
|
|
|
const char* g_szAniName[] =
|
|
{
|
|
// 2010.10.04 - prodongi
|
|
/*
|
|
"static_common_rank00",
|
|
"static_common_rank01",
|
|
"static_common_rank02",
|
|
"static_common_rank03",
|
|
"static_common_rank04",
|
|
"static_common_rank05", //아이템 랭크
|
|
"static_common_rank06", // #2.1.13
|
|
*/
|
|
"common_mark_rank_player01",
|
|
"common_mark_rank_player02",
|
|
"common_mark_rank_player03",
|
|
"common_mark_rank_player04",
|
|
"common_mark_rank_player05",
|
|
"common_mark_rank_player06", //아이템 랭크
|
|
"common_mark_rank_player07", // #2.1.13
|
|
|
|
"static_common_setitem00_able", // #2.1.2.6.1
|
|
"static_common_setitem00_disable",
|
|
"static_common_setitem01_able",
|
|
"static_common_setitem01_disable",
|
|
"static_common_setitem02_able",
|
|
"static_common_setitem02_disable",
|
|
"static_common_setitem_plus",
|
|
|
|
"static_creature_star00",
|
|
"static_creature_star01",
|
|
"static_creature_star02",//크리쳐 별
|
|
|
|
// 2010.08.26 - prodongi
|
|
/*
|
|
"static_creature_rank00",
|
|
"static_creature_rank01",
|
|
"static_creature_rank02",
|
|
"static_creature_rank03",
|
|
"static_creature_rank04",
|
|
"static_creature_rank05",//크리쳐 랭크
|
|
*/
|
|
// 2010.10.04 - prodongi
|
|
/*
|
|
"game_creature_mark_rank00",
|
|
"game_creature_mark_rank01",
|
|
"game_creature_mark_rank02",
|
|
"game_creature_mark_rank03",
|
|
"game_creature_mark_rank04",
|
|
"game_creature_mark_rank05",//크리쳐 랭크
|
|
*/
|
|
"game_creature_mark_rank01",
|
|
"game_creature_mark_rank02",
|
|
"game_creature_mark_rank03",
|
|
"game_creature_mark_rank04",
|
|
"game_creature_mark_rank05",
|
|
"game_creature_mark_rank06",//크리쳐 랭크
|
|
|
|
//AziaMAfia Pet Rarity
|
|
"game_creature_mark_rank07",
|
|
"game_creature_mark_rank08",
|
|
"game_creature_mark_rank09",
|
|
"game_creature_mark_rank10",
|
|
"game_creature_mark_rank11",
|
|
|
|
"static_tooltip_symbolnormal", //nomal
|
|
"static_tooltip_symbolfire", //fire
|
|
"static_tooltip_symbolwind", //wind
|
|
"static_tooltip_symbollightness", //light
|
|
"static_tooltip_symbolwater", //water
|
|
"static_tooltip_symbolearth", //earth
|
|
"static_tooltip_symboldarkness", //dark
|
|
|
|
"icon_soulstone_agi_basic1_s",
|
|
"icon_soulstone_agi_basic2_s",
|
|
"icon_soulstone_agi_basic3_s",
|
|
"icon_soulstone_agi_basic4_s",
|
|
"icon_soulstone_agi_basic5_s",
|
|
"icon_soulstone_agi_basic6_s",
|
|
"icon_soulstone_agi_basic7_s",
|
|
"icon_soulstone_dex_basic1_s",
|
|
"icon_soulstone_dex_basic2_s",
|
|
"icon_soulstone_dex_basic3_s",
|
|
"icon_soulstone_dex_basic4_s",
|
|
"icon_soulstone_dex_basic5_s",
|
|
"icon_soulstone_dex_basic6_s",
|
|
"icon_soulstone_dex_basic7_s",
|
|
"icon_soulstone_int_basic1_s",
|
|
"icon_soulstone_int_basic2_s",
|
|
"icon_soulstone_int_basic3_s",
|
|
"icon_soulstone_int_basic4_s",
|
|
"icon_soulstone_int_basic5_s",
|
|
"icon_soulstone_int_basic6_s",
|
|
"icon_soulstone_int_basic7_s",
|
|
"icon_soulstone_men_basic1_s",
|
|
"icon_soulstone_men_basic2_s",
|
|
"icon_soulstone_men_basic3_s",
|
|
"icon_soulstone_men_basic4_s",
|
|
"icon_soulstone_men_basic5_s",
|
|
"icon_soulstone_men_basic6_s",
|
|
"icon_soulstone_men_basic7_s",
|
|
"icon_soulstone_str_basic1_s",
|
|
"icon_soulstone_str_basic2_s",
|
|
"icon_soulstone_str_basic3_s",
|
|
"icon_soulstone_str_basic4_s",
|
|
"icon_soulstone_str_basic5_s",
|
|
"icon_soulstone_str_basic6_s",
|
|
"icon_soulstone_str_basic7_s",
|
|
"icon_soulstone_vit_basic1_s",
|
|
"icon_soulstone_vit_basic2_s",
|
|
"icon_soulstone_vit_basic3_s",
|
|
"icon_soulstone_vit_basic4_s",
|
|
"icon_soulstone_vit_basic5_s",
|
|
"icon_soulstone_vit_basic6_s",
|
|
"icon_soulstone_vit_basic7_s",
|
|
|
|
"icon_soulstone_str_rare1_s",
|
|
"icon_soulstone_str_rare2_s",
|
|
"icon_soulstone_str_rare3_s",
|
|
"icon_soulstone_str_rare4_s",
|
|
"icon_soulstone_str_rare5_s",
|
|
"icon_soulstone_str_rare6_s",
|
|
"icon_soulstone_str_rare7_s",
|
|
|
|
"icon_soulstone_str_epic1_s",
|
|
"icon_soulstone_str_epic2_s",
|
|
"icon_soulstone_str_epic3_s",
|
|
"icon_soulstone_str_epic4_s",
|
|
"icon_soulstone_str_epic5_s",
|
|
"icon_soulstone_str_epic6_s",
|
|
"icon_soulstone_str_epic7_s",
|
|
|
|
"icon_soulstone_vit_rare1_s",
|
|
"icon_soulstone_vit_rare2_s",
|
|
"icon_soulstone_vit_rare3_s",
|
|
"icon_soulstone_vit_rare4_s",
|
|
"icon_soulstone_vit_rare5_s",
|
|
"icon_soulstone_vit_rare6_s",
|
|
"icon_soulstone_vit_rare7_s",
|
|
|
|
"icon_soulstone_vit_epic1_s",
|
|
"icon_soulstone_vit_epic2_s",
|
|
"icon_soulstone_vit_epic3_s",
|
|
"icon_soulstone_vit_epic4_s",
|
|
"icon_soulstone_vit_epic5_s",
|
|
"icon_soulstone_vit_epic6_s",
|
|
"icon_soulstone_vit_epic7_s",
|
|
|
|
"icon_soulstone_dex_rare1_s",
|
|
"icon_soulstone_dex_rare2_s",
|
|
"icon_soulstone_dex_rare3_s",
|
|
"icon_soulstone_dex_rare4_s",
|
|
"icon_soulstone_dex_rare5_s",
|
|
"icon_soulstone_dex_rare6_s",
|
|
"icon_soulstone_dex_rare7_s",
|
|
|
|
"icon_soulstone_dex_epic1_s",
|
|
"icon_soulstone_dex_epic2_s",
|
|
"icon_soulstone_dex_epic3_s",
|
|
"icon_soulstone_dex_epic4_s",
|
|
"icon_soulstone_dex_epic5_s",
|
|
"icon_soulstone_dex_epic6_s",
|
|
"icon_soulstone_dex_epic7_s",
|
|
|
|
"icon_soulstone_agi_rare1_s",
|
|
"icon_soulstone_agi_rare2_s",
|
|
"icon_soulstone_agi_rare3_s",
|
|
"icon_soulstone_agi_rare4_s",
|
|
"icon_soulstone_agi_rare5_s",
|
|
"icon_soulstone_agi_rare6_s",
|
|
"icon_soulstone_agi_rare7_s",
|
|
|
|
"icon_soulstone_agi_epic1_s",
|
|
"icon_soulstone_agi_epic2_s",
|
|
"icon_soulstone_agi_epic3_s",
|
|
"icon_soulstone_agi_epic4_s",
|
|
"icon_soulstone_agi_epic5_s",
|
|
"icon_soulstone_agi_epic6_s",
|
|
"icon_soulstone_agi_epic7_s",
|
|
|
|
"icon_soulstone_int_rare1_s",
|
|
"icon_soulstone_int_rare2_s",
|
|
"icon_soulstone_int_rare3_s",
|
|
"icon_soulstone_int_rare4_s",
|
|
"icon_soulstone_int_rare5_s",
|
|
"icon_soulstone_int_rare6_s",
|
|
"icon_soulstone_int_rare7_s",
|
|
|
|
"icon_soulstone_int_epic1_s",
|
|
"icon_soulstone_int_epic2_s",
|
|
"icon_soulstone_int_epic3_s",
|
|
"icon_soulstone_int_epic4_s",
|
|
"icon_soulstone_int_epic5_s",
|
|
"icon_soulstone_int_epic6_s",
|
|
"icon_soulstone_int_epic7_s",
|
|
|
|
"icon_soulstone_men_rare1_s",
|
|
"icon_soulstone_men_rare2_s",
|
|
"icon_soulstone_men_rare3_s",
|
|
"icon_soulstone_men_rare4_s",
|
|
"icon_soulstone_men_rare5_s",
|
|
"icon_soulstone_men_rare6_s",
|
|
"icon_soulstone_men_rare7_s",
|
|
|
|
"icon_soulstone_men_epic1_s",
|
|
"icon_soulstone_men_epic2_s",
|
|
"icon_soulstone_men_epic3_s",
|
|
"icon_soulstone_men_epic4_s",
|
|
"icon_soulstone_men_epic5_s",
|
|
"icon_soulstone_men_epic6_s",
|
|
"icon_soulstone_men_epic7_s",
|
|
|
|
/// 2011.12.06 - prodongi
|
|
"icon_soulstone_agi_unique7_s",
|
|
"icon_soulstone_chaser_unique7_s",
|
|
"icon_soulstone_commerce_agi_unique7_s",
|
|
"icon_soulstone_commerce_chaser_unique7_s",
|
|
"icon_soulstone_commerce_dex_unique7_s",
|
|
"icon_soulstone_commerce_edge_unique7_s",
|
|
"icon_soulstone_commerce_energy_unique7_s",
|
|
"icon_soulstone_commerce_hunter_unique7_s",
|
|
"icon_soulstone_commerce_int_unique7_s",
|
|
"icon_soulstone_commerce_magical_unique7_s",
|
|
"icon_soulstone_commerce_men_unique7_s",
|
|
"icon_soulstone_commerce_pen_unique7_s",
|
|
"icon_soulstone_commerce_perfect_unique7_s",
|
|
"icon_soulstone_commerce_save_unique7_s",
|
|
"icon_soulstone_commerce_str_unique7_s",
|
|
"icon_soulstone_commerce_vit_unique7_s",
|
|
"icon_soulstone_dex_unique7_s",
|
|
"icon_soulstone_edge_unique7_s",
|
|
"icon_soulstone_energy_unique7_s",
|
|
"icon_soulstone_hunter_unique7_s",
|
|
"icon_soulstone_int_unique7_s",
|
|
"icon_soulstone_magical_unique7_s",
|
|
"icon_soulstone_men_unique7_s",
|
|
"icon_soulstone_pen_unique7_s",
|
|
"icon_soulstone_perfect_unique7_s",
|
|
"icon_soulstone_save_unique7_s",
|
|
"icon_soulstone_str_unique7_s",
|
|
"icon_soulstone_vit_unique7_s",
|
|
|
|
/// 2019.06.21 - G4ngor
|
|
"icon_soulstone_commerce_agi_unique8_s",
|
|
"icon_soulstone_commerce_chaser_unique8_s",
|
|
"icon_soulstone_commerce_dex_unique8_s",
|
|
"icon_soulstone_commerce_edge_unique8_s",
|
|
"icon_soulstone_commerce_energy_unique8_s",
|
|
"icon_soulstone_commerce_hunter_unique8_s",
|
|
"icon_soulstone_commerce_int_unique8_s",
|
|
"icon_soulstone_commerce_magical_unique8_s",
|
|
"icon_soulstone_commerce_men_unique8_s",
|
|
"icon_soulstone_commerce_pen_unique8_s",
|
|
"icon_soulstone_commerce_perfect_unique8_s",
|
|
"icon_soulstone_commerce_save_unique8_s",
|
|
"icon_soulstone_commerce_str_unique8_s",
|
|
"icon_soulstone_commerce_vit_unique8_s",
|
|
|
|
"static_common_socket_itemslot",
|
|
|
|
"icon_effectstone_fire_tooltip",
|
|
"icon_effectstone_wind_tooltip",
|
|
"icon_effectstone_light_tooltip",
|
|
"icon_effectstone_water_tooltip",
|
|
"icon_effectstone_earth_tooltip",
|
|
"icon_effectstone_dark_tooltip",
|
|
"icon_item_flystone_fire2_tooltip",
|
|
"icon_item_flystone_wind2_tooltip",
|
|
"icon_item_flystone_light2_tooltip",
|
|
"icon_item_flystone_water2_tooltip",
|
|
"icon_item_flystone_earth2_tooltip",
|
|
"icon_item_flystone_dark2_tooltip",
|
|
|
|
"common_mark_titanium_guild_notice",
|
|
"common_mark_titanium_guild_memo",
|
|
|
|
/// 2011.09.28 퀘스트 난이도 - prodongi
|
|
"common_mark_quest_difficulty_easy",
|
|
"common_mark_quest_difficulty_nomal",
|
|
"common_mark_quest_difficulty_hard",
|
|
|
|
"icon_soulstone8_normal_orange_s",
|
|
"icon_soulstone8_normal_purple_s",
|
|
"icon_soulstone8_normal_blue_s",
|
|
"icon_soulstone8_normal_sky_s",
|
|
"icon_soulstone8_normal_red_s",
|
|
"icon_soulstone8_normal_yellow_s",
|
|
"icon_soulstone8_normal_green_s",
|
|
|
|
};
|
|
|
|
// 나중에.. 디비에 넣거나, 테이블을 구성해야 한다.
|
|
// ex
|
|
// field : emoticon_id, emoticon_type, emoticon_filter, emoticon_flag(고정크기,원본크기등), emoticon_ani, emoticon_spr
|
|
const char* g_szEmoticonFilter[] =
|
|
{
|
|
"#@1R@#",
|
|
"#@2R@#",
|
|
"#@3R@#",
|
|
"#@4R@#",
|
|
"#@5R@#",
|
|
"#@6R@#",
|
|
"#@7R@#", // #2.1.13
|
|
|
|
"#@SETPART_ARMO_ON@#", // #2.1.2.6.1
|
|
"#@SETPART_ARMO_OFF@#",
|
|
"#@SETPART_HAND_ON@#",
|
|
"#@SETPART_HAND_OFF@#",
|
|
"#@SETPART_HELM_ON@#",
|
|
"#@SETPART_HELM_OFF@#",
|
|
"#@SETPART_PLUS@#",
|
|
|
|
"#@1S@#",
|
|
"#@2S@#",
|
|
"#@3S@#",
|
|
|
|
"#@C1R@#",
|
|
"#@C2R@#",
|
|
"#@C3R@#",
|
|
"#@C4R@#",
|
|
"#@C5R@#",
|
|
"#@C6R@#",
|
|
|
|
//AziaMAfia Pet Rarity
|
|
"#@C7R@#",
|
|
"#@C8R@#",
|
|
"#@C9R@#",
|
|
"#@C10R@#",
|
|
"#@C11R@#",
|
|
|
|
"#@NOMAL@#",
|
|
"#@FIRE@#",
|
|
"#@WIND@#",
|
|
"#@LIGHT@#",
|
|
"#@WATER@#",
|
|
"#@EARTH@#",
|
|
"#@DARK@#",
|
|
|
|
"#@agi_basic1@#",
|
|
"#@agi_basic2@#",
|
|
"#@agi_basic3@#",
|
|
"#@agi_basic4@#",
|
|
"#@agi_basic5@#",
|
|
"#@agi_basic6@#",
|
|
"#@agi_basic7@#",
|
|
"#@dex_basic1@#",
|
|
"#@dex_basic2@#",
|
|
"#@dex_basic3@#",
|
|
"#@dex_basic4@#",
|
|
"#@dex_basic5@#",
|
|
"#@dex_basic6@#",
|
|
"#@dex_basic7@#",
|
|
"#@int_basic1@#",
|
|
"#@int_basic2@#",
|
|
"#@int_basic3@#",
|
|
"#@int_basic4@#",
|
|
"#@int_basic5@#",
|
|
"#@int_basic6@#",
|
|
"#@int_basic7@#",
|
|
"#@men_basic1@#",
|
|
"#@men_basic2@#",
|
|
"#@men_basic3@#",
|
|
"#@men_basic4@#",
|
|
"#@men_basic5@#",
|
|
"#@men_basic6@#",
|
|
"#@men_basic7@#",
|
|
"#@str_basic1@#",
|
|
"#@str_basic2@#",
|
|
"#@str_basic3@#",
|
|
"#@str_basic4@#",
|
|
"#@str_basic5@#",
|
|
"#@str_basic6@#",
|
|
"#@str_basic7@#",
|
|
"#@vit_basic1@#",
|
|
"#@vit_basic2@#",
|
|
"#@vit_basic3@#",
|
|
"#@vit_basic4@#",
|
|
"#@vit_basic5@#",
|
|
"#@vit_basic6@#",
|
|
"#@vit_basic7@#",
|
|
|
|
"#@str_rare1@#",
|
|
"#@str_rare2@#",
|
|
"#@str_rare3@#",
|
|
"#@str_rare4@#",
|
|
"#@str_rare5@#",
|
|
"#@str_rare6@#",
|
|
"#@str_rare7@#",
|
|
|
|
"#@str_epic1@#",
|
|
"#@str_epic2@#",
|
|
"#@str_epic3@#",
|
|
"#@str_epic4@#",
|
|
"#@str_epic5@#",
|
|
"#@str_epic6@#",
|
|
"#@str_epic7@#",
|
|
|
|
"#@vit_rare1@#",
|
|
"#@vit_rare2@#",
|
|
"#@vit_rare3@#",
|
|
"#@vit_rare4@#",
|
|
"#@vit_rare5@#",
|
|
"#@vit_rare6@#",
|
|
"#@vit_rare7@#",
|
|
|
|
"#@vit_epic1@#",
|
|
"#@vit_epic2@#",
|
|
"#@vit_epic3@#",
|
|
"#@vit_epic4@#",
|
|
"#@vit_epic5@#",
|
|
"#@vit_epic6@#",
|
|
"#@vit_epic7@#",
|
|
|
|
"#@dex_rare1@#",
|
|
"#@dex_rare2@#",
|
|
"#@dex_rare3@#",
|
|
"#@dex_rare4@#",
|
|
"#@dex_rare5@#",
|
|
"#@dex_rare6@#",
|
|
"#@dex_rare7@#",
|
|
|
|
"#@dex_epic1@#",
|
|
"#@dex_epic2@#",
|
|
"#@dex_epic3@#",
|
|
"#@dex_epic4@#",
|
|
"#@dex_epic5@#",
|
|
"#@dex_epic6@#",
|
|
"#@dex_epic7@#",
|
|
|
|
"#@agi_rare1@#",
|
|
"#@agi_rare2@#",
|
|
"#@agi_rare3@#",
|
|
"#@agi_rare4@#",
|
|
"#@agi_rare5@#",
|
|
"#@agi_rare6@#",
|
|
"#@agi_rare7@#",
|
|
|
|
"#@agi_epic1@#",
|
|
"#@agi_epic2@#",
|
|
"#@agi_epic3@#",
|
|
"#@agi_epic4@#",
|
|
"#@agi_epic5@#",
|
|
"#@agi_epic6@#",
|
|
"#@agi_epic7@#",
|
|
|
|
"#@int_rare1@#",
|
|
"#@int_rare2@#",
|
|
"#@int_rare3@#",
|
|
"#@int_rare4@#",
|
|
"#@int_rare5@#",
|
|
"#@int_rare6@#",
|
|
"#@int_rare7@#",
|
|
|
|
"#@int_epic1@#",
|
|
"#@int_epic2@#",
|
|
"#@int_epic3@#",
|
|
"#@int_epic4@#",
|
|
"#@int_epic5@#",
|
|
"#@int_epic6@#",
|
|
"#@int_epic7@#",
|
|
|
|
"#@men_rare1@#",
|
|
"#@men_rare2@#",
|
|
"#@men_rare3@#",
|
|
"#@men_rare4@#",
|
|
"#@men_rare5@#",
|
|
"#@men_rare6@#",
|
|
"#@men_rare7@#",
|
|
|
|
"#@men_epic1@#",
|
|
"#@men_epic2@#",
|
|
"#@men_epic3@#",
|
|
"#@men_epic4@#",
|
|
"#@men_epic5@#",
|
|
"#@men_epic6@#",
|
|
"#@men_epic7@#",
|
|
|
|
/// 2011.12.06 - prodongi
|
|
"#@agi_unique7@#",
|
|
"#@chaser_unique7@#",
|
|
"#@commerce_agi_unique7@#",
|
|
"#@commerce_chaser_unique7@#",
|
|
"#@commerce_dex_unique7@#",
|
|
"#@commerce_edge_unique7@#",
|
|
"#@commerce_energy_unique7@#",
|
|
"#@commerce_hunter_unique7@#",
|
|
"#@commerce_int_unique7@#",
|
|
"#@commerce_magical_unique7@#",
|
|
"#@commerce_men_unique7@#",
|
|
"#@commerce_pen_unique7@#",
|
|
"#@commerce_perfect_unique7@#",
|
|
"#@commerce_save_unique7@#",
|
|
"#@commerce_str_unique7@#",
|
|
"#@commerce_vit_unique7@#",
|
|
"#@dex_unique7@#",
|
|
"#@edge_unique7@#",
|
|
"#@energy_unique7@#",
|
|
"#@hunter_unique7@#",
|
|
"#@int_unique7@#",
|
|
"#@magical_unique7@#",
|
|
"#@men_unique7@#",
|
|
"#@pen_unique7@#",
|
|
"#@perfect_unique7@#",
|
|
"#@save_unique7@#",
|
|
"#@str_unique7@#",
|
|
"#@vit_unique7@#",
|
|
|
|
/// Alucard
|
|
"#@commerce_agi_unique8@#",
|
|
"#@commerce_chaser_unique8@#",
|
|
"#@commerce_dex_unique8@#",
|
|
"#@commerce_edge_unique8@#",
|
|
"#@commerce_energy_unique8@#",
|
|
"#@commerce_hunter_unique8@#",
|
|
"#@commerce_int_unique8@#",
|
|
"#@commerce_magical_unique8@#",
|
|
"#@commerce_men_unique8@#",
|
|
"#@commerce_pen_unique8@#",
|
|
"#@commerce_perfect_unique8@#",
|
|
"#@commerce_save_unique8@#",
|
|
"#@commerce_str_unique8@#",
|
|
"#@commerce_vit_unique8@#",
|
|
|
|
"#@socket_empty@#",
|
|
|
|
"#@fx_fire@#",
|
|
"#@fx_wind@#",
|
|
"#@fx_light@#",
|
|
"#@fx_water@#",
|
|
"#@fx_earth@#",
|
|
"#@fx_dark@#",
|
|
"#@fx_fire2@#",
|
|
"#@fx_wind2@#",
|
|
"#@fx_light2@#",
|
|
"#@fx_water2@#",
|
|
"#@fx_earth2@#",
|
|
"#@fx_dark2@#",
|
|
|
|
"#@guild_notice@#",
|
|
"#@guild_memo@#",
|
|
|
|
"#@quest_easy@#",
|
|
"#@quest_normal@#",
|
|
"#@quest_hard@#",
|
|
|
|
"#@_normal_orange@#",
|
|
"#@_normal_purple@#",
|
|
"#@_normal_blue@#",
|
|
"#@_normal_sky@#",
|
|
"#@_normal_red@#",
|
|
"#@_normal_yellow@#",
|
|
"#@_normal_green@#",
|
|
|
|
NULL
|
|
};
|
|
|
|
#ifdef _USE_XTRAP_MODULE
|
|
void XTrapThread(void* pArg)
|
|
{
|
|
int delay = 20000; // 20초
|
|
for (;;)
|
|
{
|
|
Sleep(delay);
|
|
XTrap_C_CallbackAlive(delay);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/// 2010.11.11 - prodongi
|
|
void _getModulePath();
|
|
bool _isValidDxVersion();
|
|
void _setDebugFlag();
|
|
bool _isValidResolution();
|
|
void _setTitle();
|
|
void _parsingLocaleInfo();
|
|
void _initEmoticonList();
|
|
void _setEditBoxFontTag();
|
|
void _initGuildIcon();
|
|
void _initCom();
|
|
void _initAtlModule(CComModule& _Module);
|
|
void _initBotManager(HWND hWnd, HINSTANCE hInstance);
|
|
void _initBotManagerUIScript();
|
|
void _mainLoop(MSG& msg);
|
|
void _saveLogStringRate();
|
|
void _clearWebBrowser();
|
|
void _clearMain(HANDLE& hMutex, CComModule* _Module);
|
|
void _deleteSGObj(); //gmpbigsun( 20130726 ) : static 변수를 없애서 leak을 잡자.
|
|
|
|
#ifdef _HACK_SHIELD_
|
|
void _startHackShieldService();
|
|
#endif
|
|
|
|
bool _startNProtectService();
|
|
|
|
bool _checkDoubleExecute(HANDLE& hMutex);
|
|
|
|
#ifndef _COUNTRY_ME_
|
|
bool _setLocaleFontInfo();
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
void _saveMemAllocCount();
|
|
#endif
|
|
|
|
|
|
enum
|
|
{
|
|
VALID_PARENT_SUCCESS = 0,
|
|
VALID_PARENT_GETPATH_FAILED = 1<<1,
|
|
VALID_PARENT_PARENT_SIGNER_FAILED = 1<<2,
|
|
VALID_PARENT_MY_SIGNER_FAILED = 1<<3,
|
|
VALID_PARENT_ENVIRONMENT_VALUE_FAILED = 1<<4,
|
|
VALID_PARENT_WAIT_HANDLE_VALUE_FAILED = 1<<5,
|
|
VALID_PARENT_SETEVENT_FAILED = 1<<6,
|
|
VALID_PARENT_CLOSEHANDLE_FAILED = 1<<7,
|
|
};
|
|
|
|
DWORD ValidParentProcess( std::wstring* msg, SYSTEMTIME* my_timestamp )
|
|
{
|
|
DWORD dwResultMask = 0;
|
|
|
|
std::string strMyProcessName = XProcess::GetProcessFileName( ::GetCurrentProcess() );
|
|
XStringUtil::ToLower( strMyProcessName );
|
|
|
|
// 디지털 서명 확인
|
|
bool bCheckSigner = (ENV().GetInt( "check_digital_signer", 0 ) != 0);
|
|
if( bCheckSigner == true )
|
|
{
|
|
std::wstring strParentProcess = XProcess::GetParentProcessFullPath();
|
|
if( strParentProcess.empty() == true )
|
|
{
|
|
std::string strParent = strMyProcessName + "_PARENT";
|
|
char szPath[MAX_PATH] = { 0, };
|
|
if( ::GetEnvironmentVariable( strParent.c_str(), szPath, _countof( szPath ) ) > 0 )
|
|
{
|
|
wchar_t szWPath[MAX_PATH] = { 0, };
|
|
//AziaMafia Fix CODEPAGE CP_UTF8
|
|
//::MultiByteToWideChar( ::GetACP(), 0, szPath, -1, szWPath, _countof( szWPath ) );
|
|
::MultiByteToWideChar(::GetACP(), 0, szPath, -1, szWPath, _countof( szWPath ) );
|
|
strParentProcess = szWPath;
|
|
}
|
|
}
|
|
|
|
if( strParentProcess.empty() == true )
|
|
{
|
|
dwResultMask |= VALID_PARENT_GETPATH_FAILED;
|
|
}
|
|
|
|
BYTE bySerialNumber[16] = { 0x0d, 0xf9, 0xee, 0x3c, 0xfb, 0xc6, 0xd8, 0xde, 0xe0, 0x77, 0x7f, 0x92, 0x63, 0xce, 0x06, 0xdf };
|
|
if( XVerifyProcessSigner( strParentProcess, L"Gala Lab Corp.", bySerialNumber, sizeof( bySerialNumber ), NULL, msg ) == false )
|
|
{
|
|
dwResultMask |= VALID_PARENT_PARENT_SIGNER_FAILED;
|
|
}
|
|
|
|
wchar_t szMyPath[MAX_PATH] = { 0, };
|
|
|
|
//AziaMafia Fix CODEPAGE CP_UTF8
|
|
//::MultiByteToWideChar( ::GetACP(), 0, strMyProcessName.c_str(), -1, szMyPath, _countof( szMyPath ) );
|
|
::MultiByteToWideChar(::GetACP(), 0, strMyProcessName.c_str(), -1, szMyPath, _countof( szMyPath ) );
|
|
std::wstring strMyProcessTemp = szMyPath;
|
|
if( XVerifyProcessSigner( strMyProcessTemp, L"Gala Lab Corp.", bySerialNumber, sizeof( bySerialNumber ), my_timestamp, msg ) == false )
|
|
{
|
|
dwResultMask |= VALID_PARENT_MY_SIGNER_FAILED;
|
|
}
|
|
}
|
|
|
|
std::string strRunWaitHandle = strMyProcessName + "_RUNNER";
|
|
char szWaitHandle[64] = { 0, };
|
|
if( ::GetEnvironmentVariable( strRunWaitHandle.c_str(), szWaitHandle, _countof( szWaitHandle ) ) <= 0 )
|
|
{
|
|
dwResultMask |= VALID_PARENT_ENVIRONMENT_VALUE_FAILED;
|
|
}
|
|
|
|
HANDLE hRunWait = reinterpret_cast< HANDLE >( _atoi64( szWaitHandle ) );
|
|
if( hRunWait == NULL )
|
|
{
|
|
dwResultMask |= VALID_PARENT_WAIT_HANDLE_VALUE_FAILED;
|
|
}
|
|
|
|
if( ::SetEvent( hRunWait ) == FALSE )
|
|
{
|
|
dwResultMask |= VALID_PARENT_SETEVENT_FAILED;
|
|
}
|
|
|
|
if( ::CloseHandle( hRunWait ) == FALSE )
|
|
{
|
|
dwResultMask |= VALID_PARENT_CLOSEHANDLE_FAILED;
|
|
}
|
|
|
|
return dwResultMask;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//Main
|
|
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
g_pNpgl = NULL;
|
|
|
|
std::wstring valild_msg;
|
|
SYSTEMTIME timestamp;
|
|
DWORD dwIsValidParent = ValidParentProcess( &valild_msg, ×tamp );
|
|
DWORD dwValidParentLastError = ::GetLastError();
|
|
|
|
#ifdef _USE_XTRAP_MODULE
|
|
char XTrapKey[] = "660970B4CA79D814E13D6D9844CFE862A476DA4508687AF092D5D482BB89FDCFEACF088691D3EBC25799F4E785CF821D1F8847AE46380D24DE516E28FC67A34D0F7D04245246E41FB1670C4E95407619E96980387320B6505436FCED87B1E5752B95727C";
|
|
// XTrap_L_Patch(XTrapKey, 0, 60);
|
|
XTrap_C_Start(XTrapKey, NULL);
|
|
#endif
|
|
|
|
_getModulePath(); /// 2010.11.11 - prodongi
|
|
GetLog().LogStart();
|
|
ENV().ParseCmdLine();
|
|
|
|
#ifdef _COUNTRY_ME_
|
|
SGameOperationManager* pGameOperationManager = new SGameOperationManager;
|
|
#endif
|
|
|
|
if( InitResource() == false )
|
|
{
|
|
// Game exit
|
|
MessageBox( g_hWnd, "Not Found Resource\nGame Exit!!!", "Rappelz-Error", MB_OK|MB_ICONERROR );
|
|
SLOG("Not Found Resource!");
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef _HACK_SHIELD_
|
|
_startHackShieldService(); /// 2010.11.11 - prodongi
|
|
#endif
|
|
|
|
bool bNProtectAble = (ENV().GetInt( "use_nprotect", 1 ) != 0);
|
|
#ifdef FRAUN_NO_GG // Fraun 7/11/2025 disabling GameGuard
|
|
bNProtectAble = false;
|
|
#endif
|
|
|
|
|
|
#ifdef _DEV
|
|
bNProtectAble = false;
|
|
#endif
|
|
if( bNProtectAble == true && _startNProtectService() == false )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// 2010.05.04 - prodongi
|
|
bool applySplash = true;
|
|
cSplashLoading splashLoading(applySplash);
|
|
if (applySplash) nCmdShow = SW_HIDE;
|
|
splashLoading.begin(hInstance);
|
|
|
|
// Execute Check
|
|
/// 2010.11.11 - prodongi
|
|
HANDLE hMutex = NULL;
|
|
bool bAllowDoubleExecute = (ENV().GetInt( "allow_double_exec", 0 ) != 0);
|
|
#ifdef _DEV
|
|
bAllowDoubleExecute = true;
|
|
#endif
|
|
if( bAllowDoubleExecute == false && _checkDoubleExecute(hMutex) == false )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//_CrtSetBreakAlloc(1880332);
|
|
|
|
strcpy(BuildDate, __DATE__);
|
|
strcpy(BuildTime, __TIME__);
|
|
|
|
/// 2010.11.11 - prodongi
|
|
if (!_isValidDxVersion())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#ifndef DISABLE_DEBUGGER_DETECTOR
|
|
if( IsDebuggerPresent() )
|
|
{
|
|
m_nDummyInt = 1;
|
|
MessageBox( NULL, "Debugger detected!!\nplease disable it and restart the application.", "ERROR", MB_ICONWARNING| MB_OK );
|
|
SLOG("Debugger Detected!");
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
GetGameOption();
|
|
|
|
MSG msg;
|
|
HACCEL hAccelTable;
|
|
memset( &msg, 0, sizeof(msg) );
|
|
|
|
#ifdef _EXCEPTION_PROCESS
|
|
#ifdef _DEV
|
|
StartExceptionHandler( "SFrame" );
|
|
#else
|
|
StartExceptionHandler( "SFrame", false );
|
|
#endif
|
|
SetUserFunc( UserFunc );
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
_setDebugFlag(); /// 2010.11.12 - prodongi
|
|
#endif
|
|
|
|
//gmpbigsun( 20130311 ) : for autobuild
|
|
if( true == ENV().IsExist( "ImmTerminate" ) )
|
|
return 0;
|
|
|
|
#ifdef _DEV
|
|
bool bCheckSigner = (ENV().GetInt( "check_digital_signer", 0 ) != 0);
|
|
if( bCheckSigner == false )
|
|
{
|
|
dwIsValidParent = VALID_PARENT_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
if( CheckAuthServerIP( ENV().GetString( "auth_ip", "" ) ) == false )
|
|
{
|
|
MessageBox( g_hWnd, "Invalid Server IP.\nGame Exit!!!", "Rappelz-Error", MB_OK|MB_ICONERROR );
|
|
return 0;
|
|
}
|
|
|
|
if (!_isValidResolution())
|
|
{
|
|
MessageBox(g_hWnd, "Invalid resolution", "Rappelz - Error", MB_OK | MB_ICONERROR);
|
|
return 0;
|
|
}
|
|
|
|
_setTitle(); /// 2010.11.11 - prodongi
|
|
|
|
#ifdef _COMPANY
|
|
strcat( szTitle, " Release Company" );
|
|
#endif
|
|
|
|
#ifdef _DEV
|
|
strcat( szTitle, " Dev" );
|
|
#endif
|
|
|
|
// Initialize Thai word breaker
|
|
#ifdef _COUNTRY_TL_
|
|
LocalizationTL::g_TEWordBreak.LoadDic();
|
|
LocalizationTL::g_TEWordBreak.wcut = "<WB>";
|
|
#endif
|
|
|
|
LoadString(hInstance, IDC_SFRAME, szWindowClass, MAX_LOADSTRING);
|
|
|
|
MyRegisterClass(hInstance);
|
|
|
|
// Perform application initialization
|
|
HWND hWnd = InitInstance( hInstance, nCmdShow );
|
|
if( !hWnd )
|
|
{
|
|
SLOG("Program initialize error!");
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return 0;
|
|
}
|
|
|
|
g_hInstance = hInstance;
|
|
g_hWnd = hWnd;
|
|
|
|
// [sonador][1.5.1] Keyboard input improvements
|
|
#ifdef _USE_KEYBOARD_HOOK
|
|
g_hKeyBoardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) KeyboardProc, NULL, GetCurrentThreadId());
|
|
#endif
|
|
|
|
#ifdef _EDIT_ENVIRONMENT_
|
|
// Initialize dialog parameters for editing environment parameters
|
|
GetEditParameterDialog().SetParam(g_hInstance, g_hWnd);
|
|
#endif
|
|
|
|
initKeyboardHook(); // 2010.06.17 - prodongi
|
|
CheckOSVersion();
|
|
_parsingLocaleInfo(); /// 2010.11.11 - prodongi
|
|
|
|
#ifndef _COUNTRY_ME_ // sonador #2.4.10.2
|
|
if (!_setLocaleFontInfo())
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
_initEmoticonList(); /// 2010.11.11 - prodongi
|
|
_setEditBoxFontTag(); /// 2010.11.11 - prodongi
|
|
CEditBoxInfo::SetUseClipException( true );
|
|
|
|
#define BUFSIZE MAX_PATH
|
|
|
|
_initGuildIcon();
|
|
|
|
#define _EXPLORER_
|
|
|
|
#ifdef _EXPLORER_
|
|
_initCom(); /// 2010.11.11 - prodongi
|
|
|
|
CComModule _Module;
|
|
_initAtlModule(_Module);
|
|
#endif
|
|
|
|
#ifdef CLOUD_LUA
|
|
CreateCloudDB();
|
|
#endif
|
|
|
|
_initBotManager(hWnd, hInstance); /// 2010.11.12 - prodongi
|
|
InitScript();
|
|
_initBotManagerUIScript(); /// 2010.11.12 - prodongi
|
|
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SFRAME);
|
|
|
|
// 윈도우 핸들이 생성된 후, 그리고 모든 그래픽, UI 관련 초기화가 끝난 후 SetHwnd() 호출
|
|
if( g_pNpgl != NULL )
|
|
{
|
|
g_pNpgl->SetHwnd( g_hWnd );
|
|
}
|
|
|
|
#ifdef _USE_XTRAP_MODULE
|
|
XTrap_C_KeepAlive();
|
|
_beginthread(XTrapThread, 0, NULL);
|
|
#endif
|
|
|
|
splashLoading.end(g_hWnd); // 2010.05.04 - prodongi
|
|
|
|
/// 2010.11.11 - prodongi
|
|
_mainLoop(msg);
|
|
|
|
SLOG("Game Main-loop Finished");
|
|
|
|
#ifdef CLOUD_LUA
|
|
DestroyCloudDB();
|
|
#endif
|
|
|
|
_clearMain(hMutex, &_Module);
|
|
_deleteSGObj();
|
|
|
|
return (int) msg.wParam;
|
|
}
|
|
|
|
//
|
|
// Function: MyRegisterClass()
|
|
//
|
|
// Purpose: Registers a window class.
|
|
//
|
|
// Description:
|
|
//
|
|
// Use this function only if you need compatibility with the Win32 system
|
|
// before the 'RegisterClassEx' function, which was added in Windows 95.
|
|
// You must call this function to get the 'correct format' small icon
|
|
// associated with the application.
|
|
//
|
|
|
|
ATOM MyRegisterClass(HINSTANCE hInstance)
|
|
{
|
|
WNDCLASSEX wcex;
|
|
|
|
wcex.cbSize = sizeof(wcex);
|
|
|
|
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
|
|
wcex.lpfnWndProc = (WNDPROC)WndProc;
|
|
wcex.cbClsExtra = 0;
|
|
wcex.cbWndExtra = 0;
|
|
wcex.hInstance = hInstance;
|
|
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SFRAME);
|
|
wcex.hCursor = NULL;//LoadCursor(NULL, IDC_ARROW);
|
|
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
|
wcex.lpszMenuName = 0;
|
|
wcex.lpszClassName = szWindowClass;
|
|
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
|
|
|
|
return RegisterClassEx(&wcex);
|
|
}
|
|
|
|
//
|
|
// 함수: InitInstance(HANDLE, int)
|
|
//
|
|
// 목적: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
|
|
//
|
|
// 설명:
|
|
//
|
|
// 이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
|
|
// 주 프로그램 창을 만든 다음 표시합니다.
|
|
//
|
|
HWND InitInstance(HINSTANCE hInstance, int nCmdShow)
|
|
{
|
|
HWND hWnd;
|
|
|
|
DWORD dwStyle = 0;
|
|
//전체 모드일때, 캡션 보더 사용안함.
|
|
if( ENV().IsExist( "full" ) )
|
|
{
|
|
// TODO : 우선 1024 해상도로 맞춰둔다 옵션 적용되면 삭제
|
|
|
|
dwStyle = WS_POPUPWINDOW;
|
|
}
|
|
else
|
|
{
|
|
if( ENV().IsExist( "win" ) )
|
|
{
|
|
// TODO : 우선 1024 해상도로 맞춰둔다 옵션 적용되면 삭제
|
|
#ifdef _DEV
|
|
if( GetGameOption().GetFullWindowMode() ) // 전체 창 모드라면
|
|
{
|
|
dwStyle = WS_POPUPWINDOW; //전체 창 모드
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
dwStyle = WS_OVERLAPPEDWINDOW; //윈도우 모드
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( GetGameOption().GetWinMode() == 1 )
|
|
{
|
|
int sx = GetSystemMetrics(SM_CXSCREEN);
|
|
int sy = GetSystemMetrics(SM_CYSCREEN);
|
|
if( sx == 1024 && sy == 768 )
|
|
{
|
|
dwStyle = WS_POPUPWINDOW; //1024x768 예외처리
|
|
dwStyle &= ~WS_SYSMENU;
|
|
}
|
|
else
|
|
{
|
|
dwStyle = WS_OVERLAPPEDWINDOW; //윈도우 모드
|
|
dwStyle |= WS_SYSMENU;
|
|
dwStyle |= WS_MINIMIZEBOX;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwStyle = WS_POPUPWINDOW; //전체모드
|
|
dwStyle &= ~WS_SYSMENU;
|
|
}
|
|
}
|
|
}
|
|
|
|
dwStyle &= ~WS_THICKFRAME;
|
|
dwStyle &= ~WS_MAXIMIZEBOX;
|
|
|
|
|
|
//Explorer
|
|
dwStyle |= WS_CLIPCHILDREN;
|
|
dwStyle |= WS_CLIPSIBLINGS;
|
|
|
|
RECT rect;
|
|
rect.left = rect.top = 0;
|
|
rect.right = RES_1024;
|
|
rect.bottom = RES_768;
|
|
// rect.right = RES_1280;//RES_1024;
|
|
// rect.bottom = RES_1024;//RES_768;
|
|
|
|
#ifdef _WEB_DISP_MODE
|
|
CheckDisplay();
|
|
#endif
|
|
|
|
GetCommandBuilder();
|
|
rect.right = GetGameOption().GetResolution_Width();
|
|
rect.bottom = GetGameOption().GetResolution_Height();
|
|
|
|
KUIWndManager::SetResolution( KSize(rect.right, rect.bottom) );
|
|
|
|
AdjustWindowRect( &rect, dwStyle, FALSE );
|
|
|
|
int nW = rect.right - rect.left;
|
|
int nH = rect.bottom - rect.top;
|
|
|
|
|
|
g_hWnd= hWnd = CreateWindow(szWindowClass, szTitle, dwStyle,
|
|
CW_USEDEFAULT, 0, nW, nH, NULL, NULL, hInstance, NULL);
|
|
|
|
if( hWnd )
|
|
{
|
|
ShowWindow(hWnd, nCmdShow);
|
|
UpdateWindow(hWnd);
|
|
}
|
|
|
|
// 중문은 윈도 타이틀 다르게..
|
|
//홍콩, //대만
|
|
|
|
|
|
|
|
if( stricmp( ENV().GetString( "locale" ).c_str(), "BIG5" ) == 0 )
|
|
{
|
|
//KTextRender::SetDefaultCodePage( 950 ); //FreeType에 영향
|
|
|
|
if( stricmp( ENV().GetString( "country" ).c_str(), "HK" ) == 0 )
|
|
{
|
|
wchar_t szTChnName[] = { 0x795E, 0x9B54, 0x50B3, 0x8AAA, 0 };
|
|
::SetWindowTextW( g_hWnd, szTChnName );
|
|
}
|
|
else if( stricmp( ENV().GetString( "country" ).c_str(), "TW" ) == 0 ||
|
|
stricmp( ENV().GetString( "country" ).c_str(), "MASG" ) == 0 )
|
|
{
|
|
wchar_t szTChnName[] = { 0x81F3, 0x5C0A, 0x4E5D, 0x5C01, 0 };
|
|
::SetWindowTextW( g_hWnd, szTChnName );
|
|
}
|
|
|
|
KUIControl::SetBlankWidth( 30 );
|
|
KTextParser::SetUseWordWrap( false );
|
|
}
|
|
|
|
//태국
|
|
if( stricmp( ENV().GetString( "locale" ).c_str(), "CP874" ) == 0 && stricmp( ENV().GetString( "country" ).c_str(), "TL" ) == 0 )
|
|
{
|
|
//KTextRender::SetDefaultCodePage( 874 );
|
|
//wchar_t szTChnName[] = { 0x5c01, 0x5370, 0x4f20, 0x8bf4, 0 };
|
|
//::SetWindowTextW( g_hWnd, szTChnName );
|
|
KUIControl::SetBlankWidth( 30 );
|
|
KTextParser::SetUseWordWrap( false );
|
|
}
|
|
|
|
//터키
|
|
/*if( stricmp( ENV().GetString( "locale" ).c_str(), "CP1254" ) == 0 && stricmp( ENV().GetString( "country" ).c_str(), "TR" ) == 0 )
|
|
{
|
|
KTextRender::SetDefaultCodePage( 1254 );
|
|
//wchar_t szTChnName[] = { 0x5c01, 0x5370, 0x4f20, 0x8bf4, 0 };
|
|
//::SetWindowTextW( g_hWnd, szTChnName );
|
|
KUIControl::SetBlankWidth( 30 );
|
|
KTextParser::SetUseWordWrap( false );
|
|
}*/
|
|
|
|
//중국
|
|
if( stricmp( ENV().GetString( "locale" ).c_str(), "CP936" ) == 0 && stricmp( ENV().GetString( "country" ).c_str(), "CN" ) == 0 )
|
|
{
|
|
//KTextRender::SetDefaultCodePage( 936 );
|
|
wchar_t szTChnName[] = { 0x65B0, 0x5C01, 0x5370, 0x4F20, 0x8BF4, 0 };
|
|
::SetWindowTextW( g_hWnd, szTChnName );
|
|
KUIControl::SetBlankWidth( 30 );
|
|
KTextParser::SetUseWordWrap( false );
|
|
}
|
|
else if( stricmp( ENV().GetString( "country" ).c_str(), "HK" ) == 0 )
|
|
{
|
|
wchar_t szTChnName[] = { 39764, 31070, 20659, 0 };
|
|
::SetWindowTextW( g_hWnd, szTChnName );
|
|
KUIControl::SetBlankWidth( 30 );
|
|
KTextParser::SetUseWordWrap( false );
|
|
}
|
|
|
|
// sonador 0.2.2 Country-specific local bitset integration and separation of Europe
|
|
if( stricmp( ENV().GetString( "locale" ).c_str(), "windows-1252" ) == 0 )
|
|
{
|
|
// KTextRender::SetDefaultCodePage( 1252 );
|
|
}
|
|
// sonador #2.1.8
|
|
else if( stricmp( ENV().GetString( "locale" ).c_str(), "windows-1251" ) == 0 )
|
|
{
|
|
//KTextRender::SetDefaultCodePage( 1251 );
|
|
}
|
|
// sonador #2.4.10.1
|
|
else if( stricmp( ENV().GetString( "locale" ).c_str(), "windows-1256" ) == 0 )
|
|
{
|
|
//KTextRender::SetDefaultCodePage( 1256 );
|
|
#ifdef _COUNTRY_ME_
|
|
//g_pGameOperationManager->SetDefaultCodePage( 1256 );
|
|
#endif
|
|
}
|
|
// 2010.09.03 - prodongi
|
|
else if (stricmp(ENV().GetString("locale").c_str(), "Shift-JIS") == 0 )
|
|
{
|
|
KUIControl::SetBlankWidth( 10 );
|
|
}
|
|
|
|
// 2010.09.20 - prodongi
|
|
if(GameRule::GetCurrentLocalBitSet() == GameRule::LOCAL_BITSET::KR)
|
|
{
|
|
KUIControl::SetBlankWidth(5);
|
|
}
|
|
|
|
if( ENV().IsExist( "alwaysontop" ) ) { // 항상 제일 위에 둔다
|
|
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
|
}
|
|
|
|
//RECT frect;
|
|
//frect.left = 0;
|
|
//frect.top = 0;
|
|
//frect.right = GetGameOption().GetResolution_Width();
|
|
//frect.bottom = GetGameOption().GetResolution_Height();
|
|
|
|
//HDC dc = ::GetDC( hWnd );
|
|
//HBRUSH black_brush = (HBRUSH)::GetStockObject( BLACK_BRUSH );
|
|
|
|
//::FillRect( dc, &frect, black_brush );
|
|
//::ReleaseDC( hWnd, dc );
|
|
|
|
#ifdef _WEB_DISP_MODE
|
|
if( GetGameOption().GetWinMode() == 0 )
|
|
{
|
|
if( !ENV().IsExist( "win" ) )
|
|
{
|
|
ChangeDisplay();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return hWnd;
|
|
}
|
|
|
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
//Web Browser Key Proc
|
|
// if( ( WM_KEYDOWN == message || WM_KEYUP == message ) && g_IsShowWebBrowser )
|
|
if( ( WM_KEYDOWN == message || WM_KEYUP == message ) && g_IsShowWebBrowser && !g_bServerListFocus )
|
|
{
|
|
|
|
if(
|
|
wParam == VK_DELETE || wParam == VK_TAB ||
|
|
(wParam >= 0x60 && wParam < 0x70) || //VK_NUMPAD0 - VK_NUMPAD9
|
|
(wParam >= 0x30 && wParam < 0x40) || //ASCII '0' - '9' (0x30 - 0x39)
|
|
(wParam >= 0x41 && wParam < 0x5B) ) //ASCII 'A' - 'Z' (0x41 - 0x5A)
|
|
{
|
|
|
|
|
|
// Ctrl + N을막기위해 일단 Ctrl키 입력자체를 막음 2009.10.26 sfreer
|
|
if( g_pWebBrowser && GetAsyncKeyState(VK_CONTROL) == 0 /*&& !ControlKeyCheck*/ )
|
|
{
|
|
CComQIPtr<IOleInPlaceActiveObject, &IID_IOleInPlaceActiveObject> pIOIPAO(g_pWebBrowser) ;
|
|
if(pIOIPAO)
|
|
{
|
|
MSG msg;
|
|
msg.message = message;
|
|
msg.wParam = wParam;
|
|
msg.lParam = lParam;
|
|
|
|
pIOIPAO->TranslateAccelerator(&msg);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ //웹페이지 처리이므로 게임엔 주지 않음
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
#ifdef _HACK_SHIELD_
|
|
// { 키보드 메시지 들어 오면, 후킹 검사 내려감.
|
|
if( WM_SYSKEYDOWN == message ||
|
|
WM_KEYDOWN == message )
|
|
{
|
|
g_dwKeyResumeTime = GetSafeTickCount();
|
|
|
|
if( g_bCheckHook == false )
|
|
{
|
|
if( g_bAhnHS )
|
|
SetWindowText( g_hWnd, "_AhnHS_PauseService( AHNHS_CHKOPT_MESSAGEHOOK )" );
|
|
_AhnHS_PauseService( AHNHS_CHKOPT_MESSAGEHOOK );
|
|
}
|
|
|
|
g_bCheckHook = true;
|
|
}
|
|
#endif
|
|
|
|
// { alt 키 메뉴 뜨는것 막음
|
|
if ( message == WM_SYSCOMMAND )
|
|
{
|
|
if( wParam == SC_KEYMENU ) return 0;
|
|
}
|
|
// }
|
|
if( message == WM_SYSKEYDOWN )
|
|
{
|
|
if( wParam == VK_F4 ) return 0;
|
|
}
|
|
|
|
if(g_pSBotMng)
|
|
{
|
|
g_pSBotMng->WndProc( hWnd, message, wParam, lParam );
|
|
}
|
|
|
|
#ifdef _EDIT_ENVIRONMENT_
|
|
if( message == WM_CLOSE )
|
|
{
|
|
// 환경 파라미터 편집을 위한 다이얼로그 파괴
|
|
GetEditParameterDialog().End();
|
|
return 0;
|
|
}
|
|
#else
|
|
if( message == WM_CLOSE )
|
|
return 0;
|
|
#endif
|
|
|
|
if ( message == WM_ACTIVATE || message == WM_SYNCPAINT )
|
|
{
|
|
// 로그가 너무 많이 출력되서 일단 주석
|
|
//_oprint( "!!!!!!!!!! WM_ACTIVATE !!!!!!!!!!!\n" );
|
|
ResetHotKeys();
|
|
}
|
|
|
|
|
|
if( g_hWnd == hWnd )
|
|
{
|
|
switch( message )
|
|
{
|
|
case WM_IME_SETCONTEXT : /*_performance_print( "* WM_IME_SETCONTEXT %d\n", wParam );*/
|
|
lParam = 0;
|
|
break;
|
|
|
|
case WM_IME_COMPOSITION : /*_performance_print( "* WM_IME_COMPOSITION %d\n", wParam ); */
|
|
KUIControlEdit::PostWndMsgToFocusEdit( message, wParam, lParam );
|
|
return 0L;
|
|
case WM_IME_NOTIFY : /*_performance_print( "* WM_IME_NOTIFY %d\n", wParam );*/
|
|
KUIControlEdit::PostWndMsgToFocusEdit( message, wParam, lParam );
|
|
return 0L;
|
|
|
|
case WM_IME_STARTCOMPOSITION : /*_performance_print( "* WM_IME_STARTCOMPOSITION %d\n", wParam ); */
|
|
return 0L;
|
|
|
|
case WM_IME_ENDCOMPOSITION : /*_performance_print( "* WM_IME_ENDCOMPOSITION %d\n", wParam );*/ break;
|
|
case WM_IME_CONTROL : /*_performance_print( "* WM_IME_CONTROL %d\n", wParam );*/ break;
|
|
case WM_IME_COMPOSITIONFULL : /*_performance_print( "* WM_IME_COMPOSITIONFULL %d\n", wParam );*/ break;
|
|
case WM_IME_SELECT : /*_performance_print( "* WM_IME_SELECT %d\n", wParam );*/ break;
|
|
case WM_IME_CHAR : /*_performance_print( "* WM_IME_CHAR %d\n", wParam );*/ break;
|
|
case WM_IME_REQUEST : /*_performance_print( "* WM_IME_REQUEST %d\n", wParam );*/ break;
|
|
case WM_IME_KEYDOWN : /*_performance_print( "* WM_IME_KEYDOWN %d\n", wParam );*/ break;
|
|
case WM_IME_KEYUP : /*_performance_print( "* WM_IME_KEYUP %d\n", wParam );*/ break;
|
|
}
|
|
}
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
}
|
|
|
|
// { [sonador][1.5.1] 키보드 입력 개선
|
|
#ifdef _USE_KEYBOARD_HOOK
|
|
LRESULT CALLBACK KeyboardProc( int code, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
static GameHotKeystrcut HotKey;
|
|
// static bool bShift, bAlt, bCtrl, bTab;
|
|
static WPARAM sParam;
|
|
static BYTE s_Key[256]; //Key State Map
|
|
sParam = wParam;
|
|
|
|
#ifndef _RELEASE
|
|
int nDebug = LOWORD( wParam );
|
|
#endif
|
|
|
|
//ALT, CTRL, SHIFT만 눌렀을 경우에는 메세지가 안 간다.
|
|
if( HIWORD( lParam ) & KF_UP )
|
|
{
|
|
if( LOWORD( wParam ) == VK_SHIFT )
|
|
{
|
|
if( HotKey.bShift )
|
|
{
|
|
HotKey.bShift = false;
|
|
// g_pSBotMng->onHotkey(bShift, bAlt, bCtrl, LOWORD( sParam ) );
|
|
// _oprint( "_SHIFT Off\n" );
|
|
}
|
|
}
|
|
if( LOWORD( wParam ) == VK_MENU )
|
|
{
|
|
if( HotKey.bAlt )
|
|
{
|
|
HotKey.bAlt = false;
|
|
// g_pSBotMng->onHotkey(bShift, bAlt, bCtrl, LOWORD( sParam ) );
|
|
// _oprint( "_ALT Off\n" );
|
|
}
|
|
}
|
|
if( LOWORD( wParam ) == VK_CONTROL )
|
|
{
|
|
if( HotKey.bCtrl )
|
|
{
|
|
HotKey.bCtrl = false;
|
|
// g_pSBotMng->onHotkey(bShift, bAlt, bCtrl, LOWORD( sParam ) );
|
|
// _oprint( "_CONTROL Off\n" );
|
|
}
|
|
}
|
|
if( LOWORD( wParam ) == VK_TAB )
|
|
{
|
|
if( HotKey.bTab )
|
|
{
|
|
HotKey.bTab = false;
|
|
}
|
|
}
|
|
|
|
if( s_Key[LOWORD( sParam )] || LOWORD(sParam) == VK_SNAPSHOT )
|
|
{
|
|
s_Key[LOWORD( sParam )] = false;
|
|
|
|
HotKey.Virtual_Key = LOWORD( sParam );
|
|
HotKey.bUp = TRUE;
|
|
|
|
if( g_pSBotMng ) g_pSBotMng->onHotkey( HotKey );
|
|
// _oprint( "WPARAM %d\n", LOWORD( sParam ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( LOWORD( wParam ) == VK_SHIFT )
|
|
{
|
|
if( !HotKey.bShift )
|
|
{
|
|
HotKey.bShift = true;
|
|
// g_pSBotMng->onHotkey(bShift, bAlt, bCtrl, LOWORD( sParam ) );
|
|
// _oprint( "_SHIFT On\n" );
|
|
}
|
|
}
|
|
if( LOWORD( wParam ) == VK_MENU )
|
|
{
|
|
if( !HotKey.bAlt )
|
|
{
|
|
HotKey.bAlt = true;
|
|
// g_pSBotMng->onHotkey(bShift, bAlt, bCtrl, LOWORD( sParam ) );
|
|
// _oprint( "_ALT On\n" );
|
|
}
|
|
}
|
|
if( LOWORD( wParam ) == VK_CONTROL )
|
|
{
|
|
if( !HotKey.bCtrl )
|
|
{
|
|
HotKey.bCtrl = true;
|
|
// g_pSBotMng->onHotkey(bShift, bAlt, bCtrl, LOWORD( sParam ) );
|
|
// _oprint( "_CONTROL On\n" );
|
|
}
|
|
}
|
|
if( LOWORD( wParam ) == VK_TAB )
|
|
{
|
|
if( !HotKey.bTab )
|
|
{
|
|
HotKey.bTab = true;
|
|
}
|
|
}
|
|
|
|
if( !s_Key[LOWORD( sParam )] )
|
|
{
|
|
s_Key[LOWORD( sParam )] = true;
|
|
|
|
HotKey.Virtual_Key = LOWORD( sParam );
|
|
HotKey.bUp = FALSE;
|
|
|
|
if( g_pSBotMng ) g_pSBotMng->onHotkey( HotKey );
|
|
// _oprint( "WPARAM %d\n", LOWORD( sParam ) );
|
|
}
|
|
}
|
|
|
|
return CallNextHookEx( g_hKeyBoardHook, code, wParam, lParam );
|
|
}
|
|
#else
|
|
static GameHotKeystrcut HotKey;
|
|
static BYTE s_Key[256] = {0, }; //Key State Map
|
|
|
|
// #2.3.1.28
|
|
void ResetHotKeys()
|
|
{
|
|
SHORT sKey;
|
|
|
|
sKey = GetKeyState( VK_MENU );
|
|
HotKey.Virtual_Key = VK_MENU;
|
|
HotKey.bAlt = ((sKey & 0x1000) == 0x1000);
|
|
HotKey.bUp = ((sKey & 0x1000) == 0);
|
|
s_Key[ VK_MENU ] = sKey & 0x1000;
|
|
if( g_pSBotMng )
|
|
g_pSBotMng->onHotkey( HotKey );
|
|
|
|
sKey = GetKeyState( VK_CONTROL );
|
|
HotKey.Virtual_Key = VK_MENU;
|
|
HotKey.bCtrl = ((sKey & 0x1000) == 0x1000);
|
|
HotKey.bUp = ((sKey & 0x1000) == 0);
|
|
s_Key[ VK_MENU ] = sKey & 0x1000;
|
|
if( g_pSBotMng )
|
|
g_pSBotMng->onHotkey( HotKey );
|
|
|
|
sKey = GetKeyState( VK_SHIFT );
|
|
HotKey.Virtual_Key = VK_SHIFT;
|
|
HotKey.bShift = ((sKey & 0x1000) == 0x1000);
|
|
HotKey.bUp = ((sKey & 0x1000) == 0);
|
|
s_Key[ VK_MENU ] = sKey & 0x1000;
|
|
if( g_pSBotMng )
|
|
g_pSBotMng->onHotkey( HotKey );
|
|
|
|
sKey = GetKeyState( VK_TAB);
|
|
HotKey.Virtual_Key = VK_TAB;
|
|
HotKey.bTab = ((sKey & 0x1000) == 0x1000);
|
|
HotKey.bUp = ((sKey & 0x1000) == 0);
|
|
s_Key[ VK_MENU ] = sKey & 0x1000;
|
|
if( g_pSBotMng )
|
|
g_pSBotMng->onHotkey( HotKey );
|
|
|
|
// 알탭후 알트 눌려져있는 문제때문에 추가해봄. by 정동섭
|
|
HotKey.bAlt = false;
|
|
}
|
|
|
|
#include "SGameInterface.h"
|
|
#include "SGameSystem.h"
|
|
#include "SGameWorld.h"
|
|
#include "SGame.h"
|
|
#include "SUIChattingWnd.h"
|
|
extern SGameSystem* g_pCurrentGameSystem; // 2011.11.04 - servantes
|
|
LRESULT CALLBACK HotKeyProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
|
|
// static bool bShift, bAlt, bCtrl, bTab;
|
|
static WPARAM virtualKey;
|
|
|
|
//BEGIN-------------------------------------------------------------------------------------------------
|
|
//gmpbigsun( 20130108, #22935 ) : 키보드 후킹에서 VK_RETRUN을 포커싱관계에 상관없이 처리되고있었다.
|
|
//본 함수에서 채팅창 포커싱을 주게끔하는 로직이 포함되어있어서 현재 많은 EditBox중 포커싱이 있는경우
|
|
//채팅창과 관계(포커싱)없다면 무시하도록 수정되었다.
|
|
|
|
if( wParam == VK_RETURN )
|
|
{
|
|
if( KUIControlEdit::IsFocusEdit() && g_pCurrentGameSystem )
|
|
{
|
|
SUIChattingWnd* pChatWnd = NULL;
|
|
|
|
SGameWorld* pGameWorld = dynamicCast<SGameWorld*>(g_pCurrentGameSystem->GetGame());
|
|
if( pGameWorld )
|
|
{
|
|
SGameManager* pGameManager = pGameWorld->GetGameManager();
|
|
if( pGameManager )
|
|
{
|
|
SGameInterface* pGameInterface = pGameManager->GetGameInterface();
|
|
if( pGameInterface )
|
|
pChatWnd = (SUIChattingWnd*)pGameInterface->GetUIWindow( TOGGLE_WINDOW::UIWINDOW_CHATTING );
|
|
}
|
|
}
|
|
|
|
if( pChatWnd )
|
|
{
|
|
//채팅창에 포커스가 있을경우만 VK_RETURN처리한다.
|
|
if( false == pChatWnd->GetFocusEdit() )
|
|
return ::DefWindowProc( hWnd, message, wParam, lParam );
|
|
}
|
|
}
|
|
}
|
|
//END-------------------------------------------------------------------------------------------------
|
|
|
|
// take correct virtual key...
|
|
if( wParam == VK_PROCESSKEY )
|
|
{
|
|
virtualKey = ::ImmGetVirtualKey( hWnd );
|
|
}
|
|
else
|
|
{
|
|
virtualKey = wParam;
|
|
}
|
|
|
|
#ifndef _RELEASE
|
|
int nDebug = LOWORD( wParam );
|
|
#endif
|
|
|
|
switch( message )
|
|
{
|
|
case WM_SYSCOMMAND:
|
|
break;
|
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
if( virtualKey == VK_SHIFT )
|
|
{
|
|
if( !HotKey.bShift )
|
|
{
|
|
HotKey.bShift = true;
|
|
}
|
|
}
|
|
if( virtualKey == VK_CONTROL )
|
|
{
|
|
if( !HotKey.bCtrl )
|
|
{
|
|
HotKey.bCtrl = true;
|
|
}
|
|
}
|
|
if( virtualKey == VK_MENU )
|
|
{
|
|
if( !HotKey.bAlt )
|
|
{
|
|
HotKey.bAlt = true;
|
|
}
|
|
}
|
|
if( virtualKey == VK_TAB )
|
|
{
|
|
if( !HotKey.bTab )
|
|
{
|
|
HotKey.bTab = true;
|
|
}
|
|
}
|
|
if( !s_Key[LOWORD( virtualKey )] )
|
|
{
|
|
s_Key[LOWORD( virtualKey )] = true;
|
|
|
|
HotKey.Virtual_Key = LOWORD( virtualKey );
|
|
HotKey.bUp = FALSE;
|
|
|
|
if( g_pSBotMng )
|
|
{
|
|
g_pSBotMng->onHotkey( HotKey );
|
|
|
|
// #2.3.1.29
|
|
// alt + F6 동작 오류 수정
|
|
// WM_SYSKEYDOWN 메시지 처리후 ::DefWindowProc 을 호출하여 WM_SYSKEYUP 메시지가 전달되지 않아서 발생한 문제.
|
|
// 결국 F6 키가 눌러졌다가 다시 때지는 순간을 알 수 없었기 때문에 항상 눌려져 있는 상태로 기록되어 있었다.
|
|
/// 2011.06.10 mantis 13776 alt+f4를 막음 - prodongi
|
|
if (VK_F4 == wParam)
|
|
return 1L;
|
|
|
|
// return 1L;
|
|
return ::DefWindowProc( hWnd, message, wParam, lParam ); //2011.05.06 - servantes
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_SYSKEYUP:
|
|
|
|
//_oprint( "syskeyup: %d\n", virtualKey );
|
|
|
|
if( virtualKey == VK_SHIFT )
|
|
{
|
|
if( HotKey.bShift )
|
|
{
|
|
HotKey.bShift = false;
|
|
}
|
|
}
|
|
if( virtualKey == VK_CONTROL )
|
|
{
|
|
if( HotKey.bCtrl )
|
|
{
|
|
HotKey.bCtrl = false;
|
|
}
|
|
}
|
|
if( virtualKey == VK_MENU )
|
|
{
|
|
//_oprint("!!! alt up syskeyup 1 !!!\n" );
|
|
if( HotKey.bAlt )
|
|
{
|
|
HotKey.bAlt = false;
|
|
//_oprint("!!! alt up syskeyup 2 !!!\n" );
|
|
}
|
|
}
|
|
if( virtualKey == VK_TAB )
|
|
{
|
|
if( HotKey.bTab )
|
|
{
|
|
HotKey.bTab = false;
|
|
}
|
|
}
|
|
if( s_Key[LOWORD( virtualKey )] || LOWORD( virtualKey ) == VK_SNAPSHOT )
|
|
{
|
|
s_Key[LOWORD( virtualKey )] = false;
|
|
|
|
HotKey.Virtual_Key = LOWORD( virtualKey );
|
|
HotKey.bUp = TRUE;
|
|
|
|
if( g_pSBotMng )
|
|
{
|
|
g_pSBotMng->onHotkey( HotKey );
|
|
|
|
// #2.3.1.29
|
|
// alt + F6 동작 오류 수정
|
|
// WM_SYSKEYDOWN 메시지 처리후 ::DefWindowProc 을 호출하여 WM_SYSKEYUP 메시지가 전달되지 않아서 발생한 문제.
|
|
// 결국 F6 키가 눌러졌다가 다시 때지는 순간을 알 수 없었기 때문에 항상 눌려져 있는 상태로 기록되어 있었다.
|
|
/// 2011.06.10 mantis 13776 alt+f4를 막음 - prodongi
|
|
if (VK_F4 == wParam)
|
|
return 1L;
|
|
|
|
// return 1L;
|
|
return ::DefWindowProc( hWnd, message, wParam, lParam ); //2011.05.06 - servantes
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
//_oprint( "keydown: %d\n", virtualKey );
|
|
|
|
if( virtualKey == VK_SHIFT )
|
|
{
|
|
if( !HotKey.bShift )
|
|
{
|
|
HotKey.bShift = true;
|
|
}
|
|
}
|
|
if( virtualKey == VK_CONTROL )
|
|
{
|
|
if( !HotKey.bCtrl )
|
|
{
|
|
HotKey.bCtrl = true;
|
|
}
|
|
}
|
|
if( virtualKey == VK_MENU )
|
|
{
|
|
//_oprint("!!! alt down keydown 1 !!!\n" );
|
|
if( !HotKey.bAlt )
|
|
{
|
|
HotKey.bAlt = true;
|
|
//_oprint("!!! alt down keydown 2 !!!\n" );
|
|
}
|
|
}
|
|
if( virtualKey == VK_TAB )
|
|
{
|
|
if( !HotKey.bTab )
|
|
{
|
|
HotKey.bTab = true;
|
|
}
|
|
}
|
|
if( !s_Key[LOWORD( virtualKey )] )
|
|
{
|
|
s_Key[LOWORD( virtualKey )] = true;
|
|
|
|
HotKey.Virtual_Key = LOWORD( virtualKey );
|
|
HotKey.bUp = FALSE;
|
|
|
|
if( g_pSBotMng ) g_pSBotMng->onHotkey( HotKey );
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_KEYUP:
|
|
|
|
//_oprint( "keyup: %d\n", virtualKey );
|
|
|
|
if( virtualKey == VK_SHIFT )
|
|
{
|
|
if( HotKey.bShift )
|
|
{
|
|
HotKey.bShift = false;
|
|
}
|
|
}
|
|
if( virtualKey == VK_CONTROL )
|
|
{
|
|
if( HotKey.bCtrl )
|
|
{
|
|
HotKey.bCtrl = false;
|
|
}
|
|
}
|
|
if( virtualKey == VK_MENU )
|
|
{
|
|
//_oprint("!!! alt up keyup 1 !!!\n" );
|
|
if( HotKey.bAlt )
|
|
{
|
|
HotKey.bAlt = false;
|
|
//_oprint("!!! alt up keyup 2 !!!\n" );
|
|
}
|
|
}
|
|
if( virtualKey == VK_TAB )
|
|
{
|
|
if( HotKey.bTab )
|
|
{
|
|
HotKey.bTab = false;
|
|
}
|
|
}
|
|
if( s_Key[LOWORD( virtualKey )] || LOWORD( virtualKey ) == VK_SNAPSHOT )
|
|
{
|
|
s_Key[LOWORD( virtualKey )] = false;
|
|
|
|
HotKey.Virtual_Key = LOWORD( virtualKey );
|
|
HotKey.bUp = TRUE;
|
|
|
|
if( g_pSBotMng ) g_pSBotMng->onHotkey( HotKey );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
#endif
|
|
// }
|
|
|
|
void ScriptLog( const char *szStr );
|
|
|
|
void InitScript()
|
|
{
|
|
//Lua Init
|
|
LUA()->Init();
|
|
LUA()->InitThread();
|
|
|
|
//기존 스크립트 화일 Load - RunFile
|
|
// std::string strTmpFile = KResourceManager::GetTempFileName( "어쩌구.lua" );
|
|
|
|
//Object
|
|
LUA()->RegisterFunction( "spell" , SCRIPT_Spell );
|
|
LUA()->RegisterFunction( "skill" , SCRIPT_Skill );
|
|
LUA()->RegisterFunction( "attack", SCRIPT_Attack );
|
|
LUA()->RegisterFunction( "move" , SCRIPT_Move );
|
|
//bot manage
|
|
LUA()->RegisterFunction( "botadd" , SCRIPT_BotAdd );
|
|
LUA()->RegisterFunction( "botdel" , SCRIPT_BotDel );
|
|
LUA()->RegisterFunction( "botlist", SCRIPT_BotList );
|
|
LUA()->RegisterFunction( "botsel" , SCRIPT_BotSelect );
|
|
//System
|
|
LUA()->RegisterFunction( "log" , SCRIPT_ReportLog );
|
|
LUA()->RegisterFunction( "profile", SCRIPT_Profile );
|
|
//option
|
|
LUA()->RegisterFunction( "set_music" , SCRIPT_SetMusic );
|
|
LUA()->RegisterFunction( "set_sound" , SCRIPT_SetSound );
|
|
LUA()->RegisterFunction( "set_volume", SCRIPT_SetVolume );
|
|
|
|
//게임 이펙트
|
|
LUA()->RegisterFunction( "playFX" , SCRIPT_FX );
|
|
LUA()->RegisterFunction( "playSound", SCRIPT_PlaySound );
|
|
LUA()->RegisterFunction( "playattackFX", SCRIPT_ATTACK_FX );
|
|
|
|
//게임 컨텐츠
|
|
LUA()->RegisterFunction( "getItemClass", SCRIPT_GetItemClass );
|
|
LUA()->RegisterFunction( "getMaterial" , SCRIPT_GetMaterial );
|
|
LUA()->RegisterFunction( "getGroundMaterial" , SCRIPT_GetGroundMaterial );
|
|
LUA()->RegisterFunction( "getMovingType", SCRIPT_GetMovingType );
|
|
|
|
|
|
//스크립트 디버그 연결~
|
|
_oprint( ">>>>>>>>>>>>>>>script_file Loading...start=====================\n" );
|
|
LUA()->BindLogOutputFunction( ScriptLog );
|
|
std::string strScript = KFileManager::Instance().CreateTemporaryFileFromResource( "FX_Script.lua" );
|
|
if( strScript.length() )
|
|
{
|
|
LUA()->RunFile( strScript.c_str() );
|
|
|
|
KFileManager::Instance().DeleteTemporaryFile( "FX_Script.lua" );
|
|
}
|
|
else
|
|
{
|
|
_oprint( "File Not Found : FX_Script.lua\n" );
|
|
}
|
|
_oprint( ">>>>>>>>>>>>>>>script_file Loaded...end=====================\n" );
|
|
|
|
//상태 관련 정보 가져오기
|
|
LUA()->RegisterFunction( "gethp", SCRIPT_GetHP );
|
|
LUA()->RegisterFunction( "getmp", SCRIPT_GetMP );
|
|
LUA()->RegisterFunction( "getmax_hp", SCRIPT_GetMax_HP );
|
|
LUA()->RegisterFunction( "getmax_mp", SCRIPT_GetMax_MP );
|
|
|
|
//크리처 동작
|
|
LUA()->RegisterFunction( "c_standby", SCRIPT_C_Standby );
|
|
LUA()->RegisterFunction( "c_move", SCRIPT_C_Move );
|
|
LUA()->RegisterFunction( "c_attack", SCRIPT_C_Attack );
|
|
LUA()->RegisterFunction( "c_skill", SCRIPT_C_Skill );
|
|
LUA()->RegisterFunction( "c_idle", SCRIPT_C_Idle );
|
|
|
|
_oprint( ">>>>>>>>>>>>>>>creature_script_file Loading...start=====================\n" );
|
|
LUA()->BindLogOutputFunction( ScriptLog );
|
|
strScript = KFileManager::Instance().CreateTemporaryFileFromResource( "CreatureState_Script.lua" );
|
|
if( strScript.length() )
|
|
{
|
|
LUA()->RunFile( strScript.c_str() );
|
|
|
|
KFileManager::Instance().DeleteTemporaryFile( "CreatureState_Script.lua" );
|
|
}
|
|
else
|
|
{
|
|
_oprint( "File Not Found : CreatureState_Script.lua\n" );
|
|
}
|
|
|
|
_oprint( ">>>>>>>>>>>>>>>creature_script_file Loaded...end=====================\n" );
|
|
|
|
//지역 관련
|
|
LUA()->RegisterFunction( "lc_in", SCRIPT_LC_In );
|
|
LUA()->RegisterFunction( "lc_out", SCRIPT_LC_Out );
|
|
LUA()->RegisterFunction( "lc_local", SCRIPT_LC_Local );
|
|
LUA()->RegisterFunction( "lc_world", SCRIPT_LC_World );
|
|
|
|
_oprint( ">>>>>>>>>>>>>>>local_script_file Loading...start=====================\n" );
|
|
LUA()->BindLogOutputFunction( ScriptLog );
|
|
strScript = KFileManager::Instance().CreateTemporaryFileFromResource( "Location_Script.lua" );
|
|
if( strScript.length() )
|
|
{
|
|
LUA()->RunFile( strScript.c_str() );
|
|
|
|
KFileManager::Instance().DeleteTemporaryFile( "CreatureState_Script.lua" );
|
|
}
|
|
else
|
|
{
|
|
_oprint( "File Not Found : CreatureState_Script.lua\n" );
|
|
}
|
|
_oprint( ">>>>>>>>>>>>>>>local_script_file Loaded...end=====================\n" );
|
|
|
|
// { [sonador] 날씨 관련 스크립트
|
|
LUA()->RegisterFunction( "get_current_weather_theme", SCRIPT_WEATHER_GetTheme );
|
|
LUA()->RegisterFunction( "set_current_weather_theme", SCRIPT_WEATHER_SetTheme );
|
|
LUA()->RegisterFunction( "set_thunder_attribute", SCRIPT_WEATHER_SetThunderAttribute );
|
|
LUA()->RegisterFunction( "set_lightning_attribute", SCRIPT_WEATHER_SetLightningAttribute );
|
|
|
|
_oprint( ">>>>>>>>>>>>>>>weather_script_file Loading...start=====================\n" );
|
|
LUA()->BindLogOutputFunction( ScriptLog );
|
|
strScript = KFileManager::Instance().CreateTemporaryFileFromResource( "weather_script.lua" );
|
|
if( strScript.length() )
|
|
{
|
|
LUA()->RunFile( strScript.c_str() );
|
|
KFileManager::Instance().DeleteTemporaryFile( "weather_script.lua" );
|
|
}
|
|
else
|
|
{
|
|
_oprint( "File Not Found : weather_script.lua\n" );
|
|
}
|
|
_oprint( ">>>>>>>>>>>>>>>weather_script_file Loaded...end=====================\n" );
|
|
|
|
// 환경값 설정용 스크립트
|
|
LUA()->RegisterFunction( "set_environment_info", SCRIPT_ENVIRONMENT_GetAttribute );
|
|
// } [sonador] 날씨 관련 스크립트
|
|
|
|
|
|
//게임 UIWindows AddOn 관련
|
|
LUA()->RegisterFunction( "init_addon_list", SCRIPT_UIWINDOWS_InitAddonList );
|
|
LUA()->RegisterFunction( "create_addon", SCRIPT_UIWINDOWS_CreateAddOn );
|
|
|
|
_oprint( ">>>>>>>>>>>>>>>uiwindows_addon_script Loading...start=====================\n" );
|
|
LUA()->BindLogOutputFunction( ScriptLog );
|
|
|
|
strScript = KFileManager::Instance().CreateTemporaryFileFromResource( "UIWindows_addon_script.lua" );
|
|
if( strScript.length() )
|
|
{
|
|
LUA()->RunFile( strScript.c_str() );
|
|
KFileManager::Instance().DeleteTemporaryFile( "UIWindows_addon_script.lua" );
|
|
}
|
|
else
|
|
{
|
|
_oprint( "File Not Found : UIWindows_addon_script.lua\n" );
|
|
}
|
|
_oprint( ">>>>>>>>>>>>>>>uiwindows_addon_script Loaded...end=====================\n" );
|
|
|
|
#ifdef DISTANCE_VIEW
|
|
_oprint( ">>>>>>>>>>>>>>>skybox_script_file Loading...start=====================\n" );
|
|
LUA()->BindLogOutputFunction( ScriptLog );
|
|
// strScript = KFileManager::Instance().CreateTemporaryFileFromResource( "skybox_script.lua" );
|
|
strScript = KFileManager::Instance().CreateTemporaryFileFromResource( "skybox_script2.lua" );
|
|
if( strScript.length() )
|
|
{
|
|
LUA()->RunFile( strScript.c_str() );
|
|
// KFileManager::Instance().DeleteTemporaryFile( "skybox_script.lua" );
|
|
KFileManager::Instance().DeleteTemporaryFile( "skybox_script2.lua" );
|
|
}
|
|
else
|
|
{
|
|
_oprint( "File Not Found : skybox_script.lua\n" );
|
|
}
|
|
|
|
LUA()->RegisterFunction( "set_current_skybox_theme_sky", SCRIPT_SKYBOX_SetTheme_sky );
|
|
LUA()->RegisterFunction( "set_current_skybox_theme_distance_view", SCRIPT_SKYBOX_SetTheme_distanceView );
|
|
LUA()->RegisterFunction( "load_localmodelinfo", SCRIPT_SKYBOX_load_localmodelinfo );
|
|
// LUA()->RunString( "read_local_model_info()" );
|
|
|
|
_oprint( ">>>>>>>>>>>>>>>skybox_script_file Loaded...end=====================\n" );
|
|
#endif
|
|
|
|
#ifdef CLOUD_LUA
|
|
strScript = KFileManager::Instance().CreateTemporaryFileFromResource( "cloud_script.lua" );
|
|
if( strScript.length() > 0 )
|
|
{
|
|
LUA()->RunFile( strScript.c_str() );
|
|
KFileManager::Instance().DeleteTemporaryFile( "cloud_script.lua" );
|
|
}
|
|
LUA()->RegisterFunction( "load_kind", SCRIPT_CLOUD_LoadKind );
|
|
LUA()->RegisterFunction( "load_thickness", SCRIPT_CLOUD_LoadThickness );
|
|
LUA()->RegisterFunction( "load_thickness_gap", SCRIPT_CLOUD_LoadThicknessGap );
|
|
LUA()->RegisterFunction( "load_size", SCRIPT_CLOUD_LoadSize );
|
|
LUA()->RegisterFunction( "load_texture_group", SCRIPT_CLOUD_LoadTextureGroup );
|
|
LUA()->RegisterFunction( "load_middle_texture_group", SCRIPT_CLOUD_LoadMiddleTextureGroup );
|
|
LUA()->RegisterFunction( "load_dark_texture_group", SCRIPT_CLOUD_LoadDarkTextureGroup );
|
|
LUA()->RegisterFunction( "load_distribution", SCRIPT_CLOUD_LoadDistribution );
|
|
LUA()->RegisterFunction( "load_height_random_gap", SCRIPT_CLOUD_LoadHeightRandomGap );
|
|
LUA()->RegisterFunction( "load_layer_gap", SCRIPT_CLOUD_LoadLayerGap );
|
|
LUA()->RegisterFunction( "load_move_dir", SCRIPT_CLOUD_LoadMoveDir );
|
|
LUA()->RegisterFunction( "load_path", SCRIPT_CLOUD_LoadPath );
|
|
LUA()->RegisterFunction( "load_type", SCRIPT_CLOUD_LoadType );
|
|
LUA()->RegisterFunction( "load_appear_layer", SCRIPT_CLOUD_LoadAppearLayer );
|
|
LUA()->RegisterFunction( "load_layer_set", SCRIPT_CLOUD_LoadLayerSet );
|
|
// LUA()->RunString( "loadCloudInfo()" );
|
|
|
|
std::string function_call;
|
|
XStringUtil::Format( function_call, "loadCloudInfo()" );
|
|
LUA()->RunString( function_call.c_str() );
|
|
#endif
|
|
}
|
|
|
|
|
|
std::string GetOSInfo()
|
|
{
|
|
//프로세스 메모리 얻는 것 넣어야 함.
|
|
// GetProcessMemoryInfo();
|
|
|
|
OSVERSIONINFO info;
|
|
memset( &info, 0, sizeof(info) );
|
|
info.dwOSVersionInfoSize = sizeof(info);
|
|
if( !GetVersionEx( &info ) ) return "Unknown OS";
|
|
|
|
std::string strName = "Windows ";
|
|
switch( info.dwPlatformId )
|
|
{
|
|
case VER_PLATFORM_WIN32s:
|
|
{
|
|
strName += "Win32s ";
|
|
break;
|
|
}
|
|
case VER_PLATFORM_WIN32_WINDOWS:
|
|
{
|
|
if( info.dwMajorVersion == 4 && info.dwMinorVersion == 0 ) strName += "95 ";
|
|
if( info.dwMajorVersion == 4 && info.dwMinorVersion == 10 ) strName += "98 ";
|
|
if( info.dwMajorVersion == 4 && info.dwMinorVersion == 90 ) strName += "Me ";
|
|
break;
|
|
}
|
|
case VER_PLATFORM_WIN32_NT:
|
|
{
|
|
if( info.dwMajorVersion == 3 && info.dwMinorVersion == 51 ) strName += "NT 3.51 ";
|
|
if( info.dwMajorVersion == 4 && info.dwMinorVersion == 0 ) strName += "NT 4.0 ";
|
|
if( info.dwMajorVersion == 5 && info.dwMinorVersion == 0 ) strName += "2000 ";
|
|
if( info.dwMajorVersion == 5 && info.dwMinorVersion == 1 ) strName += "XP ";
|
|
if( info.dwMajorVersion == 5 && info.dwMinorVersion == 2 ) strName += "2003 ";
|
|
}
|
|
}
|
|
|
|
strName += info.szCSDVersion;
|
|
strName += " ";
|
|
|
|
char buf[256];
|
|
sprintf( buf, "(%d.%d.%d)", info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber );
|
|
strName += buf;
|
|
|
|
return strName;
|
|
}
|
|
|
|
bool RestoreDisplay()
|
|
{
|
|
//화면 해상도 복구
|
|
DEVMODE _devmode = g_dm;
|
|
|
|
if( g_dm_apply.dmPelsWidth != _devmode.dmPelsWidth ||
|
|
g_dm_apply.dmPelsHeight != _devmode.dmPelsHeight )
|
|
{
|
|
if( _devmode.dmPelsWidth != GetGameOption().GetResolution_Width() ||
|
|
_devmode.dmPelsHeight != GetGameOption().GetResolution_Height() )
|
|
{
|
|
ChangeDisplaySettings( &_devmode, 0 );
|
|
|
|
g_dm_apply = _devmode;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ChangeDisplay()
|
|
{
|
|
//화면 해상도 복구
|
|
DEVMODE _devmode = g_dm;
|
|
|
|
if( g_dm_apply.dmPelsWidth != GetGameOption().GetResolution_Width() ||
|
|
g_dm_apply.dmPelsHeight != GetGameOption().GetResolution_Height() )
|
|
{
|
|
_devmode.dmPelsWidth = GetGameOption().GetResolution_Width();
|
|
_devmode.dmPelsHeight = GetGameOption().GetResolution_Height();
|
|
ChangeDisplaySettings( &_devmode, 0 );
|
|
|
|
g_dm_apply = _devmode;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void SetWindowStyle( bool bFullScreen )
|
|
{
|
|
DWORD dwStyle = 0;
|
|
|
|
//전체 모드일때, 캡션 보더 사용안함.
|
|
if(bFullScreen)
|
|
{
|
|
dwStyle = WS_POPUPWINDOW;
|
|
dwStyle &= ~WS_SYSMENU;
|
|
dwStyle &= ~WS_MINIMIZEBOX;
|
|
}
|
|
else
|
|
{
|
|
dwStyle = WS_OVERLAPPEDWINDOW;
|
|
dwStyle &= ~WS_SYSMENU;
|
|
dwStyle |= WS_MINIMIZEBOX;
|
|
}
|
|
|
|
dwStyle &= ~WS_THICKFRAME;
|
|
dwStyle &= ~WS_MAXIMIZEBOX;
|
|
|
|
|
|
//Explorer
|
|
dwStyle |= WS_CLIPCHILDREN;
|
|
dwStyle |= WS_CLIPSIBLINGS;
|
|
|
|
SetWindowLong((HWND) g_hWnd, GWL_STYLE, dwStyle);
|
|
|
|
if(!bFullScreen)
|
|
{
|
|
//int x, y, cx, cy, sx, sy;
|
|
int cx, cy, sx, sy;
|
|
|
|
cx = GetGameOption().GetResolution_Width() + GetSystemMetrics(SM_CXFIXEDFRAME) * 2;
|
|
cy = GetGameOption().GetResolution_Height() + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFIXEDFRAME) * 2;
|
|
|
|
sx = GetSystemMetrics(SM_CXSCREEN);
|
|
sy = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
//SetWindowPos((HWND) m_cs.hWnd, HWND_NOTOPMOST, (sx - cx) / 2, (sy - cy) / 2, cx, cy, SWP_SHOWWINDOW);
|
|
SetWindowPos((HWND) g_hWnd, HWND_NOTOPMOST, (sx - cx) / 2, (sy - cy) / 2, cx, cy, 0);
|
|
}
|
|
else
|
|
{
|
|
int cx, cy;
|
|
|
|
cx = GetGameOption().GetResolution_Width();
|
|
cy = GetGameOption().GetResolution_Height();
|
|
|
|
SetWindowPos((HWND) g_hWnd, HWND_NOTOPMOST, 0, 0, cx, cy, 0);
|
|
}
|
|
|
|
ShowWindow((HWND) g_hWnd, SW_SHOW);
|
|
}
|
|
|
|
void CheckDisplay()
|
|
{
|
|
ZeroMemory(&g_dm , sizeof(g_dm) );
|
|
ZeroMemory(&g_dm_apply, sizeof(g_dm_apply));
|
|
|
|
TCHAR msg[10000] = _T("");
|
|
|
|
DISPLAY_DEVICE dd;
|
|
dd.cb = sizeof(dd);
|
|
DWORD dev = 0; // device index
|
|
int id = 1; // monitor number, as used by Display Properties > Settings
|
|
|
|
while (EnumDisplayDevices(0, dev, &dd, 0))
|
|
{
|
|
if (!(dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
|
|
{
|
|
// ignore virtual mirror displays
|
|
|
|
// get information about the monitor attached to this display adapter. dualhead cards
|
|
// and laptop video cards can have multiple monitors attached
|
|
|
|
DISPLAY_DEVICE ddMon;
|
|
ZeroMemory(&ddMon, sizeof(ddMon));
|
|
ddMon.cb = sizeof(ddMon);
|
|
DWORD devMon = 0;
|
|
|
|
// please note that this enumeration may not return the correct monitor if multiple monitors
|
|
// are attached. this is because not all display drivers return the ACTIVE flag for the monitor
|
|
// that is actually active
|
|
while (EnumDisplayDevices(dd.DeviceName, devMon, &ddMon, 0))
|
|
{
|
|
if (ddMon.StateFlags & DISPLAY_DEVICE_ACTIVE)
|
|
break;
|
|
|
|
devMon++;
|
|
}
|
|
|
|
if (!*ddMon.DeviceString)
|
|
{
|
|
EnumDisplayDevices(dd.DeviceName, 0, &ddMon, 0);
|
|
if (!*ddMon.DeviceString)
|
|
lstrcpy(ddMon.DeviceString, _T("Default Monitor"));
|
|
}
|
|
|
|
// get information about the display's position and the current display mode
|
|
DEVMODE dm;
|
|
ZeroMemory(&dm, sizeof(dm));
|
|
dm.dmSize = sizeof(dm);
|
|
if (EnumDisplaySettingsEx(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm, 0) == FALSE)
|
|
EnumDisplaySettingsEx(dd.DeviceName, ENUM_REGISTRY_SETTINGS, &dm, 0);
|
|
|
|
if( id == 1)
|
|
{
|
|
g_dm = dm;
|
|
g_dm_apply = g_dm;
|
|
}
|
|
|
|
// get the monitor handle and workspace
|
|
HMONITOR hm = 0;
|
|
MONITORINFO mi;
|
|
ZeroMemory(&mi, sizeof(mi));
|
|
mi.cbSize = sizeof(mi);
|
|
if (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
|
|
{
|
|
// display is enabled. only enabled displays have a monitor handle
|
|
POINT pt = { dm.dmPosition.x, dm.dmPosition.y };
|
|
hm = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
|
|
if (hm)
|
|
GetMonitorInfo(hm, &mi);
|
|
}
|
|
|
|
// format information about this monitor
|
|
TCHAR buf[1000];
|
|
|
|
// 1. MyMonitor on MyVideoCard
|
|
wsprintf(buf, _T("%d. %s on %s\r\n"), id, ddMon.DeviceString, dd.DeviceString);
|
|
lstrcat(msg, buf);
|
|
|
|
// status flags: primary, disabled, removable
|
|
buf[0] = _T('\0');
|
|
if (!(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
|
|
lstrcat(buf, _T("disabled, "));
|
|
else if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
|
lstrcat(buf, _T("primary, "));
|
|
if (dd.StateFlags & DISPLAY_DEVICE_REMOVABLE)
|
|
lstrcat(buf, _T("removable, "));
|
|
|
|
if (*buf)
|
|
{
|
|
buf[lstrlen(buf) - 2] = _T('\0');
|
|
lstrcat(buf, _T("\r\n"));
|
|
lstrcat(msg, buf);
|
|
}
|
|
|
|
// width x height @ x,y - bpp - refresh rate
|
|
// note that refresh rate information is not available on Win9x
|
|
wsprintf(buf, _T("%d x %d @ %d,%d - %d-bit - %d Hz\r\n"), dm.dmPelsWidth, dm.dmPelsHeight,
|
|
dm.dmPosition.x, dm.dmPosition.y, dm.dmBitsPerPel, dm.dmDisplayFrequency);
|
|
lstrcat(msg, buf);
|
|
|
|
if (hm)
|
|
{
|
|
// workspace and monitor handle
|
|
|
|
// workspace: x,y - x,y HMONITOR: handle
|
|
wsprintf(buf, _T("workspace: %d,%d - %d,%d HMONITOR: 0x%X\r\n"), mi.rcWork.left,
|
|
mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom, hm);
|
|
lstrcat(msg, buf);
|
|
}
|
|
|
|
// device name
|
|
wsprintf(buf, _T("Device: %s\r\n\r\n"), *ddMon.DeviceName ? ddMon.DeviceName : dd.DeviceName);
|
|
lstrcat(msg, buf);
|
|
|
|
id++;
|
|
}
|
|
|
|
dev++;
|
|
}
|
|
}
|
|
|
|
// { 힙 펜스 (힙 깨진거 찾기 위함.
|
|
#ifndef _DEBUG
|
|
|
|
const int HEAP_FENCE_BEGIN = 0xFA3FDEED;
|
|
const int HEAP_FENCE_END = 0xDC8FBEEF;
|
|
|
|
//#define DETECT_HEAP_OVERRUN
|
|
//#define USE_MEMORY_POOL
|
|
|
|
/*
|
|
라펠즈 프로파일링 결과에 따르면, 약 10분정도 플레이시 블럭 크기별로 아래 횟수만큼 할당/해제가 일어난다.
|
|
해서 48바이트 이하의 할당은 메모리 풀에서 관리하도록 한다. 이는 USE_MEMORY_POOL 로 사용 가능하다.
|
|
|
|
(상위 10개)
|
|
32 1583004
|
|
8 1113468
|
|
16 1037935
|
|
24 1011784
|
|
48 486685
|
|
40 365477
|
|
12 320878
|
|
72 300097
|
|
104 252618
|
|
13 249758
|
|
*/
|
|
|
|
#ifdef USE_MEMORY_POOL
|
|
static bool s_bPoolInitComplete = false;
|
|
int g_nMemAllocCnt[128];
|
|
int POOL_MASK = 0x80000000;
|
|
|
|
XCriticalSection & getHeapCS()
|
|
{
|
|
static XCriticalSection cs;
|
|
return cs;
|
|
}
|
|
|
|
//#define _USE_OLD_POOL
|
|
#ifndef _USE_OLD_POOL
|
|
|
|
#ifdef DETECT_HEAP_OVERRUN
|
|
#define PAREN 8
|
|
#else
|
|
#define PAREN 0
|
|
#endif
|
|
|
|
struct MemPool
|
|
{
|
|
c_unimempool< 8 + 4 + PAREN > Mem8;
|
|
c_unimempool< 16 + 4 + PAREN > Mem16;
|
|
c_unimempool< 32 + 4 + PAREN > Mem32;
|
|
c_unimempool< 24 + 4 + PAREN > Mem24;
|
|
c_unimempool< 48 + 4 + PAREN > Mem48;
|
|
|
|
};
|
|
|
|
static MemPool* s_pool = NULL;
|
|
|
|
struct Module
|
|
{
|
|
Module() { s_pool = new MemPool; s_bPoolInitComplete = true; }
|
|
~Module() { MemPool* p = s_pool; s_pool = NULL; delete p; }
|
|
};
|
|
|
|
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
|
|
{
|
|
static size_t cnt;
|
|
|
|
if ( size == 0 ) // to make D3DX happy - by Tyburn
|
|
size = 1;
|
|
|
|
char *p;
|
|
|
|
if ( size > 48 || !s_pool )
|
|
{
|
|
p = (char*)malloc( size + 4 + PAREN );
|
|
*((size_t *)p) = size;
|
|
}
|
|
else
|
|
{
|
|
THREAD_SYNCRONIZE( getHeapCS() );
|
|
if( size == 32 ) p = (char*)s_pool->Mem32.alloc();
|
|
else if( size == 24 ) p = (char*)s_pool->Mem24.alloc();
|
|
else if( size <= 8 ) p = (char*)s_pool->Mem8.alloc();
|
|
else if( size <= 16 ) p = (char*)s_pool->Mem16.alloc();
|
|
else if( size <= 48 ) p = (char*)s_pool->Mem48.alloc();
|
|
|
|
*((size_t *)p) = size | POOL_MASK;
|
|
}
|
|
|
|
if( size < 128 )
|
|
interlocked_increment( &g_nMemAllocCnt[size] );
|
|
|
|
#ifdef DETECT_HEAP_OVERRUN
|
|
unsigned int *begin = (unsigned int *)( p + 4 );
|
|
unsigned int *end = (unsigned int *)( p + 4 + PAREN/2 + size );
|
|
|
|
*begin = HEAP_FENCE_BEGIN;
|
|
*end = HEAP_FENCE_END;
|
|
|
|
//if(s_bLeackCheck)
|
|
//{
|
|
// g_leakChecker.add(reinterpret_cast<int>(p), StackTrace(2, 1));
|
|
//}
|
|
#endif
|
|
|
|
return p + 4 + PAREN/2;
|
|
}
|
|
|
|
void operator delete( void * p ) throw()
|
|
{
|
|
if( !p )
|
|
return;
|
|
|
|
char *p2 = (char*)p;
|
|
|
|
p2 -= 4 + PAREN/2;
|
|
|
|
size_t *alloc_size = (size_t *)p2;
|
|
|
|
bool bIsPoolMemory = false;
|
|
if( *alloc_size & POOL_MASK )
|
|
{
|
|
*alloc_size &= ( ~POOL_MASK );
|
|
bIsPoolMemory = true;
|
|
}
|
|
|
|
#ifdef DETECT_HEAP_OVERRUN
|
|
|
|
unsigned int *begin = (unsigned int *)( p2 + 4 );
|
|
unsigned int *end = (unsigned int *)( p2 + *alloc_size + 8 );
|
|
|
|
if( *begin != HEAP_FENCE_BEGIN || *end != HEAP_FENCE_END )
|
|
{
|
|
char buf[256];
|
|
sprintf( buf, "%08X : %08X : %d", *begin, *end, *alloc_size );
|
|
MessageBox( NULL, buf, "HEAP!", MB_OK );
|
|
}
|
|
#endif
|
|
|
|
if ( bIsPoolMemory )
|
|
{
|
|
if ( s_pool )
|
|
{
|
|
size_t size = *alloc_size;
|
|
THREAD_SYNCRONIZE( getHeapCS() );
|
|
if( size == 32 ) s_pool->Mem32.free( p2 );
|
|
else if( size == 24 ) s_pool->Mem24.free( p2 );
|
|
else if( size <= 8 ) s_pool->Mem8.free( p2 );
|
|
else if( size <= 16 ) s_pool->Mem16.free( p2 );
|
|
else if( size <= 48 ) s_pool->Mem48.free( p2 );
|
|
}
|
|
else
|
|
assert(0);
|
|
}
|
|
else
|
|
free( p2 );
|
|
|
|
//if(s_bLeackCheck)
|
|
//{
|
|
// if(g_leakChecker.has(reinterpret_cast<int>(p)))
|
|
// g_leakChecker.erase(reinterpret_cast<int>(p));
|
|
//}
|
|
}
|
|
|
|
#undef PAREN
|
|
|
|
#else
|
|
|
|
static bool s_bPoolInitComplete = false;
|
|
|
|
static XMemoryPool* getMemoryPool( size_t size )
|
|
{
|
|
#ifndef USE_MEMORY_POOL
|
|
return 0;
|
|
#endif
|
|
|
|
if( !s_bPoolInitComplete ) return NULL;
|
|
|
|
#ifdef DETECT_HEAP_OVERRUN
|
|
static XMemoryPool s_Mem8( 8 + 12 );
|
|
static XMemoryPool s_Mem32( 32 + 12 );
|
|
static XMemoryPool s_Mem16( 16 + 12 );
|
|
static XMemoryPool s_Mem24( 24 + 12 );
|
|
static XMemoryPool s_Mem48( 48 + 12 );
|
|
#else
|
|
static XMemoryPool s_Mem8( 8 + 4 );
|
|
static XMemoryPool s_Mem32( 32 + 4 );
|
|
static XMemoryPool s_Mem16( 16 + 4 );
|
|
static XMemoryPool s_Mem24( 24 + 4 );
|
|
static XMemoryPool s_Mem48( 48 + 4 );
|
|
#endif
|
|
|
|
s_bPoolInitComplete = true;
|
|
|
|
if( size == 32 ) return &s_Mem32;
|
|
else if( size == 24 ) return &s_Mem24;
|
|
else if( size <= 8 ) return &s_Mem8;
|
|
else if( size <= 16 ) return &s_Mem16;
|
|
else if( size <= 48 ) return &s_Mem48;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
|
|
{
|
|
static size_t cnt;
|
|
|
|
if( size == 0 ) return (void*)0x00000001;
|
|
|
|
XMemoryPool *pPool = getMemoryPool( size );
|
|
|
|
char *p;
|
|
|
|
if( pPool )
|
|
{
|
|
THREAD_SYNCRONIZE( getHeapCS() );
|
|
p = (char*)pPool->Alloc();
|
|
}
|
|
else p = (char*)malloc( size + 12 );
|
|
|
|
size_t *alloc_size = (size_t *)p;
|
|
|
|
|
|
#ifdef _DEBUG
|
|
if( size < 128 ) interlocked_increment( &g_nMemAllocCnt[size] );
|
|
#endif
|
|
|
|
if( pPool ) { *alloc_size |= POOL_MASK; }
|
|
else { *alloc_size = size; }
|
|
|
|
// { 일정 횟수당 한번씩 디버거 붙어 있는지 검사해서 네트웍을 깨버린다.
|
|
#ifndef DISABLE_DEBUGGER_DETECTOR
|
|
#ifndef _DEBUG
|
|
++cnt;
|
|
if( cnt > 1000 )
|
|
{
|
|
if( is_debugger_present() ) XBasicCipher::BreakCipher( (int)p );
|
|
cnt -= 1000;
|
|
}
|
|
#endif
|
|
#endif
|
|
// }
|
|
|
|
#ifdef DETECT_HEAP_OVERRUN
|
|
unsigned int *begin = (unsigned int *)( p + 4 );
|
|
unsigned int *end = (unsigned int *)( p + size + 8 );
|
|
*begin = HEAP_FENCE_BEGIN;
|
|
*end = HEAP_FENCE_END;
|
|
return p + 8;
|
|
#else
|
|
return p + 4;
|
|
#endif
|
|
|
|
}
|
|
|
|
void operator delete( void * p ) throw()
|
|
{
|
|
if( !p || p == (void*)0x00000001 ) return;
|
|
|
|
char *p2 = (char*)p;
|
|
|
|
#ifdef DETECT_HEAP_OVERRUN
|
|
p2 -= 8;
|
|
#else
|
|
p2 -= 4;
|
|
#endif
|
|
|
|
size_t *alloc_size = (size_t *)p2;
|
|
|
|
bool bIsPoolMemory = false;
|
|
if( *alloc_size & POOL_MASK )
|
|
{
|
|
*alloc_size &= ( ~POOL_MASK );
|
|
bIsPoolMemory = true;
|
|
}
|
|
|
|
#ifdef DETECT_HEAP_OVERRUN
|
|
unsigned int *begin = (unsigned int *)( p2 + 4 );
|
|
unsigned int *end = (unsigned int *)( p2 + *alloc_size + 8 );
|
|
|
|
if( *begin != HEAP_FENCE_BEGIN || *end != HEAP_FENCE_END )
|
|
{
|
|
char buf[256];
|
|
sprintf( buf, "%08X : %08X : %d", *begin, *end, *alloc_size );
|
|
MessageBox( g_hWnd, buf, "HEAP!", MB_OK );
|
|
}
|
|
#endif
|
|
|
|
XMemoryPool *pPool = getMemoryPool( *alloc_size );
|
|
|
|
if( bIsPoolMemory )
|
|
{
|
|
if( pPool )
|
|
{
|
|
THREAD_SYNCRONIZE( getHeapCS() );
|
|
pPool->Free( p2 );
|
|
}
|
|
else
|
|
{
|
|
assert( 0 );
|
|
}
|
|
}
|
|
else free( p2 );
|
|
}
|
|
|
|
#endif // _USE_OLD_POOL
|
|
|
|
#endif // USE_MEMORY_POOL
|
|
|
|
#endif // _DEBUG
|
|
|
|
// }
|
|
|
|
|
|
#ifdef _HACK_SHIELD_
|
|
int __stdcall _AhnHS_Callback( long lCode, long lParamSize, void* pParam )
|
|
{
|
|
// sonador 7.4.2 안랩 측 핵쉴드 버그 수정(callback function 내의 static variable 제거)
|
|
bool bDtectAlReadyHooked = true;
|
|
bool bDtectAutoMouse = true;
|
|
bool bDtectHookFuntion = true;
|
|
bool bDtectDriveFailed = true;
|
|
bool bDtectSpeedHack = true;
|
|
bool bDtectSpeedHack_app = true;
|
|
bool bDtectMessageHook = true;
|
|
bool bDtectKDTrace = true;
|
|
bool bDtectKDTraceChanged = true;
|
|
bool bDtectSpeedHackRatio = true;
|
|
bool bDtectGameHack = true;
|
|
bool bDtectGeneralHack = true;
|
|
bool bDtectModuleChange = true;
|
|
bool bDetectAutoMacro = true; // sonador 7.4.1 AHNHS_ACTAPC_DETECT_AUTOMACRO 관련 callback 처리
|
|
bool bDetectNanoEngineFailed = true; // sonador 7.4.4 핵쉴드 270 적용
|
|
bool bDetectCodeMismatch = true; //
|
|
|
|
|
|
bool bExitGame = false;
|
|
|
|
GameSecurityMsg::MSG_TYPE msgtype = GameSecurityMsg::MSG_MAX;
|
|
|
|
switch( lCode )
|
|
{
|
|
/* case AHNHS_ACTAPC_DETECT_ALREADYHOOKED: //"일부 API가 이미 후킹되어 있는 상태입니다. (그러나 실제로는 이를 차단하고 있기 때문에 후킹프로그램은 동작하지 않습니다.)";
|
|
{ //운영 룰 : 아무것도 안함
|
|
if( bDtectAlReadyHooked )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_ALREADYHOOKED;
|
|
bDtectAlReadyHooked = false;
|
|
}
|
|
break;
|
|
}*/
|
|
case AHNHS_ACTAPC_DETECT_AUTOMOUSE: //"오토마우스 행위가 감지되었습니다.";
|
|
{ //운영 룰 : 메세지 출력 및 종료
|
|
if( bDtectAutoMouse )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_AUTOMOUSE;
|
|
bDtectAutoMouse = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_HOOKFUNCTION: //"보호 API에 대한 후킹 행위가 감지되었습니다.";
|
|
{ //운영 룰 : 메세지 출력 및 종료
|
|
if( bDtectHookFuntion )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_HOOKFUNCTION;
|
|
bDtectHookFuntion = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_DRIVERFAILED: //"해킹 차단 드라이버가 로드되지 않았습니다.";
|
|
{ //운영 룰 : 메세지 출력 및 종료
|
|
if( bDtectDriveFailed )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_DRIVERFAILED;
|
|
bDtectDriveFailed = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_SPEEDHACK: //"스피드핵류의 프로그램에 의해 시스템 시간이 변경되었습니다.";
|
|
{ //운영 룰 : 메세지 출력 및 종료
|
|
if( bDtectSpeedHack )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_SPEEDHACK;
|
|
bDtectSpeedHack = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_SPEEDHACK_APP: //"스피드핵류의 프로그램에 의해 시스템 시간이 변경되었습니다.";
|
|
{ //운영 룰 : 메세지 출력 및 종료
|
|
if( bDtectSpeedHack_app )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_SPEEDHACK_APP;
|
|
bDtectSpeedHack_app = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_MESSAGEHOOK: //"메시지 후킹이 시도되었으며 이를 차단하지 못했습니다.";
|
|
{ //운영 룰 : 메세지 출력 및 종료
|
|
if( bDtectMessageHook )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_MESSAGEHOOK;
|
|
bDtectMessageHook = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_KDTRACE: //"디버거 트래이싱이 발생했다.(커널 디버거 활성화, 이후 브레이크 포인터 처리)";
|
|
{ //운영 룰 : 메세지 출력 및 종료
|
|
if( bDtectKDTrace )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_KDTRACE;
|
|
bDtectKDTrace = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_KDTRACE_CHANGED: //"설치된 디버거 트래이싱이 변경되었다.";
|
|
{ //운영 룰 : 메세지 출력 및 종료
|
|
if( bDtectKDTraceChanged )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_KDTRACE_CHANGED;
|
|
bDtectKDTraceChanged = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_SPEEDHACK_RATIO: //"스피드핵 감지 옵션이 'GAME'이 경우 이 콜백으로 최근 5초동안의 시간정보가 전달됩니다.";
|
|
{
|
|
if( bDtectSpeedHackRatio )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_SPEEDHACK_RATIO;
|
|
bDtectSpeedHackRatio = false;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ENGINE_DETECT_GAME_HACK: //"게임 해킹툴의 실행이 발견되었습니다.";
|
|
{ //운영 룰 : 메세지 출력 및 종료
|
|
if( bDtectGameHack )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_GAME_HACK;
|
|
bDtectGameHack = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ENGINE_DETECT_GENERAL_HACK: //"일반 해킹툴(트로이목마 종류)이 발견되었습니다.";
|
|
{ //운영 룰 : 메세지 출력 Yes, No
|
|
if( bDtectGeneralHack )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_GENERAL_HACK;
|
|
bDtectGeneralHack = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_MODULE_CHANGE: //"핵쉴드 관련모듈이 변경되었습니다.";
|
|
{
|
|
//운영 룰 : 메세지 출력
|
|
if( bDtectModuleChange )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_MODULE_CHANGE;
|
|
bDtectModuleChange = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_AUTOMACRO: // sonador 7.4.1 AHNHS_ACTAPC_DETECT_AUTOMACRO 관련 callback 처리
|
|
{
|
|
if( bDetectAutoMacro )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_AUTOMACRO;
|
|
bDetectAutoMacro = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_ENGINEFAILED: // sonador 7.4.4 핵쉴드 270 적용
|
|
{
|
|
if( bDetectNanoEngineFailed )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_ENGINEFAILED;
|
|
bDetectNanoEngineFailed = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
case AHNHS_ACTAPC_DETECT_CODEMISMATCH: // sonacor 7.4.4 핵쉴드 270 적용
|
|
{
|
|
if( bDetectCodeMismatch )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_HACK_SHIELD_DETECT_CODEMISMATCH;
|
|
bDetectCodeMismatch = false;
|
|
bExitGame = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( bExitGame )
|
|
{
|
|
GameSecurityMsg* pSecurityMsg = new GameSecurityMsg;
|
|
pSecurityMsg->nMsgType = msgtype;
|
|
pSecurityMsg->nNativeCode = static_cast< unsigned long >( lCode ); // sonador 7.4.3 해킹 툴 감지후 종료 프로세스 구현
|
|
g_SecurityMsg.push_back( pSecurityMsg );
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// sonador 7.4.4 핵쉴드 270 적용
|
|
bool UpdateHackShieldService()
|
|
{
|
|
TCHAR *pEnd = NULL;
|
|
TCHAR lpszUpdateDir[MAX_PATH] = { 0, };
|
|
|
|
GetModuleFileName(NULL, lpszUpdateDir, MAX_PATH);
|
|
pEnd = _tcsrchr( lpszUpdateDir, _T('\\')) + 1;
|
|
|
|
if (!pEnd)
|
|
{
|
|
TCHAR strResult[1024];
|
|
_sntprintf( strResult, 1024, TEXT("HackShieldService Failed - %s"), lpszUpdateDir );
|
|
MessageBox( NULL, strResult, TEXT("Error"), MB_OK | MB_ICONERROR );
|
|
|
|
return false;
|
|
}
|
|
|
|
*pEnd = _T('\0');
|
|
lstrcat(lpszUpdateDir, _T("HackShield"));
|
|
|
|
int nResult = _AhnHS_HSUpdate( lpszUpdateDir, 600000 ); // sonador 7.4.6 스마트 업데이트 대기 시간 수정
|
|
if( nResult != HACKSHIELD_ERROR_SUCCESS )
|
|
{
|
|
std::string strerr;
|
|
switch( nResult )
|
|
{
|
|
case HSERROR_ENVFILE_NOTREAD: strerr = S( 4132 ); break; // "HSUpdate.env 파일을 읽을 수 없습니다."
|
|
case HSERROR_ENVFILE_NOTWRITE: strerr = S( 4133 ); break; // "HSUpdate.env 파일을 쓸 수 없습니다."
|
|
case HSERROR_NETWORK_CONNECT_FAIL: strerr = S( 4134 ); break; // "해당 서버에 연결할 수 없습니다."
|
|
case HSERROR_LIB_NOTEDIT_REG: strerr = S( 4135 ); break; // "네트워크 결과 입력 중에 오류가 발생하였습니다."
|
|
case HSERROR_NOTFINDFILE: strerr = S( 4136 ); break; // "HackShield 업데이트 프로그램 관련 파일을 찾을 수 없습니다."
|
|
case HSERROR_PROTECT_LISTLOAD_FAIL: strerr = S( 4137 ); break; // "HSUpdate.pt 인증 파일을 찾을 수 없습니다."
|
|
case HSERROR_HSUPDATE_TIMEOUT: strerr = S( 4138 ); break; // "HackShield 업데이트 프로그램이 업데이트 전송 시간을 초과하였습니다."
|
|
default: strerr = S( 4139 ); break; // "HackShield 업데이트 오류"
|
|
}
|
|
|
|
strerr = nsl::format( "%s(%d)\n", strerr.c_str(), nResult );
|
|
|
|
/* if( g_pFLog )
|
|
{
|
|
fprintf( g_pFLog, "%d%s\n", nResult, strerr.c_str() );
|
|
fflush( g_pFLog );
|
|
}
|
|
*/
|
|
MessageBox( g_hWnd, strerr.c_str(), "Rappelz-HackShield", MB_OK | MB_ICONERROR );
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool StartHackShieldService()
|
|
{
|
|
TCHAR *pEnd = NULL;
|
|
TCHAR szFullFileName[MAX_PATH] = { 0, };
|
|
|
|
GetModuleFileName(NULL, szFullFileName, MAX_PATH);
|
|
pEnd = _tcsrchr( szFullFileName, _T('\\')) + 1;
|
|
|
|
if (!pEnd)
|
|
{
|
|
TCHAR strResult[1024];
|
|
_sntprintf( strResult, 1024, TEXT("HackShieldService Failed - %s"), szFullFileName );
|
|
MessageBox( NULL, strResult, TEXT("Error"), MB_OK | MB_ICONERROR );
|
|
|
|
return false;
|
|
}
|
|
|
|
*pEnd = _T('\0');
|
|
lstrcat(szFullFileName, _T("HackShield\\EhSvc.dll"));
|
|
|
|
#ifdef 국내
|
|
// const int nGameCode = 2802; //Trial
|
|
// const char* szLicense = "619B435F75BB9AB73733DD71"; //Trial
|
|
|
|
const int nGameCode = 2803; //Commercial
|
|
const char* szLicense = "4DBC3A48AE1B5DA2FFC82149"; //Commercial
|
|
#endif
|
|
|
|
#ifdef 미국
|
|
const int nGameCode = 2804;
|
|
const char* szLicense = "1C7DF61A08F7C881CECEBA22";
|
|
#endif
|
|
|
|
#ifdef _HONGKONG_
|
|
const int nGameCode = 2802;
|
|
const char* szLicense = "619B435F75BB9AB73733DD71";
|
|
#endif
|
|
|
|
#ifdef _JAPAN_
|
|
const int nGameCode = 2802;
|
|
const char* szLicense = "619B435F75BB9AB73733DD71";
|
|
#endif
|
|
|
|
#ifdef 중국
|
|
const int nGameCode = 2805;
|
|
const char* szLicense = "33C5A763CA347F50C77820FE";
|
|
#endif
|
|
|
|
#ifdef 독일
|
|
const int nGameCode = 6912; //Original
|
|
const char* szLicense = "2422F23A8217FD6E295891A9"; //Original
|
|
#endif
|
|
|
|
#ifdef 프랑스
|
|
const int nGameCode = 6912; //Original
|
|
const char* szLicense = "2422F23A8217FD6E295891A9"; //Original
|
|
#endif
|
|
|
|
#ifdef _RELEASE
|
|
//배포용 옵션
|
|
// const DWORD dwOption = AHNHS_CHKOPT_ALL | AHNHS_ALLOW_SVCHOST_OPENPROCESS | AHNHS_ALLOW_LSASS_OPENPROCESS | AHNHS_ALLOW_CSRSS_OPENPROCESS | AHNHS_DISPLAY_HACKSHIELD_LOGO;
|
|
#ifdef _COUNTRY_CN_
|
|
const DWORD dwOption = AHNHS_CHKOPT_READWRITEPROCESSMEMORY \
|
|
| AHNHS_CHKOPT_KDTRACER \
|
|
| AHNHS_CHKOPT_OPENPROCESS \
|
|
| AHNHS_CHKOPT_AUTOMOUSE \
|
|
| AHNHS_CHKOPT_PROCESSSCAN \
|
|
| AHNHS_CHKOPT_HSMODULE_CHANGE \
|
|
| AHNHS_USE_LOG_FILE \
|
|
| AHNHS_ALLOW_SVCHOST_OPENPROCESS \
|
|
| AHNHS_ALLOW_LSASS_OPENPROCESS \
|
|
| AHNHS_ALLOW_CSRSS_OPENPROCESS \
|
|
| AHNHS_DONOT_TERMINATE_PROCESS \
|
|
| AHNHS_CHKOPT_SPEEDHACK \
|
|
| AHNHS_CHKOPT_MESSAGEHOOK;
|
|
|
|
#else
|
|
const DWORD dwOption = AHNHS_CHKOPT_READWRITEPROCESSMEMORY \
|
|
| AHNHS_CHKOPT_KDTRACER \
|
|
| AHNHS_CHKOPT_OPENPROCESS \
|
|
| AHNHS_CHKOPT_AUTOMOUSE \
|
|
| AHNHS_CHKOPT_PROCESSSCAN \
|
|
| AHNHS_CHKOPT_HSMODULE_CHANGE \
|
|
| AHNHS_USE_LOG_FILE \
|
|
| AHNHS_ALLOW_SVCHOST_OPENPROCESS \
|
|
| AHNHS_ALLOW_LSASS_OPENPROCESS \
|
|
| AHNHS_ALLOW_CSRSS_OPENPROCESS \
|
|
| AHNHS_DONOT_TERMINATE_PROCESS \
|
|
| AHNHS_DISPLAY_HACKSHIELD_LOGO \
|
|
| AHNHS_CHKOPT_MESSAGEHOOK; // SetHook 동작 안 됨.
|
|
//| AHNHS_CHKOPT_SPEEDHACK 노트북 문제로 제거 되었음.
|
|
#endif
|
|
#else
|
|
//디버깅용 옵션
|
|
const DWORD dwOption = AHNHS_CHKOPT_READWRITEPROCESSMEMORY \
|
|
| AHNHS_CHKOPT_OPENPROCESS \
|
|
| AHNHS_CHKOPT_AUTOMOUSE \
|
|
| AHNHS_CHKOPT_MESSAGEHOOK \
|
|
| AHNHS_CHKOPT_PROCESSSCAN \
|
|
| AHNHS_CHKOPT_HSMODULE_CHANGE \
|
|
| AHNHS_USE_LOG_FILE \
|
|
| AHNHS_ALLOW_SVCHOST_OPENPROCESS | AHNHS_ALLOW_LSASS_OPENPROCESS | AHNHS_ALLOW_CSRSS_OPENPROCESS | AHNHS_DISPLAY_HACKSHIELD_LOGO;
|
|
#endif
|
|
|
|
const unsigned int unSHackSensingRatio = AHNHS_SPEEDHACK_SENSING_RATIO_NORMAL;
|
|
/*
|
|
if( g_pFLog == NULL )
|
|
g_pFLog = fopen( "rappelz_HShield.log", "a+" );
|
|
*/
|
|
int nResult = _AhnHS_Initialize( szFullFileName
|
|
, _AhnHS_Callback
|
|
, nGameCode
|
|
, szLicense
|
|
, dwOption
|
|
, unSHackSensingRatio );
|
|
|
|
if( nResult == HS_ERR_OK )
|
|
{
|
|
// 함수 호출 성공
|
|
int nStartSVResult = _AhnHS_StartService();
|
|
if( nStartSVResult != HS_ERR_OK )
|
|
{
|
|
std::string strerr;
|
|
switch( nStartSVResult )
|
|
{
|
|
case HS_ERR_START_ENGINE_FAILED: strerr = S( 4107 ); break; //"해킹 프로그램 감지 엔진을 시작할 수 없습니다.";
|
|
case HS_ERR_ALREADY_SERVICE_RUNNING: strerr = S( 4108 ); break; //"이미 핵쉴드 서비스가 실행 중입니다.";
|
|
case HS_ERR_DRV_FILE_CREATE_FAILED: strerr = S( 4109 ); break; //"핵 쉴드 드라이버 파일을 생성할 수 없습니다.";
|
|
case HS_ERR_REG_DRV_FILE_FAILED: strerr = S( 4110 ); break; //"핵 쉴드 드라이버를 등록할 수 없습니다.";
|
|
case HS_ERR_START_DRV_FAILED: strerr = S( 4111 ); break; //"핵 쉴드 드라이버를 시작할 수 없습니다.";
|
|
}
|
|
/*
|
|
if( g_pFLog )
|
|
{
|
|
fprintf( g_pFLog, "%d%s\n", nStartSVResult, strerr.c_str() );
|
|
fflush( g_pFLog );
|
|
}
|
|
*/
|
|
MessageBox( g_hWnd, strerr.c_str(), "Rappelz-HackShield", MB_OK | MB_ICONERROR );
|
|
return false;
|
|
}
|
|
|
|
// MessageBox( g_hWnd, "HackShield 성공적으로 수행됨", "HackShield", MB_OK );
|
|
|
|
g_bStartingHSService = true;
|
|
}
|
|
else
|
|
{
|
|
std::string strerr;
|
|
switch( nResult )
|
|
{
|
|
case HS_ERR_UNKNOWN: strerr = S( 4112 ); break; //"알 수 없는 오류가 발생했습니다."; break; //"알 수 없는 오류가 발생했습니다.";
|
|
case HS_ERR_INVALID_PARAM: strerr = S( 4113 ); break; //"올바르지 않은 인자입니다."; break; //"올바르지 않은 인자입니다.";
|
|
case HS_ERR_NOT_INITIALIZED: strerr = S( 4114 ); break; //"핵쉴드 모듈이 초기화되지 않은 상태입니다."; break; //"핵쉴드 모듈이 초기화되지 않은 상태입니다.";
|
|
case HS_ERR_COMPATIBILITY_MODE_RUNNING: strerr = S( 4115 ); break; //"현재 프로세스가 호환성 모드로 실행되었습니다."; break; //"현재 프로세스가 호환성 모드로 실행되었습니다.";
|
|
case HS_ERR_INVALID_LICENSE: strerr = S( 4116 ); break; //"올바르지 않은 라이센스 키입니다."; break; //"올바르지 않은 라이센스 키입니다.";
|
|
case HS_ERR_INVALID_FILES: strerr = S( 4117 ); break; //"잘못된 파일 설치되었습니다. 프로그램을 재설치하시기 바랍니다."; break; //"잘못된 파일 설치되었습니다. 프로그램을 재설치하시기 바랍니다.";
|
|
case HS_ERR_INIT_DRV_FAILED: strerr = S( 4118 ); break; //"해킹 차단 기능 드라이버 초기하에 실패하여 해킹 차단 기능이 정상 동작할 수 없습니다."; break; //"해킹 차단 기능 드라이버 초기하에 실패하여 해킹 차단 기능이 정상 동작할 수 없습니다.";
|
|
case HS_ERR_ANOTHER_SERVICE_RUNNING: strerr = S( 4119 ); break; //"다른 게임이나 프로세스에서 핵쉴드를 이미 사용하고 있습니다."; break; //"다른 게임이나 프로세스에서 핵쉴드를 이미 사용하고 있습니다.";
|
|
case HS_ERR_ALREADY_INITIALIZED: strerr = S( 4120 ); break; //"이미 핵쉴드 모듈이 초기화되어 있습니다."; break; //"이미 핵쉴드 모듈이 초기화되어 있습니다.";
|
|
case HS_ERR_DEBUGGER_DETECT: strerr = S( 4121 ); break; //"컴퓨터에서 디버거 실행이 감지되었습니다. 디버거의 실행을 중지시킨 뒤에 다시 실행시켜주시기바랍니다."; break; //"컴퓨터에서 디버거 실행이 감지되었습니다. 디버거의 실행을 중지시킨 뒤에 다시 실행시켜주시기바랍니다.";
|
|
case HS_ERR_EXECUTABLE_FILE_CRACKED: strerr = S( 4122 ); break; //"실행 파일의 코드가 크랙 되었습니다."; break; //"실행 파일의 코드가 크랙 되었습니다.";
|
|
case HS_ERR_NEED_ADMIN_RIGHTS: strerr = S( 4123 ); break; //"ADMIN 권한이 필요합니다."; break; //"ADMIN 권한이 필요합니다.";
|
|
case HS_ERR_START_ENGINE_FAILED: strerr = S( 4124 ); break; //"해킹 프로그램 감지 엔진을 시작할 수 없습니다."; break; //"해킹 프로그램 감지 엔진을 시작할 수 없습니다.";
|
|
case HS_ERR_ALREADY_SERVICE_RUNNING: strerr = S( 4125 ); break; //"이미 핵 쉴드 서비스가 실행 중입니다."; break; //"이미 핵 쉴드 서비스가 실행 중입니다.";
|
|
case HS_ERR_DRV_FILE_CREATE_FAILED: strerr = S( 4126 ); break; //"핵 쉴드 드라이버 파일을 생성할 수 없습니다."; break; //"핵 쉴드 드라이버 파일을 생성할 수 없습니다.";
|
|
case HS_ERR_REG_DRV_FILE_FAILED: strerr = S( 4127 ); break; //"핵 쉴드 드라이버를 등록할 수 없습니다."; break; //"핵 쉴드 드라이버를 등록할 수 없습니다.";
|
|
case HS_ERR_START_DRV_FAILED: strerr = S( 4128 ); break; //"핵 쉴드 드라이버를 시작할 수 없습니다."; break; //"핵 쉴드 드라이버를 시작할 수 없습니다.";
|
|
case HS_ERR_SERVICE_NOT_RUNNING: strerr = S( 4129 ); break; //"핵 쉴드 서비스가 실행되고 있지 않은 상태입니다."; break; //"핵 쉴드 서비스가 실행되고 있지 않은 상태입니다.";
|
|
case HS_ERR_SERVICE_STILL_RUNNING: strerr = S( 4130 ); break; //"핵 쉴드 서비스가 아직 실행중인 상태입니다."; break; //"핵 쉴드 서비스가 아직 실행중인 상태입니다.";
|
|
case HS_ERR_NEED_UPDATE: strerr = S( 4131 ); break; //"핵 쉴드 모듈의 업데이트가 필요합니다."; break; //"핵 쉴드 모듈의 업데이트가 필요합니다.";
|
|
}
|
|
|
|
/* if( g_pFLog )
|
|
{
|
|
fprintf( g_pFLog, "%d%s\n", nResult, strerr.c_str() );
|
|
fflush( g_pFLog );
|
|
}
|
|
*/
|
|
MessageBox( g_hWnd, strerr.c_str(), "Rappelz-HackShield", MB_OK | MB_ICONERROR );
|
|
return false;
|
|
}
|
|
|
|
_AhnHS_SaveFuncAddress( 7, _AhnHS_Callback, StartHackShieldService, WndProc, HotKeyProc, &SGameVM::onReadEvent, &SGameManager::PendMessage, &SGameManager::ReqMove );
|
|
|
|
return true;
|
|
}
|
|
|
|
void StopHackShieldService()
|
|
{
|
|
_AhnHS_StopService();
|
|
_AhnHS_Uninitialize();
|
|
}
|
|
|
|
void PauseHackShieldService()
|
|
{
|
|
_AhnHS_PauseService( AHNHS_CHKOPT_MESSAGEHOOK );
|
|
}
|
|
|
|
void ResumeHackShieldService()
|
|
{
|
|
_AhnHS_ResumeService( AHNHS_CHKOPT_MESSAGEHOOK );
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
BOOL CALLBACK NPGameMonCallback(DWORD dwMsg, DWORD dwArg)
|
|
{
|
|
static bool bDtectCommClose = true;
|
|
static bool bDtectInitError = true;
|
|
static bool bDtectSpeedHack = true;
|
|
static bool bDtectGameHackKilled = true;
|
|
static bool bDtectGameHackDetect = true;
|
|
static bool bDtectGamehack_Doubt = true;
|
|
|
|
bool bExitGame = false;
|
|
|
|
GameSecurityMsg::MSG_TYPE msgtype = GameSecurityMsg::MSG_MAX;
|
|
|
|
std::string strHackMsg;
|
|
|
|
switch (dwMsg)
|
|
{
|
|
case NPGAMEMON_COMM_ERROR: //GameMon과의 통신 채널이 끊어졌습니다.
|
|
case NPGAMEMON_COMM_CLOSE:
|
|
{
|
|
if( bDtectCommClose )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_NPROTECT_COMM_CLOSE;
|
|
bDtectCommClose = false;
|
|
bExitGame = true;
|
|
}
|
|
}
|
|
break;
|
|
case NPGAMEMON_INIT_ERROR: //GameMon 실행 에러
|
|
{
|
|
if( bDtectInitError )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_NPROTECT_INIT_ERROR;
|
|
bDtectInitError = false;
|
|
bExitGame = true;
|
|
|
|
XStringUtil::Format( strHackMsg, "게임가드 초기화 에러 : %lu", dwArg );
|
|
}
|
|
}
|
|
break;
|
|
case NPGAMEMON_SPEEDHACK: //스피드핵이 감지되었습니다
|
|
{
|
|
if( bDtectSpeedHack )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_NPROTECT_SPEEDHACK;
|
|
bDtectSpeedHack = false;
|
|
bExitGame = true;
|
|
|
|
XStringUtil::Format( strHackMsg, "스피드핵이 감지되었습니다." );
|
|
}
|
|
}
|
|
break;
|
|
case NPGAMEMON_GAMEHACK_KILLED: //게임핵이 발견되었습니다
|
|
{
|
|
if( bDtectGameHackKilled )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_NPROTECT_GAMEHACK_KILLED;
|
|
bDtectGameHackKilled = false;
|
|
bExitGame = true;
|
|
|
|
//XStringUtil::Format( strHackMsg, "게임핵이 발견되었습니다.\r\n%s", npgl.GetInfo() );
|
|
XStringUtil::Format( strHackMsg, "게임핵이 발견되었습니다.\r\n%s", g_pNpgl->GetInfo() );
|
|
|
|
}
|
|
}
|
|
break;
|
|
case NPGAMEMON_GAMEHACK_DETECT: //게임핵이 발견되었습니다
|
|
{
|
|
if( bDtectGameHackDetect )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_NPROTECT_GAMEHACK_DETECT;
|
|
bDtectGameHackDetect = false;
|
|
bExitGame = true;
|
|
|
|
XStringUtil::Format( strHackMsg, "게임핵이 발견되었습니다.\r\n%s", g_pNpgl->GetInfo() );
|
|
}
|
|
}
|
|
break;
|
|
case NPGAMEMON_GAMEHACK_DOUBT:
|
|
{
|
|
if( bDtectGamehack_Doubt )
|
|
{
|
|
msgtype = GameSecurityMsg::MSG_NPROTECT_GAMEHACK_DOUBT;
|
|
bDtectGamehack_Doubt = false;
|
|
bExitGame = true;
|
|
|
|
XStringUtil::Format( strHackMsg, "게임이나 게임가드가 변조되었습니다." );
|
|
}
|
|
}
|
|
break;
|
|
case NPGAMEMON_GAMEHACK_REPORT:
|
|
{
|
|
DWORD dwHackInfoSize = 0;
|
|
LPBYTE pHackInfo = NULL;
|
|
pHackInfo = g_pNpgl->GetHackInfo( &dwHackInfoSize );
|
|
if( pHackInfo && dwHackInfoSize > 0 )
|
|
{
|
|
//SendToHackLog( pHackInfo, dwHackInfoSiz e); // 서버로 데이터 전송
|
|
}
|
|
}
|
|
break;
|
|
case NPGAMEMON_CHECK_CSAUTH2:
|
|
{
|
|
GG_AUTH_DATA authData;
|
|
memcpy(&authData, (PVOID)dwArg, sizeof(authData));
|
|
|
|
if( g_pSBotMng->GameGuardSendToServer( &authData ) == false )
|
|
{
|
|
/* if( g_pFLog )
|
|
{
|
|
fprintf( g_pFLog, "%s\n", "if( sizeof( TS_CS_GAME_GUARD_AUTH_ANSWER ) != sizeof( GG_AUTH_DATA ) )" );
|
|
fflush( g_pFLog );
|
|
}*/
|
|
}
|
|
}
|
|
break;
|
|
case NPGAMEMON_CHECK_CSAUTH3:
|
|
{
|
|
PCSAuth3Data pCSAuth3 = (PCSAuth3Data)dwArg;
|
|
g_pSBotMng->GameGuardSendToServer( pCSAuth3 );
|
|
}
|
|
break;
|
|
}
|
|
|
|
if( bExitGame )
|
|
{
|
|
/* if( g_pFLog == NULL )
|
|
g_pFLog = fopen( "rappelz_nProtect.log", "a+" );
|
|
|
|
if( g_pFLog && !strHackMsg.empty() )
|
|
{
|
|
fprintf( g_pFLog, "%s\n", strHackMsg.c_str() );
|
|
fflush( g_pFLog );
|
|
}
|
|
*/
|
|
#ifdef _DEV
|
|
SLOG("nPROTECT - %s\n", strHackMsg.c_str());
|
|
#endif
|
|
GameSecurityMsg* pSecurityMsg = new GameSecurityMsg;
|
|
pSecurityMsg->nMsgType = msgtype;
|
|
pSecurityMsg->nNativeCode = static_cast< unsigned long >( dwMsg ); // sonador 7.4.3 해킹 툴 감지후 종료 프로세스 구현
|
|
g_SecurityMsg.push_back( pSecurityMsg );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool StartnProtectService()
|
|
{
|
|
DWORD dwResult = g_pNpgl->Init();
|
|
if (dwResult != NPGAMEMON_SUCCESS)
|
|
{
|
|
std::string strerr;
|
|
|
|
// ‘6. 주요에러코드’를 참조하여 상황에 맞는 메시지를 출력해줍니다.
|
|
switch (dwResult)
|
|
{
|
|
case NPGAMEMON_ERROR_EXIST: strerr = S( 769 ); break; //"게임가드가 실행 중 입니다. 잠시 후나 재부팅 후에 다시 실행해보시기 바랍니다."
|
|
case NPGAMEMON_ERROR_GAME_EXIST: strerr = S( 770 ); break; //"게임이 중복 실행되었거나 게임가드가 이미 실행 중 입니다. 게임 종료 후 다시 실행해보시기 바랍니다."
|
|
case NPGAMEMON_ERROR_INIT:
|
|
{
|
|
if (GGGetLastError() == 14000)
|
|
strerr = S( 183 ); // 게임가드에서 가상머신을 차단하였을 때 출력되는 메세지
|
|
else
|
|
strerr = S( 771 ); //"게임가드 초기화 에러입니다. 재부팅 후 다시 실행해보거나 충돌할 수 있는 다른 프로그램들을 종료한 후 실행해 보시기 바랍니다."
|
|
}
|
|
break;
|
|
case NPGAMEMON_ERROR_AUTH_GAMEGUARD:
|
|
case NPGAMEMON_ERROR_NFOUND_GG:
|
|
case NPGAMEMON_ERROR_AUTH_INI:
|
|
case NPGAMEMON_ERROR_CORRUPT_INI:
|
|
case NPGAMEMON_ERROR_CORRUPT_INI2:
|
|
case NPGAMEMON_ERROR_NFOUND_INI: strerr = S( 772 ); break; //"게임가드 파일이 없거나 변조되었습니다. 게임가드 셋업 파일을 설치해보시기 바랍니다."
|
|
case NPGAMEMON_ERROR_CRYPTOAPI: strerr = S( 773 ); break; //"윈도우의 일부 시스템 파일이 손상되었습니다. 인터넷 익스플로러(IE)를 다시 설치해보시기 바랍니다."
|
|
case NPGAMEMON_ERROR_EXECUTE: strerr = S( 774 ); break; //"게임가드 실행에 실패했습니다. 게임가드 셋업 파일을 다시 설치해보시기 바랍니다."
|
|
case NPGAMEMON_ERROR_ILLEGAL_PRG: strerr = S( 775 ); break; //"불법 프로그램이 발견되었습니다. 불필요한 프로그램을 종료한 후 다시 실행해보시기 바랍니다."
|
|
case NPGMUP_ERROR_ABORT: strerr = S( 776 ); break; //"게임가드 업데이트를 취소하셨습니다. 접속이 계속 되지 않을 경우 인터넷 및 개인 방화벽 설정을 조정해 보시기 바랍니다."
|
|
case NPGMUP_ERROR_CONNECT:
|
|
// case HOOK_TIMEOUT: strerr = S( 777 ); break; //"바이러스나 스파이웨어로 인해 후킹이 실패하였습니다. 최신백신을 받으신 후 컴퓨터 전체검사를 해봅니다."
|
|
case NPGAMEMON_ERROR_GAMEGUARD: strerr = S( 778 ); break; //"게임가드 초기화 에러 또는 구버젼의 게임가드 파일입니다. 게임가드 셋업파일을 다시 설치하고 게임을 실행해봅니다."
|
|
case NPGMUP_ERROR_PARAM: strerr = S( 779 ); break; //"ini 파일이 없거나 변조되었습니다. 게임가드 셋업 파일을 설치하면 해결할 수 있습니다."
|
|
case NPGMUP_ERROR_INIT: strerr = S( 780 ); break; //"npgmup.des 초기화 에러입니다. 게임가드폴더를 삭제후 다시 게임실행을 해봅니다."
|
|
case 128: strerr = S( 781 ); break; //"검증되지 않은 Windows XP x64 버전을 실행한 경우입니다. 최신으로 버전으로 설치후 게임실행을 해봅니다."
|
|
case NPGMUP_ERROR_DOWNCFG: strerr = S( 783 ); break; //"게임가드 업데이트 서버 접속에 실패하였습니다. 잠시 후 재시도 해보거나, 개인 방화벽이 있다면 설정을 조정해 보시기 바랍니다."
|
|
case NPGMUP_ERROR_AUTH: strerr = S( 784 ); break; //"게임가드 업데이트를 완료하지 못 했습니다. 바이러스 백신을 일시 중시 시킨 후 재시도 해보시거나, PC 관리 프로그램을 사용하시면 설정을 조정해 보시기 바랍니다."
|
|
case NPGAMEMON_ERROR_NPSCAN: strerr = S( 785 ); break; //"바이러스 및 해킹툴 검사 모듈 로딩에 실패 했습니다. 메모리 부족이거나 바이러스에 의한 감염일 수 있습니다."
|
|
case NPGG_ERROR_COLLISION: //"게임가드와 충돌 프로그램이 발겫되었습니다."
|
|
default:
|
|
{
|
|
// 적절한 종료 메시지 출력
|
|
strerr = S( 791 ); break; //"게임가드 실행 중 에러가 발생하였습니다. 게임 폴더 안의 GameGuard 폴더에 있는 *.erl 파일들을 Game1@inca.co.kr로 첨부하여 메일 보내주시기 바랍니다."
|
|
}
|
|
break;
|
|
}
|
|
|
|
if( g_pFLog == NULL )
|
|
g_pFLog = fopen( "rappelz_nProtect.log", "a+" );
|
|
|
|
if( g_pFLog )
|
|
{
|
|
fprintf( g_pFLog, "%lu %s\n", dwResult, strerr.c_str() );
|
|
fflush( g_pFLog );
|
|
}
|
|
|
|
#ifdef _DEV
|
|
SLOG("%lu %s\n", dwResult, strerr.c_str());
|
|
#endif
|
|
strerr = CStringUtil::StringFormat( "err code[%d]:%s", dwResult, strerr.c_str() );
|
|
MessageBox( g_hWnd, strerr.c_str(), "Rappelz-nProtect", MB_OK | MB_ICONERROR );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
|
|
|
|
BOOL CheckOSVersion()
|
|
{
|
|
OSVERSIONINFOEX osvi;
|
|
SYSTEM_INFO si;
|
|
PGNSI pGNSI;
|
|
BOOL bOsVersionInfoEx;
|
|
|
|
ZeroMemory(&si, sizeof(si));
|
|
ZeroMemory(&osvi, sizeof(osvi));
|
|
|
|
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
|
|
// If that fails, try using the OSVERSIONINFO structure.
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
|
|
|
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
|
|
{
|
|
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
|
|
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
|
|
return FALSE;
|
|
}
|
|
|
|
// Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
|
|
|
|
pGNSI = (PGNSI) GetProcAddress( GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
|
|
if(NULL != pGNSI)
|
|
pGNSI(&si);
|
|
else GetSystemInfo(&si);
|
|
|
|
switch (osvi.dwPlatformId)
|
|
{
|
|
// Test for the Windows NT product family.
|
|
|
|
case VER_PLATFORM_WIN32_NT:
|
|
|
|
// Test for the specific product.
|
|
|
|
// windows vista, windows 7 OS일 경우 bold 태그 예외를 둔다.
|
|
// 일본 시스템 메세지 깨짐 문제 수정. kappamind, 2010.01.21
|
|
// if ( ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 ) ||
|
|
// ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1 )
|
|
// )
|
|
if( ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 0 ) ) //gmpbigsun(20130617) : window vista, 7, 8
|
|
{
|
|
if( osvi.wProductType == VER_NT_WORKSTATION )
|
|
{
|
|
KTextRender::SetOSandLocale( true, ENV().GetString( "locale", "CP949" ).c_str() );
|
|
|
|
_performance_print("Windows Vista or 7 or 8 ");
|
|
}
|
|
else _performance_print ("Windows Server \"Longhorn\" " );
|
|
}
|
|
|
|
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
|
|
{
|
|
#if(_WIN32_WINNT >= 0x0501)
|
|
if( GetSystemMetrics(SM_SERVERR2) )
|
|
printf( "Microsoft Windows Server 2003 \"R2\" ");
|
|
else if( osvi.wProductType == VER_NT_WORKSTATION &&
|
|
si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
|
|
{
|
|
printf( "Microsoft Windows XP Professional x64 Edition ");
|
|
}
|
|
else printf ("Microsoft Windows Server 2003, ");
|
|
#endif /* _WIN32_WINNT >= 0x0501 */
|
|
}
|
|
|
|
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
|
|
_performance_print ("Microsoft Windows XP ");
|
|
|
|
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
|
|
_performance_print ("Microsoft Windows 2000 ");
|
|
|
|
if ( osvi.dwMajorVersion <= 4 )
|
|
_performance_print ("Microsoft Windows NT ");
|
|
|
|
// Test for specific product on Windows NT 4.0 SP6 and later.
|
|
if( bOsVersionInfoEx )
|
|
{
|
|
// Test for the workstation type.
|
|
if ( osvi.wProductType == VER_NT_WORKSTATION &&
|
|
si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64)
|
|
{
|
|
if( osvi.dwMajorVersion == 4 )
|
|
_performance_print ( "Workstation 4.0 " );
|
|
else if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
|
|
_performance_print ( "Home Edition " );
|
|
else _performance_print ( "Professional " );
|
|
}
|
|
|
|
// Test for the server type.
|
|
else if ( osvi.wProductType == VER_NT_SERVER ||
|
|
osvi.wProductType == VER_NT_DOMAIN_CONTROLLER )
|
|
{
|
|
if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2)
|
|
{
|
|
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
|
|
{
|
|
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
|
|
_performance_print ( "Datacenter Edition for Itanium-based Systems" );
|
|
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
|
|
_performance_print ( "Enterprise Edition for Itanium-based Systems" );
|
|
}
|
|
|
|
else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
|
|
{
|
|
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
|
|
_performance_print ( "Datacenter x64 Edition " );
|
|
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
|
|
_performance_print ( "Enterprise x64 Edition " );
|
|
else _performance_print( "Standard x64 Edition " );
|
|
}
|
|
|
|
else
|
|
{
|
|
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
|
|
_performance_print ( "Datacenter Edition " );
|
|
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
|
|
_performance_print ( "Enterprise Edition " );
|
|
else if ( osvi.wSuiteMask & VER_SUITE_BLADE )
|
|
_performance_print ( "Web Edition " );
|
|
else _performance_print ( "Standard Edition " );
|
|
}
|
|
}
|
|
else if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
|
|
{
|
|
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
|
|
_performance_print ( "Datacenter Server " );
|
|
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
|
|
_performance_print ( "Advanced Server " );
|
|
else _performance_print ( "Server " );
|
|
}
|
|
else // Windows NT 4.0
|
|
{
|
|
if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
|
|
_performance_print ("Server 4.0, Enterprise Edition " );
|
|
else _performance_print ( "Server 4.0 " );
|
|
}
|
|
}
|
|
}
|
|
// Test for specific product on Windows NT 4.0 SP5 and earlier
|
|
else
|
|
{
|
|
HKEY hKey;
|
|
TCHAR szProductType[BUFSIZE];
|
|
DWORD dwBufLen = sizeof( szProductType );
|
|
LONG lRet;
|
|
|
|
lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), 0, KEY_QUERY_VALUE, &hKey );
|
|
if( lRet != ERROR_SUCCESS )
|
|
return FALSE;
|
|
|
|
lRet = RegQueryValueEx( hKey, TEXT("ProductType"), NULL, NULL, (LPBYTE) szProductType, &dwBufLen);
|
|
RegCloseKey( hKey );
|
|
|
|
if( (lRet != ERROR_SUCCESS) || (dwBufLen > sizeof( szProductType )) )
|
|
return FALSE;
|
|
|
|
if ( lstrcmpi( TEXT("WINNT"), szProductType) == 0 )
|
|
_performance_print( "Workstation " );
|
|
if ( lstrcmpi( TEXT("LANMANNT"), szProductType) == 0 )
|
|
_performance_print( "Server " );
|
|
if ( lstrcmpi( TEXT("SERVERNT"), szProductType) == 0 )
|
|
_performance_print( "Advanced Server " );
|
|
_performance_print( "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion );
|
|
}
|
|
|
|
// Display service pack (if any) and build number.
|
|
|
|
if( osvi.dwMajorVersion == 4 &&
|
|
lstrcmpi( osvi.szCSDVersion, TEXT("Service Pack 6") ) == 0 )
|
|
{
|
|
HKEY hKey;
|
|
LONG lRet;
|
|
|
|
// Test for SP6 versus SP6a.
|
|
lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), 0, KEY_QUERY_VALUE, &hKey );
|
|
if( lRet == ERROR_SUCCESS )
|
|
_performance_print( "Service Pack 6a (Build %d)\n", osvi.dwBuildNumber & 0xFFFF );
|
|
else // Windows NT 4.0 prior to SP6a
|
|
{
|
|
_performance_print( TEXT("%s (Build %d)\n"), osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
}
|
|
else // not Windows NT 4.0
|
|
{
|
|
_performance_print( TEXT("%s (Build %d)\n"), osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF );
|
|
}
|
|
|
|
break;
|
|
|
|
// Test for the Windows Me/98/95.
|
|
case VER_PLATFORM_WIN32_WINDOWS:
|
|
|
|
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
|
|
{
|
|
_performance_print ("Microsoft Windows 95 ");
|
|
if (osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B')
|
|
_performance_print("OSR2 " );
|
|
}
|
|
|
|
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
|
|
{
|
|
_performance_print ("Microsoft Windows 98 ");
|
|
if ( osvi.szCSDVersion[1]=='A' || osvi.szCSDVersion[1]=='B')
|
|
_performance_print("SE " );
|
|
}
|
|
|
|
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
|
|
{
|
|
_performance_print ("Microsoft Windows Millennium Edition\n");
|
|
}
|
|
break;
|
|
|
|
case VER_PLATFORM_WIN32s:
|
|
|
|
_performance_print ("Microsoft Win32s\n");
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// 젠장-_-;
|
|
|
|
/// 2010.11.11 - prodongi
|
|
void _getModulePath()
|
|
{
|
|
_setmaxstdio( 512 );
|
|
{
|
|
TCHAR *pEnd = NULL;
|
|
TCHAR szFullFileName[MAX_PATH] = { 0, };
|
|
GetModuleFileName(NULL, szFullFileName, MAX_PATH);
|
|
pEnd = _tcsrchr( szFullFileName, _T('\\')) + 1;
|
|
|
|
if (!pEnd)
|
|
{
|
|
//에러
|
|
}
|
|
else
|
|
{
|
|
*pEnd = _T('\0');
|
|
SetCurrentDirectory(szFullFileName);
|
|
|
|
lstrcat(szFullFileName, _T("cam") );
|
|
g_strModulePath = szFullFileName;
|
|
DWORD dwAttr = GetFileAttributes( g_strModulePath.c_str() );
|
|
if( INVALID_FILE_ATTRIBUTES == dwAttr )
|
|
{
|
|
CreateDirectory( g_strModulePath.c_str(), NULL );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 2010.11.11 - prodongi
|
|
#ifdef _HACK_SHIELD_
|
|
void startHackShieldService()
|
|
{
|
|
// sonador 7.4.4 핵쉴드 270 적용
|
|
if( !UpdateHackShieldService() )
|
|
{
|
|
SLOG("Hackshield Update Failed!");
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return 0;
|
|
}
|
|
if( !StartHackShieldService() )
|
|
{
|
|
StopHackShieldService();
|
|
SLOG("Hackshield Start Failed!");
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return 0;
|
|
}
|
|
|
|
//빌드용
|
|
if( ENV().IsExist( "crcbuild" ) )
|
|
{
|
|
StopHackShieldService();
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
bool _startNProtectService()
|
|
{
|
|
int nLocalBitSet = GameRule::GetCurrentLocalBitSet();
|
|
|
|
|
|
if( nLocalBitSet == GameRule::LOCAL_BITSET::KR ) { g_pNpgl = new CNPGameLib( getNProtectIniFileName( "RappelzKR" ) ); }
|
|
else if( nLocalBitSet == GameRule::LOCAL_BITSET::DE ||
|
|
nLocalBitSet == GameRule::LOCAL_BITSET::FR ||
|
|
nLocalBitSet == GameRule::LOCAL_BITSET::IT ||
|
|
nLocalBitSet == GameRule::LOCAL_BITSET::PL ) { g_pNpgl = new CNPGameLib( "RappelzGB" ); }
|
|
else if( nLocalBitSet == GameRule::LOCAL_BITSET::TR) { g_pNpgl = new CNPGameLib( "RappelzTR" ); }
|
|
else if( nLocalBitSet == GameRule::LOCAL_BITSET::RU) { g_pNpgl = new CNPGameLib( getNProtectIniFileName( "RappelzRU" ) ); }
|
|
else if( nLocalBitSet == GameRule::LOCAL_BITSET::ID) { g_pNpgl = new CNPGameLib( "RappelzID" ); }
|
|
else if( nLocalBitSet == GameRule::LOCAL_BITSET::US) { g_pNpgl = new CNPGameLib( "RappelzUS" ); }
|
|
else if( nLocalBitSet == GameRule::LOCAL_BITSET::ME) { g_pNpgl = new CNPGameLib( getNProtectIniFileName( "RappelzDU" ) ); }
|
|
|
|
|
|
if( g_pNpgl == NULL )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if( !StartnProtectService() )
|
|
{
|
|
delete g_pNpgl;
|
|
g_pNpgl = NULL;
|
|
SLOG("NProtect Start Failed!");
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool _checkDoubleExecute(HANDLE& hMutex)
|
|
{
|
|
hMutex = CreateMutex(NULL, TRUE, "Global\\wbc_sbc");
|
|
DWORD dwLastError = GetLastError();
|
|
if(dwLastError==ERROR_ALREADY_EXISTS ||
|
|
dwLastError==ERROR_ACCESS_DENIED )
|
|
{
|
|
std::string strErr;
|
|
XStringUtil::Format( strErr, "Execute Error %d", dwLastError );
|
|
MessageBox( 0, strErr.c_str(), "Rappelz-Error", MB_OK );
|
|
SLOG("Duplicate Execute Error!");
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
//#endif
|
|
|
|
bool _isValidDxVersion()
|
|
{
|
|
//DX 버전 검사
|
|
HRESULT hr;
|
|
TCHAR strResult[128];
|
|
|
|
union
|
|
{
|
|
DWORD dwDirectXVersion;
|
|
char cVersion[4];
|
|
} DXVERSION;
|
|
|
|
TCHAR strDirectXVersion[10];
|
|
TCHAR cDXVerLetter;
|
|
cDXVerLetter = ' ';
|
|
|
|
hr = GetDXVersion( &DXVERSION.dwDirectXVersion, strDirectXVersion, 10, cDXVerLetter );
|
|
_oprint( "DX %d.%d(%c) [%s]\n", DXVERSION.cVersion[2], DXVERSION.cVersion[1], cDXVerLetter, strDirectXVersion );
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
if( DXVERSION.dwDirectXVersion > 0 )
|
|
{
|
|
//9.0c 보다 낮으면 실행 안됨
|
|
if( ( DXVERSION.cVersion[2] < 9 ) ||
|
|
( DXVERSION.cVersion[2] == 9 && DXVERSION.cVersion[1] == 0 && cDXVerLetter < 'c' ) )
|
|
{
|
|
_sntprintf( strResult, 128, TEXT("DirectX %s installed\n Need DirectX 9.0c or higher"), strDirectXVersion );
|
|
strResult[127] = 0;
|
|
MessageBox( NULL, strResult, TEXT("Rappelz-DirectX Version:"), MB_OK | MB_ICONINFORMATION );
|
|
|
|
// 다른 나라도 지원되게 해야함.
|
|
// DialogBox(hInstance, MAKEINTRESOURCE(IDD_DOWN_BOX), NULL, About);
|
|
|
|
SLOG("Too low DirectX Version!");
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_tcsncpy( strResult, TEXT("DirectX not installed"), 128 );
|
|
strResult[127] = 0;
|
|
MessageBox( NULL, strResult, TEXT("Rappelz-DirectX Version:"), MB_OK | MB_ICONINFORMATION );
|
|
|
|
// 다른 나라도 지원되게 해야함.
|
|
// DialogBox(hInstance, MAKEINTRESOURCE(IDD_DOWN_BOX), NULL, About);
|
|
|
|
SLOG("DirectX file missed!");
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_sntprintf( strResult, 128, TEXT("Unknown version of DirectX installed") );
|
|
strResult[127] = 0;
|
|
MessageBox( NULL, strResult, TEXT("Rappelz-DirectX Version:"), MB_OK | MB_ICONINFORMATION );
|
|
|
|
// 다른 나라도 지원되게 해야함.
|
|
// DialogBox(hInstance, MAKEINTRESOURCE(IDD_DOWN_BOX), NULL, About);
|
|
|
|
SLOG("Unknown Version of DirectX Detected!");
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void _setDebugFlag()
|
|
{
|
|
/*int tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); // 현재 플래그 얻음.
|
|
//
|
|
tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF; // Leak 체크 플래그 추가
|
|
//tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF; // 블럭들을 실제로 해제하지 않는 플래그 추가.
|
|
//tmpDbgFlag |= _CRTDBG_CHECK_ALWAYS_DF; // alloc/dealloc에 대해 메모리 점검 수행 플래그 추가.
|
|
//
|
|
_CrtSetDbgFlag(tmpDbgFlag); // 새로운 플래그 설정.
|
|
*/
|
|
|
|
// http://msdn.microsoft.com/ko-kr/library/x98tx3cf(VS.80).aspx
|
|
// _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
|
|
|
// _CrtSetBreakAlloc(8761666);
|
|
// 8761637
|
|
// 740312
|
|
}
|
|
|
|
bool _isValidResolution()
|
|
{
|
|
// 2010.07.12 최저 해상도 체크(최저 해상도 수치가 define 된게 없다,,)- prodongi
|
|
UINT minWidth = 1024;
|
|
UINT minHeight = (GameRule::isSoutheastAsia()) ? 720 : 768;
|
|
if (minWidth > GetGameOption().GetResolution_Width() ||
|
|
minHeight > GetGameOption().GetResolution_Height())
|
|
{
|
|
char msg[MAX_PATH];
|
|
sprintf(msg, "The minimum resolution is %d x %d", minWidth, minHeight);
|
|
MessageBox( 0, msg, "Error", MB_OK|MB_ICONINFORMATION );
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void _setTitle()
|
|
{
|
|
if(GameRule::GetCurrentLocalBitSet() == GameRule::LOCAL_BITSET::KR)
|
|
{
|
|
if( ENV().IsExist( "main_server" ) )
|
|
{
|
|
strcpy( szTitle, "Rappelz" );
|
|
}
|
|
else
|
|
{
|
|
strcpy( szTitle, "Rappelz - Test Server" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strcpy( szTitle, "Rappelz" );
|
|
}
|
|
}
|
|
|
|
void _parsingLocaleInfo()
|
|
{
|
|
if(GetLocaleOption().parsingOptionFile("localeinfo.ini") == false)
|
|
{
|
|
MessageBox(NULL, "'localeinfo' File Not Found","error", MB_OK);
|
|
}
|
|
}
|
|
|
|
|
|
#ifndef _COUNTRY_ME_ // sonador #2.4.10.2
|
|
|
|
bool _setLocaleFontInfo()
|
|
{
|
|
//------------------------------------------
|
|
// 멀티폰트 적용.
|
|
|
|
// FONT_01
|
|
KTextRender::AddFreeTypeFont( KTextRender::KDEFAULT_FONT_01, GetLocaleOption().GetValueString("font_01", "NanumGothic.otf") );
|
|
// FONT_02
|
|
KTextRender::AddFreeTypeFont( KTextRender::KDEFAULT_FONT_02, GetLocaleOption().GetValueString("font_02", "NanumGothicExtraBold.otf") );
|
|
// 2010.08.26 - prodongi
|
|
KTextRender::AddFreeTypeFont( KTextRender::KDEFAULT_FONT_03, GetLocaleOption().GetValueString("font_03", "NanumMyungjo.otf") );
|
|
|
|
// Default
|
|
/// 2010.11.09 font_default가 설정 안되어 있을 경우에 Tahoma.ttf를 읽도록 한다 - prodongi
|
|
if( !KTextRender::AddFreeTypeFont( KTextRender::KDEFAULT_FONT_NAME, GetLocaleOption().GetValueString("font_default", "Tahoma.ttf") ) )
|
|
{
|
|
//에러메시지..
|
|
MessageBox( g_hWnd, "Fontfile not found", "Rappelz-Error", MB_ICONERROR|MB_OK );
|
|
return false;
|
|
}
|
|
|
|
/// 2010.11.05 - prodongi
|
|
if( !KTextRender::AddFreeTypeFont( KTextRender::KDEFAULT_FONT_NAME2, GetLocaleOption().GetValueString("font_default", "Tahoma.ttf") ) )
|
|
{
|
|
//에러메시지..
|
|
MessageBox( g_hWnd, "Fontfile not found", "Rappelz-Error", MB_ICONERROR|MB_OK );
|
|
return false;
|
|
}
|
|
|
|
KTextRender::SetFontHinting( KTextRender::KDEFAULT_FONT_NAME, GetLocaleOption().GetValueInt( "FONT_DEFAULT_HINTING", 0 ) );
|
|
KTextRender::SetFontHinting( KTextRender::KDEFAULT_FONT_01, GetLocaleOption().GetValueInt( "FONT_01_HINTING", 0 ) );
|
|
KTextRender::SetFontHinting( KTextRender::KDEFAULT_FONT_02, GetLocaleOption().GetValueInt( "FONT_02_HINTING", 0 ) );
|
|
KTextRender::SetFontHinting( KTextRender::KDEFAULT_FONT_03, GetLocaleOption().GetValueInt( "FONT_03_HINTING", 0 ) );
|
|
|
|
return true;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
void _initEmoticonList()
|
|
{
|
|
KTextEmoticonRender::SetSprName( "ui_frame.spr" );
|
|
|
|
//이모티콘 리스트 초기화
|
|
for( int i(0); c_nEmoticonCnt>i; i++ )
|
|
{
|
|
KTextEmoticonRender::AddFilter( g_szEmoticonFilter[i], g_szAniName[i] );
|
|
#ifdef _COUNTRY_ME_
|
|
KTextParser::AddEmoticonFilter( g_szEmoticonFilter[i], g_szAniName[i] );// KUIControl_ME는 KTextParser을 통해 이모티콘을 필터링함.
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void _setEditBoxFontTag()
|
|
{
|
|
for( int i(0); c_nFontTagCnt>i; i++ )
|
|
{
|
|
CEditBoxInfo::AddClipException( g_szFontTag[i], ">" );
|
|
}
|
|
}
|
|
|
|
|
|
void _initGuildIcon()
|
|
{
|
|
TCHAR DirBuffer[BUFSIZE];
|
|
DWORD dwBufLen = sizeof(DirBuffer);
|
|
DWORD dwRet;
|
|
|
|
dwRet = GetCurrentDirectory( dwBufLen, DirBuffer );
|
|
if( dwRet == 0 )
|
|
{
|
|
std::string strErr = CStringUtil::StringFormat( "GetCurrentDirectory failed (%d)\n", GetLastError() );
|
|
MessageBox( g_hWnd, strErr.c_str(), "Rappelz-Error", MB_ICONERROR|MB_OK );
|
|
}
|
|
else
|
|
{
|
|
g_strGuildFullDir = DirBuffer;
|
|
g_strGuildFullDir += "\\Guild_Icon\\";
|
|
|
|
//길드 아이콘 리소스 폴더 추가
|
|
static KStdioFileSystem _guild_icon;
|
|
|
|
//길드 아이콘 폴더 생성
|
|
strcpy( DirBuffer, "Guild_Icon" );
|
|
if( !CreateDirectory( DirBuffer, NULL ) )
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
if( dwErr == ERROR_ALREADY_EXISTS )
|
|
{
|
|
_guild_icon.Init( g_strGuildFullDir.c_str() );
|
|
|
|
KFileManager::Instance().AddResourceSource( &_guild_icon );
|
|
}
|
|
else if( dwErr == ERROR_PATH_NOT_FOUND )
|
|
{
|
|
std::string strErr = CStringUtil::StringFormat( "CreateDirectory failed (%d)\n", GetLastError() );
|
|
MessageBox( g_hWnd, strErr.c_str(), "Rappelz-Error", MB_ICONERROR|MB_OK );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_guild_icon.Init( g_strGuildFullDir.c_str() );
|
|
KFileManager::Instance().AddResourceSource( &_guild_icon );
|
|
}
|
|
}
|
|
}
|
|
|
|
void _initCom()
|
|
{
|
|
//// Explorer
|
|
// Instantiate a browser
|
|
HRESULT hrCoInit = CoInitialize(NULL);
|
|
g_bCleanupCOM = SUCCEEDED(hrCoInit);
|
|
}
|
|
|
|
void _initAtlModule(CComModule& _Module)
|
|
{
|
|
//CComModule _Module;
|
|
HRESULT hrModule = _Module.Init(NULL, g_hInstance, &LIBID_ATLLib);
|
|
if( hrModule != S_OK )
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
AtlAxWinInit();
|
|
}
|
|
|
|
void _initBotManager(HWND hWnd, HINSTANCE hInstance)
|
|
{
|
|
g_pSBotMng = new SBotManager( hWnd, hInstance );
|
|
SBotManager::m_pBotThis = g_pSBotMng;
|
|
}
|
|
|
|
void _initBotManagerUIScript()
|
|
{
|
|
if( g_pSBotMng->GetCurBot() )
|
|
g_pSBotMng->GetCurBot()->InitializeScriptForGameUI();
|
|
}
|
|
|
|
void _mainLoop(MSG& msg)
|
|
{
|
|
DWORD dwOldTime = GetSafeTickCount();
|
|
DWORD dwRealTime = 0;
|
|
DWORD dwPrevFileManagerProcTime = 0;
|
|
DWORD dwCursorAniTime = 0;
|
|
|
|
char pszClassName[256];
|
|
pszClassName[_countof(pszClassName) - 1] = '\0';
|
|
|
|
while (1)
|
|
{
|
|
int t = PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE );
|
|
|
|
if ( t )
|
|
{
|
|
if ( GetMessage( &msg, NULL, 0, 0 ) == FALSE ) break;
|
|
|
|
if( g_IsShowWebBrowser )
|
|
{
|
|
if(msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST)
|
|
{
|
|
GetClassName(msg.hwnd, pszClassName, _countof( pszClassName ));
|
|
if(strcmp(pszClassName, "Internet Explorer_Server") == 0)
|
|
{
|
|
SendMessage(g_hWnd, msg.message, msg.wParam, msg.lParam);
|
|
}
|
|
}
|
|
if( g_bServerListFocus && msg.message == WM_KEYDOWN && msg.wParam == VK_RETURN )
|
|
{
|
|
SendMessage(g_hWnd, msg.message, msg.wParam, msg.lParam);
|
|
}
|
|
}
|
|
|
|
// [sonador] Replacing keyboard hooking with WM messages
|
|
#if !defined( _USE_KEYBOARD_HOOK )
|
|
if( !::HotKeyProc( msg.hwnd, msg.message, msg.wParam, msg.lParam ) ) {
|
|
#endif
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
#if !defined( _USE_KEYBOARD_HOOK )
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// For this to be possible, it is necessary to store synchronized time.
|
|
// Screenshots are taken at that synchronized time.
|
|
// I am thinking that each message is stored separately and used at the synchronized time...
|
|
dwRealTime = GetSafeTickCount();
|
|
|
|
// If processing & rendering consume too much CPU, thread loading can be delayed.
|
|
// So, if something is being loaded in a thread, we give it a suitable Sleep().
|
|
|
|
//if( KThreadResource::GetPendingWork() ) Sleep( 0 );
|
|
|
|
{
|
|
{
|
|
DWORD dwTm = GetSafeTickCount();
|
|
|
|
if( !g_SecurityMsg.empty() )
|
|
{
|
|
if( g_dwhkTime == 0 ) g_dwhkTime = dwTm;
|
|
|
|
if( dwTm - g_dwhkTime > 5000 )
|
|
{
|
|
g_dwhkTime = dwTm;
|
|
if( g_pSBotMng->GetCurBot() && g_pSBotMng->GetCurBot()->GetActiveGame() )
|
|
{
|
|
GameSecurityMsg* pSecurityMsg = g_SecurityMsg[0];
|
|
g_pSBotMng->ProcSecurityMsg( pSecurityMsg );
|
|
g_SecurityMsg.erase( g_SecurityMsg.begin() );
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef _HACK_SHIELD_
|
|
if( g_bCheckHook )
|
|
{
|
|
if( g_dwKeyResumeTime == 0 ) g_dwKeyResumeTime = dwTm;
|
|
// If nothing is done for about 3 minutes, it becomes active again
|
|
if( dwTm - g_dwKeyResumeTime > 180000 )
|
|
{
|
|
if( g_bAhnHS )
|
|
SetWindowText( g_hWnd, "_AhnHS_ResumeService( AHNHS_CHKOPT_MESSAGEHOOK )" );
|
|
g_dwKeyResumeTime = 0;
|
|
g_bCheckHook = false;
|
|
_AhnHS_ResumeService( AHNHS_CHKOPT_MESSAGEHOOK );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if( g_bConnGameMon && g_pNpgl != NULL )
|
|
{
|
|
if( g_dwCheckGameMon == 0 ) g_dwCheckGameMon = dwTm;
|
|
if( dwTm - g_dwCheckGameMon > 30000 )
|
|
{
|
|
//if (npgl.Check() != NPGAMEMON_SUCCESS)
|
|
if( g_pNpgl->Check() != NPGAMEMON_SUCCESS )
|
|
{
|
|
GameSecurityMsg* pSecurityMsg = new GameSecurityMsg;
|
|
pSecurityMsg->nMsgType = GameSecurityMsg::MSG_NPROTECT_COMM_CLOSE;
|
|
g_SecurityMsg.push_back( pSecurityMsg );
|
|
g_bConnGameMon = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Main Process function
|
|
g_pSBotMng->Process();
|
|
|
|
dwTm = GetSafeTickCount() - dwTm;
|
|
if( dwTm > 300 )
|
|
{
|
|
_oprint( "CAUTION: Process time: %d !!!!!!\n", dwTm );
|
|
}
|
|
}
|
|
{
|
|
DWORD dwTm = GetSafeTickCount();
|
|
|
|
g_pSBotMng->Render();
|
|
|
|
dwTm = GetSafeTickCount() - dwTm;
|
|
if( dwTm > 300 )
|
|
{
|
|
_oprint( "CAUTION: Render time: %d !!!!!!\n", dwTm );
|
|
}
|
|
}
|
|
|
|
{
|
|
// Every 1 minute, check if there is any stream cache to discard and delete it
|
|
if( dwPrevFileManagerProcTime + 6000 < dwRealTime )
|
|
{
|
|
KFileManager::Instance().RemoveUnnecessaryStream();
|
|
dwPrevFileManagerProcTime = dwRealTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
g_dwCount++;
|
|
g_dwFPSTime += dwRealTime - dwOldTime;
|
|
dwCursorAniTime += dwRealTime - dwOldTime;
|
|
if(g_dwFPSTime >= 1000)
|
|
{
|
|
float fTime = (float)g_dwFPSTime / 1000.0f;
|
|
g_dwFPS = DWORD( (float)g_dwCount / fTime );
|
|
|
|
if( g_bWindowFPS )
|
|
{
|
|
sprintf( szFPS, "FPS : %d", g_dwFPS );
|
|
SetWindowText( g_hWnd, szFPS );
|
|
}
|
|
g_dwFPSTime = 0;
|
|
g_dwCount = 0;
|
|
}
|
|
|
|
dwOldTime = dwRealTime;
|
|
|
|
// _oprint( "%d\n", GetArTime() );
|
|
}
|
|
}
|
|
}
|
|
|
|
void _saveLogStringRate()
|
|
{
|
|
/// g_StringOccurMap는 언제 클리어 해주나? - prodongi
|
|
if( g_bLogStringRate )
|
|
{
|
|
extern std::map< int, int > g_StringOccurMap;
|
|
|
|
FILE *fp = fopen( "string_occur_rate.txt", "w" );
|
|
std::map< int, int >::iterator it;
|
|
|
|
for( it = g_StringOccurMap.begin(); it != g_StringOccurMap.end(); ++it )
|
|
{
|
|
fprintf( fp, "%d\t%d\n", it->first, it->second );
|
|
}
|
|
fclose( fp );
|
|
}
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
/// 2010.11.12 - prodongi
|
|
void _saveMemAllocCount()
|
|
{
|
|
FILE *fp = fopen( "mem_alloc.txt", "w" );
|
|
for( int i = 0; i < 128; ++i )
|
|
{
|
|
fprintf( fp, "%3d\t%d\n", i, g_nMemAllocCnt[i] );
|
|
}
|
|
fclose( fp );
|
|
}
|
|
#endif
|
|
|
|
void _clearWebBrowser()
|
|
{
|
|
if( g_pWebBrowser )
|
|
{
|
|
CloseWebBrowser( g_pWebBrowser );
|
|
g_pWebBrowser = NULL;
|
|
}
|
|
}
|
|
|
|
void _clearMain(HANDLE& hMutex, CComModule* _Module)
|
|
{
|
|
#ifdef _HACK_SHIELD_
|
|
StopHackShieldService();
|
|
#endif
|
|
|
|
if( hMutex != NULL )
|
|
{
|
|
ReleaseMutex(hMutex);
|
|
CloseHandle(hMutex);
|
|
}
|
|
|
|
/// 2010.11.12 - prodongi
|
|
_saveLogStringRate();
|
|
/*
|
|
if( g_bLogStringRate )
|
|
{
|
|
extern std::map< int, int > g_StringOccurMap;
|
|
|
|
FILE *fp = fopen( "string_occur_rate.txt", "w" );
|
|
std::map< int, int >::iterator it;
|
|
|
|
for( it = g_StringOccurMap.begin(); it != g_StringOccurMap.end(); ++it )
|
|
{
|
|
fprintf( fp, "%d\t%d\n", it->first, it->second );
|
|
}
|
|
fclose( fp );
|
|
}
|
|
*/
|
|
|
|
#ifdef _DEBUG
|
|
/// 2010.11.12 - prodongi
|
|
_saveMemAllocCount();
|
|
/*
|
|
FILE *fp = fopen( "mem_alloc.txt", "w" );
|
|
for( int i = 0; i < 128; ++i )
|
|
{
|
|
fprintf( fp, "%3d\t%d\n", i, g_nMemAllocCnt[i] );
|
|
}
|
|
fclose( fp );
|
|
*/
|
|
#endif
|
|
|
|
|
|
KFileManager::Instance().RemoveAllStream();
|
|
|
|
// if( g_hWnd_Dlg ) DestroyWindow( g_hWnd_Dlg );
|
|
//
|
|
/// 2010.11.12 - prodongi
|
|
_clearWebBrowser();
|
|
/*
|
|
if( g_pWebBrowser )
|
|
{
|
|
CloseWebBrowser( g_pWebBrowser );
|
|
g_pWebBrowser = NULL;
|
|
}
|
|
*/
|
|
|
|
if( g_pFLog )
|
|
fclose( g_pFLog );
|
|
|
|
DeleteAllWebBrowserInfo();
|
|
|
|
SAFE_DELETE( g_pSBotMng );
|
|
|
|
LUA()->DeInit();
|
|
|
|
#ifdef _USE_KEYBOARD_HOOK
|
|
UnhookWindowsHookEx( g_hKeyBoardHook );
|
|
#endif
|
|
|
|
// 2010.06.17 - prodongi
|
|
delKeyboardHook();
|
|
|
|
#ifdef _EXCEPTION_PROCESS
|
|
EndExceptionHandler();
|
|
#endif
|
|
|
|
// rdb 몇가지는 미리 로드
|
|
//::GetSkillDB().Clear();
|
|
//::GetSkillStageDB().Clear();
|
|
//::GetCharacterMotionEventDB().Clear();
|
|
//::GetMotionEventHanderDB().Clear();
|
|
//::GetMotionFxSetDB().Clear();
|
|
//::GetMotionSetDB().Clear();
|
|
//::GetTenacityDB().Clear();
|
|
//::GetStringDB().Clear();
|
|
//::GetItemDB().Clear();
|
|
//::GetDefaultItemDB().Clear();
|
|
//::GetAbuseDB().Clear();
|
|
|
|
|
|
// _CrtCheckMemory(); // 메모리 체크 결과를 보여줌.
|
|
|
|
//#ifdef _DEBUG
|
|
// _CrtDumpMemoryLeaks(); // 메모리 Leak 체크 결과를 보여줌.
|
|
//#endif
|
|
|
|
|
|
#ifdef _EXPLORER_
|
|
|
|
AtlAxWinTerm();
|
|
if (_Module)
|
|
_Module->Term();
|
|
|
|
#endif
|
|
|
|
nsl::uni::deinit();
|
|
|
|
if( g_bCleanupCOM )
|
|
CoUninitialize();
|
|
|
|
#ifdef _WEB_DISP_MODE
|
|
RestoreDisplay();
|
|
#endif
|
|
|
|
if (g_pNpgl != NULL)
|
|
{
|
|
delete g_pNpgl;
|
|
g_pNpgl = NULL;
|
|
}
|
|
|
|
GetLog().OutputFile(LOGFILE_NAME);
|
|
}
|
|
|
|
void _deleteSGObj( )
|
|
{
|
|
SAFE_DELETE( SBanWordDB::m_pThis );
|
|
SAFE_DELETE( SStringDB::m_pThis );
|
|
SAFE_DELETE( SItemReferenceDB::m_pThis );
|
|
SAFE_DELETE( SItemDB::m_pThis );
|
|
SAFE_DELETE( SNpcResourceDB::m_pThis );
|
|
SAFE_DELETE( SMonsterDB::m_pThis );
|
|
SAFE_DELETE( SPetDB::m_pThis );
|
|
SAFE_DELETE( SCreatureDB::m_pThis );
|
|
SAFE_DELETE( SCreatureEnhanceDB::m_pThis );
|
|
SAFE_DELETE( SCreatureFarmDB::m_pThis );
|
|
SAFE_DELETE( SSkillDB::m_pThis );
|
|
//10
|
|
|
|
SAFE_DELETE( STenacityDB::m_pThis );
|
|
SAFE_DELETE( SQuestDB::m_pThis );
|
|
SAFE_DELETE( SQuestLinkDB::m_pThis );
|
|
SAFE_DELETE( SCombineDB::m_pThis );
|
|
SAFE_DELETE( SDecomposeDB::m_pThis );
|
|
SAFE_DELETE( SItemEffectResourceDB::m_pThis );
|
|
SAFE_DELETE( SDefaultTextureResourceDB::m_pThis );
|
|
SAFE_DELETE( SDefaultTextureIconResourceDB::m_pThis );
|
|
SAFE_DELETE( SMixCategoryDB::m_pThis );
|
|
//20
|
|
|
|
//SAFE_DELETE( SEnhanceFXDB::m_pThis );
|
|
SAFE_DELETE( SExpDB::m_pThis );
|
|
SAFE_DELETE( SFieldPropResourceDB::m_pThis );
|
|
SAFE_DELETE( SMotionSetDB::m_pThis );
|
|
SAFE_DELETE( SWorldLocationDB::m_pThis );
|
|
SAFE_DELETE( SLowQualityWaterDB::m_pThis );
|
|
SAFE_DELETE( SBattleArenaBeginAreaDB::m_pThis );
|
|
SAFE_DELETE( SResourceDB::m_pThis );
|
|
SAFE_DELETE( SLocalCommandDB::m_pThis );
|
|
SAFE_DELETE( STitleDB::m_pThis );
|
|
//30
|
|
|
|
SAFE_DELETE( SJobDB::m_pThis );
|
|
SAFE_DELETE( SHuntaHolicResourceDB::m_pThis );
|
|
SAFE_DELETE( SDungeonResourceDB::m_pThis );
|
|
SAFE_DELETE( SMonsterMotionSetDB::m_pThis );
|
|
SAFE_DELETE( SCharacterMotionDB::m_pThis );
|
|
SAFE_DELETE( SMotionEventHanderDB::m_pThis );
|
|
SAFE_DELETE( SMotionFxSetDB::m_pThis );
|
|
|
|
SAFE_DELETE( SMonstarCreatureDB::m_pThis );
|
|
//SAFE_DELETE( SEnhanceEffectDB::m_pThis );
|
|
}
|