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