From 302dc37fb9baa45c5864af533664c4139e209590 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 9 Feb 2022 22:37:22 +0100 Subject: Windows: Make Travel Disk contains 32-bit and arm64 binaries when VeraCrypt installed using MSI --- src/COMReg/COMReg.cpp | 30 + src/COMReg/COMReg.rc | 100 ++ src/COMReg/COMReg.vcxproj | 119 ++ src/COMReg/COMReg.vcxproj.filters | 49 + src/COMReg/COMReg.vcxproj.user | 7 + src/COMReg/Resource.h | 18 + src/Common/Dlgcode.c | 2336 +++++++++++++++++++------------------ src/Mount/Mount.c | 180 +-- src/Setup/SelfExtract.c | 41 +- src/Setup/SelfExtract.h | 5 +- src/Setup/Setup.c | 4 +- src/Signing/sign.bat | 8 +- 12 files changed, 1638 insertions(+), 1259 deletions(-) create mode 100644 src/COMReg/COMReg.cpp create mode 100644 src/COMReg/COMReg.rc create mode 100644 src/COMReg/COMReg.vcxproj create mode 100644 src/COMReg/COMReg.vcxproj.filters create mode 100644 src/COMReg/COMReg.vcxproj.user create mode 100644 src/COMReg/Resource.h diff --git a/src/COMReg/COMReg.cpp b/src/COMReg/COMReg.cpp new file mode 100644 index 00000000..d1f97492 --- /dev/null +++ b/src/COMReg/COMReg.cpp @@ -0,0 +1,30 @@ +#include "Tcdefs.h" +#include +#include "SelfExtract.h" + +int APIENTRY _tWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) +{ + wchar_t SetupFilesDir[TC_MAX_PATH]; + wchar_t *s; + UNREFERENCED_PARAMETER(hInstance); + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(nCmdShow); + + if (lpCmdLine[0] == L'/' && lpCmdLine[1] == L'p') + { + MessageBox(NULL, L"",L"",0); + SelfExtractStartupInit(); + GetModuleFileName (NULL, SetupFilesDir, ARRAYSIZE (SetupFilesDir)); + s = wcsrchr (SetupFilesDir, L'\\'); + if (s) + s[1] = 0; + + /* Create self-extracting package */ + MakeSelfExtractingPackage (NULL, SetupFilesDir, TRUE); + } + + return 0; +} diff --git a/src/COMReg/COMReg.rc b/src/COMReg/COMReg.rc new file mode 100644 index 00000000..0fd3f44d --- /dev/null +++ b/src/COMReg/COMReg.rc @@ -0,0 +1,100 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,25,8,1 + PRODUCTVERSION 1,25,8,1 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "IDRIX" + VALUE "FileDescription", "VeraCrypt COMReg" + VALUE "FileVersion", "1.25" + VALUE "LegalTrademarks", "VeraCrypt" + VALUE "OriginalFilename", "VeraCrypt COMReg.exe" + VALUE "ProductName", "VeraCrypt" + VALUE "ProductVersion", "1.25" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// REGISTRY +// + +IDR_COMREG REGISTRY "..\Setup\ComSetup.rgs" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_COMREG ICON "..\Setup\Setup.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""..\\\\common\\\\resource.h""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// diff --git a/src/COMReg/COMReg.vcxproj b/src/COMReg/COMReg.vcxproj new file mode 100644 index 00000000..91a440e1 --- /dev/null +++ b/src/COMReg/COMReg.vcxproj @@ -0,0 +1,119 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {C8914211-32AC-4F48-ACD9-8212E8DE53F3} + Win32Proj + COMReg + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + VeraCryptCOMRegBase + Debug\ + Debug\ + + + false + VeraCryptCOMRegBase + Release\ + Release\ + + + + NotUsing + Level3 + Disabled + WIN32;VC_COMREG;_DEBUG;_WINDOWS;HAVE_CONFIG_H;ZIP_STATIC;%(PreprocessorDefinitions) + MultiThreadedDebug + ..\Setup;..\Common;..\Crypto;..\;..\PKCS11;..\Common\zlib;..\Common\libzip;..\Common\lzma;%(AdditionalIncludeDirectories) + + + Windows + true + ..\Common\Debug\Zip.lib;..\Crypto\Debug\crypto.lib;..\Common\Debug\lzma.lib;%(AdditionalDependencies) + + + copy Debug\VeraCryptCOMRegBase.exe "..\Debug\Setup Files\VeraCryptCOMRegBase.exe" + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;VC_COMREG;NDEBUG;_WINDOWS;HAVE_CONFIG_H;ZIP_STATIC;%(PreprocessorDefinitions) + MultiThreaded + ..\Setup;..\Common;..\Crypto;..\;..\PKCS11;..\Common\zlib;..\Common\libzip;..\Common\lzma;%(AdditionalIncludeDirectories) + + + Windows + false + true + true + ..\Common\Release\Zip.lib;..\Crypto\Release\crypto.lib;..\Common\Release\lzma.lib;%(AdditionalDependencies) + + + copy Release\VeraCryptCOMRegBase.exe "..\Release\Setup Files\VeraCryptCOMRegBase.exe" + + + + + + CompileAsCpp + CompileAsCpp + + + Default + + + + + + + + + + + + + + {b896fe1f-6bf3-4f75-9148-f841829073d9} + + + + + + \ No newline at end of file diff --git a/src/COMReg/COMReg.vcxproj.filters b/src/COMReg/COMReg.vcxproj.filters new file mode 100644 index 00000000..cc5c60a3 --- /dev/null +++ b/src/COMReg/COMReg.vcxproj.filters @@ -0,0 +1,49 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {453a6bf1-2afd-4016-8b8f-e3821a6c8ab5} + + + {efcd999c-3973-4bd6-af14-0583669e6722} + + + + + Source Files + + + Source Files + + + Source Files\Common + + + Source Files\Common + + + + + Resource Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/src/COMReg/COMReg.vcxproj.user b/src/COMReg/COMReg.vcxproj.user new file mode 100644 index 00000000..deea718b --- /dev/null +++ b/src/COMReg/COMReg.vcxproj.user @@ -0,0 +1,7 @@ + + + + $(TargetPath) + WindowsLocalDebugger + + \ No newline at end of file diff --git a/src/COMReg/Resource.h b/src/COMReg/Resource.h new file mode 100644 index 00000000..14901ce6 --- /dev/null +++ b/src/COMReg/Resource.h @@ -0,0 +1,18 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by COMReg.rc +// +#define IDR_COMREG 10 +#define IDI_COMREG 11 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 12 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index f757fb47..f76cc295 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -514,6 +514,955 @@ typedef struct } MULTI_CHOICE_DLGPROC_PARAMS; + + + +// Loads a 32-bit integer from the file at the specified file offset. The saved value is assumed to have been +// processed by mputLong(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). +BOOL LoadInt32 (const wchar_t *filePath, unsigned __int32 *result, __int64 fileOffset) +{ + DWORD bufSize = sizeof(__int32); + unsigned char *buffer = (unsigned char *) malloc (bufSize); + unsigned char *bufferPtr = buffer; + HANDLE src = NULL; + DWORD bytesRead; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL retVal = FALSE; + + if (buffer == NULL) + return -1; + + src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + { + free (buffer); + return FALSE; + } + + seekOffset.QuadPart = fileOffset; + + if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + goto fsif_end; + + if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 + || bytesRead != bufSize) + goto fsif_end; + + + retVal = TRUE; + + *result = mgetLong(bufferPtr); + +fsif_end: + CloseHandle (src); + free (buffer); + + return retVal; +} + +// Loads a 16-bit integer from the file at the specified file offset. The saved value is assumed to have been +// processed by mputWord(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). +BOOL LoadInt16 (const wchar_t *filePath, int *result, __int64 fileOffset) +{ + DWORD bufSize = sizeof(__int16); + unsigned char *buffer = (unsigned char *) malloc (bufSize); + unsigned char *bufferPtr = buffer; + HANDLE src = NULL; + DWORD bytesRead; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL retVal = FALSE; + + if (buffer == NULL) + return -1; + + src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + { + free (buffer); + return FALSE; + } + + seekOffset.QuadPart = fileOffset; + + if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + goto fsif_end; + + if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 + || bytesRead != bufSize) + goto fsif_end; + + + retVal = TRUE; + + *result = mgetWord(bufferPtr); + +fsif_end: + CloseHandle (src); + free (buffer); + + return retVal; +} + +// Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated. +char *LoadFile (const wchar_t *fileName, DWORD *size) +{ + char *buf; + DWORD fileSize = INVALID_FILE_SIZE; + HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (h == INVALID_HANDLE_VALUE) + return NULL; + + if ((fileSize = GetFileSize (h, NULL)) == INVALID_FILE_SIZE) + { + CloseHandle (h); + return NULL; + } + + *size = fileSize; + buf = (char *) calloc (*size + 1, 1); + + if (buf == NULL) + { + CloseHandle (h); + return NULL; + } + + if (!ReadFile (h, buf, *size, size, NULL)) + { + free (buf); + buf = NULL; + } + + CloseHandle (h); + return buf; +} + + +// Returns NULL if there's any error. +char *LoadFileBlock (const wchar_t *fileName, __int64 fileOffset, DWORD count) +{ + char *buf; + DWORD bytesRead = 0; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL bStatus; + + HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (h == INVALID_HANDLE_VALUE) + return NULL; + + seekOffset.QuadPart = fileOffset; + + if (SetFilePointerEx (h, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + { + CloseHandle (h); + return NULL; + } + + buf = (char *) calloc (count, 1); + + if (buf == NULL) + { + CloseHandle (h); + return NULL; + } + + bStatus = ReadFile (h, buf, count, &bytesRead, NULL); + + CloseHandle (h); + + if (!bStatus || (bytesRead != count)) + { + free (buf); + return NULL; + } + + return buf; +} + + +// Returns -1 if there is an error, or the size of the file. +__int64 GetFileSize64 (const wchar_t *path) +{ + HANDLE h = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + LARGE_INTEGER size; + __int64 retSize = -1; + + if (h) + { + if (GetFileSizeEx (h, &size)) + { + retSize = size.QuadPart; + } + + CloseHandle (h); + } + + return retSize; +} + +// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file +// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE). +BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed) +{ + HANDLE dst; + DWORD bytesWritten; + BOOL res = TRUE; + DWORD dwLastError = 0; + + dst = CreateFile (destinationFile, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); + + dwLastError = GetLastError(); + if (!bAppend && bRenameIfFailed && (dst == INVALID_HANDLE_VALUE) && (GetLastError () == ERROR_SHARING_VIOLATION)) + { + wchar_t renamedPath[TC_MAX_PATH + 1]; + StringCbCopyW (renamedPath, sizeof(renamedPath), destinationFile); + StringCbCatW (renamedPath, sizeof(renamedPath), VC_FILENAME_RENAMED_SUFFIX); + + /* rename the locked file in order to be able to create a new one */ + if (MoveFileEx (destinationFile, renamedPath, MOVEFILE_REPLACE_EXISTING)) + { + dst = CreateFile (destinationFile, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); + dwLastError = GetLastError(); + if (dst == INVALID_HANDLE_VALUE) + { + /* restore the original file name */ + MoveFileEx (renamedPath, destinationFile, MOVEFILE_REPLACE_EXISTING); + } + else + { + /* delete the renamed file when the machine reboots */ + MoveFileEx (renamedPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); + } + } + } + + if (dst == INVALID_HANDLE_VALUE) + { + SetLastError (dwLastError); + handleWin32Error (MainDlg, SRC_POS); + return FALSE; + } + + if (bAppend) + SetFilePointer (dst, 0, NULL, FILE_END); + + if (!WriteFile (dst, inputBuffer, inputLength, &bytesWritten, NULL) + || inputLength != bytesWritten) + { + res = FALSE; + } + + if (!res) + { + // If CREATE_ALWAYS is used, ERROR_ALREADY_EXISTS is returned after successful overwrite + // of an existing file (it's not an error) + if (! (GetLastError() == ERROR_ALREADY_EXISTS && !bAppend) ) + handleWin32Error (MainDlg, SRC_POS); + } + + CloseHandle (dst); + + if (!res && !bAppend) + _wremove (destinationFile); + + return res; +} + + +// Returns -1 if the specified string is not found in the buffer. Otherwise, returns the +// offset of the first occurrence of the string. The string and the buffer may contain zeroes, +// which do NOT terminate them. +int64 FindString (const char *buf, const char *str, int64 bufLen, int64 strLen, int64 startOffset) +{ + if (buf == NULL + || str == NULL + || strLen > bufLen + || bufLen < 1 + || strLen < 1 + || startOffset > bufLen - strLen) + { + return -1; + } + + for (int64 i = startOffset; i <= bufLen - strLen; i++) + { + if (memcmp (buf + i, str, (size_t) strLen) == 0) + return i; + } + + return -1; +} + +// Returns TRUE if the file or directory exists (both may be enclosed in quotation marks). +BOOL FileExists (const wchar_t *filePathPtr) +{ + wchar_t filePath [TC_MAX_PATH * 2 + 1]; + + // Strip quotation marks (if any) + if (filePathPtr [0] == L'"') + { + StringCbCopyW (filePath, sizeof(filePath), filePathPtr + 1); + } + else + { + StringCbCopyW (filePath, sizeof(filePath), filePathPtr); + } + + // Strip quotation marks (if any) + if (filePath [wcslen (filePath) - 1] == L'"') + filePath [wcslen (filePath) - 1] = 0; + + return (_waccess (filePath, 0) != -1); +} + + +// Searches the file from its end for the LAST occurrence of the string str. +// The string may contain zeroes, which do NOT terminate the string. +// If the string is found, its offset from the start of the file is returned. +// If the string isn't found or if any error occurs, -1 is returned. +__int64 FindStringInFile (const wchar_t *filePath, const char* str, int strLen) +{ + int bufSize = 64 * BYTES_PER_KB; + char *buffer = (char *) err_malloc (bufSize); + HANDLE src = NULL; + DWORD bytesRead; + BOOL readRetVal; + __int64 filePos = GetFileSize64 (filePath); + int bufPos = 0; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL bExit = FALSE; + int filePosStep; + __int64 retVal = -1; + + if (filePos <= 0 + || buffer == NULL + || strLen > bufSize + || strLen < 1) + { + if (buffer) + free (buffer); + return -1; + } + + src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + { + free (buffer); + return -1; + } + + filePosStep = bufSize - strLen + 1; + + do + { + filePos -= filePosStep; + + if (filePos < 0) + { + filePos = 0; + bExit = TRUE; + } + + seekOffset.QuadPart = filePos; + + if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + goto fsif_end; + + if ((readRetVal = ReadFile (src, buffer, bufSize, &bytesRead, NULL)) == 0 + || bytesRead == 0) + goto fsif_end; + + bufPos = bytesRead - strLen; + + while (bufPos > 0) + { + if (memcmp (buffer + bufPos, str, strLen) == 0) + { + // String found + retVal = filePos + bufPos; + goto fsif_end; + } + bufPos--; + } + + } while (!bExit); + +fsif_end: + CloseHandle (src); + free (buffer); + + return retVal; +} + +// System CopyFile() copies source file attributes (like FILE_ATTRIBUTE_ENCRYPTED) +// so we need to use our own copy function +BOOL TCCopyFileBase (HANDLE src, HANDLE dst) +{ + __int8 *buffer; + FILETIME fileTime; + DWORD bytesRead, bytesWritten; + BOOL res; + + buffer = (char *) malloc (64 * 1024); + if (!buffer) + { + CloseHandle (src); + CloseHandle (dst); + return FALSE; + } + + while (res = ReadFile (src, buffer, 64 * 1024, &bytesRead, NULL)) + { + if (bytesRead == 0) + { + res = 1; + break; + } + + if (!WriteFile (dst, buffer, bytesRead, &bytesWritten, NULL) + || bytesRead != bytesWritten) + { + res = 0; + break; + } + } + + if (GetFileTime (src, NULL, NULL, &fileTime)) + SetFileTime (dst, NULL, NULL, &fileTime); + + CloseHandle (src); + CloseHandle (dst); + + free (buffer); + return res != 0; +} + +BOOL TCCopyFile (wchar_t *sourceFileName, wchar_t *destinationFile) +{ + HANDLE src, dst; + + src = CreateFileW (sourceFileName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + return FALSE; + + dst = CreateFileW (destinationFile, + GENERIC_WRITE, + 0, NULL, CREATE_ALWAYS, 0, NULL); + + if (dst == INVALID_HANDLE_VALUE) + { + CloseHandle (src); + return FALSE; + } + + return TCCopyFileBase (src, dst); +} + +#if defined(NDEBUG) && !defined(VC_SKIP_OS_DRIVER_REQ_CHECK) +static BOOL InitializeWintrust() +{ + if (!hWinTrustLib) + { + wchar_t szPath[MAX_PATH] = {0}; + + if (GetSystemDirectory(szPath, MAX_PATH)) + StringCchCatW (szPath, MAX_PATH, L"\\Wintrust.dll"); + else + StringCchCopyW (szPath, MAX_PATH, L"C:\\Windows\\System32\\Wintrust.dll"); + + hWinTrustLib = LoadLibrary (szPath); + if (hWinTrustLib) + { + WinVerifyTrustFn = (WINVERIFYTRUST) GetProcAddress (hWinTrustLib, "WinVerifyTrust"); + WTHelperProvDataFromStateDataFn = (WTHELPERPROVDATAFROMSTATEDATA) GetProcAddress (hWinTrustLib, "WTHelperProvDataFromStateData"); + WTHelperGetProvSignerFromChainFn = (WTHELPERGETPROVSIGNERFROMCHAIN) GetProcAddress (hWinTrustLib, "WTHelperGetProvSignerFromChain"); + WTHelperGetProvCertFromChainFn = (WTHELPERGETPROVCERTFROMCHAIN) GetProcAddress (hWinTrustLib, "WTHelperGetProvCertFromChain"); + + if ( !WinVerifyTrustFn + || !WTHelperProvDataFromStateDataFn + || !WTHelperGetProvSignerFromChainFn + || !WTHelperGetProvCertFromChainFn) + { + FreeLibrary (hWinTrustLib); + hWinTrustLib = NULL; + } + + } + } + + if (hWinTrustLib) + return TRUE; + else + return FALSE; +} + +static void FinalizeWintrust() +{ + if (hWinTrustLib) + { + FreeLibrary (hWinTrustLib); + hWinTrustLib = NULL; + } +} + +#endif + +BOOL VerifyModuleSignature (const wchar_t* path) +{ +#if defined(NDEBUG) && !defined (VC_SKIP_OS_DRIVER_REQ_CHECK) + BOOL bResult = FALSE; + HRESULT hResult; + GUID gActionID = WINTRUST_ACTION_GENERIC_VERIFY_V2; + WINTRUST_FILE_INFO fileInfo = {0}; + WINTRUST_DATA WVTData = {0}; + wchar_t filePath [TC_MAX_PATH + 1024]; + + // we check our own authenticode signature only starting from Windows 10 since this is + // the minimal supported OS apart from XP where we can't verify SHA256 signatures + if (!IsOSAtLeast (WIN_10)) + return TRUE; + + // Strip quotation marks (if any) + if (path [0] == L'"') + { + StringCbCopyW (filePath, sizeof(filePath), path + 1); + } + else + { + StringCbCopyW (filePath, sizeof(filePath), path); + } + + // Strip quotation marks (if any) + if (filePath [wcslen (filePath) - 1] == L'"') + filePath [wcslen (filePath) - 1] = 0; + + if (!InitializeWintrust ()) + return FALSE; + + fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO); + fileInfo.pcwszFilePath = filePath; + fileInfo.hFile = NULL; + + WVTData.cbStruct = sizeof(WINTRUST_DATA); + WVTData.dwUIChoice = WTD_UI_NONE; + WVTData.fdwRevocationChecks = WTD_REVOKE_NONE; + WVTData.dwUnionChoice = WTD_CHOICE_FILE; + WVTData.pFile = &fileInfo; + WVTData.dwStateAction = WTD_STATEACTION_VERIFY; + WVTData.dwProvFlags = WTD_REVOCATION_CHECK_NONE | WTD_CACHE_ONLY_URL_RETRIEVAL; + + hResult = WinVerifyTrustFn(0, &gActionID, &WVTData); + if (0 == hResult) + { + PCRYPT_PROVIDER_DATA pProviderData = WTHelperProvDataFromStateDataFn (WVTData.hWVTStateData); + if (pProviderData) + { + PCRYPT_PROVIDER_SGNR pProviderSigner = WTHelperGetProvSignerFromChainFn (pProviderData, 0, FALSE, 0); + if (pProviderSigner) + { + PCRYPT_PROVIDER_CERT pProviderCert = WTHelperGetProvCertFromChainFn (pProviderSigner, 0); + if (pProviderCert && (pProviderCert->pCert)) + { + BYTE hashVal[64]; + sha512 (hashVal, pProviderCert->pCert->pbCertEncoded, pProviderCert->pCert->cbCertEncoded); + + if ( (0 == memcmp (hashVal, gpbSha256CodeSignCertFingerprint, 64)) + || (0 == memcmp (hashVal, gpbSha256MSCodeSignCertFingerprint, 64)) + ) + { + bResult = TRUE; + } + } + } + } + } + + WVTData.dwUIChoice = WTD_UI_NONE; + WVTData.dwStateAction = WTD_STATEACTION_CLOSE; + WinVerifyTrustFn(0, &gActionID, &WVTData); + + FinalizeWintrust (); + + return bResult; +#else + return TRUE; +#endif +} + +DWORD handleWin32Error (HWND hwndDlg, const char* srcPos) +{ +#ifndef VC_COMREG + PWSTR lpMsgBuf; + DWORD dwError = GetLastError (); + wchar_t szErrorValue[32]; + wchar_t* pszDesc; + + if (Silent || dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE) + return dwError; + + // Access denied + if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ()) + { + ErrorDirect ( AppendSrcPos (GetString ("ERR_ACCESS_DENIED"), srcPos).c_str (), hwndDlg); + 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; + } + + MessageBoxW (hwndDlg, AppendSrcPos (pszDesc, srcPos).c_str (), lpszTitle, ICON_HAND); + if (lpMsgBuf) LocalFree (lpMsgBuf); + + // User-friendly hardware error explanation + if (IsDiskError (dwError)) + Error ("ERR_HARDWARE_ERROR", hwndDlg); + + // Device not ready + if (dwError == ERROR_NOT_READY) + HandleDriveNotReadyError(hwndDlg); + + SetLastError (dwError); // Preserve the original error code + + return dwError; +#else + return GetLastError(); +#endif +} + +int Error (char *stringId, HWND hwnd) +{ +#ifndef VC_COMREG + if (Silent) return 0; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR); +#else + return 0; +#endif +} + +BOOL IsOSAtLeast (OSVersionEnum reqMinOS) +{ + return IsOSVersionAtLeast (reqMinOS, 0); +} + + +// Returns TRUE if the operating system is at least reqMinOS and service pack at least reqMinServicePack. +// Example 1: IsOSVersionAtLeast (WIN_VISTA, 1) called under Windows 2008, returns TRUE. +// Example 2: IsOSVersionAtLeast (WIN_XP, 3) called under Windows XP SP1, returns FALSE. +// Example 3: IsOSVersionAtLeast (WIN_XP, 3) called under Windows Vista SP1, returns TRUE. +BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack) +{ + /* When updating this function, update IsOSAtLeast() in Ntdriver.c too. */ + + if (CurrentOSMajor <= 0) + TC_THROW_FATAL_EXCEPTION; + + int major = 0, minor = 0; + + switch (reqMinOS) + { + case WIN_2000: major = 5; minor = 0; break; + case WIN_XP: major = 5; minor = 1; break; + case WIN_SERVER_2003: major = 5; minor = 2; break; + case WIN_VISTA: major = 6; minor = 0; break; + case WIN_7: major = 6; minor = 1; break; + case WIN_8: major = 6; minor = 2; break; + case WIN_8_1: major = 6; minor = 3; break; + case WIN_10: major = 10; minor = 0; break; + + default: + TC_THROW_FATAL_EXCEPTION; + break; + } + + return ((CurrentOSMajor << 16 | CurrentOSMinor << 8 | CurrentOSServicePack) + >= (major << 16 | minor << 8 | reqMinServicePack)); +} + +#ifdef SETUP_DLL +static BOOL GetWindowVersionFromFile(DWORD* pdwMajor, DWORD* pdwMinor, DWORD* pdwBuildNumber) +{ + wchar_t dllPath[MAX_PATH]; + BOOL bRet = FALSE; + LPBYTE versionInfo = NULL; + UINT size; + VS_FIXEDFILEINFO *vinfo; + + /* 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), L"Kernel32.dll"); + + size = GetFileVersionInfoSizeW(dllPath, NULL); + if (size) + { + versionInfo = (LPBYTE) TCalloc(size); + if (GetFileVersionInfo(dllPath, 0, size, versionInfo)) + { + + if (VerQueryValueW(versionInfo, L"\\", (LPVOID *)&vinfo, &size) && (size >=sizeof(VS_FIXEDFILEINFO))) + { + *pdwMajor = HIWORD(vinfo->dwProductVersionMS); + *pdwMinor = LOWORD(vinfo->dwProductVersionMS); + *pdwBuildNumber = HIWORD(vinfo->dwProductVersionLS); + bRet = TRUE; + } + } + } + + if (versionInfo) + TCfree(versionInfo); + return bRet; +} +#endif + +/* + * Use RtlGetVersion to get Windows version because GetVersionEx is affected by application manifestation. + */ +typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); + +static BOOL GetWindowsVersion(LPOSVERSIONINFOW lpVersionInformation) +{ + BOOL bRet = FALSE; +#ifdef SETUP_DLL + DWORD dwMajor, dwMinor, dwBuildNumber; +#endif + RtlGetVersionPtr RtlGetVersionFn = (RtlGetVersionPtr) GetProcAddress(GetModuleHandle (L"ntdll.dll"), "RtlGetVersion"); + if (RtlGetVersionFn != NULL) + { + if (ERROR_SUCCESS == RtlGetVersionFn (lpVersionInformation)) + bRet = TRUE; + } + + if (!bRet) + bRet = GetVersionExW (lpVersionInformation); + +#ifdef SETUP_DLL + // we get real version from Kernel32.dll version since MSI always sets current version to 6.0 + // https://stackoverflow.com/questions/49335885/windows-10-not-detecting-on-installshield/49343826#49343826 + if (GetWindowVersionFromFile(&dwMajor, &dwMinor, &dwBuildNumber)) + { + lpVersionInformation->dwMajorVersion = dwMajor; + lpVersionInformation->dwMinorVersion = dwMinor; + lpVersionInformation->dwBuildNumber = dwBuildNumber; + } +#endif + + return bRet; +} + + +void InitOSVersionInfo () +{ + OSVERSIONINFOEXW os; + os.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); + + if (GetWindowsVersion ((LPOSVERSIONINFOW) &os) == FALSE) + AbortProcess ("NO_OS_VER"); + + CurrentOSMajor = os.dwMajorVersion; + CurrentOSMinor = os.dwMinorVersion; + CurrentOSServicePack = os.wServicePackMajor; + CurrentOSBuildNumber = os.dwBuildNumber; + + if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 0) + nCurrentOS = WIN_2000; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 1) + nCurrentOS = WIN_XP; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 2) + { + if (os.wProductType == VER_NT_SERVER || os.wProductType == VER_NT_DOMAIN_CONTROLLER) + nCurrentOS = WIN_SERVER_2003; + else + nCurrentOS = WIN_XP64; + } + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 0) + { + if (os.wProductType != VER_NT_WORKSTATION) + nCurrentOS = WIN_SERVER_2008; + else + nCurrentOS = WIN_VISTA; + } + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 1) + nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2008_R2 : WIN_7); + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 2) + nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012 : WIN_8); + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 3) + nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012_R2 : WIN_8_1); + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 10 && CurrentOSMinor == 0) + nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2016 : WIN_10); + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 4) + nCurrentOS = WIN_NT4; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 0) + nCurrentOS = WIN_95; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 10) + nCurrentOS = WIN_98; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 90) + nCurrentOS = WIN_ME; + else if (os.dwPlatformId == VER_PLATFORM_WIN32s) + nCurrentOS = WIN_31; + else + nCurrentOS = WIN_UNKNOWN; +} + +#pragma warning(push) +#pragma warning(disable:4702) + +void *err_malloc (size_t size) +{ + void *z = (void *) TCalloc (size); + if (z) + return z; + AbortProcess ("OUTOFMEMORY"); + return 0; +} + +#pragma warning(pop) + + +char *err_strdup (char *lpszText) +{ + size_t j = (strlen (lpszText) + 1) * sizeof (char); + char *z = (char *) err_malloc (j); + memmove (z, lpszText, j); + return z; +} + +void AbortProcessDirect (wchar_t *abortMsg) +{ + // Note that this function also causes localcleanup() to be called (see atexit()) + MessageBeep (MB_ICONEXCLAMATION); + MessageBoxW (NULL, abortMsg, lpszTitle, ICON_HAND); +#ifndef VC_COMREG + FREE_DLL (hRichEditDll); + FREE_DLL (hComctl32Dll); + FREE_DLL (hSetupDll); + FREE_DLL (hShlwapiDll); + FREE_DLL (hProfApiDll); + FREE_DLL (hUsp10Dll); + FREE_DLL (hCryptSpDll); + FREE_DLL (hUXThemeDll); + FREE_DLL (hUserenvDll); + FREE_DLL (hRsaenhDll); + FREE_DLL (himm32dll); + FREE_DLL (hMSCTFdll); + FREE_DLL (hfltlibdll); + FREE_DLL (hframedyndll); + FREE_DLL (hpsapidll); + FREE_DLL (hsecur32dll); + FREE_DLL (hnetapi32dll); + FREE_DLL (hauthzdll); + FREE_DLL (hxmllitedll); + FREE_DLL (hmprdll); + FREE_DLL (hsppdll); + FREE_DLL (vssapidll); + FREE_DLL (hvsstracedll); + FREE_DLL (hCryptSpDll); + FREE_DLL (hcfgmgr32dll); + FREE_DLL (hdevobjdll); + FREE_DLL (hpowrprofdll); + FREE_DLL (hsspiclidll); + FREE_DLL (hcryptbasedll); + FREE_DLL (hdwmapidll); + FREE_DLL (hmsasn1dll); + FREE_DLL (hcrypt32dll); + FREE_DLL (hbcryptdll); + FREE_DLL (hbcryptprimitivesdll); + FREE_DLL (hMsls31); + FREE_DLL (hntmartadll); + FREE_DLL (hwinscarddll); + FREE_DLL (hmsvcrtdll); + FREE_DLL (hAdvapi32Dll); +#endif + exit (1); +} + +void AbortProcess (char *stringId) +{ + // Note that this function also causes localcleanup() to be called (see atexit()) +#ifndef VC_COMREG + AbortProcessDirect (GetString (stringId)); +#else + static wchar_t g_wszUnknown[1024]; + StringCbPrintfW (g_wszUnknown, sizeof(g_wszUnknown), UNKNOWN_STRING_ID L"%hs" UNKNOWN_STRING_ID, stringId); + AbortProcessDirect (g_wszUnknown); +#endif +} + +#ifndef VC_COMREG +void AbortProcessSilent (void) +{ + FREE_DLL (hRichEditDll); + FREE_DLL (hComctl32Dll); + FREE_DLL (hSetupDll); + FREE_DLL (hShlwapiDll); + FREE_DLL (hProfApiDll); + FREE_DLL (hUsp10Dll); + FREE_DLL (hCryptSpDll); + FREE_DLL (hUXThemeDll); + FREE_DLL (hUserenvDll); + FREE_DLL (hRsaenhDll); + FREE_DLL (himm32dll); + FREE_DLL (hMSCTFdll); + FREE_DLL (hfltlibdll); + FREE_DLL (hframedyndll); + FREE_DLL (hpsapidll); + FREE_DLL (hsecur32dll); + FREE_DLL (hnetapi32dll); + FREE_DLL (hauthzdll); + FREE_DLL (hxmllitedll); + FREE_DLL (hmprdll); + FREE_DLL (hsppdll); + FREE_DLL (vssapidll); + FREE_DLL (hvsstracedll); + FREE_DLL (hCryptSpDll); + FREE_DLL (hcfgmgr32dll); + FREE_DLL (hdevobjdll); + FREE_DLL (hpowrprofdll); + FREE_DLL (hsspiclidll); + FREE_DLL (hcryptbasedll); + FREE_DLL (hdwmapidll); + FREE_DLL (hmsasn1dll); + FREE_DLL (hcrypt32dll); + FREE_DLL (hbcryptdll); + FREE_DLL (hbcryptprimitivesdll); + FREE_DLL (hMsls31); + FREE_DLL (hntmartadll); + FREE_DLL (hwinscarddll); + FREE_DLL (hmsvcrtdll); + FREE_DLL (hAdvapi32Dll); + + // Note that this function also causes localcleanup() to be called (see atexit()) + exit (1); +} + void InitGlobalLocks () { InitializeCriticalSection (&csWNetCalls); @@ -726,182 +1675,57 @@ BOOL IsValidFileName(const wchar_t* str) BOOL IsVolumeDeviceHosted (const wchar_t *lpszDiskFile) { return wcsstr (lpszDiskFile, L"\\Device\\") == lpszDiskFile - || wcsstr (lpszDiskFile, L"\\DEVICE\\") == lpszDiskFile; -} - - -void CreateFullVolumePath (wchar_t *lpszDiskFile, size_t cbDiskFile, const wchar_t *lpszFileName, BOOL * bDevice) -{ - UpperCaseCopy (lpszDiskFile, cbDiskFile, lpszFileName); - - *bDevice = FALSE; - - if (wmemcmp (lpszDiskFile, L"\\DEVICE", 7) == 0) - { - *bDevice = TRUE; - } - - StringCbCopyW (lpszDiskFile, cbDiskFile, lpszFileName); - -#if _DEBUG - OutputDebugString (L"CreateFullVolumePath: "); - OutputDebugString (lpszDiskFile); - OutputDebugString (L"\n"); -#endif - -} - -int FakeDosNameForDevice (const wchar_t *lpszDiskFile , wchar_t *lpszDosDevice , size_t cbDosDevice, wchar_t *lpszCFDevice , size_t cbCFDevice, BOOL bNameOnly) -{ - BOOL bDosLinkCreated = TRUE; - StringCbPrintfW (lpszDosDevice, cbDosDevice,L"veracrypt%lu", GetCurrentProcessId ()); - - if (bNameOnly == FALSE) - bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile); - - if (bDosLinkCreated == FALSE) - return ERR_OS_ERROR; - else - StringCbPrintfW (lpszCFDevice, cbCFDevice,L"\\\\.\\%s", lpszDosDevice); - - return 0; -} - -int RemoveFakeDosName (wchar_t *lpszDiskFile, wchar_t *lpszDosDevice) -{ - BOOL bDosLinkRemoved = DefineDosDevice (DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | - DDD_REMOVE_DEFINITION, lpszDosDevice, lpszDiskFile); - if (bDosLinkRemoved == FALSE) - { - return ERR_OS_ERROR; - } - - return 0; -} - - -void AbortProcessDirect (wchar_t *abortMsg) -{ - // Note that this function also causes localcleanup() to be called (see atexit()) - MessageBeep (MB_ICONEXCLAMATION); - MessageBoxW (NULL, abortMsg, lpszTitle, ICON_HAND); - FREE_DLL (hRichEditDll); - FREE_DLL (hComctl32Dll); - FREE_DLL (hSetupDll); - FREE_DLL (hShlwapiDll); - FREE_DLL (hProfApiDll); - FREE_DLL (hUsp10Dll); - FREE_DLL (hCryptSpDll); - FREE_DLL (hUXThemeDll); - FREE_DLL (hUserenvDll); - FREE_DLL (hRsaenhDll); - FREE_DLL (himm32dll); - FREE_DLL (hMSCTFdll); - FREE_DLL (hfltlibdll); - FREE_DLL (hframedyndll); - FREE_DLL (hpsapidll); - FREE_DLL (hsecur32dll); - FREE_DLL (hnetapi32dll); - FREE_DLL (hauthzdll); - FREE_DLL (hxmllitedll); - FREE_DLL (hmprdll); - FREE_DLL (hsppdll); - FREE_DLL (vssapidll); - FREE_DLL (hvsstracedll); - FREE_DLL (hCryptSpDll); - FREE_DLL (hcfgmgr32dll); - FREE_DLL (hdevobjdll); - FREE_DLL (hpowrprofdll); - FREE_DLL (hsspiclidll); - FREE_DLL (hcryptbasedll); - FREE_DLL (hdwmapidll); - FREE_DLL (hmsasn1dll); - FREE_DLL (hcrypt32dll); - FREE_DLL (hbcryptdll); - FREE_DLL (hbcryptprimitivesdll); - FREE_DLL (hMsls31); - FREE_DLL (hntmartadll); - FREE_DLL (hwinscarddll); - FREE_DLL (hmsvcrtdll); - FREE_DLL (hAdvapi32Dll); - - exit (1); -} - -void AbortProcess (char *stringId) -{ - // Note that this function also causes localcleanup() to be called (see atexit()) - AbortProcessDirect (GetString (stringId)); + || wcsstr (lpszDiskFile, L"\\DEVICE\\") == lpszDiskFile; } -void AbortProcessSilent (void) + +void CreateFullVolumePath (wchar_t *lpszDiskFile, size_t cbDiskFile, const wchar_t *lpszFileName, BOOL * bDevice) { - FREE_DLL (hRichEditDll); - FREE_DLL (hComctl32Dll); - FREE_DLL (hSetupDll); - FREE_DLL (hShlwapiDll); - FREE_DLL (hProfApiDll); - FREE_DLL (hUsp10Dll); - FREE_DLL (hCryptSpDll); - FREE_DLL (hUXThemeDll); - FREE_DLL (hUserenvDll); - FREE_DLL (hRsaenhDll); - FREE_DLL (himm32dll); - FREE_DLL (hMSCTFdll); - FREE_DLL (hfltlibdll); - FREE_DLL (hframedyndll); - FREE_DLL (hpsapidll); - FREE_DLL (hsecur32dll); - FREE_DLL (hnetapi32dll); - FREE_DLL (hauthzdll); - FREE_DLL (hxmllitedll); - FREE_DLL (hmprdll); - FREE_DLL (hsppdll); - FREE_DLL (vssapidll); - FREE_DLL (hvsstracedll); - FREE_DLL (hCryptSpDll); - FREE_DLL (hcfgmgr32dll); - FREE_DLL (hdevobjdll); - FREE_DLL (hpowrprofdll); - FREE_DLL (hsspiclidll); - FREE_DLL (hcryptbasedll); - FREE_DLL (hdwmapidll); - FREE_DLL (hmsasn1dll); - FREE_DLL (hcrypt32dll); - FREE_DLL (hbcryptdll); - FREE_DLL (hbcryptprimitivesdll); - FREE_DLL (hMsls31); - FREE_DLL (hntmartadll); - FREE_DLL (hwinscarddll); - FREE_DLL (hmsvcrtdll); - FREE_DLL (hAdvapi32Dll); + UpperCaseCopy (lpszDiskFile, cbDiskFile, lpszFileName); - // Note that this function also causes localcleanup() to be called (see atexit()) - exit (1); -} + *bDevice = FALSE; + if (wmemcmp (lpszDiskFile, L"\\DEVICE", 7) == 0) + { + *bDevice = TRUE; + } -#pragma warning(push) -#pragma warning(disable:4702) + StringCbCopyW (lpszDiskFile, cbDiskFile, lpszFileName); + +#if _DEBUG + OutputDebugString (L"CreateFullVolumePath: "); + OutputDebugString (lpszDiskFile); + OutputDebugString (L"\n"); +#endif -void *err_malloc (size_t size) -{ - void *z = (void *) TCalloc (size); - if (z) - return z; - AbortProcess ("OUTOFMEMORY"); - return 0; } -#pragma warning(pop) +int FakeDosNameForDevice (const wchar_t *lpszDiskFile , wchar_t *lpszDosDevice , size_t cbDosDevice, wchar_t *lpszCFDevice , size_t cbCFDevice, BOOL bNameOnly) +{ + BOOL bDosLinkCreated = TRUE; + StringCbPrintfW (lpszDosDevice, cbDosDevice,L"veracrypt%lu", GetCurrentProcessId ()); + if (bNameOnly == FALSE) + bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile); -char *err_strdup (char *lpszText) + if (bDosLinkCreated == FALSE) + return ERR_OS_ERROR; + else + StringCbPrintfW (lpszCFDevice, cbCFDevice,L"\\\\.\\%s", lpszDosDevice); + + return 0; +} + +int RemoveFakeDosName (wchar_t *lpszDiskFile, wchar_t *lpszDosDevice) { - size_t j = (strlen (lpszText) + 1) * sizeof (char); - char *z = (char *) err_malloc (j); - memmove (z, lpszText, j); - return z; + BOOL bDosLinkRemoved = DefineDosDevice (DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | + DDD_REMOVE_DEFINITION, lpszDosDevice, lpszDiskFile); + if (bDosLinkRemoved == FALSE) + { + return ERR_OS_ERROR; + } + + return 0; } @@ -933,59 +1757,6 @@ BOOL IsDiskError (DWORD error) return IsDiskReadError (error) || IsDiskWriteError (error); } - -DWORD handleWin32Error (HWND hwndDlg, const char* srcPos) -{ - PWSTR lpMsgBuf; - DWORD dwError = GetLastError (); - wchar_t szErrorValue[32]; - wchar_t* pszDesc; - - if (Silent || dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE) - return dwError; - - // Access denied - if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ()) - { - ErrorDirect ( AppendSrcPos (GetString ("ERR_ACCESS_DENIED"), srcPos).c_str (), hwndDlg); - 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; - } - - MessageBoxW (hwndDlg, AppendSrcPos (pszDesc, srcPos).c_str (), lpszTitle, ICON_HAND); - if (lpMsgBuf) LocalFree (lpMsgBuf); - - // User-friendly hardware error explanation - if (IsDiskError (dwError)) - Error ("ERR_HARDWARE_ERROR", hwndDlg); - - // Device not ready - if (dwError == ERROR_NOT_READY) - HandleDriveNotReadyError(hwndDlg); - - SetLastError (dwError); // Preserve the original error code - - return dwError; -} - BOOL translateWin32Error (wchar_t *lpszMsgBuf, int nWSizeOfBuf) { DWORD dwError = GetLastError (); @@ -2879,155 +3650,27 @@ void DoPostInstallTasks (HWND hwndDlg) if (AskYesNo ("AFTER_INSTALL_TUTORIAL", hwndDlg) == IDYES) Applink ("beginnerstutorial"); - bDone = TRUE; - } - - if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES))) - { - if (AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES", hwndDlg) == IDYES) - Applink ("releasenotes"); - - bDone = TRUE; - } - - if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK))) - { - if (AskYesNo ("AFTER_UPGRADE_RESCUE_DISK", hwndDlg) == IDYES) - PostMessage (hwndDlg, VC_APPMSG_CREATE_RESCUE_DISK, 0, 0); - - bDone = TRUE; - } - - if (bDone) - SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_REMOVE_ALL); -} - -#ifdef SETUP_DLL -static BOOL GetWindowVersionFromFile(DWORD* pdwMajor, DWORD* pdwMinor, DWORD* pdwBuildNumber) -{ - wchar_t dllPath[MAX_PATH]; - BOOL bRet = FALSE; - LPBYTE versionInfo = NULL; - UINT size; - VS_FIXEDFILEINFO *vinfo; - - /* 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), L"Kernel32.dll"); - - size = GetFileVersionInfoSizeW(dllPath, NULL); - if (size) - { - versionInfo = (LPBYTE) TCalloc(size); - if (GetFileVersionInfo(dllPath, 0, size, versionInfo)) - { - - if (VerQueryValueW(versionInfo, L"\\", (LPVOID *)&vinfo, &size) && (size >=sizeof(VS_FIXEDFILEINFO))) - { - *pdwMajor = HIWORD(vinfo->dwProductVersionMS); - *pdwMinor = LOWORD(vinfo->dwProductVersionMS); - *pdwBuildNumber = HIWORD(vinfo->dwProductVersionLS); - bRet = TRUE; - } - } - } - - if (versionInfo) - TCfree(versionInfo); - return bRet; -} -#endif - -/* - * Use RtlGetVersion to get Windows version because GetVersionEx is affected by application manifestation. - */ -typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); - -static BOOL GetWindowsVersion(LPOSVERSIONINFOW lpVersionInformation) -{ - BOOL bRet = FALSE; -#ifdef SETUP_DLL - DWORD dwMajor, dwMinor, dwBuildNumber; -#endif - RtlGetVersionPtr RtlGetVersionFn = (RtlGetVersionPtr) GetProcAddress(GetModuleHandle (L"ntdll.dll"), "RtlGetVersion"); - if (RtlGetVersionFn != NULL) - { - if (ERROR_SUCCESS == RtlGetVersionFn (lpVersionInformation)) - bRet = TRUE; - } - - if (!bRet) - bRet = GetVersionExW (lpVersionInformation); - -#ifdef SETUP_DLL - // we get real version from Kernel32.dll version since MSI always sets current version to 6.0 - // https://stackoverflow.com/questions/49335885/windows-10-not-detecting-on-installshield/49343826#49343826 - if (GetWindowVersionFromFile(&dwMajor, &dwMinor, &dwBuildNumber)) - { - lpVersionInformation->dwMajorVersion = dwMajor; - lpVersionInformation->dwMinorVersion = dwMinor; - lpVersionInformation->dwBuildNumber = dwBuildNumber; - } -#endif - - return bRet; -} - - -void InitOSVersionInfo () -{ - OSVERSIONINFOEXW os; - os.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); - - if (GetWindowsVersion ((LPOSVERSIONINFOW) &os) == FALSE) - AbortProcess ("NO_OS_VER"); - - CurrentOSMajor = os.dwMajorVersion; - CurrentOSMinor = os.dwMinorVersion; - CurrentOSServicePack = os.wServicePackMajor; - CurrentOSBuildNumber = os.dwBuildNumber; + bDone = TRUE; + } - if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 0) - nCurrentOS = WIN_2000; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 1) - nCurrentOS = WIN_XP; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 2) + if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES))) { - if (os.wProductType == VER_NT_SERVER || os.wProductType == VER_NT_DOMAIN_CONTROLLER) - nCurrentOS = WIN_SERVER_2003; - else - nCurrentOS = WIN_XP64; + if (AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES", hwndDlg) == IDYES) + Applink ("releasenotes"); + + bDone = TRUE; } - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 0) + + if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK))) { - if (os.wProductType != VER_NT_WORKSTATION) - nCurrentOS = WIN_SERVER_2008; - else - nCurrentOS = WIN_VISTA; + if (AskYesNo ("AFTER_UPGRADE_RESCUE_DISK", hwndDlg) == IDYES) + PostMessage (hwndDlg, VC_APPMSG_CREATE_RESCUE_DISK, 0, 0); + + bDone = TRUE; } - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 1) - nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2008_R2 : WIN_7); - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 2) - nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012 : WIN_8); - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 3) - nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012_R2 : WIN_8_1); - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 10 && CurrentOSMinor == 0) - nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2016 : WIN_10); - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 4) - nCurrentOS = WIN_NT4; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 0) - nCurrentOS = WIN_95; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 10) - nCurrentOS = WIN_98; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 90) - nCurrentOS = WIN_ME; - else if (os.dwPlatformId == VER_PLATFORM_WIN32s) - nCurrentOS = WIN_31; - else - nCurrentOS = WIN_UNKNOWN; + + if (bDone) + SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_REMOVE_ALL); } static void LoadSystemDll (LPCTSTR szModuleName, HMODULE *pHandle, BOOL bIgnoreError, const char* srcPos) @@ -9074,458 +9717,193 @@ int FileSystemAppearsEmpty (const wchar_t *devicePath) if (occupiedBytes > BYTES_PER_GB && percentFreeSpace < 99.99 // "percentFreeSpace < 99.99" is needed because an NTFS filesystem larger than several terabytes can have more than 1GB of data in use, even if there are no files stored on it. || percentFreeSpace < 88) // A 24-MB NTFS filesystem has 11.5% of space in use even if there are no files stored on it. { - return 0; - } - else - return 1; - } - else - return -1; -} - - -// Returns the free space on the specified partition (volume) in bytes. If the 'occupiedBytes' pointer -// is not NULL, size of occupied space (in bytes) is written to the pointed location. In addition, if the -// 'percent' pointer is not NULL, % of free space is stored in the pointed location. If there's an error, -// returns -1. -__int64 GetStatsFreeSpaceOnPartition (const wchar_t *devicePath, float *percentFree, __int64 *occupiedBytes, BOOL silent) -{ - WCHAR devPath [MAX_PATH]; - int driveLetterNo = -1; - wchar_t szRootPath[4] = {0, L':', L'\\', 0}; - ULARGE_INTEGER freeSpaceSize; - ULARGE_INTEGER totalNumberOfBytes; - ULARGE_INTEGER totalNumberOfFreeBytes; - - StringCbCopyW (devPath, sizeof(devPath), devicePath); - - driveLetterNo = GetDiskDeviceDriveLetter (devPath); - szRootPath[0] = (wchar_t) driveLetterNo + L'A'; - - - if (!GetDiskFreeSpaceEx (szRootPath, &freeSpaceSize, &totalNumberOfBytes, &totalNumberOfFreeBytes)) - { - if (!silent) - { - handleWin32Error (MainDlg, SRC_POS); - Error ("CANNOT_CALC_SPACE", MainDlg); - } - - return -1; - } - - - if (percentFree != NULL || occupiedBytes != NULL) - { - // Determine occupied space and % of free space - - PARTITION_INFORMATION partitionInfo; - - if (!GetPartitionInfo (devicePath, &partitionInfo)) - { - if (!silent) - { - handleWin32Error (MainDlg, SRC_POS); - Error ("CANT_GET_VOLSIZE", MainDlg); - } - return -1; - } - - if (occupiedBytes != NULL) - *occupiedBytes = partitionInfo.PartitionLength.QuadPart - freeSpaceSize.QuadPart; - - if (percentFree != NULL) - *percentFree = (float) ((double) freeSpaceSize.QuadPart / (double) partitionInfo.PartitionLength.QuadPart * 100.0); - } - - return freeSpaceSize.QuadPart; -} - - -// Returns -1 if there's an error. -__int64 GetDeviceSize (const wchar_t *devicePath) -{ - PARTITION_INFORMATION partitionInfo; - - if (!GetPartitionInfo (devicePath, &partitionInfo)) - return -1; - - return partitionInfo.PartitionLength.QuadPart; -} - - -HANDLE DismountDrive (wchar_t *devName, wchar_t *devicePath) -{ - DWORD dwResult; - HANDLE hVolume; - BOOL bResult = FALSE; - int attempt = UNMOUNT_MAX_AUTO_RETRIES; - int driveLetterNo = -1; - WCHAR devPath [MAX_PATH]; - - StringCbCopyW (devPath, sizeof(devPath), devicePath); - driveLetterNo = GetDiskDeviceDriveLetter (devPath); - - - hVolume = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (hVolume == INVALID_HANDLE_VALUE) - return INVALID_HANDLE_VALUE; - - - // Try to lock the volume first so that dismount is not forced. - // If we fail, we will dismount anyway even if it needs to be forced. - - CloseVolumeExplorerWindows (MainDlg, driveLetterNo); - - while (!(bResult = DeviceIoControl (hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) - && attempt > 0) - { - Sleep (UNMOUNT_AUTO_RETRY_DELAY); - attempt--; - } - - - // Try to dismount the volume - - attempt = UNMOUNT_MAX_AUTO_RETRIES; - - while (!(bResult = DeviceIoControl (hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) - && attempt > 0) - { - Sleep (UNMOUNT_AUTO_RETRY_DELAY); - attempt--; - } - - if (!bResult) - CloseHandle (hVolume); - - return (bResult ? hVolume : INVALID_HANDLE_VALUE); -} - -// Returns -1 if the specified string is not found in the buffer. Otherwise, returns the -// offset of the first occurrence of the string. The string and the buffer may contain zeroes, -// which do NOT terminate them. -int64 FindString (const char *buf, const char *str, int64 bufLen, int64 strLen, int64 startOffset) -{ - if (buf == NULL - || str == NULL - || strLen > bufLen - || bufLen < 1 - || strLen < 1 - || startOffset > bufLen - strLen) - { - return -1; - } - - for (int64 i = startOffset; i <= bufLen - strLen; i++) - { - if (memcmp (buf + i, str, (size_t) strLen) == 0) - return i; - } - - return -1; -} - -// Returns TRUE if the file or directory exists (both may be enclosed in quotation marks). -BOOL FileExists (const wchar_t *filePathPtr) -{ - wchar_t filePath [TC_MAX_PATH * 2 + 1]; - - // Strip quotation marks (if any) - if (filePathPtr [0] == L'"') - { - StringCbCopyW (filePath, sizeof(filePath), filePathPtr + 1); - } - else - { - StringCbCopyW (filePath, sizeof(filePath), filePathPtr); - } - - // Strip quotation marks (if any) - if (filePath [wcslen (filePath) - 1] == L'"') - filePath [wcslen (filePath) - 1] = 0; - - return (_waccess (filePath, 0) != -1); -} - -// Searches the file from its end for the LAST occurrence of the string str. -// The string may contain zeroes, which do NOT terminate the string. -// If the string is found, its offset from the start of the file is returned. -// If the string isn't found or if any error occurs, -1 is returned. -__int64 FindStringInFile (const wchar_t *filePath, const char* str, int strLen) -{ - int bufSize = 64 * BYTES_PER_KB; - char *buffer = (char *) err_malloc (bufSize); - HANDLE src = NULL; - DWORD bytesRead; - BOOL readRetVal; - __int64 filePos = GetFileSize64 (filePath); - int bufPos = 0; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL bExit = FALSE; - int filePosStep; - __int64 retVal = -1; - - if (filePos <= 0 - || buffer == NULL - || strLen > bufSize - || strLen < 1) - { - if (buffer) - free (buffer); - return -1; + return 0; + } + else + return 1; } + else + return -1; +} - src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (src == INVALID_HANDLE_VALUE) - { - free (buffer); - return -1; - } +// Returns the free space on the specified partition (volume) in bytes. If the 'occupiedBytes' pointer +// is not NULL, size of occupied space (in bytes) is written to the pointed location. In addition, if the +// 'percent' pointer is not NULL, % of free space is stored in the pointed location. If there's an error, +// returns -1. +__int64 GetStatsFreeSpaceOnPartition (const wchar_t *devicePath, float *percentFree, __int64 *occupiedBytes, BOOL silent) +{ + WCHAR devPath [MAX_PATH]; + int driveLetterNo = -1; + wchar_t szRootPath[4] = {0, L':', L'\\', 0}; + ULARGE_INTEGER freeSpaceSize; + ULARGE_INTEGER totalNumberOfBytes; + ULARGE_INTEGER totalNumberOfFreeBytes; - filePosStep = bufSize - strLen + 1; + StringCbCopyW (devPath, sizeof(devPath), devicePath); - do - { - filePos -= filePosStep; + driveLetterNo = GetDiskDeviceDriveLetter (devPath); + szRootPath[0] = (wchar_t) driveLetterNo + L'A'; - if (filePos < 0) + + if (!GetDiskFreeSpaceEx (szRootPath, &freeSpaceSize, &totalNumberOfBytes, &totalNumberOfFreeBytes)) + { + if (!silent) { - filePos = 0; - bExit = TRUE; + handleWin32Error (MainDlg, SRC_POS); + Error ("CANNOT_CALC_SPACE", MainDlg); } - seekOffset.QuadPart = filePos; + return -1; + } - if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - goto fsif_end; - if ((readRetVal = ReadFile (src, buffer, bufSize, &bytesRead, NULL)) == 0 - || bytesRead == 0) - goto fsif_end; + if (percentFree != NULL || occupiedBytes != NULL) + { + // Determine occupied space and % of free space - bufPos = bytesRead - strLen; + PARTITION_INFORMATION partitionInfo; - while (bufPos > 0) + if (!GetPartitionInfo (devicePath, &partitionInfo)) { - if (memcmp (buffer + bufPos, str, strLen) == 0) + if (!silent) { - // String found - retVal = filePos + bufPos; - goto fsif_end; + handleWin32Error (MainDlg, SRC_POS); + Error ("CANT_GET_VOLSIZE", MainDlg); } - bufPos--; + return -1; } - } while (!bExit); + if (occupiedBytes != NULL) + *occupiedBytes = partitionInfo.PartitionLength.QuadPart - freeSpaceSize.QuadPart; -fsif_end: - CloseHandle (src); - free (buffer); + if (percentFree != NULL) + *percentFree = (float) ((double) freeSpaceSize.QuadPart / (double) partitionInfo.PartitionLength.QuadPart * 100.0); + } - return retVal; + return freeSpaceSize.QuadPart; } -// System CopyFile() copies source file attributes (like FILE_ATTRIBUTE_ENCRYPTED) -// so we need to use our own copy function -BOOL TCCopyFileBase (HANDLE src, HANDLE dst) -{ - __int8 *buffer; - FILETIME fileTime; - DWORD bytesRead, bytesWritten; - BOOL res; - buffer = (char *) malloc (64 * 1024); - if (!buffer) - { - CloseHandle (src); - CloseHandle (dst); - return FALSE; - } +// Returns -1 if there's an error. +__int64 GetDeviceSize (const wchar_t *devicePath) +{ + PARTITION_INFORMATION partitionInfo; - while (res = ReadFile (src, buffer, 64 * 1024, &bytesRead, NULL)) - { - if (bytesRead == 0) - { - res = 1; - break; - } + if (!GetPartitionInfo (devicePath, &partitionInfo)) + return -1; - if (!WriteFile (dst, buffer, bytesRead, &bytesWritten, NULL) - || bytesRead != bytesWritten) - { - res = 0; - break; - } - } + return partitionInfo.PartitionLength.QuadPart; +} - if (GetFileTime (src, NULL, NULL, &fileTime)) - SetFileTime (dst, NULL, NULL, &fileTime); - CloseHandle (src); - CloseHandle (dst); +HANDLE DismountDrive (wchar_t *devName, wchar_t *devicePath) +{ + DWORD dwResult; + HANDLE hVolume; + BOOL bResult = FALSE; + int attempt = UNMOUNT_MAX_AUTO_RETRIES; + int driveLetterNo = -1; + WCHAR devPath [MAX_PATH]; - free (buffer); - return res != 0; -} + StringCbCopyW (devPath, sizeof(devPath), devicePath); + driveLetterNo = GetDiskDeviceDriveLetter (devPath); -BOOL TCCopyFile (wchar_t *sourceFileName, wchar_t *destinationFile) -{ - HANDLE src, dst; - src = CreateFileW (sourceFileName, - GENERIC_READ, + hVolume = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (src == INVALID_HANDLE_VALUE) - return FALSE; + if (hVolume == INVALID_HANDLE_VALUE) + return INVALID_HANDLE_VALUE; - dst = CreateFileW (destinationFile, - GENERIC_WRITE, - 0, NULL, CREATE_ALWAYS, 0, NULL); - if (dst == INVALID_HANDLE_VALUE) - { - CloseHandle (src); - return FALSE; - } + // Try to lock the volume first so that dismount is not forced. + // If we fail, we will dismount anyway even if it needs to be forced. - return TCCopyFileBase (src, dst); -} + CloseVolumeExplorerWindows (MainDlg, driveLetterNo); -BOOL DecompressZipToDir (const unsigned char *inputBuffer, DWORD inputLength, const wchar_t *destinationDir, ProgressFn progressFnPtr, HWND hwndDlg) -{ - BOOL res = TRUE; - zip_error_t zerr; - zip_int64_t numFiles, i; - zip_stat_t sb; - zip_source_t* zsrc = zip_source_buffer_create (inputBuffer, inputLength, 0, &zerr); - if (!zsrc) - return FALSE; - zip_t* z = zip_open_from_source (zsrc, ZIP_CHECKCONS | ZIP_RDONLY, &zerr); - if (!z) + while (!(bResult = DeviceIoControl (hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) + && attempt > 0) { - zip_source_free (zsrc); - return FALSE; + Sleep (UNMOUNT_AUTO_RETRY_DELAY); + attempt--; } - finally_do_arg (zip_t*, z, { zip_close (finally_arg); }); - - numFiles = zip_get_num_entries (z, 0); - if (numFiles <= 0) - return FALSE; - - for (i = 0; (i < numFiles) && res; i++) - { - ZeroMemory (&sb, sizeof (sb)); - if ((0 == zip_stat_index (z, i, 0, &sb)) && (sb.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) && (sb.size > 0)) - { - std::wstring wname = Utf8StringToWide (sb.name); - CorrectFileName (wname); - - std::wstring filePath = destinationDir + wname; - size_t pos = filePath.find_last_of (L"/\\"); - // create the parent directory if it doesn't exist - if (pos != std::wstring::npos) - { - SHCreateDirectoryEx (NULL, filePath.substr (0, pos).c_str(), NULL); - } - - zip_file_t *f = zip_fopen_index (z, i, 0); - if (f) - { - ByteArray buffer((ByteArray::size_type) sb.size); - zip_fread (f, buffer.data(), sb.size); - zip_fclose (f); + // Try to dismount the volume - if (progressFnPtr) - progressFnPtr (hwndDlg, filePath.c_str()); + attempt = UNMOUNT_MAX_AUTO_RETRIES; - res = SaveBufferToFile ((char *) buffer.data(), filePath.c_str(), (DWORD) buffer.size(), FALSE, TRUE); - } - } + while (!(bResult = DeviceIoControl (hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) + && attempt > 0) + { + Sleep (UNMOUNT_AUTO_RETRY_DELAY); + attempt--; } - return res; + if (!bResult) + CloseHandle (hVolume); + + return (bResult ? hVolume : INVALID_HANDLE_VALUE); } -// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file -// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE). -BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed) +BOOL DecompressZipToDir (const unsigned char *inputBuffer, DWORD inputLength, const wchar_t *destinationDir, ProgressFn progressFnPtr, HWND hwndDlg) { - HANDLE dst; - DWORD bytesWritten; - BOOL res = TRUE; - DWORD dwLastError = 0; - - dst = CreateFile (destinationFile, - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); - - dwLastError = GetLastError(); - if (!bAppend && bRenameIfFailed && (dst == INVALID_HANDLE_VALUE) && (GetLastError () == ERROR_SHARING_VIOLATION)) - { - wchar_t renamedPath[TC_MAX_PATH + 1]; - StringCbCopyW (renamedPath, sizeof(renamedPath), destinationFile); - StringCbCatW (renamedPath, sizeof(renamedPath), VC_FILENAME_RENAMED_SUFFIX); - - /* rename the locked file in order to be able to create a new one */ - if (MoveFileEx (destinationFile, renamedPath, MOVEFILE_REPLACE_EXISTING)) - { - dst = CreateFile (destinationFile, - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); - dwLastError = GetLastError(); - if (dst == INVALID_HANDLE_VALUE) - { - /* restore the original file name */ - MoveFileEx (renamedPath, destinationFile, MOVEFILE_REPLACE_EXISTING); - } - else - { - /* delete the renamed file when the machine reboots */ - MoveFileEx (renamedPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); - } - } - } - - if (dst == INVALID_HANDLE_VALUE) + BOOL res = TRUE; + zip_error_t zerr; + zip_int64_t numFiles, i; + zip_stat_t sb; + zip_source_t* zsrc = zip_source_buffer_create (inputBuffer, inputLength, 0, &zerr); + if (!zsrc) + return FALSE; + zip_t* z = zip_open_from_source (zsrc, ZIP_CHECKCONS | ZIP_RDONLY, &zerr); + if (!z) { - SetLastError (dwLastError); - handleWin32Error (MainDlg, SRC_POS); + zip_source_free (zsrc); return FALSE; } - if (bAppend) - SetFilePointer (dst, 0, NULL, FILE_END); + finally_do_arg (zip_t*, z, { zip_close (finally_arg); }); - if (!WriteFile (dst, inputBuffer, inputLength, &bytesWritten, NULL) - || inputLength != bytesWritten) - { - res = FALSE; - } + numFiles = zip_get_num_entries (z, 0); + if (numFiles <= 0) + return FALSE; - if (!res) + for (i = 0; (i < numFiles) && res; i++) { - // If CREATE_ALWAYS is used, ERROR_ALREADY_EXISTS is returned after successful overwrite - // of an existing file (it's not an error) - if (! (GetLastError() == ERROR_ALREADY_EXISTS && !bAppend) ) - handleWin32Error (MainDlg, SRC_POS); - } + ZeroMemory (&sb, sizeof (sb)); + if ((0 == zip_stat_index (z, i, 0, &sb)) && (sb.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) && (sb.size > 0)) + { + std::wstring wname = Utf8StringToWide (sb.name); + CorrectFileName (wname); - CloseHandle (dst); + std::wstring filePath = destinationDir + wname; + size_t pos = filePath.find_last_of (L"/\\"); + // create the parent directory if it doesn't exist + if (pos != std::wstring::npos) + { + SHCreateDirectoryEx (NULL, filePath.substr (0, pos).c_str(), NULL); + } - if (!res && !bAppend) - _wremove (destinationFile); + zip_file_t *f = zip_fopen_index (z, i, 0); + if (f) + { + ByteArray buffer((ByteArray::size_type) sb.size); + + zip_fread (f, buffer.data(), sb.size); + zip_fclose (f); + + if (progressFnPtr) + progressFnPtr (hwndDlg, filePath.c_str()); + + res = SaveBufferToFile ((char *) buffer.data(), filePath.c_str(), (DWORD) buffer.size(), FALSE, TRUE); + } + } + } return res; } - // Proper flush for Windows systems. Returns TRUE if successful. BOOL TCFlushFile (FILE *f) { @@ -9908,249 +10286,64 @@ void ClearHistory (HWND hwndDlgItem) #endif // #ifndef SETUP -LRESULT ListItemAdd (HWND list, int index, const wchar_t *string) -{ - LVITEM li; - memset (&li, 0, sizeof(li)); - - li.mask = LVIF_TEXT; - li.pszText = (wchar_t*) string; - li.iItem = index; - li.iSubItem = 0; - return ListView_InsertItem (list, &li); -} - - -LRESULT ListSubItemSet (HWND list, int index, int subIndex, const wchar_t *string) -{ - LVITEM li; - memset (&li, 0, sizeof(li)); - - li.mask = LVIF_TEXT; - li.pszText = (wchar_t*) string; - li.iItem = index; - li.iSubItem = subIndex; - return ListView_SetItem (list, &li); -} - - -BOOL GetMountList (MOUNT_LIST_STRUCT *list) -{ - DWORD dwResult; - MOUNT_LIST_STRUCT localList = {0}; - - if ( list && DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &localList, - sizeof (localList), &localList, sizeof (localList), &dwResult, - NULL) - && (localList.ulMountedDrives < (1 << 26)) - ) - { - memcpy (list, &localList, sizeof (MOUNT_LIST_STRUCT)); - return TRUE; - } - else - return FALSE; -} - - -int GetDriverRefCount () -{ - DWORD dwResult; - BOOL bResult; - int refCount; - - bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount, - sizeof (refCount), &dwResult, NULL); - - if (bResult) - return refCount; - else - return -1; -} - -// Loads a 32-bit integer from the file at the specified file offset. The saved value is assumed to have been -// processed by mputLong(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). -BOOL LoadInt32 (const wchar_t *filePath, unsigned __int32 *result, __int64 fileOffset) -{ - DWORD bufSize = sizeof(__int32); - unsigned char *buffer = (unsigned char *) malloc (bufSize); - unsigned char *bufferPtr = buffer; - HANDLE src = NULL; - DWORD bytesRead; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL retVal = FALSE; - - if (buffer == NULL) - return -1; - - src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src == INVALID_HANDLE_VALUE) - { - free (buffer); - return FALSE; - } - - seekOffset.QuadPart = fileOffset; - - if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - goto fsif_end; - - if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 - || bytesRead != bufSize) - goto fsif_end; - - - retVal = TRUE; - - *result = mgetLong(bufferPtr); - -fsif_end: - CloseHandle (src); - free (buffer); - - return retVal; -} - -// Loads a 16-bit integer from the file at the specified file offset. The saved value is assumed to have been -// processed by mputWord(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). -BOOL LoadInt16 (const wchar_t *filePath, int *result, __int64 fileOffset) -{ - DWORD bufSize = sizeof(__int16); - unsigned char *buffer = (unsigned char *) malloc (bufSize); - unsigned char *bufferPtr = buffer; - HANDLE src = NULL; - DWORD bytesRead; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL retVal = FALSE; - - if (buffer == NULL) - return -1; - - src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src == INVALID_HANDLE_VALUE) - { - free (buffer); - return FALSE; - } - - seekOffset.QuadPart = fileOffset; - - if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - goto fsif_end; - - if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 - || bytesRead != bufSize) - goto fsif_end; - - - retVal = TRUE; - - *result = mgetWord(bufferPtr); - -fsif_end: - CloseHandle (src); - free (buffer); - - return retVal; -} - -// Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated. -char *LoadFile (const wchar_t *fileName, DWORD *size) -{ - char *buf; - DWORD fileSize = INVALID_FILE_SIZE; - HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (h == INVALID_HANDLE_VALUE) - return NULL; - - if ((fileSize = GetFileSize (h, NULL)) == INVALID_FILE_SIZE) - { - CloseHandle (h); - return NULL; - } - - *size = fileSize; - buf = (char *) calloc (*size + 1, 1); - - if (buf == NULL) - { - CloseHandle (h); - return NULL; - } - - if (!ReadFile (h, buf, *size, size, NULL)) - { - free (buf); - buf = NULL; - } - - CloseHandle (h); - return buf; -} - - -// Returns NULL if there's any error. -char *LoadFileBlock (const wchar_t *fileName, __int64 fileOffset, DWORD count) -{ - char *buf; - DWORD bytesRead = 0; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL bStatus; - - HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (h == INVALID_HANDLE_VALUE) - return NULL; - - seekOffset.QuadPart = fileOffset; +LRESULT ListItemAdd (HWND list, int index, const wchar_t *string) +{ + LVITEM li; + memset (&li, 0, sizeof(li)); - if (SetFilePointerEx (h, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - { - CloseHandle (h); - return NULL; - } + li.mask = LVIF_TEXT; + li.pszText = (wchar_t*) string; + li.iItem = index; + li.iSubItem = 0; + return ListView_InsertItem (list, &li); +} - buf = (char *) calloc (count, 1); - if (buf == NULL) - { - CloseHandle (h); - return NULL; - } +LRESULT ListSubItemSet (HWND list, int index, int subIndex, const wchar_t *string) +{ + LVITEM li; + memset (&li, 0, sizeof(li)); - bStatus = ReadFile (h, buf, count, &bytesRead, NULL); + li.mask = LVIF_TEXT; + li.pszText = (wchar_t*) string; + li.iItem = index; + li.iSubItem = subIndex; + return ListView_SetItem (list, &li); +} - CloseHandle (h); - if (!bStatus || (bytesRead != count)) +BOOL GetMountList (MOUNT_LIST_STRUCT *list) +{ + DWORD dwResult; + MOUNT_LIST_STRUCT localList = {0}; + + if ( list && DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &localList, + sizeof (localList), &localList, sizeof (localList), &dwResult, + NULL) + && (localList.ulMountedDrives < (1 << 26)) + ) { - free (buf); - return NULL; + memcpy (list, &localList, sizeof (MOUNT_LIST_STRUCT)); + return TRUE; } - - return buf; + else + return FALSE; } -// Returns -1 if there is an error, or the size of the file. -__int64 GetFileSize64 (const wchar_t *path) +int GetDriverRefCount () { - HANDLE h = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - LARGE_INTEGER size; - __int64 retSize = -1; - - if (h) - { - if (GetFileSizeEx (h, &size)) - { - retSize = size.QuadPart; - } + DWORD dwResult; + BOOL bResult; + int refCount; - CloseHandle (h); - } + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount, + sizeof (refCount), &dwResult, NULL); - return retSize; + if (bResult) + return refCount; + else + return -1; } @@ -10355,13 +10548,6 @@ int WarningDirect (const wchar_t *warnMsg, HWND hwnd) return MessageBoxW (hwnd, warnMsg, lpszTitle, MB_ICONWARNING); } - -int Error (char *stringId, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR); -} - int ErrorRetryCancel (char *stringId, HWND hwnd) { if (Silent) return 0; @@ -10840,46 +11026,6 @@ void DebugMsgBox (char *format, ...) MessageBoxA (MainDlg, buf, "VeraCrypt debug", 0); } - -BOOL IsOSAtLeast (OSVersionEnum reqMinOS) -{ - return IsOSVersionAtLeast (reqMinOS, 0); -} - - -// Returns TRUE if the operating system is at least reqMinOS and service pack at least reqMinServicePack. -// Example 1: IsOSVersionAtLeast (WIN_VISTA, 1) called under Windows 2008, returns TRUE. -// Example 2: IsOSVersionAtLeast (WIN_XP, 3) called under Windows XP SP1, returns FALSE. -// Example 3: IsOSVersionAtLeast (WIN_XP, 3) called under Windows Vista SP1, returns TRUE. -BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack) -{ - /* When updating this function, update IsOSAtLeast() in Ntdriver.c too. */ - - if (CurrentOSMajor <= 0) - TC_THROW_FATAL_EXCEPTION; - - int major = 0, minor = 0; - - switch (reqMinOS) - { - case WIN_2000: major = 5; minor = 0; break; - case WIN_XP: major = 5; minor = 1; break; - case WIN_SERVER_2003: major = 5; minor = 2; break; - case WIN_VISTA: major = 6; minor = 0; break; - case WIN_7: major = 6; minor = 1; break; - case WIN_8: major = 6; minor = 2; break; - case WIN_8_1: major = 6; minor = 3; break; - case WIN_10: major = 10; minor = 0; break; - - default: - TC_THROW_FATAL_EXCEPTION; - break; - } - - return ((CurrentOSMajor << 16 | CurrentOSMinor << 8 | CurrentOSServicePack) - >= (major << 16 | minor << 8 | reqMinServicePack)); -} - BOOL IsSupportedOS () { BOOL bRet = FALSE; @@ -14125,137 +14271,6 @@ INT_PTR SecureDesktopDialogBoxParam( #endif -#if defined(NDEBUG) && !defined(VC_SKIP_OS_DRIVER_REQ_CHECK) -static BOOL InitializeWintrust() -{ - if (!hWinTrustLib) - { - wchar_t szPath[MAX_PATH] = {0}; - - if (GetSystemDirectory(szPath, MAX_PATH)) - StringCchCatW (szPath, MAX_PATH, L"\\Wintrust.dll"); - else - StringCchCopyW (szPath, MAX_PATH, L"C:\\Windows\\System32\\Wintrust.dll"); - - hWinTrustLib = LoadLibrary (szPath); - if (hWinTrustLib) - { - WinVerifyTrustFn = (WINVERIFYTRUST) GetProcAddress (hWinTrustLib, "WinVerifyTrust"); - WTHelperProvDataFromStateDataFn = (WTHELPERPROVDATAFROMSTATEDATA) GetProcAddress (hWinTrustLib, "WTHelperProvDataFromStateData"); - WTHelperGetProvSignerFromChainFn = (WTHELPERGETPROVSIGNERFROMCHAIN) GetProcAddress (hWinTrustLib, "WTHelperGetProvSignerFromChain"); - WTHelperGetProvCertFromChainFn = (WTHELPERGETPROVCERTFROMCHAIN) GetProcAddress (hWinTrustLib, "WTHelperGetProvCertFromChain"); - - if ( !WinVerifyTrustFn - || !WTHelperProvDataFromStateDataFn - || !WTHelperGetProvSignerFromChainFn - || !WTHelperGetProvCertFromChainFn) - { - FreeLibrary (hWinTrustLib); - hWinTrustLib = NULL; - } - - } - } - - if (hWinTrustLib) - return TRUE; - else - return FALSE; -} - -static void FinalizeWintrust() -{ - if (hWinTrustLib) - { - FreeLibrary (hWinTrustLib); - hWinTrustLib = NULL; - } -} - -#endif - -BOOL VerifyModuleSignature (const wchar_t* path) -{ -#if defined(NDEBUG) && !defined (VC_SKIP_OS_DRIVER_REQ_CHECK) - BOOL bResult = FALSE; - HRESULT hResult; - GUID gActionID = WINTRUST_ACTION_GENERIC_VERIFY_V2; - WINTRUST_FILE_INFO fileInfo = {0}; - WINTRUST_DATA WVTData = {0}; - wchar_t filePath [TC_MAX_PATH + 1024]; - - // we check our own authenticode signature only starting from Windows 10 since this is - // the minimal supported OS apart from XP where we can't verify SHA256 signatures - if (!IsOSAtLeast (WIN_10)) - return TRUE; - - // Strip quotation marks (if any) - if (path [0] == L'"') - { - StringCbCopyW (filePath, sizeof(filePath), path + 1); - } - else - { - StringCbCopyW (filePath, sizeof(filePath), path); - } - - // Strip quotation marks (if any) - if (filePath [wcslen (filePath) - 1] == L'"') - filePath [wcslen (filePath) - 1] = 0; - - if (!InitializeWintrust ()) - return FALSE; - - fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO); - fileInfo.pcwszFilePath = filePath; - fileInfo.hFile = NULL; - - WVTData.cbStruct = sizeof(WINTRUST_DATA); - WVTData.dwUIChoice = WTD_UI_NONE; - WVTData.fdwRevocationChecks = WTD_REVOKE_NONE; - WVTData.dwUnionChoice = WTD_CHOICE_FILE; - WVTData.pFile = &fileInfo; - WVTData.dwStateAction = WTD_STATEACTION_VERIFY; - WVTData.dwProvFlags = WTD_REVOCATION_CHECK_NONE | WTD_CACHE_ONLY_URL_RETRIEVAL; - - hResult = WinVerifyTrustFn(0, &gActionID, &WVTData); - if (0 == hResult) - { - PCRYPT_PROVIDER_DATA pProviderData = WTHelperProvDataFromStateDataFn (WVTData.hWVTStateData); - if (pProviderData) - { - PCRYPT_PROVIDER_SGNR pProviderSigner = WTHelperGetProvSignerFromChainFn (pProviderData, 0, FALSE, 0); - if (pProviderSigner) - { - PCRYPT_PROVIDER_CERT pProviderCert = WTHelperGetProvCertFromChainFn (pProviderSigner, 0); - if (pProviderCert && (pProviderCert->pCert)) - { - BYTE hashVal[64]; - sha512 (hashVal, pProviderCert->pCert->pbCertEncoded, pProviderCert->pCert->cbCertEncoded); - - if ( (0 == memcmp (hashVal, gpbSha256CodeSignCertFingerprint, 64)) - || (0 == memcmp (hashVal, gpbSha256MSCodeSignCertFingerprint, 64)) - ) - { - bResult = TRUE; - } - } - } - } - } - - WVTData.dwUIChoice = WTD_UI_NONE; - WVTData.dwStateAction = WTD_STATEACTION_CLOSE; - WinVerifyTrustFn(0, &gActionID, &WVTData); - - FinalizeWintrust (); - - return bResult; -#else - return TRUE; -#endif -} - void GetInstallationPath (HWND hwndDlg, wchar_t* szInstallPath, DWORD cchSize, BOOL* pbInstallPathDetermined) { HKEY hkey; @@ -15645,3 +15660,4 @@ bool OneOfKBsInstalled (const wchar_t* szKBs[], int count) return bRet; } +#endif // VC_COMREG \ No newline at end of file diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index 53be5177..5b964d4e 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -4790,15 +4790,101 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa else { int fileNo = 0; + BOOL bMsiX64Case = FALSE; // get file from the Setup binary after checking its signature and its version StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt COMReg.exe", appDir); // MSI installation case if (FileExists(srcPath)) { - // we copy only our binaries since we don't have those of the other platforms + bMsiX64Case = TRUE; + } + else + StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt Setup.exe", appDir); // EXE installation case + + FreeAllFileBuffers (); + + if (!VerifyPackageIntegrity (srcPath) || !SelfExtractInMemory (srcPath, TRUE) || (!bMsiX64Case && (Decompressed_Files_Count != NBR_COMPRESSED_FILES))) + { + MessageBoxW (hwndDlg, GetString ("DIST_PACKAGE_CORRUPTED"), lpszTitle, MB_ICONEXCLAMATION); + goto stop; + } + + for (fileNo = 0; fileNo < Decompressed_Files_Count; fileNo++) + { + wchar_t fileName [TC_MAX_PATH] = {0}; + + // Filename + StringCchCopyNW (fileName, ARRAYSIZE(fileName), Decompressed_Files[fileNo].fileName, Decompressed_Files[fileNo].fileNameLength); + if (wcscmp (fileName, L"VeraCrypt.exe") == 0) + { + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt.exe", dstDir); + } + else if (wcscmp (fileName, L"VeraCrypt-x64.exe") == 0) + { + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt-x64.exe", dstDir); + } + else if (wcscmp(fileName, L"VeraCrypt-arm64.exe") == 0) + { + StringCbPrintfW(dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt-arm64.exe", dstDir); + } + else if (wcscmp (fileName, L"veracrypt.sys") == 0) + { + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt.sys", dstDir); + } + else if (wcscmp (fileName, L"veracrypt-x64.sys") == 0) + { + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt-x64.sys", dstDir); + } + else if (wcscmp(fileName, L"veracrypt-arm64.sys") == 0) + { + StringCbPrintfW(dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt-arm64.sys", dstDir); + } + else if (copyWizard && (wcscmp (fileName, L"VeraCrypt Format.exe") == 0)) + { + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format.exe", dstDir); + } + else if (copyWizard && (wcscmp (fileName, L"VeraCrypt Format-x64.exe") == 0)) + { + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format-x64.exe", dstDir); + } + else if (copyWizard && (wcscmp(fileName, L"VeraCrypt Format-arm64.exe") == 0)) + { + StringCbPrintfW(dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format-arm64.exe", dstDir); + } + else if (copyExpander && (wcscmp (fileName, L"VeraCryptExpander.exe") == 0)) + { + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander.exe", dstDir); + } + else if (copyExpander && (wcscmp (fileName, L"VeraCryptExpander-x64.exe") == 0)) + { + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander-x64.exe", dstDir); + } + else if (copyExpander && (wcscmp(fileName, L"VeraCryptExpander-arm64.exe") == 0)) + { + StringCbPrintfW(dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander-arm64.exe", dstDir); + } + else + continue; + + if (!SaveBufferToFile ( + (char *) Decompressed_Files[fileNo].fileContent, + dstPath, + Decompressed_Files[fileNo].fileLength, + FALSE, FALSE)) + { + wchar_t szTmp[512]; + + StringCbPrintfW (szTmp, sizeof (szTmp), GetString ("CANNOT_WRITE_FILE_X"), dstPath); + MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); + goto stop; + } + } + + if (bMsiX64Case) + { // Main app StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt.exe", appDir); - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt.exe", dstDir); + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt-x64.exe", dstDir); if (!VerifyModuleSignature (srcPath)) { Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); @@ -4814,7 +4900,7 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa if (copyWizard) { StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt Format.exe", appDir); - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format.exe", dstDir); + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format-x64.exe", dstDir); if (!VerifyModuleSignature (srcPath)) { Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); @@ -4831,7 +4917,7 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa if (copyExpander) { StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCryptExpander.exe", appDir); - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander.exe", dstDir); + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander-x64.exe", dstDir); if (!VerifyModuleSignature (srcPath)) { Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); @@ -4846,7 +4932,7 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa // Driver StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\veracrypt.sys", appDir); - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt.sys", dstDir); + StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt-x64.sys", dstDir); if (!VerifyModuleSignature (srcPath)) { Error ("DIST_PACKAGE_CORRUPTED", hwndDlg); @@ -4858,90 +4944,6 @@ BOOL CALLBACK TravelerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa goto stop; } } - else - { - StringCbPrintfW (srcPath, sizeof(srcPath), L"%s\\VeraCrypt Setup.exe", appDir); // EXE installation case - - FreeAllFileBuffers (); - - if (!VerifyPackageIntegrity (srcPath) || !SelfExtractInMemory (srcPath)) - { - MessageBoxW (hwndDlg, GetString ("DIST_PACKAGE_CORRUPTED"), lpszTitle, MB_ICONEXCLAMATION); - goto stop; - } - - for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++) - { - wchar_t fileName [TC_MAX_PATH] = {0}; - - // Filename - StringCchCopyNW (fileName, ARRAYSIZE(fileName), Decompressed_Files[fileNo].fileName, Decompressed_Files[fileNo].fileNameLength); - - if (wcscmp (fileName, L"VeraCrypt.exe") == 0) - { - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt.exe", dstDir); - } - else if (wcscmp (fileName, L"VeraCrypt-x64.exe") == 0) - { - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt-x64.exe", dstDir); - } - else if (wcscmp(fileName, L"VeraCrypt-arm64.exe") == 0) - { - StringCbPrintfW(dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt-arm64.exe", dstDir); - } - else if (wcscmp (fileName, L"veracrypt.sys") == 0) - { - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt.sys", dstDir); - } - else if (wcscmp (fileName, L"veracrypt-x64.sys") == 0) - { - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt-x64.sys", dstDir); - } - else if (wcscmp(fileName, L"veracrypt-arm64.sys") == 0) - { - StringCbPrintfW(dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\veracrypt-arm64.sys", dstDir); - } - else if (copyWizard && (wcscmp (fileName, L"VeraCrypt Format.exe") == 0)) - { - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format.exe", dstDir); - } - else if (copyWizard && (wcscmp (fileName, L"VeraCrypt Format-x64.exe") == 0)) - { - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format-x64.exe", dstDir); - } - else if (copyWizard && (wcscmp(fileName, L"VeraCrypt Format-arm64.exe") == 0)) - { - StringCbPrintfW(dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCrypt Format-arm64.exe", dstDir); - } - else if (copyExpander && (wcscmp (fileName, L"VeraCryptExpander.exe") == 0)) - { - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander.exe", dstDir); - } - else if (copyExpander && (wcscmp (fileName, L"VeraCryptExpander-x64.exe") == 0)) - { - StringCbPrintfW (dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander-x64.exe", dstDir); - } - else if (copyExpander && (wcscmp(fileName, L"VeraCryptExpander-arm64.exe") == 0)) - { - StringCbPrintfW(dstPath, sizeof(dstPath), L"%s\\VeraCrypt\\VeraCryptExpander-arm64.exe", dstDir); - } - else - continue; - - if (!SaveBufferToFile ( - (char *) Decompressed_Files[fileNo].fileContent, - dstPath, - Decompressed_Files[fileNo].fileLength, - FALSE, FALSE)) - { - wchar_t szTmp[512]; - - StringCbPrintfW (szTmp, sizeof (szTmp), GetString ("CANNOT_WRITE_FILE_X"), dstPath); - MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); - goto stop; - } - } - } } if (strcmp (GetPreferredLangId (), "en") != 0) diff --git a/src/Setup/SelfExtract.c b/src/Setup/SelfExtract.c index 34fb0b25..acb2a625 100644 --- a/src/Setup/SelfExtract.c +++ b/src/Setup/SelfExtract.c @@ -32,8 +32,12 @@ #ifdef PORTABLE #define OutputPackageFile L"VeraCrypt Portable " _T(VERSION_STRING) _T(VERSION_STRING_SUFFIX)L".exe" #else +#ifdef VC_COMREG +#define OutputPackageFile L"VeraCrypt COMReg.exe" +#else #define OutputPackageFile L"VeraCrypt Setup " _T(VERSION_STRING) _T(VERSION_STRING_SUFFIX) L".exe" #endif +#endif #define MAG_START_MARKER "VCINSTRT" #define MAG_END_MARKER_OBFUSCATED "V/C/I/N/S/C/R/C" #define PIPE_BUFFER_LEN (4 * BYTES_PER_KB) @@ -41,6 +45,7 @@ unsigned char MagEndMarker [sizeof (MAG_END_MARKER_OBFUSCATED)]; wchar_t DestExtractPath [TC_MAX_PATH]; DECOMPRESSED_FILE Decompressed_Files [NBR_COMPRESSED_FILES]; +int Decompressed_Files_Count = 0; volatile char *PipeWriteBuf = NULL; volatile HANDLE hChildStdinWrite = INVALID_HANDLE_VALUE; @@ -119,7 +124,7 @@ static void WipeSignatureAreas (char *buffer) } -BOOL MakeSelfExtractingPackage (HWND hwndDlg, wchar_t *szDestDir) +BOOL MakeSelfExtractingPackage (HWND hwndDlg, wchar_t *szDestDir, BOOL bSkipX64) { int i, x; wchar_t inputFile [TC_MAX_PATH]; @@ -163,6 +168,17 @@ BOOL MakeSelfExtractingPackage (HWND hwndDlg, wchar_t *szDestDir) for (i = 0; i < sizeof (szCompressedFiles) / sizeof (szCompressedFiles[0]); i++) { + if (bSkipX64 && wcsstr(szCompressedFiles[i], L"-x64")) + continue; + +#ifdef VC_COMREG + if ( wcsstr(szCompressedFiles[i], L".zip") || wcsstr(szCompressedFiles[i], L".inf") + || wcsstr(szCompressedFiles[i], L".cat") || wcsstr(szCompressedFiles[i], L".txt") + || wcsstr(szCompressedFiles[i], L"LICENSE") || wcsstr(szCompressedFiles[i], L"NOTICE") + ) + continue; +#endif + StringCbPrintfW (szTmpFilePath, sizeof(szTmpFilePath), L"%s%s", szDestDir, szCompressedFiles[i]); if (!FileExists (szTmpFilePath)) @@ -215,6 +231,17 @@ BOOL MakeSelfExtractingPackage (HWND hwndDlg, wchar_t *szDestDir) DWORD tmpFileSize; unsigned char *tmpBuffer; + if (bSkipX64 && wcsstr(szCompressedFiles[i], L"-x64")) + continue; + +#ifdef VC_COMREG + if ( wcsstr(szCompressedFiles[i], L".zip") || wcsstr(szCompressedFiles[i], L".inf") + || wcsstr(szCompressedFiles[i], L".cat") || wcsstr(szCompressedFiles[i], L".txt") + || wcsstr(szCompressedFiles[i], L"LICENSE") || wcsstr(szCompressedFiles[i], L"NOTICE") + ) + continue; +#endif + StringCbPrintfW (szTmpFilePath, sizeof(szTmpFilePath), L"%s%s", szDestDir, szCompressedFiles[i]); tmpBuffer = LoadFile (szTmpFilePath, &tmpFileSize); @@ -485,6 +512,8 @@ void FreeAllFileBuffers (void) Decompressed_Files[fileNo].fileLength = 0; Decompressed_Files[fileNo].crc = 0; } + + Decompressed_Files_Count = 0; } @@ -492,7 +521,7 @@ void FreeAllFileBuffers (void) // 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 (wchar_t *path) +BOOL SelfExtractInMemory (wchar_t *path, BOOL bSkipCountCheck) { int filePos = 0, fileNo = 0; int fileDataEndPos = 0; @@ -548,7 +577,7 @@ BOOL SelfExtractInMemory (wchar_t *path) Error ("DIST_PACKAGE_CORRUPTED", NULL); } - decompressedDataLen = uncompressedLen + 524288; // + 512K reserve + decompressedDataLen = uncompressedLen; DecompressedData = malloc (decompressedDataLen); if (DecompressedData == NULL) { @@ -607,12 +636,14 @@ BOOL SelfExtractInMemory (wchar_t *path) fileNo++; } - if (fileNo < NBR_COMPRESSED_FILES) + if (!bSkipCountCheck && (fileNo < NBR_COMPRESSED_FILES)) { Error ("DIST_PACKAGE_CORRUPTED", NULL); goto sem_end; } + Decompressed_Files_Count = fileNo; + free (compressedData); return TRUE; @@ -635,7 +666,7 @@ void __cdecl ExtractAllFilesThread (void *hwndDlg) GetModuleFileName (NULL, packageFile, ARRAYSIZE (packageFile)); - if (!(bSuccess = SelfExtractInMemory (packageFile))) + if (!(bSuccess = SelfExtractInMemory (packageFile, FALSE))) goto eaf_end; if (mkfulldir (DestExtractPath, TRUE) != 0) diff --git a/src/Setup/SelfExtract.h b/src/Setup/SelfExtract.h index ed4b6655..bcdb6fdb 100644 --- a/src/Setup/SelfExtract.h +++ b/src/Setup/SelfExtract.h @@ -27,11 +27,12 @@ typedef struct } DECOMPRESSED_FILE; extern DECOMPRESSED_FILE Decompressed_Files [NBR_COMPRESSED_FILES]; +extern int Decompressed_Files_Count; void SelfExtractStartupInit (void); -BOOL SelfExtractInMemory (wchar_t *path); +BOOL SelfExtractInMemory (wchar_t *path, BOOL bSkipCountCheck); void __cdecl ExtractAllFilesThread (void *hwndDlg); -BOOL MakeSelfExtractingPackage (HWND hwndDlg, wchar_t *szDestDir); +BOOL MakeSelfExtractingPackage (HWND hwndDlg, wchar_t *szDestDir, BOOL bSkipX64); BOOL VerifyPackageIntegrity (const wchar_t *path); BOOL VerifySelfPackageIntegrity (void); BOOL IsSelfExtractingPackage (void); diff --git a/src/Setup/Setup.c b/src/Setup/Setup.c index 9f025ef0..fbc8a7d8 100644 --- a/src/Setup/Setup.c +++ b/src/Setup/Setup.c @@ -787,7 +787,7 @@ BOOL DoFilesInstall (HWND hwndDlg, wchar_t *szDestDir) GetModuleFileName (NULL, szTmp, ARRAYSIZE (szTmp)); - if (!SelfExtractInMemory (szTmp)) + if (!SelfExtractInMemory (szTmp, FALSE)) return FALSE; } @@ -2779,7 +2779,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpsz { /* Create self-extracting package */ - MakeSelfExtractingPackage (NULL, SetupFilesDir); + MakeSelfExtractingPackage (NULL, SetupFilesDir, FALSE); } else { diff --git a/src/Signing/sign.bat b/src/Signing/sign.bat index b5f3974f..e925048e 100644 --- a/src/Signing/sign.bat +++ b/src/Signing/sign.bat @@ -10,7 +10,7 @@ call "..\..\doc\chm\create_chm.bat" cd %SIGNINGPATH% rem sign using SHA-256 -signtool sign /v /sha1 88c1ff4b7469ea3915bd8e7635a7567d34f43202 /ac GlobalSign_SHA256_EV_CodeSigning_CA.cer /fd sha256 /tr http://timestamp.digicert.com /td SHA256 "..\Release\Setup Files\VeraCrypt.exe" "..\Release\Setup Files\VeraCrypt Format.exe" "..\Release\Setup Files\VeraCryptExpander.exe" "..\Release\Setup Files\VeraCrypt-x64.exe" "..\Release\Setup Files\VeraCrypt Format-x64.exe" "..\Release\Setup Files\VeraCryptExpander-x64.exe" "..\Release\Setup Files\VeraCrypt-arm64.exe" "..\Release\Setup Files\VeraCrypt Format-arm64.exe" "..\Release\Setup Files\VeraCryptExpander-arm64.exe" "..\Release\Setup Files\VeraCrypt COMReg.exe" "..\Release\Setup Files\VeraCryptSetup.dll" +signtool sign /v /sha1 88c1ff4b7469ea3915bd8e7635a7567d34f43202 /ac GlobalSign_SHA256_EV_CodeSigning_CA.cer /fd sha256 /tr http://timestamp.digicert.com /td SHA256 "..\Release\Setup Files\VeraCrypt.exe" "..\Release\Setup Files\VeraCrypt Format.exe" "..\Release\Setup Files\VeraCryptExpander.exe" "..\Release\Setup Files\VeraCrypt-x64.exe" "..\Release\Setup Files\VeraCrypt Format-x64.exe" "..\Release\Setup Files\VeraCryptExpander-x64.exe" "..\Release\Setup Files\VeraCrypt-arm64.exe" "..\Release\Setup Files\VeraCrypt Format-arm64.exe" "..\Release\Setup Files\VeraCryptExpander-arm64.exe" "..\Release\Setup Files\VeraCryptSetup.dll" rem create setup and MSI cd "..\Release\Setup Files\" @@ -38,6 +38,12 @@ del docs.zip 7z a -y docs.zip docs "VeraCrypt Setup.exe" /p "VeraCrypt Portable.exe" /p +VeraCryptCOMRegBase.exe /p + +cd %SIGNINGPATH% +signtool sign /v /sha1 88c1ff4b7469ea3915bd8e7635a7567d34f43202 /ac GlobalSign_SHA256_EV_CodeSigning_CA.cer /fd sha256 /tr http://timestamp.digicert.com /td SHA256 "..\Release\Setup Files\VeraCrypt COMReg.exe" + +cd "..\Release\Setup Files\" call build_msi_x64.bat %VC_VERSION_NBRE% del LICENSE del License.txt -- cgit v1.2.3