1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/tools/installer/PerformInstall.cpp Sun Mar 30 07:00:22 2008 +0000
1.3 @@ -0,0 +1,438 @@
1.4 +#include "InstallerMain.h"
1.5 +#include "InstallerUtil.h"
1.6 +#include "PerformInstall.h"
1.7 +#include "CCriticalSection.h"
1.8 +
1.9 +#define WMU_INSTALLER_DONE WM_USER+2
1.10 +#define PBAR_RANGE_HIGH 100
1.11 +#define PBAR_RANGE_LOW 0
1.12 +
1.13 +ICopyMethod *g_pCopyMethod = NULL;
1.14 +HANDLE g_hCopyThread = NULL;
1.15 +copy_thread_args_t g_thread_args = {NULL, NULL, NULL, false, false};
1.16 +CCriticalSection g_update_window;
1.17 +
1.18 +class TrackProgress : public ICopyProgress
1.19 +{
1.20 +public:
1.21 + void Initialize(HWND hTextBar, HWND hCurBar, HWND hTotalBar, size_t total_size)
1.22 + {
1.23 + m_hTextBar = hTextBar;
1.24 + m_hCurBar = hCurBar;
1.25 + m_hTotalBar = hTotalBar;
1.26 + m_TotalSize = total_size;
1.27 + m_TotalDone = 0;
1.28 + RedrawProgressBars(0.0, 0.0);
1.29 + }
1.30 + void Finished()
1.31 + {
1.32 + RedrawProgressBars(100.0, 100.0);
1.33 + }
1.34 +public:
1.35 + void StartingNewFile(const TCHAR *filename)
1.36 + {
1.37 + TCHAR buffer[255];
1.38 +
1.39 + if (g_update_window.TryEnter())
1.40 + {
1.41 + UTIL_Format(buffer, sizeof(buffer) / sizeof(TCHAR), _T("Copying: %s"), filename);
1.42 + SendMessage(m_hTextBar, WM_SETTEXT, 0, (LPARAM)buffer);
1.43 + UpdateWindow(m_hTextBar);
1.44 + g_update_window.Leave();
1.45 + }
1.46 + }
1.47 + void UpdateProgress(size_t bytes, size_t total_bytes)
1.48 + {
1.49 + float fCur = (float)bytes / (float)total_bytes;
1.50 + float fTotal = ((float)m_TotalDone + (float)bytes) / (float)m_TotalSize;
1.51 + RedrawProgressBars(fCur, fTotal);
1.52 + }
1.53 + void FileDone(size_t total_size)
1.54 + {
1.55 + m_TotalDone += total_size;
1.56 + RedrawProgressBars(0.0, (float)m_TotalDone / (float)m_TotalSize);
1.57 + }
1.58 +private:
1.59 + void RedrawProgressBar(HWND hBar, float fPerc)
1.60 + {
1.61 + /* Get a percentage point in the range */
1.62 + float fPointInRange = (float)(PBAR_RANGE_HIGH - PBAR_RANGE_LOW) * fPerc;
1.63 + int iPointInRange = (int)fPointInRange;
1.64 +
1.65 + /* Scale it */
1.66 + iPointInRange += PBAR_RANGE_LOW;
1.67 +
1.68 + if (g_update_window.TryEnter())
1.69 + {
1.70 + SendMessage(hBar,
1.71 + PBM_SETPOS,
1.72 + iPointInRange,
1.73 + 0);
1.74 + g_update_window.Leave();
1.75 + }
1.76 + }
1.77 + void RedrawProgressBars(float fCurrent, float fTotal)
1.78 + {
1.79 + RedrawProgressBar(m_hCurBar, fCurrent);
1.80 + RedrawProgressBar(m_hTotalBar, fTotal);
1.81 + }
1.82 +private:
1.83 + size_t m_TotalSize;
1.84 + size_t m_TotalDone;
1.85 + HWND m_hTextBar;
1.86 + HWND m_hCurBar;
1.87 + HWND m_hTotalBar;
1.88 +} s_ProgressTracker;
1.89 +
1.90 +void CancelPerformInstall()
1.91 +{
1.92 + delete g_thread_args.pFileList;
1.93 + g_thread_args.pFileList = NULL;
1.94 +}
1.95 +
1.96 +void SetInstallMethod(ICopyMethod *pCopyMethod)
1.97 +{
1.98 + g_pCopyMethod = pCopyMethod;
1.99 +}
1.100 +
1.101 +bool CopyStructureRecursively(ICopyMethod *pCopyMethod,
1.102 + CFileList *pFileList,
1.103 + const TCHAR *basepath,
1.104 + const TCHAR *local_path,
1.105 + TCHAR *errbuf,
1.106 + size_t maxchars)
1.107 +{
1.108 + TCHAR file_path[MAX_PATH];
1.109 + const TCHAR *file;
1.110 + CFileList *pSubList;
1.111 +
1.112 + if (!pCopyMethod->SetCurrentFolder(local_path, errbuf, maxchars))
1.113 + {
1.114 + return false;
1.115 + }
1.116 +
1.117 + /* Copy files */
1.118 + while ((file = pFileList->PeekCurrentFile()) != NULL)
1.119 + {
1.120 + if (local_path == NULL)
1.121 + {
1.122 + UTIL_PathFormat(file_path,
1.123 + sizeof(file_path) / sizeof(TCHAR),
1.124 + _T("%s\\%s"),
1.125 + basepath,
1.126 + file);
1.127 + }
1.128 + else
1.129 + {
1.130 + UTIL_PathFormat(file_path,
1.131 + sizeof(file_path) / sizeof(TCHAR),
1.132 + _T("%s\\%s\\%s"),
1.133 + basepath,
1.134 + local_path,
1.135 + file);
1.136 + }
1.137 +
1.138 + if (!pCopyMethod->SendFile(file_path, errbuf, maxchars))
1.139 + {
1.140 + return false;
1.141 + }
1.142 +
1.143 + pFileList->PopCurrentFile();
1.144 + }
1.145 +
1.146 + /* Now copy folders */
1.147 + while ((pSubList = pFileList->PeekCurrentFolder()) != NULL)
1.148 + {
1.149 + if (g_thread_args.m_bIsUpgrade)
1.150 + {
1.151 + /* :TODO: put this somewhere else because it technically
1.152 + * means the progress bars get calculated wrong
1.153 + */
1.154 + if (tstrcasecmp(pSubList->GetFolderName(), _T("cfg")) == 0
1.155 + || tstrcasecmp(pSubList->GetFolderName(), _T("configs")) == 0)
1.156 + {
1.157 + pFileList->PopCurrentFolder();
1.158 + continue;
1.159 + }
1.160 + }
1.161 +
1.162 + /* Try creating the folder */
1.163 + if (!pCopyMethod->CreateFolder(pSubList->GetFolderName(), errbuf, maxchars))
1.164 + {
1.165 + return false;
1.166 + }
1.167 +
1.168 + TCHAR new_local_path[MAX_PATH];
1.169 + if (local_path == NULL)
1.170 + {
1.171 + UTIL_PathFormat(new_local_path,
1.172 + sizeof(new_local_path) / sizeof(TCHAR),
1.173 + _T("%s"),
1.174 + pSubList->GetFolderName());
1.175 + }
1.176 + else
1.177 + {
1.178 + UTIL_PathFormat(new_local_path,
1.179 + sizeof(new_local_path) / sizeof(TCHAR),
1.180 + _T("%s\\%s"),
1.181 + local_path,
1.182 + pSubList->GetFolderName());
1.183 + }
1.184 +
1.185 + if (!CopyStructureRecursively(pCopyMethod,
1.186 + pSubList,
1.187 + basepath,
1.188 + new_local_path,
1.189 + errbuf,
1.190 + maxchars))
1.191 + {
1.192 + return false;
1.193 + }
1.194 +
1.195 + pFileList->PopCurrentFolder();
1.196 +
1.197 + /* Set the current folder again for the next operation */
1.198 + if (!pCopyMethod->SetCurrentFolder(local_path, errbuf, maxchars))
1.199 + {
1.200 + return false;
1.201 + }
1.202 + }
1.203 +
1.204 + return true;
1.205 +}
1.206 +
1.207 +DWORD WINAPI T_CopyFiles(LPVOID arg)
1.208 +{
1.209 + bool result =
1.210 + CopyStructureRecursively(g_thread_args.pCopyMethod,
1.211 + g_thread_args.pFileList,
1.212 + g_thread_args.basepath,
1.213 + NULL,
1.214 + g_thread_args.error,
1.215 + sizeof(g_thread_args.error) / sizeof(TCHAR));
1.216 +
1.217 + PostMessage(g_thread_args.hWnd, WMU_INSTALLER_DONE, result ? TRUE : FALSE, 0);
1.218 +
1.219 + return 0;
1.220 +}
1.221 +
1.222 +bool StartFileCopy(HWND hWnd)
1.223 +{
1.224 + g_thread_args.m_bWasCancelled = false;
1.225 + g_thread_args.hWnd = hWnd;
1.226 + if ((g_hCopyThread = CreateThread(NULL,
1.227 + 0,
1.228 + T_CopyFiles,
1.229 + NULL,
1.230 + 0,
1.231 + NULL))
1.232 + == NULL)
1.233 + {
1.234 + MessageBox(
1.235 + hWnd,
1.236 + _T("Could not initialize copy thread."),
1.237 + _T("SourceMod Installer"),
1.238 + MB_OK|MB_ICONERROR);
1.239 + return false;
1.240 + }
1.241 + return true;
1.242 +}
1.243 +
1.244 +void StopFileCopy()
1.245 +{
1.246 + g_thread_args.m_bWasCancelled = true;
1.247 + g_pCopyMethod->CancelCurrentCopy();
1.248 +
1.249 + if (g_hCopyThread != NULL)
1.250 + {
1.251 + g_update_window.Enter();
1.252 + WaitForSingleObject(g_hCopyThread, INFINITE);
1.253 + g_update_window.Leave();
1.254 + CloseHandle(g_hCopyThread);
1.255 + g_hCopyThread = NULL;
1.256 + }
1.257 +}
1.258 +
1.259 +bool RequestCancelInstall(HWND hWnd)
1.260 +{
1.261 + StopFileCopy();
1.262 +
1.263 + int val = MessageBox(
1.264 + hWnd,
1.265 + _T("Are you sure you want to cancel the install?"),
1.266 + _T("SourceMod Installer"),
1.267 + MB_YESNO|MB_ICONQUESTION);
1.268 +
1.269 + if (val == IDYES)
1.270 + {
1.271 + return true;
1.272 + }
1.273 +
1.274 + if (g_thread_args.pFileList == NULL)
1.275 + {
1.276 + return false;
1.277 + }
1.278 +
1.279 + /* Start the thread, note our return value is opposite */
1.280 + return !StartFileCopy(hWnd);
1.281 +}
1.282 +
1.283 +bool StartInstallProcess(HWND hWnd)
1.284 +{
1.285 + if (g_pCopyMethod->CheckForExistingInstall())
1.286 + {
1.287 + int val = MessageBox(
1.288 + hWnd,
1.289 + _T("It looks like a previous SourceMod installation exists. Select \"Yes\" to skip copying configuration files. Select \"No\" to perform a full re-install."),
1.290 + _T("SourceMod Installer"),
1.291 + MB_YESNO|MB_ICONQUESTION);
1.292 +
1.293 + if (val == 0 || val == IDYES)
1.294 + {
1.295 + g_thread_args.m_bIsUpgrade = true;
1.296 + }
1.297 + else
1.298 + {
1.299 + g_thread_args.m_bIsUpgrade = false;
1.300 + }
1.301 + }
1.302 +
1.303 +#if 0
1.304 + TCHAR cur_path[MAX_PATH];
1.305 + if (_tgetcwd(cur_path, sizeof(cur_path)) == NULL)
1.306 + {
1.307 + MessageBox(
1.308 + hWnd,
1.309 + _T("Could not locate current directory!"),
1.310 + _T("SourceMod Installer"),
1.311 + MB_OK|MB_ICONERROR);
1.312 + return false;
1.313 + }
1.314 +#endif
1.315 +
1.316 +#if 0
1.317 + UTIL_PathFormat(source_path,
1.318 + sizeof(source_path) / sizeof(TCHAR),
1.319 + _T("%s\\files"),
1.320 + cur_path);
1.321 +#else
1.322 + UTIL_PathFormat(g_thread_args.basepath,
1.323 + sizeof(g_thread_args.basepath) / sizeof(TCHAR),
1.324 + _T("C:\\real\\done\\base"));
1.325 +#endif
1.326 +
1.327 + if (GetFileAttributes(g_thread_args.basepath) == INVALID_FILE_ATTRIBUTES)
1.328 + {
1.329 + MessageBox(
1.330 + hWnd,
1.331 + _T("Could not locate the source installation files!"),
1.332 + _T("SourceMod Installer"),
1.333 + MB_OK|MB_ICONERROR);
1.334 + return false;
1.335 + }
1.336 +
1.337 + delete g_thread_args.pFileList;
1.338 + g_thread_args.pFileList = CFileList::BuildFileList(_T(""), g_thread_args.basepath);
1.339 +
1.340 + s_ProgressTracker.Initialize(
1.341 + GetDlgItem(hWnd, IDC_PROGRESS_CURCOPY),
1.342 + GetDlgItem(hWnd, IDC_PROGRESS_CURRENT),
1.343 + GetDlgItem(hWnd, IDC_PROGRESS_TOTAL),
1.344 + (size_t)g_thread_args.pFileList->GetRecursiveSize());
1.345 + g_pCopyMethod->TrackProgress(&s_ProgressTracker);
1.346 + g_thread_args.pCopyMethod = g_pCopyMethod;
1.347 +
1.348 + return StartFileCopy(hWnd);
1.349 +}
1.350 +
1.351 +INT_PTR CALLBACK PerformInstallHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1.352 +{
1.353 + switch (message)
1.354 + {
1.355 + case WM_INITDIALOG:
1.356 + {
1.357 + SetToGlobalPosition(hDlg);
1.358 + return (INT_PTR)TRUE;
1.359 + }
1.360 + case WM_COMMAND:
1.361 + {
1.362 + if (LOWORD(wParam) == ID_INSTALL_CANCEL
1.363 + || LOWORD(wParam) == ID_CLOSE)
1.364 + {
1.365 + if (RequestCancelInstall(hDlg))
1.366 + {
1.367 + CancelPerformInstall();
1.368 + UpdateGlobalPosition(hDlg);
1.369 + EndDialog(hDlg, NULL);
1.370 + }
1.371 + return (INT_PTR)TRUE;
1.372 + }
1.373 + else if (LOWORD(wParam) == ID_INSTALL_START)
1.374 + {
1.375 + HWND hButton = GetDlgItem(hDlg, ID_INSTALL_START);
1.376 + EnableWindow(hButton, FALSE);
1.377 + StartInstallProcess(hDlg);
1.378 + }
1.379 + break;
1.380 + }
1.381 + case WMU_INSTALLER_DONE:
1.382 + {
1.383 + if (wParam == TRUE)
1.384 + {
1.385 + s_ProgressTracker.Finished();
1.386 + MessageBox(hDlg,
1.387 + _T("SourceMod was successfully installed! Please visit http://www.sourcemod.net/ for documentation."),
1.388 + _T("SourceMod Installer"),
1.389 + MB_OK);
1.390 + CancelPerformInstall();
1.391 + UpdateGlobalPosition(hDlg);
1.392 + EndDialog(hDlg, NULL);
1.393 + return (INT_PTR)TRUE;
1.394 + }
1.395 + else if (!g_thread_args.m_bWasCancelled)
1.396 + {
1.397 + TCHAR buffer[500];
1.398 +
1.399 + UTIL_Format(buffer,
1.400 + sizeof(buffer) / sizeof(TCHAR),
1.401 + _T("Encountered error: %s"),
1.402 + g_thread_args.error);
1.403 + int res = MessageBox(hDlg,
1.404 + buffer,
1.405 + _T("SourceMod Installer"),
1.406 + MB_ICONERROR|MB_RETRYCANCEL);
1.407 +
1.408 + if (res == IDRETRY)
1.409 + {
1.410 + StartFileCopy(hDlg);
1.411 + }
1.412 + else
1.413 + {
1.414 + CancelPerformInstall();
1.415 + UpdateGlobalPosition(hDlg);
1.416 + EndDialog(hDlg, NULL);
1.417 + return (INT_PTR)TRUE;
1.418 + }
1.419 + }
1.420 + break;
1.421 + }
1.422 + }
1.423 +
1.424 + return (INT_PTR)FALSE;
1.425 +}
1.426 +
1.427 +void *DisplayPerformInstall(HWND hWnd)
1.428 +{
1.429 + INT_PTR val;
1.430 +
1.431 + if ((val = DialogBox(
1.432 + g_hInstance,
1.433 + MAKEINTRESOURCE(IDD_PERFORM_INSTALL),
1.434 + hWnd,
1.435 + PerformInstallHandler)) == -1)
1.436 + {
1.437 + return NULL;
1.438 + }
1.439 +
1.440 + return (void *)val;
1.441 +}