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