//---------------------------------------------------------------------------------- // StartDownload: Start the thread that will download the file. //---------------------------------------------------------------------------------- void PatchDetailsCtrl::StartDownload(void) { CustomInfo* pCustInfo = GetCustomInfo(); if (m_sURL != "") { CreateDirectoryRecursive(pCustInfo->GetPatchFolder()); m_sInfoFile = pCustInfo->GetPatchFolder(); m_sInfoFile.append("PatchDetails.txt"); // Remove it (make sure we don't accidentaly use some old leftover). DeleteFile(m_sInfoFile.c_str()); if (IsFtpAddress(m_sURL)) { m_pFtpGetFile = new FTPGetOp(m_sURL, true); m_pFtpGetFile->SetLocalPath(m_sInfoFile); m_pFtpGetFile->SetCompletion(new PatchDetailsCompletion(FtpDownloadDoneCallback)); m_pFtpGetFile->RunAsync(static_cast<ULONG>(OP_TIMEOUT_INFINITE)); } else { m_pHttpGetFile = new HTTPGetOp(m_sURL); m_pHttpGetFile->SetLocalPath(m_sInfoFile); m_pHttpGetFile->SetCompletion(new PatchDetailsCompletion(HttpDownloadDoneCallback)); m_pHttpGetFile->RunAsync(static_cast<ULONG>(OP_TIMEOUT_INFINITE)); } m_bDownloadStarted = true; } }
//---------------------------------------------------------------------------------- // SendReport: Send report on what happened with this patch. // (for automatic pruning of poor patch locations) //---------------------------------------------------------------------------------- void DownloadCtrl::SendReport(void) { CustomInfo* pCustInfo = GetCustomInfo(); CPatchData* pPatch = pCustInfo->GetSelectedPatch(); PatchCore* pCore = GetMainControl()->GetPatchCore(); ServerContext* pGamePatchServers = pCore->GetGamePatchServers(); if (pGamePatchServers == NULL) return; AsyncSocketPtr aSocketP = new AsyncSocket(AsyncSocket::UDP); aSocketP->Bind(0); AddrList GamePatchServerAddrList; pGamePatchServers->CopyAddresses(GamePatchServerAddrList); for (AddrList::iterator anItr = GamePatchServerAddrList.begin(); anItr != GamePatchServerAddrList.end(); ++anItr) { ReportPatchStatusOpPtr pOp = new ReportPatchStatusOp(*anItr); pOp->SetProductName(pCustInfo->GetProductName()); pOp->SetConfigName(pCustInfo->GetExtraConfig()); pOp->SetFromVersion(pPatch->GetFromVersion()); pOp->SetToVersion(pCustInfo->GetNewVersion()); pOp->SetNetAddress(pPatch->GetPatchUrl()); pOp->SetUDPSocket(aSocketP); if (m_bAborted) pOp->SetPatchStatus(1); // cancel type else if (m_bPatchIsValid && m_bPatchDownloadSucceeded) pOp->SetPatchStatus(0); // success type else pOp->SetPatchStatus(2); // failed type pOp->RunBlock(0); } }
//---------------------------------------------------------------------------------- // Show: Make this dialog visible (or invisible), and start (or stop) any threads // that are needed. //---------------------------------------------------------------------------------- void PatchDetailsCtrl::Show(bool bShow) { SetVisible(bShow); if (bShow) { CustomInfo* pCI = GetCustomInfo(); // Check to see if we have already downloaded these patch details. if (m_bDownloadSucceeded && (m_sURL == pCI->GetPatchDescriptionUrl())) { // We already have the file, re-display it. LoadInfoTextFromFile(m_sInfoFile); // Make sure the Next button is the default button. m_pNextButton->RequestFocus(); return; } // Some of the text changes dynamically based on patch selection, update it. ResourceManager* pResMgr = GetCustomInfo()->GetResourceManager(); // Informational (Main) text. GUIString sInfo = pResMgr->BuildInfoString(PatchDetails_Info1_String_Id); m_pInfoText->Clear(); m_pInfoText->AddFormatedText(sInfo); m_pInfoText->SetVertOffset(0); // Scroll to the top. m_pInfoText->Invalidate(); // Reset the download variables. m_bDownloadStarted = false; m_bDownloadComplete = false; m_bDownloadSucceeded = false; m_bAborted = false; m_sURL = pCI->GetPatchDescriptionUrl(); EnableControls(); // Start the download itself. m_pBackButton->RequestFocus(); StartDownload(); } else { // If the download is still in progress, kill it. KillThreads(); } }
//---------------------------------------------------------------------------------- // TimerEvent: Handle a timer event. //---------------------------------------------------------------------------------- bool DownloadCtrl::TimerEvent(int tDelta) { Container::TimerEvent(tDelta); m_tDownloading += tDelta; if (! m_bShownTimeoutWarning) { CustomInfo* pCustInfo = GetCustomInfo(); ResourceManager* pResMgr = pCustInfo->GetResourceManager(); if (m_tDownloading > pCustInfo->GetPatchTimeout()) { m_bShownTimeoutWarning = true; MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_NoData_String), pResMgr->GetFinishedString(Global_Warning_String), MD_OK); } } return true; }
//---------------------------------------------------------------------------------- // CreateMainScreen: Create the main screen. //---------------------------------------------------------------------------------- void CreateMainScreen(void) { int nWidth = g_pWindow->GetRoot()->Width(); int nHeight = g_pWindow->GetRoot()->Height(); g_pMainScreen = new Container; g_pMainScreen->SetSize(nWidth, nHeight); WONUpdateCtrlPtr pCtrl = new WONUpdateCtrl(); ResourceConfigTablePtr aTable = pCtrl->InitScreens(); g_pMainScreen->AddChildLayout(pCtrl, CLI_SameSize, g_pMainScreen); pCtrl->SetFinishedCallback(Finished); pCtrl->SetTitleChangedCallback(TitleChanged); g_pAboutDlg = pCtrl->GetAboutCtrl(); CustomInfo* pCI = GetCustomInfo(); g_pAboutDlg->SetVersion(pCI->GetSierraUpVersion()); g_pMainScreen->AddChild(pCtrl); }
//---------------------------------------------------------------------------------- // Show: Make this dialog visible (or invisible), and start (or stop) any threads // that are needed. //---------------------------------------------------------------------------------- void OptionalPatchCtrl::Show(bool bShow) { SetVisible(bShow); if (bShow) { // Some of the text changes dynamically based on patch selection, update it. ResourceManager* pResMgr = GetCustomInfo()->GetResourceManager(); // Informational (Main) text. GUIString sInfo = pResMgr->BuildInfoString(OptionalPatch_Info1_String_Id); m_pInfoText->Clear(); m_pInfoText->AddFormatedText(sInfo); m_pInfoText->SetVertOffset(0); // Scroll to the top. // Make sure the Next button is the default button. m_pNextButton->RequestFocus(); CustomInfo* pCI = GetCustomInfo(); m_pPatchDetailsButton->Enable(pCI->GetPatchDescriptionUrl() != ""); } // No threads used in this dialog. }
//---------------------------------------------------------------------------------- // FtpDownloadComplete: The ftp transfer has completed for the patch. Check the // status to see if it worked. //---------------------------------------------------------------------------------- void PatchDetailsCtrl::FtpDownloadComplete(FTPGetOp* pGetOp) { CustomInfo* pCustInfo = GetCustomInfo(); ResourceManager* pResMgr = pCustInfo->GetResourceManager(); WONStatus aStatus = pGetOp->GetStatus(); if (aStatus == WS_Success) { if (! m_bAborted) LoadInfoTextFromFile(m_sInfoFile); m_bDownloadSucceeded = true; } else { if (! m_bAborted) // If the user aborted don't pop up an error telling them they aborted... { // Clear the file name (so no one tries to use it), but don't deleted it, // we can resume the download later. /// pCustInfo->SetPatchFile(""); GUIString sTitle = pResMgr->GetFinishedString(Download_DownloadError_String); GUIString sMsg; switch (aStatus) { case WS_FTP_StatusError: switch (pGetOp->GetFTPStatus()) { case 500: MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_InvalidFtpUser_String), sTitle, MD_OK); break; case 530: MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_InvalidFtpPassword_String), sTitle, MD_OK); break; case 550: MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_InvalidFtpFile_String), sTitle, MD_OK); break; default: sMsg = pResMgr->GetFinishedString(Download_FtpError_String); ReplaceSubInt(sMsg, "%ERROR%", pGetOp->GetFTPStatus()); MessageBox(GetWindow(), sMsg, sTitle, MD_OK); } //lint !e788 break; case WS_FTP_InvalidResponse: MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_InvalidFtpResp_String), sTitle, MD_OK); break; case WS_FTP_InvalidPasvResponse: MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_InvalidFtpPasvResp_String), sTitle, MD_OK); break; case WS_WSAECONNREFUSED: MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_ConnectionRefused_String), sTitle, MD_OK); break; default: sMsg = pResMgr->GetFinishedString(Download_UnknownFtpError_String); ReplaceSubString(sMsg, "%ERROR%", WONStatusToString(aStatus)); MessageBox(GetWindow(), sMsg, sTitle, MD_OK); } //lint !e788 } } m_bDownloadComplete = true; EnableControls(); }
//---------------------------------------------------------------------------------- // StartDownloads: Start the threads that will download the files. //---------------------------------------------------------------------------------- void DownloadCtrl::StartDownloads(void) { CustomInfo* pCustInfo = GetCustomInfo(); CPatchData* pPatch = pCustInfo->GetSelectedPatch(); if (pPatch) { #ifdef _DEBUG if (GetKeyState(VK_MENU) & GetKeyState(VK_CONTROL) & GetKeyState(VK_SHIFT) & 0x8000) pPatch->DebugBox(GetWindow()); #endif GUIString sPatchFile = pPatch->GetPatchUrl(); int nPos = sPatchFile.rFind('/'); if (nPos == -1) nPos = sPatchFile.rFind('\\'); if (nPos != -1) sPatchFile.erase(0, nPos + 1); else sPatchFile = TEXT("Update.exe"); std::string aHostGraphic = pPatch->GetHostBmp(); int aPos = aHostGraphic.find_last_of('.'); std::string aHostGraphicExtension; if(aPos != std::string::npos && aHostGraphic.length() > aPos + 1) aHostGraphicExtension = aHostGraphic.substr(aPos+1); else aHostGraphicExtension = "bmp"; m_sHostBitmapFile = GenerateTempFileName("FS", aHostGraphicExtension); CreateDirectoryRecursive(pCustInfo->GetPatchFolder()); GUIString sPatchExe = pCustInfo->GetPatchFolder(); sPatchExe.append(sPatchFile); pCustInfo->SetPatchFile(sPatchExe); mStartTime = time(NULL); mNumberCallbacks = 0; if (IsFtpAddress(pPatch->GetHostBmp())) { // Don't attempt to handle resumed downloads of bitmaps - not worth it. DeleteFile(std::string(m_sHostBitmapFile).c_str()); m_pFtpGetBitmap = new FTPGetOp(pPatch->GetHostBmp(), true); m_pFtpGetBitmap->SetLocalPath(m_sHostBitmapFile); m_pFtpGetBitmap->SetCompletion(new DownloadCompletion(FtpBitmapDoneCallback)); m_pFtpGetBitmap->RunAsync(static_cast<ULONG>(OP_TIMEOUT_INFINITE)); } else { m_pHttpGetBitmap = new HTTPGetOp(pPatch->GetHostBmp()); m_pHttpGetBitmap->SetLocalPath(m_sHostBitmapFile); m_pHttpGetBitmap->SetCompletion(new DownloadCompletion(HttpBitmapDoneCallback)); m_pHttpGetBitmap->RunAsync(static_cast<ULONG>(OP_TIMEOUT_INFINITE)); } // m_tDownloadStarted = GetTickCount(); m_nPrevDownloadedFtpBytes = 0; if (IsFtpAddress(pPatch->GetPatchUrl())) { // If the previous patch profile does not match this patch profile, nuke the file. if (! pCustInfo->MatchFtpDownloadTag(sPatchExe, pCustInfo->GetNewVersion(), pPatch->GetPatchSize(), pPatch->GetChecksum())) DeleteFile(std::string(sPatchExe).c_str()); else m_nPrevDownloadedFtpBytes = GetFileSize(sPatchExe); // Tag the patch's profile (so we can 'resume or not as appropriate later). pCustInfo->TagFtpDownload(sPatchExe, pCustInfo->GetNewVersion(), pPatch->GetPatchSize(), pPatch->GetChecksum()); m_pFtpGetPatch = new FTPGetOp(pPatch->GetPatchUrl(), true); m_pFtpGetPatch->SetDoResume(true); // Allow resuming of downloads. m_pFtpGetPatch->SetLocalPath(sPatchExe); m_pFtpGetPatch->SetRecvChunkCompletion(new DownloadCompletion(PatchProgressCallback), CHUNCK_SIZE); m_pFtpGetPatch->SetCompletion(new DownloadCompletion(FtpPatchDoneCallback)); m_pFtpGetPatch->RunAsync(static_cast<ULONG>(OP_TIMEOUT_INFINITE)); } else { m_pHttpGetPatch = new HTTPGetOp(pPatch->GetPatchUrl()); m_pHttpGetPatch->SetLocalPath(sPatchExe); m_pHttpGetPatch->SetRecvChunkCompletion(new DownloadCompletion(PatchProgressCallback), CHUNCK_SIZE); m_pHttpGetPatch->SetCompletion(new DownloadCompletion(HttpPatchDoneCallback)); m_pHttpGetPatch->RunAsync(static_cast<ULONG>(OP_TIMEOUT_INFINITE)); } m_bDownloadStarted = true; } }
//---------------------------------------------------------------------------------- // FtpPatchDownloadComplete: The ftp transfer has completed for the patch. Check // the status to see if it worked. //---------------------------------------------------------------------------------- void DownloadCtrl::FtpPatchDownloadComplete(FTPGetOp* pGetOp) { CustomInfo* pCustInfo = GetCustomInfo(); ResourceManager* pResMgr = pCustInfo->GetResourceManager(); // Turn off the timer. RequestTimer(false); WONStatus aStatus = pGetOp->GetStatus(); CPatchData* pPatch = pCustInfo->GetSelectedPatch(); if (aStatus == WS_Success) { if (pPatch) pCustInfo->SaveDefaultSelection(pPatch->GetHostName()); m_bPatchDownloadSucceeded = true; if (! m_bAborted) { // Set the progress bar to 100%. int nLower, nUpper; m_pProgressBar->GetRange(nLower, nUpper); UpdateProgressBar(nUpper, nUpper); ValidatePatch(); } } else { if (! m_bAborted) // If the user aborted don't pop up an error telling them they aborted... { // Clear the file name (so no one tries to use it), but don't deleted it, // we can resume the download later. pCustInfo->SetPatchFile(""); GUIString sTitle = pResMgr->GetFinishedString(Download_DownloadError_String); GUIString sMsg; if (pPatch) pPatch->SetDownloadFailures(pPatch->GetDownloadFailures() + 1); switch (aStatus) { case WS_FTP_StatusError: switch (pGetOp->GetFTPStatus()) { case 500: NamePasswordDialog(pGetOp, sTitle, pResMgr->GetFinishedString(Download_InvalidFtpUser_String)); return; case 530: NamePasswordDialog(pGetOp, sTitle, pResMgr->GetFinishedString(Download_InvalidFtpPassword_String)); return; case 550: MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_InvalidFtpFile_String), sTitle, MD_OK); break; default: sMsg = pResMgr->GetFinishedString(Download_FtpError_String); ReplaceSubInt(sMsg, "%ERROR%", pGetOp->GetFTPStatus()); MessageBox(GetWindow(), sMsg, sTitle, MD_OK); } //lint !e788 break; case WS_FTP_InvalidResponse: MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_InvalidFtpResp_String), sTitle, MD_OK); break; case WS_FTP_InvalidPasvResponse: MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_InvalidFtpPasvResp_String), sTitle, MD_OK); break; case WS_WSAECONNREFUSED: MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_ConnectionRefused_String), sTitle, MD_OK); break; default: sMsg = pResMgr->GetFinishedString(Download_UnknownFtpError_String); ReplaceSubString(sMsg, "%ERROR%", WONStatusToString(aStatus)); MessageBox(GetWindow(), sMsg, sTitle, MD_OK); } //lint !e788 FireBackButton(); } } m_bPatchDownloadComplete = true; SendReport(); EnableControls(); }
//---------------------------------------------------------------------------------- // Show: Make this dialog visible (or invisible), and start (or stop) any threads // that are needed. //---------------------------------------------------------------------------------- void DownloadCtrl::Show(bool bShow) { SetVisible(bShow); if (bShow) { m_bPatchIsValid = false; m_bShownTimeoutWarning = false; // m_nReturnResult = SUR_UNKNOWN; GetMainControl()->SetReturnResult(SUR_UNKNOWN); CustomInfo* pCustInfo = GetCustomInfo(); ResourceManager* pResMgr = pCustInfo->GetResourceManager(); // Some of the text changes dynamically based on patch selection, update it. // Informational (Main) text. GUIString sInfo = pResMgr->BuildInfoString(Download_Info1_String_Id); m_pInfoText->Clear(); m_pInfoText->AddFormatedText(sInfo); m_pInfoText->SetVertOffset(0); // Scroll to the top. // Visit Host prompt. m_pVisitHostLabel->SetText(pResMgr->GetFinishedString(Download_Host_String)); m_pVisitHostLabel->SetDesiredSize(); // Visit Host button. m_pVisitHostButton->SetText(pResMgr->GetFinishedString(Download_VisitHost_String)); ResetProgressBar(); // Make sure the Next button is the default button. m_pNextButton->RequestFocus(); // Start the download clock. m_tDownloading = 0; m_bDownloadStarted = false; m_bPatchDownloadComplete = false; m_bPatchDownloadSucceeded = false; m_bBitmapDownloadComplete = false; m_bBitmapDownloadSucceeded = false; m_bAborted = false; RequestTimer(true); m_pVisitHostButton->SetVisible(true); m_pVisitHostImageButton->SetVisible(false); EnableControls(); // Check to see if we are using a previously downloaded patch. if (pCustInfo->GetPatchFile() != "") { m_bPatchDownloadComplete = true; int nLower, nUpper; m_pProgressBar->GetRange(nLower, nUpper); UpdateProgressBar(nUpper, nUpper); ValidatePatch(); // Check it (we are paranoid). EnableControls(); } else StartDownloads(); // Start the download itself. } else { // Turn off the timer. RequestTimer(false); // If the download is still in progress, kill it. KillThreads(); } }
//---------------------------------------------------------------------------------- // UpdatePatchList: Update the list of patches (and results). //---------------------------------------------------------------------------------- void SelectHostCtrl::UpdatePatchList(void) { CustomInfo* pCustInfo = GetCustomInfo(); ResourceManager* pResMgr = pCustInfo->GetResourceManager(); GUIString sError; int nManualPatches = 0; int nAutoPatches = 0; // Clear the list box of old refuse. m_pHostList->Clear(); m_pHostList->BeginMultiChange(); GUIString sDefault = pCustInfo->LoadDefaultSelection(); sDefault.toLowerCase(); CPatchDataList* pPatches = pCustInfo->GetPatchList(); // Go through the list and decide if we have to mark manual downloads. CPatchDataList::iterator Itr = pPatches->begin(); while (Itr != pPatches->end()) { CPatchData* pData = *Itr; if (pData) { if (pData->GetMustVisitHost()) nManualPatches++; else nAutoPatches++; } ++Itr; } m_bMixedPatches = nManualPatches != 0 && nAutoPatches != 0; // Now go through the list and add all of the items to the list box. Itr = pPatches->begin(); int nIndex = 0; int nSelectIndex = -1; while (Itr != pPatches->end()) { CPatchData* pData = *Itr; //pData->MessageBox(GetWindow()); // Debugging Aide. if (pData) { // Start with the Patch Name (we will display this). std::string sLine = pData->GetPatchName(); // Add the Manual flag (if needed). if (pData->GetMustVisitHost() && m_bMixedPatches) sLine += " *"; // Now add the results of previous download atempts. int nFailures = pData->GetDownloadFailures(); int nAborts = pData->GetDownloadAborts(); if (nFailures) { sError = pResMgr->GetFinishedString(Global_DownloadFailures_String); ReplaceSubInt(sError, "%NUM_FAILURES%", nFailures); } else if (nAborts) { sError = pResMgr->GetFinishedString(Global_DownloadAborts_String); ReplaceSubInt(sError, "%NUM_ABORTS%", nAborts); } else sError = ""; PatchDataItem* pItem = static_cast<PatchDataItem*>(m_pHostList->InsertItem(new PatchDataItem)); m_pHostList->SetString(nIndex, 0, sLine); m_pHostList->SetString(nIndex, 1, sError); pItem->m_pPatchData = pData; // Check to see if this was the last 'successful download site', if so, select it. GUIString sHost = pData->GetHostName(); sHost.toLowerCase(); if (sDefault == sHost) nSelectIndex = nIndex; ++nIndex; } ++Itr; } // If no site was selected, choose one at random. if (nSelectIndex == -1 && nIndex > 0) { srand(GetTickCount()); nSelectIndex = rand() % nIndex; } // Actually make the selection. if (nSelectIndex != -1) m_pHostList->SetSelItem(nSelectIndex); m_pHostList->EndMultiChange(); // Changing the patch list can change the Info Text, so update it. UpdateInfoText(); EnableControls(); }