#include "StdAfx.h" #include "PythonApplication.h" #include "ProcessScanner.h" #include "PythonExceptionSender.h" #include "resource.h" #include "Version.h" #ifdef _DEBUG #include #endif #include "../eterPack/EterPackManager.h" #include "../eterLib/Util.h" #include "../CWebBrowser/CWebBrowser.h" #include "../eterBase/CPostIt.h" #include "CheckLatestFiles.h" extern "C" { extern int _fltused; volatile int _AVOID_FLOATING_POINT_LIBRARY_BUG = _fltused; }; #pragma comment(linker, "/NODEFAULTLIB:libci.lib") #pragma comment( lib, "version.lib" ) #pragma comment( lib, "imagehlp.lib" ) #pragma comment( lib, "devil.lib" ) #if GrannyProductMinorVersion==4 #pragma comment( lib, "granny2.4.0.10.lib" ) #elif GrannyProductMinorVersion==7 #pragma comment( lib, "granny2.7.0.30.lib" ) #elif GrannyProductMinorVersion==8 #pragma comment( lib, "granny2.8.49.0.lib" ) #elif GrannyProductMinorVersion==9 #pragma comment( lib, "granny2.9.12.0.lib" ) #elif GrannyProductMinorVersion==11 #pragma comment( lib, "granny2.11.8.0.lib" ) #else #error "unknown granny version" #endif #pragma comment( lib, "mss32.lib" ) #pragma comment( lib, "winmm.lib" ) #pragma comment( lib, "imm32.lib" ) #pragma comment( lib, "oldnames.lib" ) #pragma comment( lib, "SpeedTreeRT.lib" ) #pragma comment( lib, "dinput8.lib" ) #pragma comment( lib, "dxguid.lib" ) #pragma comment( lib, "ws2_32.lib" ) #pragma comment( lib, "strmiids.lib" ) #pragma comment( lib, "ddraw.lib" ) #pragma comment( lib, "dmoguids.lib" ) //#pragma comment( lib, "wsock32.lib" ) #include #include bool __IS_TEST_SERVER_MODE__=false; // #define __USE_CYTHON__ #ifdef __USE_CYTHON__ // don't include these two files .h .cpp if you're implementing cython via .pyd // #include "PythonrootlibManager.h" // it would be better including such file in the project, but this is easier at this moment: // #include "PythonrootlibManager.cpp" #endif // #define __USE_EXTRA_CYTHON__ #ifdef __USE_EXTRA_CYTHON__ // don't include these two files .h .cpp if you're implementing cython via .pyd // #include "PythonuiscriptlibManager.h" // it would be better including such file in the project, but this is easier at this moment: // #include "PythonuiscriptlibManager.cpp" #endif #define ENABLE_PYLIB_CHECK #define ENABLE_MILES_CHECK // #define ENABLE_DAEMONPROTECTION #ifdef ENABLE_DAEMONPROTECTION #define DPDLL_FILENAME "dpdll.dll" #define DPDLL_CRC32 0x48104810 #define DPDLL_FILESIZE 1234567+4 #endif extern bool SetDefaultCodePage(DWORD codePage); static const char * sc_apszPythonLibraryFilenames[] = { "UserDict.pyc", "__future__.pyc", "copy_reg.pyc", "linecache.pyc", "ntpath.pyc", "os.pyc", "site.pyc", "stat.pyc", "string.pyc", "traceback.pyc", "types.pyc", "\n", }; #ifdef ENABLE_PYLIB_CHECK constexpr int PrintLevel = 0; #define PYFOLD "./lib" template void PrintMe(int level, const Args& ...Arguments) { if (PrintLevel >= level) TraceError(Arguments...); } // #define PYFORCE typedef struct PyLibFiles_s { std::string sFileName; size_t stSize; DWORD dwCRC32; } PyLibFiles_t; PyLibFiles_t PyLibFilesTable[] = { #if PY_VERSION_HEX==0x020706f0 { PYFOLD"/abc.pyc", 6187, 3834771731}, { PYFOLD"/bisect.pyc", 3236, 3116899751}, { PYFOLD"/codecs.pyc", 36978, 2928014693}, { PYFOLD"/collections.pyc", 26172, 385366131}, { PYFOLD"/copy.pyc", 13208, 1091298715}, { PYFOLD"/copy_reg.pyc", 5157, 536292604}, { PYFOLD"/encodings/aliases.pyc", 8803, 3888310600}, { PYFOLD"/encodings/cp949.pyc", 2009, 1824094431}, { PYFOLD"/encodings/__init__.pyc", 4510, 2926961588}, { PYFOLD"/fnmatch.pyc", 3732, 4270526278}, { PYFOLD"/functools.pyc", 6193, 3257285433}, { PYFOLD"/genericpath.pyc", 3303, 1652596334}, { PYFOLD"/heapq.pyc", 13896, 2948659214}, { PYFOLD"/keyword.pyc", 2169, 2178546341}, { PYFOLD"/linecache.pyc", 3235, 4048207604}, { PYFOLD"/locale.pyc", 49841, 4114662314}, { PYFOLD"/ntpath.pyc", 11961, 2765879465}, { PYFOLD"/os.pyc", 25769, 911432770}, { PYFOLD"/pyexpat.pyd", 127488, 2778492911}, { PYFOLD"/pyexpat_d.pyd", 194560, 2589182738}, { PYFOLD"/re.pyc", 13178, 1671609387}, { PYFOLD"/shutil.pyc", 19273, 1873281015}, { PYFOLD"/site.pyc", 20019, 3897044925}, { PYFOLD"/sre_compile.pyc", 11107, 1620746411}, { PYFOLD"/sre_constants.pyc", 6108, 3900811275}, { PYFOLD"/sre_parse.pyc", 19244, 1459430047}, { PYFOLD"/stat.pyc", 2791, 1375966108}, { PYFOLD"/string.pyc", 19656, 1066063587}, { PYFOLD"/sysconfig.pyc", 17571, 1529083148}, { PYFOLD"/traceback.pyc", 11703, 3768933732}, { PYFOLD"/types.pyc", 2530, 920695307}, { PYFOLD"/UserDict.pyc", 9000, 1431875928}, { PYFOLD"/warnings.pyc", 13232, 3752454002}, { PYFOLD"/weakref.pyc", 16037, 2124701469}, { PYFOLD"/xml/dom/domreg.pyc", 3506, 2127674645}, { PYFOLD"/xml/dom/expatbuilder.pyc", 36698, 316034696}, { PYFOLD"/xml/dom/minicompat.pyc", 4144, 747596376}, { PYFOLD"/xml/dom/minidom.pyc", 74704, 1543233763}, { PYFOLD"/xml/dom/nodefilter.pyc", 1243, 3805409468}, { PYFOLD"/xml/dom/xmlbuilder.pyc", 18659, 4118801318}, { PYFOLD"/xml/dom/__init__.pyc", 7337, 343751384}, { PYFOLD"/xml/parsers/expat.pyc", 326, 2425747752}, { PYFOLD"/xml/parsers/__init__.pyc", 353, 1691127318}, { PYFOLD"/xml/__init__.pyc", 1117, 3531597556}, { PYFOLD"/_abcoll.pyc", 22339, 2365844594}, { PYFOLD"/_locale.pyc", 49841, 4114662314}, { PYFOLD"/_weakrefset.pyc", 10490, 1576811346}, { PYFOLD"/__future__.pyc", 4431, 2857792867}, #elif PY_VERSION_HEX==0x020203f0 #else #error "unknown python version" #endif }; bool checkPyLibDir(const string szDirName) { bool HasHack = false; char szDirNamePath[MAX_PATH]; sprintf(szDirNamePath, "%s\\*", szDirName.c_str()); WIN32_FIND_DATA f; HANDLE h = FindFirstFile(szDirNamePath, &f); if (h == INVALID_HANDLE_VALUE) { return HasHack; } do { if (HasHack) break; const char * name = f.cFileName; if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { continue; } if (f.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) { char filePath[MAX_PATH]; sprintf(filePath, "%s%s%s", szDirName.c_str(), "\\", name); PrintMe(1, "sub %s", filePath); checkPyLibDir(filePath); } else { // start processing file PrintMe(1, "starting %s", name); std::string sName(name); std::string sPathName(szDirName+"/"+name); // change \\ to / std::replace(sPathName.begin(), sPathName.end(), '\\', '/'); PrintMe(1, "path %s", sPathName.c_str()); // lower file name std::transform(sName.begin(), sName.end(), sName.begin(), ::tolower); { PrintMe(1, "verify %s", sName.c_str()); bool isPyLibFound = false; for (PyLibFiles_t *i1=std::begin(PyLibFilesTable), *e1=std::end(PyLibFilesTable); i1sFileName.compare(sPathName)) { PrintMe(1, "found %s==%s", i1->sFileName.c_str(), sName.c_str()); DWORD dwCrc32 = GetFileCRC32(sPathName.c_str()); // assert(dwCrc32); DWORD dwFileSize = f.nFileSizeLow; if (i1->stSize!=dwFileSize) { PrintMe(1, "wrong size %u==%u", i1->stSize, dwFileSize); HasHack = true; PrintMe(0, "wrong size %u for %s", dwFileSize, sPathName.c_str()); return HasHack; } else if (i1->dwCRC32 != dwCrc32) { PrintMe(1, "wrong crc32 %u==%u", i1->dwCRC32, dwCrc32); HasHack = true; PrintMe(0, "wrong crc32 %u for %s", dwCrc32, sPathName.c_str()); return HasHack; } PrintMe(1, "right size %u==%u", i1->stSize, dwFileSize); PrintMe(1, "right crc32 %u==%u", i1->dwCRC32, dwCrc32); PrintMe(2, "{ \"%s\", %u, %u},", sPathName.c_str(), dwFileSize, dwCrc32); isPyLibFound = true; break; } } // block ambiguous pyc/d files if (!isPyLibFound) { PrintMe(1, "not found %s", sName.c_str()); #ifdef PYFORCE HasHack = true; PRINTME(0, "ambiguous file for %s", sPathName.c_str()); return HasHack; #endif } PrintMe(1, "skipping file(%s) hack(%u) found(%u)", sName.c_str(), HasHack, isPyLibFound); } } } while (FindNextFile(h, &f)); FindClose(h); return HasHack; } bool __CheckPyLibFiles() { PrintMe(1, "__CheckPyLibFiles processing " PYFOLD); if (checkPyLibDir(PYFOLD)) return false; return true; } #endif #ifdef ENABLE_MILES_CHECK #include #include "../EterBase/Filename.h" // #include "../EterBase/CRC32.h" typedef struct MilesFiles_s { std::string sFileName; size_t stSize; DWORD dwCRC32; } MilesFiles_t; typedef struct MilesExten_s { std::string ExtName; bool IsUni; } MilesExten_t; MilesExten_t MilesExtenTable[] = { {"dll", false}, {"asi", true}, {"flt", true}, {"m3d", true}, {"mix", true}, }; MilesFiles_t MilesFilesTable[] = { {"mss32.dll", 349696, 1817711331}, {"mssa3d.m3d", 83456, 1812642892}, {"mssds3d.m3d", 70656, 2704596484}, {"mssdsp.flt", 93696, 3364819387}, {"mssdx7.m3d", 80896, 236402185}, {"msseax.m3d", 103424, 3195814903}, {"mssmp3.asi", 125952, 1219814613}, {"mssrsx.m3d", 354816, 550946743}, {"msssoft.m3d", 67072, 4284421368}, {"mssvoice.asi", 197120, 1407967464}, }; bool checkMilesDir(const string szDirName) { bool HasHack = false; char szDirNamePath[MAX_PATH]; sprintf(szDirNamePath, "%s\\*", szDirName.c_str()); WIN32_FIND_DATA f; HANDLE h = FindFirstFile(szDirNamePath, &f); if (h == INVALID_HANDLE_VALUE) { return HasHack; } do { if (HasHack) break; const char * name = f.cFileName; if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { continue; } if (f.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) { // do nothing if it's a folder } else { // start processing file PrintMe(1, "starting %s", name); std::string sName(name); std::string sPathName(szDirName+"/"+name); PrintMe(1, "path %s", sPathName.c_str()); // lower file name std::transform(sName.begin(), sName.end(), sName.begin(), ::tolower); // file or symlink; check for asi flt m3d mix exploit string sNameExt = CFileNameHelper::GetExtension(sName); PrintMe(1, "ext %s", sNameExt.c_str()); // workaround instead of std::find bool isMilesFile = false, isMilesUnique = false; for (MilesExten_t *i1=std::begin(MilesExtenTable), *e1=std::end(MilesExtenTable); i1ExtName.c_str(), sNameExt.c_str()); if (!sNameExt.compare(0, i1->ExtName.length(), i1->ExtName)) { isMilesFile = true; isMilesUnique = i1->IsUni; } } if (isMilesFile) { PrintMe(1, "verify %s -> %s", sName.c_str(), sNameExt.c_str()); bool isMilesFound = false; for (MilesFiles_t *i1=std::begin(MilesFilesTable), *e1=std::end(MilesFilesTable); i1sFileName.compare(sName)) { PrintMe(1, "found %s==%s", i1->sFileName.c_str(), sName.c_str()); DWORD dwCrc32 = GetFileCRC32(sPathName.c_str()); // assert(dwCrc32); DWORD dwFileSize = f.nFileSizeLow; if (i1->stSize!=dwFileSize) { PrintMe(1, "wrong size %u==%u", i1->stSize, dwFileSize); HasHack = true; PrintMe(0, "wrong size %u for %s", dwFileSize, sPathName.c_str()); return HasHack; } else if (i1->dwCRC32 != dwCrc32) { PrintMe(1, "wrong crc32 %u==%u", i1->dwCRC32, dwCrc32); HasHack = true; PrintMe(0, "wrong crc32 %u for %s", dwCrc32, sPathName.c_str()); return HasHack; } PrintMe(1, "right size %u==%u", i1->stSize, dwFileSize); PrintMe(1, "right crc32 %u==%u", i1->dwCRC32, dwCrc32); isMilesFound = true; break; } } // only mss32.dll is checked, and there's no need to check the others if (!isMilesFound && isMilesUnique) { PrintMe(1, "not found %s", sName.c_str()); HasHack = true; PrintMe(0, "ambiguous file for %s", sPathName.c_str()); return HasHack; } PrintMe(1, "skipping file(%s) hack(%u) found(%u) uni(%u)", sName.c_str(), HasHack, isMilesFound, isMilesUnique); } } } while (FindNextFile(h, &f)); FindClose(h); return HasHack; } bool __CheckMilesFiles() { PrintMe(1, "__CheckMilesFiles processing . and .\\miles"); if (checkMilesDir(".") || checkMilesDir(".\\miles")) return false; return true; } #endif char gs_szErrorString[512] = ""; void ApplicationSetErrorString(const char* szErrorString) { strcpy(gs_szErrorString, szErrorString); } bool CheckPythonLibraryFilenames() { for (int i = 0; *sc_apszPythonLibraryFilenames[i] != '\n'; ++i) { std::string stFilename = "lib\\"; stFilename += sc_apszPythonLibraryFilenames[i]; if (_access(stFilename.c_str(), 0) != 0) { return false; } MoveFile(stFilename.c_str(), stFilename.c_str()); } return true; } struct ApplicationStringTable { HINSTANCE m_hInstance; std::map m_kMap_dwID_stLocale; } gs_kAppStrTable; void ApplicationStringTable_Initialize(HINSTANCE hInstance) { gs_kAppStrTable.m_hInstance=hInstance; } const std::string& ApplicationStringTable_GetString(DWORD dwID, LPCSTR szKey) { char szBuffer[512]; char szIniFileName[256]; char szLocale[256]; ::GetCurrentDirectory(sizeof(szIniFileName), szIniFileName); if(szIniFileName[lstrlen(szIniFileName)-1] != '\\') strcat(szIniFileName, "\\"); strcat(szIniFileName, "metin2client.dat"); strcpy(szLocale, LocaleService_GetLocalePath()); if(strnicmp(szLocale, "locale/", strlen("locale/")) == 0) strcpy(szLocale, LocaleService_GetLocalePath() + strlen("locale/")); ::GetPrivateProfileString(szLocale, szKey, NULL, szBuffer, sizeof(szBuffer)-1, szIniFileName); if(szBuffer[0] == '\0') LoadString(gs_kAppStrTable.m_hInstance, dwID, szBuffer, sizeof(szBuffer)-1); if(szBuffer[0] == '\0') ::GetPrivateProfileString("en", szKey, NULL, szBuffer, sizeof(szBuffer)-1, szIniFileName); if(szBuffer[0] == '\0') strcpy(szBuffer, szKey); std::string& rstLocale=gs_kAppStrTable.m_kMap_dwID_stLocale[dwID]; rstLocale=szBuffer; return rstLocale; } const std::string& ApplicationStringTable_GetString(DWORD dwID) { char szBuffer[512]; LoadString(gs_kAppStrTable.m_hInstance, dwID, szBuffer, sizeof(szBuffer)-1); std::string& rstLocale=gs_kAppStrTable.m_kMap_dwID_stLocale[dwID]; rstLocale=szBuffer; return rstLocale; } const char* ApplicationStringTable_GetStringz(DWORD dwID, LPCSTR szKey) { return ApplicationStringTable_GetString(dwID, szKey).c_str(); } const char* ApplicationStringTable_GetStringz(DWORD dwID) { return ApplicationStringTable_GetString(dwID).c_str(); } //////////////////////////////////////////// int Setup(LPSTR lpCmdLine); // Internal function forward bool PackInitialize(const char * c_pszFolder) { if (_access(c_pszFolder, 0) != 0) return true; std::string stFolder(c_pszFolder); stFolder += "/"; std::string stFileName(stFolder); stFileName += "Index"; CMappedFile file; LPCVOID pvData; if (!file.Create(stFileName.c_str(), &pvData, 0, 0)) { LogBoxf("FATAL ERROR! File not exist: %s", stFileName.c_str()); TraceError("FATAL ERROR! File not exist: %s", stFileName.c_str()); return true; } CMemoryTextFileLoader TextLoader; TextLoader.Bind(file.Size(), pvData); bool bPackFirst = TRUE; const std::string& strPackType = TextLoader.GetLineString(0); if (strPackType.compare("FILE") && strPackType.compare("PACK")) { TraceError("Pack/Index has invalid syntax. First line must be 'PACK' or 'FILE'"); return false; } #ifdef NDEBUG // @warme601 _DISTRIBUTE -> NDEBUG Tracef("Note: PackFirst mode enabled. [pack]\n"); #else bPackFirst = FALSE; Tracef("Note: PackFirst mode not enabled. [file]\n"); #endif CTextFileLoader::SetCacheMode(); #if defined(USE_RELATIVE_PATH) CEterPackManager::Instance().SetRelativePathMode(); #endif CEterPackManager::Instance().SetCacheMode(); CEterPackManager::Instance().SetSearchMode(bPackFirst); CSoundData::SetPackMode(); std::string strPackName, strTexCachePackName; for (DWORD i = 1; i < TextLoader.GetLineCount() - 1; i += 2) { const std::string & c_rstFolder = TextLoader.GetLineString(i); const std::string & c_rstName = TextLoader.GetLineString(i + 1); strPackName = stFolder + c_rstName; strTexCachePackName = strPackName + "_texcache"; CEterPackManager::Instance().RegisterPack(strPackName.c_str(), c_rstFolder.c_str()); CEterPackManager::Instance().RegisterPack(strTexCachePackName.c_str(), c_rstFolder.c_str()); } CEterPackManager::Instance().RegisterRootPack((stFolder + std::string("root")).c_str()); return true; } bool RunMainScript(CPythonLauncher& pyLauncher, const char* lpCmdLine) { initpack(); initdbg(); initime(); initgrp(); initgrpImage(); initgrpText(); initwndMgr(); ///////////////////////////////////////////// initudp(); initapp(); initsystemSetting(); initchr(); initchrmgr(); initPlayer(); initItem(); initNonPlayer(); initTrade(); initChat(); initTextTail(); initnet(); initMiniMap(); initProfiler(); initEvent(); initeffect(); initfly(); initsnd(); initeventmgr(); initshop(); initskill(); initquest(); initBackground(); initMessenger(); #ifdef ENABLE_ACCE_COSTUME_SYSTEM initAcce(); #endif #ifdef ENABLE_IKASHOP_RENEWAL initikashop(); #endif initsafebox(); initguild(); initServerStateChecker(); #ifdef __USE_CYTHON__ // don't add this line if you're implementing cython via .pyd: // initrootlibManager(); #endif #ifdef __USE_EXTRA_CYTHON__ // don't add this line if you're implementing cython via .pyd: // inituiscriptlibManager(); #endif PyObject * builtins = PyImport_ImportModule("__builtin__"); #ifdef NDEBUG // @warme601 _DISTRIBUTE -> NDEBUG PyModule_AddIntConstant(builtins, "__DEBUG__", 0); #else PyModule_AddIntConstant(builtins, "__DEBUG__", 1); #endif #ifdef __USE_CYTHON__ PyModule_AddIntConstant(builtins, "__USE_CYTHON__", 1); #else PyModule_AddIntConstant(builtins, "__USE_CYTHON__", 0); #endif #ifdef __USE_EXTRA_CYTHON__ PyModule_AddIntConstant(builtins, "__USE_EXTRA_CYTHON__", 1); #else PyModule_AddIntConstant(builtins, "__USE_EXTRA_CYTHON__", 0); #endif // RegisterCommandLine { std::string stRegisterCmdLine; const char * loginMark = "-cs"; const char * loginMark_NonEncode = "-ncs"; const char * seperator = " "; std::string stCmdLine; const int CmdSize = 3; std::vector stVec; SplitLine(lpCmdLine,seperator,&stVec); if (CmdSize == stVec.size() && stVec[0]==loginMark) { char buf[MAX_PATH]; base64_decode(stVec[2].c_str(),buf); stVec[2] = buf; string_join(seperator,stVec,&stCmdLine); } else if (CmdSize <= stVec.size() && stVec[0]==loginMark_NonEncode) { stVec[0] = loginMark; string_join(" ",stVec,&stCmdLine); } else stCmdLine = lpCmdLine; PyModule_AddStringConstant(builtins, "__COMMAND_LINE__", stCmdLine.c_str()); } { std::vector stVec; SplitLine(lpCmdLine," " ,&stVec); if (stVec.size() != 0 && "--pause-before-create-window" == stVec[0]) system("pause"); #ifdef ENABLE_DAEMONPROTECTION DWORD dwCrc32, dwSize; if (!((dwCrc32 = GetFileCRC32(DPDLL_FILENAME))==DPDLL_CRC32)) { TraceError("dpdll wrong crc32 %d", dwCrc32); return false; } if (!((dwSize = GetFileSize(DPDLL_FILENAME))==DPDLL_FILESIZE)) { TraceError("dpdll wrong size %d", dwSize); return false; } if (!LoadLibraryA(DPDLL_FILENAME)) { TraceError("dpdll not loaded"); return false; } #endif #ifdef __USE_CYTHON__ if (!pyLauncher.RunLine("import rootlib\nrootlib.moduleImport('system')")) #else if (!pyLauncher.RunFile("system.py")) #endif { TraceError("RunMain Error"); return false; } } return true; } bool Main(HINSTANCE hInstance, LPSTR lpCmdLine) { #ifdef LOCALE_SERVICE_YMIR extern bool g_isScreenShotKey; g_isScreenShotKey = true; #endif DWORD dwRandSeed=time(NULL)+DWORD(GetCurrentProcess()); srandom(dwRandSeed); srand(random()); SetLogLevel(1); #ifdef LOCALE_SERVICE_VIETNAM_MILD extern BOOL USE_VIETNAM_CONVERT_WEAPON_VNUM; USE_VIETNAM_CONVERT_WEAPON_VNUM = true; #endif if (_access("perf_game_update.txt", 0)==0) { DeleteFile("perf_game_update.txt"); } if (_access("newpatch.exe", 0)==0) { system("patchupdater.exe"); return false; } ilInit(); if (!Setup(lpCmdLine)) return false; #ifdef _DEBUG OpenConsoleWindow(); OpenLogFile(true); // true == uses syserr.txt and log.txt #else OpenLogFile(false); // false == uses syserr.txt only #endif static CLZO lzo; static CEterPackManager EterPackManager; if (!PackInitialize("pack")) { LogBox("Pack Initialization failed. Check log.txt file.."); return false; } if(LocaleService_LoadGlobal(hInstance)) SetDefaultCodePage(LocaleService_GetCodePage()); #ifdef ENABLE_PYLIB_CHECK if (!__CheckPyLibFiles()) return false; #endif #ifdef ENABLE_MILES_CHECK if (!__CheckMilesFiles()) return false; #endif CPythonApplication * app = new CPythonApplication; app->Initialize(hInstance); bool ret=false; { CPythonLauncher pyLauncher; CPythonExceptionSender pyExceptionSender; SetExceptionSender(&pyExceptionSender); if (pyLauncher.Create()) { ret=RunMainScript(pyLauncher, lpCmdLine); } //ProcessScanner_ReleaseQuitEvent(); app->Clear(); timeEndPeriod(1); pyLauncher.Clear(); } app->Destroy(); delete app; return ret; } HANDLE CreateMetin2GameMutex() { SECURITY_ATTRIBUTES sa; ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = FALSE; return CreateMutex(&sa, FALSE, "Metin2GameMutex"); } void DestroyMetin2GameMutex(HANDLE hMutex) { if (hMutex) { ReleaseMutex(hMutex); hMutex = NULL; } } void __ErrorPythonLibraryIsNotExist() { LogBoxf("FATAL ERROR!! Python Library file not exist!"); } bool __IsTimeStampOption(LPSTR lpCmdLine) { const char* TIMESTAMP = "/timestamp"; return (strncmp(lpCmdLine, TIMESTAMP, strlen(TIMESTAMP))==0); } void __PrintTimeStamp() { #ifdef _DEBUG if (__IS_TEST_SERVER_MODE__) LogBoxf("METIN2 BINARY TEST DEBUG VERSION %s ( MS C++ %d Compiled )", __TIMESTAMP__, _MSC_VER); else LogBoxf("METIN2 BINARY DEBUG VERSION %s ( MS C++ %d Compiled )", __TIMESTAMP__, _MSC_VER); #else if (__IS_TEST_SERVER_MODE__) LogBoxf("METIN2 BINARY TEST VERSION %s ( MS C++ %d Compiled )", __TIMESTAMP__, _MSC_VER); else LogBoxf("METIN2 BINARY DISTRIBUTE VERSION %s ( MS C++ %d Compiled )", __TIMESTAMP__, _MSC_VER); #endif } bool __IsLocaleOption(LPSTR lpCmdLine) { return (strcmp(lpCmdLine, "--locale") == 0); } bool __IsLocaleVersion(LPSTR lpCmdLine) { return (strcmp(lpCmdLine, "--perforce-revision") == 0); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { #ifdef _DEBUG _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_CRT_DF | _CRTDBG_LEAK_CHECK_DF ); //_CrtSetBreakAlloc( 110247 ); #endif ApplicationStringTable_Initialize(hInstance); LocaleService_LoadConfig("locale.cfg"); #if defined(__BL_MULTI_LANGUAGE__) LocaleService_LoadLocaConfig(); #endif SetDefaultCodePage(LocaleService_GetCodePage()); #if defined(CHECK_LATEST_DATA_FILES) if (!CheckLatestFiles()) return 0; #endif bool bQuit = false; bool bAuthKeyChecked = false; int nArgc = 0; PCHAR* szArgv = CommandLineToArgv( lpCmdLine, &nArgc ); for( int i=0; i < nArgc; i++ ) { if(szArgv[i] == 0) continue; if (__IsLocaleVersion(szArgv[i])) { char szModuleName[MAX_PATH]; char szVersionPath[MAX_PATH]; GetModuleFileName(NULL, szModuleName, sizeof(szModuleName)); sprintf(szVersionPath, "%s.version", szModuleName); FILE* fp = fopen(szVersionPath, "wt"); if (fp) { extern int METIN2_GET_VERSION(); fprintf(fp, "r%d\n", METIN2_GET_VERSION()); fclose(fp); } bQuit = true; } else if (__IsLocaleOption(szArgv[i])) { FILE* fp=fopen("locale.txt", "wt"); fprintf(fp, "service[%s] code_page[%d]", LocaleService_GetName(), LocaleService_GetCodePage()); fclose(fp); bQuit = true; } else if (__IsTimeStampOption(szArgv[i])) { __PrintTimeStamp(); bQuit = true; } else if ((strcmp(szArgv[i], "--force-set-locale") == 0)) { if (nArgc <= i + 2) { MessageBox(NULL, "Invalid arguments", ApplicationStringTable_GetStringz(IDS_APP_NAME, "APP_NAME"), MB_ICONSTOP); goto Clean; } const char* localeName = szArgv[++i]; const char* localePath = szArgv[++i]; LocaleService_ForceSetLocale(localeName, localePath); } } if(bQuit) goto Clean; #if defined(NEEDED_COMMAND_ARGUMENT) if (strstr(lpCmdLine, NEEDED_COMMAND_ARGUMENT) == 0) { MessageBox(NULL, ApplicationStringTable_GetStringz(IDS_ERR_MUST_LAUNCH_FROM_PATCHER, "ERR_MUST_LAUNCH_FROM_PATCHER"), ApplicationStringTable_GetStringz(IDS_APP_NAME, "APP_NAME"), MB_ICONSTOP); goto Clean; } #endif #if defined(NEEDED_COMMAND_CLIPBOARD) { CHAR szSecKey[256]; CPostIt cPostIt( "VOLUME1" ); if( cPostIt.Get( "SEC_KEY", szSecKey, sizeof(szSecKey) ) == FALSE ) { MessageBox(NULL, ApplicationStringTable_GetStringz(IDS_ERR_MUST_LAUNCH_FROM_PATCHER, "ERR_MUST_LAUNCH_FROM_PATCHER"), ApplicationStringTable_GetStringz(IDS_APP_NAME, "APP_NAME"), MB_ICONSTOP); goto Clean; } if( strstr(szSecKey, NEEDED_COMMAND_CLIPBOARD) == 0 ) { MessageBox(NULL, ApplicationStringTable_GetStringz(IDS_ERR_MUST_LAUNCH_FROM_PATCHER, "ERR_MUST_LAUNCH_FROM_PATCHER"), ApplicationStringTable_GetStringz(IDS_APP_NAME, "APP_NAME"), MB_ICONSTOP); goto Clean; } cPostIt.Empty(); } #endif WebBrowser_Startup(hInstance); #ifndef ENABLE_PYLIB_CHECK if (!CheckPythonLibraryFilenames()) { __ErrorPythonLibraryIsNotExist(); goto Clean; } #endif Main(hInstance, lpCmdLine); WebBrowser_Cleanup(); ::CoUninitialize(); if(gs_szErrorString[0]) MessageBox(NULL, gs_szErrorString, ApplicationStringTable_GetStringz(IDS_APP_NAME, "APP_NAME"), MB_ICONSTOP); Clean: SAFE_FREE_GLOBAL(szArgv); return 0; } #if GrannyProductMinorVersion==4 || GrannyProductMinorVersion==7 static void GrannyError(granny_log_message_type Type, granny_log_message_origin Origin, char const *Error, void *UserData) { TraceError("GRANNY: %s", Error); } #elif GrannyProductMinorVersion==9 || GrannyProductMinorVersion==8 static void GrannyError(granny_log_message_type Type, granny_log_message_origin Origin, char const* File, granny_int32x Line, char const *Error, void *UserData) { //Origin==GrannyFileReadingLogMessage for granny run-time tag& revision warning (Type==GrannyWarningLogMessage) //Origin==GrannyControlLogMessage for miss track_group on static models as weapons warning (Type==GrannyWarningLogMessage) //Origin==GrannyMeshBindingLogMessage for miss bone ToSkeleton on new ymir models error (Type==GrannyErrorLogMessage) // if (Type == GrannyWarningLogMessage) if (Origin==GrannyFileReadingLogMessage || Origin==GrannyControlLogMessage || Origin==GrannyMeshBindingLogMessage) return; TraceError("GRANNY: %s(%d): ERROR: %s --- [%d] %s --- [%d] %s", File, Line, Error, Type, GrannyGetLogMessageTypeString(Type), Origin, GrannyGetLogMessageOriginString(Origin)); } #elif GrannyProductMinorVersion==11 static void GrannyError(granny_log_message_type Type, granny_log_message_origin Origin, char const* File, granny_int32x Line, char const *Error, void *UserData) { } #else #error "unknown granny version" #endif int Setup(LPSTR lpCmdLine) { TIMECAPS tc; UINT wTimerRes; if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) return 0; wTimerRes = MINMAX(tc.wPeriodMin, 1, tc.wPeriodMax); timeBeginPeriod(wTimerRes); granny_log_callback Callback; Callback.Function = GrannyError; Callback.UserData = 0; GrannySetLogCallback(&Callback); return 1; } //martysama0134's 2e58d0b8baeb072acdf3afc4a5d1999f