//----------------------------------------------------------------------------------
// LoadInfoTextFromFile: Load the info box from the downloaded file.
//----------------------------------------------------------------------------------
void PatchDetailsCtrl::LoadInfoTextFromFile(const std::string& sFile)
{
	FILE* pFile = fopen(sFile.c_str(), "rt+");
	if (pFile)
	{
		ResourceManager* pResMgr = GetCustomInfo()->GetResourceManager();

		const int MAX_INFO_FILE_SIZE = 100000;
		char sRawContents[MAX_INFO_FILE_SIZE] = "";
		memset(sRawContents, 0, MAX_INFO_FILE_SIZE);
		UINT nRead = static_cast<UINT>(fread(sRawContents, 1, sizeof(sRawContents) - 1, pFile));
		if (nRead == sizeof(sRawContents) - 1)
		{
			char sRead[32];
			wsprintf(sRead, "%d", nRead);
			GUIString sFormat = pResMgr->GetFinishedString(PatchDetails_FileTooBig_String);
			MessageBox(GetWindow(), sFormat, pResMgr->GetFinishedString(PatchDetails_FileTooBigTtl_String), MD_OK);
		}
		else
			sRawContents[nRead] = 0;

		if (nRead > 0)
		{
			m_pInfoText->Clear();
			m_pInfoText->AddFormatedText(sRawContents);
			m_pInfoText->SetVertOffset(0); // Scroll to the top.
			m_pInfoText->Invalidate();
		}

		fclose(pFile);
	}
}
//----------------------------------------------------------------------------------
// HandleAlreadyHaveUpdateButton: Process a click on the Already Have Update button.
//----------------------------------------------------------------------------------
bool SelectHostCtrl::HandleAlreadyHaveUpdateButton(ComponentEvent* pEvent)
{
	if (pEvent->mType != ComponentEvent_ButtonPressed)
		return false;

	ResourceManager* pResMgr = GetCustomInfo()->GetResourceManager();

	MSFileDialog Dlg;
	Dlg.SetFileMustExist(true);
	Dlg.AddFilter("*.exe", pResMgr->GetFinishedString(SelectHost_PatchFilter_String));
	Dlg.SetTitle(pResMgr->GetFinishedString(SelectHost_FileOpenDlgTitle_String));
	//Dlg.SetOkTitle("Open"); // No reason to change the default.
	Dlg.SetFileMustExist(true);
	Dlg.SetNoChangeDir(true);
	Dlg.SetInitialDir(GetCustomInfo()->GetPatchFolder());

	if (Dlg.DoDialog(GetWindow()))
	{
		m_sLocalPatch = Dlg.GetFile();
		if (GetMainControl()->GetPatchCore()->MatchLocalPatch(GetWindow(), m_sLocalPatch))
			FireNextButton();
		else
			m_sLocalPatch = "";
	}

	return true;
}
//----------------------------------------------------------------------------------
// 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;
}
//----------------------------------------------------------------------------------
// HandleVisitHostButton: Process a click on the Visit Host button.
//----------------------------------------------------------------------------------
bool DownloadCtrl::HandleVisitHostButton(ComponentEvent* pEvent)
{
	if (pEvent->mType != ComponentEvent_ButtonPressed)
		return false;

	ResourceManager* pResMgr = GetCustomInfo()->GetResourceManager();
	CPatchData* pPatch = GetCustomInfo()->GetSelectedPatch();

	// Launch the user's browser (send them to the host's site).
	if (pPatch)
	{
		if (pPatch->GetHostUrl().length())
			Browse(pPatch->GetHostUrl());
		else
			MessageBox(GetWindow(), pResMgr->GetFinishedString(Download_NoHostUrl_String), pResMgr->GetFinishedString(Global_Error_String), MD_OK);
	}

	return true;
}
Ejemplo n.º 5
0
//----------------------------------------------------------------------------------
// Create the Restartter appliaction by extracting it from the embedded resource.
//----------------------------------------------------------------------------------
bool ExtractRestarter(void)
{
    ResourceManager* pResMgr = GetCustomInfo()->GetResourceManager();

    DebugLog("Preparing to extract restarter\n");

    if (! ExtractResourceFile(IDF_RESTARTER_EXE, sRestartExe))
    {
        MessageBox(g_pWindow, pResMgr->GetFinishedString(Global_NoWriteRestarter_String), pResMgr->GetFinishedString(Global_Error_String), MB_OK);
        return false;
    }

    if (! ExtractResourceFile(IDF_PSAPI_DLL, sPsapiDll))
    {
        MessageBox(g_pWindow, pResMgr->GetFinishedString(Global_NoWritePsapi_String), pResMgr->GetFinishedString(Global_Error_String), MB_OK);
        return false;
    }

    return true;
}
//----------------------------------------------------------------------------------
// CanClose: Is it okay to close this window?  In other words, ask the user if they 
// really want to abort the download (if its still in progress).
//----------------------------------------------------------------------------------
bool DownloadCtrl::CanClose(void)
{
	if (m_bPatchDownloadComplete)
		return true;

	if (m_bValidatingPatch)
		return false;

	// The MessageBox does not block access to this call so make sure we don't trap 
	// ourselves.
	if (m_bShowingAbortDlg)
		return false;

	m_bShowingAbortDlg = true;

	ResourceManager* pResMgr = GetCustomInfo()->GetResourceManager();
	int nResult = MessageBox(GetWindow(), 
							 pResMgr->GetFinishedString(Download_AbandonDownload_String), 
							 pResMgr->GetFinishedString(Download_Confirm_String), MD_YESNO);

	m_bShowingAbortDlg = false;

	// Did the download complete while we were waiting?
	if (nResult == MDR_NO && m_bPatchDownloadSucceeded)
	{
		ValidatePatch();
		EnableControls();
	}

	if (nResult == MDR_YES)
	{
		// Tag the patch as canceled.
		CPatchData* pPatch = GetCustomInfo()->GetSelectedPatch();
		pPatch->SetDownloadAborts(pPatch->GetDownloadAborts() + 1);
	}

	return nResult == MDR_YES;
}
//----------------------------------------------------------------------------------
// UpdateInfoText: Update the contents of the info text box.
//----------------------------------------------------------------------------------
void SelectHostCtrl::UpdateInfoText(void)
{
	// Some of the text changes dynamically based on patch selection, update it.
	ResourceManager* pResMgr = GetCustomInfo()->GetResourceManager();

	GUIString sInfo = pResMgr->BuildInfoString(SelectHost_WaitInfo1_String_Id);

	if (GetCustomInfo()->GetPatchList()->size())
	{
		sInfo = pResMgr->BuildInfoString(SelectHost_Info1_String_Id);

		if (m_bMixedPatches)
		{
			sInfo.append("\n\n");
			sInfo.append(pResMgr->GetFinishedString(SelectHost_InfoManual_String));
		}
	}

	m_pInfoText->Clear();
	m_pInfoText->AddFormatedText(sInfo);
	m_pInfoText->SetVertOffset(0); // Scroll to the top.
}
//----------------------------------------------------------------------------------
// 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();
}
//----------------------------------------------------------------------------------
// 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();
}
Ejemplo n.º 10
0
//----------------------------------------------------------------------------------
// 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();
	}
}
Ejemplo n.º 11
0
//----------------------------------------------------------------------------------
// UpdateProgressBar: Update the status bar (and related text) to reflect the 
// supplied position of the download.
//----------------------------------------------------------------------------------
void DownloadCtrl::UpdateProgressBar(int nBytesRcvd, int nTotalSize)
{
	ResourceManager* pResMgr = GetCustomInfo()->GetResourceManager();

	if (nBytesRcvd > 0)
		RequestTimer(false);

	if (! m_bAborted)
	{
		// Update the Progress Bar.
		m_pProgressBar->SetRange(0, nTotalSize);
		m_pProgressBar->SetPosition(nBytesRcvd);

		// Time Remaining text.
		DWORD tElapsed = m_tDownloading;
		if (nTotalSize == 0)
			nTotalSize = nBytesRcvd; // Sanity Check (avoid a rare divide by zero).
		int nPercentDone = nBytesRcvd ? (int)((100.0 * (double)nBytesRcvd) / (double)nTotalSize): 0;

		int aTimeElapsed = time(NULL) - mStartTime;
		if(aTimeElapsed < 0)
			aTimeElapsed = 0;

		mNumberCallbacks++;

		int nBytesLeft = nTotalSize - nBytesRcvd;
		float fSecsPerByte = (float)aTimeElapsed / (float)nBytesRcvd;
		int nTimeLeft = (int)((float)nBytesLeft * fSecsPerByte);
		if(nTimeLeft < 1)
			nTimeLeft = 1;
			
		GUIString sOutput;
		if (nTotalSize == nBytesRcvd) // Are we done?
			sOutput = "";
		else if (mNumberCallbacks >= 3 && nTimeLeft && nTimeLeft < (60 * 60 * 24)) // Make sure its less than a day.
		{
			int nHours = nTimeLeft / (60 * 60);
			int nMinutes = (nTimeLeft / 60) % 60;
			int nSeconds = nTimeLeft % 60;

			if (nHours > 1)
				sOutput = pResMgr->GetFinishedString(Download_TimeHoursMinutes_String);
			else if (nHours)
				sOutput = pResMgr->GetFinishedString(Download_TimeHourMinutes_String);
			else if (nMinutes > 1)
				sOutput = pResMgr->GetFinishedString(Download_TimeMinutesSeconds_String);
			else if (nMinutes)
				sOutput = pResMgr->GetFinishedString(Download_TimeMinuteSeconds_String);
			else
				sOutput = pResMgr->GetFinishedString(Download_TimeSeconds_String);

			TCHAR sTime[32];
			wsprintf(sTime, "%d", nHours);
			GUIString sHours = sTime;
			wsprintf(sTime, "%d", nMinutes);
			GUIString sMinutes = sTime;
			wsprintf(sTime, "%d", nSeconds);
			GUIString sSeconds = sTime;

			ReplaceSubString(sOutput, sHoursKey, sHours);
			ReplaceSubString(sOutput, sMinutesKey, sMinutes);
			ReplaceSubString(sOutput, sSecondsKey, sSeconds);
		}
		else
			sOutput = pResMgr->GetFinishedString(Download_Estimating_String);

		m_pTimeLeftLabel->SetText(sOutput);
		m_pTimeLeftLabel->Invalidate();

		// Download Progress text.
		sOutput = pResMgr->GetFinishedString(Download_BytesTransferred_String);

		TCHAR sPercent[32];
		wsprintf(sPercent, "%d", nPercentDone);
		ReplaceSubString(sOutput, sPercentDoneKey, sPercent);
		ReplaceSubString(sOutput, sReceivedKey, NumToStrWithCommas(nBytesRcvd));
		ReplaceSubString(sOutput, sTotalSizeKey, NumToStrWithCommas(nTotalSize));

		m_pProgressStatusLabel->SetText(sOutput);
		m_pProgressStatusLabel->Invalidate();
	}
}
Ejemplo n.º 12
0
//----------------------------------------------------------------------------------
// Start the restarter.  Or is that restart the starter?  No, that's not right.
//
// Start the application that waits for SierraUp to shutdown.  The restarter will
// then apply the SierraUp patch, and restart Sierraup.
//----------------------------------------------------------------------------------
bool LaunchRestarter(const std::string& sPatchExe)
{
    ResourceManager* pResMgr = GetCustomInfo()->GetResourceManager();

    DebugLog("Preparing to launch restarter (applying update file: %s)\n", sPatchExe.c_str());

    char sSelf[MAX_PATH];
    GetModuleFileName(0, sSelf, MAX_PATH);

    // Fetch the current working folder.
    TCHAR sWorkingDir[MAX_PATH];
    GetCurrentDirectory(sizeof(sWorkingDir), sWorkingDir);
    if (sWorkingDir[0] && sWorkingDir[strlen(sWorkingDir) - 1] != '\\')
        strcat(sWorkingDir, "\\");

    // Fetch the folder SierraUp is installed in.
    std::string sSelfDir = sSelf;
    int nPos = sSelfDir.rfind('\\');
    sSelfDir.erase(nPos + 1, sSelfDir.length() - (nPos + 1)); // Leave the last backslash.
    DebugLog("SierraUpdate folder: %s\n", sSelfDir.c_str());

    // What is our executable name (just in case we change it).
    std::string sOurExeName = sSelf;
    nPos = sOurExeName.rfind('\\'); // Redundant, but just in case I move this block of code.
    sOurExeName.erase(0, nPos + 1);
    std::string sLowerExeName = StringToLowerCase(sOurExeName);
    DebugLog("SierraUpdate executable: %s\n", sOurExeName.c_str());

    // Fetch the original Command Line (we are going to re-use it).
    std::string sOrigCmdLine = GetCommandLine();
    std::string sLowerCmdLine = StringToLowerCase(sOrigCmdLine);
    std::string sNewCmdLine = sOrigCmdLine; // We will remove 'ourself' in a bit.
    DebugLog("Original Command Line = '%s'\n", sOrigCmdLine.c_str());

    // Find and remove ourself from the command line.
    nPos = sLowerCmdLine.find(sLowerExeName);
    if (nPos != -1)
    {
        UINT nDelta = nPos + sLowerExeName.length();
        sNewCmdLine.erase(0, nDelta);

        if (sNewCmdLine.length() && sNewCmdLine[0] == '\"')
            sNewCmdLine.erase(0, 1); // Bypass the ending quote.

        if (sNewCmdLine.length())
            sNewCmdLine.erase(0, 1); // Bypass the space.
    }
    DebugLog("New Command Line (for restart) = '%s'\n", sNewCmdLine.c_str());

    // We need the full path to the patch exe (replace the '.\' with our folder).
    std::string sFullPatchPath = CorrectPath(sPatchExe);
    DebugLog("Full update path = '%s'\n", sFullPatchPath.c_str());

    // Write the configuration file the the restarter will use.
    WritePrivateProfileString(sRestartSec, sWaitTimeKey, sRestartWaitTime, sRestartIniFile);
    WritePrivateProfileString(sRestartSec, sWaitAppKey, sSelf, sRestartIniFile);
    WritePrivateProfileString(sRestartSec, sRestartParamsKey, sNewCmdLine.c_str(), sRestartIniFile);
    WritePrivateProfileString(sRestartSec, sUpdateAppKey, sFullPatchPath.c_str(), sRestartIniFile);
    WritePrivateProfileString(sRestartSec, sUpdateParamsKey, sSelfDir.c_str(), sRestartIniFile);
    WritePrivateProfileString(sRestartSec, sDebugKey, GetCustomInfo()->GetDebug() ? "1" : "0", sRestartIniFile);

    std::string sCmdLine = "\"";
    sCmdLine += sRestartExe;
    sCmdLine += TEXT("\" ");
    sCmdLine += sRestartIniFile;

    STARTUPINFO SI;
    ZeroMemory(&SI, sizeof(SI));
    SI.cb = sizeof(STARTUPINFO);
    PROCESS_INFORMATION PI;

    DebugLog("Launching SierraUpRestarter\n");
    BOOL bRes = CreateProcess(NULL, (LPTSTR)(LPCTSTR)sCmdLine.c_str(), NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &SI, &PI);

    if (bRes)
    {
        // Clean up.
        CloseHandle(PI.hThread);
        CloseHandle(PI.hProcess);

        return true;
    }
    else
    {
        GUIString sMsg;

        if (GetLastError() == 2)
            sMsg = pResMgr->GetFinishedString(Global_NoFindRestarter_String);
        else
        {
            sMsg = pResMgr->GetFinishedString(Global_NoRunRestarter_String);
            ReplaceSubInt(sMsg, "%ERROR%", GetLastError());
        }

        DebugLog("Error Starting SierraUpRestarter: %s\n", std::string(sMsg).c_str());
        MessageBox(g_pWindow, sMsg, pResMgr->GetFinishedString(Global_RestarterFailed_String), MB_OK);
        return false;
    }
}
//----------------------------------------------------------------------------------
// 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();
}