/* Legal Notice: Some portions of the source code contained in this file were derived from the source code of TrueCrypt 7.1a, which is Copyright (c) 2003-2012 TrueCrypt Developers Association and which is governed by the TrueCrypt License 3.0, also 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) 2013-2017 IDRIX and are governed by the Apache License 2.0 the full text of which is contained in the file License.txt included in VeraCrypt binary and source code distribution packages. */ #include "Tcdefs.h" #include #include #include #include #include #include #include #include #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 "../Common/Resource.h" #pragma comment(lib, "Shlwapi.lib") using namespace VeraCrypt; #pragma warning( disable : 4201 ) #pragma warning( disable : 4115 ) #include #pragma warning( default : 4201 ) #pragma warning( default : 4115 ) #include #include #include #include #include #if !defined(va_copy) #define va_copy(d, s) ((d) = (s)) #endif typedef enum { MSI_INFO_LEVEL = 0, MSI_WARNING_LEVEL, MSI_ERROR_LEVEL } eMSILogLevel; #define WAIT_PERIOD 3 wchar_t InstallationPath[TC_MAX_PATH]; BOOL bUninstall = FALSE; BOOL bDowngrade = FALSE; BOOL bUninstallInProgress = FALSE; BOOL PortableMode = FALSE; BOOL UnloadDriver = TRUE; BOOL Rollback = FALSE; BOOL bReinstallMode = FALSE; BOOL bUpgrade = FALSE; BOOL bPossiblyFirstTimeInstall = FALSE; BOOL bDevm = FALSE; BOOL SystemEncryptionUpdate = FALSE; BOOL bRestartRequired = FALSE; BOOL bDisableSwapFiles = FALSE; BOOL bSystemRestore = TRUE; HMODULE volatile SystemRestoreDll = 0; BOOL bPromptFastStartup = FALSE; BOOL bPromptReleaseNotes = FALSE; BOOL bPromptTutorial = FALSE; BOOL bUpdateRescueDisk = FALSE; BOOL bRepairMode = FALSE; BOOL bUserSetLanguage = FALSE; /* BOOL bMakePackage = FALSE; BOOL bDone = FALSE; BOOL bForAllUsers = TRUE; BOOL bRegisterFileExt = TRUE; BOOL bAddToStartMenu = TRUE; BOOL bDesktopIcon = TRUE; BOOL bDesktopIconStatusDetermined = FALSE; */ /* **************************************************************************** */ /* Defined in this file, but a little bit late */ BOOL IsSystemRestoreEnabled (); /* * Same as in Setup.c */ BOOL ForceCopyFile (LPCWSTR szSrcFile, LPCWSTR szDestFile) { BOOL bRet = CopyFileW (szSrcFile, szDestFile, FALSE); if (!bRet) { wstring renamedPath = szDestFile; renamedPath += VC_FILENAME_RENAMED_SUFFIX; /* rename the locked file in order to be able to create a new one */ if (MoveFileExW (szDestFile, renamedPath.c_str(), MOVEFILE_REPLACE_EXISTING)) { bRet = CopyFileW (szSrcFile, szDestFile, FALSE); if (bRet) { /* delete the renamed file when the machine reboots */ MoveFileEx (renamedPath.c_str(), NULL, MOVEFILE_DELAY_UNTIL_REBOOT); } else { /* restore the original file name */ MoveFileEx (renamedPath.c_str(), szDestFile, MOVEFILE_REPLACE_EXISTING); } } } return bRet; } /* * Same as in Setup.c */ BOOL ForceDeleteFile (LPCWSTR szFileName) { if (!DeleteFile (szFileName)) { /* delete the renamed file when the machine reboots */ return MoveFileEx (szFileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); } else return TRUE; } /* * Same as in Setup.c */ BOOL StatDeleteFile (wchar_t *lpszFile, BOOL bCheckForOldFile) { struct __stat64 st; if (bCheckForOldFile) { wchar_t szOldPath[MAX_PATH + 1]; StringCbCopyW (szOldPath, sizeof(szOldPath), lpszFile); StringCbCatW (szOldPath, sizeof(szOldPath), VC_FILENAME_RENAMED_SUFFIX); if (_wstat64 (szOldPath, &st) == 0) { ForceDeleteFile (szOldPath); } } if (_wstat64 (lpszFile, &st) == 0) return ForceDeleteFile (lpszFile); else return TRUE; } /* * Same as in Setup.c */ BOOL StatRemoveDirectory (wchar_t *lpszDir) { struct __stat64 st; if (_wstat64 (lpszDir, &st) == 0) { return DeleteDirectory (lpszDir); } else return TRUE; } /* * Same as in Setup.c */ 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); } /* * Same as in Setup.c */ void DetermineUpgradeDowngradeStatus (BOOL bCloseDriverHandle, LONG *driverVersionPtr) { LONG driverVersion = VERSION_NUM; int status = 0; if (hDriver == INVALID_HANDLE_VALUE) status = DriverAttach(); if ((status == 0) && (hDriver != INVALID_HANDLE_VALUE)) { DWORD dwResult; BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &driverVersion, sizeof (driverVersion), &dwResult, NULL); bUpgrade = (bResult && driverVersion <= VERSION_NUM); bDowngrade = (bResult && driverVersion > VERSION_NUM); bReinstallMode = (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; } /* * Same as in Setup.c */ BOOL IsSystemRestoreEnabled () { BOOL bEnabled = FALSE; HKEY hKey; DWORD dwValue = 0, cbValue = sizeof (DWORD); wchar_t szRegPath[MAX_PATH]; GetRestorePointRegKeyName (szRegPath, sizeof (szRegPath)); if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szRegPath, 0, KEY_READ | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS) { if ( (ERROR_SUCCESS == RegQueryValueEx (hKey, L"RPSessionInterval", NULL, NULL, (LPBYTE) &dwValue, &cbValue)) && (dwValue == 1) ) { bEnabled = TRUE; } RegCloseKey (hKey); } return bEnabled; } /* * Same as in Setup.c */ static void RecursiveSetOwner (HKEY hKey, PSECURITY_DESCRIPTOR pSD) { LSTATUS status = 0; DWORD dwIndex = 0, dwMaxNameLen = 0, dwNameLen = 0, numberSubKeys = 0; HKEY hSubKey; if ( (ERROR_SUCCESS == status) && (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, &numberSubKeys, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL)) && (numberSubKeys >= 1) ) { dwMaxNameLen++; wchar_t* szNameValue = new wchar_t[dwMaxNameLen]; while (true) { dwNameLen = dwMaxNameLen; status = RegEnumKeyExW (hKey, dwIndex++, szNameValue, &dwNameLen, NULL, NULL, NULL, NULL); if (status == ERROR_SUCCESS) { status = RegOpenKeyExW (hKey, szNameValue, 0, WRITE_OWNER | KEY_READ , &hSubKey); if (ERROR_SUCCESS == status) { RecursiveSetOwner (hSubKey, pSD); RegCloseKey(hSubKey); } } else break; } delete [] szNameValue; } RegSetKeySecurity (hKey, OWNER_SECURITY_INFORMATION, pSD); } /* * Same as in Setup.c */ static void RecursiveSetDACL (HKEY hKey, const wchar_t* SubKeyName, PSECURITY_DESCRIPTOR pSD) { HKEY hSubKey; DWORD dwIndex = 0, dwMaxNameLen = 0, dwNameLen = 0, numberSubKeys = 0; LSTATUS status = RegOpenKeyExW(hKey, SubKeyName, 0, WRITE_DAC | KEY_READ /*| ACCESS_SYSTEM_SECURITY*/, &hSubKey); if (status == ERROR_SUCCESS) { status = RegSetKeySecurity (hSubKey, DACL_SECURITY_INFORMATION, pSD); if (status == ERROR_SUCCESS) { RegCloseKey(hSubKey); status = RegOpenKeyExW(hKey, SubKeyName, 0, WRITE_DAC | KEY_READ , &hSubKey); } if ( (ERROR_SUCCESS == status) && (ERROR_SUCCESS == RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &numberSubKeys, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL)) && (numberSubKeys >= 1) ) { dwMaxNameLen++; wchar_t* szNameValue = new wchar_t[dwMaxNameLen]; while (true) { dwNameLen = dwMaxNameLen; status = RegEnumKeyExW (hSubKey, dwIndex++, szNameValue, &dwNameLen, NULL, NULL, NULL, NULL); if (status == ERROR_SUCCESS) { RecursiveSetDACL (hSubKey, szNameValue, pSD); } else break; } delete [] szNameValue; } } } /* * Same as in Setup.c */ static void AllowKeyAccess(HKEY Key,const wchar_t* SubKeyName) { LSTATUS RegResult; HKEY SvcKey = NULL; DWORD dwLength = 0; HANDLE Token = NULL; PTOKEN_USER pTokenUser = NULL; std::string sNewSD; RegResult = RegOpenKeyExW(Key, SubKeyName, 0, WRITE_OWNER | KEY_READ, &SvcKey); if (RegResult==ERROR_SUCCESS) { if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token)) { if (!GetTokenInformation(Token, TokenUser, pTokenUser, 0, &dwLength)) { if (GetLastError() ==ERROR_INSUFFICIENT_BUFFER) { pTokenUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (pTokenUser) { if (GetTokenInformation(Token, TokenUser, pTokenUser, dwLength, &dwLength)) { SECURITY_DESCRIPTOR SecDesc; if ( InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION) && SetSecurityDescriptorDacl(&SecDesc, TRUE, NULL, FALSE) // NULL DACL: full access to everyone && SetSecurityDescriptorOwner(&SecDesc, pTokenUser->User.Sid, FALSE) ) { RecursiveSetOwner(SvcKey, &SecDesc); } } } } } } RegCloseKey(SvcKey); } if (pTokenUser) { PSID pSid = pTokenUser->User.Sid; DWORD dwAclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + ::GetLengthSid(pSid) - sizeof(DWORD); PACL pDacl = (PACL) new BYTE[dwAclSize]; if (pDacl) { if (TRUE == ::InitializeAcl(pDacl, dwAclSize, ACL_REVISION)) { if (TRUE == AddAccessAllowedAceEx(pDacl, ACL_REVISION, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, WRITE_DAC | KEY_ALL_ACCESS, pSid)) { SECURITY_DESCRIPTOR SecDesc; if (TRUE == ::InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION)) { if (TRUE == ::SetSecurityDescriptorDacl(&SecDesc, TRUE, pDacl, FALSE)) { RecursiveSetDACL (Key, SubKeyName, &SecDesc); } } } } delete [] pDacl; } } if (pTokenUser) HeapFree(GetProcessHeap(), 0, pTokenUser); if (Token) CloseHandle(Token); } /* * Same as in Setup.c */ void SearchAndDeleteRegistrySubString (HKEY hKey, const wchar_t *subKey, const wchar_t *str, BOOL bEnumSubKeys, const wchar_t* enumMatchSubStr) { HKEY hSubKey = 0; LSTATUS status = 0; DWORD dwIndex = 0, dwType, dwValueNameLen, dwDataLen; std::list subKeysList; size_t subStringLength = str? wcslen(str) : 0; if (bEnumSubKeys) { DWORD dwMaxNameLen = 0; if (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL)) { dwMaxNameLen++; wchar_t* szNameValue = new wchar_t[dwMaxNameLen]; dwIndex = 0; while (true) { dwValueNameLen = dwMaxNameLen; status = RegEnumKeyExW (hKey, dwIndex++, szNameValue, &dwValueNameLen, NULL, NULL, NULL, NULL); if (status == ERROR_SUCCESS) { if (enumMatchSubStr && !wcsstr(szNameValue, enumMatchSubStr)) continue; std::wstring entryName = szNameValue; entryName += L"\\"; entryName += subKey; entryName += L"\\"; subKeysList.push_back(entryName); } else break; } delete [] szNameValue; } } else { subKeysList.push_back(subKey); } for (std::list::iterator ItSubKey = subKeysList.begin(); ItSubKey != subKeysList.end(); ItSubKey++) { // if the string to search for is empty, delete the sub key, otherwise, look for matching value and delete them if (subStringLength == 0) { if (ERROR_ACCESS_DENIED == DeleteRegistryKey (hKey, ItSubKey->c_str())) { // grant permission to delete AllowKeyAccess (hKey, ItSubKey->c_str()); // try again DeleteRegistryKey (hKey, ItSubKey->c_str()); } } else { if (RegOpenKeyExW (hKey, ItSubKey->c_str(), 0, KEY_ALL_ACCESS, &hSubKey) == ERROR_SUCCESS) { DWORD dwMaxNameLen = 0, dwMaxDataLen = 0; if (ERROR_SUCCESS == RegQueryInfoKey(hSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxNameLen, &dwMaxDataLen, NULL, NULL)) { dwMaxNameLen++; wchar_t* szNameValue = new wchar_t[dwMaxNameLen]; LPBYTE pbData = new BYTE[dwMaxDataLen]; std::list foundEntries; dwIndex = 0; do { dwValueNameLen = dwMaxNameLen; dwDataLen = dwMaxDataLen; status = RegEnumValueW(hSubKey, dwIndex++, szNameValue, &dwValueNameLen, NULL, &dwType, pbData, &dwDataLen); if (status == ERROR_SUCCESS) { if ( (wcslen(szNameValue) >= subStringLength && wcsstr(szNameValue, str)) || (dwType == REG_SZ && wcslen((wchar_t*) pbData) >= subStringLength && wcsstr((wchar_t*) pbData, str)) ) { foundEntries.push_back(szNameValue); } } } while ((status == ERROR_SUCCESS) || (status == ERROR_MORE_DATA)); // we ignore ERROR_MORE_DATA errors since // we are sure to use the correct sizes // delete the entries if (!foundEntries.empty()) { for (std::list::iterator It = foundEntries.begin(); It != foundEntries.end(); It++) { RegDeleteValueW (hSubKey, It->c_str()); } } delete [] szNameValue; delete [] pbData; } RegCloseKey (hSubKey); } } } } /* **************************************************************************** */ // Adds a line to the log file of the installer. void MSILog(MSIHANDLE hInstall, eMSILogLevel level, const wchar_t* zcFormat, ...) { std::wstring wszMessage; // initialize use of the variable argument array va_list vaArgs; va_start(vaArgs, zcFormat); // reliably acquire the size // from a copy of the variable argument array // and a functionally reliable call to mock the formatting va_list vaArgsCopy; va_copy(vaArgsCopy, vaArgs); const int iLen = vswprintf(NULL, 0, zcFormat, vaArgsCopy); va_end(vaArgsCopy); // return a formatted string without risking memory mismanagement // and without assuming any compiler or platform specific behavior std::vector zc(iLen + 1); vswprintf(zc.data(), zc.size(), zcFormat, vaArgs); va_end(vaArgs); wszMessage.assign(zc.data(), iLen); #ifdef TEST_HARNESS if (!hInstall) { MessageBox(NULL, pszMessage, wszMessage.c_str(), 0); return; } #endif PMSIHANDLE hRecord = MsiCreateRecord(1); // field 0 is the template MsiRecordSetString(hRecord, 0, (level == MSI_INFO_LEVEL) ? L"VeraCryptCustomAction_INFO: [1]" : ((level == MSI_WARNING_LEVEL) ? L"VeraCryptCustomAction_WARNING: [1]" : L"VeraCryptCustomAction_ERROR: [1]")); // field 1, to be placed in [1] placeholder MsiRecordSetString(hRecord, 1, wszMessage.c_str()); // send message to running installer MsiProcessMessage(hInstall, INSTALLMESSAGE_INFO, hRecord); } // Adds a line to the log file of the installer and shows a popup. // Since MsiProcessMessage() takes the UILEVEL into account, // this won't cause a deadlock in case of a silent install. void MSILogAndShow(MSIHANDLE hInstall, eMSILogLevel level, const wchar_t* zcFormat, ...) { std::wstring wszMessage; // initialize use of the variable argument array va_list vaArgs; va_start(vaArgs, zcFormat); // reliably acquire the size // from a copy of the variable argument array // and a functionally reliable call to mock the formatting va_list vaArgsCopy; va_copy(vaArgsCopy, vaArgs); const int iLen = vswprintf(NULL, 0, zcFormat, vaArgsCopy); va_end(vaArgsCopy); // return a formatted string without risking memory mismanagement // and without assuming any compiler or platform specific behavior std::vector zc(iLen + 1); vswprintf(zc.data(), zc.size(), zcFormat, vaArgs); va_end(vaArgs); wszMessage.assign(zc.data(), iLen); #ifdef TEST_HARNESS if (!hInstall) { MessageBox(NULL, pszMessage, wszMessage.c_str(), 0); return; } #endif PMSIHANDLE hRecord0 = MsiCreateRecord(1); // field 0 is the template MsiRecordSetString(hRecord0, 0, (level == MSI_INFO_LEVEL) ? L"VeraCryptCustomAction_INFO: [1]" : ((level == MSI_WARNING_LEVEL) ? L"VeraCryptCustomAction_WARNING: [1]" : L"VeraCryptCustomAction_ERROR: [1]")); // field 1, to be placed in [1] placeholder MsiRecordSetString(hRecord0, 1, wszMessage.c_str()); // send message to running installer MsiProcessMessage(hInstall, INSTALLMESSAGE_INFO, hRecord0); PMSIHANDLE hRecord1 = MsiCreateRecord(0); MsiRecordSetString(hRecord1, 0, wszMessage.c_str()); if (level == MSI_INFO_LEVEL) MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO + MB_OK), hRecord1); else if (level == MSI_WARNING_LEVEL) MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord1); else MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord1); } /* **************************************************************************** */ /* * Defined in Dlgcode.c. */ extern void ExceptionHandlerThread (void *threadArg); extern LONG __stdcall ExceptionHandler (EXCEPTION_POINTERS *ep); extern void InvalidParameterHandler (const wchar_t *expression, const wchar_t *function, const wchar_t *file, unsigned int line, uintptr_t reserved); extern BOOL SystemFileSelectorCallPending; extern DWORD SystemFileSelectorCallerThreadId; /* **************************************************************************** */ /* * Same as in Dlgcode.c, Applink() , but * removed unnecessary code. */ void Applink_Dll (MSIHANDLE hInstaller, const char *dest) { wchar_t url [MAX_URL_LENGTH] = {0}; wchar_t page[TC_MAX_PATH] = {0}; wchar_t installDir[TC_MAX_PATH] = {0}; BOOL buildUrl = TRUE; int r; StringCbCopyW (installDir, sizeof (installDir), InstallationPath); if (strcmp(dest, "donate") == 0) { StringCbCopyW (page, sizeof (page),L"Donation.html"); } else if (strcmp(dest, "main") == 0) { StringCbCopyW (url, sizeof (url), TC_HOMEPAGE); buildUrl = FALSE; } else if (strcmp(dest,"localizations") == 0) { StringCbCopyW (page, sizeof (page),L"Language%20Packs.html"); } else if (strcmp(dest, "beginnerstutorial") == 0 || strcmp(dest,"tutorial") == 0) { StringCbCopyW (page, sizeof (page),L"Beginner%27s%20Tutorial.html"); } else if (strcmp(dest, "releasenotes") == 0 || strcmp(dest, "history") == 0) { StringCbCopyW (page, sizeof (page),L"Release%20Notes.html"); } else if (strcmp(dest, "hwacceleration") == 0) { StringCbCopyW (page, sizeof (page),L"Hardware%20Acceleration.html"); } else if (strcmp(dest, "parallelization") == 0) { StringCbCopyW (page, sizeof (page),L"Parallelization.html"); } else if (strcmp(dest, "help") == 0) { StringCbCopyW (page, sizeof (page),L"Documentation.html"); } else if (strcmp(dest, "onlinehelp") == 0) { StringCbCopyW (url, sizeof (url),L"https://www.veracrypt.fr/en/Documentation.html"); buildUrl = FALSE; } else if (strcmp(dest, "keyfiles") == 0) { StringCbCopyW (page, sizeof (page),L"Keyfiles.html"); } else if (strcmp(dest, "introcontainer") == 0) { StringCbCopyW (page, sizeof (page),L"Creating%20New%20Volumes.html"); } else if (strcmp(dest, "introsysenc") == 0) { StringCbCopyW (page, sizeof (page),L"System%20Encryption.html"); } else if (strcmp(dest, "hiddensysenc") == 0) { StringCbCopyW (page, sizeof (page),L"VeraCrypt%20Hidden%20Operating%20System.html"); } else if (strcmp(dest, "sysencprogressinfo") == 0) { StringCbCopyW (page, sizeof (page),L"System%20Encryption.html"); } else if (strcmp(dest, "hiddenvolume") == 0) { StringCbCopyW (page, sizeof (page),L"Hidden%20Volume.html"); } else if (strcmp(dest, "aes") == 0) { StringCbCopyW (page, sizeof (page),L"AES.html"); } else if (strcmp(dest, "serpent") == 0) { StringCbCopyW (page, sizeof (page),L"Serpent.html"); } else if (strcmp(dest, "twofish") == 0) { StringCbCopyW (page, sizeof (page),L"Twofish.html"); } else if (strcmp(dest, "kuznyechik") == 0) { StringCbCopyW (page, sizeof (page),L"Kuznyechik.html"); } else if (strcmp(dest, "camellia") == 0) { StringCbCopyW (page, sizeof (page),L"Camellia.html"); } else if (strcmp(dest, "cascades") == 0) { StringCbCopyW (page, sizeof (page),L"Cascades.html"); } else if (strcmp(dest, "hashalgorithms") == 0) { StringCbCopyW (page, sizeof (page),L"Hash%20Algorithms.html"); } else if (strcmp(dest, "isoburning") == 0) { StringCbCopyW (url, sizeof (url),L"https://cdburnerxp.se/en/home"); buildUrl = FALSE; } else if (strcmp(dest, "sysfavorites") == 0) { StringCbCopyW (page, sizeof (page),L"System%20Favorite%20Volumes.html"); } else if (strcmp(dest, "favorites") == 0) { StringCbCopyW (page, sizeof (page),L"Favorite%20Volumes.html"); } else if (strcmp(dest, "hiddenvolprotection") == 0) { StringCbCopyW (page, sizeof (page),L"Protection%20of%20Hidden%20Volumes.html"); } else if (strcmp(dest, "faq") == 0) { StringCbCopyW (page, sizeof (page),L"FAQ.html"); } else if (strcmp(dest, "downloads") == 0) { StringCbCopyW (page, sizeof (page),L"Downloads.html"); } else if (strcmp(dest, "news") == 0) { StringCbCopyW (page, sizeof (page),L"News.html"); } else if (strcmp(dest, "contact") == 0) { StringCbCopyW (page, sizeof (page),L"Contact.html"); } else if (strcmp(dest, "pim") == 0) { StringCbCopyW (page, sizeof (page),L"Personal%20Iterations%20Multiplier%20%28PIM%29.html"); } else { StringCbCopyW (url, sizeof (url),TC_APPLINK); buildUrl = FALSE; } if (buildUrl) { StringCbPrintfW (url, sizeof (url), L"file:///%sdocs/html/en/%s", installDir, page); CorrectURL (url); } MSILog(hInstaller, MSI_INFO_LEVEL, L"Applink_Dll: url(%s)", url); if (IsAdmin ()) { // TODO: FileExists always returns FALSE // This is due to the fact that waccess does not like url encoded as 'file:///%sdocs/html/en/%s'. // It fails with '0x0000007B: The filename, directory name, or volume label syntax is incorrect.'. if (buildUrl && !FileExists (url)) { // fallbacl to online resources StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page); SafeOpenURL (url); } else { SafeOpenURL (url); } } else { r = (int) ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL); if (((r == ERROR_FILE_NOT_FOUND) || (r == ERROR_PATH_NOT_FOUND)) && buildUrl) { // fallbacl to online resources StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page); ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL); } } } /* * Same as in Dlgcode.c, CheckCapsLock(), but * replaced MessageBoxW() with MSILogAndShow(). */ BOOL CheckCapsLock_Dll (MSIHANDLE hInstaller, BOOL quiet) { if ((GetKeyState(VK_CAPITAL) & 1) != 0) { MSILogAndShow(hInstaller, MSI_WARNING_LEVEL, GetString ("CAPSLOCK_ON")); return TRUE; } return FALSE; } /* * Same as in Dlgcode.c, GetWrongPasswordErrorMessage(), but * replaced CheckCapsLock() with CheckCapsLock_Dll(). */ std::wstring GetWrongPasswordErrorMessage_Dll (MSIHANDLE hInstaller) { WCHAR szTmp[8192]; StringCbPrintfW (szTmp, sizeof(szTmp), GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_WRONG" : "PASSWORD_WRONG")); if (CheckCapsLock_Dll (hInstaller, TRUE)) StringCbCatW (szTmp, sizeof(szTmp), GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); wstring msg = szTmp; return msg; } /* * Same as in Dlgcode.c, HandleDriveNotReadyError(), but * replaced Warning() with MSILogAndShow(). */ void HandleDriveNotReadyError_Dll (MSIHANDLE hInstaller) { HKEY hkey = 0; DWORD value = 0, size = sizeof (DWORD); if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\MountMgr", 0, KEY_READ, &hkey) != ERROR_SUCCESS) return; if (RegQueryValueEx (hkey, L"NoAutoMount", 0, 0, (LPBYTE) &value, &size) == ERROR_SUCCESS && value != 0) { MSILogAndShow (hInstaller, MSI_WARNING_LEVEL, GetString("SYS_AUTOMOUNT_DISABLED")); } else MSILogAndShow (hInstaller, MSI_WARNING_LEVEL, GetString("DEVICE_NOT_READY_ERROR")); RegCloseKey (hkey); } /* * Same as in Dlgcode.c, handleWin32Error(), but * replaced ErrorDirect(), Error() and MessageBoxW with MSILogAndShow(), * replaced HandleDriveNotReadyError() with HandleDriveNotReadyError_Dll(). */ DWORD handleWin32Error_Dll (MSIHANDLE hInstaller, const char* srcPos) { PWSTR lpMsgBuf; DWORD dwError = GetLastError (); wchar_t szErrorValue[32]; wchar_t* pszDesc; if (dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE) return dwError; // Access denied if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ()) { MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("ERR_ACCESS_DENIED"), srcPos).c_str ()); SetLastError (dwError); // Preserve the original error code return dwError; } FormatMessageW ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ (PWSTR) &lpMsgBuf, 0, NULL ); if (lpMsgBuf) pszDesc = (wchar_t*) lpMsgBuf; else { StringCchPrintfW (szErrorValue, ARRAYSIZE (szErrorValue), L"Error 0x%.8X", dwError); pszDesc = szErrorValue; } MSILogAndShow (hInstaller, MSI_INFO_LEVEL, AppendSrcPos (pszDesc, srcPos).c_str ()); if (lpMsgBuf) LocalFree (lpMsgBuf); // User-friendly hardware error explanation if (IsDiskError (dwError)) MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString("ERR_HARDWARE_ERROR")); // Device not ready if (dwError == ERROR_NOT_READY) HandleDriveNotReadyError_Dll(hInstaller); SetLastError (dwError); // Preserve the original error code return dwError; } /* * Same as in Dlgcode.c, handleError(), but * replaced ErrorDirect(), Error() and MessageBoxW with MSILogAndShow(), * replaced handleWin32Error() with handleWin32Error_Dll(). */ void handleError_Dll (MSIHANDLE hInstaller, int code, const char* srcPos) { WCHAR szTmp[4096]; switch (code & 0x0000FFFF) { case ERR_OS_ERROR: handleWin32Error_Dll (hInstaller, srcPos); break; case ERR_OUTOFMEMORY: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("OUTOFMEMORY"), srcPos).c_str()); break; case ERR_PASSWORD_WRONG: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetWrongPasswordErrorMessage_Dll (hInstaller).c_str(), srcPos).c_str()); break; case ERR_DRIVE_NOT_FOUND: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("NOT_FOUND"), srcPos).c_str()); break; case ERR_FILES_OPEN: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("OPENFILES_DRIVER"), srcPos).c_str()); break; case ERR_FILES_OPEN_LOCK: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("OPENFILES_LOCK"), srcPos).c_str()); break; case ERR_VOL_SIZE_WRONG: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("VOL_SIZE_WRONG"), srcPos).c_str()); break; case ERR_COMPRESSION_NOT_SUPPORTED: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("COMPRESSION_NOT_SUPPORTED"), srcPos).c_str()); break; case ERR_PASSWORD_CHANGE_VOL_TYPE: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("WRONG_VOL_TYPE"), srcPos).c_str()); break; case ERR_VOL_SEEKING: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("VOL_SEEKING"), srcPos).c_str()); break; case ERR_CIPHER_INIT_FAILURE: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("ERR_CIPHER_INIT_FAILURE"), srcPos).c_str()); break; case ERR_CIPHER_INIT_WEAK_KEY: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("ERR_CIPHER_INIT_WEAK_KEY"), srcPos).c_str()); break; case ERR_VOL_ALREADY_MOUNTED: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("VOL_ALREADY_MOUNTED"), srcPos).c_str()); break; case ERR_FILE_OPEN_FAILED: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("FILE_OPEN_FAILED"), srcPos).c_str()); break; case ERR_VOL_MOUNT_FAILED: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("VOL_MOUNT_FAILED"), srcPos).c_str()); break; case ERR_NO_FREE_DRIVES: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("NO_FREE_DRIVES"), srcPos).c_str()); break; case ERR_ACCESS_DENIED: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("ACCESS_DENIED"), srcPos).c_str()); break; case ERR_DRIVER_VERSION: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString("DRIVER_VERSION")); break; case ERR_NEW_VERSION_REQUIRED: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (GetString ("NEW_VERSION_REQUIRED"), srcPos).c_str()); break; case ERR_SELF_TESTS_FAILED: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString("ERR_SELF_TESTS_FAILED")); break; case ERR_VOL_FORMAT_BAD: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString ("ERR_VOL_FORMAT_BAD")); break; case ERR_ENCRYPTION_NOT_COMPLETED: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString ("ERR_ENCRYPTION_NOT_COMPLETED")); break; case ERR_NONSYS_INPLACE_ENC_INCOMPLETE: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString ("ERR_NONSYS_INPLACE_ENC_INCOMPLETE")); break; case ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString ("ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG")); break; case ERR_PARAMETER_INCORRECT: MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString ("ERR_PARAMETER_INCORRECT")); break; case ERR_USER_ABORT: case ERR_DONT_REPORT: // A non-error break; default: StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("ERR_UNKNOWN"), code); MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, AppendSrcPos (szTmp, srcPos).c_str()); } } /* * Same as in Dlgcode.c, LoadSystemDll() , but * replaced AbortProcess() with MSILogAndShow() + return, */ static void LoadSystemDll_Dll (MSIHANDLE hInstaller, LPCTSTR szModuleName, HMODULE *pHandle, BOOL bIgnoreError, const char* srcPos) { wchar_t dllPath[MAX_PATH]; /* Load dll explictely from System32 to avoid Dll hijacking attacks*/ if (!GetSystemDirectory(dllPath, MAX_PATH)) StringCbCopyW(dllPath, sizeof(dllPath), L"C:\\Windows\\System32"); StringCbCatW(dllPath, sizeof(dllPath), L"\\"); StringCbCatW(dllPath, sizeof(dllPath), szModuleName); if (((*pHandle = LoadLibrary(dllPath)) == NULL) && !bIgnoreError) { // This error is fatal handleWin32Error_Dll (hInstaller, srcPos); MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString ("INIT_DLL")); } } /* * Same as in Dlgcode.c, handleWin32Error(), but * replaced AbortProcess() with MSILogAndShow() + return, */ BOOL IsPagingFileActive_Dll (MSIHANDLE hInstaller, BOOL checkNonWindowsPartitionsOnly) { // GlobalMemoryStatusEx() cannot be used to determine if a paging file is active wchar_t data[65536]; DWORD size = sizeof (data); if (IsPagingFileWildcardActive()) return TRUE; if (ReadLocalMachineRegistryMultiString (L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", L"PagingFiles", data, &size) && size > 24 && !checkNonWindowsPartitionsOnly) return TRUE; if (!IsAdmin()) { MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString("UAC_INIT_ERROR")); return FALSE; } for (wchar_t drive = L'C'; drive <= L'Z'; ++drive) { // Query geometry of the drive first to prevent "no medium" pop-ups wstring drivePath = L"\\\\.\\X:"; drivePath[4] = drive; if (checkNonWindowsPartitionsOnly) { wchar_t sysDir[MAX_PATH]; if (GetSystemDirectory (sysDir, ARRAYSIZE (sysDir)) != 0 && towupper (sysDir[0]) == drive) continue; } HANDLE handle = CreateFile (drivePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (handle == INVALID_HANDLE_VALUE) continue; BYTE dgBuffer[256]; DWORD dwResult; if (!DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, dgBuffer, sizeof (dgBuffer), &dwResult, NULL) && !DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, dgBuffer, sizeof (dgBuffer), &dwResult, NULL)) { CloseHandle (handle); continue; } CloseHandle (handle); // Test if a paging file exists and is locked by another process wstring path = L"X:\\pagefile.sys"; path[0] = drive; handle = CreateFile (path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (handle != INVALID_HANDLE_VALUE) CloseHandle (handle); else if (GetLastError() == ERROR_SHARING_VIOLATION) return TRUE; } return FALSE; } /* * Same as in Dlgcode.c, DoDriverInstall(), but * replaced StatusMessage() with MSILog(). */ BOOL DoDriverInstall_Dll (MSIHANDLE hInstaller) { MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin DoDriverInstall_Dll"); SC_HANDLE hManager, hService = NULL; BOOL bOK = FALSE, bRet; #ifdef SETUP if (SystemEncryptionUpdate) { MSILog(hInstaller, MSI_INFO_LEVEL, L"SystemEncryptionUpdate == TRUE"); bOK = TRUE; goto end; } #endif hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hManager == NULL) goto error; #ifdef SETUP MSILog (hInstaller, MSI_INFO_LEVEL, GetString("INSTALLING_DRIVER")); #endif hService = CreateService (hManager, L"veracrypt", L"veracrypt", SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_SYSTEM_START, SERVICE_ERROR_NORMAL, L"System32\\drivers\\veracrypt.sys", NULL, NULL, NULL, NULL, NULL); if (hService == NULL) goto error; else CloseServiceHandle (hService); hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS); if (hService == NULL) goto error; #ifdef SETUP MSILog (hInstaller, MSI_INFO_LEVEL, GetString("STARTING_DRIVER")); #endif bRet = StartService (hService, 0, NULL); if (bRet == FALSE) goto error; bOK = TRUE; error: if (bOK == FALSE && GetLastError () != ERROR_SERVICE_ALREADY_RUNNING) { handleWin32Error_Dll (hInstaller, SRC_POS); MSILogAndShow(hInstaller, MSI_ERROR_LEVEL, GetString("DRIVER_INSTALL_FAILED")); } else bOK = TRUE; if (hService != NULL) CloseServiceHandle (hService); if (hManager != NULL) CloseServiceHandle (hManager); end: MSILog(hInstaller, MSI_INFO_LEVEL, L"End DoDriverInstall_Dll"); return bOK; } /* **************************************************************************** */ /* * Same as in Setup.c, StartStopService(), but * replaced StatusMessage() with MSILog(). */ BOOL StartStopService_Dll (MSIHANDLE hInstaller, wchar_t *lpszService, BOOL bStart, DWORD argc, LPCWSTR* argv) { SC_HANDLE hManager, hService = NULL; BOOL bOK = FALSE, bRet; SERVICE_STATUS status = {0}; int x; DWORD dwExpectedState = bStart? SERVICE_RUNNING : SERVICE_STOPPED; 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 (bStart) MSILog(hInstaller, MSI_INFO_LEVEL, L"STARTING %s", lpszService); else MSILog(hInstaller, MSI_INFO_LEVEL, L"STOPPING %s", lpszService); if (bStart) { if (!StartService (hService, argc, argv) && (GetLastError () != ERROR_SERVICE_ALREADY_RUNNING)) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"Failed to start %s. Error 0x%.8X", lpszService, GetLastError ()); goto error; } } else ControlService (hService, SERVICE_CONTROL_STOP, &status); for (x = 0; x < WAIT_PERIOD; x++) { bRet = QueryServiceStatus (hService, &status); if (bRet != TRUE) goto error; if (status.dwCurrentState == dwExpectedState) break; Sleep (1000); } bRet = QueryServiceStatus (hService, &status); if (bRet != TRUE) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"Failed to query status of %s. Error 0x%.8X", lpszService, GetLastError ()); goto error; } if (status.dwCurrentState != dwExpectedState) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"Current state of %s (0x%.8X) is different from expected one (0x%.8X).", lpszService, status.dwCurrentState, dwExpectedState); goto error; } bOK = TRUE; error: if (bOK == FALSE && GetLastError () == ERROR_SERVICE_DOES_NOT_EXIST) { bOK = TRUE; } if (hService != NULL) CloseServiceHandle (hService); if (hManager != NULL) CloseServiceHandle (hManager); return bOK; } /* * Same as in Setup.c, SetSystemRestorePoint(), but * replaced StatusMessage() with MSILog(). */ static void SetSystemRestorePoint_Dll (MSIHANDLE hInstaller, BOOL finalize) { static RESTOREPOINTINFO RestPtInfo; static STATEMGRSTATUS SMgrStatus; static BOOL failed = FALSE; static BOOL (__stdcall *_SRSetRestorePoint)(PRESTOREPOINTINFO, PSTATEMGRSTATUS); MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin SetSystemRestorePoint_Dll"); if (!SystemRestoreDll) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"SystemRestoreDll NULL"); goto end; } _SRSetRestorePoint = (BOOL (__stdcall *)(PRESTOREPOINTINFO, PSTATEMGRSTATUS))GetProcAddress (SystemRestoreDll,"SRSetRestorePointW"); if (_SRSetRestorePoint == 0) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"_SRSetRestorePoint NULL"); FreeLibrary (SystemRestoreDll); SystemRestoreDll = 0; goto end; } if (!finalize) { MSILog (hInstaller, MSI_INFO_LEVEL, GetString("CREATING_SYS_RESTORE")); RestPtInfo.dwEventType = BEGIN_SYSTEM_CHANGE; RestPtInfo.dwRestorePtType = bUninstall ? APPLICATION_UNINSTALL : APPLICATION_INSTALL | DEVICE_DRIVER_INSTALL; RestPtInfo.llSequenceNumber = 0; StringCbCopyW (RestPtInfo.szDescription, sizeof(RestPtInfo.szDescription), bUninstall ? L"VeraCrypt uninstallation" : L"VeraCrypt installation"); if(!_SRSetRestorePoint (&RestPtInfo, &SMgrStatus)) { MSILog (hInstaller, MSI_ERROR_LEVEL, GetString("FAILED_SYS_RESTORE")); failed = TRUE; } } else if (!failed) { RestPtInfo.dwEventType = END_SYSTEM_CHANGE; RestPtInfo.llSequenceNumber = SMgrStatus.llSequenceNumber; if(!_SRSetRestorePoint(&RestPtInfo, &SMgrStatus)) { MSILog (hInstaller, MSI_ERROR_LEVEL, GetString("FAILED_SYS_RESTORE")); } } end: MSILog(hInstaller, MSI_INFO_LEVEL, L"End SetSystemRestorePoint_Dll"); } /* * Same as in Setup.c, DoDriverUnload(), but * replaced AbortProcess() and AbortProcessSilent() with MSILogAndShow() + return, * replaced Error(), MessageBoxW() with MSILogAndShow(), * replaced StatusMessage() with MSILog(), * replaced handleWin32Error() with handleWin32Error_Dll(). */ BOOL DoDriverUnload_Dll (MSIHANDLE hInstaller, HWND hwnd) { BOOL bOK = TRUE; int status = 0; MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin DoDriverUnload_Dll"); status = DriverAttach (); if (status != 0) { if (status == ERR_OS_ERROR && GetLastError () != ERROR_FILE_NOT_FOUND) { handleWin32Error_Dll (hInstaller, SRC_POS); MSILogAndShow(hInstaller, MSI_ERROR_LEVEL, GetString("NODRIVER")); bOK = FALSE; goto end; } if (status != ERR_OS_ERROR) { handleError_Dll (hInstaller, status, SRC_POS); MSILogAndShow(hInstaller, MSI_ERROR_LEVEL, GetString("NODRIVER")); bOK = FALSE; goto end; } } if (hDriver != INVALID_HANDLE_VALUE) { 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 (hwnd); 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", hwnd) == IDNO) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"User denied request"); bOK = FALSE; goto end; } } } } catch (...) { } if (bUninstallInProgress && !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) { MSILogAndShow(hInstaller, MSI_ERROR_LEVEL, (bDowngrade ? GetString("SETUP_FAILED_BOOT_DRIVE_ENCRYPTED_DOWNGRADE") : GetString("SETUP_FAILED_BOOT_DRIVE_ENCRYPTED"))); bOK = FALSE; goto end; } else { if (CurrentOSMajor == 6 && CurrentOSMinor == 0 && CurrentOSServicePack < 1) { MSILogAndShow(hInstaller, MSI_ERROR_LEVEL, GetString("SYS_ENCRYPTION_UPGRADE_UNSUPPORTED_ON_VISTA_SP0")); bOK = FALSE; goto end; } // check if we are upgrading a system encrypted with unsupported algorithms if (bootEnc.IsUsingUnsupportedAlgorithm(driverVersion)) { MSILogAndShow(hInstaller, MSI_ERROR_LEVEL, GetString("SYS_ENCRYPTION_UPGRADE_UNSUPPORTED_ALGORITHM")); bOK = FALSE; goto end; } 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) { if (volumesMounted != 0) { bOK = FALSE; MSILogAndShow(hInstaller, MSI_WARNING_LEVEL, GetString ("DISMOUNT_ALL_FIRST")); } } else { bOK = FALSE; handleWin32Error_Dll (hInstaller, SRC_POS); } } // Try to close all open TC windows if (bOK) { BOOL TCWindowClosed = FALSE; EnumWindows (CloseTCWindowsEnum, (LPARAM) &TCWindowClosed); if (TCWindowClosed) Sleep (2000); // stop service if (SystemEncryptionUpdate) { StartStopService_Dll (hInstaller, TC_SYSTEM_FAVORITES_SERVICE_NAME, FALSE, 0, NULL); } } // 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) { MSILogAndShow(hInstaller, MSI_WARNING_LEVEL, GetString ("CLOSE_TC_FIRST")); 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 VeraCrypt for the first time now (we also cannot know if the user has already // installed and used VeraCrypt on another system before). bPossiblyFirstTimeInstall = TRUE; } end: MSILog(hInstaller, MSI_INFO_LEVEL, L"End DoDriverUnload_Dll"); return bOK; } /* * Same as in Setup.c, DoServiceUninstall(), but * replaced AbortProcess() and AbortProcessSilent() with MSILogAndShow() + return, * replaced Error(), MessageBoxW() with MSILogAndShow(), * replaced StatusMessage() with MSILog(), * replaced handleWin32Error() with handleWin32Error_Dll(). */ BOOL DoServiceUninstall_Dll (MSIHANDLE hInstaller, HWND hwndDlg, wchar_t *lpszService) { SC_HANDLE hManager, hService = NULL; BOOL bOK = FALSE, bRet; SERVICE_STATUS status; BOOL firstTry = TRUE; int x; MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin DoServiceUninstall_Dll"); 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 (wcscmp (L"veracrypt", 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 (...) { } MSILog (hInstaller, MSI_INFO_LEVEL, GetString("STOPPING_DRIVER")); } else MSILog (hInstaller, MSI_INFO_LEVEL, L"STOPPING %s", lpszService); 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 (wcscmp (L"veracrypt", lpszService) == 0) MSILog (hInstaller, MSI_INFO_LEVEL, GetString("REMOVING_DRIVER")); else MSILog (hInstaller, MSI_INFO_LEVEL, L"REMOVING %s", lpszService); if (hService != NULL) { CloseServiceHandle (hService); hService = NULL; } if (hManager != NULL) { CloseServiceHandle (hManager); hManager = NULL; } 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); hService = NULL; hManager = NULL; Sleep(1000); firstTry = FALSE; goto retry; } goto error; } bOK = TRUE; error: if (bOK == FALSE && GetLastError ()!= ERROR_SERVICE_DOES_NOT_EXIST) { handleWin32Error_Dll (hInstaller, SRC_POS); MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString("DRIVER_UINSTALL_FAILED")); } else bOK = TRUE; if (hService != NULL) CloseServiceHandle (hService); if (hManager != NULL) CloseServiceHandle (hManager); MSILog(hInstaller, MSI_INFO_LEVEL, L"End DoServiceUninstall_Dll"); return bOK; } /* * Same as in Setup.c, DoRegUninstall(), but * replaced StatusMessage() with MSILog(), * removed unnecessary code that is done by MSI. */ BOOL DoRegUninstall_Dll (MSIHANDLE hInstaller, BOOL bRemoveDeprecated) { MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin DoRegUninstall_Dll"); wchar_t regk [64]; typedef LSTATUS (WINAPI *RegDeleteKeyExWFn) (HKEY hKey,LPCWSTR lpSubKey,REGSAM samDesired,WORD Reserved); RegDeleteKeyExWFn RegDeleteKeyExWPtr = NULL; HMODULE hAdvapiDll = LoadLibrary (L"Advapi32.dll"); if (hAdvapiDll) { RegDeleteKeyExWPtr = (RegDeleteKeyExWFn) GetProcAddress(hAdvapiDll, "RegDeleteKeyExW"); } // Unregister COM servers if (!bRemoveDeprecated) { if (!UnregisterComServers (InstallationPath)) MSILog (hInstaller, MSI_ERROR_LEVEL, GetString("COM_DEREG_FAILED")); } if (!bRemoveDeprecated) MSILog (hInstaller, MSI_INFO_LEVEL, GetString("REMOVING_REG")); /* The following is done by MSI, so we skip it */ /* if (RegDeleteKeyExWPtr) { RegDeleteKeyExWPtr (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt", KEY_WOW64_32KEY, 0); RegDeleteKeyExWPtr (HKEY_CURRENT_USER, L"Software\\VeraCrypt", KEY_WOW64_32KEY, 0); } else { RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt"); RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\VeraCrypt"); } RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\VeraCryptVolume\\Shell\\open\\command"); RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\VeraCryptVolume\\Shell\\open"); RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\VeraCryptVolume\\Shell"); RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\VeraCryptVolume\\DefaultIcon"); RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\VeraCryptVolume"); */ if (!bRemoveDeprecated) { HKEY hKey; GetStartupRegKeyName (regk, sizeof(regk)); DeleteRegistryValue (regk, L"VeraCrypt"); // The following is done by MSI, so we skip it // DeleteRegistryKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\.hc"); // enable the SE_TAKE_OWNERSHIP_NAME privilege for this operation SetPrivilege (SE_TAKE_OWNERSHIP_NAME, TRUE); // clean MuiCache list from VeraCrypt entries SearchAndDeleteRegistrySubString (HKEY_CLASSES_ROOT, L"Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache", L"VeraCrypt", FALSE, NULL); // clean other VeraCrypt entries from all users SearchAndDeleteRegistrySubString (HKEY_USERS, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.hc", NULL, TRUE, NULL); SearchAndDeleteRegistrySubString (HKEY_USERS, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Compatibility Assistant\\Persisted", L"VeraCrypt", TRUE, NULL); SearchAndDeleteRegistrySubString (HKEY_USERS, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage\\NewShortcuts", L"VeraCrypt", TRUE, NULL); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM", 0, KEY_ALL_ACCESS | WRITE_DAC | WRITE_OWNER, &hKey) == ERROR_SUCCESS) { SearchAndDeleteRegistrySubString (hKey, L"Enum\\Root\\LEGACY_VERACRYPT", NULL, TRUE, L"ControlSet"); SearchAndDeleteRegistrySubString (hKey, L"services\\veracrypt", NULL, TRUE, L"ControlSet"); RegCloseKey(hKey); } // disable the SE_TAKE_OWNERSHIP_NAME privilege for this operation SetPrivilege (SE_TAKE_OWNERSHIP_NAME, FALSE); // The following is done by MSI, so we skip it //SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); } if (hAdvapiDll) FreeLibrary (hAdvapiDll); MSILog(hInstaller, MSI_INFO_LEVEL, L"End DoRegUninstall_Dll"); return TRUE; } /* * Same as in Setup.c, UpgradeBootLoader(), but * replaced StatusMessage() with MSILog(). */ BOOL UpgradeBootLoader_Dll (MSIHANDLE hInstaller, HWND hwndDlg) { MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin UpgradeBootLoader_Dll"); BOOL bOK = FALSE, bNeedUnloadDriver = FALSE; int status; if (!SystemEncryptionUpdate) { MSILog(hInstaller, MSI_INFO_LEVEL, L"SystemEncryptionUpdate == FALSE"); bOK = TRUE; goto end; } if (hDriver == INVALID_HANDLE_VALUE) { status = DriverAttach(); if ((status == 0) && (hDriver != INVALID_HANDLE_VALUE)) { bNeedUnloadDriver = TRUE; } else { MSILog(hInstaller, MSI_INFO_LEVEL, L"UpgradeBootLoader_Dll: failed to attach to driver"); } } try { BootEncryption bootEnc (hwndDlg); uint64 bootLoaderVersion = bootEnc.GetInstalledBootLoaderVersion(); if ((bootLoaderVersion < VERSION_NUM) || (bReinstallMode && (bootLoaderVersion == VERSION_NUM))) { MSILog (hInstaller, MSI_INFO_LEVEL, GetString("INSTALLER_UPDATING_BOOT_LOADER")); // this is done by the service now //bootEnc.InstallBootLoader (true); if (bootEnc.GetInstalledBootLoaderVersion() <= TC_RESCUE_DISK_UPGRADE_NOTICE_MAX_VERSION) { bUpdateRescueDisk = TRUE; MSILog (hInstaller, MSI_INFO_LEVEL, GetString(IsHiddenOSRunning() ? "BOOT_LOADER_UPGRADE_OK_HIDDEN_OS" : "BOOT_LOADER_UPGRADE_OK")); } } bOK = TRUE; goto end; } catch (Exception &e) { e.Show (hwndDlg); } catch (...) { } MSILog (hInstaller, MSI_ERROR_LEVEL, GetString("BOOT_LOADER_UPGRADE_FAILED")); end: if (bNeedUnloadDriver) { CloseHandle (hDriver); hDriver = INVALID_HANDLE_VALUE; } MSILog(hInstaller, MSI_INFO_LEVEL, L"End UpgradeBootLoader_Dll"); return bOK; } /* * Same as Setup.c, function DoApplicationDataUninstall(), but * replaced StatusMessage() and RemoveMessage() with MSILog(). */ BOOL DoApplicationDataUninstall_Dll (MSIHANDLE hInstaller) { MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin DoApplicationDataUninstall"); wchar_t path[MAX_PATH]; wchar_t path2[MAX_PATH]; BOOL bOK = TRUE; MSILog(hInstaller, MSI_INFO_LEVEL, GetString("REMOVING_APPDATA")); SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path); StringCbCatW (path, sizeof(path), L"\\VeraCrypt\\"); // Delete favorite volumes file StringCbPrintfW (path2, sizeof(path2), L"%s%s", path, TC_APPD_FILENAME_FAVORITE_VOLUMES); MSILog(hInstaller, MSI_INFO_LEVEL, L"REMOVING %s", path2); StatDeleteFile (path2, FALSE); // Delete keyfile defaults StringCbPrintfW (path2, sizeof(path2), L"%s%s", path, TC_APPD_FILENAME_DEFAULT_KEYFILES); MSILog(hInstaller, MSI_INFO_LEVEL, L"REMOVING %s", path2); StatDeleteFile (path2, FALSE); // Delete history file StringCbPrintfW (path2, sizeof(path2), L"%s%s", path, TC_APPD_FILENAME_HISTORY); MSILog(hInstaller, MSI_INFO_LEVEL, L"REMOVING %s", path2); StatDeleteFile (path2, FALSE); // Delete configuration file StringCbPrintfW (path2, sizeof(path2), L"%s%s", path, TC_APPD_FILENAME_CONFIGURATION); MSILog(hInstaller, MSI_INFO_LEVEL, L"REMOVING %s", path2); StatDeleteFile (path2, FALSE); // Delete system encryption configuration file StringCbPrintfW (path2, sizeof(path2), L"%s%s", path, TC_APPD_FILENAME_SYSTEM_ENCRYPTION); MSILog(hInstaller, MSI_INFO_LEVEL, L"REMOVING %s", path2); StatDeleteFile (path2, FALSE); SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path); StringCbCatW (path, sizeof(path), L"\\VeraCrypt"); MSILog(hInstaller, MSI_INFO_LEVEL, L"REMOVING %s", path); if (!StatRemoveDirectory (path)) { handleWin32Error_Dll (hInstaller, SRC_POS); bOK = FALSE; } // remove VeraCrypt under common appdata if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) { StringCbCatW (path, sizeof(path), L"\\VeraCrypt"); // Delete original bootloader StringCbPrintfW (path2, sizeof(path2), L"%s\\%s", path, TC_SYS_BOOT_LOADER_BACKUP_NAME); MSILog(hInstaller, MSI_INFO_LEVEL, L"REMOVING %s", path2); StatDeleteFile (path2, FALSE); // remove VeraCrypt folder MSILog(hInstaller, MSI_INFO_LEVEL, L"REMOVING %s", path); StatRemoveDirectory (path); } MSILog(hInstaller, MSI_INFO_LEVEL, L"End DoApplicationDataUninstall"); return bOK; } /* * Same as Setup.c, function DoUninstall(), but * removed uninstall of files and registry as it will be * done by MSI. */ BOOL DoUninstall_Dll (MSIHANDLE hInstaller, HWND hwndDlg) { MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin DoUninstall_Dll"); BOOL bOK = TRUE; BOOL bTempSkipSysRestore = FALSE; if (DoDriverUnload_Dll (hInstaller, 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_Dll (hInstaller, FALSE); if (DoServiceUninstall_Dll (hInstaller, hwndDlg, L"veracrypt") == FALSE) { bOK = FALSE; } else if (DoRegUninstall_Dll (hInstaller, FALSE) == FALSE) { bOK = FALSE; } /* Following skipped because done by MSI */ /* else if (DoFilesInstall ((HWND) hwndDlg, InstallationPath) == FALSE) { bOK = FALSE; } else if (DoShortcutsUninstall (hwndDlg, InstallationPath) == FALSE) { bOK = FALSE; } */ else if (!DoApplicationDataUninstall_Dll (hInstaller)) { bOK = FALSE; } else { // Deprecated service DoServiceUninstall_Dll (hInstaller, hwndDlg, L"VeraCryptService"); } } if (Rollback) goto end; if (bSystemRestore && !bTempSkipSysRestore) SetSystemRestorePoint_Dll (hInstaller, TRUE); if (!bOK) bUninstallInProgress = FALSE; end: MSILog(hInstaller, MSI_INFO_LEVEL, L"End DoUninstall_Dll"); return bOK; } /* * Same as Setup.c, function InitApp(), but * replaced unnecessary calls, * forced english as language, * replaced LoadLanguageFile() with LoadLanguageFromResource() to be able to set bForceSilent. */ BOOL InitDll (MSIHANDLE hInstaller) { MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin InitDll"); BOOL bOK = TRUE; InitOSVersionInfo(); InitGlobalLocks (); SetErrorMode (SetErrorMode (0) | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); // Force language to english to read strings from the default Language.xml embedded in the DLL. SetPreferredLangId ("en"); bUserSetLanguage = TRUE; LoadLanguageFromResource (0, FALSE, TRUE); SetUnhandledExceptionFilter (ExceptionHandler); _set_invalid_parameter_handler (InvalidParameterHandler); RemoteSession = GetSystemMetrics (SM_REMOTESESSION) != 0; MSILog(hInstaller, MSI_INFO_LEVEL, L"End InitDll"); return bOK; } /* **************************************************************************** */ /* * Same as Setup.c, function wWinMain(), but * replaced unnecessary calls. * This should be called at the beginning of each operation (install, uninstall...), * before atexit(VC_CustomAction_Cleanup()) call. */ BOOL VC_CustomAction_Init(MSIHANDLE hInstaller, const wchar_t* szInstallDir) { MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin VC_CustomAction_Init"); BOOL bOK = TRUE; if (!InitDll(hInstaller)) { bOK = FALSE; goto end; } // System Restore if (IsSystemRestoreEnabled ()) { MSILog(hInstaller, MSI_INFO_LEVEL, L"System Restore is enabled"); wchar_t dllPath[MAX_PATH]; if (GetSystemDirectory (dllPath, MAX_PATH)) { StringCbCatW(dllPath, sizeof(dllPath), L"\\srclient.dll"); } else StringCbCopyW(dllPath, sizeof(dllPath), L"C:\\Windows\\System32\\srclient.dll"); SystemRestoreDll = LoadLibrary (dllPath); } else { MSILog(hInstaller, MSI_INFO_LEVEL, L"System Restore is not enabled"); SystemRestoreDll = 0; } // Set InstallationPath wcsncpy(InstallationPath, szInstallDir, min(wcslen(szInstallDir), ARRAYSIZE(InstallationPath))); end: MSILog(hInstaller, MSI_INFO_LEVEL, L"End VC_CustomAction_Init"); return bOK; } /* * Same as Setup.c, function localcleanup(), but * replaced unnecessary calls. * This should be called at the beginning of each operation (install, uninstall...), * as an argument to atexit() before VC_CustomAction_Init() call. */ void VC_CustomAction_Cleanup () { //MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin VC_CustomAction_Cleanup"); /* Cleanup the GDI fonts */ if (hFixedFont != NULL) DeleteObject (hFixedFont); if (hFixedDigitFont != NULL) DeleteObject (hFixedDigitFont); if (hBoldFont != NULL) DeleteObject (hBoldFont); if (hTitleFont != NULL) DeleteObject (hTitleFont); if (hUserFont != NULL) DeleteObject (hUserFont); if (hUserUnderlineFont != NULL) DeleteObject (hUserUnderlineFont); if (hUserBoldFont != NULL) DeleteObject (hUserBoldFont); /* Close the device driver handle */ if (hDriver != INVALID_HANDLE_VALUE) { // Unload driver mode if possible (non-install mode) if (IsNonInstallMode ()) { // If a dismount was forced in the lifetime of the driver, Windows may later prevent it to be loaded again from // the same path. Therefore, the driver will not be unloaded even though it was loaded in non-install mode. int driverUnloadDisabled; DWORD dwResult; if (!DeviceIoControl (hDriver, TC_IOCTL_IS_DRIVER_UNLOAD_DISABLED, NULL, 0, &driverUnloadDisabled, sizeof (driverUnloadDisabled), &dwResult, NULL)) driverUnloadDisabled = 0; if (!driverUnloadDisabled) DriverUnload (); else { CloseHandle (hDriver); hDriver = INVALID_HANDLE_VALUE; } } else { CloseHandle (hDriver); hDriver = INVALID_HANDLE_VALUE; } } CoUninitialize (); CloseSysEncMutex (); FinalizeGlobalLocks (); //MSILog(hInstaller, MSI_INFO_LEVEL, L"End VC_CustomAction_Cleanup"); } void Tokenize(const wchar_t* szInput, std::vector& szTokens) { std::wstringstream check(szInput); std::wstring intermediate; while(std::getline(check, intermediate, L'?')) { szTokens.push_back(intermediate); } } /* * Same as Setup.c, function DoInstall(), but * without the actual installation, it only prepares the system * before the installation (before DoFilesInstall). * It runs as a Deferred CA. */ EXTERN_C UINT STDAPICALLTYPE VC_CustomAction_PreInstall(MSIHANDLE hInstaller) { HWND hwndDlg = NULL; std::wstring szValueBuf = L""; DWORD cchValueBuf = 0; UINT uiStat = 0; HKEY hkey = 0; DWORD dw = 0; BootEncryption bootEnc(NULL); std::wstring szInstallDir = L""; UINT uiRet = ERROR_INSTALL_FAILURE; BOOL bOK = TRUE; MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin VC_CustomAction_PreInstall"); // Get UILevel to see whether we're being installed silently or not. // Also get INSTALLDIR to see where we're being installed. // Since this is a Deferred CA, they are to be setup in its CustomActionData. uiStat = MsiGetProperty(hInstaller, TEXT("CustomActionData"), (LPWSTR)TEXT(""), &cchValueBuf); if (ERROR_MORE_DATA == uiStat) { ++cchValueBuf; // add 1 for null termination szValueBuf.resize(cchValueBuf); uiStat = MsiGetProperty(hInstaller, TEXT("CustomActionData"), &szValueBuf[0], &cchValueBuf); if ((ERROR_SUCCESS == uiStat)) { MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PreInstall: CustomActionData = '%s'", szValueBuf.c_str()); std::vector szTokens; Tokenize(szValueBuf.c_str(), szTokens); for (size_t i = 0; i < szTokens.size(); i++) { std::wstring szToken = szTokens[i]; if (wcsncmp(szToken.c_str(), L"UILEVEL=", wcslen(L"UILEVEL=")) == 0) { size_t index0 = szToken.find_first_of(L"="); if (index0 != std::wstring::npos) { std::wstring uiLevel = szToken.substr(index0 + 1); Silent = (stoi(uiLevel) <= 3); MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PreInstall: UILEVEL = '%s', bSilent = '%d'", uiLevel.c_str(), Silent); } } else if (wcsncmp(szToken.c_str(), L"INSTALLDIR=", wcslen(L"INSTALLDIR=")) == 0) { size_t index0 = szToken.find_first_of(L"="); if (index0 != std::wstring::npos) { szInstallDir = szToken.substr(index0 + 1); MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PreInstall: INSTALLDIR = '%s'", szInstallDir.c_str()); } } else if (wcsncmp(szToken.c_str(), L"REINSTALL=", wcslen(L"REINSTALL=")) == 0) { size_t index0 = szToken.find_first_of(L"="); if (index0 != std::wstring::npos) { std::wstring szReinstall = szToken.substr(index0 + 1); bRepairMode = (wcslen(szReinstall.c_str()) != 0); MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PreInstall: REINSTALL = '%s', bRepairMode = '%s'", szReinstall.c_str(), bRepairMode ? L"TRUE" : L"FALSE"); } } } } } // Get this MSI Installer HWND. // There cannot be 2 MSIs or more running at the same time, so we're sure we'll get ours. // This is only possible in case of non silent install. hwndDlg = FindWindow(L"MsiDialogCloseClass", NULL); if (!hwndDlg && !Silent) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PreInstall: MsiDialogCloseClass not found"); goto end; } /* Start actual work */ if (!VC_CustomAction_Init(hInstaller, szInstallDir.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PreInstall: VC_CustomAction_Init() failed"); goto end; } atexit(VC_CustomAction_Cleanup); bootEnc.SetParentWindow(hwndDlg); if (DoDriverUnload_Dll (hInstaller, hwndDlg) == FALSE) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PreInstall: DoDriverUnload_Dll() failed"); goto end; } if (bSystemRestore) { SetSystemRestorePoint_Dll (hInstaller, FALSE); } if (bDisableSwapFiles && IsPagingFileActive_Dll (hInstaller, FALSE)) { if (!DisablePagingFile()) { handleWin32Error_Dll (hInstaller, SRC_POS); MSILogAndShow(hInstaller, MSI_ERROR_LEVEL, GetString("FAILED_TO_DISABLE_PAGING_FILES")); } else { bRestartRequired = TRUE; } } // Remove deprecated DoServiceUninstall_Dll (hInstaller, hwndDlg, L"VeraCryptService"); if (!SystemEncryptionUpdate) DoRegUninstall_Dll (hInstaller, TRUE); if (UnloadDriver && DoServiceUninstall_Dll(hInstaller, hwndDlg, L"veracrypt") == FALSE) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PreInstall: DoServiceUninstall_Dll(veracrypt) failed"); bOK = FALSE; } // uiRet = MsiSetProperty(hInstaller, TEXT("ISREBOOTREQUIRED"), TEXT("1")); // Cannot do this because this is a Deferred CA (we need Deferred so that it runs with admin privileges). // MsiGetProperty and MsiSetProperty properties cannot be used for deferred InstallScript custom actions, // which do not have access to the active .msi database and do not recognize any Windows Installer properties. // They can access only the information that has been written into the execution script (CustomActionData). // Therefore, we set the values in RegKeys that are volatile. if (bOK) { if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, L"Software\\.VeraCrypt\\Values", 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) == ERROR_SUCCESS) { RegSetValueEx (hkey, L"Silent", 0, REG_DWORD, (const BYTE*)(&Silent), sizeof(BOOL)); RegSetValueEx (hkey, L"bUninstall", 0, REG_DWORD, (const BYTE*)(&bUninstall), sizeof(BOOL)); RegSetValueEx (hkey, L"bDowngrade", 0, REG_DWORD, (const BYTE*)(&bDowngrade), sizeof(BOOL)); RegSetValueEx (hkey, L"bUninstallInProgress", 0, REG_DWORD, (const BYTE*)(&bUninstallInProgress), sizeof(BOOL)); RegSetValueEx (hkey, L"PortableMode", 0, REG_DWORD, (const BYTE*)(&PortableMode), sizeof(BOOL)); RegSetValueEx (hkey, L"UnloadDriver", 0, REG_DWORD, (const BYTE*)(&UnloadDriver), sizeof(BOOL)); RegSetValueEx (hkey, L"Rollback", 0, REG_DWORD, (const BYTE*)(&Rollback), sizeof(BOOL)); RegSetValueEx (hkey, L"bReinstallMode", 0, REG_DWORD, (const BYTE*)(&bReinstallMode), sizeof(BOOL)); RegSetValueEx (hkey, L"bUpgrade", 0, REG_DWORD, (const BYTE*)(&bUpgrade), sizeof(BOOL)); RegSetValueEx (hkey, L"bPossiblyFirstTimeInstall", 0, REG_DWORD, (const BYTE*)(&bPossiblyFirstTimeInstall), sizeof(BOOL)); RegSetValueEx (hkey, L"bDevm", 0, REG_DWORD, (const BYTE*)(&bDevm), sizeof(BOOL)); RegSetValueEx (hkey, L"SystemEncryptionUpdate", 0, REG_DWORD, (const BYTE*)(&SystemEncryptionUpdate), sizeof(BOOL)); RegSetValueEx (hkey, L"bRestartRequired", 0, REG_DWORD, (const BYTE*)(&bRestartRequired), sizeof(BOOL)); RegSetValueEx (hkey, L"bDisableSwapFiles", 0, REG_DWORD, (const BYTE*)(&bDisableSwapFiles), sizeof(BOOL)); RegSetValueEx (hkey, L"bSystemRestore", 0, REG_DWORD, (const BYTE*)(&bSystemRestore), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptFastStartup", 0, REG_DWORD, (const BYTE*)(&bPromptFastStartup), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptReleaseNotes", 0, REG_DWORD, (const BYTE*)(&bPromptReleaseNotes), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptTutorial", 0, REG_DWORD, (const BYTE*)(&bPromptTutorial), sizeof(BOOL)); RegSetValueEx (hkey, L"bUpdateRescueDisk", 0, REG_DWORD, (const BYTE*)(&bUpdateRescueDisk), sizeof(BOOL)); RegSetValueEx (hkey, L"bRepairMode", 0, REG_DWORD, (const BYTE*)(&bRepairMode), sizeof(BOOL)); RegSetValueEx (hkey, L"bUserSetLanguage", 0, REG_DWORD, (const BYTE*)(&bUserSetLanguage), sizeof(BOOL)); RegCloseKey (hkey); uiRet = ERROR_SUCCESS; } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"End VC_CustomAction_PreInstall: Could not write to registry"); } } end: MSILog(hInstaller, MSI_INFO_LEVEL, L"End VC_CustomAction_PreInstall"); return uiRet; } /* * Same as Setup.c, function DoInstall(), but * without the actual installation, it only performs * post install operations (after DoRegInstall and last parts * of DoFilesInstall / DoRegInstall). * It also does the Fast Startup check, shows Release Notes and * Beginner's Tutorial if needed and sets regkey accordingly. * It runs as a Deferred CA. */ EXTERN_C UINT STDAPICALLTYPE VC_CustomAction_PostInstall(MSIHANDLE hInstaller) { HWND hwndDlg = NULL; std::wstring szValueBuf = L""; DWORD cchValueBuf = 0; UINT uiStat = 0; HKEY hkey = 0; DWORD dw = 0; BootEncryption bootEnc(NULL); std::wstring szInstallDir = L""; UINT uiRet = ERROR_INSTALL_FAILURE; BOOL bOK = TRUE; WCHAR szCurrentDir[MAX_PATH]; const wchar_t* oldFileNames[] = { L"docs\\html\\en\\AddNewSystemVar.jpg", L"docs\\html\\en\\CertificateCannotBeVerified.jpg", L"docs\\html\\en\\CertVerifyFails.jpg", L"docs\\html\\en\\DistributionPackageDamaged.jpg", L"docs\\html\\en\\DownloadVS2010.jpg", L"docs\\html\\en\\DownloadVS2019.jpg", L"docs\\html\\en\\DownloadVSBuildTools.jpg", L"docs\\html\\en\\gzipCommandLine.jpg", L"docs\\html\\en\\NasmCommandLine.jpg", L"docs\\html\\en\\RegeditPermissions-1.jpg", L"docs\\html\\en\\RegeditPermissions-2.jpg", L"docs\\html\\en\\RegeditPermissions-3.jpg", L"docs\\html\\en\\RegeditPermissions-4.jpg", L"docs\\html\\en\\SelectAdvancedSystemSettings.jpg", L"docs\\html\\en\\SelectEnvironmentVariables.jpg", L"docs\\html\\en\\SelectPathVariable.jpg", L"docs\\html\\en\\SelectThisPC.jpg", L"docs\\html\\en\\upxCommandLine.jpg", L"docs\\html\\en\\VS2010BuildSolution.jpg", L"docs\\html\\en\\VS2010Win32Config.jpg", L"docs\\html\\en\\VS2010X64Config.jpg", L"docs\\html\\en\\VS2019ARM64Config.jpg", L"docs\\html\\en\\VS2019BuildSolution.jpg", L"docs\\html\\en\\YasmCommandLine.jpg", L"docs\\html\\en\\BCH_Logo_48x30.png", L"docs\\html\\en\\LinuxPrepAndBuild.sh", L"docs\\html\\en\\LinuxPrepAndBuild.zip", L"docs\\html\\en\\RIPEMD-160.html", L"docs\\html\\en\\ru\\BCH_Logo_48x30.png", L"Languages\\Language.ru - Copy.xml", }; MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin VC_CustomAction_PostInstall"); // Get INSTALLDIR to see where we're being installed. uiStat = MsiGetProperty(hInstaller, TEXT("CustomActionData"), (LPWSTR)TEXT(""), &cchValueBuf); if (ERROR_MORE_DATA == uiStat) { ++cchValueBuf; // add 1 for null termination szValueBuf.resize(cchValueBuf); uiStat = MsiGetProperty(hInstaller, TEXT("CustomActionData"), &szValueBuf[0], &cchValueBuf); if ((ERROR_SUCCESS == uiStat)) { MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PostInstall: CustomActionData = '%s'", szValueBuf.c_str()); if (wcsncmp(szValueBuf.c_str(), L"INSTALLDIR=", wcslen(L"INSTALLDIR=")) == 0) { size_t index0 = szValueBuf.find_first_of(L"="); if (index0 != std::wstring::npos) { szInstallDir = szValueBuf.substr(index0 + 1); MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PostInstall: INSTALLDIR = '%s'", szInstallDir.c_str()); } } } } // Read RegKeys previously setup by PreInstall if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"Software\\.VeraCrypt\\Values", 0, KEY_READ, &hkey) == ERROR_SUCCESS) { DWORD cbValue = sizeof(DWORD); DWORD dwValue = 0; RegQueryValueEx (hkey, L"Silent", NULL, NULL, (LPBYTE) &dwValue, &cbValue); Silent = (dwValue == 1); RegQueryValueEx (hkey, L"bUninstall", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUninstall = (dwValue == 1); RegQueryValueEx (hkey, L"bDowngrade", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bDowngrade = (dwValue == 1); RegQueryValueEx (hkey, L"bUninstallInProgress", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUninstallInProgress = (dwValue == 1); RegQueryValueEx (hkey, L"PortableMode", NULL, NULL, (LPBYTE) &dwValue, &cbValue); PortableMode = (dwValue == 1); RegQueryValueEx (hkey, L"UnloadDriver", NULL, NULL, (LPBYTE) &dwValue, &cbValue); UnloadDriver = (dwValue == 1); RegQueryValueEx (hkey, L"Rollback", NULL, NULL, (LPBYTE) &dwValue, &cbValue); Rollback = (dwValue == 1); RegQueryValueEx (hkey, L"bReinstallMode", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bReinstallMode = (dwValue == 1); RegQueryValueEx (hkey, L"bUpgrade", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUpgrade = (dwValue == 1); RegQueryValueEx (hkey, L"bPossiblyFirstTimeInstall", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPossiblyFirstTimeInstall = (dwValue == 1); RegQueryValueEx (hkey, L"bDevm", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bDevm = (dwValue == 1); RegQueryValueEx (hkey, L"SystemEncryptionUpdate", NULL, NULL, (LPBYTE) &dwValue, &cbValue); SystemEncryptionUpdate = (dwValue == 1); RegQueryValueEx (hkey, L"bRestartRequired", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bRestartRequired = (dwValue == 1); RegQueryValueEx (hkey, L"bDisableSwapFiles", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bDisableSwapFiles = (dwValue == 1); RegQueryValueEx (hkey, L"bSystemRestore", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bSystemRestore = (dwValue == 1); RegQueryValueEx (hkey, L"bPromptFastStartup", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPromptFastStartup = (dwValue == 1); RegQueryValueEx (hkey, L"bPromptReleaseNotes", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPromptReleaseNotes = (dwValue == 1); RegQueryValueEx (hkey, L"bPromptTutorial", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPromptTutorial = (dwValue == 1); RegQueryValueEx (hkey, L"bUpdateRescueDisk", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUpdateRescueDisk = (dwValue == 1); RegQueryValueEx (hkey, L"bRepairMode", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bRepairMode = (dwValue == 1); RegQueryValueEx (hkey, L"bUserSetLanguage", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUserSetLanguage = (dwValue == 1); RegCloseKey (hkey); } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"End VC_CustomAction_PostInstall: Could not read from registry"); goto end; } // Get this MSI Installer HWND. // There cannot be 2 MSIs or more running at the same time, so we're sure we'll get ours. // This is only possible in case of non silent install. hwndDlg = FindWindow(L"MsiDialogCloseClass", NULL); if (!hwndDlg && !Silent) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostInstall: MsiDialogCloseClass not found"); goto end; } /* Start actual work */ if (!VC_CustomAction_Init(hInstaller, szInstallDir.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostInstall: VC_CustomAction_Init() failed"); goto end; } atexit(VC_CustomAction_Cleanup); bootEnc.SetParentWindow(hwndDlg); // Last part of DoFilesInstall() { BOOL bResult = FALSE; WIN32_FIND_DATA f; HANDLE h; wchar_t szTmp[TC_MAX_PATH]; size_t i; // delete "VeraCrypt Setup.exe" if it exists StringCbPrintfW (szTmp, sizeof(szTmp), L"%s%s", szInstallDir.c_str(), L"VeraCrypt Setup.exe"); if (FileExists(szTmp)) { ForceDeleteFile(szTmp); } // delete files wrongly installed by previous versions in installation folder for (i = 0; i < ARRAYSIZE(oldFileNames); i++) { StringCbPrintfW (szTmp, sizeof(szTmp), L"%s%s", szInstallDir.c_str(), oldFileNames[i]); if (FileExists(szTmp)) { ForceDeleteFile(szTmp); } } StringCbPrintfW (szTmp, sizeof(szTmp), L"%s%s", szInstallDir.c_str(), L"VeraCrypt.exe"); EnableWow64FsRedirection (FALSE); wstring servicePath = GetServiceConfigPath (_T(TC_APP_NAME) L".exe", false); wstring serviceLegacyPath = GetServiceConfigPath (_T(TC_APP_NAME) L".exe", true); wstring favoritesFile = GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, false); wstring favoritesLegacyFile = GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, true); if (FileExists (favoritesLegacyFile.c_str()) && !FileExists (favoritesFile.c_str())) { // copy the favorites XML file to the native system directory bResult = CopyFile (favoritesLegacyFile.c_str(), favoritesFile.c_str(), FALSE); } else { bResult = TRUE; } if (bResult) { // Update the path of the service BootEncryption BootEncObj (hwndDlg); try { if (BootEncObj.GetDriverServiceStartType() == SERVICE_BOOT_START) { uint32 driverFlags = ReadDriverConfigurationFlags (); uint32 serviceFlags = BootEncObj.ReadServiceConfigurationFlags (); BootEncObj.UpdateSystemFavoritesService (); MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostInstall: INSTALLING %s", servicePath.c_str()); // Tell the service not to update loader on stop BootEncObj.SetServiceConfigurationFlag (VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_UPDATE_LOADER, true); if (StartStopService_Dll (hInstaller, TC_SYSTEM_FAVORITES_SERVICE_NAME, FALSE, 0, NULL)) { // we tell the service not to load system favorites on startup and to update bootloader on startup LPCWSTR szArgs[3] = { TC_SYSTEM_FAVORITES_SERVICE_NAME, VC_SYSTEM_FAVORITES_SERVICE_ARG_SKIP_MOUNT, VC_SYSTEM_FAVORITES_SERVICE_ARG_UPDATE_LOADER}; if (!CopyFile (szTmp, servicePath.c_str(), FALSE)) ForceCopyFile (szTmp, servicePath.c_str()); MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostInstall: SystemEncryptionUpdate = %s", SystemEncryptionUpdate? L"TRUE" : L"FALSE"); StartStopService_Dll (hInstaller, TC_SYSTEM_FAVORITES_SERVICE_NAME, TRUE, SystemEncryptionUpdate? 3 : 2, szArgs); } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostInstall: failed to stop %S", servicePath.c_str()); ForceCopyFile (szTmp, servicePath.c_str()); } BootEncObj.SetDriverConfigurationFlag (driverFlags, true); // remove the service flag if it was set originally if (!(serviceFlags & VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_UPDATE_LOADER)) BootEncObj.SetServiceConfigurationFlag (VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_UPDATE_LOADER, false); } } catch (...) {} } // delete files from legacy path if (FileExists (favoritesLegacyFile.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostInstall: REMOVING %s", favoritesLegacyFile.c_str()); ForceDeleteFile (favoritesLegacyFile.c_str()); } if (FileExists (serviceLegacyPath.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostInstall: REMOVING %s", serviceLegacyPath.c_str()); ForceDeleteFile (serviceLegacyPath.c_str()); } EnableWow64FsRedirection (TRUE); if (bResult == FALSE) { LPVOID lpMsgBuf; DWORD dwError = GetLastError (); wchar_t szTmp2[700]; wchar_t szErrorValue[16]; wchar_t* pszDesc; FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ (wchar_t *) &lpMsgBuf, 0, NULL ); if (lpMsgBuf) pszDesc = (wchar_t*) lpMsgBuf; else { StringCbPrintfW (szErrorValue, sizeof (szErrorValue), L"0x%.8X", dwError); pszDesc = szErrorValue; } if (bUninstall == FALSE) StringCbPrintfW (szTmp2, sizeof(szTmp2), GetString ("INSTALL_OF_FAILED"), szTmp, pszDesc); else StringCbPrintfW (szTmp2, sizeof(szTmp2), GetString ("UNINSTALL_OF_FAILED"), szTmp, pszDesc); if (lpMsgBuf) LocalFree (lpMsgBuf); if (!Silent && MessageBoxW (hwndDlg, szTmp2, lpszTitle, MB_YESNO | MB_ICONHAND) != IDYES) goto end; } if (bUninstall == FALSE) { GetCurrentDirectory (MAX_PATH, szCurrentDir); // Save current dir since it will be changed SetCurrentDirectory (szInstallDir.c_str()); // remove PDF from previous version if any h = FindFirstFile (L"VeraCrypt User Guide*.pdf", &f); if (h != INVALID_HANDLE_VALUE) { do { StatDeleteFile (f.cFileName, TRUE); } while (FindNextFile(h, &f) != 0); FindClose (h); } // remove language XML files from previous version if any h = FindFirstFile (L"Language*.xml", &f); if (h != INVALID_HANDLE_VALUE) { do { StatDeleteFile (f.cFileName, TRUE); } while (FindNextFile(h, &f) != 0); FindClose (h); } // remvove legacy files that are not needed anymore for (i = 0; i < sizeof (szLegacyFiles) / sizeof (szLegacyFiles[0]); i++) { StatDeleteFile (szLegacyFiles [i], TRUE); } SetCurrentDirectory(szCurrentDir); } } // Last part of DoRegInstall() { // Register COM servers for UAC if (!RegisterComServers ((wchar_t*)szInstallDir.c_str())) { MSILogAndShow (hInstaller, MSI_ERROR_LEVEL, GetString("COM_REG_FAILED")); goto end; } } if (UnloadDriver && DoDriverInstall_Dll(hInstaller) == FALSE) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostInstall: DoDriverInstall_Dll() failed"); bOK = FALSE; } else if (SystemEncryptionUpdate && UpgradeBootLoader_Dll(hInstaller, hwndDlg) == FALSE) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostInstall: UpgradeBootLoader_Dll() failed"); bOK = FALSE; } // Shortcuts are installed by MSI, so we skip that. if (!UnloadDriver) bRestartRequired = TRUE; try { bootEnc.RenameDeprecatedSystemLoaderBackup(); } catch (...) { } if (bSystemRestore) SetSystemRestorePoint_Dll (hInstaller, TRUE); if (bOK) { MSILog(hInstaller, MSI_INFO_LEVEL, GetString("INSTALL_COMPLETED")); } else { MSILog(hInstaller, MSI_INFO_LEVEL, L"Post install failed"); if (!SystemEncryptionUpdate) { bUninstall = TRUE; Rollback = TRUE; Silent = TRUE; DoUninstall_Dll (hInstaller, hwndDlg); bUninstall = FALSE; Rollback = FALSE; Silent = FALSE; MSILog(hInstaller, MSI_INFO_LEVEL, GetString("ROLLBACK")); } else { MSILog(hInstaller, MSI_WARNING_LEVEL, GetString("SYS_ENC_UPGRADE_FAILED")); } } if (bOK && !bUninstall && !bDowngrade && !bRepairMode && !bDevm) { BOOL bHibernateEnabled = FALSE, bHiberbootEnabled = FALSE; if (GetHibernateStatus (bHibernateEnabled, bHiberbootEnabled)) { if (bHiberbootEnabled) { bPromptFastStartup = TRUE; } } 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); if (bUpdateRescueDisk) { SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_RESCUE_DISK); } } else if (bPossiblyFirstTimeInstall) { SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_TUTORIAL); } } else { // No restart will be required if (bUpgrade) { bPromptReleaseNotes = TRUE; } else if (bPossiblyFirstTimeInstall) { bPromptTutorial = TRUE; } } } } if (bOK) { // This is part of MainDialogProc, WM_CLOSE, after PostMessage (MainDlg, bOK ? TC_APPMSG_INSTALL_SUCCESS : TC_APPMSG_INSTALL_FAILURE, 0, 0); /* if user selected a language, use for GUI in the next run */ if (bUserSetLanguage) { WCHAR langId[6]; MultiByteToWideChar (CP_ACP, 0, GetPreferredLangId(), -1, langId, ARRAYSIZE (langId)); WriteRegistryString (L"Software\\VeraCrypt", L"SetupUILanguage", langId); } if (bPromptFastStartup && AskWarnYesNo ("CONFIRM_DISABLE_FAST_STARTUP", hwndDlg) == IDYES) { WriteLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power", L"HiberbootEnabled", 0); bRestartRequired = TRUE; } bPromptFastStartup = FALSE; if (bPromptReleaseNotes && AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES", hwndDlg) == IDYES) { Applink_Dll (hInstaller, "releasenotes"); } bPromptReleaseNotes = FALSE; if (bPromptTutorial && AskYesNo ("AFTER_INSTALL_TUTORIAL", hwndDlg) == IDYES) { Applink_Dll (hInstaller, "beginnerstutorial"); } bPromptTutorial = FALSE; if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, L"Software\\.VeraCrypt\\Values", 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) == ERROR_SUCCESS) { RegSetValueEx (hkey, L"Silent", 0, REG_DWORD, (const BYTE*)(&Silent), sizeof(BOOL)); RegSetValueEx (hkey, L"bUninstall", 0, REG_DWORD, (const BYTE*)(&bUninstall), sizeof(BOOL)); RegSetValueEx (hkey, L"bDowngrade", 0, REG_DWORD, (const BYTE*)(&bDowngrade), sizeof(BOOL)); RegSetValueEx (hkey, L"bUninstallInProgress", 0, REG_DWORD, (const BYTE*)(&bUninstallInProgress), sizeof(BOOL)); RegSetValueEx (hkey, L"PortableMode", 0, REG_DWORD, (const BYTE*)(&PortableMode), sizeof(BOOL)); RegSetValueEx (hkey, L"UnloadDriver", 0, REG_DWORD, (const BYTE*)(&UnloadDriver), sizeof(BOOL)); RegSetValueEx (hkey, L"Rollback", 0, REG_DWORD, (const BYTE*)(&Rollback), sizeof(BOOL)); RegSetValueEx (hkey, L"bReinstallMode", 0, REG_DWORD, (const BYTE*)(&bReinstallMode), sizeof(BOOL)); RegSetValueEx (hkey, L"bUpgrade", 0, REG_DWORD, (const BYTE*)(&bUpgrade), sizeof(BOOL)); RegSetValueEx (hkey, L"bPossiblyFirstTimeInstall", 0, REG_DWORD, (const BYTE*)(&bPossiblyFirstTimeInstall), sizeof(BOOL)); RegSetValueEx (hkey, L"bDevm", 0, REG_DWORD, (const BYTE*)(&bDevm), sizeof(BOOL)); RegSetValueEx (hkey, L"SystemEncryptionUpdate", 0, REG_DWORD, (const BYTE*)(&SystemEncryptionUpdate), sizeof(BOOL)); RegSetValueEx (hkey, L"bRestartRequired", 0, REG_DWORD, (const BYTE*)(&bRestartRequired), sizeof(BOOL)); RegSetValueEx (hkey, L"bDisableSwapFiles", 0, REG_DWORD, (const BYTE*)(&bDisableSwapFiles), sizeof(BOOL)); RegSetValueEx (hkey, L"bSystemRestore", 0, REG_DWORD, (const BYTE*)(&bSystemRestore), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptFastStartup", 0, REG_DWORD, (const BYTE*)(&bPromptFastStartup), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptReleaseNotes", 0, REG_DWORD, (const BYTE*)(&bPromptReleaseNotes), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptTutorial", 0, REG_DWORD, (const BYTE*)(&bPromptTutorial), sizeof(BOOL)); RegSetValueEx (hkey, L"bUpdateRescueDisk", 0, REG_DWORD, (const BYTE*)(&bUpdateRescueDisk), sizeof(BOOL)); RegSetValueEx (hkey, L"bRepairMode", 0, REG_DWORD, (const BYTE*)(&bRepairMode), sizeof(BOOL)); RegSetValueEx (hkey, L"bUserSetLanguage", 0, REG_DWORD, (const BYTE*)(&bUserSetLanguage), sizeof(BOOL)); RegCloseKey (hkey); uiRet = ERROR_SUCCESS; } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"End VC_CustomAction_PostInstall: Could not write to registry"); } // delete entry of EXE installation if it exists RegDeleteKeyExW (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt", KEY_WOW64_32KEY, 0); } end: MSILog(hInstaller, MSI_INFO_LEVEL, L"End VC_CustomAction_PostInstall"); return uiRet; } /* * Same as Setup.c, function DoUninstall(), but * without the actual uninstall, it only prepares the system * before the uninstall (before DoFilesInstall). * It runs as a Deferred CA. */ EXTERN_C UINT STDAPICALLTYPE VC_CustomAction_PreUninstall(MSIHANDLE hInstaller) { HWND hwndDlg = NULL; std::wstring szValueBuf = L""; DWORD cchValueBuf = 0; UINT uiStat = 0; HKEY hkey = 0; DWORD dw = 0; BootEncryption bootEnc(NULL); std::wstring szInstallDir = L""; UINT uiRet = ERROR_INSTALL_FAILURE; BOOL bTempSkipSysRestore = FALSE; BOOL bOK = TRUE; MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin VC_CustomAction_PreUninstall"); // Get UILevel to see whether we're being installed silently or not. // Also get INSTALLDIR to see where we're being installed. // Since this is a Deferred CA, they are to be setup in its CustomActionData. uiStat = MsiGetProperty(hInstaller, TEXT("CustomActionData"), (LPWSTR)TEXT(""), &cchValueBuf); if (ERROR_MORE_DATA == uiStat) { ++cchValueBuf; // add 1 for null termination szValueBuf.resize(cchValueBuf); uiStat = MsiGetProperty(hInstaller, TEXT("CustomActionData"), &szValueBuf[0], &cchValueBuf); if ((ERROR_SUCCESS == uiStat)) { MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PreUninstall: CustomActionData = '%s'", szValueBuf.c_str()); std::vector szTokens; Tokenize(szValueBuf.c_str(), szTokens); for (size_t i = 0; i < szTokens.size(); i++) { std::wstring szToken = szTokens[i]; if (wcsncmp(szToken.c_str(), L"UILEVEL=", wcslen(L"UILEVEL=")) == 0) { size_t index0 = szToken.find_first_of(L"="); if (index0 != std::wstring::npos) { std::wstring uiLevel = szToken.substr(index0 + 1); Silent = (stoi(uiLevel) <= 3); MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PreInstall: UILEVEL = '%s', bSilent = '%d'", uiLevel.c_str(), Silent); } } else if (wcsncmp(szToken.c_str(), L"INSTALLDIR=", wcslen(L"INSTALLDIR=")) == 0) { size_t index0 = szToken.find_first_of(L"="); if (index0 != std::wstring::npos) { szInstallDir = szToken.substr(index0 + 1); MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PreInstall: INSTALLDIR = '%s'", szInstallDir.c_str()); } } else if (wcsncmp(szToken.c_str(), L"REINSTALL=", wcslen(L"REINSTALL=")) == 0) { size_t index0 = szToken.find_first_of(L"="); if (index0 != std::wstring::npos) { std::wstring szReinstall = szToken.substr(index0 + 1); bRepairMode = (wcslen(szReinstall.c_str()) != 0); MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PreInstall: REINSTALL = '%s', bRepairMode = '%s'", szReinstall.c_str(), bRepairMode ? L"TRUE" : L"FALSE"); } } } } } // Get this MSI Installer HWND. // There cannot be 2 MSIs or more running at the same time, so we're sure we'll get ours. // This is only possible in case of non silent install. hwndDlg = FindWindow(L"MsiDialogCloseClass", NULL); if (!hwndDlg && !Silent) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PreUninstall: MsiDialogCloseClass not found"); goto end; } /* Start actual work */ bUninstall = TRUE; if (!VC_CustomAction_Init(hInstaller, szInstallDir.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PreUninstall: VC_CustomAction_Init() failed"); goto end; } atexit(VC_CustomAction_Cleanup); bootEnc.SetParentWindow(hwndDlg); if (DoDriverUnload_Dll(hInstaller, hwndDlg) == FALSE) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PreUninstall: DoDriverUnload_Dll() failed"); bOK = FALSE; bTempSkipSysRestore = TRUE; // Volumes are possibly mounted; defer System Restore point creation for this uninstall attempt. } else { if (!Rollback && bSystemRestore && !bTempSkipSysRestore) SetSystemRestorePoint_Dll (hInstaller, FALSE); if (DoServiceUninstall_Dll (hInstaller, hwndDlg, L"veracrypt") == FALSE) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PreUninstall: DoServiceUninstall_Dll(veracrypt) failed"); bOK = FALSE; } // DoRegUninstall_Dll removes regkeys that are not linked to MSI // We need to do this in PreUninstall instead of in PostUninstall so that UnregisterComServers works, // because in PostUninstall the "VeraCrypt COMReg.exe" is removed and UnregisterComServers will fail. else if (DoRegUninstall_Dll (hInstaller, FALSE) == FALSE) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PreUninstall: DoRegUninstall_Dll() failed"); bOK = FALSE; } } if (bOK) { // uiRet = MsiSetProperty(hInstaller, TEXT("ISREBOOTREQUIRED"), TEXT("1")); // Cannot do this because this is a Deferred CA (we need Deferred so that it runs with admin privileges). // MsiGetProperty and MsiSetProperty properties cannot be used for deferred InstallScript custom actions, // which do not have access to the active .msi database and do not recognize any Windows Installer properties. // They can access only the information that has been written into the execution script (CustomActionData). // Therefore, we set the values in RegKeys that are volatile. if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, L"Software\\.VeraCrypt\\Values", 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) == ERROR_SUCCESS) { RegSetValueEx (hkey, L"Silent", 0, REG_DWORD, (const BYTE*)(&Silent), sizeof(BOOL)); RegSetValueEx (hkey, L"bUninstall", 0, REG_DWORD, (const BYTE*)(&bUninstall), sizeof(BOOL)); RegSetValueEx (hkey, L"bDowngrade", 0, REG_DWORD, (const BYTE*)(&bDowngrade), sizeof(BOOL)); RegSetValueEx (hkey, L"bUninstallInProgress", 0, REG_DWORD, (const BYTE*)(&bUninstallInProgress), sizeof(BOOL)); RegSetValueEx (hkey, L"PortableMode", 0, REG_DWORD, (const BYTE*)(&PortableMode), sizeof(BOOL)); RegSetValueEx (hkey, L"UnloadDriver", 0, REG_DWORD, (const BYTE*)(&UnloadDriver), sizeof(BOOL)); RegSetValueEx (hkey, L"Rollback", 0, REG_DWORD, (const BYTE*)(&Rollback), sizeof(BOOL)); RegSetValueEx (hkey, L"bReinstallMode", 0, REG_DWORD, (const BYTE*)(&bReinstallMode), sizeof(BOOL)); RegSetValueEx (hkey, L"bUpgrade", 0, REG_DWORD, (const BYTE*)(&bUpgrade), sizeof(BOOL)); RegSetValueEx (hkey, L"bPossiblyFirstTimeInstall", 0, REG_DWORD, (const BYTE*)(&bPossiblyFirstTimeInstall), sizeof(BOOL)); RegSetValueEx (hkey, L"bDevm", 0, REG_DWORD, (const BYTE*)(&bDevm), sizeof(BOOL)); RegSetValueEx (hkey, L"SystemEncryptionUpdate", 0, REG_DWORD, (const BYTE*)(&SystemEncryptionUpdate), sizeof(BOOL)); RegSetValueEx (hkey, L"bRestartRequired", 0, REG_DWORD, (const BYTE*)(&bRestartRequired), sizeof(BOOL)); RegSetValueEx (hkey, L"bDisableSwapFiles", 0, REG_DWORD, (const BYTE*)(&bDisableSwapFiles), sizeof(BOOL)); RegSetValueEx (hkey, L"bSystemRestore", 0, REG_DWORD, (const BYTE*)(&bSystemRestore), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptFastStartup", 0, REG_DWORD, (const BYTE*)(&bPromptFastStartup), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptReleaseNotes", 0, REG_DWORD, (const BYTE*)(&bPromptReleaseNotes), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptTutorial", 0, REG_DWORD, (const BYTE*)(&bPromptTutorial), sizeof(BOOL)); RegSetValueEx (hkey, L"bUpdateRescueDisk", 0, REG_DWORD, (const BYTE*)(&bUpdateRescueDisk), sizeof(BOOL)); RegSetValueEx (hkey, L"bRepairMode", 0, REG_DWORD, (const BYTE*)(&bRepairMode), sizeof(BOOL)); RegSetValueEx (hkey, L"bUserSetLanguage", 0, REG_DWORD, (const BYTE*)(&bUserSetLanguage), sizeof(BOOL)); RegCloseKey (hkey); uiRet = ERROR_SUCCESS; } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"End VC_CustomAction_PreUninstall: Could not write to registry"); } } end: MSILog(hInstaller, MSI_INFO_LEVEL, L"End VC_CustomAction_PreUninstall"); return uiRet; } static BOOL DirectoryExists (const wchar_t *dirName) { DWORD attrib = GetFileAttributes (dirName); return (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY)); } static BOOL DeleteContentsOnReboot(LPCTSTR pszDir) { TCHAR szPath[MAX_PATH]; TCHAR szSubPath[MAX_PATH]; WIN32_FIND_DATA FindFileData; HANDLE hFind; BOOL bHasBackslash = FALSE; // check if pszDir ends with a backslash if (pszDir[_tcslen(pszDir) - 1] == '\\') { bHasBackslash = TRUE; } // Prepare the path for FindFirstFile if (bHasBackslash) StringCchPrintf(szPath, MAX_PATH, TEXT("%s*"), pszDir); else StringCchPrintf(szPath, MAX_PATH, TEXT("%s\\*"), pszDir); hFind = FindFirstFile(szPath, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { return FALSE; } BOOL result = TRUE; do { if (_tcscmp(FindFileData.cFileName, TEXT(".")) != 0 && _tcscmp(FindFileData.cFileName, TEXT("..")) != 0) { if (bHasBackslash) StringCchPrintf(szSubPath, MAX_PATH, TEXT("%s%s"), pszDir, FindFileData.cFileName); else StringCchPrintf(szSubPath, MAX_PATH, TEXT("%s\\%s"), pszDir, FindFileData.cFileName); if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // Recursive call to handle subdirectories if (!DeleteContentsOnReboot(szSubPath)) { result = FALSE; // Track failures but attempt to continue } } else { // Schedule the file for deletion if (!MoveFileEx(szSubPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) { result = FALSE; // Track failures } } } } while (FindNextFile(hFind, &FindFileData) != 0); FindClose(hFind); // Schedule the root directory for deletion, only if not done already if (!MoveFileEx(pszDir, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) { result = FALSE; } return result; } /* * Same as Setup.c, function DoUninstall(), but * without the actual installation, it only performs * post install operations (after DoFilesInstall and last parts * of DoFilesInstall / DoRegUninstall). * It also sets regkey accordingly. * It runs as a Deferred CA. */ EXTERN_C UINT STDAPICALLTYPE VC_CustomAction_PostUninstall(MSIHANDLE hInstaller) { HWND hwndDlg = NULL; std::wstring szValueBuf = L""; DWORD cchValueBuf = 0; UINT uiStat = 0; HKEY hkey = 0; DWORD dw = 0; BootEncryption bootEnc(NULL); std::wstring szInstallDir = L""; UINT uiRet = ERROR_INSTALL_FAILURE; BOOL bTempSkipSysRestore = FALSE; BOOL bOK = TRUE; MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin VC_CustomAction_PostUninstall"); // Get INSTALLDIR to see where we're being installed. uiStat = MsiGetProperty(hInstaller, TEXT("CustomActionData"), (LPWSTR)TEXT(""), &cchValueBuf); if (ERROR_MORE_DATA == uiStat) { ++cchValueBuf; // add 1 for null termination szValueBuf.resize(cchValueBuf); uiStat = MsiGetProperty(hInstaller, TEXT("CustomActionData"), &szValueBuf[0], &cchValueBuf); if ((ERROR_SUCCESS == uiStat)) { MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PostUninstall: CustomActionData = '%s'", szValueBuf.c_str()); if (wcsncmp(szValueBuf.c_str(), L"INSTALLDIR=", wcslen(L"INSTALLDIR=")) == 0) { size_t index0 = szValueBuf.find_first_of(L"="); if (index0 != std::wstring::npos) { szInstallDir = szValueBuf.substr(index0 + 1); MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_PostUninstall: INSTALLDIR = '%s'", szInstallDir.c_str()); } } } } // Read RegKeys previously setup by PreInstall if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"Software\\.VeraCrypt\\Values", 0, KEY_READ, &hkey) == ERROR_SUCCESS) { DWORD cbValue = sizeof(DWORD); DWORD dwValue = 0; RegQueryValueEx (hkey, L"Silent", NULL, NULL, (LPBYTE) &dwValue, &cbValue); Silent = (dwValue == 1); RegQueryValueEx (hkey, L"bUninstall", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUninstall = (dwValue == 1); RegQueryValueEx (hkey, L"bDowngrade", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bDowngrade = (dwValue == 1); RegQueryValueEx (hkey, L"bUninstallInProgress", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUninstallInProgress = (dwValue == 1); RegQueryValueEx (hkey, L"PortableMode", NULL, NULL, (LPBYTE) &dwValue, &cbValue); PortableMode = (dwValue == 1); RegQueryValueEx (hkey, L"UnloadDriver", NULL, NULL, (LPBYTE) &dwValue, &cbValue); UnloadDriver = (dwValue == 1); RegQueryValueEx (hkey, L"Rollback", NULL, NULL, (LPBYTE) &dwValue, &cbValue); Rollback = (dwValue == 1); RegQueryValueEx (hkey, L"bReinstallMode", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bReinstallMode = (dwValue == 1); RegQueryValueEx (hkey, L"bUpgrade", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUpgrade = (dwValue == 1); RegQueryValueEx (hkey, L"bPossiblyFirstTimeInstall", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPossiblyFirstTimeInstall = (dwValue == 1); RegQueryValueEx (hkey, L"bDevm", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bDevm = (dwValue == 1); RegQueryValueEx (hkey, L"SystemEncryptionUpdate", NULL, NULL, (LPBYTE) &dwValue, &cbValue); SystemEncryptionUpdate = (dwValue == 1); RegQueryValueEx (hkey, L"bRestartRequired", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bRestartRequired = (dwValue == 1); RegQueryValueEx (hkey, L"bDisableSwapFiles", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bDisableSwapFiles = (dwValue == 1); RegQueryValueEx (hkey, L"bSystemRestore", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bSystemRestore = (dwValue == 1); RegQueryValueEx (hkey, L"bPromptFastStartup", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPromptFastStartup = (dwValue == 1); RegQueryValueEx (hkey, L"bPromptReleaseNotes", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPromptReleaseNotes = (dwValue == 1); RegQueryValueEx (hkey, L"bPromptTutorial", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPromptTutorial = (dwValue == 1); RegQueryValueEx (hkey, L"bUpdateRescueDisk", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUpdateRescueDisk = (dwValue == 1); RegQueryValueEx (hkey, L"bRepairMode", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bRepairMode = (dwValue == 1); RegQueryValueEx (hkey, L"bUserSetLanguage", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUserSetLanguage = (dwValue == 1); RegCloseKey (hkey); } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"End VC_CustomAction_PostUninstall: Could not read from registry"); goto end; } // Get this MSI Installer HWND. // There cannot be 2 MSIs or more running at the same time, so we're sure we'll get ours. // This is only possible in case of non silent install. hwndDlg = FindWindow(L"MsiDialogCloseClass", NULL); if (!hwndDlg && !Silent) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: MsiDialogCloseClass not found"); goto end; } /* Start actual work */ bUninstall = TRUE; if (!VC_CustomAction_Init(hInstaller, szInstallDir.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: VC_CustomAction_Init() failed"); goto end; } atexit(VC_CustomAction_Cleanup); bootEnc.SetParentWindow(hwndDlg); if (!DoApplicationDataUninstall_Dll (hInstaller)) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: DoApplicationDataUninstall_Dll() failed"); bOK = FALSE; } else { // Deprecated service DoServiceUninstall_Dll (hInstaller, hwndDlg, L"VeraCryptService"); } // Last part of DoFilesInstall() { EnableWow64FsRedirection (FALSE); wstring servicePath = GetServiceConfigPath (_T(TC_APP_NAME) L".exe", false); wstring serviceLegacyPath = GetServiceConfigPath (_T(TC_APP_NAME) L".exe", true); wstring favoritesFile = GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, false); wstring favoritesLegacyFile = GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, true); // delete all files related to system favorites service if (FileExists (favoritesFile.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: REMOVING %s", favoritesFile.c_str()); ForceDeleteFile (favoritesFile.c_str()); } if (FileExists (servicePath.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: REMOVING %s", servicePath.c_str()); ForceDeleteFile (servicePath.c_str()); } if (FileExists (favoritesLegacyFile.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: REMOVING %s", favoritesLegacyFile.c_str()); ForceDeleteFile (favoritesLegacyFile.c_str()); } if (FileExists (serviceLegacyPath.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: REMOVING %s", serviceLegacyPath.c_str()); ForceDeleteFile (serviceLegacyPath.c_str()); } EnableWow64FsRedirection (TRUE); // remove the installation folder is case it remains after uninstall if (DirectoryExists (szInstallDir.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: REMOVING %s", szInstallDir.c_str()); if(DeleteDirectory (szInstallDir.c_str())) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: %s removed", szInstallDir.c_str()); } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: %s could not be removed. Scheduling removal on reboot", szInstallDir.c_str()); if (DeleteContentsOnReboot(szInstallDir.c_str())) { bRestartRequired = TRUE; MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: %s scheduled for removal on reboot", szInstallDir.c_str()); } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: %s could not be scheduled for removal on reboot", szInstallDir.c_str()); } } } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_PostUninstall: %s does not exist", szInstallDir.c_str()); } } if (bSystemRestore && !bTempSkipSysRestore) SetSystemRestorePoint_Dll (hInstaller, TRUE); if (bOK) { // uiRet = MsiSetProperty(hInstaller, TEXT("ISREBOOTREQUIRED"), TEXT("1")); // Cannot do this because this is a Deferred CA (we need Deferred so that it runs with admin privileges). // MsiGetProperty and MsiSetProperty properties cannot be used for deferred InstallScript custom actions, // which do not have access to the active .msi database and do not recognize any Windows Installer properties. // They can access only the information that has been written into the execution script (CustomActionData). // Therefore, we set the values in RegKeys that are volatile. if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, L"Software\\.VeraCrypt\\Values", 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) == ERROR_SUCCESS) { RegSetValueEx (hkey, L"Silent", 0, REG_DWORD, (const BYTE*)(&Silent), sizeof(BOOL)); RegSetValueEx (hkey, L"bUninstall", 0, REG_DWORD, (const BYTE*)(&bUninstall), sizeof(BOOL)); RegSetValueEx (hkey, L"bDowngrade", 0, REG_DWORD, (const BYTE*)(&bDowngrade), sizeof(BOOL)); RegSetValueEx (hkey, L"bUninstallInProgress", 0, REG_DWORD, (const BYTE*)(&bUninstallInProgress), sizeof(BOOL)); RegSetValueEx (hkey, L"PortableMode", 0, REG_DWORD, (const BYTE*)(&PortableMode), sizeof(BOOL)); RegSetValueEx (hkey, L"UnloadDriver", 0, REG_DWORD, (const BYTE*)(&UnloadDriver), sizeof(BOOL)); RegSetValueEx (hkey, L"Rollback", 0, REG_DWORD, (const BYTE*)(&Rollback), sizeof(BOOL)); RegSetValueEx (hkey, L"bReinstallMode", 0, REG_DWORD, (const BYTE*)(&bReinstallMode), sizeof(BOOL)); RegSetValueEx (hkey, L"bUpgrade", 0, REG_DWORD, (const BYTE*)(&bUpgrade), sizeof(BOOL)); RegSetValueEx (hkey, L"bPossiblyFirstTimeInstall", 0, REG_DWORD, (const BYTE*)(&bPossiblyFirstTimeInstall), sizeof(BOOL)); RegSetValueEx (hkey, L"bDevm", 0, REG_DWORD, (const BYTE*)(&bDevm), sizeof(BOOL)); RegSetValueEx (hkey, L"SystemEncryptionUpdate", 0, REG_DWORD, (const BYTE*)(&SystemEncryptionUpdate), sizeof(BOOL)); RegSetValueEx (hkey, L"bRestartRequired", 0, REG_DWORD, (const BYTE*)(&bRestartRequired), sizeof(BOOL)); RegSetValueEx (hkey, L"bDisableSwapFiles", 0, REG_DWORD, (const BYTE*)(&bDisableSwapFiles), sizeof(BOOL)); RegSetValueEx (hkey, L"bSystemRestore", 0, REG_DWORD, (const BYTE*)(&bSystemRestore), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptFastStartup", 0, REG_DWORD, (const BYTE*)(&bPromptFastStartup), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptReleaseNotes", 0, REG_DWORD, (const BYTE*)(&bPromptReleaseNotes), sizeof(BOOL)); RegSetValueEx (hkey, L"bPromptTutorial", 0, REG_DWORD, (const BYTE*)(&bPromptTutorial), sizeof(BOOL)); RegSetValueEx (hkey, L"bUpdateRescueDisk", 0, REG_DWORD, (const BYTE*)(&bUpdateRescueDisk), sizeof(BOOL)); RegSetValueEx (hkey, L"bRepairMode", 0, REG_DWORD, (const BYTE*)(&bRepairMode), sizeof(BOOL)); RegSetValueEx (hkey, L"bUserSetLanguage", 0, REG_DWORD, (const BYTE*)(&bUserSetLanguage), sizeof(BOOL)); RegCloseKey (hkey); uiRet = ERROR_SUCCESS; } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"End VC_CustomAction_PostUninstall: Could not write to registry"); } } else bUninstallInProgress = FALSE; end: MSILog(hInstaller, MSI_INFO_LEVEL, L"End VC_CustomAction_PostUninstall"); return uiRet; } /* Runs as a Commit CA : therefore, we can get / set properties that are defined in WiX. * It sets ISREBOOTREQUIRED Wix Property accordingly and refreshes extensions list * if REGISTERVCFILEEXT is set. */ EXTERN_C UINT STDAPICALLTYPE VC_CustomAction_DoChecks(MSIHANDLE hInstaller) { HWND hwndDlg = NULL; std::wstring szValueBuf = L""; DWORD cchValueBuf = 0; UINT uiStat = 0; HKEY hkey = 0; std::wstring szInstallDir = L""; BOOL bRefreshExts = FALSE; BOOL bDisableReboot = FALSE; UINT uiRet = ERROR_INSTALL_FAILURE; MSILog(hInstaller, MSI_INFO_LEVEL, L"Begin VC_CustomAction_DoChecks"); // Get WIXUI_INSTALLDIR to see where we're being installed uiStat = MsiGetProperty(hInstaller, TEXT("APPLICATIONROOTFOLDER"), (LPWSTR)TEXT(""), &cchValueBuf); if (ERROR_MORE_DATA == uiStat) { ++cchValueBuf; // add 1 for null termination szValueBuf.resize(cchValueBuf); uiStat = MsiGetProperty(hInstaller, TEXT("APPLICATIONROOTFOLDER"), &szValueBuf[0], &cchValueBuf); if ((ERROR_SUCCESS == uiStat)) { MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_DoChecks: APPLICATIONROOTFOLDER = '%s'", szValueBuf.c_str()); szInstallDir = szValueBuf; } } // Get REGISTERVCFILEEXT to see whether we should refresh extensions list. szValueBuf.clear(); cchValueBuf = 0; uiStat = MsiGetProperty(hInstaller, TEXT("REGISTERVCFILEEXT"), (LPWSTR)TEXT(""), &cchValueBuf); if (ERROR_MORE_DATA == uiStat) { ++cchValueBuf; // add 1 for null termination szValueBuf.resize(cchValueBuf); uiStat = MsiGetProperty(hInstaller, TEXT("REGISTERVCFILEEXT"), &szValueBuf[0], &cchValueBuf); if ((ERROR_SUCCESS == uiStat)) { MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_DoChecks: REGISTERVCFILEEXT = '%s'", szValueBuf.c_str()); bRefreshExts = (szValueBuf[0] == L'1'); } } // Get REBOOT to see whether it specified "ReallySuppress" which means no automatic reboot szValueBuf.clear(); cchValueBuf = 0; uiStat = MsiGetProperty(hInstaller, TEXT("REBOOT"), (LPWSTR)TEXT(""), &cchValueBuf); if (ERROR_MORE_DATA == uiStat) { ++cchValueBuf; // add 1 for null termination szValueBuf.resize(cchValueBuf); uiStat = MsiGetProperty(hInstaller, TEXT("REBOOT"), &szValueBuf[0], &cchValueBuf); if ((ERROR_SUCCESS == uiStat)) { MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_DoChecks: REBOOT = '%s'", szValueBuf.c_str()); bDisableReboot = (szValueBuf[0] == L'R' || szValueBuf[0] == L'r'); } } // Read RegKeys previously setup by Pre/Post-Install if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"Software\\.VeraCrypt\\Values", 0, KEY_READ, &hkey) == ERROR_SUCCESS) { DWORD cbValue = sizeof(DWORD); DWORD dwValue = 0; RegQueryValueEx (hkey, L"Silent", NULL, NULL, (LPBYTE) &dwValue, &cbValue); Silent = (dwValue == 1); RegQueryValueEx (hkey, L"bUninstall", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUninstall = (dwValue == 1); RegQueryValueEx (hkey, L"bDowngrade", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bDowngrade = (dwValue == 1); RegQueryValueEx (hkey, L"bUninstallInProgress", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUninstallInProgress = (dwValue == 1); RegQueryValueEx (hkey, L"PortableMode", NULL, NULL, (LPBYTE) &dwValue, &cbValue); PortableMode = (dwValue == 1); RegQueryValueEx (hkey, L"UnloadDriver", NULL, NULL, (LPBYTE) &dwValue, &cbValue); UnloadDriver = (dwValue == 1); RegQueryValueEx (hkey, L"Rollback", NULL, NULL, (LPBYTE) &dwValue, &cbValue); Rollback = (dwValue == 1); RegQueryValueEx (hkey, L"bReinstallMode", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bReinstallMode = (dwValue == 1); RegQueryValueEx (hkey, L"bUpgrade", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUpgrade = (dwValue == 1); RegQueryValueEx (hkey, L"bPossiblyFirstTimeInstall", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPossiblyFirstTimeInstall = (dwValue == 1); RegQueryValueEx (hkey, L"bDevm", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bDevm = (dwValue == 1); RegQueryValueEx (hkey, L"SystemEncryptionUpdate", NULL, NULL, (LPBYTE) &dwValue, &cbValue); SystemEncryptionUpdate = (dwValue == 1); RegQueryValueEx (hkey, L"bRestartRequired", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bRestartRequired = (dwValue == 1); RegQueryValueEx (hkey, L"bDisableSwapFiles", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bDisableSwapFiles = (dwValue == 1); RegQueryValueEx (hkey, L"bSystemRestore", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bSystemRestore = (dwValue == 1); RegQueryValueEx (hkey, L"bPromptFastStartup", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPromptFastStartup = (dwValue == 1); RegQueryValueEx (hkey, L"bPromptReleaseNotes", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPromptReleaseNotes = (dwValue == 1); RegQueryValueEx (hkey, L"bPromptTutorial", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bPromptTutorial = (dwValue == 1); RegQueryValueEx (hkey, L"bUpdateRescueDisk", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUpdateRescueDisk = (dwValue == 1); RegQueryValueEx (hkey, L"bRepairMode", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bRepairMode = (dwValue == 1); RegQueryValueEx (hkey, L"bUserSetLanguage", NULL, NULL, (LPBYTE) &dwValue, &cbValue); bUserSetLanguage = (dwValue == 1); RegCloseKey (hkey); } else { MSILog(hInstaller, MSI_ERROR_LEVEL, L"End VC_CustomAction_DoChecks: Could not read from registry"); goto end; } // Get this MSI Installer HWND. // There cannot be 2 MSIs or more running at the same time, so we're sure we'll get ours. // This is only possible in case of non silent install. hwndDlg = FindWindow(L"MsiDialogCloseClass", NULL); if (!hwndDlg && !Silent) { MSILog(hInstaller, MSI_ERROR_LEVEL, L"VC_CustomAction_DoChecks: MsiDialogCloseClass not found"); goto end; } /* Start actual work */ if (bRefreshExts) { MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_DoChecks: Will refresh file extensions"); SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); } // Check if reboot was required by the pre/post-install and set Wix property ISREBOOTREQUIRED accordingly. if (bRestartRequired) { if (bDisableReboot) { MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_DoChecks: reboot is required but it is disabled because \"REBOOT\" specifies ReallySuppress"); uiRet = ERROR_SUCCESS; } else { MSILog(hInstaller, MSI_INFO_LEVEL, L"VC_CustomAction_DoChecks: reboot is required"); uiRet = MsiSetProperty(hInstaller, L"ISREBOOTREQUIRED", L"1"); } } else { uiRet = ERROR_SUCCESS; } // Remove volatile regkeys SHDeleteKey(HKEY_LOCAL_MACHINE, L"Software\\.VeraCrypt"); end: MSILog(hInstaller, MSI_INFO_LEVEL, L"End VC_CustomAction_DoChecks"); return uiRet; } BOOL WINAPI DllMain( HMODULE hInstDLL, DWORD dwReason, LPVOID lpvReserved) { UNREFERENCED_PARAMETER(lpvReserved); /* Save the instance handle for later, * especially for loading embedded Language.xml file * in Dlgcode.c, MapResource() function. */ hInst = hInstDLL; return TRUE; }