Metin2 Client Exe Giriş Sınırlandırma

Quaftar

Moderatör
Moderatör
Premium Üye
Geliştirici
Yardımsever Üye
Editör
Mesaj
735
Çözümler
55
Beğeni
1.379
Puan
1.179
Ticaret Puanı
0
:mmt-hakkinda:
Metin2 oyunu açma sınırı belirlemektir. İlerde sunucu acarken girişler tıkanmaması için client sınırı uygulanabilir.
Sunucuya saldırılardan bir tanesi client'den saldırmaktır, bunun sayasiyle 1 bilgisayardan 10 veya 15 hatta daha fazla oyun açarak sunucu girişlerini zorlamaktır.
Bu sistem sayesiyle client'den saldırıyı bir nebze olsa azaltmaktır, Bir çok yerde parayla satılmaktadır.

Client/UserInterface/UserInterface.cpp Müsait Bi Yere Ekle:
bool genMutex(int id)
{
std::string mutex_name = "MultiBoxBlock";
mutex_name.push_back(id);
HANDLE Mutex = OpenMutexA(MUTEX_ALL_ACCESS, 1, mutex_name.c_str());

if (!Mutex || WaitForSingleObject(Mutex,500) == WAIT_ABANDONED)
{
CreateMutexA(0, 1, mutex_name.c_str());
Sleep(INFINITY);//locks mutex
return true;
}

return false;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
bool ret = false;
for (int i = 0;i<3;i++) // Client sınırını 3 olarak ayarlamak.
{
ret = genMutex(i);
if (ret)
break;
}
if (!ret)
{
MessageBoxA(NULL, "MultiBox detected", "", MB_OK);
ExitProcess(0);
}
 
Sınır 3 değiştirilebilir.:
for (int i = 0;i<3;i++) // Client sınırını 3 olarak ayarlamak.
 
Linkleri görebilmek için giriş yap veya kayıt ol.
bu hatayı alıyorum müsait bir yerine dediniz
Linkleri görebilmek için giriş yap veya kayıt ol.
buraya ekledim en alta \Client_Source\source\UserInterface/UserInterface.cpp
tab ayarına dikkat edelim:
bool genMutex(int id)
{
    std::string mutex_name = "MultiBoxBlock";
    mutex_name.push_back(id);
    HANDLE Mutex = OpenMutexA(MUTEX_ALL_ACCESS, 1, mutex_name.c_str());
    
    if (!Mutex || WaitForSingleObject(Mutex,500) == WAIT_ABANDONED)
    {
        CreateMutexA(0, 1, mutex_name.c_str());
        Sleep(INFINITY);//locks mutex
        return true;
    }
    
    return false;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    bool ret = false;
    for (int i = 0;i<3;i++)
    {
        ret = genMutex(i);
        if (ret)
            break;
    }
    if (!ret)
    {
        MessageBoxA(NULL, "MultiBox detected", "", MB_OK);
        ExitProcess(0);
    }
 
Paylaşım için teşekkür ederim. Çalışıyor fakat alınan hata şu şekilde zaten bu kod bloğu var yazıyor winmain kod bloğunu aratıp bulup aşağıdaki kodları içine eklemeniz gerekiyor.

C++:
        bool ret = false;
    for (int i = 0;i<3;i++)
    {
        ret = genMutex(i);
        if (ret)
            break;
    }
    if (!ret)
    {
        MessageBoxA(NULL, "MultiBox detected", "", MB_OK);
        ExitProcess(0);
    }
 
Çıkan uyarı penceresi ikonsuz ve başlıksızdır bende ki gibi özelleştirmek isterseniz bu kodu kullanabilirsiniz.

C++:
MessageBoxA(NULL, "Daha fazla oyuna izin verilmez. \n\n Site Adresiniz", "UYARI", MB_OK  | MB_ICONWARNING);

Linkleri görebilmek için giriş yap veya kayıt ol.
 
metin hocam ben bir türlü ekliyemiyorum hatta alıyorum sıfırdan siz ekler misiniz
Linkleri görebilmek için giriş yap veya kayıt ol.
Şu şekilde bir dener misin?
UserInterface.cpp:
#include "StdAfx.h"
#include "PythonApplication.h"
#include "ProcessScanner.h"
#include "PythonExceptionSender.h"
#include "resource.h"
#include "Version.h"

#ifdef _DEBUG
#include <crtdbg.h>
#endif

#include "../eterPack/EterPackManager.h"
#include "../eterLib/Util.h"
#include "../CWebBrowser/CWebBrowser.h"
#include "../eterBase/CPostIt.h"

#include "CheckLatestFiles.h"

#ifdef fMetin_HACKSHIELD
    #include "fMetin_Shield.h"
#endif

#include "Hackshield.h"
#include "NProtectGameGuard.h"
#include "WiseLogicXTrap.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, "python27.lib" )
#pragma comment( lib, "imagehlp.lib" )
#pragma comment( lib, "devil.lib" )
#pragma comment( lib, "granny2.lib" )
#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 <stdlib.h>
#include <cryptopp/cryptoppLibLink.h>
bool __IS_TEST_SERVER_MODE__=false;

extern bool SetDefaultCodePage(DWORD codePage);

#ifdef USE_OPENID
extern int openid_test;
#endif

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",
};

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<DWORD, std::string> 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)
{
    NANOBEGIN
    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 _DISTRIBUTE
    Tracef("알림: 팩 모드입니다.\n");
    
    //if (0 == strPackType.compare("FILE"))
    //{
    //    bPackFirst = FALSE;
    //    Tracef("알림: 파일 모드입니다.\n");
    //}
    //else
    //{
    //    Tracef("알림: 팩 모드입니다.\n");
    //}
#else
    bPackFirst = FALSE;
    Tracef("알림: 파일 모드입니다.\n");
#endif

    CTextFileLoader::SetCacheMode();
#if defined(USE_RELATIVE_PATH)
    CEterPackManager::Instance().SetRelativePathMode();
#endif
    CEterPackManager::Instance().SetCacheMode();
    CEterPackManager::Instance().SetSearchMode(bPackFirst);

    CSoundData::SetPackMode(); // Miles 파일 콜백을 셋팅

    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());
    NANOEND
    return true;
}

bool RunMainScript(CPythonLauncher& pyLauncher, const char* lpCmdLine)
{
    initpack();
    initdbg();
    initime();
    initgrp();
    initgrpImage();
    initgrpText();
    initwndMgr();
    /////////////////////////////////////////////
    initudp();
    initapp();
    initsystem();
    initchr();
    initchrmgr();
    initPlayer();
    initItem();
    initNonPlayer();
    initTrade();
    initChat();
    initTextTail();
    initnet();
    initMiniMap();
    initProfiler();
    initEvent();
    initeffect();
    initfly();
    initsnd();
    initeventmgr();
    initshop();
    initskill();
    initquest();
    initBackground();
    initMessenger();

    initsafebox();

#ifdef ENABLE_WHISPER_RENEWAL
    initWhisper();
#endif

    initguild();
    initServerStateChecker();
#ifdef ENABLE_SWITCHBOT
    initSwitchbot();
#endif
    NANOBEGIN

    // RegisterDebugFlag
    {
        std::string stRegisterDebugFlag;

#ifdef _DISTRIBUTE
        stRegisterDebugFlag ="__DEBUG__ = 0";
#else
        stRegisterDebugFlag ="__DEBUG__ = 1";
#endif

        if (!pyLauncher.RunLine(stRegisterDebugFlag.c_str()))
        {
            TraceError("RegisterDebugFlag Error");
            return false;
        }
    }

    // RegisterCommandLine
    {
        std::string stRegisterCmdLine;

        const char * loginMark = "-cs";
        const char * loginMark_NonEncode = "-ncs";
        const char * seperator = " ";

        std::string stCmdLine;
        const int CmdSize = 3;
        vector<std::string> stVec;
        SplitLine(lpCmdLine,seperator,&stVec);
        if (CmdSize == stVec.size() && stVec[0]==loginMark)
        {
            char buf[MAX_PATH];    //TODO 아래 함수 string 형태로 수정
            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;

        stRegisterCmdLine ="__COMMAND_LINE__ = ";
        stRegisterCmdLine+='"';
        stRegisterCmdLine+=stCmdLine;
        stRegisterCmdLine+='"';

        const CHAR* c_szRegisterCmdLine=stRegisterCmdLine.c_str();
        if (!pyLauncher.RunLine(c_szRegisterCmdLine))
        {
            TraceError("RegisterCommandLine Error");
            return false;
        }
    }
    {
        vector<std::string> stVec;
        SplitLine(lpCmdLine," " ,&stVec);

        if (stVec.size() != 0 && "--pause-before-create-window" == stVec[0])
        {
#ifdef XTRAP_CLIENT_ENABLE
            if (!XTrap_CheckInit())
                return false;
#endif
            system("pause");
        }
        if (!pyLauncher.RunFile("system.py"))
        {
            TraceError("RunMain Error");
            return false;
        }
    }

    NANOEND
    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;
    }
#ifndef __VTUNE__
    ilInit();
#endif
    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());

    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);
}

#ifdef USE_OPENID
//2012.07.16 김용욱
//일본 OpenID 지원. 인증키 인자 추가
bool __IsOpenIDAuthKeyOption(LPSTR lpCmdLine)
{
    return (strcmp(lpCmdLine, "--openid-authkey") == 0);
}

bool __IsOpenIDTestOption(LPSTR lpCmdLine) //클라이언트에서 로그인이 가능하다.
{
    return (strcmp(lpCmdLine, "--openid-test") == 0);
}
#endif /* USE_OPENID */

bool genMutex(int id)
{
    std::string mutex_name = "MultiBoxBlock";
    mutex_name.push_back(id);
    HANDLE Mutex = OpenMutexA(MUTEX_ALL_ACCESS, 1, mutex_name.c_str());
    
    if (!Mutex || WaitForSingleObject(Mutex,500) == WAIT_ABANDONED)
    {
        CreateMutexA(0, 1, mutex_name.c_str());
        Sleep(INFINITY);//locks mutex
        return true;
    }
    
    return false;
}


#ifdef URIEL_AC_VERIFY
extern "C" __declspec(dllexport) void urielac();
#endif
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    
    bool ret = false;
    for (int i = 0;i<3;i++) // Client sınırını 3 olarak ayarlamak.
    {
        ret = genMutex(i);
        if (ret)
            break;
    }
    if (!ret)
    {
        MessageBoxA(NULL, "MultiBox detected", "", MB_OK);
        ExitProcess(0);
    }
    
#ifdef URIEL_AC_VERIFY
    urielac();
#endif
    if (strstr(lpCmdLine, "--hackshield") != 0)
        return 0;

#ifdef fMetin_HACKSHIELD
    if (strstr(lpCmdLine, "--m2hshield") == 0)
        HileEngel_Tarama_fMetin();
#endif

#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");
    SetDefaultCodePage(LocaleService_GetCodePage());   

#ifdef XTRAP_CLIENT_ENABLE
    if (!XTrap_Init())
        return 0;
#endif

#ifdef USE_AHNLAB_HACKSHIELD
    if (!HackShield_Init())
        return 0;
#endif

#ifdef USE_NPROTECT_GAMEGUARD
    if (!GameGuard_Init())
        return 0;
#endif

#if defined(CHECK_LATEST_DATA_FILES)
    if (!CheckLatestFiles())
        return 0;
#endif

    bool bQuit = false;
    bool bAuthKeyChecked = false;    //OpenID 버전에서 인증키가 들어왔는지 알기 위한 인자.
    int nArgc = 0;
    PCHAR* szArgv = CommandLineToArgv( lpCmdLine, &nArgc );

    for( int i=0; i < nArgc; i++ ) {
        if(szArgv[i] == 0)
            continue;
        if (__IsLocaleVersion(szArgv[i])) // #0000829: [M2EU] 버전 파일이 항상 생기지 않도록 수정
        {
            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))
        {
            // locale 설정엔 인자가 두 개 더 필요함 (로케일 명칭, 데이터 경로)
            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);
        }
#ifdef USE_OPENID
        else if (__IsOpenIDAuthKeyOption(szArgv[i]))    //2012.07.16 OpenID : 김용욱
        {
            // 인증키 설정엔 인자가 한 개 더 필요함 (인증키)
            if (nArgc <= i + 1)
            {
                MessageBox(NULL, "Invalid arguments", ApplicationStringTable_GetStringz(IDS_APP_NAME, "APP_NAME"), MB_ICONSTOP);
                goto Clean;
            }

            const char* authKey = szArgv[++i];

            //ongoing (2012.07.16)
            //인증키 저장하는 부분
            LocaleService_SetOpenIDAuthKey(authKey);

            bAuthKeyChecked = true;
        }
        else if (__IsOpenIDTestOption(szArgv[i]))
        {
            openid_test = 1;

        }
#endif /* USE_OPENID */
    }

#ifdef USE_OPENID
    //OpenID
    //OpenID 클라이언트의 경우인증키를 받아오지 않을 경우 (웹을 제외하고 실행 시) 클라이언트 종료.
    
    if (false == bAuthKeyChecked && !openid_test)
    {
        MessageBox(NULL, "Invalid execution", ApplicationStringTable_GetStringz(IDS_APP_NAME, "APP_NAME"), MB_ICONSTOP);
        goto Clean;
    }
#endif /* USE_OPENID */


    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);

    if (!CheckPythonLibraryFilenames())
    {
        __ErrorPythonLibraryIsNotExist();
        goto Clean;
    }

    Main(hInstance, lpCmdLine);

#ifdef USE_NPROTECT_GAMEGUARD
    GameGuard_NoticeMessage();
#endif

    WebBrowser_Cleanup();

    ::CoUninitialize();

    if(gs_szErrorString[0])
        MessageBox(NULL, gs_szErrorString, ApplicationStringTable_GetStringz(IDS_APP_NAME, "APP_NAME"), MB_ICONSTOP);

Clean:
#ifdef USE_AHNLAB_HACKSHIELD
    HackShield_Shutdown();
#endif
    SAFE_FREE_GLOBAL(szArgv);

    return 0;
}

static void GrannyError(granny_log_message_type Type,
                        granny_log_message_origin Origin,
                        char const* File,
                        granny_int32x Line,
                        char const *Error,
                        void *UserData)
{
    TraceError("GRANNY: %s", Error);
}

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);

    return 1;
}
 
Tam olarak nereye ekleyeceğiz deniyorum hata almaktayız.
 
Metin2 oyunu gerçekten ilgi alanım olmasa da, aşağıda ki gibi bir düzenlemenin çok daha sağlıklı olacağına inanıyorum.

Öncelikle, blokta hata kontrolleri eklemek iyi bir uygulama olacaktır. basitçe, OpenMutexA veya CreateMutexA çağrıları başarısız olursa, dönüşün nedenini belirten bir hata mesajı almak daha sağlıklı olabilir.
C++:
HANDLE Mutex = OpenMutexA(MUTEX_ALL_ACCESS, FALSE, mutex_name.c_str());
if (!Mutex) {
    if (GetLastError() == ERROR_FILE_NOT_FOUND) {
        Mutex = CreateMutexA(NULL, FALSE, mutex_name.c_str());
        if (!Mutex) {
            // Bu noktada Mutex oluşturma hatasını ele alıyoruz
        }
    }
    else {
    }
}

Mutex access: Yukarıda CreateMutexA çağırınca lpMutexAttributes parametresini kullanarak daha spesifik mutex erişim hakları belirleyebilirsiniz. Bu şekilde, duplicate görevi gören diğer 3th. uygulamaların gereksiz erişimini engelleyebilirsiniz.
Tercihe bağlı olarak, daha spesifik hale getirmek isterseniz WaitForSingleObject fonksiyonunu kullanırken WAIT_ABANDONED durumunu kontrol etmek yerine, WAIT_FAILED durumunu kontrol edip daha spesifik hata mesajları alabilirsiniz.
C++:
DWORD waitResult = WaitForSingleObject(Mutex, 500);
if (waitResult == WAIT_FAILED) {
    // WaitForSingleObject hatasını ele alıyoruz
}
else if (waitResult == WAIT_ABANDONED) {
    // WAIT_ABANDONED koşulunu bu notkada işliyoruz
}

//Alternatifen
Mutex isimlendirmek güçlü bir çözüm olabilir, HeroEngine'de çoğu Mutexlerimizi güçlü şekilde isimlendiriyoruz. Her ne kadar biz Real-time bir kod yapısı kullansak da C++'de Mutex isimlendirirken dikkatli olmalısınız. HeroEngine kendi özel program betiğini kullanıyor, OOP (Object-Oriented Programming) temelinde bir dil olduğu için, bazı ifadelerde ve işlev çağrılarında çok büyük farklılık var. Dinamik bir DOM kullandığımız için işte basit bir örnek;
1691420413770.png
Her neyse bu durumda tekil ve tahmin edilmesi zor bir isim kullanarak diğer bu yukarda dediğim gibi 3th uygulamaların bu mutex'e erişmesini zorlaştırabilirsiniz.

Thread'in güvenliğinde ise yürütülebilir istemci'nin thread kontrolü atlanmaması gereken önemli bir nokta, eğer birden fazla iş parçacığında çalışacaksa, mutex erişimi ve diğer senkronizasyon mekanizmalarını kullanarak kodun thread güvenliğini sağlayalım. Bununla birlikte de for ile sonsuz bir döngüye girmemek için ret değerini başlangıçta false olarak ayarlayabilirsiniz. Böylece, döngü içinde doğru mutex bulunduğunda döngüden çıkabilirsiniz.

Buna göre, kodu aşağıda ki şekilde değiştirmek daha sağlıklı olabilir.
C++:
bool ret = false;
for (int i = 0; i < 3 && !ret; i++) {
    ret = genMutex(i);
}

Bilgilendirme: Test edilmiş ve çalıştığı gözlemlenerek performans analizleri dahilinde konuya paylaşılmıştır.

Bu aşağıda sunacaklarım kesinlikle öneridir. Magic To Master'de her bir client'i ClientTracking ID ile takip ediyoruz böylece her istemcinin analitik verilerine ulaşabiliyoruz. Hangi cihaz kaç istemci çalıştırıyor, bunları gözlemleyebiliyoruz. Söylediğim gibi HSL'de yani (OOP) programlamada ki mantık çok farklı. Aşağıda ki yöntemle C++ haline uyarlayabilir ve bir WebAPIConnector yazarak bunu bir kontrol paneline bağlayabilirsiniz.
  • std::unordered_setile istemci takibi client ilk defa bir mutex oluşturursa, bu clienti izlemeye (tracking) alır. Program sona erdiğinde, tüm clientin sahip olduğu mutex'leri boşa bırakır.
Aşağıda client takip için yeniden yazılmış bir örnek bulabilirsiniz.

C++:
std::unordered_set<int> trackedClients;

bool genMutex(int id) {
    std::string mutex_name = "MultiBoxBlock";
    mutex_name.push_back(id);

    HANDLE Mutex = OpenMutexA(MUTEX_ALL_ACCESS, FALSE, mutex_name.c_str());

    if (!Mutex) {
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
            Mutex = CreateMutexA(NULL, FALSE, mutex_name.c_str());
            if (!Mutex) {
            }
            else {
                trackedClients.insert(id);  // Track
            }
        }
        else {
        }
    }

    if (Mutex) {
        DWORD waitResult = WaitForSingleObject(Mutex, 500);
        if (waitResult == WAIT_FAILED) {
        }
        else if (waitResult == WAIT_ABANDONED) {
        }
        else {
            return true;
        }
    }

    return false;
}

İşte daha fazlası için neler yapabileceğinize dair bir kaç fikir.
CRPT: Eğer verileri güvence altına almanız gerekiyorsa, kriptografi kullanabilirsiniz. Örneğin, veri iletimi sırasında SSL/TLS gibi şifreleme protokollerini kullanabilirsiniz. Bunun için güçlü bir Root CA ihtiyacınız olacak. Sectigo tercih edilebilir.
(LPP) Least Privilege Principle: Oyun istemcilerinin çalışma sürecine ve kullanıcılarına en az ayrıcalıkla yetki verebilirsiniz. Bu şekilde, bir AC kullanmıyorsanız gereksiz erişimlerin engellenmesi sağlanabilir.
(NPS) Null Pointer Safety: Nps, oyun istemcinizin çalışma zamanında null (nullptr) erişmesini engellemeyi amaçlayan bir güvenlik ve hata önlemidir. Bir işaretçi nullptr (veya NULL) değerini taşıdığında, bu işaretçi üzerinden veriye veya işlemlere erişilmeye çalışıldığında hatalara neden olur. NPS ile pointerlerinizi güvence altına alabilirsiniz.

Bir konu olabilecek kadar geniş bir konuyu, severim post olarak atmayı. :cool:
Keyifli forumlar, bol kodlu iyi çalışmalar.
 
valla dostum yeniyim kusura bakma cok faydalı bir paylaşım olmuş fakat bu kodları nasıl nereye yapıştırıcam bilmiyorum.
Client/UserInterface/UserInterface.cpp M Böyle bi sekmem yok maalesef
 
@tahir3461 client source dosyaları elinizde mevcutsa yardımcı olurum.
 
Geri
Üst