|
|
1.1.1.11 root 1: /*
1.1.1.13 root 2: Legal Notice: Some portions of the source code contained in this file were
3: derived from the source code of Encryption for the Masses 2.02a, which is
4: Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
5: Agreement for Encryption for the Masses'. Modifications and additions to
1.1.1.23 root 6: the original source code (contained in this file) and all other portions
1.1.1.24 root 7: of this file are Copyright (c) 2003-2010 TrueCrypt Developers Association
8: and are governed by the TrueCrypt License 3.0 the full text of which is
1.1.1.23 root 9: contained in the file License.txt included in TrueCrypt binary and source
10: code distribution packages. */
1.1 root 11:
1.1.1.7 root 12: #include "Tcdefs.h"
1.1 root 13: #include <SrRestorePtApi.h>
1.1.1.24 root 14: #include <io.h>
1.1.1.22 root 15: #include <propkey.h>
16: #include <propvarutil.h>
1.1.1.7 root 17: #include <sys/types.h>
18: #include <sys/stat.h>
1.1 root 19:
1.1.1.7 root 20: #include "Apidrvr.h"
1.1.1.13 root 21: #include "BootEncryption.h"
1.1.1.22 root 22: #include "Boot/Windows/BootCommon.h"
1.1.1.7 root 23: #include "Combo.h"
1.1.1.11 root 24: #include "ComSetup.h"
1.1.1.7 root 25: #include "Dlgcode.h"
26: #include "Language.h"
27: #include "Registry.h"
28: #include "Resource.h"
1.1 root 29:
1.1.1.7 root 30: #include "Dir.h"
31: #include "Setup.h"
1.1.1.13 root 32: #include "SelfExtract.h"
33: #include "Wizard.h"
1.1 root 34:
1.1.1.7 root 35: #include "../Common/Resource.h"
1.1 root 36:
1.1.1.13 root 37: using namespace TrueCrypt;
38:
1.1 root 39: #pragma warning( disable : 4201 )
40: #pragma warning( disable : 4115 )
41:
42: #include <shlobj.h>
43:
44: #pragma warning( default : 4201 )
45: #pragma warning( default : 4115 )
46:
1.1.1.13 root 47: char InstallationPath[TC_MAX_PATH];
1.1.1.8 root 48: char SetupFilesDir[TC_MAX_PATH];
1.1.1.11 root 49: char UninstallBatch[MAX_PATH];
1.1.1.8 root 50:
1.1.1.24 root 51: LONG InstalledVersion = 0;
1.1 root 52: BOOL bUninstall = FALSE;
1.1.1.25! root 53: BOOL bRestartRequired = FALSE;
1.1.1.13 root 54: BOOL bMakePackage = FALSE;
1.1 root 55: BOOL bDone = FALSE;
1.1.1.11 root 56: BOOL Rollback = FALSE;
57: BOOL bUpgrade = FALSE;
1.1.1.18 root 58: BOOL bDowngrade = FALSE;
1.1.1.14 root 59: BOOL SystemEncryptionUpgrade = FALSE;
1.1.1.24 root 60: BOOL PortableMode = FALSE;
1.1.1.13 root 61: BOOL bRepairMode = FALSE;
62: BOOL bChangeMode = FALSE;
63: BOOL bDevm = FALSE;
1.1.1.25! root 64: BOOL bPossiblyFirstTimeInstall = FALSE;
1.1.1.13 root 65: BOOL bUninstallInProgress = FALSE;
1.1.1.22 root 66: BOOL UnloadDriver = TRUE;
1.1.1.13 root 67:
68: BOOL bSystemRestore = TRUE;
1.1.1.18 root 69: BOOL bDisableSwapFiles = FALSE;
1.1.1.13 root 70: BOOL bForAllUsers = TRUE;
71: BOOL bRegisterFileExt = TRUE;
72: BOOL bAddToStartMenu = TRUE;
73: BOOL bDesktopIcon = TRUE;
1.1 root 74:
1.1.1.23 root 75: BOOL bDesktopIconStatusDetermined = FALSE;
76:
1.1.1.13 root 77: HMODULE volatile SystemRestoreDll = 0;
1.1 root 78:
1.1.1.17 root 79: void localcleanup (void)
80: {
81: localcleanupwiz ();
82: cleanup ();
83:
84: CloseAppSetupMutex ();
85: }
86:
1.1.1.18 root 87: BOOL StatDeleteFile (char *lpszFile)
1.1 root 88: {
89: struct __stat64 st;
90:
91: if (_stat64 (lpszFile, &st) == 0)
92: return DeleteFile (lpszFile);
93: else
94: return TRUE;
95: }
96:
1.1.1.18 root 97: BOOL StatRemoveDirectory (char *lpszDir)
1.1 root 98: {
99: struct __stat64 st;
100:
101: if (_stat64 (lpszDir, &st) == 0)
102: return RemoveDirectory (lpszDir);
103: else
104: return TRUE;
105: }
106:
1.1.1.18 root 107: HRESULT CreateLink (char *lpszPathObj, char *lpszArguments,
1.1 root 108: char *lpszPathLink)
109: {
110: HRESULT hres;
111: IShellLink *psl;
112:
113: /* Get a pointer to the IShellLink interface. */
1.1.1.13 root 114: hres = CoCreateInstance (CLSID_ShellLink, NULL,
115: CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *) &psl);
1.1 root 116: if (SUCCEEDED (hres))
117: {
118: IPersistFile *ppf;
119:
120: /* Set the path to the shortcut target, and add the
121: description. */
1.1.1.13 root 122: psl->SetPath (lpszPathObj);
123: psl->SetArguments (lpszArguments);
1.1 root 124:
1.1.1.22 root 125: // Application ID
126: if (strstr (lpszPathObj, TC_APP_NAME ".exe"))
127: {
128: IPropertyStore *propStore;
129:
130: if (SUCCEEDED (psl->QueryInterface (IID_PPV_ARGS (&propStore))))
131: {
132: PROPVARIANT propVariant;
133: if (SUCCEEDED (InitPropVariantFromString (TC_APPLICATION_ID, &propVariant)))
134: {
135: if (SUCCEEDED (propStore->SetValue (PKEY_AppUserModel_ID, propVariant)))
136: propStore->Commit();
137:
138: PropVariantClear (&propVariant);
139: }
140:
141: propStore->Release();
142: }
143: }
144:
1.1 root 145: /* Query IShellLink for the IPersistFile interface for saving
146: the shortcut in persistent storage. */
1.1.1.13 root 147: hres = psl->QueryInterface (IID_IPersistFile,
148: (void **) &ppf);
1.1 root 149:
150: if (SUCCEEDED (hres))
151: {
1.1.1.13 root 152: wchar_t wsz[TC_MAX_PATH];
1.1 root 153:
154: /* Ensure that the string is ANSI. */
155: MultiByteToWideChar (CP_ACP, 0, lpszPathLink, -1,
1.1.1.15 root 156: wsz, sizeof(wsz) / sizeof(wsz[0]));
1.1 root 157:
158: /* Save the link by calling IPersistFile::Save. */
1.1.1.13 root 159: hres = ppf->Save (wsz, TRUE);
160: ppf->Release ();
1.1 root 161: }
1.1.1.13 root 162: psl->Release ();
1.1 root 163: }
164: return hres;
165: }
166:
1.1.1.18 root 167: void GetProgramPath (HWND hwndDlg, char *path)
1.1 root 168: {
169: ITEMIDLIST *i;
170: HRESULT res;
171:
1.1.1.13 root 172: if (bForAllUsers)
1.1 root 173: res = SHGetSpecialFolderLocation (hwndDlg, CSIDL_COMMON_PROGRAMS, &i);
174: else
175: res = SHGetSpecialFolderLocation (hwndDlg, CSIDL_PROGRAMS, &i);
176:
177: SHGetPathFromIDList (i, path);
178: }
179:
1.1.1.18 root 180: void StatusMessage (HWND hwndDlg, char *stringId)
1.1 root 181: {
1.1.1.11 root 182: if (Rollback)
183: return;
184:
1.1.1.13 root 185: SendMessageW (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_ADDSTRING, 0, (LPARAM) GetString (stringId));
1.1.1.11 root 186:
1.1.1.13 root 187: SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_SETTOPINDEX,
188: SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_GETCOUNT, 0, 0) - 1, 0);
1.1 root 189: }
190:
1.1.1.18 root 191: void StatusMessageParam (HWND hwndDlg, char *stringId, char *param)
1.1 root 192: {
1.1.1.7 root 193: wchar_t szTmp[1024];
1.1.1.11 root 194:
195: if (Rollback)
196: return;
197:
1.1.1.7 root 198: wsprintfW (szTmp, L"%s %hs", GetString (stringId), param);
1.1.1.13 root 199: SendMessageW (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_ADDSTRING, 0, (LPARAM) szTmp);
1.1.1.7 root 200:
1.1.1.13 root 201: SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_SETTOPINDEX,
202: SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_GETCOUNT, 0, 0) - 1, 0);
203: }
204:
1.1.1.18 root 205: void ClearLogWindow (HWND hwndDlg)
1.1.1.13 root 206: {
207: SendMessage (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_RESETCONTENT, 0, 0);
1.1 root 208: }
209:
1.1.1.18 root 210: void RegMessage (HWND hwndDlg, char *txt)
1.1 root 211: {
1.1.1.7 root 212: StatusMessageParam (hwndDlg, "ADDING_REG", txt);
1.1 root 213: }
214:
1.1.1.18 root 215: void CopyMessage (HWND hwndDlg, char *txt)
1.1 root 216: {
1.1.1.11 root 217: StatusMessageParam (hwndDlg, "INSTALLING", txt);
1.1 root 218: }
219:
1.1.1.18 root 220: void RemoveMessage (HWND hwndDlg, char *txt)
1.1 root 221: {
1.1.1.11 root 222: if (!Rollback)
223: StatusMessageParam (hwndDlg, "REMOVING", txt);
1.1 root 224: }
225:
1.1.1.18 root 226: void IconMessage (HWND hwndDlg, char *txt)
1.1 root 227: {
1.1.1.7 root 228: StatusMessageParam (hwndDlg, "ADDING_ICON", txt);
1.1 root 229: }
230:
1.1.1.22 root 231: void DetermineUpgradeDowngradeStatus (BOOL bCloseDriverHandle, LONG *driverVersionPtr)
232: {
233: LONG driverVersion = VERSION_NUM;
234:
235: if (hDriver == INVALID_HANDLE_VALUE)
236: DriverAttach();
237:
238: if (hDriver != INVALID_HANDLE_VALUE)
239: {
240: DWORD dwResult;
241: BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &driverVersion, sizeof (driverVersion), &dwResult, NULL);
242:
243: if (!bResult)
244: bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &driverVersion, sizeof (driverVersion), &dwResult, NULL);
245:
1.1.1.24 root 246: if (bResult)
247: InstalledVersion = driverVersion;
248:
1.1.1.22 root 249: bUpgrade = (bResult && driverVersion < VERSION_NUM);
250: bDowngrade = (bResult && driverVersion > VERSION_NUM);
251:
1.1.1.24 root 252: PortableMode = DeviceIoControl (hDriver, TC_IOCTL_GET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dwResult, NULL);
253:
1.1.1.22 root 254: if (bCloseDriverHandle)
255: {
256: CloseHandle (hDriver);
257: hDriver = INVALID_HANDLE_VALUE;
258: }
259: }
260:
261: *driverVersionPtr = driverVersion;
262: }
1.1 root 263:
1.1.1.23 root 264:
265: static BOOL IsFileInUse (const string &filePath)
266: {
267: HANDLE useTestHandle = CreateFile (filePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
268:
269: if (useTestHandle != INVALID_HANDLE_VALUE)
270: CloseHandle (useTestHandle);
271: else if (GetLastError() == ERROR_SHARING_VIOLATION)
272: return TRUE;
273:
274: return FALSE;
275: }
276:
277:
1.1.1.13 root 278: BOOL DoFilesInstall (HWND hwndDlg, char *szDestDir)
1.1 root 279: {
1.1.1.13 root 280: /* WARNING: Note that, despite its name, this function is used during UNinstallation as well. */
1.1 root 281:
282: char szTmp[TC_MAX_PATH];
283: BOOL bOK = TRUE;
1.1.1.13 root 284: int i, x, fileNo;
285: char curFileName [TC_MAX_PATH] = {0};
286:
287: if (!bUninstall && !bDevm)
288: {
289: // Self-extract all files to memory
290:
291: GetModuleFileName (NULL, szTmp, sizeof (szTmp));
292:
293: if (!SelfExtractInMemory (szTmp))
294: return FALSE;
295: }
1.1 root 296:
1.1.1.11 root 297: x = strlen (szDestDir);
1.1.1.13 root 298: if (x < 2)
1.1.1.11 root 299: return FALSE;
300:
301: if (szDestDir[x - 1] != '\\')
302: strcat (szDestDir, "\\");
1.1 root 303:
304: for (i = 0; i < sizeof (szFiles) / sizeof (szFiles[0]); i++)
305: {
1.1.1.11 root 306: BOOL bResult;
1.1 root 307: char szDir[TC_MAX_PATH];
308:
1.1.1.13 root 309: if (strstr (szFiles[i], "TrueCrypt Setup") != 0)
310: {
311: if (bUninstall)
312: continue; // Prevent 'access denied' error
313:
314: if (bRepairMode)
315: continue; // Destination = target
316: }
1.1 root 317:
318: if (*szFiles[i] == 'A')
319: strcpy (szDir, szDestDir);
320: else if (*szFiles[i] == 'D')
321: {
1.1.1.10 root 322: GetSystemDirectory (szDir, sizeof (szDir));
1.1 root 323:
1.1.1.11 root 324: x = strlen (szDir);
325: if (szDir[x - 1] != '\\')
1.1 root 326: strcat (szDir, "\\");
327:
1.1.1.11 root 328: strcat (szDir, "Drivers\\");
1.1 root 329: }
330: else if (*szFiles[i] == 'W')
331: GetWindowsDirectory (szDir, sizeof (szDir));
332:
1.1.1.7 root 333: if (*szFiles[i] == 'I')
1.1 root 334: continue;
335:
336: sprintf (szTmp, "%s%s", szDir, szFiles[i] + 1);
337:
338: if (bUninstall == FALSE)
339: CopyMessage (hwndDlg, szTmp);
340: else
341: RemoveMessage (hwndDlg, szTmp);
342:
343: if (bUninstall == FALSE)
344: {
1.1.1.8 root 345: SetCurrentDirectory (SetupFilesDir);
346:
1.1.1.13 root 347: if (strstr (szFiles[i], "TrueCrypt Setup") != 0)
1.1 root 348: {
1.1.1.13 root 349: // Copy ourselves (the distribution package) to the destination location as 'TrueCrypt Setup.exe'
1.1.1.7 root 350:
1.1.1.13 root 351: char mp[MAX_PATH];
1.1.1.7 root 352:
1.1.1.13 root 353: GetModuleFileName (NULL, mp, sizeof (mp));
354: bResult = TCCopyFile (mp, szTmp);
355: }
356: else
357: {
1.1.1.24 root 358: BOOL driver64 = FALSE;
359:
1.1.1.13 root 360: strncpy (curFileName, szFiles[i] + 1, strlen (szFiles[i]) - 1);
361: curFileName [strlen (szFiles[i]) - 1] = 0;
362:
363: if (Is64BitOs ()
364: && strcmp (szFiles[i], "Dtruecrypt.sys") == 0)
365: {
1.1.1.24 root 366: driver64 = TRUE;
1.1.1.13 root 367: strncpy (curFileName, FILENAME_64BIT_DRIVER, sizeof (FILENAME_64BIT_DRIVER));
368: }
369:
370: if (!bDevm)
371: {
372: bResult = FALSE;
373:
374: // Find the correct decompressed file in memory
375: for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++)
376: {
377: // Write the file (stored in memory) directly to the destination location
378: // (there will be no temporary files).
379: if (memcmp (
380: curFileName,
381: Decompressed_Files[fileNo].fileName,
382: min (strlen (curFileName), (size_t) Decompressed_Files[fileNo].fileNameLength)) == 0)
383: {
1.1.1.24 root 384: // Dump filter driver cannot be installed to SysWOW64 directory
385: if (driver64 && !EnableWow64FsRedirection (FALSE))
386: {
387: handleWin32Error (hwndDlg);
388: bResult = FALSE;
389: goto err;
390: }
391:
1.1.1.13 root 392: bResult = SaveBufferToFile (
393: (char *) Decompressed_Files[fileNo].fileContent,
394: szTmp,
395: Decompressed_Files[fileNo].fileLength,
396: FALSE);
397:
1.1.1.24 root 398: if (driver64)
399: {
400: if (!EnableWow64FsRedirection (TRUE))
401: {
402: handleWin32Error (hwndDlg);
403: bResult = FALSE;
404: goto err;
405: }
406:
407: if (!bResult)
408: goto err;
409:
410: if (bUpgrade && InstalledVersion < 0x700)
411: {
412: bResult = WriteLocalMachineRegistryString ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "ImagePath", "System32\\drivers\\truecrypt.sys", TRUE);
413: if (!bResult)
414: {
415: handleWin32Error (hwndDlg);
416: goto err;
417: }
418:
419: DeleteFile (szTmp);
420: }
421: }
422:
1.1.1.13 root 423: break;
424: }
425: }
426: }
427: else
428: {
1.1.1.24 root 429: if (driver64)
430: EnableWow64FsRedirection (FALSE);
431:
1.1.1.13 root 432: bResult = TCCopyFile (curFileName, szTmp);
1.1.1.24 root 433:
434: if (driver64)
435: EnableWow64FsRedirection (TRUE);
1.1.1.13 root 436: }
1.1.1.23 root 437:
438: if (bResult && strcmp (szFiles[i], "ATrueCrypt.exe") == 0)
439: {
440: string servicePath = GetServiceConfigPath (TC_APP_NAME ".exe");
441: if (FileExists (servicePath.c_str()))
442: {
443: CopyMessage (hwndDlg, (char *) servicePath.c_str());
444: bResult = CopyFile (szTmp, servicePath.c_str(), FALSE);
445: }
446: }
1.1 root 447: }
448: }
449: else
450: {
451: bResult = StatDeleteFile (szTmp);
452: }
453:
1.1.1.24 root 454: err:
1.1 root 455: if (bResult == FALSE)
456: {
457: LPVOID lpMsgBuf;
458: DWORD dwError = GetLastError ();
1.1.1.7 root 459: wchar_t szTmp2[700];
1.1 root 460:
461: FormatMessage (
462: FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
463: NULL,
464: dwError,
465: MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
466: (char *) &lpMsgBuf,
467: 0,
468: NULL
469: );
470:
471:
472: if (bUninstall == FALSE)
1.1.1.7 root 473: wsprintfW (szTmp2, GetString ("INSTALL_OF_FAILED"), szTmp, lpMsgBuf);
1.1 root 474: else
1.1.1.7 root 475: wsprintfW (szTmp2, GetString ("UNINSTALL_OF_FAILED"), szTmp, lpMsgBuf);
1.1 root 476:
477: LocalFree (lpMsgBuf);
478:
1.1.1.11 root 479: if (!Silent && MessageBoxW (hwndDlg, szTmp2, lpszTitle, MB_YESNO | MB_ICONHAND) != IDYES)
1.1 root 480: return FALSE;
481: }
1.1.1.7 root 482: }
1.1 root 483:
1.1.1.7 root 484: // Language pack
485: if (bUninstall == FALSE)
486: {
487: WIN32_FIND_DATA f;
1.1.1.8 root 488: HANDLE h;
489:
490: SetCurrentDirectory (SetupFilesDir);
491: h = FindFirstFile ("Language.*.xml", &f);
492:
1.1.1.7 root 493: if (h != INVALID_HANDLE_VALUE)
494: {
495: char d[MAX_PATH*2];
1.1.1.11 root 496: sprintf (d, "%s%s", szDestDir, f.cFileName);
1.1.1.7 root 497: CopyMessage (hwndDlg, d);
498: TCCopyFile (f.cFileName, d);
499: FindClose (h);
500: }
1.1.1.8 root 501:
502: SetCurrentDirectory (SetupFilesDir);
503: SetCurrentDirectory ("Setup files");
504: h = FindFirstFile ("TrueCrypt User Guide.*.pdf", &f);
505: if (h != INVALID_HANDLE_VALUE)
506: {
507: char d[MAX_PATH*2];
1.1.1.11 root 508: sprintf (d, "%s%s", szDestDir, f.cFileName);
1.1.1.8 root 509: CopyMessage (hwndDlg, d);
510: TCCopyFile (f.cFileName, d);
511: FindClose (h);
512: }
513: SetCurrentDirectory (SetupFilesDir);
1.1 root 514: }
515:
516: return bOK;
517: }
518:
1.1.1.18 root 519: BOOL DoRegInstall (HWND hwndDlg, char *szDestDir, BOOL bInstallType)
1.1 root 520: {
521: char szDir[TC_MAX_PATH], *key;
1.1.1.15 root 522: char szTmp[TC_MAX_PATH*4];
1.1 root 523: HKEY hkey = 0;
524: BOOL bSlash, bOK = FALSE;
525: DWORD dw;
526: int x;
527:
1.1.1.19 root 528: if (SystemEncryptionUpgrade)
529: {
530: if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt",
531: 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) == ERROR_SUCCESS)
532: {
533: strcpy (szTmp, VERSION_STRING);
534: RegSetValueEx (hkey, "DisplayVersion", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1);
535:
1.1.1.21 root 536: strcpy (szTmp, TC_HOMEPAGE);
537: RegSetValueEx (hkey, "URLInfoAbout", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1);
538:
1.1.1.19 root 539: RegCloseKey (hkey);
540: }
541:
542: return TRUE;
543: }
544:
1.1 root 545: strcpy (szDir, szDestDir);
546: x = strlen (szDestDir);
547: if (szDestDir[x - 1] == '\\')
548: bSlash = TRUE;
549: else
550: bSlash = FALSE;
551:
552: if (bSlash == FALSE)
553: strcat (szDir, "\\");
554:
1.1.1.7 root 555: if (bInstallType)
1.1 root 556: {
557:
1.1.1.11 root 558: key = "Software\\Classes\\TrueCryptVolume";
1.1 root 559: RegMessage (hwndDlg, key);
560: if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
561: key,
562: 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
563: goto error;
564:
1.1.1.10 root 565: strcpy (szTmp, "TrueCrypt Volume");
1.1 root 566: if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
567: goto error;
568:
1.1.1.22 root 569: sprintf (szTmp, "%ws", TC_APPLICATION_ID);
570: if (RegSetValueEx (hkey, "AppUserModelID", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
571: goto error;
572:
1.1 root 573: RegCloseKey (hkey);
574: hkey = 0;
575:
1.1.1.11 root 576: key = "Software\\Classes\\TrueCryptVolume\\DefaultIcon";
1.1 root 577: RegMessage (hwndDlg, key);
578: if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
579: key,
580: 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
581: goto error;
582:
583: sprintf (szTmp, "%sTrueCrypt.exe,1", szDir);
584: if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
585: goto error;
586:
587: RegCloseKey (hkey);
588: hkey = 0;
589:
1.1.1.11 root 590: key = "Software\\Classes\\TrueCryptVolume\\Shell\\open\\command";
1.1 root 591: RegMessage (hwndDlg, key);
592: if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
593: key,
594: 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
595: goto error;
596:
597: sprintf (szTmp, "\"%sTrueCrypt.exe\" /v \"%%1\"", szDir );
598: if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
599: goto error;
600:
601: RegCloseKey (hkey);
602: hkey = 0;
603:
1.1.1.11 root 604: key = "Software\\Classes\\.tc";
1.1.1.20 root 605: BOOL typeClassChanged = TRUE;
606: char typeClass[256];
607: DWORD typeClassSize = sizeof (typeClass);
608:
609: if (ReadLocalMachineRegistryString (key, "", typeClass, &typeClassSize) && typeClassSize > 0 && strcmp (typeClass, "TrueCryptVolume") == 0)
610: typeClassChanged = FALSE;
611:
1.1 root 612: RegMessage (hwndDlg, key);
613: if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
614: key,
615: 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
616: goto error;
617:
618: strcpy (szTmp, "TrueCryptVolume");
619: if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
620: goto error;
1.1.1.11 root 621:
622: RegCloseKey (hkey);
623: hkey = 0;
1.1.1.20 root 624:
625: if (typeClassChanged)
626: SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
1.1 root 627: }
628:
1.1.1.11 root 629: key = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt";
630: RegMessage (hwndDlg, key);
631: if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
632: key,
633: 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
634: goto error;
1.1 root 635:
1.1.1.13 root 636: /* IMPORTANT: IF YOU CHANGE THIS IN ANY WAY, REVISE AND UPDATE SetInstallationPath() ACCORDINGLY! */
637: sprintf (szTmp, "\"%sTrueCrypt Setup.exe\" /u", szDir);
1.1.1.11 root 638: if (RegSetValueEx (hkey, "UninstallString", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
639: goto error;
1.1 root 640:
1.1.1.13 root 641: sprintf (szTmp, "\"%sTrueCrypt Setup.exe\" /c", szDir);
642: if (RegSetValueEx (hkey, "ModifyPath", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
643: goto error;
644:
1.1.1.11 root 645: sprintf (szTmp, "\"%sTrueCrypt Setup.exe\"", szDir);
646: if (RegSetValueEx (hkey, "DisplayIcon", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
647: goto error;
1.1 root 648:
1.1.1.13 root 649: strcpy (szTmp, VERSION_STRING);
650: if (RegSetValueEx (hkey, "DisplayVersion", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
651: goto error;
652:
1.1.1.11 root 653: strcpy (szTmp, "TrueCrypt");
654: if (RegSetValueEx (hkey, "DisplayName", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
655: goto error;
1.1 root 656:
1.1.1.11 root 657: strcpy (szTmp, "TrueCrypt Foundation");
658: if (RegSetValueEx (hkey, "Publisher", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
659: goto error;
1.1 root 660:
1.1.1.21 root 661: strcpy (szTmp, TC_HOMEPAGE);
1.1.1.11 root 662: if (RegSetValueEx (hkey, "URLInfoAbout", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
663: goto error;
1.1.1.24 root 664:
1.1 root 665: bOK = TRUE;
666:
1.1.1.11 root 667: error:
1.1 root 668: if (hkey != 0)
669: RegCloseKey (hkey);
670:
671: if (bOK == FALSE)
672: {
673: handleWin32Error (hwndDlg);
1.1.1.11 root 674: Error ("REG_INSTALL_FAILED");
675: }
676:
677: // Register COM servers for UAC
1.1.1.20 root 678: if (IsOSAtLeast (WIN_VISTA))
1.1.1.11 root 679: {
680: if (!RegisterComServers (szDir))
681: {
682: Error ("COM_REG_FAILED");
683: return FALSE;
684: }
1.1 root 685: }
686:
687: return bOK;
688: }
689:
1.1.1.18 root 690: BOOL DoApplicationDataUninstall (HWND hwndDlg)
1.1.1.7 root 691: {
692: char path[MAX_PATH];
693: char path2[MAX_PATH];
694: BOOL bOK = TRUE;
695:
696: StatusMessage (hwndDlg, "REMOVING_APPDATA");
697:
698: SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path);
699: strcat (path, "\\TrueCrypt\\");
700:
701: // Delete favorite volumes file
1.1.1.18 root 702: sprintf (path2, "%s%s", path, TC_APPD_FILENAME_FAVORITE_VOLUMES);
1.1.1.7 root 703: RemoveMessage (hwndDlg, path2);
704: StatDeleteFile (path2);
705:
706: // Delete keyfile defaults
1.1.1.18 root 707: sprintf (path2, "%s%s", path, TC_APPD_FILENAME_DEFAULT_KEYFILES);
1.1.1.7 root 708: RemoveMessage (hwndDlg, path2);
709: StatDeleteFile (path2);
710:
711: // Delete history file
1.1.1.18 root 712: sprintf (path2, "%s%s", path, TC_APPD_FILENAME_HISTORY);
1.1.1.7 root 713: RemoveMessage (hwndDlg, path2);
714: StatDeleteFile (path2);
715:
716: // Delete configuration file
1.1.1.18 root 717: sprintf (path2, "%s%s", path, TC_APPD_FILENAME_CONFIGURATION);
1.1.1.7 root 718: RemoveMessage (hwndDlg, path2);
719: StatDeleteFile (path2);
720:
1.1.1.13 root 721: // Delete system encryption configuration file
1.1.1.18 root 722: sprintf (path2, "%s%s", path, TC_APPD_FILENAME_SYSTEM_ENCRYPTION);
1.1.1.13 root 723: RemoveMessage (hwndDlg, path2);
724: StatDeleteFile (path2);
725:
1.1.1.7 root 726: SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path);
727: strcat (path, "\\TrueCrypt");
728: RemoveMessage (hwndDlg, path);
729: if (!StatRemoveDirectory (path))
730: {
731: handleWin32Error (hwndDlg);
732: bOK = FALSE;
733: }
734:
735: return bOK;
736: }
737:
1.1.1.18 root 738: BOOL DoRegUninstall (HWND hwndDlg, BOOL bRemoveDeprecated)
1.1 root 739: {
740: BOOL bOK = FALSE;
1.1.1.7 root 741: char regk [64];
1.1 root 742:
1.1.1.11 root 743: // Unregister COM servers
1.1.1.20 root 744: if (!bRemoveDeprecated && IsOSAtLeast (WIN_VISTA))
1.1.1.11 root 745: {
1.1.1.13 root 746: if (!UnregisterComServers (InstallationPath))
1.1.1.11 root 747: StatusMessage (hwndDlg, "COM_DEREG_FAILED");
748: }
749:
750: if (!bRemoveDeprecated)
751: StatusMessage (hwndDlg, "REMOVING_REG");
1.1 root 752:
1.1.1.11 root 753: RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt");
754: RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\Shell\\open\\command");
755: RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\Shell\\open");
756: RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\Shell");
757: RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\DefaultIcon");
758: RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume");
759: RegDeleteKey (HKEY_CURRENT_USER, "Software\\TrueCrypt");
1.1.1.7 root 760:
761: if (!bRemoveDeprecated)
762: {
1.1.1.24 root 763: GetStartupRegKeyName (regk);
1.1.1.7 root 764: DeleteRegistryValue (regk, "TrueCrypt");
765:
1.1.1.11 root 766: RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\.tc");
1.1.1.20 root 767: SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
1.1.1.7 root 768: }
1.1 root 769:
770: bOK = TRUE;
771:
772: if (bOK == FALSE && GetLastError ()!= ERROR_NO_TOKEN && GetLastError ()!= ERROR_FILE_NOT_FOUND
773: && GetLastError ()!= ERROR_PATH_NOT_FOUND)
774: {
775: handleWin32Error (hwndDlg);
776: }
777: else
778: bOK = TRUE;
779:
780: return bOK;
781: }
782:
1.1.1.11 root 783:
1.1.1.18 root 784: BOOL DoServiceUninstall (HWND hwndDlg, char *lpszService)
1.1 root 785: {
786: SC_HANDLE hManager, hService = NULL;
787: BOOL bOK = FALSE, bRet;
788: SERVICE_STATUS status;
1.1.1.6 root 789: BOOL firstTry = TRUE;
1.1 root 790: int x;
791:
1.1.1.6 root 792: memset (&status, 0, sizeof (status)); /* Keep VC6 quiet */
793:
794: retry:
1.1 root 795:
796: hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
797: if (hManager == NULL)
798: goto error;
799:
800: hService = OpenService (hManager, lpszService, SERVICE_ALL_ACCESS);
801: if (hService == NULL)
802: goto error;
803:
1.1.1.7 root 804: if (strcmp ("truecrypt", lpszService) == 0)
1.1.1.19 root 805: {
1.1.1.20 root 806: try
1.1.1.19 root 807: {
1.1.1.20 root 808: BootEncryption bootEnc (hwndDlg);
809: if (bootEnc.GetDriverServiceStartType() == SERVICE_BOOT_START)
810: {
1.1.1.24 root 811: try { bootEnc.RegisterFilterDriver (false, BootEncryption::DriveFilter); } catch (...) { }
812: try { bootEnc.RegisterFilterDriver (false, BootEncryption::VolumeFilter); } catch (...) { }
813: try { bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter); } catch (...) { }
1.1.1.20 root 814: }
1.1.1.19 root 815: }
1.1.1.20 root 816: catch (...) { }
1.1.1.19 root 817:
1.1.1.7 root 818: StatusMessage (hwndDlg, "STOPPING_DRIVER");
1.1.1.19 root 819: }
1.1.1.7 root 820: else
821: StatusMessageParam (hwndDlg, "STOPPING", lpszService);
1.1 root 822:
823: #define WAIT_PERIOD 3
824:
825: for (x = 0; x < WAIT_PERIOD; x++)
826: {
827: bRet = QueryServiceStatus (hService, &status);
828: if (bRet != TRUE)
829: goto error;
830:
831: if (status.dwCurrentState != SERVICE_START_PENDING &&
832: status.dwCurrentState != SERVICE_STOP_PENDING &&
833: status.dwCurrentState != SERVICE_CONTINUE_PENDING)
834: break;
835:
836: Sleep (1000);
837: }
838:
839: if (status.dwCurrentState != SERVICE_STOPPED)
840: {
841: bRet = ControlService (hService, SERVICE_CONTROL_STOP, &status);
842: if (bRet == FALSE)
843: goto try_delete;
844:
845: for (x = 0; x < WAIT_PERIOD; x++)
846: {
847: bRet = QueryServiceStatus (hService, &status);
848: if (bRet != TRUE)
849: goto error;
850:
851: if (status.dwCurrentState != SERVICE_START_PENDING &&
852: status.dwCurrentState != SERVICE_STOP_PENDING &&
853: status.dwCurrentState != SERVICE_CONTINUE_PENDING)
854: break;
855:
856: Sleep (1000);
857: }
858:
859: if (status.dwCurrentState != SERVICE_STOPPED && status.dwCurrentState != SERVICE_STOP_PENDING)
860: goto error;
861: }
862:
1.1.1.6 root 863: try_delete:
864:
1.1.1.7 root 865: if (strcmp ("truecrypt", lpszService) == 0)
866: StatusMessage (hwndDlg, "REMOVING_DRIVER");
867: else
868: StatusMessageParam (hwndDlg, "REMOVING", lpszService);
1.1 root 869:
870: if (hService != NULL)
871: CloseServiceHandle (hService);
872:
873: if (hManager != NULL)
874: CloseServiceHandle (hManager);
875:
876: hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
877: if (hManager == NULL)
878: goto error;
879:
880: hService = OpenService (hManager, lpszService, SERVICE_ALL_ACCESS);
881: if (hService == NULL)
882: goto error;
883:
884: bRet = DeleteService (hService);
885: if (bRet == FALSE)
1.1.1.6 root 886: {
887: if (firstTry && GetLastError () == ERROR_SERVICE_MARKED_FOR_DELETE)
888: {
889: // Second try for an eventual no-install driver instance
890: CloseServiceHandle (hService);
891: CloseServiceHandle (hManager);
892:
893: Sleep(1000);
894: firstTry = FALSE;
895: goto retry;
896: }
897:
1.1 root 898: goto error;
1.1.1.6 root 899: }
1.1 root 900:
901: bOK = TRUE;
902:
1.1.1.6 root 903: error:
904:
1.1 root 905: if (bOK == FALSE && GetLastError ()!= ERROR_SERVICE_DOES_NOT_EXIST)
906: {
907: handleWin32Error (hwndDlg);
1.1.1.7 root 908: MessageBoxW (hwndDlg, GetString ("DRIVER_UINSTALL_FAILED"), lpszTitle, MB_ICONHAND);
1.1 root 909: }
910: else
911: bOK = TRUE;
912:
913: if (hService != NULL)
914: CloseServiceHandle (hService);
915:
916: if (hManager != NULL)
917: CloseServiceHandle (hManager);
918:
919: return bOK;
920: }
921:
1.1.1.7 root 922:
1.1.1.15 root 923: BOOL DoDriverUnload (HWND hwndDlg)
1.1 root 924: {
925: BOOL bOK = TRUE;
926: int status;
927:
928: status = DriverAttach ();
929: if (status != 0)
930: {
1.1.1.11 root 931: if (status == ERR_OS_ERROR && GetLastError () != ERROR_FILE_NOT_FOUND)
1.1 root 932: {
933: handleWin32Error (hwndDlg);
1.1.1.7 root 934: AbortProcess ("NODRIVER");
1.1 root 935: }
936:
937: if (status != ERR_OS_ERROR)
938: {
939: handleError (NULL, status);
1.1.1.7 root 940: AbortProcess ("NODRIVER");
1.1 root 941: }
942: }
943:
944: if (hDriver != INVALID_HANDLE_VALUE)
945: {
1.1.1.3 root 946: MOUNT_LIST_STRUCT driver;
1.1.1.11 root 947: LONG driverVersion = VERSION_NUM;
1.1.1.7 root 948: int refCount;
1.1.1.3 root 949: DWORD dwResult;
950: BOOL bResult;
1.1.1.13 root 951:
1.1.1.14 root 952: // Try to determine if it's upgrade (and not reinstall, downgrade, or first-time install).
1.1.1.22 root 953: DetermineUpgradeDowngradeStatus (FALSE, &driverVersion);
1.1.1.14 root 954:
1.1.1.13 root 955: // Test for encrypted boot drive
956: try
957: {
958: BootEncryption bootEnc (hwndDlg);
959: if (bootEnc.GetDriverServiceStartType() == SERVICE_BOOT_START)
960: {
1.1.1.17 root 961: try
962: {
963: // Check hidden OS update consistency
964: if (IsHiddenOSRunning())
965: {
966: if (bootEnc.GetInstalledBootLoaderVersion() != VERSION_NUM)
967: {
968: if (AskWarnNoYes ("UPDATE_TC_IN_DECOY_OS_FIRST") == IDNO)
969: AbortProcessSilent ();
970: }
971: }
972: }
973: catch (...) { }
974:
1.1.1.19 root 975: if (bUninstallInProgress && driverVersion >= 0x500 && !bootEnc.GetStatus().DriveMounted)
1.1.1.15 root 976: {
1.1.1.24 root 977: try { bootEnc.RegisterFilterDriver (false, BootEncryption::DriveFilter); } catch (...) { }
978: try { bootEnc.RegisterFilterDriver (false, BootEncryption::VolumeFilter); } catch (...) { }
979: try { bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter); } catch (...) { }
1.1.1.15 root 980: bootEnc.SetDriverServiceStartType (SERVICE_SYSTEM_START);
981: }
1.1.1.19 root 982: else if (bUninstallInProgress || bDowngrade)
1.1.1.14 root 983: {
1.1.1.22 root 984: Error (bDowngrade ? "SETUP_FAILED_BOOT_DRIVE_ENCRYPTED_DOWNGRADE" : "SETUP_FAILED_BOOT_DRIVE_ENCRYPTED");
1.1.1.14 root 985: return FALSE;
986: }
1.1.1.15 root 987: else
988: {
1.1.1.24 root 989: if (CurrentOSMajor == 6 && CurrentOSMinor == 0 && CurrentOSServicePack < 1)
990: AbortProcess ("SYS_ENCRYPTION_UPGRADE_UNSUPPORTED_ON_VISTA_SP0");
1.1.1.20 root 991:
1.1.1.15 root 992: SystemEncryptionUpgrade = TRUE;
1.1.1.24 root 993: PortableMode = FALSE;
1.1.1.15 root 994: }
1.1.1.13 root 995: }
996: }
997: catch (...) { }
1.1 root 998:
1.1.1.22 root 999: if (!bUninstall
1000: && (bUpgrade || SystemEncryptionUpgrade)
1001: && (!bDevm || SystemEncryptionUpgrade))
1002: {
1003: UnloadDriver = FALSE;
1004: }
1005:
1.1.1.24 root 1006: if (PortableMode && !SystemEncryptionUpgrade)
1007: UnloadDriver = TRUE;
1008:
1.1.1.22 root 1009: if (UnloadDriver)
1.1.1.14 root 1010: {
1.1.1.20 root 1011: int volumesMounted = 0;
1012:
1.1.1.14 root 1013: // Check mounted volumes
1014: bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL);
1.1.1.13 root 1015:
1.1.1.14 root 1016: if (!bResult)
1017: {
1018: bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL);
1019: if (bResult)
1020: volumesMounted = driver.ulMountedDrives;
1021: }
1.1.1.13 root 1022:
1023: if (bResult)
1.1.1.14 root 1024: {
1025: if (volumesMounted != 0)
1026: {
1027: bOK = FALSE;
1028: MessageBoxW (hwndDlg, GetString ("DISMOUNT_ALL_FIRST"), lpszTitle, MB_ICONHAND);
1029: }
1030: }
1031: else
1.1 root 1032: {
1033: bOK = FALSE;
1.1.1.14 root 1034: handleWin32Error (hwndDlg);
1.1 root 1035: }
1036: }
1.1.1.14 root 1037:
1.1.1.7 root 1038: // Try to close all open TC windows
1.1.1.11 root 1039: if (bOK)
1.1.1.7 root 1040: {
1041: BOOL TCWindowClosed = FALSE;
1.1.1.11 root 1042:
1.1.1.7 root 1043: EnumWindows (CloseTCWindowsEnum, (LPARAM) &TCWindowClosed);
1.1.1.11 root 1044:
1045: if (TCWindowClosed)
1046: Sleep (2000);
1.1.1.7 root 1047: }
1048:
1049: // Test for any applications attached to driver
1.1.1.23 root 1050: if (!bUpgrade)
1.1.1.7 root 1051: {
1.1.1.23 root 1052: bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount,
1053: sizeof (refCount), &dwResult, NULL);
1054:
1055: if (bOK && bResult && refCount > 1)
1056: {
1057: MessageBoxW (hwndDlg, GetString ("CLOSE_TC_FIRST"), lpszTitle, MB_ICONSTOP);
1058: bOK = FALSE;
1059: }
1.1.1.7 root 1060: }
1.1 root 1061:
1.1.1.22 root 1062: if (!bOK || UnloadDriver)
1.1.1.14 root 1063: {
1064: CloseHandle (hDriver);
1065: hDriver = INVALID_HANDLE_VALUE;
1066: }
1.1 root 1067: }
1.1.1.11 root 1068: else
1069: {
1.1.1.25! root 1070: // Note that the driver may have already been unloaded during this session (e.g. retry after an error, etc.) so it is not
! 1071: // guaranteed that the user is installing TrueCrypt for the first time now (we also cannot know if the user has already
! 1072: // installed and used TrueCrypt on another system before).
! 1073: bPossiblyFirstTimeInstall = TRUE;
1.1.1.11 root 1074: }
1.1 root 1075:
1076: return bOK;
1077: }
1078:
1079:
1.1.1.14 root 1080: BOOL UpgradeBootLoader (HWND hwndDlg)
1081: {
1082: if (!SystemEncryptionUpgrade)
1083: return TRUE;
1084:
1085: try
1086: {
1087: BootEncryption bootEnc (hwndDlg);
1088: if (bootEnc.GetInstalledBootLoaderVersion() < VERSION_NUM)
1089: {
1.1.1.17 root 1090: StatusMessage (hwndDlg, "INSTALLER_UPDATING_BOOT_LOADER");
1091:
1.1.1.18 root 1092: bootEnc.InstallBootLoader (true);
1.1.1.22 root 1093:
1094: if (bootEnc.GetInstalledBootLoaderVersion() <= TC_RESCUE_DISK_UPGRADE_NOTICE_MAX_VERSION)
1095: Info (IsHiddenOSRunning() ? "BOOT_LOADER_UPGRADE_OK_HIDDEN_OS" : "BOOT_LOADER_UPGRADE_OK");
1.1.1.14 root 1096: }
1097: return TRUE;
1098: }
1099: catch (Exception &e)
1100: {
1101: e.Show (hwndDlg);
1102: }
1103: catch (...) { }
1104:
1105: Error ("BOOT_LOADER_UPGRADE_FAILED");
1106: return FALSE;
1107: }
1108:
1109:
1.1.1.15 root 1110: BOOL DoShortcutsUninstall (HWND hwndDlg, char *szDestDir)
1.1 root 1111: {
1.1.1.11 root 1112: char szLinkDir[TC_MAX_PATH];
1.1.1.7 root 1113: char szTmp2[TC_MAX_PATH];
1.1 root 1114: BOOL bSlash, bOK = FALSE;
1115: HRESULT hOle;
1116: int x;
1117: BOOL allUsers = FALSE;
1118:
1119: hOle = OleInitialize (NULL);
1120:
1121: // User start menu
1122: SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_PROGRAMS, 0);
1123: x = strlen (szLinkDir);
1124: if (szLinkDir[x - 1] == '\\')
1125: bSlash = TRUE;
1126: else
1127: bSlash = FALSE;
1128:
1129: if (bSlash == FALSE)
1130: strcat (szLinkDir, "\\");
1131:
1132: strcat (szLinkDir, "TrueCrypt");
1133:
1134: // Global start menu
1135: {
1136: struct _stat st;
1137: char path[TC_MAX_PATH];
1138:
1139: SHGetSpecialFolderPath (hwndDlg, path, CSIDL_COMMON_PROGRAMS, 0);
1140: strcat (path, "\\TrueCrypt");
1141:
1142: if (_stat (path, &st) == 0)
1143: {
1144: strcpy (szLinkDir, path);
1145: allUsers = TRUE;
1146: }
1147: }
1148:
1149: // Start menu entries
1150: sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk");
1151: RemoveMessage (hwndDlg, szTmp2);
1152: if (StatDeleteFile (szTmp2) == FALSE)
1153: goto error;
1154:
1.1.1.11 root 1155: sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt Website.url");
1.1 root 1156: RemoveMessage (hwndDlg, szTmp2);
1157: if (StatDeleteFile (szTmp2) == FALSE)
1158: goto error;
1159:
1160: sprintf (szTmp2, "%s%s", szLinkDir, "\\Uninstall TrueCrypt.lnk");
1161: RemoveMessage (hwndDlg, szTmp2);
1162: if (StatDeleteFile (szTmp2) == FALSE)
1163: goto error;
1.1.1.11 root 1164:
1165: sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt User's Guide.lnk");
1166: DeleteFile (szTmp2);
1.1 root 1167:
1168: // Start menu group
1169: RemoveMessage ((HWND) hwndDlg, szLinkDir);
1170: if (StatRemoveDirectory (szLinkDir) == FALSE)
1171: handleWin32Error ((HWND) hwndDlg);
1172:
1173: // Desktop icon
1174:
1175: if (allUsers)
1176: SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_COMMON_DESKTOPDIRECTORY, 0);
1177: else
1178: SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_DESKTOPDIRECTORY, 0);
1179:
1180: sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk");
1181:
1182: RemoveMessage (hwndDlg, szTmp2);
1183: if (StatDeleteFile (szTmp2) == FALSE)
1184: goto error;
1185:
1186: bOK = TRUE;
1187:
1188: error:
1189: OleUninitialize ();
1190:
1191: return bOK;
1192: }
1193:
1.1.1.18 root 1194: BOOL DoShortcutsInstall (HWND hwndDlg, char *szDestDir, BOOL bProgGroup, BOOL bDesktopIcon)
1.1 root 1195: {
1196: char szLinkDir[TC_MAX_PATH], szDir[TC_MAX_PATH];
1.1.1.7 root 1197: char szTmp[TC_MAX_PATH], szTmp2[TC_MAX_PATH], szTmp3[TC_MAX_PATH];
1.1 root 1198: BOOL bSlash, bOK = FALSE;
1199: HRESULT hOle;
1200: int x;
1201:
1202: if (bProgGroup == FALSE && bDesktopIcon == FALSE)
1203: return TRUE;
1204:
1205: hOle = OleInitialize (NULL);
1206:
1207: GetProgramPath (hwndDlg, szLinkDir);
1208:
1209: x = strlen (szLinkDir);
1210: if (szLinkDir[x - 1] == '\\')
1211: bSlash = TRUE;
1212: else
1213: bSlash = FALSE;
1214:
1215: if (bSlash == FALSE)
1216: strcat (szLinkDir, "\\");
1217:
1218: strcat (szLinkDir, "TrueCrypt");
1219:
1220: strcpy (szDir, szDestDir);
1221: x = strlen (szDestDir);
1222: if (szDestDir[x - 1] == '\\')
1223: bSlash = TRUE;
1224: else
1225: bSlash = FALSE;
1226:
1227: if (bSlash == FALSE)
1228: strcat (szDir, "\\");
1229:
1230: if (bProgGroup)
1231: {
1.1.1.11 root 1232: FILE *f;
1233:
1.1 root 1234: if (mkfulldir (szLinkDir, TRUE) != 0)
1235: {
1236: if (mkfulldir (szLinkDir, FALSE) != 0)
1237: {
1.1.1.13 root 1238: wchar_t szTmp[TC_MAX_PATH];
1239:
1.1 root 1240: handleWin32Error (hwndDlg);
1.1.1.7 root 1241: wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), szLinkDir);
1242: MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND);
1.1 root 1243: goto error;
1244: }
1245: }
1246:
1247: sprintf (szTmp, "%s%s", szDir, "TrueCrypt.exe");
1248: sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk");
1249:
1250: IconMessage (hwndDlg, szTmp2);
1251: if (CreateLink (szTmp, "", szTmp2) != S_OK)
1252: goto error;
1253:
1.1.1.11 root 1254: sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt Website.url");
1.1 root 1255: IconMessage (hwndDlg, szTmp2);
1.1.1.11 root 1256: f = fopen (szTmp2, "w");
1257: if (f)
1258: {
1.1.1.21 root 1259: fprintf (f, "[InternetShortcut]\nURL=%s\n", TC_HOMEPAGE);
1.1.1.24 root 1260:
1261: CheckFileStreamWriteErrors (f, szTmp2);
1.1.1.11 root 1262: fclose (f);
1263: }
1.1 root 1264: else
1.1.1.11 root 1265: goto error;
1.1 root 1266:
1267: sprintf (szTmp, "%s%s", szDir, "TrueCrypt Setup.exe");
1268: sprintf (szTmp2, "%s%s", szLinkDir, "\\Uninstall TrueCrypt.lnk");
1.1.1.13 root 1269: strcpy (szTmp3, "/u");
1.1 root 1270:
1271: IconMessage (hwndDlg, szTmp2);
1.1.1.7 root 1272: if (CreateLink (szTmp, szTmp3, szTmp2) != S_OK)
1.1 root 1273: goto error;
1274:
1.1.1.11 root 1275: sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt User's Guide.lnk");
1276: DeleteFile (szTmp2);
1.1 root 1277: }
1278:
1279: if (bDesktopIcon)
1280: {
1281: strcpy (szDir, szDestDir);
1282: x = strlen (szDestDir);
1283: if (szDestDir[x - 1] == '\\')
1284: bSlash = TRUE;
1285: else
1286: bSlash = FALSE;
1287:
1288: if (bSlash == FALSE)
1289: strcat (szDir, "\\");
1290:
1.1.1.13 root 1291: if (bForAllUsers)
1.1 root 1292: SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_COMMON_DESKTOPDIRECTORY, 0);
1293: else
1294: SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_DESKTOPDIRECTORY, 0);
1295:
1296: sprintf (szTmp, "%s%s", szDir, "TrueCrypt.exe");
1297: sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk");
1298:
1299: IconMessage (hwndDlg, szTmp2);
1300:
1301: if (CreateLink (szTmp, "", szTmp2) != S_OK)
1302: goto error;
1303: }
1304:
1305: bOK = TRUE;
1306:
1307: error:
1308: OleUninitialize ();
1309:
1310: return bOK;
1311: }
1312:
1313:
1.1.1.18 root 1314: void OutcomePrompt (HWND hwndDlg, BOOL bOK)
1.1 root 1315: {
1.1.1.7 root 1316: if (bOK)
1.1 root 1317: {
1318: EnableWindow (GetDlgItem ((HWND) hwndDlg, IDCANCEL), FALSE);
1319:
1320: bDone = TRUE;
1321:
1.1.1.7 root 1322: if (bUninstall == FALSE)
1.1.1.13 root 1323: {
1.1.1.25! root 1324: if (!DonEnabled || DonPagePos != 4)
! 1325: {
! 1326: if (bDevm)
! 1327: PostMessage (MainDlg, WM_CLOSE, 0, 0);
! 1328: else if (bPossiblyFirstTimeInstall && !SystemEncryptionUpgrade && !bUpgrade && !bDowngrade && !bRepairMode)
! 1329: Info ("INSTALL_OK");
! 1330: else if (!bRestartRequired || (DonEnabled && DonPagePos == 3))
! 1331: Info ("SETUP_UPDATE_OK");
! 1332: }
1.1.1.13 root 1333: }
1.1 root 1334: else
1.1.1.11 root 1335: {
1336: wchar_t str[4096];
1337:
1.1.1.13 root 1338: swprintf (str, GetString ("UNINSTALL_OK"), InstallationPath);
1.1.1.11 root 1339: MessageBoxW (hwndDlg, str, lpszTitle, MB_ICONASTERISK);
1340: }
1.1 root 1341: }
1342: else
1343: {
1344: if (bUninstall == FALSE)
1.1.1.11 root 1345: Error ("INSTALL_FAILED");
1.1 root 1346: else
1.1.1.11 root 1347: Error ("UNINSTALL_FAILED");
1.1 root 1348: }
1349: }
1350:
1.1.1.13 root 1351: static void SetSystemRestorePoint (HWND hwndDlg, BOOL finalize)
1.1 root 1352: {
1353: static RESTOREPOINTINFO RestPtInfo;
1354: static STATEMGRSTATUS SMgrStatus;
1355: static BOOL failed = FALSE;
1356: static BOOL (__stdcall *_SRSetRestorePoint)(PRESTOREPOINTINFO, PSTATEMGRSTATUS);
1357:
1358: if (!SystemRestoreDll) return;
1359:
1360: _SRSetRestorePoint = (BOOL (__stdcall *)(PRESTOREPOINTINFO, PSTATEMGRSTATUS))GetProcAddress (SystemRestoreDll,"SRSetRestorePointA");
1361: if (_SRSetRestorePoint == 0)
1362: {
1363: FreeLibrary (SystemRestoreDll);
1364: SystemRestoreDll = 0;
1365: return;
1366: }
1367:
1368: if (!finalize)
1369: {
1.1.1.7 root 1370: StatusMessage (hwndDlg, "CREATING_SYS_RESTORE");
1.1 root 1371:
1372: RestPtInfo.dwEventType = BEGIN_SYSTEM_CHANGE;
1.1.1.24 root 1373: RestPtInfo.dwRestorePtType = bUninstall ? APPLICATION_UNINSTALL : APPLICATION_INSTALL | DEVICE_DRIVER_INSTALL;
1.1 root 1374: RestPtInfo.llSequenceNumber = 0;
1.1.1.13 root 1375: strcpy (RestPtInfo.szDescription, bUninstall ? "TrueCrypt uninstallation" : "TrueCrypt installation");
1.1 root 1376:
1.1.1.7 root 1377: if(!_SRSetRestorePoint (&RestPtInfo, &SMgrStatus))
1.1 root 1378: {
1.1.1.7 root 1379: StatusMessage (hwndDlg, "FAILED_SYS_RESTORE");
1.1 root 1380: failed = TRUE;
1381: }
1382: }
1.1.1.11 root 1383: else if (!failed)
1.1 root 1384: {
1.1.1.11 root 1385: RestPtInfo.dwEventType = END_SYSTEM_CHANGE;
1386: RestPtInfo.llSequenceNumber = SMgrStatus.llSequenceNumber;
1387:
1388: if(!_SRSetRestorePoint(&RestPtInfo, &SMgrStatus))
1389: {
1390: StatusMessage (hwndDlg, "FAILED_SYS_RESTORE");
1391: }
1.1 root 1392: }
1393: }
1394:
1.1.1.18 root 1395: void DoUninstall (void *arg)
1.1 root 1396: {
1.1.1.13 root 1397: HWND hwndDlg = (HWND) arg;
1.1 root 1398: BOOL bOK = TRUE;
1.1.1.13 root 1399: BOOL bTempSkipSysRestore = FALSE;
1.1 root 1400:
1.1.1.11 root 1401: if (!Rollback)
1402: EnableWindow (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), FALSE);
1.1 root 1403:
1404: WaitCursor ();
1405:
1.1.1.11 root 1406: if (!Rollback)
1.1 root 1407: {
1.1.1.13 root 1408: ClearLogWindow (hwndDlg);
1.1 root 1409: }
1.1.1.13 root 1410:
1411: if (DoDriverUnload (hwndDlg) == FALSE)
1.1.1.7 root 1412: {
1413: bOK = FALSE;
1.1.1.13 root 1414: bTempSkipSysRestore = TRUE; // Volumes are possibly mounted; defer System Restore point creation for this uninstall attempt.
1.1.1.7 root 1415: }
1.1 root 1416: else
1417: {
1.1.1.13 root 1418: if (!Rollback && bSystemRestore && !bTempSkipSysRestore)
1419: SetSystemRestorePoint (hwndDlg, FALSE);
1.1.1.11 root 1420:
1.1.1.13 root 1421: if (DoServiceUninstall (hwndDlg, "truecrypt") == FALSE)
1422: {
1.1.1.11 root 1423: bOK = FALSE;
1.1.1.13 root 1424: }
1425: else if (DoRegUninstall ((HWND) hwndDlg, FALSE) == FALSE)
1426: {
1427: bOK = FALSE;
1428: }
1429: else if (DoFilesInstall ((HWND) hwndDlg, InstallationPath) == FALSE)
1430: {
1431: bOK = FALSE;
1432: }
1433: else if (DoShortcutsUninstall (hwndDlg, InstallationPath) == FALSE)
1434: {
1435: bOK = FALSE;
1436: }
1437: else if (!DoApplicationDataUninstall (hwndDlg))
1438: {
1439: bOK = FALSE;
1440: }
1.1.1.11 root 1441: else
1.1 root 1442: {
1.1.1.13 root 1443: char temp[MAX_PATH];
1444: FILE *f;
1445:
1446: // Deprecated service
1447: DoServiceUninstall (hwndDlg, "TrueCryptService");
1448:
1449: GetTempPath (sizeof (temp), temp);
1450: _snprintf (UninstallBatch, sizeof (UninstallBatch), "%s\\TrueCrypt-Uninstall.bat", temp);
1451:
1.1.1.15 root 1452: UninstallBatch [sizeof(UninstallBatch)-1] = 0;
1453:
1.1.1.13 root 1454: // Create uninstall batch
1455: f = fopen (UninstallBatch, "w");
1456: if (!f)
1457: bOK = FALSE;
1458: else
1459: {
1460: fprintf (f, ":loop\n"
1461: "del \"%s%s\"\n"
1462: "if exist \"%s%s\" goto loop\n"
1463: "rmdir \"%s\"\n"
1464: "del \"%s\"",
1465: InstallationPath, "TrueCrypt Setup.exe",
1466: InstallationPath, "TrueCrypt Setup.exe",
1467: InstallationPath,
1468: UninstallBatch
1469: );
1.1.1.24 root 1470:
1471: CheckFileStreamWriteErrors (f, UninstallBatch);
1.1.1.13 root 1472: fclose (f);
1473: }
1.1 root 1474: }
1475: }
1476:
1477: NormalCursor ();
1478:
1.1.1.11 root 1479: if (Rollback)
1480: return;
1481:
1.1.1.13 root 1482: if (bSystemRestore && !bTempSkipSysRestore)
1483: SetSystemRestorePoint (hwndDlg, TRUE);
1484:
1.1.1.7 root 1485: if (bOK)
1.1.1.13 root 1486: PostMessage (hwndDlg, TC_APPMSG_UNINSTALL_SUCCESS, 0, 0);
1487: else
1488: bUninstallInProgress = FALSE;
1489:
1.1.1.7 root 1490: EnableWindow (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), TRUE);
1.1.1.11 root 1491: OutcomePrompt (hwndDlg, bOK);
1.1 root 1492: }
1493:
1.1.1.18 root 1494: void DoInstall (void *arg)
1.1 root 1495: {
1.1.1.13 root 1496: HWND hwndDlg = (HWND) arg;
1.1 root 1497: BOOL bOK = TRUE;
1.1.1.11 root 1498: char path[MAX_PATH];
1.1 root 1499:
1.1.1.17 root 1500: BootEncryption bootEnc (hwndDlg);
1501:
1.1.1.13 root 1502: // Refresh the main GUI (wizard thread)
1.1.1.24 root 1503: InvalidateRect (MainDlg, NULL, TRUE);
1.1.1.13 root 1504:
1.1.1.24 root 1505: ClearLogWindow (hwndDlg);
1.1.1.13 root 1506:
1507: if (mkfulldir (InstallationPath, TRUE) != 0)
1508: {
1509: if (mkfulldir (InstallationPath, FALSE) != 0)
1510: {
1511: wchar_t szTmp[TC_MAX_PATH];
1512:
1513: handleWin32Error (hwndDlg);
1514: wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), InstallationPath);
1515: MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND);
1516: Error ("INSTALL_FAILED");
1517: PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0);
1518: return;
1519: }
1520: }
1521:
1522: UpdateProgressBarProc(2);
1.1 root 1523:
1524: if (DoDriverUnload (hwndDlg) == FALSE)
1525: {
1.1.1.4 root 1526: NormalCursor ();
1.1.1.13 root 1527: PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0);
1.1.1.4 root 1528: return;
1.1 root 1529: }
1.1.1.13 root 1530:
1.1.1.23 root 1531: if (bUpgrade
1532: && (IsFileInUse (string (InstallationPath) + '\\' + TC_APP_NAME ".exe")
1533: || IsFileInUse (string (InstallationPath) + '\\' + TC_APP_NAME " Format.exe")
1534: || IsFileInUse (string (InstallationPath) + '\\' + TC_APP_NAME " Setup.exe")
1535: )
1536: )
1537: {
1538: NormalCursor ();
1539: Error ("CLOSE_TC_FIRST");
1540: PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0);
1541: return;
1542: }
1543:
1.1.1.13 root 1544: UpdateProgressBarProc(12);
1.1.1.4 root 1545:
1.1.1.13 root 1546: if (bSystemRestore)
1.1.1.4 root 1547: SetSystemRestorePoint (hwndDlg, FALSE);
1548:
1.1.1.17 root 1549: UpdateProgressBarProc(48);
1550:
1551: if (bDisableSwapFiles
1.1.1.18 root 1552: && IsPagingFileActive (FALSE))
1.1.1.17 root 1553: {
1554: if (!DisablePagingFile())
1555: {
1556: handleWin32Error (hwndDlg);
1557: Error ("FAILED_TO_DISABLE_PAGING_FILES");
1558: }
1559: else
1560: bRestartRequired = TRUE;
1561: }
1562:
1.1.1.13 root 1563: UpdateProgressBarProc(50);
1564:
1.1.1.11 root 1565: // Remove deprecated
1.1.1.7 root 1566: DoServiceUninstall (hwndDlg, "TrueCryptService");
1.1.1.11 root 1567:
1.1.1.13 root 1568: UpdateProgressBarProc(55);
1569:
1.1.1.14 root 1570: if (!SystemEncryptionUpgrade)
1571: DoRegUninstall ((HWND) hwndDlg, TRUE);
1.1.1.7 root 1572:
1.1.1.24 root 1573: if (SystemEncryptionUpgrade && InstalledVersion < 0x700)
1574: {
1575: try
1576: {
1577: bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter);
1578: }
1579: catch (...) { }
1580:
1581: try
1582: {
1583: bootEnc.RegisterFilterDriver (true, BootEncryption::DumpFilter);
1584: }
1585: catch (Exception &e)
1586: {
1587: try
1588: {
1589: bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter);
1590: }
1591: catch (...) { }
1592:
1593: e.Show (hwndDlg);
1594:
1595: bOK = FALSE;
1596: goto outcome;
1597: }
1598:
1599: if (ReadDriverConfigurationFlags() & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES)
1600: {
1601: WriteLocalMachineRegistryString ("SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Minimal\\" TC_SYSTEM_FAVORITES_SERVICE_NAME, NULL, "Service", FALSE);
1602: WriteLocalMachineRegistryString ("SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Network\\" TC_SYSTEM_FAVORITES_SERVICE_NAME, NULL, "Service", FALSE);
1603: }
1604: }
1605:
1606: UpdateProgressBarProc(61);
1607:
1608: if (bUpgrade && InstalledVersion < 0x700)
1609: {
1610: bool bMountFavoritesOnLogon = ConfigReadInt ("MountFavoritesOnLogon", FALSE) != 0;
1611: bool bOpenExplorerWindowAfterMount = ConfigReadInt ("OpenExplorerWindowAfterMount", FALSE) != 0;
1612:
1613: if (bMountFavoritesOnLogon || bOpenExplorerWindowAfterMount)
1614: {
1615: char *favoritesFilename = GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES);
1616: DWORD size;
1617: char *favoritesXml = LoadFile (favoritesFilename, &size);
1618:
1619: if (favoritesXml && size != 0)
1620: {
1621: string favorites;
1622: favorites.insert (0, favoritesXml, size);
1623:
1624: size_t p = favorites.find ("<volume ");
1625: while (p != string::npos)
1626: {
1627: if (bMountFavoritesOnLogon)
1628: favorites.insert (p + 8, "mountOnLogOn=\"1\" ");
1629:
1630: if (bOpenExplorerWindowAfterMount)
1631: favorites.insert (p + 8, "openExplorerWindow=\"1\" ");
1632:
1633: p = favorites.find ("<volume ", p + 1);
1634: }
1635:
1636: SaveBufferToFile (favorites.c_str(), favoritesFilename, favorites.size(), FALSE);
1637:
1638: if (bMountFavoritesOnLogon)
1639: {
1640: char regk[64];
1641: char regVal[MAX_PATH * 2];
1642:
1643: GetStartupRegKeyName (regk);
1644:
1645: ReadRegistryString (regk, "TrueCrypt", "", regVal, sizeof (regVal));
1646:
1647: if (strstr (regVal, "favorites"))
1648: {
1649: strcat_s (regVal, sizeof (regVal), " /a logon");
1650: WriteRegistryString (regk, "TrueCrypt", regVal);
1651: }
1652: }
1653: }
1654:
1655: if (favoritesXml)
1656: free (favoritesXml);
1657: }
1658: }
1.1.1.13 root 1659:
1.1.1.11 root 1660: GetWindowsDirectory (path, sizeof (path));
1661: strcat_s (path, sizeof (path), "\\TrueCrypt Setup.exe");
1662: DeleteFile (path);
1663:
1.1.1.22 root 1664: if (UpdateProgressBarProc(63) && UnloadDriver && DoServiceUninstall (hwndDlg, "truecrypt") == FALSE)
1.1 root 1665: {
1666: bOK = FALSE;
1667: }
1.1.1.13 root 1668: else if (UpdateProgressBarProc(72) && DoFilesInstall ((HWND) hwndDlg, InstallationPath) == FALSE)
1.1 root 1669: {
1670: bOK = FALSE;
1671: }
1.1.1.19 root 1672: else if (UpdateProgressBarProc(80) && DoRegInstall ((HWND) hwndDlg, InstallationPath, bRegisterFileExt) == FALSE)
1.1 root 1673: {
1674: bOK = FALSE;
1675: }
1.1.1.22 root 1676: else if (UpdateProgressBarProc(85) && UnloadDriver && DoDriverInstall (hwndDlg) == FALSE)
1.1.1.14 root 1677: {
1678: bOK = FALSE;
1679: }
1.1.1.17 root 1680: else if (UpdateProgressBarProc(90) && SystemEncryptionUpgrade && UpgradeBootLoader (hwndDlg) == FALSE)
1.1 root 1681: {
1682: bOK = FALSE;
1683: }
1.1.1.13 root 1684: else if (UpdateProgressBarProc(93) && DoShortcutsInstall (hwndDlg, InstallationPath, bAddToStartMenu, bDesktopIcon) == FALSE)
1.1 root 1685: {
1686: bOK = FALSE;
1687: }
1688:
1.1.1.22 root 1689: if (!UnloadDriver)
1690: bRestartRequired = TRUE;
1691:
1.1.1.17 root 1692: try
1693: {
1694: bootEnc.RenameDeprecatedSystemLoaderBackup();
1695: }
1696: catch (...) { }
1697:
1.1.1.24 root 1698: if (SystemEncryptionUpgrade && InstalledVersion == 0x630)
1699: {
1700: string sysFavorites = GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES);
1701: string legacySysFavorites = GetProgramConfigPath ("System Favorite Volumes.xml");
1.1.1.23 root 1702:
1.1.1.24 root 1703: if (FileExists (legacySysFavorites.c_str()) && !FileExists (sysFavorites.c_str()))
1704: MoveFile (legacySysFavorites.c_str(), sysFavorites.c_str());
1705: }
1.1.1.17 root 1706:
1.1.1.13 root 1707: if (bOK)
1708: UpdateProgressBarProc(97);
1709:
1710: if (bSystemRestore)
1.1 root 1711: SetSystemRestorePoint (hwndDlg, TRUE);
1712:
1.1.1.7 root 1713: if (bOK)
1714: {
1.1.1.13 root 1715: UpdateProgressBarProc(100);
1.1.1.11 root 1716: UninstallBatch[0] = 0;
1.1.1.7 root 1717: StatusMessage (hwndDlg, "INSTALL_COMPLETED");
1.1.1.25! root 1718:
! 1719: if (!DonEnabled || DonPagePos != 3)
! 1720: PostMessage (MainDlg, TC_APPMSG_INSTALL_SUCCESS, 0, 0);
1.1.1.11 root 1721: }
1722: else
1723: {
1.1.1.13 root 1724: UpdateProgressBarProc(0);
1.1.1.11 root 1725: bUninstall = TRUE;
1726: Rollback = TRUE;
1727: Silent = TRUE;
1728:
1.1.1.14 root 1729: if (!SystemEncryptionUpgrade)
1730: DoUninstall (hwndDlg);
1.1.1.11 root 1731:
1732: bUninstall = FALSE;
1733: Rollback = FALSE;
1734: Silent = FALSE;
1735:
1.1.1.24 root 1736: if (SystemEncryptionUpgrade)
1737: Warning ("SYS_ENC_UPGRADE_FAILED");
1738: else
1739: StatusMessage (hwndDlg, "ROLLBACK");
1.1.1.7 root 1740: }
1.1 root 1741:
1.1.1.24 root 1742: outcome:
1.1.1.11 root 1743: OutcomePrompt (hwndDlg, bOK);
1744:
1.1.1.25! root 1745: if (bOK && DonEnabled && DonPagePos == 3)
! 1746: PostMessage (MainDlg, TC_APPMSG_INSTALL_SUCCESS, 0, 0);
! 1747:
1.1.1.13 root 1748: if (!bOK)
1749: {
1750: PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0);
1751: }
1752: else if (!bUninstall && !bDevm)
1.1.1.11 root 1753: {
1.1.1.17 root 1754: if (!IsHiddenOSRunning()) // A hidden OS user should not see the post-install notes twice (on decoy OS and then on hidden OS).
1.1.1.11 root 1755: {
1.1.1.17 root 1756: if (bUpgrade)
1.1.1.14 root 1757: {
1.1.1.18 root 1758: if (bRestartRequired || SystemEncryptionUpgrade)
1759: {
1760: SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_RELEASE_NOTES);
1761: }
1.1.1.25! root 1762: else if ((!DonEnabled || DonPagePos == 2)
! 1763: && AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES") == IDYES)
1.1.1.18 root 1764: {
1765: Applink ("releasenotes", TRUE, "");
1766: }
1.1.1.14 root 1767: }
1.1.1.25! root 1768: else if (bPossiblyFirstTimeInstall)
1.1.1.14 root 1769: {
1.1.1.18 root 1770: if (bRestartRequired || SystemEncryptionUpgrade)
1771: {
1772: SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_TUTORIAL);
1773: }
1.1.1.25! root 1774: else if ((!DonEnabled || DonPagePos == 2)
! 1775: && AskYesNo ("AFTER_INSTALL_TUTORIAL") == IDYES)
1.1.1.18 root 1776: {
1777: Applink ("beginnerstutorial", TRUE, "");
1778: }
1.1.1.14 root 1779: }
1.1.1.11 root 1780: }
1.1.1.22 root 1781: }
1.1.1.17 root 1782:
1.1.1.25! root 1783: if (!DonEnabled || DonPagePos == 2)
1.1.1.22 root 1784: {
1.1.1.25! root 1785: if (bOK && bRestartRequired)
! 1786: {
! 1787: if (AskYesNo (bUpgrade ? "UPGRADE_OK_REBOOT_REQUIRED" : "CONFIRM_RESTART") == IDYES)
! 1788: RestartComputer();
! 1789: }
1.1.1.11 root 1790: }
1.1 root 1791: }
1792:
1793:
1.1.1.13 root 1794: void SetInstallationPath (HWND hwndDlg)
1795: {
1796: HKEY hkey;
1797: BOOL bInstallPathDetermined = FALSE;
1798: char path[MAX_PATH+20];
1799: ITEMIDLIST *itemList;
1800:
1801: memset (InstallationPath, 0, sizeof (InstallationPath));
1802:
1803: // Determine if TrueCrypt is already installed and try to determine its "Program Files" location
1804: if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt", 0, KEY_READ, &hkey) == ERROR_SUCCESS)
1805: {
1806: /* Default 'UninstallString' registry strings written by past versions of TrueCrypt:
1807: ------------------------------------------------------------------------------------
1808: 1.0 C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
1809: 1.0a C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
1810: 2.0 C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
1811: 2.1 C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
1812: 2.1a C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
1813: 3.0 C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
1814: 3.0a C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
1815: 3.1 The UninstallString was NEVER written (fortunately, 3.1a replaced 3.1 after 2 weeks)
1816: 3.1a C:\WINDOWS\TrueCrypt Setup.exe /u
1817: 4.0 C:\WINDOWS\TrueCrypt Setup.exe /u C:\Program Files\TrueCrypt
1818: 4.1 C:\WINDOWS\TrueCrypt Setup.exe /u C:\Program Files\TrueCrypt
1819: 4.2 C:\WINDOWS\TrueCrypt Setup.exe /u C:\Program Files\TrueCrypt
1820: 4.2a C:\WINDOWS\TrueCrypt Setup.exe /u C:\Program Files\TrueCrypt
1821: 4.3 "C:\Program Files\TrueCrypt\TrueCrypt Setup.exe" /u C:\Program Files\TrueCrypt\
1822: 4.3a "C:\Program Files\TrueCrypt\TrueCrypt Setup.exe" /u C:\Program Files\TrueCrypt\
1.1.1.15 root 1823: 5.0+ "C:\Program Files\TrueCrypt\TrueCrypt Setup.exe" /u
1.1.1.13 root 1824:
1825: Note: In versions 1.0-3.0a the user was able to choose whether to install the uninstaller.
1826: The default was to install it. If it wasn't installed, there was no UninstallString.
1827: */
1828:
1829: char rv[MAX_PATH*4];
1830: DWORD size = sizeof (rv);
1.1.1.17 root 1831: if (RegQueryValueEx (hkey, "UninstallString", 0, 0, (LPBYTE) &rv, &size) == ERROR_SUCCESS && strrchr (rv, '/'))
1.1.1.13 root 1832: {
1833: size_t len = 0;
1834:
1835: // Cut and paste the location (path) where TrueCrypt is installed to InstallationPath
1836: if (rv[0] == '"')
1837: {
1838: // 4.3 or later
1839:
1840: len = strrchr (rv, '/') - rv - 2;
1841: strncpy (InstallationPath, rv + 1, len);
1842: InstallationPath [len] = 0;
1843: bInstallPathDetermined = TRUE;
1844:
1845: if (InstallationPath [strlen (InstallationPath) - 1] != '\\')
1846: {
1847: len = strrchr (InstallationPath, '\\') - InstallationPath;
1848: InstallationPath [len] = 0;
1849: }
1850: }
1851: else
1852: {
1853: // 1.0-4.2a (except 3.1)
1854:
1855: len = strrchr (rv, '/') - rv;
1856: if (rv[len+2] == ' ')
1857: {
1858: // 4.0-4.2a
1859:
1860: strncpy (InstallationPath, rv + len + 3, strlen (rv) - len - 3);
1861: InstallationPath [strlen (rv) - len - 3] = 0;
1862: bInstallPathDetermined = TRUE;
1863: }
1864: else
1865: {
1866: // 1.0-3.1a (except 3.1)
1867:
1868: // We know that TrueCrypt is installed but don't know where. It's not safe to continue installing
1869: // over the old version.
1870:
1871: Error ("UNINSTALL_OLD_VERSION_FIRST");
1872:
1873: len = strrchr (rv, '/') - rv - 1;
1874: strncpy (InstallationPath, rv, len); // Path and filename of the uninstaller
1875: InstallationPath [len] = 0;
1876: bInstallPathDetermined = FALSE;
1877:
1878: ShellExecute (NULL, "open", InstallationPath, "/u", NULL, SW_SHOWNORMAL);
1879: RegCloseKey (hkey);
1880: exit (1);
1881: }
1882: }
1883:
1884: }
1885: RegCloseKey (hkey);
1886: }
1887:
1888: if (bInstallPathDetermined)
1889: {
1890: char mp[MAX_PATH];
1891:
1892: // Determine whether we were launched from the folder where TrueCrypt is installed
1893: GetModuleFileName (NULL, mp, sizeof (mp));
1894: if (strncmp (InstallationPath, mp, min (strlen(InstallationPath), strlen(mp))) == 0)
1895: {
1896: // We were launched from the folder where TrueCrypt is installed
1897:
1898: if (!IsNonInstallMode() && !bDevm)
1899: bChangeMode = TRUE;
1900: }
1901: }
1902: else
1903: {
1904: /* TrueCypt is not installed or it wasn't possible to determine where it is installed. */
1905:
1906: // Default "Program Files" path.
1907: SHGetSpecialFolderLocation (hwndDlg, CSIDL_PROGRAM_FILES, &itemList);
1908: SHGetPathFromIDList (itemList, path);
1.1.1.24 root 1909:
1910: if (Is64BitOs())
1911: {
1912: // Use a unified default installation path (registry redirection of %ProgramFiles% does not work if the installation path is user-selectable)
1913: string s = path;
1914: size_t p = s.find (" (x86)");
1915: if (p != string::npos)
1916: {
1917: s = s.substr (0, p);
1918: if (_access (s.c_str(), 0) != -1)
1919: strcpy_s (path, sizeof (path), s.c_str());
1920: }
1921: }
1922:
1.1.1.15 root 1923: strncat (path, "\\TrueCrypt\\", min (strlen("\\TrueCrypt\\"), sizeof(path)-strlen(path)-1));
1924: strncpy (InstallationPath, path, sizeof(InstallationPath)-1);
1.1.1.13 root 1925: }
1926:
1927: // Make sure the path ends with a backslash
1928: if (InstallationPath [strlen (InstallationPath) - 1] != '\\')
1929: {
1930: strcat (InstallationPath, "\\");
1931: }
1932: }
1933:
1934:
1935: // Handler for uninstall only (install is handled by the wizard)
1.1.1.18 root 1936: BOOL CALLBACK UninstallDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
1.1 root 1937: {
1938: WORD lw = LOWORD (wParam);
1939:
1940: switch (msg)
1941: {
1942: case WM_INITDIALOG:
1.1.1.17 root 1943:
1.1.1.7 root 1944: MainDlg = hwndDlg;
1.1.1.17 root 1945:
1946: if (!CreateAppSetupMutex ())
1947: AbortProcess ("TC_INSTALLER_IS_RUNNING");
1948:
1.1 root 1949: InitDialog (hwndDlg);
1.1.1.7 root 1950: LocalizeDialog (hwndDlg, NULL);
1.1 root 1951:
1.1.1.13 root 1952: SetWindowTextW (hwndDlg, lpszTitle);
1.1 root 1953:
1.1.1.13 root 1954: // System Restore
1955: SetCheckBox (hwndDlg, IDC_SYSTEM_RESTORE, bSystemRestore);
1956: if (SystemRestoreDll == 0)
1.1 root 1957: {
1.1.1.13 root 1958: SetCheckBox (hwndDlg, IDC_SYSTEM_RESTORE, FALSE);
1959: EnableWindow (GetDlgItem (hwndDlg, IDC_SYSTEM_RESTORE), FALSE);
1.1 root 1960: }
1961:
1.1.1.13 root 1962: SetFocus (GetDlgItem (hwndDlg, IDC_UNINSTALL));
1.1.1.11 root 1963:
1.1 root 1964: return 1;
1965:
1966: case WM_SYSCOMMAND:
1967: if (lw == IDC_ABOUT)
1968: {
1.1.1.7 root 1969: DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc);
1.1 root 1970: return 1;
1971: }
1972: return 0;
1973:
1974: case WM_COMMAND:
1.1.1.13 root 1975: if (lw == IDC_UNINSTALL)
1.1 root 1976: {
1.1.1.7 root 1977: if (bDone)
1.1 root 1978: {
1.1.1.13 root 1979: bUninstallInProgress = FALSE;
1980: PostMessage (hwndDlg, WM_CLOSE, 0, 0);
1.1 root 1981: return 1;
1982: }
1983:
1.1.1.13 root 1984: bUninstallInProgress = TRUE;
1.1 root 1985:
1.1.1.11 root 1986: WaitCursor ();
1987:
1.1.1.13 root 1988: if (bUninstall)
1.1.1.18 root 1989: _beginthread (DoUninstall, 0, (void *) hwndDlg);
1.1 root 1990:
1991: return 1;
1992: }
1993:
1.1.1.13 root 1994: if (lw == IDC_SYSTEM_RESTORE)
1.1 root 1995: {
1.1.1.13 root 1996: bSystemRestore = IsButtonChecked (GetDlgItem (hwndDlg, IDC_SYSTEM_RESTORE));
1.1 root 1997: return 1;
1998: }
1999:
1.1.1.13 root 2000: if (lw == IDCANCEL)
1.1 root 2001: {
1.1.1.13 root 2002: PostMessage (hwndDlg, WM_CLOSE, 0, 0);
1.1 root 2003: return 1;
2004: }
2005:
2006: return 0;
2007:
1.1.1.13 root 2008: case TC_APPMSG_UNINSTALL_SUCCESS:
1.1.1.11 root 2009: SetWindowTextW (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), GetString ("FINALIZE"));
2010: NormalCursor ();
1.1.1.13 root 2011: return 1;
1.1.1.7 root 2012:
1.1 root 2013: case WM_CLOSE:
1.1.1.13 root 2014: if (bUninstallInProgress)
2015: {
2016: NormalCursor();
2017: if (AskNoYes("CONFIRM_EXIT_UNIVERSAL") == IDNO)
2018: {
2019: return 1;
2020: }
2021: WaitCursor ();
2022: }
1.1 root 2023: EndDialog (hwndDlg, IDCANCEL);
2024: return 1;
2025: }
2026:
2027: return 0;
2028: }
2029:
2030:
1.1.1.22 root 2031: int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpszCommandLine, int nCmdShow)
1.1 root 2032: {
1.1.1.17 root 2033: atexit (localcleanup);
2034:
1.1.1.13 root 2035: SelfExtractStartupInit();
1.1 root 2036:
1.1.1.7 root 2037: lpszTitle = L"TrueCrypt Setup";
1.1 root 2038:
1.1.1.18 root 2039: InitCommonControls ();
2040:
1.1 root 2041: /* Call InitApp to initialize the common code */
1.1.1.11 root 2042: InitApp (hInstance, NULL);
1.1 root 2043:
1.1.1.7 root 2044: if (IsAdmin () != TRUE)
2045: if (MessageBoxW (NULL, GetString ("SETUP_ADMIN"), lpszTitle, MB_YESNO | MB_ICONQUESTION) != IDYES)
1.1.1.13 root 2046: {
1.1.1.11 root 2047: exit (1);
1.1.1.13 root 2048: }
1.1 root 2049:
1.1.1.8 root 2050: /* Setup directory */
2051: {
2052: char *s;
2053: GetModuleFileName (NULL, SetupFilesDir, sizeof (SetupFilesDir));
2054: s = strrchr (SetupFilesDir, '\\');
2055: if (s)
2056: s[1] = 0;
2057: }
2058:
1.1.1.13 root 2059: /* Parse command line arguments */
2060:
2061: if (lpszCommandLine[0] == '/')
1.1 root 2062: {
1.1.1.13 root 2063: if (lpszCommandLine[1] == 'u')
2064: {
2065: // Uninstall: /u
2066:
2067: bUninstall = TRUE;
2068: }
2069: else if (lpszCommandLine[1] == 'c')
2070: {
2071: // Change: /c
1.1 root 2072:
1.1.1.13 root 2073: bChangeMode = TRUE;
2074: }
2075: else if (lpszCommandLine[1] == 'p')
2076: {
2077: // Create self-extracting package: /p
2078:
2079: bMakePackage = TRUE;
2080: }
2081: else if (lpszCommandLine[1] == 'd')
2082: {
2083: // Dev mode: /d
2084: bDevm = TRUE;
2085: }
2086: }
1.1.1.24 root 2087:
1.1.1.13 root 2088: if (bMakePackage)
1.1.1.11 root 2089: {
1.1.1.13 root 2090: /* Create self-extracting package */
1.1.1.11 root 2091:
1.1.1.13 root 2092: MakeSelfExtractingPackage (NULL, SetupFilesDir);
2093: }
2094: else
2095: {
2096: SetInstallationPath (NULL);
1.1.1.11 root 2097:
1.1.1.13 root 2098: if (!bUninstall)
1.1.1.11 root 2099: {
1.1.1.13 root 2100: if (IsSelfExtractingPackage())
1.1.1.11 root 2101: {
1.1.1.13 root 2102: if (!VerifyPackageIntegrity())
1.1.1.12 root 2103: {
1.1.1.13 root 2104: // Package corrupted
2105: exit (1);
1.1.1.12 root 2106: }
1.1.1.13 root 2107: bDevm = FALSE;
1.1.1.11 root 2108: }
1.1.1.13 root 2109: else if (!bDevm)
1.1.1.11 root 2110: {
1.1.1.18 root 2111: MessageBox (NULL, "Error: This installer file does not contain any compressed files.\n\nTo create a self-extracting installation package (with embedded compressed files), run:\n\"TrueCrypt Setup.exe\" /p", "TrueCrypt", MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
1.1.1.12 root 2112: exit (1);
1.1.1.11 root 2113: }
1.1.1.13 root 2114:
2115: if (bChangeMode)
2116: {
2117: /* TrueCrypt is already installed on this system and we were launched from the Program Files folder */
2118:
2119: char *tmpStr[] = {0, "SELECT_AN_ACTION", "REPAIR_REINSTALL", "UNINSTALL", "EXIT", 0};
2120:
2121: // Ask the user to select either Repair or Unistallation
1.1.1.18 root 2122: switch (AskMultiChoice ((void **) tmpStr, FALSE))
1.1.1.13 root 2123: {
2124: case 1:
2125: bRepairMode = TRUE;
2126: break;
2127: case 2:
2128: bUninstall = TRUE;
2129: break;
2130: default:
2131: exit (1);
2132: }
2133: }
1.1.1.11 root 2134: }
2135:
1.1.1.13 root 2136: // System Restore
2137: SystemRestoreDll = LoadLibrary ("srclient.dll");
2138:
2139: if (!bUninstall)
1.1.1.11 root 2140: {
1.1.1.13 root 2141: /* Create the main dialog for install */
1.1.1.11 root 2142:
1.1.1.13 root 2143: DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_INSTL_DLG), NULL, (DLGPROC) MainDialogProc,
2144: (LPARAM)lpszCommandLine);
2145: }
2146: else
2147: {
2148: /* Create the main dialog for uninstall */
2149:
2150: DialogBoxW (hInstance, MAKEINTRESOURCEW (IDD_UNINSTALL), NULL, (DLGPROC) UninstallDlgProc);
1.1.1.11 root 2151:
1.1.1.13 root 2152: if (UninstallBatch[0])
2153: {
2154: STARTUPINFO si;
2155: PROCESS_INFORMATION pi;
2156:
2157: ZeroMemory (&si, sizeof (si));
2158: si.cb = sizeof (si);
2159: si.dwFlags = STARTF_USESHOWWINDOW;
2160: si.wShowWindow = SW_HIDE;
2161:
2162: if (!CreateProcess (UninstallBatch, NULL, NULL, NULL, FALSE, IDLE_PRIORITY_CLASS, NULL, NULL, &si, &pi))
2163: DeleteFile (UninstallBatch);
1.1.1.15 root 2164: else
2165: {
2166: CloseHandle (pi.hProcess);
2167: CloseHandle (pi.hThread);
2168: }
1.1.1.13 root 2169: }
1.1.1.11 root 2170: }
1.1 root 2171: }
2172:
2173: return 0;
2174: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.