From c606f0866c3a2a5db3ef9bc41738ef33eb9612a9 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sat, 22 Jun 2013 16:16:13 +0200 Subject: Add original TrueCrypt 7.1a sources --- src/Setup/ComSetup.cpp | 88 ++ src/Setup/ComSetup.h | 18 + src/Setup/ComSetup.rgs | 92 ++ src/Setup/Dir.c | 104 ++ src/Setup/Dir.h | 21 + src/Setup/Resource.h | 64 + src/Setup/SelfExtract.c | 734 ++++++++++ src/Setup/SelfExtract.h | 39 + src/Setup/Setup.c | 2160 ++++++++++++++++++++++++++++++ src/Setup/Setup.h | 100 ++ src/Setup/Setup.ico | Bin 0 -> 13382 bytes src/Setup/Setup.manifest | 21 + src/Setup/Setup.rc | 327 +++++ src/Setup/Setup.vcproj | 482 +++++++ src/Setup/TrueCrypt_setup.bmp | Bin 0 -> 49398 bytes src/Setup/TrueCrypt_setup_background.bmp | Bin 0 -> 822 bytes src/Setup/Wizard.c | 1203 +++++++++++++++++ src/Setup/Wizard.h | 29 + 18 files changed, 5482 insertions(+) create mode 100644 src/Setup/ComSetup.cpp create mode 100644 src/Setup/ComSetup.h create mode 100644 src/Setup/ComSetup.rgs create mode 100644 src/Setup/Dir.c create mode 100644 src/Setup/Dir.h create mode 100644 src/Setup/Resource.h create mode 100644 src/Setup/SelfExtract.c create mode 100644 src/Setup/SelfExtract.h create mode 100644 src/Setup/Setup.c create mode 100644 src/Setup/Setup.h create mode 100644 src/Setup/Setup.ico create mode 100644 src/Setup/Setup.manifest create mode 100644 src/Setup/Setup.rc create mode 100644 src/Setup/Setup.vcproj create mode 100644 src/Setup/TrueCrypt_setup.bmp create mode 100644 src/Setup/TrueCrypt_setup_background.bmp create mode 100644 src/Setup/Wizard.c create mode 100644 src/Setup/Wizard.h (limited to 'src/Setup') diff --git a/src/Setup/ComSetup.cpp b/src/Setup/ComSetup.cpp new file mode 100644 index 00000000..1608bcea --- /dev/null +++ b/src/Setup/ComSetup.cpp @@ -0,0 +1,88 @@ +/* + Copyright (c) 2007-2010 TrueCrypt Developers Association. All rights reserved. + + Governed by the TrueCrypt License 3.0 the full text of which is contained in + the file License.txt included in TrueCrypt binary and source code distribution + packages. +*/ + +#define TC_MAIN_COM_VERSION_MAJOR 2 +#define TC_MAIN_COM_VERSION_MINOR 4 + +#define TC_FORMAT_COM_VERSION_MAJOR 2 +#define TC_FORMAT_COM_VERSION_MINOR 4 + +#include +#include +#include +#include +#include "ComSetup.h" +#include "Dlgcode.h" +#include "Resource.h" +#include "../Mount/MainCom_i.c" +#include "../Format/FormatCom_i.c" + + +extern "C" BOOL RegisterComServers (char *modulePath) +{ + BOOL ret = TRUE; + wchar_t mainModule[1024], formatModule[1024]; + CComPtr tl, tl2; + + wsprintfW (mainModule, L"%hsTrueCrypt.exe", modulePath); + wsprintfW (formatModule, L"%hsTrueCrypt Format.exe", modulePath); + + UnRegisterTypeLib (LIBID_TrueCryptMainCom, TC_MAIN_COM_VERSION_MAJOR, TC_MAIN_COM_VERSION_MINOR, 0, SYS_WIN32); + UnRegisterTypeLib (LIBID_TrueCryptFormatCom, TC_FORMAT_COM_VERSION_MAJOR, TC_FORMAT_COM_VERSION_MINOR, 0, SYS_WIN32); + + wchar_t setupModule[MAX_PATH]; + GetModuleFileNameW (NULL, setupModule, sizeof (setupModule) / sizeof (setupModule[0])); + + CRegObject ro; + HRESULT r; + + if (!SUCCEEDED (r = ro.FinalConstruct ()) + || !SUCCEEDED (r = ro.AddReplacement (L"MAIN_MODULE", mainModule)) + || !SUCCEEDED (r = ro.AddReplacement (L"FORMAT_MODULE", formatModule)) + || !SUCCEEDED (r = ro.ResourceRegister (setupModule, IDR_COMREG, L"REGISTRY")) + || !SUCCEEDED (r = LoadTypeLib (mainModule, &tl)) + || !SUCCEEDED (r = RegisterTypeLib (tl, mainModule, 0)) + || !SUCCEEDED (r = LoadTypeLib (formatModule, &tl2)) + || !SUCCEEDED (r = RegisterTypeLib (tl2, formatModule, 0))) + { + MessageBox (MainDlg, _com_error (r).ErrorMessage(), TC_APP_NAME, MB_ICONERROR); + ret = FALSE; + } + + ro.FinalRelease (); + return ret; +} + + +extern "C" BOOL UnregisterComServers (char *modulePath) +{ + BOOL ret; + + if (UnRegisterTypeLib (LIBID_TrueCryptMainCom, TC_MAIN_COM_VERSION_MAJOR, TC_MAIN_COM_VERSION_MINOR, 0, SYS_WIN32) != S_OK) + return FALSE; + if (UnRegisterTypeLib (LIBID_TrueCryptFormatCom, TC_FORMAT_COM_VERSION_MAJOR, TC_FORMAT_COM_VERSION_MINOR, 0, SYS_WIN32) != S_OK) + return FALSE; + + wchar_t module[1024]; + CRegObject ro; + ro.FinalConstruct (); + + wsprintfW (module, L"%hsTrueCrypt.exe", modulePath); + ro.AddReplacement (L"MAIN_MODULE", module); + + wsprintfW (module, L"%hsTrueCrypt Format.exe", modulePath); + ro.AddReplacement (L"FORMAT_MODULE", module); + + wchar_t setupModule[MAX_PATH]; + GetModuleFileNameW (NULL, setupModule, sizeof (setupModule) / sizeof (setupModule[0])); + + ret = ro.ResourceUnregister (setupModule, IDR_COMREG, L"REGISTRY") == S_OK; + + ro.FinalRelease (); + return ret; +} diff --git a/src/Setup/ComSetup.h b/src/Setup/ComSetup.h new file mode 100644 index 00000000..7a9fad2d --- /dev/null +++ b/src/Setup/ComSetup.h @@ -0,0 +1,18 @@ +/* + Copyright (c) 2007 TrueCrypt Developers Association. All rights reserved. + + Governed by the TrueCrypt License 3.0 the full text of which is contained in + the file License.txt included in TrueCrypt binary and source code distribution + packages. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +BOOL RegisterComServers (char *modulePath); +BOOL UnregisterComServers (char *modulePath); + +#ifdef __cplusplus +} +#endif diff --git a/src/Setup/ComSetup.rgs b/src/Setup/ComSetup.rgs new file mode 100644 index 00000000..a1cf61f5 --- /dev/null +++ b/src/Setup/ComSetup.rgs @@ -0,0 +1,92 @@ +HKCR +{ + ForceRemove TrueCrypt.1 = s 'TrueCrypt class' + { + CLSID = s '{CECBC0EE-78D9-41E6-BCF1-BC222BB224BA}' + } + + ForceRemove TrueCrypt = s 'TrueCrypt class' + { + CLSID = s '{CECBC0EE-78D9-41E6-BCF1-BC222BB224BA}' + CurVer = s 'TrueCrypt.1' + } + + NoRemove CLSID + { + ForceRemove {CECBC0EE-78D9-41E6-BCF1-BC222BB224BA} = s 'TrueCrypt class' + { + ProgID = s 'TrueCrypt.1' + VersionIndependentProgID = s 'TrueCrypt' + LocalServer32 = s '"%MAIN_MODULE%"' + + TypeLib = s '{1770F56C-7881-4591-A179-79B8001C7D42}' + + Elevation + { + val Enabled = d 1 + val IconReference = s '@%MAIN_MODULE%,-501' + } + + val AppId = s '{CECBC0EE-78D9-41E6-BCF1-BC222BB224BA}' + val LocalizedString = s '@%MAIN_MODULE%,-110' + } + } + + NoRemove AppId + { + ForceRemove {CECBC0EE-78D9-41E6-BCF1-BC222BB224BA} = s 'TrueCrypt class' + { + val AccessPermission = b 010004803000000040000000000000001400000002001c000100000000001400070000000101000000000005040000000102000000000005200000002002000001020000000000052000000020020000 + } + + ForceRemove TrueCrypt.exe + { + val AppId = s '{CECBC0EE-78D9-41E6-BCF1-BC222BB224BA}' + } + } + + ForceRemove TrueCryptFormat.1 = s 'TrueCryptFormat class' + { + CLSID = s '{777DCDFD-C330-480B-B582-B02B57580CC9}' + } + + ForceRemove TrueCryptFormat = s 'TrueCryptFormat class' + { + CLSID = s '{777DCDFD-C330-480B-B582-B02B57580CC9}' + CurVer = s 'TrueCryptFormat.1' + } + + NoRemove CLSID + { + ForceRemove {777DCDFD-C330-480B-B582-B02B57580CC9} = s 'TrueCryptFormat class' + { + ProgID = s 'TrueCryptFormat.1' + VersionIndependentProgID = s 'TrueCryptFormat' + LocalServer32 = s '"%FORMAT_MODULE%"' + + TypeLib = s '{A7DF958C-0716-49E9-8C3E-53A775797576}' + + Elevation + { + val Enabled = d 1 + val IconReference = s '@%FORMAT_MODULE%,-501' + } + + val AppId = s '{777DCDFD-C330-480B-B582-B02B57580CC9}' + val LocalizedString = s '@%FORMAT_MODULE%,-112' + } + } + + NoRemove AppId + { + ForceRemove {777DCDFD-C330-480B-B582-B02B57580CC9} = s 'TrueCryptFormat class' + { + val AccessPermission = b 010004803000000040000000000000001400000002001c000100000000001400070000000101000000000005040000000102000000000005200000002002000001020000000000052000000020020000 + } + + ForceRemove 'TrueCrypt Format.exe' + { + val AppId = s '{777DCDFD-C330-480B-B582-B02B57580CC9}' + } + } +} \ No newline at end of file diff --git a/src/Setup/Dir.c b/src/Setup/Dir.c new file mode 100644 index 00000000..7c418c74 --- /dev/null +++ b/src/Setup/Dir.c @@ -0,0 +1,104 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions + of this file are Copyright (c) 2003-2008 TrueCrypt Developers Association + and are governed by the TrueCrypt License 3.0 the full text of which is + contained in the file License.txt included in TrueCrypt binary and source + code distribution packages. */ + +#include "Tcdefs.h" + +#include +#include +#include +#include +#include +#include + +#include "Dir.h" + +/* create full directory tree. returns 0 for success, -1 if failure */ +int +mkfulldir (char *oriPath, BOOL bCheckonly) +{ + struct _stat st; + char *uniq_file; + char path [TC_MAX_PATH]; + + strcpy (path, oriPath); + + if (strlen (path) == 3 && path[1] == ':') + goto is_root; /* keep final slash in root if present */ + + /* strip final forward or backslash if we have one! */ + uniq_file = strrchr (path, '\\'); + if (uniq_file && uniq_file[1] == '\0') + uniq_file[0] = '\0'; + else + { + uniq_file = strrchr (path, '/'); + if (uniq_file && uniq_file[1] == '\0') + uniq_file[0] = '\0'; + } + + is_root: + if (bCheckonly) + return _stat (path, &st); + + if (_stat (path, &st)) + return mkfulldir_internal (path); + else + return 0; +} + + +int +mkfulldir_internal (char *path) +{ + char *token; + struct _stat st; + static char tokpath[_MAX_PATH]; + static char trail[_MAX_PATH]; + + strcpy (tokpath, path); + trail[0] = '\0'; + + token = strtok (tokpath, "\\/"); + + if (tokpath[0] == '\\' && tokpath[1] == '\\') + { /* unc */ + trail[0] = tokpath[0]; + trail[1] = tokpath[1]; + trail[2] = '\0'; + strcat (trail, token); + strcat (trail, "\\"); + token = strtok (NULL, "\\/"); + if (token) + { /* get share name */ + strcat (trail, token); + strcat (trail, "\\"); + } + token = strtok (NULL, "\\/"); + } + + if (tokpath[1] == ':') + { /* drive letter */ + strcat (trail, tokpath); + strcat (trail, "\\"); + token = strtok (NULL, "\\/"); + } + + while (token != NULL) + { + int x; + strcat (trail, token); + x = _mkdir (trail); + strcat (trail, "\\"); + token = strtok (NULL, "\\/"); + } + + return _stat (path, &st); +} diff --git a/src/Setup/Dir.h b/src/Setup/Dir.h new file mode 100644 index 00000000..506dff17 --- /dev/null +++ b/src/Setup/Dir.h @@ -0,0 +1,21 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions + of this file are Copyright (c) 2003-2008 TrueCrypt Developers Association + and are governed by the TrueCrypt License 3.0 the full text of which is + contained in the file License.txt included in TrueCrypt binary and source + code distribution packages. */ + +#ifdef __cplusplus +extern "C" { +#endif + +int mkfulldir ( char *path , BOOL bCheckonly ); +int mkfulldir_internal ( char *path ); + +#ifdef __cplusplus +} +#endif diff --git a/src/Setup/Resource.h b/src/Setup/Resource.h new file mode 100644 index 00000000..2baaefe0 --- /dev/null +++ b/src/Setup/Resource.h @@ -0,0 +1,64 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Setup.rc +// +#define IDR_COMREG 10 +#define IDD_INSTALL 101 +#define IDD_INSTALL_OPTIONS_PAGE_DLG 102 +#define IDD_UNINSTALL 103 +#define IDI_SETUP 104 +#define IDR_SETUP_RSRC_HEADER 105 +#define IDD_EXTRACTION_OPTIONS_PAGE_DLG 106 +#define IDB_SETUP_WIZARD 107 +#define IDD_INTRO_PAGE_DLG 108 +#define IDB_SETUP_WIZARD_BKG 109 +#define IDD_INFO_PAGE_DLG 110 +#define IDD_INSTL_DLG 111 +#define IDD_WIZARD_MODE_PAGE_DLG 112 +#define IDD_PROGRESS_PAGE_DLG 113 +#define IDD_DONATIONS_PAGE_DLG 114 +#define IDC_DESTINATION 1000 +#define IDC_BOX_TITLE 1001 +#define IDC_BROWSE 1002 +#define IDC_BOX_INFO 1003 +#define IDC_LICENSE 1004 +#define IDC_BOX_HELP 1005 +#define IDC_LICENSE_TEXT 1006 +#define IDC_BOX_HELP2 1007 +#define IDC_FILE_TYPE 1008 +#define IDT_UNINSTALL_DIR 1009 +#define IDC_PROG_GROUP 1010 +#define IDC_SYSTEM_RESTORE 1011 +#define IDC_DESKTOP_ICON 1012 +#define IDC_ALL_USERS 1013 +#define IDT_INSTALL_DESTINATION 1014 +#define IDC_UNINSTALL 1015 +#define IDC_PROGRESS_BAR 1016 +#define IDC_LOG_WINDOW 1017 +#define IDC_SETUP_WIZARD_BKG 1018 +#define IDC_SETUP_WIZARD_GFX_AREA 1019 +#define IDC_HR 1020 +#define IDC_OPEN_CONTAINING_FOLDER 1021 +#define IDC_AGREE 1022 +#define IDC_HR_BOTTOM 1023 +#define IDC_WIZARD_MODE_INSTALL 1024 +#define IDC_WIZARD_MODE_EXTRACT_ONLY 1025 +#define IDC_NEXT 1026 +#define IDC_PREV 1027 +#define IDT_EXTRACT_DESTINATION 1028 +#define IDC_POS_BOX 1029 +#define IDC_BITMAP_SETUP_WIZARD 1030 +#define IDC_MAIN_CONTENT_CANVAS 1031 +#define IDC_DONATE 1032 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 115 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1033 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Setup/SelfExtract.c b/src/Setup/SelfExtract.c new file mode 100644 index 00000000..7377da4a --- /dev/null +++ b/src/Setup/SelfExtract.c @@ -0,0 +1,734 @@ +/* + Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved. + + Governed by the TrueCrypt License 3.0 the full text of which is contained in + the file License.txt included in TrueCrypt binary and source code distribution + packages. +*/ + +#include "Tcdefs.h" + +#include "Inflate.h" +#include "SelfExtract.h" +#include "Wizard.h" +#include "Setup.h" +#include "Crc.h" +#include "Endian.h" +#include "Dlgcode.h" +#include "Dir.h" +#include "Language.h" +#include "Resource.h" + +#define OutputPackageFile "TrueCrypt Setup " VERSION_STRING ".exe" + +#define MAG_START_MARKER "TCINSTRT" +#define MAG_END_MARKER_OBFUSCATED "T/C/I/N/S/C/R/C" +#define PIPE_BUFFER_LEN (4 * BYTES_PER_KB) + +unsigned char MagEndMarker [sizeof (MAG_END_MARKER_OBFUSCATED)]; +char DestExtractPath [TC_MAX_PATH]; +DECOMPRESSED_FILE Decompressed_Files [NBR_COMPRESSED_FILES]; + +volatile char *PipeWriteBuf = NULL; +volatile HANDLE hChildStdinWrite = INVALID_HANDLE_VALUE; +unsigned char *DecompressedData = NULL; + + + +void SelfExtractStartupInit (void) +{ + DeobfuscateMagEndMarker (); +} + + +// The end marker must be included in the self-extracting exe only once, not twice (used e.g. +// by IsSelfExtractingPackage()) and that's why MAG_END_MARKER_OBFUSCATED is obfuscated and +// needs to be deobfuscated using this function at startup. +static void DeobfuscateMagEndMarker (void) +{ + int i; + + for (i = 0; i < sizeof (MAG_END_MARKER_OBFUSCATED); i += 2) + MagEndMarker [i/2] = MAG_END_MARKER_OBFUSCATED [i]; + + MagEndMarker [i/2] = 0; +} + + +static void PkgError (char *msg) +{ + MessageBox (NULL, msg, "TrueCrypt", MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); +} + + +static void PkgWarning (char *msg) +{ + MessageBox (NULL, msg, "TrueCrypt", MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); +} + + +static void PkgInfo (char *msg) +{ + MessageBox (NULL, msg, "TrueCrypt", MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); +} + + +// Returns 0 if decompression fails or, if successful, returns the size of the decompressed data +static int DecompressBuffer (char *out, char *in, int len) +{ + return (DecompressDeflatedData (out, in, len)); // Inflate +} + + +static void __cdecl PipeWriteThread (void *len) +{ + int sendBufSize = PIPE_BUFFER_LEN, bytesSent = 0; + int bytesToSend = *((int *) len), bytesSentTotal = 0; + + if (PipeWriteBuf == NULL || (HANDLE) hChildStdinWrite == INVALID_HANDLE_VALUE) + { + PkgError ("Failed sending data to the STDIN pipe"); + return; + } + + while (bytesToSend > 0) + { + if (bytesToSend < PIPE_BUFFER_LEN) + sendBufSize = bytesToSend; + + if (!WriteFile ((HANDLE) hChildStdinWrite, (char *) PipeWriteBuf + bytesSentTotal, sendBufSize, &bytesSent, NULL) + || bytesSent == 0 + || bytesSent != sendBufSize) + { + PkgError ("Failed sending data to the STDIN pipe"); + return; + } + + bytesToSend -= bytesSent; + bytesSentTotal += bytesSent; + } + + // Closing the pipe causes the child process to stop reading from it + + if (!CloseHandle (hChildStdinWrite)) + { + PkgError ("Cannot close pipe"); + return; + } +} + + +// Returns 0 if compression fails or, if successful, the size of the compressed data +static int CompressBuffer (char *out, char *in, int len) +{ + SECURITY_ATTRIBUTES securityAttrib; + DWORD bytesReceived = 0; + HANDLE hChildStdoutWrite = INVALID_HANDLE_VALUE; + HANDLE hChildStdoutRead = INVALID_HANDLE_VALUE; + HANDLE hChildStdinRead = INVALID_HANDLE_VALUE; + STARTUPINFO startupInfo; + PROCESS_INFORMATION procInfo; + char pipeBuffer [PIPE_BUFFER_LEN]; + int res_len = 0; + BOOL bGzipHeaderRead = FALSE; + + ZeroMemory (&startupInfo, sizeof (startupInfo)); + ZeroMemory (&procInfo, sizeof (procInfo)); + + // Pipe handle inheritance + securityAttrib.bInheritHandle = TRUE; + securityAttrib.nLength = sizeof (securityAttrib); + securityAttrib.lpSecurityDescriptor = NULL; + + if (!CreatePipe (&hChildStdoutRead, &hChildStdoutWrite, &securityAttrib, 0)) + { + PkgError ("Cannot create STDOUT pipe."); + return 0; + } + SetHandleInformation (hChildStdoutRead, HANDLE_FLAG_INHERIT, 0); + + if (!CreatePipe (&hChildStdinRead, &((HANDLE) hChildStdinWrite), &securityAttrib, 0)) + { + PkgError ("Cannot create STDIN pipe."); + return 0; + } + SetHandleInformation (hChildStdinWrite, HANDLE_FLAG_INHERIT, 0); + + // Create a child process that will compress the data + + startupInfo.wShowWindow = SW_HIDE; + startupInfo.hStdInput = hChildStdinRead; + startupInfo.hStdOutput = hChildStdoutWrite; + startupInfo.cb = sizeof (startupInfo); + startupInfo.hStdError = hChildStdoutWrite; + startupInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + + if (!CreateProcess (NULL, "gzip --best", NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &procInfo)) + { + PkgError ("Error: Cannot run gzip.\n\nBefore you can create a self-extracting TrueCrypt package, you need to have the open-source 'gzip' compression tool placed in any directory in the search path for executable files (for example, in 'C:\\Windows\\').\n\nNote: gzip can be freely downloaded e.g. from www.gzip.org"); + return 0; + } + + CloseHandle (procInfo.hProcess); + CloseHandle (procInfo.hThread); + + // Start sending the uncompressed data to the pipe (STDIN) + PipeWriteBuf = in; + _beginthread (PipeWriteThread, PIPE_BUFFER_LEN * 2, (void *) &len); + + if (!CloseHandle (hChildStdoutWrite)) + { + PkgError ("Cannot close STDOUT write"); + return 0; + } + + bGzipHeaderRead = FALSE; + + // Read the compressed data from the pipe (sent by the child process to STDOUT) + while (TRUE) + { + if (!ReadFile (hChildStdoutRead, pipeBuffer, bGzipHeaderRead ? PIPE_BUFFER_LEN : 10, &bytesReceived, NULL)) + break; + + if (bGzipHeaderRead) + { + memcpy (out + res_len, pipeBuffer, bytesReceived); + res_len += bytesReceived; + } + else + bGzipHeaderRead = TRUE; // Skip the 10-byte gzip header + } + return res_len - 8; // A gzip stream ends with a CRC-32 hash and a 32-bit size (those 8 bytes need to be chopped off) +} + + +// Clears all bytes that change when an exe file is digitally signed, except the data that are appended. +// If those bytes weren't cleared, CRC-32 checks would fail after signing. +static void WipeSignatureAreas (char *buffer) +{ + // Clear bytes 0x130-0x1ff + memset (buffer + 0x130, 0, 0x200 - 0x130); +} + + +BOOL MakeSelfExtractingPackage (HWND hwndDlg, char *szDestDir) +{ + int i, x; + unsigned char inputFile [TC_MAX_PATH]; + unsigned char outputFile [TC_MAX_PATH]; + unsigned char szTmpFilePath [TC_MAX_PATH]; + unsigned char szTmp32bit [4] = {0}; + unsigned char *szTmp32bitPtr = szTmp32bit; + unsigned char *buffer = NULL, *compressedBuffer = NULL; + unsigned char *bufIndex = NULL; + char tmpStr [2048]; + int bufLen = 0, compressedDataLen = 0, uncompressedDataLen = 0; + + x = strlen (szDestDir); + if (x < 2) + goto err; + + if (szDestDir[x - 1] != '\\') + strcat (szDestDir, "\\"); + + GetModuleFileName (NULL, inputFile, sizeof (inputFile)); + + strcpy (outputFile, szDestDir); + strncat (outputFile, OutputPackageFile, sizeof (outputFile) - strlen (outputFile) - 1); + + // Clone 'TrueCrypt Setup.exe' to create the base of the new self-extracting archive + + if (!TCCopyFile (inputFile, outputFile)) + { + handleWin32Error (hwndDlg); + PkgError ("Cannot copy 'TrueCrypt Setup.exe' to the package"); + goto err; + } + + // Determine the buffer size needed for all the files and meta data and check if all required files exist + + bufLen = 0; + + for (i = 0; i < sizeof (szCompressedFiles) / sizeof (szCompressedFiles[0]); i++) + { + _snprintf (szTmpFilePath, sizeof(szTmpFilePath), "%s%s", szDestDir, szCompressedFiles[i]); + + if (!FileExists (szTmpFilePath)) + { + char tmpstr [1000]; + + _snprintf (tmpstr, sizeof(tmpstr), "File not found:\n\n'%s'", szTmpFilePath); + remove (outputFile); + PkgError (tmpstr); + goto err; + } + + bufLen += (int) GetFileSize64 (szTmpFilePath); + + bufLen += 2; // 16-bit filename length + bufLen += strlen(szCompressedFiles[i]); // Filename + bufLen += 4; // CRC-32 + bufLen += 4; // 32-bit file length + } + + buffer = malloc (bufLen + 524288); // + 512K reserve + if (buffer == NULL) + { + PkgError ("Cannot allocate memory for uncompressed data"); + remove (outputFile); + goto err; + } + + + // Write the start marker + if (!SaveBufferToFile (MAG_START_MARKER, outputFile, strlen (MAG_START_MARKER), TRUE)) + { + PkgError ("Cannot write the start marker"); + remove (outputFile); + goto err; + } + + + bufIndex = buffer; + + // Copy all required files and their meta data to the buffer + for (i = 0; i < sizeof (szCompressedFiles) / sizeof (szCompressedFiles[0]); i++) + { + DWORD tmpFileSize; + unsigned char *tmpBuffer; + + _snprintf (szTmpFilePath, sizeof(szTmpFilePath), "%s%s", szDestDir, szCompressedFiles[i]); + + tmpBuffer = LoadFile (szTmpFilePath, &tmpFileSize); + + if (tmpBuffer == NULL) + { + char tmpstr [1000]; + + free (tmpBuffer); + _snprintf (tmpstr, sizeof(tmpstr), "Cannot load file \n'%s'", szTmpFilePath); + remove (outputFile); + PkgError (tmpstr); + goto err; + } + + // Copy the filename length to the main buffer + mputWord (bufIndex, (WORD) strlen(szCompressedFiles[i])); + + // Copy the filename to the main buffer + memcpy (bufIndex, szCompressedFiles[i], strlen(szCompressedFiles[i])); + bufIndex += strlen(szCompressedFiles[i]); + + // Compute CRC-32 hash of the uncompressed file and copy it to the main buffer + mputLong (bufIndex, GetCrc32 (tmpBuffer, tmpFileSize)); + + // Copy the file length to the main buffer + mputLong (bufIndex, (unsigned __int32) tmpFileSize); + + // Copy the file contents to the main buffer + memcpy (bufIndex, tmpBuffer, tmpFileSize); + bufIndex += tmpFileSize; + + free (tmpBuffer); + } + + // Calculate the total size of the uncompressed data + uncompressedDataLen = (int) (bufIndex - buffer); + + // Write total size of the uncompressed data + szTmp32bitPtr = szTmp32bit; + mputLong (szTmp32bitPtr, (unsigned __int32) uncompressedDataLen); + if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE)) + { + remove (outputFile); + PkgError ("Cannot write the total size of the uncompressed data"); + goto err; + } + + // Compress all the files and meta data in the buffer to create a solid archive + + compressedBuffer = malloc (uncompressedDataLen + 524288); // + 512K reserve + if (compressedBuffer == NULL) + { + remove (outputFile); + PkgError ("Cannot allocate memory for compressed data"); + goto err; + } + + compressedDataLen = CompressBuffer (compressedBuffer, buffer, uncompressedDataLen); + if (compressedDataLen <= 0) + { + remove (outputFile); + PkgError ("Failed to compress the data"); + goto err; + } + + free (buffer); + buffer = NULL; + + // Write the total size of the compressed data + szTmp32bitPtr = szTmp32bit; + mputLong (szTmp32bitPtr, (unsigned __int32) compressedDataLen); + if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE)) + { + remove (outputFile); + PkgError ("Cannot write the total size of the compressed data"); + goto err; + } + + // Write the compressed data + if (!SaveBufferToFile (compressedBuffer, outputFile, compressedDataLen, TRUE)) + { + remove (outputFile); + PkgError ("Cannot write compressed data to the package"); + goto err; + } + + // Write the end marker + if (!SaveBufferToFile (MagEndMarker, outputFile, strlen (MagEndMarker), TRUE)) + { + remove (outputFile); + PkgError ("Cannot write the end marker"); + goto err; + } + + free (compressedBuffer); + compressedBuffer = NULL; + + // Compute and write CRC-32 hash of the entire package + { + DWORD tmpFileSize; + char *tmpBuffer; + + tmpBuffer = LoadFile (outputFile, &tmpFileSize); + + if (tmpBuffer == NULL) + { + handleWin32Error (hwndDlg); + remove (outputFile); + PkgError ("Cannot load the package to compute CRC"); + goto err; + } + + // Zero all bytes that change when the exe is digitally signed (except appended blocks). + WipeSignatureAreas (tmpBuffer); + + szTmp32bitPtr = szTmp32bit; + mputLong (szTmp32bitPtr, GetCrc32 (tmpBuffer, tmpFileSize)); + free (tmpBuffer); + + if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE)) + { + remove (outputFile); + PkgError ("Cannot write the total size of the compressed data"); + goto err; + } + } + + sprintf (tmpStr, "Self-extracting package successfully created (%s)", outputFile); + PkgInfo (tmpStr); + return TRUE; + +err: + if (buffer) + free (buffer); + if (compressedBuffer) + free (compressedBuffer); + + return FALSE; +} + + +// Verifies the CRC-32 of the whole self-extracting package (except the digital signature areas, if present) +BOOL VerifyPackageIntegrity (void) +{ + int fileDataEndPos = 0; + int fileDataStartPos = 0; + unsigned __int32 crc = 0; + unsigned char *tmpBuffer; + int tmpFileSize; + char path [TC_MAX_PATH]; + + GetModuleFileName (NULL, path, sizeof (path)); + + fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker)); + if (fileDataEndPos < 0) + { + Error ("DIST_PACKAGE_CORRUPTED"); + return FALSE; + } + fileDataEndPos--; + + fileDataStartPos = (int) FindStringInFile (path, MAG_START_MARKER, strlen (MAG_START_MARKER)); + if (fileDataStartPos < 0) + { + Error ("DIST_PACKAGE_CORRUPTED"); + return FALSE; + } + fileDataStartPos += strlen (MAG_START_MARKER); + + + if (!LoadInt32 (path, &crc, fileDataEndPos + strlen (MagEndMarker) + 1)) + { + Error ("CANT_VERIFY_PACKAGE_INTEGRITY"); + return FALSE; + } + + // Compute the CRC-32 hash of the whole file (except the digital signature area, if present) + tmpBuffer = LoadFile (path, &tmpFileSize); + + if (tmpBuffer == NULL) + { + Error ("CANT_VERIFY_PACKAGE_INTEGRITY"); + return FALSE; + } + + // Zero all bytes that change when an exe is digitally signed (except appended blocks). + WipeSignatureAreas (tmpBuffer); + + if (crc != GetCrc32 (tmpBuffer, fileDataEndPos + 1 + strlen (MagEndMarker))) + { + free (tmpBuffer); + Error ("DIST_PACKAGE_CORRUPTED"); + return FALSE; + } + + free (tmpBuffer); + + return TRUE; +} + + +// Determines whether we are a self-extracting package +BOOL IsSelfExtractingPackage (void) +{ + char path [TC_MAX_PATH]; + + GetModuleFileName (NULL, path, sizeof (path)); + + return (FindStringInFile (path, MagEndMarker, strlen (MagEndMarker)) != -1); +} + + +static void FreeAllFileBuffers (void) +{ + int fileNo; + + if (DecompressedData != NULL) + { + free (DecompressedData); + DecompressedData = NULL; + } + + for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++) + { + Decompressed_Files[fileNo].fileName = NULL; + Decompressed_Files[fileNo].fileContent = NULL; + Decompressed_Files[fileNo].fileNameLength = 0; + Decompressed_Files[fileNo].fileLength = 0; + Decompressed_Files[fileNo].crc = 0; + } +} + + +// Assumes that VerifyPackageIntegrity() has been used. Returns TRUE, if successful (otherwise FALSE). +// Creates a table of pointers to buffers containing the following objects for each file: +// filename size, filename (not null-terminated!), file size, file CRC-32, uncompressed file contents. +// For details, see the definition of the DECOMPRESSED_FILE structure. +BOOL SelfExtractInMemory (char *path) +{ + int filePos = 0, fileNo = 0; + int fileDataEndPos = 0; + int fileDataStartPos = 0; + int uncompressedLen = 0; + int compressedLen = 0; + unsigned char *compressedData = NULL; + unsigned char *bufPos = NULL, *bufEndPos = NULL; + + FreeAllFileBuffers(); + + fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker)); + if (fileDataEndPos < 0) + { + Error ("CANNOT_READ_FROM_PACKAGE"); + return FALSE; + } + + fileDataEndPos--; + + fileDataStartPos = (int) FindStringInFile (path, MAG_START_MARKER, strlen (MAG_START_MARKER)); + if (fileDataStartPos < 0) + { + Error ("CANNOT_READ_FROM_PACKAGE"); + return FALSE; + } + + fileDataStartPos += strlen (MAG_START_MARKER); + + filePos = fileDataStartPos; + + // Read the stored total size of the uncompressed data + if (!LoadInt32 (path, &uncompressedLen, filePos)) + { + Error ("CANNOT_READ_FROM_PACKAGE"); + return FALSE; + } + + filePos += 4; + + // Read the stored total size of the compressed data + if (!LoadInt32 (path, &compressedLen, filePos)) + { + Error ("CANNOT_READ_FROM_PACKAGE"); + return FALSE; + } + + filePos += 4; + + if (compressedLen != fileDataEndPos - fileDataStartPos - 8 + 1) + { + Error ("DIST_PACKAGE_CORRUPTED"); + } + + DecompressedData = malloc (uncompressedLen + 524288); // + 512K reserve + if (DecompressedData == NULL) + { + Error ("ERR_MEM_ALLOC"); + return FALSE; + } + + bufPos = DecompressedData; + bufEndPos = bufPos + uncompressedLen - 1; + + compressedData = LoadFileBlock (path, filePos, compressedLen); + + if (compressedData == NULL) + { + free (DecompressedData); + DecompressedData = NULL; + + Error ("CANNOT_READ_FROM_PACKAGE"); + return FALSE; + } + + // Decompress the data + if (DecompressBuffer (DecompressedData, compressedData, compressedLen) != uncompressedLen) + { + Error ("DIST_PACKAGE_CORRUPTED"); + goto sem_end; + } + + while (bufPos <= bufEndPos && fileNo < NBR_COMPRESSED_FILES) + { + // Filename length + Decompressed_Files[fileNo].fileNameLength = mgetWord (bufPos); + + // Filename + Decompressed_Files[fileNo].fileName = bufPos; + bufPos += Decompressed_Files[fileNo].fileNameLength; + + // CRC-32 of the file + Decompressed_Files[fileNo].crc = mgetLong (bufPos); + + // File length + Decompressed_Files[fileNo].fileLength = mgetLong (bufPos); + + // File content + Decompressed_Files[fileNo].fileContent = bufPos; + bufPos += Decompressed_Files[fileNo].fileLength; + + // Verify CRC-32 of the file (to verify that it didn't get corrupted while creating the solid archive). + if (Decompressed_Files[fileNo].crc + != GetCrc32 (Decompressed_Files[fileNo].fileContent, Decompressed_Files[fileNo].fileLength)) + { + Error ("DIST_PACKAGE_CORRUPTED"); + goto sem_end; + } + + fileNo++; + } + + if (fileNo < NBR_COMPRESSED_FILES) + { + Error ("DIST_PACKAGE_CORRUPTED"); + goto sem_end; + } + + free (compressedData); + return TRUE; + +sem_end: + FreeAllFileBuffers(); + free (compressedData); + return FALSE; +} + + +void __cdecl ExtractAllFilesThread (void *hwndDlg) +{ + int fileNo; + BOOL bSuccess = FALSE; + char packageFile [TC_MAX_PATH]; + + InvalidateRect (GetDlgItem (GetParent (hwndDlg), IDD_INSTL_DLG), NULL, TRUE); + + ClearLogWindow (hwndDlg); + + GetModuleFileName (NULL, packageFile, sizeof (packageFile)); + + if (!(bSuccess = SelfExtractInMemory (packageFile))) + goto eaf_end; + + if (mkfulldir (DestExtractPath, TRUE) != 0) + { + if (mkfulldir (DestExtractPath, FALSE) != 0) + { + wchar_t szTmp[TC_MAX_PATH]; + + handleWin32Error (hwndDlg); + wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), DestExtractPath); + MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND); + bSuccess = FALSE; + goto eaf_end; + } + } + + for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++) + { + char fileName [TC_MAX_PATH] = {0}; + char filePath [TC_MAX_PATH] = {0}; + + // Filename + strncpy (fileName, Decompressed_Files[fileNo].fileName, Decompressed_Files[fileNo].fileNameLength); + fileName [Decompressed_Files[fileNo].fileNameLength] = 0; + strcpy (filePath, DestExtractPath); + strcat (filePath, fileName); + + StatusMessageParam (hwndDlg, "EXTRACTING_VERB", filePath); + + // Write the file + if (!SaveBufferToFile ( + Decompressed_Files[fileNo].fileContent, + filePath, + Decompressed_Files[fileNo].fileLength, + FALSE)) + { + wchar_t szTmp[512]; + + _snwprintf (szTmp, sizeof (szTmp) / 2, GetString ("CANNOT_WRITE_FILE_X"), filePath); + MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); + bSuccess = FALSE; + goto eaf_end; + } + UpdateProgressBarProc ((int) (100 * ((float) fileNo / NBR_COMPRESSED_FILES))); + } + +eaf_end: + FreeAllFileBuffers(); + + if (bSuccess) + PostMessage (MainDlg, TC_APPMSG_EXTRACTION_SUCCESS, 0, 0); + else + PostMessage (MainDlg, TC_APPMSG_EXTRACTION_FAILURE, 0, 0); +} + diff --git a/src/Setup/SelfExtract.h b/src/Setup/SelfExtract.h new file mode 100644 index 00000000..f1e62990 --- /dev/null +++ b/src/Setup/SelfExtract.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved. + + Governed by the TrueCrypt License 3.0 the full text of which is contained in + the file License.txt included in TrueCrypt binary and source code distribution + packages. +*/ + +#include "Setup.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + // WARNING: file name is NOT null-terminated (use fileNameLength). + unsigned char *fileName; + int fileNameLength; + uint32 crc; + __int32 fileLength; + unsigned char *fileContent; +} DECOMPRESSED_FILE; + +extern DECOMPRESSED_FILE Decompressed_Files [NBR_COMPRESSED_FILES]; + +void SelfExtractStartupInit (void); +BOOL SelfExtractInMemory (char *path); +void __cdecl ExtractAllFilesThread (void *hwndDlg); +BOOL MakeSelfExtractingPackage (HWND hwndDlg, char *szDestDir); +BOOL VerifyPackageIntegrity (void); +BOOL IsSelfExtractingPackage (void); +static void DeobfuscateMagEndMarker (void); + +extern char DestExtractPath [TC_MAX_PATH]; + +#ifdef __cplusplus +} +#endif diff --git a/src/Setup/Setup.c b/src/Setup/Setup.c new file mode 100644 index 00000000..f607ab00 --- /dev/null +++ b/src/Setup/Setup.c @@ -0,0 +1,2160 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions + of this file are Copyright (c) 2003-2012 TrueCrypt Developers Association + and are governed by the TrueCrypt License 3.0 the full text of which is + contained in the file License.txt included in TrueCrypt binary and source + code distribution packages. */ + +#include "Tcdefs.h" +#include +#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 "SelfExtract.h" +#include "Wizard.h" + +#include "../Common/Resource.h" + +using namespace TrueCrypt; + +#pragma warning( disable : 4201 ) +#pragma warning( disable : 4115 ) + +#include + +#pragma warning( default : 4201 ) +#pragma warning( default : 4115 ) + +char InstallationPath[TC_MAX_PATH]; +char SetupFilesDir[TC_MAX_PATH]; +char UninstallBatch[MAX_PATH]; + +LONG InstalledVersion = 0; +BOOL bUninstall = FALSE; +BOOL bRestartRequired = FALSE; +BOOL bMakePackage = FALSE; +BOOL bDone = FALSE; +BOOL Rollback = FALSE; +BOOL bUpgrade = FALSE; +BOOL bDowngrade = FALSE; +BOOL SystemEncryptionUpdate = FALSE; +BOOL PortableMode = FALSE; +BOOL bRepairMode = FALSE; +BOOL bChangeMode = FALSE; +BOOL bDevm = FALSE; +BOOL bPossiblyFirstTimeInstall = FALSE; +BOOL bUninstallInProgress = FALSE; +BOOL UnloadDriver = TRUE; + +BOOL bSystemRestore = TRUE; +BOOL bDisableSwapFiles = FALSE; +BOOL bForAllUsers = TRUE; +BOOL bRegisterFileExt = TRUE; +BOOL bAddToStartMenu = TRUE; +BOOL bDesktopIcon = TRUE; + +BOOL bDesktopIconStatusDetermined = FALSE; + +HMODULE volatile SystemRestoreDll = 0; + +void localcleanup (void) +{ + localcleanupwiz (); + cleanup (); + + CloseAppSetupMutex (); +} + +BOOL StatDeleteFile (char *lpszFile) +{ + struct __stat64 st; + + if (_stat64 (lpszFile, &st) == 0) + return DeleteFile (lpszFile); + else + return TRUE; +} + +BOOL StatRemoveDirectory (char *lpszDir) +{ + struct __stat64 st; + + if (_stat64 (lpszDir, &st) == 0) + return RemoveDirectory (lpszDir); + else + return TRUE; +} + +HRESULT CreateLink (char *lpszPathObj, char *lpszArguments, + char *lpszPathLink) +{ + HRESULT hres; + IShellLink *psl; + + /* Get a pointer to the IShellLink interface. */ + hres = CoCreateInstance (CLSID_ShellLink, NULL, + CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *) &psl); + if (SUCCEEDED (hres)) + { + IPersistFile *ppf; + + /* Set the path to the shortcut target, and add the + description. */ + psl->SetPath (lpszPathObj); + psl->SetArguments (lpszArguments); + + // Application ID + if (strstr (lpszPathObj, TC_APP_NAME ".exe")) + { + IPropertyStore *propStore; + + if (SUCCEEDED (psl->QueryInterface (IID_PPV_ARGS (&propStore)))) + { + PROPVARIANT propVariant; + if (SUCCEEDED (InitPropVariantFromString (TC_APPLICATION_ID, &propVariant))) + { + if (SUCCEEDED (propStore->SetValue (PKEY_AppUserModel_ID, propVariant))) + propStore->Commit(); + + PropVariantClear (&propVariant); + } + + propStore->Release(); + } + } + + /* Query IShellLink for the IPersistFile interface for saving + the shortcut in persistent storage. */ + hres = psl->QueryInterface (IID_IPersistFile, + (void **) &ppf); + + if (SUCCEEDED (hres)) + { + wchar_t wsz[TC_MAX_PATH]; + + /* Ensure that the string is ANSI. */ + MultiByteToWideChar (CP_ACP, 0, lpszPathLink, -1, + wsz, sizeof(wsz) / sizeof(wsz[0])); + + /* Save the link by calling IPersistFile::Save. */ + hres = ppf->Save (wsz, TRUE); + ppf->Release (); + } + psl->Release (); + } + return hres; +} + +void GetProgramPath (HWND hwndDlg, char *path) +{ + ITEMIDLIST *i; + HRESULT res; + + if (bForAllUsers) + res = SHGetSpecialFolderLocation (hwndDlg, CSIDL_COMMON_PROGRAMS, &i); + else + res = SHGetSpecialFolderLocation (hwndDlg, CSIDL_PROGRAMS, &i); + + SHGetPathFromIDList (i, path); +} + +void StatusMessage (HWND hwndDlg, char *stringId) +{ + if (Rollback) + return; + + SendMessageW (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_ADDSTRING, 0, (LPARAM) GetString (stringId)); + + SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_SETTOPINDEX, + SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_GETCOUNT, 0, 0) - 1, 0); +} + +void StatusMessageParam (HWND hwndDlg, char *stringId, char *param) +{ + wchar_t szTmp[1024]; + + if (Rollback) + return; + + wsprintfW (szTmp, L"%s %hs", GetString (stringId), param); + SendMessageW (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_ADDSTRING, 0, (LPARAM) szTmp); + + SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_SETTOPINDEX, + SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_GETCOUNT, 0, 0) - 1, 0); +} + +void ClearLogWindow (HWND hwndDlg) +{ + SendMessage (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_RESETCONTENT, 0, 0); +} + +void RegMessage (HWND hwndDlg, char *txt) +{ + StatusMessageParam (hwndDlg, "ADDING_REG", txt); +} + +void CopyMessage (HWND hwndDlg, char *txt) +{ + StatusMessageParam (hwndDlg, "INSTALLING", txt); +} + +void RemoveMessage (HWND hwndDlg, char *txt) +{ + if (!Rollback) + StatusMessageParam (hwndDlg, "REMOVING", txt); +} + +void IconMessage (HWND hwndDlg, char *txt) +{ + StatusMessageParam (hwndDlg, "ADDING_ICON", txt); +} + +void DetermineUpgradeDowngradeStatus (BOOL bCloseDriverHandle, LONG *driverVersionPtr) +{ + LONG driverVersion = VERSION_NUM; + + if (hDriver == INVALID_HANDLE_VALUE) + DriverAttach(); + + if (hDriver != INVALID_HANDLE_VALUE) + { + DWORD dwResult; + BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &driverVersion, sizeof (driverVersion), &dwResult, NULL); + + if (!bResult) + bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &driverVersion, sizeof (driverVersion), &dwResult, NULL); + + if (bResult) + InstalledVersion = driverVersion; + + bUpgrade = (bResult && driverVersion < VERSION_NUM); + bDowngrade = (bResult && driverVersion > VERSION_NUM); + + PortableMode = DeviceIoControl (hDriver, TC_IOCTL_GET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dwResult, NULL); + + if (bCloseDriverHandle) + { + CloseHandle (hDriver); + hDriver = INVALID_HANDLE_VALUE; + } + } + + *driverVersionPtr = driverVersion; +} + + +static BOOL IsFileInUse (const string &filePath) +{ + HANDLE useTestHandle = CreateFile (filePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + + if (useTestHandle != INVALID_HANDLE_VALUE) + CloseHandle (useTestHandle); + else if (GetLastError() == ERROR_SHARING_VIOLATION) + return TRUE; + + return FALSE; +} + + +BOOL DoFilesInstall (HWND hwndDlg, char *szDestDir) +{ + /* WARNING: Note that, despite its name, this function is used during UNinstallation as well. */ + + char szTmp[TC_MAX_PATH]; + BOOL bOK = TRUE; + int i, x, fileNo; + char curFileName [TC_MAX_PATH] = {0}; + + if (!bUninstall && !bDevm) + { + // Self-extract all files to memory + + GetModuleFileName (NULL, szTmp, sizeof (szTmp)); + + if (!SelfExtractInMemory (szTmp)) + return FALSE; + } + + x = strlen (szDestDir); + if (x < 2) + return FALSE; + + if (szDestDir[x - 1] != '\\') + strcat (szDestDir, "\\"); + + for (i = 0; i < sizeof (szFiles) / sizeof (szFiles[0]); i++) + { + BOOL bResult; + char szDir[TC_MAX_PATH]; + + if (strstr (szFiles[i], "TrueCrypt Setup") != 0) + { + if (bUninstall) + continue; // Prevent 'access denied' error + + if (bRepairMode) + continue; // Destination = target + } + + if (*szFiles[i] == 'A') + strcpy (szDir, szDestDir); + else if (*szFiles[i] == 'D') + { + GetSystemDirectory (szDir, sizeof (szDir)); + + x = strlen (szDir); + if (szDir[x - 1] != '\\') + strcat (szDir, "\\"); + + strcat (szDir, "Drivers\\"); + } + else if (*szFiles[i] == 'W') + GetWindowsDirectory (szDir, sizeof (szDir)); + + if (*szFiles[i] == 'I') + continue; + + sprintf (szTmp, "%s%s", szDir, szFiles[i] + 1); + + if (bUninstall == FALSE) + CopyMessage (hwndDlg, szTmp); + else + RemoveMessage (hwndDlg, szTmp); + + if (bUninstall == FALSE) + { + SetCurrentDirectory (SetupFilesDir); + + if (strstr (szFiles[i], "TrueCrypt Setup") != 0) + { + // Copy ourselves (the distribution package) to the destination location as 'TrueCrypt Setup.exe' + + char mp[MAX_PATH]; + + GetModuleFileName (NULL, mp, sizeof (mp)); + bResult = TCCopyFile (mp, szTmp); + } + else + { + BOOL driver64 = FALSE; + + strncpy (curFileName, szFiles[i] + 1, strlen (szFiles[i]) - 1); + curFileName [strlen (szFiles[i]) - 1] = 0; + + if (Is64BitOs () + && strcmp (szFiles[i], "Dtruecrypt.sys") == 0) + { + driver64 = TRUE; + strncpy (curFileName, FILENAME_64BIT_DRIVER, sizeof (FILENAME_64BIT_DRIVER)); + } + + if (!bDevm) + { + bResult = FALSE; + + // Find the correct decompressed file in memory + for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++) + { + // Write the file (stored in memory) directly to the destination location + // (there will be no temporary files). + if (memcmp ( + curFileName, + Decompressed_Files[fileNo].fileName, + min (strlen (curFileName), (size_t) Decompressed_Files[fileNo].fileNameLength)) == 0) + { + // Dump filter driver cannot be installed to SysWOW64 directory + if (driver64 && !EnableWow64FsRedirection (FALSE)) + { + handleWin32Error (hwndDlg); + bResult = FALSE; + goto err; + } + + bResult = SaveBufferToFile ( + (char *) Decompressed_Files[fileNo].fileContent, + szTmp, + Decompressed_Files[fileNo].fileLength, + FALSE); + + if (driver64) + { + if (!EnableWow64FsRedirection (TRUE)) + { + handleWin32Error (hwndDlg); + bResult = FALSE; + goto err; + } + + if (!bResult) + goto err; + + if (bUpgrade && InstalledVersion < 0x700) + { + bResult = WriteLocalMachineRegistryString ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "ImagePath", "System32\\drivers\\truecrypt.sys", TRUE); + if (!bResult) + { + handleWin32Error (hwndDlg); + goto err; + } + + DeleteFile (szTmp); + } + } + + break; + } + } + } + else + { + if (driver64) + EnableWow64FsRedirection (FALSE); + + bResult = TCCopyFile (curFileName, szTmp); + + if (driver64) + EnableWow64FsRedirection (TRUE); + } + + if (bResult && strcmp (szFiles[i], "ATrueCrypt.exe") == 0) + { + string servicePath = GetServiceConfigPath (TC_APP_NAME ".exe"); + if (FileExists (servicePath.c_str())) + { + CopyMessage (hwndDlg, (char *) servicePath.c_str()); + bResult = CopyFile (szTmp, servicePath.c_str(), FALSE); + } + } + } + } + else + { + bResult = StatDeleteFile (szTmp); + } + +err: + if (bResult == FALSE) + { + LPVOID lpMsgBuf; + DWORD dwError = GetLastError (); + wchar_t szTmp2[700]; + + FormatMessage ( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwError, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + (char *) &lpMsgBuf, + 0, + NULL + ); + + + if (bUninstall == FALSE) + wsprintfW (szTmp2, GetString ("INSTALL_OF_FAILED"), szTmp, lpMsgBuf); + else + wsprintfW (szTmp2, GetString ("UNINSTALL_OF_FAILED"), szTmp, lpMsgBuf); + + LocalFree (lpMsgBuf); + + if (!Silent && MessageBoxW (hwndDlg, szTmp2, lpszTitle, MB_YESNO | MB_ICONHAND) != IDYES) + return FALSE; + } + } + + // Language pack + if (bUninstall == FALSE) + { + WIN32_FIND_DATA f; + HANDLE h; + + SetCurrentDirectory (SetupFilesDir); + h = FindFirstFile ("Language.*.xml", &f); + + if (h != INVALID_HANDLE_VALUE) + { + char d[MAX_PATH*2]; + sprintf (d, "%s%s", szDestDir, f.cFileName); + CopyMessage (hwndDlg, d); + TCCopyFile (f.cFileName, d); + FindClose (h); + } + + SetCurrentDirectory (SetupFilesDir); + SetCurrentDirectory ("Setup files"); + h = FindFirstFile ("TrueCrypt User Guide.*.pdf", &f); + if (h != INVALID_HANDLE_VALUE) + { + char d[MAX_PATH*2]; + sprintf (d, "%s%s", szDestDir, f.cFileName); + CopyMessage (hwndDlg, d); + TCCopyFile (f.cFileName, d); + FindClose (h); + } + SetCurrentDirectory (SetupFilesDir); + } + + return bOK; +} + +BOOL DoRegInstall (HWND hwndDlg, char *szDestDir, BOOL bInstallType) +{ + char szDir[TC_MAX_PATH], *key; + char szTmp[TC_MAX_PATH*4]; + HKEY hkey = 0; + BOOL bSlash, bOK = FALSE; + DWORD dw; + int x; + + if (SystemEncryptionUpdate) + { + if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt", + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) == ERROR_SUCCESS) + { + strcpy (szTmp, VERSION_STRING); + RegSetValueEx (hkey, "DisplayVersion", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1); + + strcpy (szTmp, TC_HOMEPAGE); + RegSetValueEx (hkey, "URLInfoAbout", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1); + + RegCloseKey (hkey); + } + + return TRUE; + } + + strcpy (szDir, szDestDir); + x = strlen (szDestDir); + if (szDestDir[x - 1] == '\\') + bSlash = TRUE; + else + bSlash = FALSE; + + if (bSlash == FALSE) + strcat (szDir, "\\"); + + if (bInstallType) + { + + key = "Software\\Classes\\TrueCryptVolume"; + RegMessage (hwndDlg, key); + if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, + key, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS) + goto error; + + strcpy (szTmp, "TrueCrypt Volume"); + if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + sprintf (szTmp, "%ws", TC_APPLICATION_ID); + if (RegSetValueEx (hkey, "AppUserModelID", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + RegCloseKey (hkey); + hkey = 0; + + key = "Software\\Classes\\TrueCryptVolume\\DefaultIcon"; + RegMessage (hwndDlg, key); + if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, + key, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS) + goto error; + + sprintf (szTmp, "%sTrueCrypt.exe,1", szDir); + if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + RegCloseKey (hkey); + hkey = 0; + + key = "Software\\Classes\\TrueCryptVolume\\Shell\\open\\command"; + RegMessage (hwndDlg, key); + if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, + key, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS) + goto error; + + sprintf (szTmp, "\"%sTrueCrypt.exe\" /v \"%%1\"", szDir ); + if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + RegCloseKey (hkey); + hkey = 0; + + key = "Software\\Classes\\.tc"; + BOOL typeClassChanged = TRUE; + char typeClass[256]; + DWORD typeClassSize = sizeof (typeClass); + + if (ReadLocalMachineRegistryString (key, "", typeClass, &typeClassSize) && typeClassSize > 0 && strcmp (typeClass, "TrueCryptVolume") == 0) + typeClassChanged = FALSE; + + RegMessage (hwndDlg, key); + if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, + key, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS) + goto error; + + strcpy (szTmp, "TrueCryptVolume"); + if (RegSetValueEx (hkey, "", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + RegCloseKey (hkey); + hkey = 0; + + if (typeClassChanged) + SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); + } + + key = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt"; + RegMessage (hwndDlg, key); + if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, + key, + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS) + goto error; + + /* IMPORTANT: IF YOU CHANGE THIS IN ANY WAY, REVISE AND UPDATE SetInstallationPath() ACCORDINGLY! */ + sprintf (szTmp, "\"%sTrueCrypt Setup.exe\" /u", szDir); + if (RegSetValueEx (hkey, "UninstallString", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + sprintf (szTmp, "\"%sTrueCrypt Setup.exe\" /c", szDir); + if (RegSetValueEx (hkey, "ModifyPath", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + sprintf (szTmp, "\"%sTrueCrypt Setup.exe\"", szDir); + if (RegSetValueEx (hkey, "DisplayIcon", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + strcpy (szTmp, VERSION_STRING); + if (RegSetValueEx (hkey, "DisplayVersion", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + strcpy (szTmp, "TrueCrypt"); + if (RegSetValueEx (hkey, "DisplayName", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + strcpy (szTmp, "TrueCrypt Foundation"); + if (RegSetValueEx (hkey, "Publisher", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + strcpy (szTmp, TC_HOMEPAGE); + if (RegSetValueEx (hkey, "URLInfoAbout", 0, REG_SZ, (BYTE *) szTmp, strlen (szTmp) + 1) != ERROR_SUCCESS) + goto error; + + bOK = TRUE; + +error: + if (hkey != 0) + RegCloseKey (hkey); + + if (bOK == FALSE) + { + handleWin32Error (hwndDlg); + Error ("REG_INSTALL_FAILED"); + } + + // Register COM servers for UAC + if (IsOSAtLeast (WIN_VISTA)) + { + if (!RegisterComServers (szDir)) + { + Error ("COM_REG_FAILED"); + return FALSE; + } + } + + return bOK; +} + +BOOL DoApplicationDataUninstall (HWND hwndDlg) +{ + char path[MAX_PATH]; + char path2[MAX_PATH]; + BOOL bOK = TRUE; + + StatusMessage (hwndDlg, "REMOVING_APPDATA"); + + SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path); + strcat (path, "\\TrueCrypt\\"); + + // Delete favorite volumes file + sprintf (path2, "%s%s", path, TC_APPD_FILENAME_FAVORITE_VOLUMES); + RemoveMessage (hwndDlg, path2); + StatDeleteFile (path2); + + // Delete keyfile defaults + sprintf (path2, "%s%s", path, TC_APPD_FILENAME_DEFAULT_KEYFILES); + RemoveMessage (hwndDlg, path2); + StatDeleteFile (path2); + + // Delete history file + sprintf (path2, "%s%s", path, TC_APPD_FILENAME_HISTORY); + RemoveMessage (hwndDlg, path2); + StatDeleteFile (path2); + + // Delete configuration file + sprintf (path2, "%s%s", path, TC_APPD_FILENAME_CONFIGURATION); + RemoveMessage (hwndDlg, path2); + StatDeleteFile (path2); + + // Delete system encryption configuration file + sprintf (path2, "%s%s", path, TC_APPD_FILENAME_SYSTEM_ENCRYPTION); + RemoveMessage (hwndDlg, path2); + StatDeleteFile (path2); + + SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path); + strcat (path, "\\TrueCrypt"); + RemoveMessage (hwndDlg, path); + if (!StatRemoveDirectory (path)) + { + handleWin32Error (hwndDlg); + bOK = FALSE; + } + + return bOK; +} + +BOOL DoRegUninstall (HWND hwndDlg, BOOL bRemoveDeprecated) +{ + BOOL bOK = FALSE; + char regk [64]; + + // Unregister COM servers + if (!bRemoveDeprecated && IsOSAtLeast (WIN_VISTA)) + { + if (!UnregisterComServers (InstallationPath)) + StatusMessage (hwndDlg, "COM_DEREG_FAILED"); + } + + if (!bRemoveDeprecated) + StatusMessage (hwndDlg, "REMOVING_REG"); + + RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TrueCrypt"); + RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\Shell\\open\\command"); + RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\Shell\\open"); + RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\Shell"); + RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume\\DefaultIcon"); + RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\TrueCryptVolume"); + RegDeleteKey (HKEY_CURRENT_USER, "Software\\TrueCrypt"); + + if (!bRemoveDeprecated) + { + GetStartupRegKeyName (regk); + DeleteRegistryValue (regk, "TrueCrypt"); + + RegDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\.tc"); + SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); + } + + bOK = TRUE; + + if (bOK == FALSE && GetLastError ()!= ERROR_NO_TOKEN && GetLastError ()!= ERROR_FILE_NOT_FOUND + && GetLastError ()!= ERROR_PATH_NOT_FOUND) + { + handleWin32Error (hwndDlg); + } + else + bOK = TRUE; + + return bOK; +} + + +BOOL DoServiceUninstall (HWND hwndDlg, char *lpszService) +{ + SC_HANDLE hManager, hService = NULL; + BOOL bOK = FALSE, bRet; + SERVICE_STATUS status; + BOOL firstTry = TRUE; + int x; + + memset (&status, 0, sizeof (status)); /* Keep VC6 quiet */ + +retry: + + hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hManager == NULL) + goto error; + + hService = OpenService (hManager, lpszService, SERVICE_ALL_ACCESS); + if (hService == NULL) + goto error; + + if (strcmp ("truecrypt", lpszService) == 0) + { + try + { + BootEncryption bootEnc (hwndDlg); + if (bootEnc.GetDriverServiceStartType() == SERVICE_BOOT_START) + { + try { bootEnc.RegisterFilterDriver (false, BootEncryption::DriveFilter); } catch (...) { } + try { bootEnc.RegisterFilterDriver (false, BootEncryption::VolumeFilter); } catch (...) { } + try { bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter); } catch (...) { } + } + } + catch (...) { } + + StatusMessage (hwndDlg, "STOPPING_DRIVER"); + } + else + StatusMessageParam (hwndDlg, "STOPPING", lpszService); + +#define WAIT_PERIOD 3 + + for (x = 0; x < WAIT_PERIOD; x++) + { + bRet = QueryServiceStatus (hService, &status); + if (bRet != TRUE) + goto error; + + if (status.dwCurrentState != SERVICE_START_PENDING && + status.dwCurrentState != SERVICE_STOP_PENDING && + status.dwCurrentState != SERVICE_CONTINUE_PENDING) + break; + + Sleep (1000); + } + + if (status.dwCurrentState != SERVICE_STOPPED) + { + bRet = ControlService (hService, SERVICE_CONTROL_STOP, &status); + if (bRet == FALSE) + goto try_delete; + + for (x = 0; x < WAIT_PERIOD; x++) + { + bRet = QueryServiceStatus (hService, &status); + if (bRet != TRUE) + goto error; + + if (status.dwCurrentState != SERVICE_START_PENDING && + status.dwCurrentState != SERVICE_STOP_PENDING && + status.dwCurrentState != SERVICE_CONTINUE_PENDING) + break; + + Sleep (1000); + } + + if (status.dwCurrentState != SERVICE_STOPPED && status.dwCurrentState != SERVICE_STOP_PENDING) + goto error; + } + +try_delete: + + if (strcmp ("truecrypt", lpszService) == 0) + StatusMessage (hwndDlg, "REMOVING_DRIVER"); + else + StatusMessageParam (hwndDlg, "REMOVING", lpszService); + + if (hService != NULL) + CloseServiceHandle (hService); + + if (hManager != NULL) + CloseServiceHandle (hManager); + + hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hManager == NULL) + goto error; + + hService = OpenService (hManager, lpszService, SERVICE_ALL_ACCESS); + if (hService == NULL) + goto error; + + bRet = DeleteService (hService); + if (bRet == FALSE) + { + if (firstTry && GetLastError () == ERROR_SERVICE_MARKED_FOR_DELETE) + { + // Second try for an eventual no-install driver instance + CloseServiceHandle (hService); + CloseServiceHandle (hManager); + + Sleep(1000); + firstTry = FALSE; + goto retry; + } + + goto error; + } + + bOK = TRUE; + +error: + + if (bOK == FALSE && GetLastError ()!= ERROR_SERVICE_DOES_NOT_EXIST) + { + handleWin32Error (hwndDlg); + MessageBoxW (hwndDlg, GetString ("DRIVER_UINSTALL_FAILED"), lpszTitle, MB_ICONHAND); + } + else + bOK = TRUE; + + if (hService != NULL) + CloseServiceHandle (hService); + + if (hManager != NULL) + CloseServiceHandle (hManager); + + return bOK; +} + + +BOOL DoDriverUnload (HWND hwndDlg) +{ + BOOL bOK = TRUE; + int status; + + status = DriverAttach (); + if (status != 0) + { + if (status == ERR_OS_ERROR && GetLastError () != ERROR_FILE_NOT_FOUND) + { + handleWin32Error (hwndDlg); + AbortProcess ("NODRIVER"); + } + + if (status != ERR_OS_ERROR) + { + handleError (NULL, status); + AbortProcess ("NODRIVER"); + } + } + + if (hDriver != INVALID_HANDLE_VALUE) + { + MOUNT_LIST_STRUCT driver; + LONG driverVersion = VERSION_NUM; + int refCount; + DWORD dwResult; + BOOL bResult; + + // Try to determine if it's upgrade (and not reinstall, downgrade, or first-time install). + DetermineUpgradeDowngradeStatus (FALSE, &driverVersion); + + // Test for encrypted boot drive + try + { + BootEncryption bootEnc (hwndDlg); + if (bootEnc.GetDriverServiceStartType() == SERVICE_BOOT_START) + { + try + { + // Check hidden OS update consistency + if (IsHiddenOSRunning()) + { + if (bootEnc.GetInstalledBootLoaderVersion() != VERSION_NUM) + { + if (AskWarnNoYes ("UPDATE_TC_IN_DECOY_OS_FIRST") == IDNO) + AbortProcessSilent (); + } + } + } + catch (...) { } + + if (bUninstallInProgress && driverVersion >= 0x500 && !bootEnc.GetStatus().DriveMounted) + { + try { bootEnc.RegisterFilterDriver (false, BootEncryption::DriveFilter); } catch (...) { } + try { bootEnc.RegisterFilterDriver (false, BootEncryption::VolumeFilter); } catch (...) { } + try { bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter); } catch (...) { } + bootEnc.SetDriverServiceStartType (SERVICE_SYSTEM_START); + } + else if (bUninstallInProgress || bDowngrade) + { + Error (bDowngrade ? "SETUP_FAILED_BOOT_DRIVE_ENCRYPTED_DOWNGRADE" : "SETUP_FAILED_BOOT_DRIVE_ENCRYPTED"); + return FALSE; + } + else + { + if (CurrentOSMajor == 6 && CurrentOSMinor == 0 && CurrentOSServicePack < 1) + AbortProcess ("SYS_ENCRYPTION_UPGRADE_UNSUPPORTED_ON_VISTA_SP0"); + + SystemEncryptionUpdate = TRUE; + PortableMode = FALSE; + } + } + } + catch (...) { } + + if (!bUninstall + && (bUpgrade || SystemEncryptionUpdate) + && (!bDevm || SystemEncryptionUpdate)) + { + UnloadDriver = FALSE; + } + + if (PortableMode && !SystemEncryptionUpdate) + UnloadDriver = TRUE; + + if (UnloadDriver) + { + int volumesMounted = 0; + + // Check mounted volumes + bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL); + + if (!bResult) + { + bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL); + if (bResult) + volumesMounted = driver.ulMountedDrives; + } + + if (bResult) + { + if (volumesMounted != 0) + { + bOK = FALSE; + MessageBoxW (hwndDlg, GetString ("DISMOUNT_ALL_FIRST"), lpszTitle, MB_ICONHAND); + } + } + else + { + bOK = FALSE; + handleWin32Error (hwndDlg); + } + } + + // Try to close all open TC windows + if (bOK) + { + BOOL TCWindowClosed = FALSE; + + EnumWindows (CloseTCWindowsEnum, (LPARAM) &TCWindowClosed); + + if (TCWindowClosed) + Sleep (2000); + } + + // Test for any applications attached to driver + if (!bUpgrade) + { + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount, + sizeof (refCount), &dwResult, NULL); + + if (bOK && bResult && refCount > 1) + { + MessageBoxW (hwndDlg, GetString ("CLOSE_TC_FIRST"), lpszTitle, MB_ICONSTOP); + bOK = FALSE; + } + } + + if (!bOK || UnloadDriver) + { + CloseHandle (hDriver); + hDriver = INVALID_HANDLE_VALUE; + } + } + else + { + // Note that the driver may have already been unloaded during this session (e.g. retry after an error, etc.) so it is not + // guaranteed that the user is installing TrueCrypt for the first time now (we also cannot know if the user has already + // installed and used TrueCrypt on another system before). + bPossiblyFirstTimeInstall = TRUE; + } + + return bOK; +} + + +BOOL UpgradeBootLoader (HWND hwndDlg) +{ + if (!SystemEncryptionUpdate) + return TRUE; + + try + { + BootEncryption bootEnc (hwndDlg); + if (bootEnc.GetInstalledBootLoaderVersion() < VERSION_NUM) + { + StatusMessage (hwndDlg, "INSTALLER_UPDATING_BOOT_LOADER"); + + bootEnc.InstallBootLoader (true); + + if (bootEnc.GetInstalledBootLoaderVersion() <= TC_RESCUE_DISK_UPGRADE_NOTICE_MAX_VERSION) + Info (IsHiddenOSRunning() ? "BOOT_LOADER_UPGRADE_OK_HIDDEN_OS" : "BOOT_LOADER_UPGRADE_OK"); + } + return TRUE; + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + catch (...) { } + + Error ("BOOT_LOADER_UPGRADE_FAILED"); + return FALSE; +} + + +BOOL DoShortcutsUninstall (HWND hwndDlg, char *szDestDir) +{ + char szLinkDir[TC_MAX_PATH]; + char szTmp2[TC_MAX_PATH]; + BOOL bSlash, bOK = FALSE; + HRESULT hOle; + int x; + BOOL allUsers = FALSE; + + hOle = OleInitialize (NULL); + + // User start menu + SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_PROGRAMS, 0); + x = strlen (szLinkDir); + if (szLinkDir[x - 1] == '\\') + bSlash = TRUE; + else + bSlash = FALSE; + + if (bSlash == FALSE) + strcat (szLinkDir, "\\"); + + strcat (szLinkDir, "TrueCrypt"); + + // Global start menu + { + struct _stat st; + char path[TC_MAX_PATH]; + + SHGetSpecialFolderPath (hwndDlg, path, CSIDL_COMMON_PROGRAMS, 0); + strcat (path, "\\TrueCrypt"); + + if (_stat (path, &st) == 0) + { + strcpy (szLinkDir, path); + allUsers = TRUE; + } + } + + // Start menu entries + sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk"); + RemoveMessage (hwndDlg, szTmp2); + if (StatDeleteFile (szTmp2) == FALSE) + goto error; + + sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt Website.url"); + RemoveMessage (hwndDlg, szTmp2); + if (StatDeleteFile (szTmp2) == FALSE) + goto error; + + sprintf (szTmp2, "%s%s", szLinkDir, "\\Uninstall TrueCrypt.lnk"); + RemoveMessage (hwndDlg, szTmp2); + if (StatDeleteFile (szTmp2) == FALSE) + goto error; + + sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt User's Guide.lnk"); + DeleteFile (szTmp2); + + // Start menu group + RemoveMessage ((HWND) hwndDlg, szLinkDir); + if (StatRemoveDirectory (szLinkDir) == FALSE) + handleWin32Error ((HWND) hwndDlg); + + // Desktop icon + + if (allUsers) + SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_COMMON_DESKTOPDIRECTORY, 0); + else + SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_DESKTOPDIRECTORY, 0); + + sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk"); + + RemoveMessage (hwndDlg, szTmp2); + if (StatDeleteFile (szTmp2) == FALSE) + goto error; + + bOK = TRUE; + +error: + OleUninitialize (); + + return bOK; +} + +BOOL DoShortcutsInstall (HWND hwndDlg, char *szDestDir, BOOL bProgGroup, BOOL bDesktopIcon) +{ + char szLinkDir[TC_MAX_PATH], szDir[TC_MAX_PATH]; + char szTmp[TC_MAX_PATH], szTmp2[TC_MAX_PATH], szTmp3[TC_MAX_PATH]; + BOOL bSlash, bOK = FALSE; + HRESULT hOle; + int x; + + if (bProgGroup == FALSE && bDesktopIcon == FALSE) + return TRUE; + + hOle = OleInitialize (NULL); + + GetProgramPath (hwndDlg, szLinkDir); + + x = strlen (szLinkDir); + if (szLinkDir[x - 1] == '\\') + bSlash = TRUE; + else + bSlash = FALSE; + + if (bSlash == FALSE) + strcat (szLinkDir, "\\"); + + strcat (szLinkDir, "TrueCrypt"); + + strcpy (szDir, szDestDir); + x = strlen (szDestDir); + if (szDestDir[x - 1] == '\\') + bSlash = TRUE; + else + bSlash = FALSE; + + if (bSlash == FALSE) + strcat (szDir, "\\"); + + if (bProgGroup) + { + FILE *f; + + if (mkfulldir (szLinkDir, TRUE) != 0) + { + if (mkfulldir (szLinkDir, FALSE) != 0) + { + wchar_t szTmp[TC_MAX_PATH]; + + handleWin32Error (hwndDlg); + wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), szLinkDir); + MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND); + goto error; + } + } + + sprintf (szTmp, "%s%s", szDir, "TrueCrypt.exe"); + sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk"); + + IconMessage (hwndDlg, szTmp2); + if (CreateLink (szTmp, "", szTmp2) != S_OK) + goto error; + + sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt Website.url"); + IconMessage (hwndDlg, szTmp2); + f = fopen (szTmp2, "w"); + if (f) + { + fprintf (f, "[InternetShortcut]\nURL=%s\n", TC_HOMEPAGE); + + CheckFileStreamWriteErrors (f, szTmp2); + fclose (f); + } + else + goto error; + + sprintf (szTmp, "%s%s", szDir, "TrueCrypt Setup.exe"); + sprintf (szTmp2, "%s%s", szLinkDir, "\\Uninstall TrueCrypt.lnk"); + strcpy (szTmp3, "/u"); + + IconMessage (hwndDlg, szTmp2); + if (CreateLink (szTmp, szTmp3, szTmp2) != S_OK) + goto error; + + sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt User's Guide.lnk"); + DeleteFile (szTmp2); + } + + if (bDesktopIcon) + { + strcpy (szDir, szDestDir); + x = strlen (szDestDir); + if (szDestDir[x - 1] == '\\') + bSlash = TRUE; + else + bSlash = FALSE; + + if (bSlash == FALSE) + strcat (szDir, "\\"); + + if (bForAllUsers) + SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_COMMON_DESKTOPDIRECTORY, 0); + else + SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_DESKTOPDIRECTORY, 0); + + sprintf (szTmp, "%s%s", szDir, "TrueCrypt.exe"); + sprintf (szTmp2, "%s%s", szLinkDir, "\\TrueCrypt.lnk"); + + IconMessage (hwndDlg, szTmp2); + + if (CreateLink (szTmp, "", szTmp2) != S_OK) + goto error; + } + + bOK = TRUE; + +error: + OleUninitialize (); + + return bOK; +} + + +void OutcomePrompt (HWND hwndDlg, BOOL bOK) +{ + if (bOK) + { + EnableWindow (GetDlgItem ((HWND) hwndDlg, IDCANCEL), FALSE); + + bDone = TRUE; + + if (bUninstall == FALSE) + { + if (bDevm) + PostMessage (MainDlg, WM_CLOSE, 0, 0); + else if (bPossiblyFirstTimeInstall || bRepairMode || (!bUpgrade && !bDowngrade)) + Info ("INSTALL_OK"); + else + Info ("SETUP_UPDATE_OK"); + } + else + { + wchar_t str[4096]; + + swprintf (str, GetString ("UNINSTALL_OK"), InstallationPath); + MessageBoxW (hwndDlg, str, lpszTitle, MB_ICONASTERISK); + } + } + else + { + if (bUninstall == FALSE) + Error ("INSTALL_FAILED"); + else + Error ("UNINSTALL_FAILED"); + } +} + +static void SetSystemRestorePoint (HWND hwndDlg, BOOL finalize) +{ + static RESTOREPOINTINFO RestPtInfo; + static STATEMGRSTATUS SMgrStatus; + static BOOL failed = FALSE; + static BOOL (__stdcall *_SRSetRestorePoint)(PRESTOREPOINTINFO, PSTATEMGRSTATUS); + + if (!SystemRestoreDll) return; + + _SRSetRestorePoint = (BOOL (__stdcall *)(PRESTOREPOINTINFO, PSTATEMGRSTATUS))GetProcAddress (SystemRestoreDll,"SRSetRestorePointA"); + if (_SRSetRestorePoint == 0) + { + FreeLibrary (SystemRestoreDll); + SystemRestoreDll = 0; + return; + } + + if (!finalize) + { + StatusMessage (hwndDlg, "CREATING_SYS_RESTORE"); + + RestPtInfo.dwEventType = BEGIN_SYSTEM_CHANGE; + RestPtInfo.dwRestorePtType = bUninstall ? APPLICATION_UNINSTALL : APPLICATION_INSTALL | DEVICE_DRIVER_INSTALL; + RestPtInfo.llSequenceNumber = 0; + strcpy (RestPtInfo.szDescription, bUninstall ? "TrueCrypt uninstallation" : "TrueCrypt installation"); + + if(!_SRSetRestorePoint (&RestPtInfo, &SMgrStatus)) + { + StatusMessage (hwndDlg, "FAILED_SYS_RESTORE"); + failed = TRUE; + } + } + else if (!failed) + { + RestPtInfo.dwEventType = END_SYSTEM_CHANGE; + RestPtInfo.llSequenceNumber = SMgrStatus.llSequenceNumber; + + if(!_SRSetRestorePoint(&RestPtInfo, &SMgrStatus)) + { + StatusMessage (hwndDlg, "FAILED_SYS_RESTORE"); + } + } +} + +void DoUninstall (void *arg) +{ + HWND hwndDlg = (HWND) arg; + BOOL bOK = TRUE; + BOOL bTempSkipSysRestore = FALSE; + + if (!Rollback) + EnableWindow (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), FALSE); + + WaitCursor (); + + if (!Rollback) + { + ClearLogWindow (hwndDlg); + } + + if (DoDriverUnload (hwndDlg) == FALSE) + { + bOK = FALSE; + bTempSkipSysRestore = TRUE; // Volumes are possibly mounted; defer System Restore point creation for this uninstall attempt. + } + else + { + if (!Rollback && bSystemRestore && !bTempSkipSysRestore) + SetSystemRestorePoint (hwndDlg, FALSE); + + if (DoServiceUninstall (hwndDlg, "truecrypt") == FALSE) + { + bOK = FALSE; + } + else if (DoRegUninstall ((HWND) hwndDlg, FALSE) == FALSE) + { + bOK = FALSE; + } + else if (DoFilesInstall ((HWND) hwndDlg, InstallationPath) == FALSE) + { + bOK = FALSE; + } + else if (DoShortcutsUninstall (hwndDlg, InstallationPath) == FALSE) + { + bOK = FALSE; + } + else if (!DoApplicationDataUninstall (hwndDlg)) + { + bOK = FALSE; + } + else + { + char temp[MAX_PATH]; + FILE *f; + + // Deprecated service + DoServiceUninstall (hwndDlg, "TrueCryptService"); + + GetTempPath (sizeof (temp), temp); + _snprintf (UninstallBatch, sizeof (UninstallBatch), "%s\\TrueCrypt-Uninstall.bat", temp); + + UninstallBatch [sizeof(UninstallBatch)-1] = 0; + + // Create uninstall batch + f = fopen (UninstallBatch, "w"); + if (!f) + bOK = FALSE; + else + { + fprintf (f, ":loop\n" + "del \"%s%s\"\n" + "if exist \"%s%s\" goto loop\n" + "rmdir \"%s\"\n" + "del \"%s\"", + InstallationPath, "TrueCrypt Setup.exe", + InstallationPath, "TrueCrypt Setup.exe", + InstallationPath, + UninstallBatch + ); + + CheckFileStreamWriteErrors (f, UninstallBatch); + fclose (f); + } + } + } + + NormalCursor (); + + if (Rollback) + return; + + if (bSystemRestore && !bTempSkipSysRestore) + SetSystemRestorePoint (hwndDlg, TRUE); + + if (bOK) + PostMessage (hwndDlg, TC_APPMSG_UNINSTALL_SUCCESS, 0, 0); + else + bUninstallInProgress = FALSE; + + EnableWindow (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), TRUE); + OutcomePrompt (hwndDlg, bOK); +} + +void DoInstall (void *arg) +{ + HWND hwndDlg = (HWND) arg; + BOOL bOK = TRUE; + char path[MAX_PATH]; + + BootEncryption bootEnc (hwndDlg); + + // Refresh the main GUI (wizard thread) + InvalidateRect (MainDlg, NULL, TRUE); + + ClearLogWindow (hwndDlg); + + if (mkfulldir (InstallationPath, TRUE) != 0) + { + if (mkfulldir (InstallationPath, FALSE) != 0) + { + wchar_t szTmp[TC_MAX_PATH]; + + handleWin32Error (hwndDlg); + wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), InstallationPath); + MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND); + Error ("INSTALL_FAILED"); + PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0); + return; + } + } + + UpdateProgressBarProc(2); + + if (DoDriverUnload (hwndDlg) == FALSE) + { + NormalCursor (); + PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0); + return; + } + + if (bUpgrade + && (IsFileInUse (string (InstallationPath) + '\\' + TC_APP_NAME ".exe") + || IsFileInUse (string (InstallationPath) + '\\' + TC_APP_NAME " Format.exe") + || IsFileInUse (string (InstallationPath) + '\\' + TC_APP_NAME " Setup.exe") + ) + ) + { + NormalCursor (); + Error ("CLOSE_TC_FIRST"); + PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0); + return; + } + + UpdateProgressBarProc(12); + + if (bSystemRestore) + SetSystemRestorePoint (hwndDlg, FALSE); + + UpdateProgressBarProc(48); + + if (bDisableSwapFiles + && IsPagingFileActive (FALSE)) + { + if (!DisablePagingFile()) + { + handleWin32Error (hwndDlg); + Error ("FAILED_TO_DISABLE_PAGING_FILES"); + } + else + bRestartRequired = TRUE; + } + + UpdateProgressBarProc(50); + + // Remove deprecated + DoServiceUninstall (hwndDlg, "TrueCryptService"); + + UpdateProgressBarProc(55); + + if (!SystemEncryptionUpdate) + DoRegUninstall ((HWND) hwndDlg, TRUE); + + if (SystemEncryptionUpdate && InstalledVersion < 0x700) + { + try + { + bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter); + } + catch (...) { } + + try + { + bootEnc.RegisterFilterDriver (true, BootEncryption::DumpFilter); + } + catch (Exception &e) + { + try + { + bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter); + } + catch (...) { } + + e.Show (hwndDlg); + + bOK = FALSE; + goto outcome; + } + + if (ReadDriverConfigurationFlags() & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES) + { + WriteLocalMachineRegistryString ("SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Minimal\\" TC_SYSTEM_FAVORITES_SERVICE_NAME, NULL, "Service", FALSE); + WriteLocalMachineRegistryString ("SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Network\\" TC_SYSTEM_FAVORITES_SERVICE_NAME, NULL, "Service", FALSE); + } + } + + UpdateProgressBarProc(61); + + if (bUpgrade && InstalledVersion < 0x700) + { + bool bMountFavoritesOnLogon = ConfigReadInt ("MountFavoritesOnLogon", FALSE) != 0; + bool bOpenExplorerWindowAfterMount = ConfigReadInt ("OpenExplorerWindowAfterMount", FALSE) != 0; + + if (bMountFavoritesOnLogon || bOpenExplorerWindowAfterMount) + { + char *favoritesFilename = GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES); + DWORD size; + char *favoritesXml = LoadFile (favoritesFilename, &size); + + if (favoritesXml && size != 0) + { + string favorites; + favorites.insert (0, favoritesXml, size); + + size_t p = favorites.find ("