tools/installer/PerformInstall.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 25 18:50:13 2007 +0000 (2007-11-25)
changeset 1725 ea875bcbc286
parent 1722 2c16f160f5dd
child 1726 5ca491ac0e35
permissions -rw-r--r--
small clarification to param2 in MenuAction_End
     1 #include "InstallerMain.h"
     2 #include "InstallerUtil.h"
     3 #include "PerformInstall.h"
     4 #include "CCriticalSection.h"
     5 
     6 #define WMU_INSTALLER_DONE		WM_USER+2
     7 #define PBAR_RANGE_HIGH			100
     8 #define PBAR_RANGE_LOW			0
     9 
    10 ICopyMethod *g_pCopyMethod = NULL;
    11 HANDLE g_hCopyThread = NULL;
    12 copy_thread_args_t g_thread_args = {NULL, NULL, NULL, false, false};
    13 CCriticalSection g_update_window;
    14 
    15 class TrackProgress : public ICopyProgress
    16 {
    17 public:
    18 	void Initialize(HWND hTextBar, HWND hCurBar, HWND hTotalBar, size_t total_size)
    19 	{
    20 		m_hTextBar = hTextBar;
    21 		m_hCurBar = hCurBar;
    22 		m_hTotalBar = hTotalBar;
    23 		m_TotalSize = total_size;
    24 		m_TotalDone = 0;
    25 		RedrawProgressBars(0.0, 0.0);
    26 	}
    27 	void Finished()
    28 	{
    29 		RedrawProgressBars(100.0, 100.0);
    30 	}
    31 public:
    32 	void StartingNewFile(const TCHAR *filename)
    33 	{
    34 		TCHAR buffer[255];
    35 
    36 		if (g_update_window.TryEnter())
    37 		{
    38 			UTIL_Format(buffer, sizeof(buffer) / sizeof(TCHAR), _T("Copying: %s"), filename);
    39 			SendMessage(m_hTextBar, WM_SETTEXT, 0, (LPARAM)buffer);
    40 			UpdateWindow(m_hTextBar);
    41 			g_update_window.Leave();
    42 		}
    43 	}
    44 	void UpdateProgress(size_t bytes, size_t total_bytes)
    45 	{
    46 		float fCur = (float)bytes / (float)total_bytes;
    47 		float fTotal = ((float)m_TotalDone + (float)bytes) / (float)m_TotalSize;
    48 		RedrawProgressBars(fCur, fTotal);
    49 	}
    50 	void FileDone(size_t total_size)
    51 	{
    52 		m_TotalDone += total_size;
    53 		RedrawProgressBars(0.0, (float)m_TotalDone / (float)m_TotalSize);
    54 	}
    55 private:
    56 	void RedrawProgressBar(HWND hBar, float fPerc)
    57 	{
    58 		/* Get a percentage point in the range */
    59 		float fPointInRange = (float)(PBAR_RANGE_HIGH - PBAR_RANGE_LOW) * fPerc;
    60 		int iPointInRange = (int)fPointInRange;
    61 
    62 		/* Scale it */
    63 		iPointInRange += PBAR_RANGE_LOW;
    64 
    65 		if (g_update_window.TryEnter())
    66 		{
    67 			SendMessage(hBar,
    68 				PBM_SETPOS,
    69 				iPointInRange,
    70 				0);
    71 			g_update_window.Leave();
    72 		}
    73 	}
    74 	void RedrawProgressBars(float fCurrent, float fTotal)
    75 	{
    76 		RedrawProgressBar(m_hCurBar, fCurrent);
    77 		RedrawProgressBar(m_hTotalBar, fTotal);
    78 	}
    79 private:
    80 	size_t m_TotalSize;
    81 	size_t m_TotalDone;
    82 	HWND m_hTextBar;
    83 	HWND m_hCurBar;
    84 	HWND m_hTotalBar;
    85 } s_ProgressTracker;
    86 
    87 void CancelPerformInstall()
    88 {
    89 	delete g_thread_args.pFileList;
    90 	g_thread_args.pFileList = NULL;
    91 }
    92 
    93 void SetInstallMethod(ICopyMethod *pCopyMethod)
    94 {
    95 	g_pCopyMethod = pCopyMethod;
    96 }
    97 
    98 bool CopyStructureRecursively(ICopyMethod *pCopyMethod,
    99 							  CFileList *pFileList,
   100 							  const TCHAR *basepath,
   101 							  const TCHAR *local_path,
   102 							  TCHAR *errbuf,
   103 							  size_t maxchars)
   104 {
   105 	TCHAR file_path[MAX_PATH];
   106 	const TCHAR *file;
   107 	CFileList *pSubList;
   108 
   109 	if (!pCopyMethod->SetCurrentFolder(local_path, errbuf, maxchars))
   110 	{
   111 		return false;
   112 	}
   113 
   114 	/* Copy files */
   115 	while ((file = pFileList->PeekCurrentFile()) != NULL)
   116 	{
   117 		if (local_path == NULL)
   118 		{
   119 			UTIL_PathFormat(file_path,
   120 				sizeof(file_path) / sizeof(TCHAR),
   121 				_T("%s\\%s"),
   122 				basepath,
   123 				file);
   124 		}
   125 		else
   126 		{
   127 			UTIL_PathFormat(file_path,
   128 				sizeof(file_path) / sizeof(TCHAR), 
   129 				_T("%s\\%s\\%s"),
   130 				basepath,
   131 				local_path,
   132 				file);
   133 		}
   134 
   135 		if (!pCopyMethod->SendFile(file_path, errbuf, maxchars))
   136 		{
   137 			return false;
   138 		}
   139 
   140 		pFileList->PopCurrentFile();
   141 	}
   142 
   143 	/* Now copy folders */
   144 	while ((pSubList = pFileList->PeekCurrentFolder()) != NULL)
   145 	{
   146 		/* Try creating the folder */
   147 		if (!pCopyMethod->CreateFolder(pSubList->GetFolderName(), errbuf, maxchars))
   148 		{
   149 			return false;
   150 		}
   151 
   152 		TCHAR new_local_path[MAX_PATH];
   153 		if (local_path == NULL)
   154 		{
   155 			UTIL_PathFormat(new_local_path,
   156 				sizeof(new_local_path) / sizeof(TCHAR),
   157 				_T("%s"),
   158 				pSubList->GetFolderName());
   159 		}
   160 		else
   161 		{
   162 			UTIL_PathFormat(new_local_path,
   163 				sizeof(new_local_path) / sizeof(TCHAR),
   164 				_T("%s\\%s"),
   165 				local_path,
   166 				pSubList->GetFolderName());
   167 		}
   168 
   169 		if (!CopyStructureRecursively(pCopyMethod,
   170 				pSubList,
   171 				basepath, 
   172 				new_local_path, 
   173 				errbuf, 
   174 				maxchars))
   175 		{
   176 			return false;
   177 		}
   178 
   179 		pFileList->PopCurrentFolder();
   180 
   181 		/* Set the current folder again for the next operation */
   182 		if (!pCopyMethod->SetCurrentFolder(local_path, errbuf, maxchars))
   183 		{
   184 			return false;
   185 		}
   186 	}
   187 
   188 	return true;
   189 }
   190 
   191 DWORD WINAPI T_CopyFiles(LPVOID arg)
   192 {
   193 	bool result = 
   194 		CopyStructureRecursively(g_thread_args.pCopyMethod,
   195 		g_thread_args.pFileList,
   196 		g_thread_args.basepath,
   197 		NULL,
   198 		g_thread_args.error,
   199 		sizeof(g_thread_args.error) / sizeof(TCHAR));
   200 
   201 	PostMessage(g_thread_args.hWnd, WMU_INSTALLER_DONE, result ? TRUE : FALSE, 0);
   202 
   203 	return 0;
   204 }
   205 
   206 bool StartFileCopy(HWND hWnd)
   207 {
   208 	g_thread_args.m_bWasCancelled = false;
   209 	g_thread_args.hWnd = hWnd;
   210 	if ((g_hCopyThread = CreateThread(NULL, 
   211 		0, 
   212 		T_CopyFiles, 
   213 		NULL, 
   214 		0,
   215 		NULL))
   216 		== NULL)
   217 	{
   218 		MessageBox(
   219 			hWnd,
   220 			_T("Could not initialize copy thread."),
   221 			_T("SourceMod Installer"),
   222 			MB_OK|MB_ICONERROR);
   223 		return false;
   224 	}
   225 	return true;
   226 }
   227 
   228 void StopFileCopy()
   229 {
   230 	g_thread_args.m_bWasCancelled = true;
   231 	g_pCopyMethod->CancelCurrentCopy();
   232 
   233 	if (g_hCopyThread != NULL)
   234 	{
   235 		g_update_window.Enter();
   236 		WaitForSingleObject(g_hCopyThread, INFINITE);
   237 		g_update_window.Leave();
   238 		CloseHandle(g_hCopyThread);
   239 		g_hCopyThread = NULL;
   240 	}
   241 }
   242 
   243 bool RequestCancelInstall(HWND hWnd)
   244 {
   245 	StopFileCopy();
   246 
   247 	int val = MessageBox(
   248 		hWnd,
   249 		_T("Are you sure you want to cancel the install?"),
   250 		_T("SourceMod Installer"),
   251 		MB_YESNO|MB_ICONQUESTION);
   252 
   253 	if (val == IDYES)
   254 	{
   255 		return true;
   256 	}
   257 	
   258 	if (g_thread_args.pFileList == NULL)
   259 	{
   260 		return false;
   261 	}
   262 
   263 	/* Start the thread, note our return value is opposite */
   264 	return !StartFileCopy(hWnd);
   265 }
   266 
   267 bool StartInstallProcess(HWND hWnd)
   268 {
   269 	if (g_pCopyMethod->CheckForExistingInstall())
   270 	{
   271 		int val = MessageBox(
   272 			hWnd, 
   273 			_T("It looks like a previous SourceMod installation exists.  Do you want to upgrade?  Select \"Yes\" to upgrade and keep configuration files.  Select \"No\" to perform a full re-install."),
   274 			_T("SourceMod Installer"), 
   275 			MB_YESNO|MB_ICONQUESTION);
   276 
   277 		if (val == 0 || val == IDYES)
   278 		{
   279 		}
   280 		else
   281 		{
   282 		}
   283 	}
   284 
   285 #if 0
   286 	TCHAR cur_path[MAX_PATH];
   287 	if (_tgetcwd(cur_path, sizeof(cur_path)) == NULL)
   288 	{
   289 		MessageBox(
   290 			hWnd,
   291 			_T("Could not locate current directory!"),
   292 			_T("SourceMod Installer"),
   293 			MB_OK|MB_ICONERROR);
   294 		return false;
   295 	}
   296 #endif
   297 
   298 #if 0
   299 	UTIL_PathFormat(source_path,
   300 		sizeof(source_path) / sizeof(TCHAR),
   301 		_T("%s\\files"),
   302 		cur_path);
   303 #else
   304 	UTIL_PathFormat(g_thread_args.basepath,
   305 		sizeof(g_thread_args.basepath) / sizeof(TCHAR),
   306 		_T("C:\\real\\done\\base"));
   307 #endif
   308 
   309 	if (GetFileAttributes(g_thread_args.basepath) == INVALID_FILE_ATTRIBUTES)
   310 	{
   311 		MessageBox(
   312 			hWnd,
   313 			_T("Could not locate the source installation files!"),
   314 			_T("SourceMod Installer"),
   315 			MB_OK|MB_ICONERROR);
   316 		return false;
   317 	}
   318 
   319 	delete g_thread_args.pFileList;
   320 	g_thread_args.pFileList = CFileList::BuildFileList(_T(""), g_thread_args.basepath);
   321 
   322 	s_ProgressTracker.Initialize(
   323 		GetDlgItem(hWnd, IDC_PROGRESS_CURCOPY),
   324 		GetDlgItem(hWnd, IDC_PROGRESS_CURRENT),
   325 		GetDlgItem(hWnd, IDC_PROGRESS_TOTAL),
   326 		(size_t)g_thread_args.pFileList->GetRecursiveSize());
   327 	g_pCopyMethod->TrackProgress(&s_ProgressTracker);
   328 	g_thread_args.pCopyMethod = g_pCopyMethod;
   329 
   330 	return StartFileCopy(hWnd);
   331 }
   332 
   333 INT_PTR CALLBACK PerformInstallHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
   334 {
   335 	switch (message)
   336 	{
   337 	case WM_INITDIALOG:
   338 		{
   339 			SetToGlobalPosition(hDlg);
   340 			return (INT_PTR)TRUE;
   341 		}
   342 	case WM_COMMAND:
   343 		{
   344 			if (LOWORD(wParam) == ID_INSTALL_CANCEL
   345 				|| LOWORD(wParam) == ID_CLOSE)
   346 			{
   347 				if (RequestCancelInstall(hDlg))
   348 				{
   349 					CancelPerformInstall();
   350 					UpdateGlobalPosition(hDlg);
   351 					EndDialog(hDlg, NULL);
   352 				}
   353 				return (INT_PTR)TRUE;
   354 			}
   355 			else if (LOWORD(wParam) == ID_INSTALL_START)
   356 			{
   357 				HWND hButton = GetDlgItem(hDlg, ID_INSTALL_START);
   358 				EnableWindow(hButton, FALSE);
   359 				StartInstallProcess(hDlg);
   360 			}
   361 			break;
   362 		}
   363 	case WMU_INSTALLER_DONE:
   364 		{
   365 			if (wParam == TRUE)
   366 			{
   367 				s_ProgressTracker.Finished();
   368 				MessageBox(hDlg,
   369 					_T("SourceMod was successfully installed!  Please visit http://www.sourcemod.net/ for documentation."),
   370 					_T("SourceMod Installer"),
   371 					MB_OK);
   372 				CancelPerformInstall();
   373 				UpdateGlobalPosition(hDlg);
   374 				EndDialog(hDlg, NULL);
   375 				return (INT_PTR)TRUE;
   376 			}
   377 			else if (!g_thread_args.m_bWasCancelled)
   378 			{
   379 				TCHAR buffer[500];
   380 
   381 				UTIL_Format(buffer, 
   382 					sizeof(buffer) / sizeof(TCHAR), 
   383 					_T("Encountered error: %s"),
   384 					g_thread_args.error);
   385 				int res = MessageBox(hDlg,
   386 					buffer,
   387 					_T("SourceMod Installer"),
   388 					MB_ICONERROR|MB_RETRYCANCEL);
   389 
   390 				if (res == IDRETRY)
   391 				{
   392 					StartFileCopy(hDlg);
   393 				}
   394 				else
   395 				{
   396 					CancelPerformInstall();
   397 					UpdateGlobalPosition(hDlg);
   398 					EndDialog(hDlg, NULL);
   399 					return (INT_PTR)TRUE;
   400 				}
   401 			}
   402 			break;
   403 		}
   404 	}
   405 
   406 	return (INT_PTR)FALSE;
   407 }
   408 
   409 void *DisplayPerformInstall(HWND hWnd)
   410 {
   411 	INT_PTR val;
   412 
   413 	if ((val = DialogBox(
   414 		g_hInstance, 
   415 		MAKEINTRESOURCE(IDD_PERFORM_INSTALL),
   416 		hWnd,
   417 		PerformInstallHandler)) == -1)
   418 	{
   419 		return NULL;
   420 	}
   421 
   422 	return (void *)val;
   423 }