예제 #1
0
static void IGotAuthFileList(ENetError result, void* param, const NetCliAuthFileInfo infoArr[], unsigned infoCount)
{
    pfPatcherWorker* patcher = static_cast<pfPatcherWorker*>(param);

    if (IS_NET_SUCCESS(result)) {
        // so everything goes directly into the Requests deque because AuthSrv lists
        // don't have any hashes attached. WHY did eap think this was a good idea?!?!
        {
            hsTempMutexLock lock(patcher->fRequestMut);
            for (unsigned i = 0; i < infoCount; ++i) {
                PatcherLogYellow("\tEnqueuing Legacy File '%S'", infoArr[i].filename);

                plFileName fn = plString::FromWchar(infoArr[i].filename);
                plFileSystem::CreateDir(fn.StripFileName());

                // We purposefully do NOT Open this stream! This uses a special auth-file constructor that
                // utilizes a backing hsRAMStream. This will be fed to plStreamSource later...
                pfPatcherStream* s = new pfPatcherStream(patcher, fn, infoArr[i].filesize);
                pfPatcherWorker::Request req = pfPatcherWorker::Request(fn.AsString(), pfPatcherWorker::Request::kAuthFile, s);
                patcher->fRequests.push_back(req);
            }
        }
        patcher->IssueRequest();
    } else {
        PatcherLogRed("\tSHIT! Some legacy manifest phailed");
        patcher->EndPatch(result, "SecurePreloader failed");
    }
}
예제 #2
0
//============================================================================
static void DownloadCallback (
    ENetError       result,
    void *          param,
    const wchar_t     filename[],
    hsStream *      writer
) {
    if(IS_NET_ERROR(result)) {
        switch (result) {
            case kNetErrTimeout:
                writer->Rewind();
                NetCliFileDownloadRequest(filename, writer, DownloadCallback, param);
            break;
            
            default:
                plString msg = plString::Format("Error getting patcher file: %S", NetErrorToString(result));
                plStatusLog::AddLineS("patcher.log", msg.c_str());

                if (IS_NET_SUCCESS(s_patchResult))
                    s_patchResult = result;
            break;
        }
        return;
    }

    writer->Close();
    delete writer;
    AtomicAdd(&s_numFiles, -1);

    if(!s_numFiles) {
        s_downloadComplete = true;
        s_updated = true;
    }
}
예제 #3
0
// Add child node
void _AddNodeCallback(ENetError result, void* param) {
    pyVaultNode::pyVaultNodeOperationCallback* cb = (pyVaultNode::pyVaultNodeOperationCallback*)param;
    if (IS_NET_SUCCESS(result))
        cb->VaultOperationComplete(hsOK);
    else
        cb->VaultOperationComplete(hsFail);
}
예제 #4
0
//============================================================================
static void ManifestCallback (
    ENetError                       result,
    void *                          param,
    const wchar_t                     group[],
    const NetCliFileManifestEntry   manifest[],
    unsigned                        entryCount
) {
    if(IS_NET_ERROR(result)) {
        switch (result) {
            case kNetErrTimeout:
                NetCliFileManifestRequest(ManifestCallback, nil, s_manifest);
            break;
            
            default:
                plString msg = plString::Format("Error getting patcher manifest: %S", NetErrorToString(result));
                plStatusLog::AddLineS("patcher.log", msg.c_str());

                if (IS_NET_SUCCESS(s_patchResult))
                    s_patchResult = result;
            break;
        }
        return;
    }

#ifndef PLASMA_EXTERNAL_RELEASE
    if (entryCount == 0)  { // dataserver does not contain a patcher
        s_downloadComplete = true;
        return;
    }
#endif

    char ansi[MAX_PATH];

    // MD5 check current patcher against value in manifest
    ASSERT(entryCount == 1);
    wchar_t curPatcherFile[MAX_PATH];
    PathGetProgramName(curPatcherFile, arrsize(curPatcherFile));
    StrToAnsi(ansi, curPatcherFile, arrsize(ansi));
    if (!MD5Check(ansi, manifest[0].md5)) {
//      MessageBox(GetTopWindow(nil), "MD5 failed", "Msg", MB_OK);
        SelfPatcherStream::totalBytes += manifest[0].zipSize;

        AtomicAdd(&s_numFiles, 1);
        SetText("Downloading new patcher...");

        StrToAnsi(ansi, s_newPatcherFile, arrsize(ansi));
        SelfPatcherStream * stream = new SelfPatcherStream;
        if (!stream->Open(ansi, "wb"))
            ErrorAssert(__LINE__, __FILE__, "Failed to create file: %s, errno: %u", ansi, errno);

        NetCliFileDownloadRequest(manifest[0].downloadName, stream, DownloadCallback, nil);
    }
    else {
        s_downloadComplete = true;
    }
}
예제 #5
0
static void IFileManifestDownloadCB(ENetError result, void* param, const wchar_t group[], const NetCliFileManifestEntry manifest[], unsigned entryCount)
{
    pfPatcherWorker* patcher = static_cast<pfPatcherWorker*>(param);

    if (IS_NET_SUCCESS(result))
        IHandleManifestDownload(patcher, group, manifest, entryCount);
    else {
        PatcherLogRed("\tDownload Failed: Manifest '%S'", group);
        patcher->EndPatch(result, plString::FromWchar(group));
    }
}
예제 #6
0
static void ManifestDownloaded(
    ENetError                     result, 
    void*                         param, 
    const wchar_t                 group[], 
    const NetCliFileManifestEntry manifest[], 
    uint32_t                        entryCount)
{
    plResPatcher* patcher = (plResPatcher*)param;
    char* name = hsWStringToString(group);
    if (IS_NET_SUCCESS(result))
        PatcherLog(kInfo, "    Downloaded manifest %s", name);
    else {
        PatcherLog(kError, "    Failed to download manifest %s", name);
        patcher->Finish(false);
        delete[] name;
        return;
    }

    for (uint32_t i = 0; i < entryCount; ++i)
    {
        const NetCliFileManifestEntry mfs = manifest[i];
        char* fileName = hsWStringToString(mfs.clientName);

        // See if the files are the same
        // 1. Check file size before we do time consuming md5 operations
        // 2. Do wasteful md5. We should consider implementing a CRC instead.
        if (plFileUtils::GetFileSize(fileName) == mfs.fileSize)
        {
            plMD5Checksum cliMD5(fileName);
            plMD5Checksum srvMD5;
            char* eapSucksString = hsWStringToString(mfs.md5);
            srvMD5.SetFromHexString(eapSucksString);
            delete[] eapSucksString;

            if (cliMD5 == srvMD5)
            {
                delete[] fileName;
                continue;
            } else
                PatcherLog(kInfo, "    Enqueueing %s: MD5 Checksums Differ", fileName);
        } else
            PatcherLog(kInfo, "    Enqueueing %s: File Sizes Differ", fileName);

        // If we're still here, then we need to update the file.
        float size = mfs.zipSize ? (float)mfs.zipSize : (float)mfs.fileSize;
        patcher->GetProgress()->SetLength(size + patcher->GetProgress()->GetMax());
        patcher->RequestFile(mfs.downloadName, mfs.clientName);
    }

    patcher->IssueRequest();
    delete[] name;
}
예제 #7
0
//============================================================================
static void NetErrorHandler (ENetProtocol protocol, ENetError error) {
    plString msg = plString::Format("NetErr: %S", NetErrorToString(error));
    plStatusLog::AddLineS("patcher.log", msg.c_str());

    if (IS_NET_SUCCESS(s_patchResult))
        s_patchResult = error;
    s_downloadComplete = true;

    switch(error) {
        case kNetErrServerBusy:
            MessageBox(0, "Due to the high demand, the server is currently busy. Please try again later, or for alternative download options visit: http://www.mystonline.com/play/", "UruLauncher", MB_OK);
            s_patchResult = kNetErrServerBusy;
            s_downloadComplete = true;
        break;
    }
}
예제 #8
0
static void IAuthThingDownloadCB(ENetError result, void* param, const plFileName& filename, hsStream* writer)
{
    pfPatcherWorker* patcher = static_cast<pfPatcherWorker*>(param);

    if (IS_NET_SUCCESS(result)) {
        PatcherLogGreen("\tDownloaded Legacy File '%s'", filename.AsString().c_str());
        patcher->IssueRequest();

        // Now, we pass our RAM-backed file to the game code handlers. In the main client,
        // this will trickle down and add a new friend to plStreamSource. This should never
        // happen in any other app...
        writer->Rewind();
        patcher->WhitelistFile(filename, true, writer);
    } else {
        PatcherLogRed("\tDownloaded Failed: File '%s'", filename.AsString().c_str());
        patcher->EndPatch(result, filename.AsString());
    }
}
예제 #9
0
void pfPatcherWorker::EndPatch(ENetError result, const plString& msg)
{
    // Guard against multiple calls
    if (fStarted) {
        // Send end status
        if (fOnComplete)
            fOnComplete(result, msg);

        // yay log hax
        if (IS_NET_SUCCESS(result))
            PatcherLogWhite("--- Patch Complete ---");
        else {
            PatcherLogRed("\tNetwork Error: %S", NetErrorToString(result));
            PatcherLogWhite("--- Patch Killed by Error ---");
        }
    }

    fStarted = false;
    fFileSignal.Signal();
}
예제 #10
0
static void IPreloaderManifestDownloadCB(ENetError result, void* param, const wchar_t group[], const NetCliFileManifestEntry manifest[], unsigned entryCount)
{
    pfPatcherWorker* patcher = static_cast<pfPatcherWorker*>(param);

    if (IS_NET_SUCCESS(result))
        IHandleManifestDownload(patcher, group, manifest, entryCount);
    else {
        PatcherLogYellow("\tWARNING: *** Falling back to AuthSrv file lists to get game code ***");

        // so, we need to ask the AuthSrv about our game code
        {
            hsTempMutexLock lock(patcher->fRequestMut);
            patcher->fRequests.push_back(pfPatcherWorker::Request(plString::Null, pfPatcherWorker::Request::kPythonList));
            patcher->fRequests.push_back(pfPatcherWorker::Request(plString::Null, pfPatcherWorker::Request::kSdlList));
        }

        // continue pumping requests
        patcher->IssueRequest();
    }
}
예제 #11
0
static void IFileThingDownloadCB(ENetError result, void* param, const plFileName& filename, hsStream* writer)
{
    pfPatcherWorker* patcher = static_cast<pfPatcherWorker*>(param);
    pfPatcherStream* stream = static_cast<pfPatcherStream*>(writer);
    stream->Close();

    if (IS_NET_SUCCESS(result)) {
        PatcherLogGreen("\tDownloaded File '%s'", stream->GetFileName().AsString().c_str());
        patcher->WhitelistFile(stream->GetFileName(), true);
        if (patcher->fSelfPatch && stream->IsSelfPatch())
            patcher->fSelfPatch(stream->GetFileName());
        if (patcher->fRedistUpdateDownloaded && stream->IsRedistUpdate())
            patcher->fRedistUpdateDownloaded(stream->GetFileName());
        patcher->IssueRequest();
    } else {
        PatcherLogRed("\tDownloaded Failed: File '%s'", stream->GetFileName().AsString().c_str());
        stream->Unlink();
        patcher->EndPatch(result, filename.AsString());
    }

    delete stream;
}
예제 #12
0
//============================================================================
static bool SelfPatcherProc (bool * abort, plLauncherInfo *info) {

    bool patched = false;
    s_downloadComplete = false;
    s_patchResult = kNetSuccess;

    NetClientInitialize();
    NetClientSetErrorHandler(NetErrorHandler);

    const char** addrs;
    unsigned count;

    count = GetGateKeeperSrvHostnames(&addrs);

    // Start connecting to the server
    NetCliGateKeeperStartConnect(addrs, count);

    // request a file server ip address
    NetCliGateKeeperFileSrvIpAddressRequest(FileSrvIpAddressCallback, nil, true);

    while(!s_downloadComplete && !*abort) {
        NetClientUpdate();
        AsyncSleep(10);
    }   

    NetCliFileDisconnect();
    NetClientUpdate();

    // Shutdown the client/server networking subsystem
    NetClientDestroy();

    if (s_downloadComplete && !*abort && s_updated && IS_NET_SUCCESS(s_patchResult)) {

        // launch new patcher
        STARTUPINFOW        si;
        PROCESS_INFORMATION pi;
        memset(&si, 0, sizeof(si));
        memset(&pi, 0, sizeof(pi));
        si.cb = sizeof(si);

        wchar_t cmdline[MAX_PATH];
        StrPrintf(cmdline, arrsize(cmdline), L"%s %s", s_newPatcherFile, info->cmdLine);

        // we have only successfully patched if we actually launch the new version of the patcher
        patched = CreateProcessW(
            NULL,
            cmdline,
            NULL,
            NULL,
            FALSE, 
            DETACHED_PROCESS,
            NULL,
            NULL,
            &si,
            &pi
        );
        SetReturnCode(pi.dwProcessId);
        CloseHandle( pi.hThread );
        CloseHandle( pi.hProcess );
        ASSERT(patched);
    }

    return patched;
}
예제 #13
0
BOOL CALLBACK UruLoginDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    static LoginDialogParam* pLoginParam;
    static bool showAuthFailed = false;

    switch( uMsg )
    {
        case WM_INITDIALOG:
        {
            s_loginDlgRunning = true;
            _beginthread(StatusCallback, 0, hwndDlg);
            pLoginParam = (LoginDialogParam*)lParam;

            SetWindowText(hwndDlg, "Login");
            SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(gHInst, MAKEINTRESOURCE(IDI_ICON_DIRT)));

            EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);

            SetDlgItemText(hwndDlg, IDC_URULOGIN_USERNAME, pLoginParam->username);
            CheckDlgButton(hwndDlg, IDC_URULOGIN_REMEMBERPASS, pLoginParam->remember ? BST_CHECKED : BST_UNCHECKED);
            if (pLoginParam->remember)
                SetDlgItemText(hwndDlg, IDC_URULOGIN_PASSWORD, FAKE_PASS_STRING);

            SetFocus(GetDlgItem(hwndDlg, pLoginParam->focus));

            if (IS_NET_ERROR(pLoginParam->authError))
            {
                showAuthFailed = true;
            }

            SendMessage(GetDlgItem(hwndDlg, IDC_PRODUCTSTRING), WM_SETTEXT, 0,
                        (LPARAM)plProduct::ProductString().c_str());

            for (int i = 0; i < plLocalization::GetNumLocales(); i++)
            {
                SendMessage(GetDlgItem(hwndDlg, IDC_LANGUAGE), CB_ADDSTRING, 0, (LPARAM)plLocalization::GetLanguageName((plLocalization::Language)i));
            }
            SendMessage(GetDlgItem(hwndDlg, IDC_LANGUAGE), CB_SETCURSEL, (WPARAM)plLocalization::GetLanguage(), 0);

            SetTimer(hwndDlg, AUTH_LOGIN_TIMER, 10, NULL);
            return FALSE;
        }

        case WM_USER_SETSTATUSMSG:
             SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_TEXT), WM_SETTEXT, 0, lParam);
             return TRUE;

        case WM_DESTROY:
        {
            s_loginDlgRunning = false;
            s_statusEvent.Wait();
            KillTimer(hwndDlg, AUTH_LOGIN_TIMER);
            return TRUE;
        }
    
        case WM_NCHITTEST:
        {
            SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, (LONG_PTR)HTCAPTION);
            return TRUE;
        }
    
        case WM_PAINT:
        {
            if (showAuthFailed)
            {
                SetTimer(hwndDlg, AUTH_FAILED_TIMER, 10, NULL);
                showAuthFailed = false;
            }
            return FALSE;
        }
    
        case WM_COMMAND:
        {
            if (HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL))
            {
                bool ok = (LOWORD(wParam) == IDOK);
                if (ok)
                {
                    char password[kMaxPasswordLength];

                    GetDlgItemText(hwndDlg, IDC_URULOGIN_USERNAME, pLoginParam->username, kMaxAccountNameLength);
                    GetDlgItemText(hwndDlg, IDC_URULOGIN_PASSWORD, password, kMaxPasswordLength);
                    pLoginParam->remember = (IsDlgButtonChecked(hwndDlg, IDC_URULOGIN_REMEMBERPASS) == BST_CHECKED);

                    plLocalization::Language new_language = (plLocalization::Language)SendMessage(GetDlgItem(hwndDlg, IDC_LANGUAGE), CB_GETCURSEL, 0, 0L);
                    plLocalization::SetLanguage(new_language);

                    SaveUserPass (pLoginParam, password);

                    // Welcome to HACKland, population: Branan
                    // The code to write general.ini really doesn't belong here, but it works... for now.
                    // When general.ini gets expanded, this will need to find a proper home somewhere.
                    {
                        plFileName gipath = plFileName::Join(plFileSystem::GetInitPath(), "general.ini");
                        plString ini_str = plFormat("App.SetLanguage {}\n", plLocalization::GetLanguageName(new_language));
                        hsStream* gini = plEncryptedStream::OpenEncryptedFileWrite(gipath);
                        gini->WriteString(ini_str);
                        gini->Close();
                        delete gini;
                    }

                    memset(&pLoginParam->authError, 0, sizeof(pLoginParam->authError));
                    bool cancelled = AuthenticateNetClientComm(&pLoginParam->authError, hwndDlg);

                    if (IS_NET_SUCCESS(pLoginParam->authError) && !cancelled)
                        EndDialog(hwndDlg, ok);
                    else {
                        if (!cancelled)
                            ::DialogBoxParam(gHInst, MAKEINTRESOURCE( IDD_AUTHFAILED ), hwndDlg, AuthFailedDialogProc, (LPARAM)pLoginParam);
                        else
                        {
                            NetCommDisconnect();
                        }
                    }
                }
                else
                    EndDialog(hwndDlg, ok);

                return TRUE;
            }
            else if (HIWORD(wParam) == EN_CHANGE && LOWORD(wParam) == IDC_URULOGIN_USERNAME)
            {
                char username[kMaxAccountNameLength];
                GetDlgItemText(hwndDlg, IDC_URULOGIN_USERNAME, username, kMaxAccountNameLength);

                if (StrLen(username) == 0)
                    EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
                else
                    EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE);

                return TRUE;
            }
            else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_URULOGIN_NEWACCTLINK)
            {
                plString signupurl = GetServerSignupUrl();
                ShellExecuteW(NULL, L"open", signupurl.ToWchar(), NULL, NULL, SW_SHOWNORMAL);

                return TRUE;
            }
            break;
        }
    
        case WM_TIMER:
        {
            switch(wParam)
            {
            case AUTH_FAILED_TIMER:
                KillTimer(hwndDlg, AUTH_FAILED_TIMER);
                ::DialogBoxParam(gHInst, MAKEINTRESOURCE( IDD_AUTHFAILED ), hwndDlg, AuthFailedDialogProc, (LPARAM)pLoginParam);
                return TRUE;

            case AUTH_LOGIN_TIMER:
                NetCommUpdate();
                return TRUE;
            }
            return FALSE;
        }
    }
    return FALSE;
}