Source to setup/setup.c
/*
Legal Notice: Some portions of the source code contained in this file were
derived from the source code of Encryption for the Masses 2.02a, which is
Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
Agreement for Encryption for the Masses'. Modifications and additions to
the original source code (contained in this file) and all other portions
of this file are Copyright (c) 2003-2012 TrueCrypt Developers Association
and are governed by the TrueCrypt License 3.0 the full text of which is
contained in the file License.txt included in TrueCrypt binary and source
code distribution packages. */
#include "Tcdefs.h"
#include <SrRestorePtApi.h>
#include <io.h>
#include <propkey.h>
#include <propvarutil.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "Apidrvr.h"
#include "BootEncryption.h"
#include "Boot/Windows/BootCommon.h"
#include "Combo.h"
#include "ComSetup.h"
#include "Dlgcode.h"
#include "Language.h"
#include "Registry.h"
#include "Resource.h"
#include "Dir.h"
#include "Setup.h"
#include "SelfExtract.h"
#include "Wizard.h"
#include "../Common/Resource.h"
using namespace TrueCrypt;
#pragma warning( disable : 4201 )
#pragma warning( disable : 4115 )
#include <shlobj.h>
#pragma warning( default : 4201 )
#pragma warning( default : 4115 )
char InstallationPath[TC_MAX_PATH];
char SetupFilesDir[TC_MAX_PATH];
char UninstallBatch[MAX_PATH];
LONG InstalledVersion = 0;
BOOL bUninstall = FALSE;
BOOL bRestartRequired = FALSE;
BOOL bMakePackage = FALSE;
BOOL bDone = FALSE;
BOOL Rollback = FALSE;
BOOL bUpgrade = FALSE;
BOOL bDowngrade = FALSE;
BOOL SystemEncryptionUpdate = FALSE;
BOOL PortableMode = FALSE;
BOOL bRepairMode = FALSE;
BOOL bChangeMode = FALSE;
BOOL bDevm = FALSE;
BOOL bPossiblyFirstTimeInstall = FALSE;
BOOL bUninstallInProgress = FALSE;
BOOL UnloadDriver = TRUE;
BOOL bSystemRestore = TRUE;
BOOL bDisableSwapFiles = FALSE;
BOOL bForAllUsers = TRUE;
BOOL bRegisterFileExt = TRUE;
BOOL bAddToStartMenu = TRUE;
BOOL bDesktopIcon = TRUE;
BOOL bDesktopIconStatusDetermined = FALSE;
HMODULE volatile SystemRestoreDll = 0;
void localcleanup (void)
{
localcleanupwiz ();
cleanup ();
CloseAppSetupMutex ();
}
BOOL StatDeleteFile (char *lpszFile)
{
struct __stat64 st;
if (_stat64 (lpszFile, &st) == 0)
return DeleteFile (lpszFile);
else
return TRUE;
}
BOOL StatRemoveDirectory (char *lpszDir)
{
struct __stat64 st;
if (_stat64 (lpszDir, &st) == 0)
return RemoveDirectory (lpszDir);
else
return TRUE;
}
HRESULT CreateLink (char *lpszPathObj, char *lpszArguments,
char *lpszPathLink)
{
HRESULT hres;
IShellLink *psl;
/* Get a pointer to the IShellLink interface. */
hres = CoCreateInstance (CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *) &psl);
if (SUCCEEDED (hres))
{
IPersistFile *ppf;
/* Set the path to the shortcut target, and add the
description. */
psl->SetPath (lpszPathObj);
psl->SetArguments (lpszArguments);
// Application ID
if (strstr (lpszPathObj, TC_APP_NAME ".exe"))
{
IPropertyStore *propStore;
if (SUCCEEDED (psl->QueryInterface (IID_PPV_ARGS (&propStore))))
{
PROPVARIANT propVariant;
if (SUCCEEDED (InitPropVariantFromString (TC_APPLICATION_ID, &propVariant)))
{
if (SUCCEEDED (propStore->SetValue (PKEY_AppUserModel_ID, propVariant)))
propStore->Commit();
PropVariantClear (&propVariant);
}
propStore->Release();
}
}
/* Query IShellLink for the IPersistFile interface for saving
the shortcut in persistent storage. */
hres = psl->QueryInterface (IID_IPersistFile,
(void **) &ppf);
if (SUCCEEDED (hres))
{
wchar_t wsz[TC_MAX_PATH];
/* Ensure that the string is ANSI. */
MultiByteToWideChar (CP_ACP, 0, lpszPathLink, -1,
wsz, sizeof(wsz) / sizeof(wsz[0]));
/* Save the link by calling IPersistFile::Save. */
hres = ppf->Save (wsz, TRUE);
ppf->Release ();
}
psl->Release ();
}
return hres;
}
void GetProgramPath (HWND hwndDlg, char *path)
{
ITEMIDLIST *i;
HRESULT res;
if (bForAllUsers)
res = SHGetSpecialFolderLocation (hwndDlg, CSIDL_COMMON_PROGRAMS, &i);
else
res = SHGetSpecialFolderLocation (hwndDlg, CSIDL_PROGRAMS, &i);
SHGetPathFromIDList (i, path);
}
void StatusMessage (HWND hwndDlg, char *stringId)
{
if (Rollback)
return;
SendMessageW (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_ADDSTRING, 0, (LPARAM) GetString (stringId));
SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_SETTOPINDEX,
SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_GETCOUNT, 0, 0) - 1, 0);
}
void StatusMessageParam (HWND hwndDlg, char *stringId, char *param)
{
wchar_t szTmp[1024];
if (Rollback)
return;
wsprintfW (szTmp, L"%s %hs", GetString (stringId), param);
SendMessageW (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_ADDSTRING, 0, (LPARAM) szTmp);
SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_SETTOPINDEX,
SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_GETCOUNT, 0, 0) - 1, 0);
}
void ClearLogWindow (HWND hwndDlg)
{
SendMessage (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_RESETCONTENT, 0, 0);
}
void RegMessage (HWND hwndDlg, char *txt)
{
StatusMessageParam (hwndDlg, "ADDING_REG", txt);
}
void CopyMessage (HWND hwndDlg, char *txt)
{
StatusMessageParam (hwndDlg, "INSTALLING", txt);
}
void RemoveMessage (HWND hwndDlg, char *txt)
{
if (!Rollback)
StatusMessageParam (hwndDlg, "REMOVING", txt);
}
void IconMessage (HWND hwndDlg, char *txt)
{
StatusMessageParam (hwndDlg, "ADDING_ICON", txt);
}
void DetermineUpgradeDowngradeStatus (BOOL bCloseDriverHandle, LONG *driverVersionPtr)
{
LONG driverVersion = VERSION_NUM;
if (hDriver == INVALID_HANDLE_VALUE)
DriverAttach();
if (hDriver != INVALID_HANDLE_VALUE)
{
DWORD dwResult;
BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &driverVersion, sizeof (driverVersion), &dwResult, NULL);
if (!bResult)
bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &driverVersion, sizeof (driverVersion), &dwResult, NULL);
if (bResult)
InstalledVersion = driverVersion;
bUpgrade = (bResult && driverVersion < VERSION_NUM);
bDowngrade = (bResult && driverVersion > VERSION_NUM);
PortableMode = DeviceIoControl (hDriver, TC_IOCTL_GET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dwResult, NULL);
if (bCloseDriverHandle)
{
CloseHandle (hDriver);
hDriver = INVALID_HANDLE_VALUE;
}
}
*driverVersionPtr = driverVersion;
}
static BOOL IsFileInUse (const string &filePath)
{
HANDLE useTestHandle = CreateFile (filePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (useTestHandle != INVALID_HANDLE_VALUE)
CloseHandle (useTestHandle);
else if (GetLastError() == ERROR_SHARING_VIOLATION)
return TRUE;
return FALSE;
}
BOOL DoFilesInstall (HWND hwndDlg, char *szDestDir)
{
/* WARNING: Note that, despite its name, this function is used during UNinstallation as well. */
char szTmp[TC_MAX_PATH];
BOOL bOK = TRUE;
int i, x, fileNo;
char curFileName [TC_MAX_PATH] = {0};
if (!bUninstall && !bDevm)
{
// Self-extract all files to memory
GetModuleFileName (NULL, szTmp, sizeof (szTmp));
if (!SelfExtractInMemory (szTmp))
return FALSE;
}
x = strlen (szDestDir);
if (x < 2)
return FALSE;
if (szDestDir[x - 1] != '\\')
strcat (szDestDir, "\\");
for (i = 0; i < sizeof (szFiles) / sizeof (szFiles[0]); i++)
{
BOOL bResult;
char szDir[TC_MAX_PATH];
if (strstr (szFiles[i], "TrueCrypt Setup") != 0)
{
if (bUninstall)
continue; // Prevent 'access denied' error
if (bRepairMode)
continue; // Destination = target
}
if (*szFiles[i] == 'A')
strcpy (szDir, szDestDir);
else if (*szFiles[i] == 'D')
{
GetSystemDirectory (szDir, sizeof (szDir));
x = strlen (szDir);
if (szDir[x - 1] != '\\')
strcat (szDir, "\\");
strcat (szDir, "Drivers\\");
}
else if (*szFiles[i] == 'W')
GetWindowsDirectory (szDir, sizeof (szDir));
if (*szFiles[i] == 'I')
continue;
sprintf (szTmp, "%s%s", szDir, szFiles[i] + 1);
if (bUninstall == FALSE)
CopyMessage (hwndDlg, szTmp);
else
RemoveMessage (hwndDlg, szTmp);
if (bUninstall == FALSE)
{
SetCurrentDirectory (SetupFilesDir);
if (strstr (szFiles[i], "TrueCrypt Setup") != 0)
{
// Copy ourselves (the distribution package) to the destination location as 'TrueCrypt Setup.exe'
char mp[MAX_PATH];
GetModuleFileName (NULL, mp, sizeof (mp));
bResult = TCCopyFile (mp, szTmp);
}
else
{
BOOL driver64 = FALSE;
strncpy (curFileName, szFiles[i] + 1, strlen (szFiles[i]) - 1);
curFileName [strlen (szFiles[i]) - 1] = 0;
if (Is64BitOs ()
&& strcmp (szFiles[i], "Dtruecrypt.sys") == 0)
{
driver64 = TRUE;
strncpy (curFileName, FILENAME_64BIT_DRIVER, sizeof (FILENAME_64BIT_DRIVER));
}
if (!bDevm)
{
bResult = FALSE;
// Find the correct decompressed file in memory
for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++)
{
// Write the file (stored in memory) directly to the destination location
// (there will be no temporary files).
if (memcmp (
curFileName,
Decompressed_Files[fileNo].fileName,
min (strlen (curFileName), (size_t) Decompressed_Files[fileNo].fileNameLength)) == 0)
{
// Dump filter driver cannot be installed to SysWOW64 directory
if (driver64 && !EnableWow64FsRedirection (FALSE))
{
handleWin32Error (hwndDlg);
bResult = FALSE;
goto err;
}
bResult = SaveBufferToFile (
(char *) Decompressed_Files[fileNo].fileContent,
szTmp,
Decompressed_Files[fileNo].fileLength,
FALSE);
if (driver64)
{
if (!EnableWow64FsRedirection (TRUE))
{
handleWin32Error (hwndDlg);
bResult = FALSE;
goto err;
}
if (!bResult)
goto err;
if (bUpgrade && InstalledVersion < 0x700)
{
bResult = WriteLocalMachineRegistryString ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "ImagePath", "System32\\drivers\\truecrypt.sys", TRUE);
if (!bResult)
{
handleWin32Error (hwndDlg);
goto err;
}
DeleteFile (szTmp);
}
}
break;
}
}
}
else
{
if (driver64)
EnableWow64FsRedirection (FALSE);
bResult = TCCopyFile (curFileName, szTmp);
if (driver64)
EnableWow64FsRedirection (TRUE);
}
if (bResult && strcmp (szFiles[i], "ATrueCrypt.exe") == 0)
{
string servicePath = GetServiceConfigPath (TC_APP_NAME ".exe");
if (FileExists (servicePath.c_str()))
{
CopyMessage (hwndDlg, (char *) servicePath.c_str());
bResult = CopyFile (szTmp, servicePath.c_str(), FALSE);
}
}
}
}
else
{
bResult = StatDeleteFile (szTmp);
}
err:
if (bResult == FALSE)
{
LPVOID lpMsgBuf;
DWORD dwError = GetLastError ();
wchar_t szTmp2[700];
FormatMessage (
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwError,
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
(char *) &lpMsgBuf,
0,
NULL
);
if (bUninstall == FALSE)
wsprintfW (szTmp2, GetString ("INSTALL_OF_FAILED"), szTmp, lpMsgBuf);
else
wsprintfW (szTmp2, GetString ("UNINSTALL_OF_FAILED"), szTmp, lpMsgBuf);
LocalFree (lpMsgBuf);
if (!Silent && MessageBoxW (hwndDlg, szTmp2, lpszTitle, MB_YESNO | MB_ICONHAND) != IDYES)
return FALSE;
}
}
// Language pack
if (bUninstall == FALSE)
{
WIN32_FIND_DATA f;
HANDLE h;
SetCurrentDirectory (SetupFilesDir);
h = FindFirstFile ("Language.*.xml", &f);
if (h != INVALID_HANDLE_VALUE)
{
char d[MAX_PATH*2];
sprintf (d, "%s%s", szDestDir, f.cFileName);
CopyMessage (hwndDlg, d);
TCCopyFile (f.cFileName, d);
FindClose (h);
}
SetCurrentDirectory (SetupFilesDir);
SetCurrentDirectory ("Setup files");
h = FindFirstFile ("TrueCrypt User Guide.*.pdf", &f);
if (h != INVALID_HANDLE_VALUE)
{
char d[MAX_PATH*2];
sprintf (d, "%s%s", szDestDir, f.cFileName);
CopyMessage (hwndDlg, d);
TCCopyFile (f.cFileName, d);
FindClose (h);
}
SetCurrentDirectory (SetupFilesDir);
}
return bOK;
}
BOOL DoRegInstall (HWND hwndDlg, char *szDestDir, BOOL bInstallType)
{
char szDir[TC_MAX_PATH], *key;
char szTmp[TC_MAX_PATH*4];
HKEY hkey = 0;
BOOL bSlash, bOK = FALSE;
DWORD dw;
int x;
if (SystemEncryptionUpdate)
{
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt",
0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) == ERROR_SUCCESS)
{
strcpy (szTmp, VERSION_STRING);
RegSetValueEx (hkey, "DisplayVersion", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1);
strcpy (szTmp, TC_HOMEPAGE);
RegSetValueEx (hkey, "URLInfoAbout", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1);
RegCloseKey (hkey);
}
return TRUE;
}
strcpy (szDir, szDestDir);
x = strlen (szDestDir);
if (szDestDir[x - 1] == '\\')
bSlash = TRUE;
else
bSlash = FALSE;
if (bSlash == FALSE)
strcat (szDir, "\\");
if (bInstallType)
{
key = "Software\\Classes\\TrueCryptVolume";
RegMessage (hwndDlg, key);
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
key,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
goto error;
strcpy (szTmp, "TrueCrypt Volume");
if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
sprintf (szTmp, "%ws", TC_APPLICATION_ID);
if (RegSetValueEx (hkey, "AppUserModelID", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
RegCloseKey (hkey);
hkey = 0;
key = "Software\\Classes\\TrueCryptVolume\\DefaultIcon";
RegMessage (hwndDlg, key);
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
key,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
goto error;
sprintf (szTmp, "%sTrueCrypt.exe,1", szDir);
if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
RegCloseKey (hkey);
hkey = 0;
key = "Software\\Classes\\TrueCryptVolume\\Shell\\open\\command";
RegMessage (hwndDlg, key);
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
key,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
goto error;
sprintf (szTmp, "\"%sTrueCrypt.exe\" /v \"%%1\"", szDir );
if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
RegCloseKey (hkey);
hkey = 0;
key = "Software\\Classes\\.tc";
BOOL typeClassChanged = TRUE;
char typeClass[256];
DWORD typeClassSize = sizeof (typeClass);
if (ReadLocalMachineRegistryString (key, "", typeClass, &typeClassSize) && typeClassSize > 0 && strcmp (typeClass, "TrueCryptVolume") == 0)
typeClassChanged = FALSE;
RegMessage (hwndDlg, key);
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
key,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
goto error;
strcpy (szTmp, "TrueCryptVolume");
if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
RegCloseKey (hkey);
hkey = 0;
if (typeClassChanged)
SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
}
key = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt";
RegMessage (hwndDlg, key);
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
key,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
goto error;
/* IMPORTANT: IF YOU CHANGE THIS IN ANY WAY, REVISE AND UPDATE SetInstallationPath() ACCORDINGLY! */
sprintf (szTmp, "\"%sTrueCrypt Setup.exe\" /u", szDir);
if (RegSetValueEx (hkey, "UninstallString", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
sprintf (szTmp, "\"%sTrueCrypt Setup.exe\" /c", szDir);
if (RegSetValueEx (hkey, "ModifyPath", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
sprintf (szTmp, "\"%sTrueCrypt Setup.exe\"", szDir);
if (RegSetValueEx (hkey, "DisplayIcon", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
strcpy (szTmp, VERSION_STRING);
if (RegSetValueEx (hkey, "DisplayVersion", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
strcpy (szTmp, "TrueCrypt");
if (RegSetValueEx (hkey, "DisplayName", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
strcpy (szTmp, "TrueCrypt Foundation");
if (RegSetValueEx (hkey, "Publisher", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
strcpy (szTmp, TC_HOMEPAGE);
if (RegSetValueEx (hkey, "URLInfoAbout", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS)
goto error;
bOK = TRUE;
error:
if (hkey != 0)
RegCloseKey (hkey);
if (bOK == FALSE)
{
handleWin32Error (hwndDlg);
Error ("REG_INSTALL_FAILED");
}
// Register COM servers for UAC
if (IsOSAtLeast (WIN_VISTA))
{
if (!RegisterComServers (szDir))
{
Error ("COM_REG_FAILED");
return FALSE;
}
}
return bOK;
}
BOOL DoApplicationDataUninstall (HWND hwndDlg)
{
char path[MAX_PATH];
char path2[MAX_PATH];
BOOL bOK = TRUE;
StatusMessage (hwndDlg, "REMOVING_APPDATA");
SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path);
strcat (path, "\\TrueCrypt\\");
// Delete favorite volumes file
sprintf (path2, "%s%s", path, TC_APPD_FILENAME_FAVORITE_VOLUMES);
RemoveMessage (hwndDlg, path2);
StatDeleteFile (path2);
// Delete keyfile defaults
sprintf (path2, "%s%s", path, TC_APPD_FILENAME_DEFAULT_KEYFILES);
RemoveMessage (hwndDlg, path2);
StatDeleteFile (path2);
// Delete history file
sprintf (path2, "%s%s", path, TC_APPD_FILENAME_HISTORY);
RemoveMessage (hwndDlg, path2);
StatDeleteFile (path2);
// Delete configuration file
sprintf (path2, "%s%s", path, TC_APPD_FILENAME_CONFIGURATION);
RemoveMessage (hwndDlg, path2);
StatDeleteFile (path2);
// Delete system encryption configuration file
sprintf (path2, "%s%s", path, TC_APPD_FILENAME_SYSTEM_ENCRYPTION);
RemoveMessage (hwndDlg, path2);
StatDeleteFile (path2);
SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path);
strcat (path, "\\TrueCrypt");
RemoveMessage (hwndDlg, path);
if (!StatRemoveDirectory (path))
{
handleWin32Error (hwndDlg);
bOK = FALSE;
}
return bOK;
}
BOOL DoRegUninstall (HWND hwndDlg, BOOL bRemoveDeprecated)
{
BOOL bOK = FALSE;
char regk [64];
// Unregister COM servers
if (!bRemoveDeprecated && IsOSAtLeast (WIN_VISTA))
{
if (!UnregisterComServers (InstallationPath))
StatusMessage (hwndDlg, "COM_DEREG_FAILED");
}
if (!bRemoveDeprecated)
StatusMessage (hwndDlg, "REMOVING_REG");
RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt");
RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\Shell\\open\\command");
RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\Shell\\open");
RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\Shell");
RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\DefaultIcon");
RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume");
RegDeleteKey (HKEY_CURRENT_USER, "Software\\TrueCrypt");
if (!bRemoveDeprecated)
{
GetStartupRegKeyName (regk);
DeleteRegistryValue (regk, "TrueCrypt");
RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\.tc");
SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
}
bOK = TRUE;
if (bOK == FALSE && GetLastError ()!= ERROR_NO_TOKEN && GetLastError ()!= ERROR_FILE_NOT_FOUND
&& GetLastError ()!= ERROR_PATH_NOT_FOUND)
{
handleWin32Error (hwndDlg);
}
else
bOK = TRUE;
return bOK;
}
BOOL DoServiceUninstall (HWND hwndDlg, char *lpszService)
{
SC_HANDLE hManager, hService = NULL;
BOOL bOK = FALSE, bRet;
SERVICE_STATUS status;
BOOL firstTry = TRUE;
int x;
memset (&status, 0, sizeof (status)); /* Keep VC6 quiet */
retry:
hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hManager == NULL)
goto error;
hService = OpenService (hManager, lpszService, SERVICE_ALL_ACCESS);
if (hService == NULL)
goto error;
if (strcmp ("truecrypt", lpszService) == 0)
{
try
{
BootEncryption bootEnc (hwndDlg);
if (bootEnc.GetDriverServiceStartType() == SERVICE_BOOT_START)
{
try { bootEnc.RegisterFilterDriver (false, BootEncryption::DriveFilter); } catch (...) { }
try { bootEnc.RegisterFilterDriver (false, BootEncryption::VolumeFilter); } catch (...) { }
try { bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter); } catch (...) { }
}
}
catch (...) { }
StatusMessage (hwndDlg, "STOPPING_DRIVER");
}
else
StatusMessageParam (hwndDlg, "STOPPING", lpszService);
#define WAIT_PERIOD 3
for (x = 0; x < WAIT_PERIOD; x++)
{
bRet = QueryServiceStatus (hService, &status);
if (bRet != TRUE)
goto error;
if (status.dwCurrentState != SERVICE_START_PENDING &&
status.dwCurrentState != SERVICE_STOP_PENDING &&
status.dwCurrentState != SERVICE_CONTINUE_PENDING)
break;
Sleep (1000);
}
if (status.dwCurrentState != SERVICE_STOPPED)
{
bRet = ControlService (hService, SERVICE_CONTROL_STOP, &status);
if (bRet == FALSE)
goto try_delete;
for (x = 0; x < WAIT_PERIOD; x++)
{
bRet = QueryServiceStatus (hService, &status);
if (bRet != TRUE)
goto error;
if (status.dwCurrentState != SERVICE_START_PENDING &&
status.dwCurrentState != SERVICE_STOP_PENDING &&
status.dwCurrentState != SERVICE_CONTINUE_PENDING)
break;
Sleep (1000);
}
if (status.dwCurrentState != SERVICE_STOPPED && status.dwCurrentState != SERVICE_STOP_PENDING)
goto error;
}
try_delete:
if (strcmp ("truecrypt", lpszService) == 0)
StatusMessage (hwndDlg, "REMOVING_DRIVER");
else
StatusMessageParam (hwndDlg, "REMOVING", lpszService);
if (hService != NULL)
CloseServiceHandle (hService);
if (hManager != NULL)
CloseServiceHandle (hManager);
hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hManager == NULL)
goto error;
hService = OpenService (hManager, lpszService, SERVICE_ALL_ACCESS);
if (hService == NULL)
goto error;
bRet = DeleteService (hService);
if (bRet == FALSE)
{
if (firstTry && GetLastError () == ERROR_SERVICE_MARKED_FOR_DELETE)
{
// Second try for an eventual no-install driver instance
CloseServiceHandle (hService);
CloseServiceHandle (hManager);
Sleep(1000);
firstTry = FALSE;
goto retry;
}
goto error;
}
bOK = TRUE;
error:
if (bOK == FALSE && GetLastError ()!= ERROR_SERVICE_DOES_NOT_EXIST)
{
handleWin32Error (hwndDlg);
MessageBoxW (hwndDlg, GetString ("DRIVER_UINSTALL_FAILED"), lpszTitle, MB_ICONHAND);
}
else
bOK = TRUE;
if (hService != NULL)
CloseServiceHandle (hService);
if (hManager != NULL)
CloseServiceHandle (hManager);
return bOK;
}
BOOL DoDriverUnload (HWND hwndDlg)
{
BOOL bOK = TRUE;
int status;
status = DriverAttach ();
if (status != 0)
{
if (status == ERR_OS_ERROR && GetLastError () != ERROR_FILE_NOT_FOUND)
{
handleWin32Error (hwndDlg);
AbortProcess ("NODRIVER");
}
if (status != ERR_OS_ERROR)
{
handleError (NULL, status);
AbortProcess ("NODRIVER");
}
}
if (hDriver != INVALID_HANDLE_VALUE)
{
MOUNT_LIST_STRUCT driver;
LONG driverVersion = VERSION_NUM;
int refCount;
DWORD dwResult;
BOOL bResult;
// Try to determine if it's upgrade (and not reinstall, downgrade, or first-time install).
DetermineUpgradeDowngradeStatus (FALSE, &driverVersion);
// Test for encrypted boot drive
try
{
BootEncryption bootEnc (hwndDlg);
if (bootEnc.GetDriverServiceStartType() == SERVICE_BOOT_START)
{
try
{
// Check hidden OS update consistency
if (IsHiddenOSRunning())
{
if (bootEnc.GetInstalledBootLoaderVersion() != VERSION_NUM)
{
if (AskWarnNoYes ("UPDATE_TC_IN_DECOY_OS_FIRST") == IDNO)
AbortProcessSilent ();
}
}
}
catch (...) { }
if (bUninstallInProgress && driverVersion >= 0x500 && !bootEnc.GetStatus().DriveMounted)
{
try { bootEnc.RegisterFilterDriver (false, BootEncryption::DriveFilter); } catch (...) { }
try { bootEnc.RegisterFilterDriver (false, BootEncryption::VolumeFilter); } catch (...) { }
try { bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter); } catch (...) { }
bootEnc.SetDriverServiceStartType (SERVICE_SYSTEM_START);
}
else if (bUninstallInProgress || bDowngrade)
{
Error (bDowngrade ? "SETUP_FAILED_BOOT_DRIVE_ENCRYPTED_DOWNGRADE" : "SETUP_FAILED_BOOT_DRIVE_ENCRYPTED");
return FALSE;
}
else
{
if (CurrentOSMajor == 6 && CurrentOSMinor == 0 && CurrentOSServicePack < 1)
AbortProcess ("SYS_ENCRYPTION_UPGRADE_UNSUPPORTED_ON_VISTA_SP0");
SystemEncryptionUpdate = TRUE;
PortableMode = FALSE;
}
}
}
catch (...) { }
if (!bUninstall
&& (bUpgrade || SystemEncryptionUpdate)
&& (!bDevm || SystemEncryptionUpdate))
{
UnloadDriver = FALSE;
}
if (PortableMode && !SystemEncryptionUpdate)
UnloadDriver = TRUE;
if (UnloadDriver)
{
int volumesMounted = 0;
// Check mounted volumes
bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL);
if (!bResult)
{
bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL);
if (bResult)
volumesMounted = driver.ulMountedDrives;
}
if (bResult)
{
if (volumesMounted != 0)
{
bOK = FALSE;
MessageBoxW (hwndDlg, GetString ("DISMOUNT_ALL_FIRST"), lpszTitle, MB_ICONHAND);
}
}
else
{
bOK = FALSE;
handleWin32Error (hwndDlg);
}
}
// Try to close all open TC windows
if (bOK)
{
BOOL TCWindowClosed = FALSE;
EnumWindows (CloseTCWindowsEnum, (LPARAM) &TCWindowClosed);
if (TCWindowClosed)
Sleep (2000);
}
// Test for any applications attached to driver
if (!bUpgrade)
{
bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount,
sizeof (refCount), &dwResult, NULL);
if (bOK && bResult && refCount > 1)
{
MessageBoxW (hwndDlg, GetString ("CLOSE_TC_FIRST"), lpszTitle, MB_ICONSTOP);
bOK = FALSE;
}
}
if (!bOK || UnloadDriver)
{
CloseHandle (hDriver);
hDriver = INVALID_HANDLE_VALUE;
}
}
else
{
// Note that the driver may have already been unloaded during this session (e.g. retry after an error, etc.) so it is not
// guaranteed that the user is installing TrueCrypt for the first time now (we also cannot know if the user has already
// installed and used TrueCrypt on another system before).
bPossiblyFirstTimeInstall = TRUE;
}
return bOK;
}
BOOL UpgradeBootLoader (HWND hwndDlg)
{
if (!SystemEncryptionUpdate)
return TRUE;
try
{
BootEncryption bootEnc (hwndDlg);
if (bootEnc.GetInstalledBootLoaderVersion() < VERSION_NUM)
{
StatusMessage (hwndDlg, "INSTALLER_UPDATING_BOOT_LOADER");
bootEnc.InstallBootLoader (true);
if (bootEnc.GetInstalledBootLoaderVersion() <= TC_RESCUE_DISK_UPGRADE_NOTICE_MAX_VERSION)
Info (IsHiddenOSRunning() ? "BOOT_LOADER_UPGRADE_OK_HIDDEN_OS" : "BOOT_LOADER_UPGRADE_OK");
}
return TRUE;
}
catch (Exception &e)
{
e.Show (hwndDlg);
}
catch (...) { }
Error ("BOOT_LOADER_UPGRADE_FAILED");
return FALSE;
}
BOOL DoShortcutsUninstall (HWND hwndDlg, char *szDestDir)
{
char szLinkDir[TC_MAX_PATH];
char szTmp2[TC_MAX_PATH];
BOOL bSlash, bOK = FALSE;
HRESULT hOle;
int x;
BOOL allUsers = FALSE;
hOle = OleInitialize (NULL);
// User start menu
SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_PROGRAMS, 0);
x = strlen (szLinkDir);
if (szLinkDir[x - 1] == '\\')
bSlash = TRUE;
else
bSlash = FALSE;
if (bSlash == FALSE)
strcat (szLinkDir, "\\");
strcat (szLinkDir, "TrueCrypt");
// Global start menu
{
struct _stat st;
char path[TC_MAX_PATH];
SHGetSpecialFolderPath (hwndDlg, path, CSIDL_COMMON_PROGRAMS, 0);
strcat (path, "\\TrueCrypt");
if (_stat (path, &st) == 0)
{
strcpy (szLinkDir, path);
allUsers = TRUE;
}
}
// Start menu entries
sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk");
RemoveMessage (hwndDlg, szTmp2);
if (StatDeleteFile (szTmp2) == FALSE)
goto error;
sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt Website.url");
RemoveMessage (hwndDlg, szTmp2);
if (StatDeleteFile (szTmp2) == FALSE)
goto error;
sprintf (szTmp2, "%s%s", szLinkDir, "\\Uninstall TrueCrypt.lnk");
RemoveMessage (hwndDlg, szTmp2);
if (StatDeleteFile (szTmp2) == FALSE)
goto error;
sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt User's Guide.lnk");
DeleteFile (szTmp2);
// Start menu group
RemoveMessage ((HWND) hwndDlg, szLinkDir);
if (StatRemoveDirectory (szLinkDir) == FALSE)
handleWin32Error ((HWND) hwndDlg);
// Desktop icon
if (allUsers)
SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_COMMON_DESKTOPDIRECTORY, 0);
else
SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_DESKTOPDIRECTORY, 0);
sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk");
RemoveMessage (hwndDlg, szTmp2);
if (StatDeleteFile (szTmp2) == FALSE)
goto error;
bOK = TRUE;
error:
OleUninitialize ();
return bOK;
}
BOOL DoShortcutsInstall (HWND hwndDlg, char *szDestDir, BOOL bProgGroup, BOOL bDesktopIcon)
{
char szLinkDir[TC_MAX_PATH], szDir[TC_MAX_PATH];
char szTmp[TC_MAX_PATH], szTmp2[TC_MAX_PATH], szTmp3[TC_MAX_PATH];
BOOL bSlash, bOK = FALSE;
HRESULT hOle;
int x;
if (bProgGroup == FALSE && bDesktopIcon == FALSE)
return TRUE;
hOle = OleInitialize (NULL);
GetProgramPath (hwndDlg, szLinkDir);
x = strlen (szLinkDir);
if (szLinkDir[x - 1] == '\\')
bSlash = TRUE;
else
bSlash = FALSE;
if (bSlash == FALSE)
strcat (szLinkDir, "\\");
strcat (szLinkDir, "TrueCrypt");
strcpy (szDir, szDestDir);
x = strlen (szDestDir);
if (szDestDir[x - 1] == '\\')
bSlash = TRUE;
else
bSlash = FALSE;
if (bSlash == FALSE)
strcat (szDir, "\\");
if (bProgGroup)
{
FILE *f;
if (mkfulldir (szLinkDir, TRUE) != 0)
{
if (mkfulldir (szLinkDir, FALSE) != 0)
{
wchar_t szTmp[TC_MAX_PATH];
handleWin32Error (hwndDlg);
wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), szLinkDir);
MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND);
goto error;
}
}
sprintf (szTmp, "%s%s", szDir, "TrueCrypt.exe");
sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk");
IconMessage (hwndDlg, szTmp2);
if (CreateLink (szTmp, "", szTmp2) != S_OK)
goto error;
sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt Website.url");
IconMessage (hwndDlg, szTmp2);
f = fopen (szTmp2, "w");
if (f)
{
fprintf (f, "[InternetShortcut]\nURL=%s\n", TC_HOMEPAGE);
CheckFileStreamWriteErrors (f, szTmp2);
fclose (f);
}
else
goto error;
sprintf (szTmp, "%s%s", szDir, "TrueCrypt Setup.exe");
sprintf (szTmp2, "%s%s", szLinkDir, "\\Uninstall TrueCrypt.lnk");
strcpy (szTmp3, "/u");
IconMessage (hwndDlg, szTmp2);
if (CreateLink (szTmp, szTmp3, szTmp2) != S_OK)
goto error;
sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt User's Guide.lnk");
DeleteFile (szTmp2);
}
if (bDesktopIcon)
{
strcpy (szDir, szDestDir);
x = strlen (szDestDir);
if (szDestDir[x - 1] == '\\')
bSlash = TRUE;
else
bSlash = FALSE;
if (bSlash == FALSE)
strcat (szDir, "\\");
if (bForAllUsers)
SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_COMMON_DESKTOPDIRECTORY, 0);
else
SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_DESKTOPDIRECTORY, 0);
sprintf (szTmp, "%s%s", szDir, "TrueCrypt.exe");
sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk");
IconMessage (hwndDlg, szTmp2);
if (CreateLink (szTmp, "", szTmp2) != S_OK)
goto error;
}
bOK = TRUE;
error:
OleUninitialize ();
return bOK;
}
void OutcomePrompt (HWND hwndDlg, BOOL bOK)
{
if (bOK)
{
EnableWindow (GetDlgItem ((HWND) hwndDlg, IDCANCEL), FALSE);
bDone = TRUE;
if (bUninstall == FALSE)
{
if (bDevm)
PostMessage (MainDlg, WM_CLOSE, 0, 0);
else if (bPossiblyFirstTimeInstall || bRepairMode || (!bUpgrade && !bDowngrade))
Info ("INSTALL_OK");
else
Info ("SETUP_UPDATE_OK");
}
else
{
wchar_t str[4096];
swprintf (str, GetString ("UNINSTALL_OK"), InstallationPath);
MessageBoxW (hwndDlg, str, lpszTitle, MB_ICONASTERISK);
}
}
else
{
if (bUninstall == FALSE)
Error ("INSTALL_FAILED");
else
Error ("UNINSTALL_FAILED");
}
}
static void SetSystemRestorePoint (HWND hwndDlg, BOOL finalize)
{
static RESTOREPOINTINFO RestPtInfo;
static STATEMGRSTATUS SMgrStatus;
static BOOL failed = FALSE;
static BOOL (__stdcall *_SRSetRestorePoint)(PRESTOREPOINTINFO, PSTATEMGRSTATUS);
if (!SystemRestoreDll) return;
_SRSetRestorePoint = (BOOL (__stdcall *)(PRESTOREPOINTINFO, PSTATEMGRSTATUS))GetProcAddress (SystemRestoreDll,"SRSetRestorePointA");
if (_SRSetRestorePoint == 0)
{
FreeLibrary (SystemRestoreDll);
SystemRestoreDll = 0;
return;
}
if (!finalize)
{
StatusMessage (hwndDlg, "CREATING_SYS_RESTORE");
RestPtInfo.dwEventType = BEGIN_SYSTEM_CHANGE;
RestPtInfo.dwRestorePtType = bUninstall ? APPLICATION_UNINSTALL : APPLICATION_INSTALL | DEVICE_DRIVER_INSTALL;
RestPtInfo.llSequenceNumber = 0;
strcpy (RestPtInfo.szDescription, bUninstall ? "TrueCrypt uninstallation" : "TrueCrypt installation");
if(!_SRSetRestorePoint (&RestPtInfo, &SMgrStatus))
{
StatusMessage (hwndDlg, "FAILED_SYS_RESTORE");
failed = TRUE;
}
}
else if (!failed)
{
RestPtInfo.dwEventType = END_SYSTEM_CHANGE;
RestPtInfo.llSequenceNumber = SMgrStatus.llSequenceNumber;
if(!_SRSetRestorePoint(&RestPtInfo, &SMgrStatus))
{
StatusMessage (hwndDlg, "FAILED_SYS_RESTORE");
}
}
}
void DoUninstall (void *arg)
{
HWND hwndDlg = (HWND) arg;
BOOL bOK = TRUE;
BOOL bTempSkipSysRestore = FALSE;
if (!Rollback)
EnableWindow (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), FALSE);
WaitCursor ();
if (!Rollback)
{
ClearLogWindow (hwndDlg);
}
if (DoDriverUnload (hwndDlg) == FALSE)
{
bOK = FALSE;
bTempSkipSysRestore = TRUE; // Volumes are possibly mounted; defer System Restore point creation for this uninstall attempt.
}
else
{
if (!Rollback && bSystemRestore && !bTempSkipSysRestore)
SetSystemRestorePoint (hwndDlg, FALSE);
if (DoServiceUninstall (hwndDlg, "truecrypt") == FALSE)
{
bOK = FALSE;
}
else if (DoRegUninstall ((HWND) hwndDlg, FALSE) == FALSE)
{
bOK = FALSE;
}
else if (DoFilesInstall ((HWND) hwndDlg, InstallationPath) == FALSE)
{
bOK = FALSE;
}
else if (DoShortcutsUninstall (hwndDlg, InstallationPath) == FALSE)
{
bOK = FALSE;
}
else if (!DoApplicationDataUninstall (hwndDlg))
{
bOK = FALSE;
}
else
{
char temp[MAX_PATH];
FILE *f;
// Deprecated service
DoServiceUninstall (hwndDlg, "TrueCryptService");
GetTempPath (sizeof (temp), temp);
_snprintf (UninstallBatch, sizeof (UninstallBatch), "%s\\TrueCrypt-Uninstall.bat", temp);
UninstallBatch [sizeof(UninstallBatch)-1] = 0;
// Create uninstall batch
f = fopen (UninstallBatch, "w");
if (!f)
bOK = FALSE;
else
{
fprintf (f, ":loop\n"
"del \"%s%s\"\n"
"if exist \"%s%s\" goto loop\n"
"rmdir \"%s\"\n"
"del \"%s\"",
InstallationPath, "TrueCrypt Setup.exe",
InstallationPath, "TrueCrypt Setup.exe",
InstallationPath,
UninstallBatch
);
CheckFileStreamWriteErrors (f, UninstallBatch);
fclose (f);
}
}
}
NormalCursor ();
if (Rollback)
return;
if (bSystemRestore && !bTempSkipSysRestore)
SetSystemRestorePoint (hwndDlg, TRUE);
if (bOK)
PostMessage (hwndDlg, TC_APPMSG_UNINSTALL_SUCCESS, 0, 0);
else
bUninstallInProgress = FALSE;
EnableWindow (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), TRUE);
OutcomePrompt (hwndDlg, bOK);
}
void DoInstall (void *arg)
{
HWND hwndDlg = (HWND) arg;
BOOL bOK = TRUE;
char path[MAX_PATH];
BootEncryption bootEnc (hwndDlg);
// Refresh the main GUI (wizard thread)
InvalidateRect (MainDlg, NULL, TRUE);
ClearLogWindow (hwndDlg);
if (mkfulldir (InstallationPath, TRUE) != 0)
{
if (mkfulldir (InstallationPath, FALSE) != 0)
{
wchar_t szTmp[TC_MAX_PATH];
handleWin32Error (hwndDlg);
wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), InstallationPath);
MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND);
Error ("INSTALL_FAILED");
PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0);
return;
}
}
UpdateProgressBarProc(2);
if (DoDriverUnload (hwndDlg) == FALSE)
{
NormalCursor ();
PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0);
return;
}
if (bUpgrade
&& (IsFileInUse (string (InstallationPath) + '\\' + TC_APP_NAME ".exe")
|| IsFileInUse (string (InstallationPath) + '\\' + TC_APP_NAME " Format.exe")
|| IsFileInUse (string (InstallationPath) + '\\' + TC_APP_NAME " Setup.exe")
)
)
{
NormalCursor ();
Error ("CLOSE_TC_FIRST");
PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0);
return;
}
UpdateProgressBarProc(12);
if (bSystemRestore)
SetSystemRestorePoint (hwndDlg, FALSE);
UpdateProgressBarProc(48);
if (bDisableSwapFiles
&& IsPagingFileActive (FALSE))
{
if (!DisablePagingFile())
{
handleWin32Error (hwndDlg);
Error ("FAILED_TO_DISABLE_PAGING_FILES");
}
else
bRestartRequired = TRUE;
}
UpdateProgressBarProc(50);
// Remove deprecated
DoServiceUninstall (hwndDlg, "TrueCryptService");
UpdateProgressBarProc(55);
if (!SystemEncryptionUpdate)
DoRegUninstall ((HWND) hwndDlg, TRUE);
if (SystemEncryptionUpdate && InstalledVersion < 0x700)
{
try
{
bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter);
}
catch (...) { }
try
{
bootEnc.RegisterFilterDriver (true, BootEncryption::DumpFilter);
}
catch (Exception &e)
{
try
{
bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter);
}
catch (...) { }
e.Show (hwndDlg);
bOK = FALSE;
goto outcome;
}
if (ReadDriverConfigurationFlags() & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES)
{
WriteLocalMachineRegistryString ("SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Minimal\\" TC_SYSTEM_FAVORITES_SERVICE_NAME, NULL, "Service", FALSE);
WriteLocalMachineRegistryString ("SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Network\\" TC_SYSTEM_FAVORITES_SERVICE_NAME, NULL, "Service", FALSE);
}
}
UpdateProgressBarProc(61);
if (bUpgrade && InstalledVersion < 0x700)
{
bool bMountFavoritesOnLogon = ConfigReadInt ("MountFavoritesOnLogon", FALSE) != 0;
bool bOpenExplorerWindowAfterMount = ConfigReadInt ("OpenExplorerWindowAfterMount", FALSE) != 0;
if (bMountFavoritesOnLogon || bOpenExplorerWindowAfterMount)
{
char *favoritesFilename = GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES);
DWORD size;
char *favoritesXml = LoadFile (favoritesFilename, &size);
if (favoritesXml && size != 0)
{
string favorites;
favorites.insert (0, favoritesXml, size);
size_t p = favorites.find ("<volume ");
while (p != string::npos)
{
if (bMountFavoritesOnLogon)
favorites.insert (p + 8, "mountOnLogOn=\"1\" ");
if (bOpenExplorerWindowAfterMount)
favorites.insert (p + 8, "openExplorerWindow=\"1\" ");
p = favorites.find ("<volume ", p + 1);
}
SaveBufferToFile (favorites.c_str(), favoritesFilename, favorites.size(), FALSE);
if (bMountFavoritesOnLogon)
{
char regk[64];
char regVal[MAX_PATH * 2];
GetStartupRegKeyName (regk);
ReadRegistryString (regk, "TrueCrypt", "", regVal, sizeof (regVal));
if (strstr (regVal, "favorites"))
{
strcat_s (regVal, sizeof (regVal), " /a logon");
WriteRegistryString (regk, "TrueCrypt", regVal);
}
}
}
if (favoritesXml)
free (favoritesXml);
}
}
GetWindowsDirectory (path, sizeof (path));
strcat_s (path, sizeof (path), "\\TrueCrypt Setup.exe");
DeleteFile (path);
if (UpdateProgressBarProc(63) && UnloadDriver && DoServiceUninstall (hwndDlg, "truecrypt") == FALSE)
{
bOK = FALSE;
}
else if (UpdateProgressBarProc(72) && DoFilesInstall ((HWND) hwndDlg, InstallationPath) == FALSE)
{
bOK = FALSE;
}
else if (UpdateProgressBarProc(80) && DoRegInstall ((HWND) hwndDlg, InstallationPath, bRegisterFileExt) == FALSE)
{
bOK = FALSE;
}
else if (UpdateProgressBarProc(85) && UnloadDriver && DoDriverInstall (hwndDlg) == FALSE)
{
bOK = FALSE;
}
else if (UpdateProgressBarProc(90) && SystemEncryptionUpdate && UpgradeBootLoader (hwndDlg) == FALSE)
{
bOK = FALSE;
}
else if (UpdateProgressBarProc(93) && DoShortcutsInstall (hwndDlg, InstallationPath, bAddToStartMenu, bDesktopIcon) == FALSE)
{
bOK = FALSE;
}
if (!UnloadDriver)
bRestartRequired = TRUE;
try
{
bootEnc.RenameDeprecatedSystemLoaderBackup();
}
catch (...) { }
if (SystemEncryptionUpdate && InstalledVersion == 0x630)
{
string sysFavorites = GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES);
string legacySysFavorites = GetProgramConfigPath ("System Favorite Volumes.xml");
if (FileExists (legacySysFavorites.c_str()) && !FileExists (sysFavorites.c_str()))
MoveFile (legacySysFavorites.c_str(), sysFavorites.c_str());
}
if (bOK)
UpdateProgressBarProc(97);
if (bSystemRestore)
SetSystemRestorePoint (hwndDlg, TRUE);
if (bOK)
{
UpdateProgressBarProc(100);
UninstallBatch[0] = 0;
StatusMessage (hwndDlg, "INSTALL_COMPLETED");
}
else
{
UpdateProgressBarProc(0);
if (!SystemEncryptionUpdate)
{
bUninstall = TRUE;
Rollback = TRUE;
Silent = TRUE;
DoUninstall (hwndDlg);
bUninstall = FALSE;
Rollback = FALSE;
Silent = FALSE;
StatusMessage (hwndDlg, "ROLLBACK");
}
else
{
Warning ("SYS_ENC_UPGRADE_FAILED");
}
}
outcome:
OutcomePrompt (hwndDlg, bOK);
if (bOK && !bUninstall && !bDowngrade && !bRepairMode && !bDevm)
{
if (!IsHiddenOSRunning()) // A hidden OS user should not see the post-install notes twice (on decoy OS and then on hidden OS).
{
if (bRestartRequired || SystemEncryptionUpdate)
{
// Restart required
if (bUpgrade)
{
SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_RELEASE_NOTES);
}
else if (bPossiblyFirstTimeInstall)
{
SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_TUTORIAL);
}
}
else
{
// No restart will be required
if (bUpgrade)
{
bPromptReleaseNotes = TRUE;
}
else if (bPossiblyFirstTimeInstall)
{
bPromptTutorial = TRUE;
}
}
}
}
PostMessage (MainDlg, bOK ? TC_APPMSG_INSTALL_SUCCESS : TC_APPMSG_INSTALL_FAILURE, 0, 0);
}
void SetInstallationPath (HWND hwndDlg)
{
HKEY hkey;
BOOL bInstallPathDetermined = FALSE;
char path[MAX_PATH+20];
ITEMIDLIST *itemList;
memset (InstallationPath, 0, sizeof (InstallationPath));
// Determine if TrueCrypt is already installed and try to determine its "Program Files" location
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt", 0, KEY_READ, &hkey) == ERROR_SUCCESS)
{
/* Default 'UninstallString' registry strings written by past versions of TrueCrypt:
------------------------------------------------------------------------------------
1.0 C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
1.0a C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
2.0 C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
2.1 C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
2.1a C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
3.0 C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
3.0a C:\WINDOWS\TrueCrypt Setup.exe /u [optional]
3.1 The UninstallString was NEVER written (fortunately, 3.1a replaced 3.1 after 2 weeks)
3.1a C:\WINDOWS\TrueCrypt Setup.exe /u
4.0 C:\WINDOWS\TrueCrypt Setup.exe /u C:\Program Files\TrueCrypt
4.1 C:\WINDOWS\TrueCrypt Setup.exe /u C:\Program Files\TrueCrypt
4.2 C:\WINDOWS\TrueCrypt Setup.exe /u C:\Program Files\TrueCrypt
4.2a C:\WINDOWS\TrueCrypt Setup.exe /u C:\Program Files\TrueCrypt
4.3 "C:\Program Files\TrueCrypt\TrueCrypt Setup.exe" /u C:\Program Files\TrueCrypt\
4.3a "C:\Program Files\TrueCrypt\TrueCrypt Setup.exe" /u C:\Program Files\TrueCrypt\
5.0+ "C:\Program Files\TrueCrypt\TrueCrypt Setup.exe" /u
Note: In versions 1.0-3.0a the user was able to choose whether to install the uninstaller.
The default was to install it. If it wasn't installed, there was no UninstallString.
*/
char rv[MAX_PATH*4];
DWORD size = sizeof (rv);
if (RegQueryValueEx (hkey, "UninstallString", 0, 0, (LPBYTE) &rv, &size) == ERROR_SUCCESS && strrchr (rv, '/'))
{
size_t len = 0;
// Cut and paste the location (path) where TrueCrypt is installed to InstallationPath
if (rv[0] == '"')
{
// 4.3 or later
len = strrchr (rv, '/') - rv - 2;
strncpy (InstallationPath, rv + 1, len);
InstallationPath [len] = 0;
bInstallPathDetermined = TRUE;
if (InstallationPath [strlen (InstallationPath) - 1] != '\\')
{
len = strrchr (InstallationPath, '\\') - InstallationPath;
InstallationPath [len] = 0;
}
}
else
{
// 1.0-4.2a (except 3.1)
len = strrchr (rv, '/') - rv;
if (rv[len+2] == ' ')
{
// 4.0-4.2a
strncpy (InstallationPath, rv + len + 3, strlen (rv) - len - 3);
InstallationPath [strlen (rv) - len - 3] = 0;
bInstallPathDetermined = TRUE;
}
else
{
// 1.0-3.1a (except 3.1)
// We know that TrueCrypt is installed but don't know where. It's not safe to continue installing
// over the old version.
Error ("UNINSTALL_OLD_VERSION_FIRST");
len = strrchr (rv, '/') - rv - 1;
strncpy (InstallationPath, rv, len); // Path and filename of the uninstaller
InstallationPath [len] = 0;
bInstallPathDetermined = FALSE;
ShellExecute (NULL, "open", InstallationPath, "/u", NULL, SW_SHOWNORMAL);
RegCloseKey (hkey);
exit (1);
}
}
}
RegCloseKey (hkey);
}
if (bInstallPathDetermined)
{
char mp[MAX_PATH];
// Determine whether we were launched from the folder where TrueCrypt is installed
GetModuleFileName (NULL, mp, sizeof (mp));
if (strncmp (InstallationPath, mp, min (strlen(InstallationPath), strlen(mp))) == 0)
{
// We were launched from the folder where TrueCrypt is installed
if (!IsNonInstallMode() && !bDevm)
bChangeMode = TRUE;
}
}
else
{
/* TrueCypt is not installed or it wasn't possible to determine where it is installed. */
// Default "Program Files" path.
SHGetSpecialFolderLocation (hwndDlg, CSIDL_PROGRAM_FILES, &itemList);
SHGetPathFromIDList (itemList, path);
if (Is64BitOs())
{
// Use a unified default installation path (registry redirection of %ProgramFiles% does not work if the installation path is user-selectable)
string s = path;
size_t p = s.find (" (x86)");
if (p != string::npos)
{
s = s.substr (0, p);
if (_access (s.c_str(), 0) != -1)
strcpy_s (path, sizeof (path), s.c_str());
}
}
strncat (path, "\\TrueCrypt\\", min (strlen("\\TrueCrypt\\"), sizeof(path)-strlen(path)-1));
strncpy (InstallationPath, path, sizeof(InstallationPath)-1);
}
// Make sure the path ends with a backslash
if (InstallationPath [strlen (InstallationPath) - 1] != '\\')
{
strcat (InstallationPath, "\\");
}
}
// Handler for uninstall only (install is handled by the wizard)
BOOL CALLBACK UninstallDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
WORD lw = LOWORD (wParam);
switch (msg)
{
case WM_INITDIALOG:
MainDlg = hwndDlg;
if (!CreateAppSetupMutex ())
AbortProcess ("TC_INSTALLER_IS_RUNNING");
InitDialog (hwndDlg);
LocalizeDialog (hwndDlg, NULL);
SetWindowTextW (hwndDlg, lpszTitle);
// System Restore
SetCheckBox (hwndDlg, IDC_SYSTEM_RESTORE, bSystemRestore);
if (SystemRestoreDll == 0)
{
SetCheckBox (hwndDlg, IDC_SYSTEM_RESTORE, FALSE);
EnableWindow (GetDlgItem (hwndDlg, IDC_SYSTEM_RESTORE), FALSE);
}
SetFocus (GetDlgItem (hwndDlg, IDC_UNINSTALL));
return 1;
case WM_SYSCOMMAND:
if (lw == IDC_ABOUT)
{
DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc);
return 1;
}
return 0;
case WM_COMMAND:
if (lw == IDC_UNINSTALL)
{
if (bDone)
{
bUninstallInProgress = FALSE;
PostMessage (hwndDlg, WM_CLOSE, 0, 0);
return 1;
}
bUninstallInProgress = TRUE;
WaitCursor ();
if (bUninstall)
_beginthread (DoUninstall, 0, (void *) hwndDlg);
return 1;
}
if (lw == IDC_SYSTEM_RESTORE)
{
bSystemRestore = IsButtonChecked (GetDlgItem (hwndDlg, IDC_SYSTEM_RESTORE));
return 1;
}
if (lw == IDCANCEL)
{
PostMessage (hwndDlg, WM_CLOSE, 0, 0);
return 1;
}
return 0;
case TC_APPMSG_UNINSTALL_SUCCESS:
SetWindowTextW (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), GetString ("FINALIZE"));
NormalCursor ();
return 1;
case WM_CLOSE:
if (bUninstallInProgress)
{
NormalCursor();
if (AskNoYes("CONFIRM_EXIT_UNIVERSAL") == IDNO)
{
return 1;
}
WaitCursor ();
}
EndDialog (hwndDlg, IDCANCEL);
return 1;
}
return 0;
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpszCommandLine, int nCmdShow)
{
atexit (localcleanup);
SelfExtractStartupInit();
lpszTitle = L"TrueCrypt Setup";
InitCommonControls ();
/* Call InitApp to initialize the common code */
InitApp (hInstance, NULL);
if (IsAdmin () != TRUE)
if (MessageBoxW (NULL, GetString ("SETUP_ADMIN"), lpszTitle, MB_YESNO | MB_ICONQUESTION) != IDYES)
{
exit (1);
}
/* Setup directory */
{
char *s;
GetModuleFileName (NULL, SetupFilesDir, sizeof (SetupFilesDir));
s = strrchr (SetupFilesDir, '\\');
if (s)
s[1] = 0;
}
/* Parse command line arguments */
if (lpszCommandLine[0] == '/')
{
if (lpszCommandLine[1] == 'u')
{
// Uninstall: /u
bUninstall = TRUE;
}
else if (lpszCommandLine[1] == 'c')
{
// Change: /c
bChangeMode = TRUE;
}
else if (lpszCommandLine[1] == 'p')
{
// Create self-extracting package: /p
bMakePackage = TRUE;
}
else if (lpszCommandLine[1] == 'd')
{
// Dev mode: /d
bDevm = TRUE;
}
}
if (bMakePackage)
{
/* Create self-extracting package */
MakeSelfExtractingPackage (NULL, SetupFilesDir);
}
else
{
SetInstallationPath (NULL);
if (!bUninstall)
{
if (IsSelfExtractingPackage())
{
if (!VerifyPackageIntegrity())
{
// Package corrupted
exit (1);
}
bDevm = FALSE;
}
else if (!bDevm)
{
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);
exit (1);
}
if (bChangeMode)
{
/* TrueCrypt is already installed on this system and we were launched from the Program Files folder */
char *tmpStr[] = {0, "SELECT_AN_ACTION", "REPAIR_REINSTALL", "UNINSTALL", "EXIT", 0};
// Ask the user to select either Repair or Unistallation
switch (AskMultiChoice ((void **) tmpStr, FALSE))
{
case 1:
bRepairMode = TRUE;
break;
case 2:
bUninstall = TRUE;
break;
default:
exit (1);
}
}
}
// System Restore
SystemRestoreDll = LoadLibrary ("srclient.dll");
if (!bUninstall)
{
/* Create the main dialog for install */
DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_INSTL_DLG), NULL, (DLGPROC) MainDialogProc,
(LPARAM)lpszCommandLine);
}
else
{
/* Create the main dialog for uninstall */
DialogBoxW (hInstance, MAKEINTRESOURCEW (IDD_UNINSTALL), NULL, (DLGPROC) UninstallDlgProc);
if (UninstallBatch[0])
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory (&si, sizeof (si));
si.cb = sizeof (si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
if (!CreateProcess (UninstallBatch, NULL, NULL, NULL, FALSE, IDLE_PRIORITY_CLASS, NULL, NULL, &si, &pi))
DeleteFile (UninstallBatch);
else
{
CloseHandle (pi.hProcess);
CloseHandle (pi.hThread);
}
}
}
}
return 0;
}