diff options
Diffstat (limited to 'src/Common/Dlgcode.c')
-rw-r--r-- | src/Common/Dlgcode.c | 2091 |
1 files changed, 1063 insertions, 1028 deletions
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index b137c57b..b91167d4 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -1,120 +1,127 @@ /* Legal Notice: Some portions of the source code contained in this file were derived from the source code of TrueCrypt 7.1a, which is Copyright (c) 2003-2012 TrueCrypt Developers Association and which is governed by the TrueCrypt License 3.0, also from the source code of Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License Agreement for Encryption for the Masses' Modifications and additions to the original source code (contained in this file) and all other portions of this file are Copyright (c) 2013-2017 IDRIX and are governed by the Apache License 2.0 the full text of which is contained in the file License.txt included in VeraCrypt binary and source code distribution packages. */ #include "Tcdefs.h" #include <windowsx.h> #include <dbghelp.h> #include <dbt.h> #include <Setupapi.h> #include <aclapi.h> +#include <Netlistmgr.h> #include <fcntl.h> #include <io.h> #include <math.h> #include <shlobj.h> #include <shlwapi.h> #include <sys/stat.h> #include <stdlib.h> #include <time.h> #include <tchar.h> #include <Richedit.h> #if defined (TCMOUNT) || defined (VOLFORMAT) #include <process.h> #include <Tlhelp32.h> #endif +#if _WIN32_WINNT >= 0x0602 +#include "processthreadsapi.h" +#endif #include "Resource.h" #include "Platform/Finally.h" #include "Platform/ForEach.h" #include "Apidrvr.h" #include "BootEncryption.h" #include "Combo.h" #include "Crc.h" #include "Crypto.h" #include "Dictionary.h" #include "Dlgcode.h" #include "EncryptionThreadPool.h" #include "Endian.h" #include "Format/Inplace.h" #include "Language.h" #include "Keyfiles.h" #include "Pkcs5.h" #include "Random.h" #include "Registry.h" #include "SecurityToken.h" #include "Tests.h" #include "Volumes.h" #include "Wipe.h" #include "Xml.h" #include "Xts.h" #include "Boot/Windows/BootCommon.h" #include "Progress.h" #include "zip.h" #include "rdrand.h" #include "jitterentropy.h" #ifdef TCMOUNT #include "Mount/Mount.h" #include "Mount/resource.h" #endif #ifdef VOLFORMAT #include "Format/Tcformat.h" #endif #ifdef SETUP #include "Setup/Setup.h" #endif #include <Setupapi.h> #include <Softpub.h> #include <WinTrust.h> #include <strsafe.h> #define _WIN32_DCOM #include <comdef.h> #include <Wbemidl.h> #pragma comment(lib, "wbemuuid.lib") -#pragma comment( lib, "setupapi.lib" ) +#pragma comment(lib, "Shlwapi.lib") +#pragma comment(lib, "setupapi.lib" ) +#pragma comment(lib, "Wintrust.lib" ) +#pragma comment(lib, "Comctl32.lib" ) #ifndef TTI_INFO_LARGE #define TTI_INFO_LARGE 4 #endif #ifndef TTI_WARNING_LARGE #define TTI_WARNING_LARGE 5 #endif #ifndef TTI_ERROR_LARGE #define TTI_ERROR_LARGE 6 #endif /* GPT Partition Type GUIDs */ #define LOCAL_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID name = {l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8} LOCAL_DEFINE_GUID(PARTITION_ENTRY_UNUSED_GUID, 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); // Entry unused LOCAL_DEFINE_GUID(PARTITION_SYSTEM_GUID, 0xC12A7328L, 0xF81F, 0x11D2, 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B); // EFI system partition LOCAL_DEFINE_GUID(PARTITION_MSFT_RESERVED_GUID, 0xE3C9E316L, 0x0B5C, 0x4DB8, 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE); // Microsoft reserved space LOCAL_DEFINE_GUID(PARTITION_BASIC_DATA_GUID, 0xEBD0A0A2L, 0xB9E5, 0x4433, 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7); // Basic data partition LOCAL_DEFINE_GUID(PARTITION_LDM_METADATA_GUID, 0x5808C8AAL, 0x7E8F, 0x42E0, 0x85, 0xD2, 0xE1, 0xE9, 0x04, 0x34, 0xCF, 0xB3); // Logical Disk Manager metadata partition LOCAL_DEFINE_GUID(PARTITION_LDM_DATA_GUID, 0xAF9B60A0L, 0x1431, 0x4F62, 0xBC, 0x68, 0x33, 0x11, 0x71, 0x4A, 0x69, 0xAD); // Logical Disk Manager data partition LOCAL_DEFINE_GUID(PARTITION_MSFT_RECOVERY_GUID, 0xDE94BBA4L, 0x06D1, 0x4D40, 0xA1, 0x6A, 0xBF, 0xD5, 0x01, 0x79, 0xD6, 0xAC); // Microsoft recovery partition LOCAL_DEFINE_GUID(PARTITION_CLUSTER_GUID, 0xdb97dba9L, 0x0840, 0x4bae, 0x97, 0xf0, 0xff, 0xb9, 0xa3, 0x27, 0xc7, 0xe1); // Cluster metadata partition #ifndef PROCESSOR_ARCHITECTURE_ARM64 #define PROCESSOR_ARCHITECTURE_ARM64 12 #endif #ifndef IMAGE_FILE_MACHINE_ARM64 #define IMAGE_FILE_MACHINE_ARM64 0xAA64 @@ -186,60 +193,62 @@ int HiddenSectorDetectionStatus = 0; OSVersionEnum nCurrentOS = WIN_UNKNOWN; int CurrentOSMajor = 0; int CurrentOSMinor = 0; int CurrentOSServicePack = 0; int CurrentOSBuildNumber = 0; BOOL RemoteSession = FALSE; BOOL UacElevated = FALSE; BOOL bPortableModeConfirmed = FALSE; // TRUE if it is certain that the instance is running in portable mode BOOL bInPlaceEncNonSysPending = FALSE; // TRUE if the non-system in-place encryption config file indicates that one or more partitions are scheduled to be encrypted. This flag is set only when config files are loaded during app startup. /* Globals used by Mount and Format (separately per instance) */ BOOL PimEnable = FALSE; BOOL KeyFilesEnable = FALSE; KeyFile *FirstKeyFile = NULL; KeyFilesDlgParam defaultKeyFilesParam = {0}; BOOL IgnoreWmDeviceChange = FALSE; BOOL DeviceChangeBroadcastDisabled = FALSE; BOOL LastMountedVolumeDirty; BOOL MountVolumesAsSystemFavorite = FALSE; BOOL FavoriteMountOnArrivalInProgress = FALSE; BOOL MultipleMountOperationInProgress = FALSE; BOOL EMVSupportEnabled = FALSE; volatile BOOL NeedPeriodicDeviceListUpdate = FALSE; BOOL DisablePeriodicDeviceListUpdate = FALSE; BOOL EnableMemoryProtection = FALSE; +BOOL MemoryProtectionActivated = FALSE; + BOOL WaitDialogDisplaying = FALSE; /* Handle to the device driver */ HANDLE hDriver = INVALID_HANDLE_VALUE; /* This mutex is used to prevent multiple instances of the wizard or main app from dealing with system encryption */ volatile HANDLE hSysEncMutex = NULL; /* This mutex is used for non-system in-place encryption but only for informative (non-blocking) purposes, such as whether an app should prompt the user whether to resume scheduled process. */ volatile HANDLE hNonSysInplaceEncMutex = NULL; /* This mutex is used to prevent multiple instances of the wizard or main app from trying to install or register the driver or from trying to launch it in portable mode at the same time. */ volatile HANDLE hDriverSetupMutex = NULL; /* This mutex is used to prevent users from running the main TrueCrypt app or the wizard while an instance of the TrueCrypt installer is running (which is also useful for enforcing restart before the apps can be used). */ volatile HANDLE hAppSetupMutex = NULL; /* Critical section used to protect access to global variables used in WNetGetConnection calls */ CRITICAL_SECTION csWNetCalls; /* Critical section used to protect access to global list of physical drives */ CRITICAL_SECTION csMountableDevices; CRITICAL_SECTION csVolumeIdCandidates; static std::vector<HostDevice> mountableDevices; static std::vector<HostDevice> rawHostDeviceList; @@ -258,218 +267,84 @@ ATOM hDlgClass, hSplashClass; /* This value may changed only by calling ChangeSystemEncryptionStatus(). Only the wizard can change it (others may still read it though). */ int SystemEncryptionStatus = SYSENC_STATUS_NONE; /* Only the wizard can change this value (others may only read it). */ WipeAlgorithmId nWipeMode = TC_WIPE_NONE; BOOL bSysPartitionSelected = FALSE; /* TRUE if the user selected the system partition via the Select Device dialog */ BOOL bSysDriveSelected = FALSE; /* TRUE if the user selected the system drive via the Select Device dialog */ /* To populate these arrays, call GetSysDevicePaths(). If they contain valid paths, bCachedSysDevicePathsValid is TRUE. */ wchar_t SysPartitionDevicePath [TC_MAX_PATH]; wchar_t SysDriveDevicePath [TC_MAX_PATH]; wstring ExtraBootPartitionDevicePath; char bCachedSysDevicePathsValid = FALSE; BOOL bHyperLinkBeingTracked = FALSE; int WrongPwdRetryCounter = 0; static FILE *ConfigFileHandle; char *ConfigBuffer; BOOL SystemFileSelectorCallPending = FALSE; DWORD SystemFileSelectorCallerThreadId; #define RANDPOOL_DISPLAY_REFRESH_INTERVAL 30 #define RANDPOOL_DISPLAY_ROWS 16 #define RANDPOOL_DISPLAY_COLUMNS 20 -HMODULE hRichEditDll = NULL; -HMODULE hComctl32Dll = NULL; -HMODULE hSetupDll = NULL; -HMODULE hShlwapiDll = NULL; -HMODULE hProfApiDll = NULL; -HMODULE hUsp10Dll = NULL; -HMODULE hCryptSpDll = NULL; -HMODULE hUXThemeDll = NULL; -HMODULE hUserenvDll = NULL; -HMODULE hRsaenhDll = NULL; -HMODULE himm32dll = NULL; -HMODULE hMSCTFdll = NULL; -HMODULE hfltlibdll = NULL; -HMODULE hframedyndll = NULL; -HMODULE hpsapidll = NULL; -HMODULE hsecur32dll = NULL; -HMODULE hnetapi32dll = NULL; -HMODULE hauthzdll = NULL; -HMODULE hxmllitedll = NULL; -HMODULE hmprdll = NULL; -HMODULE hsppdll = NULL; -HMODULE vssapidll = NULL; -HMODULE hvsstracedll = NULL; -HMODULE hcfgmgr32dll = NULL; -HMODULE hdevobjdll = NULL; -HMODULE hpowrprofdll = NULL; -HMODULE hsspiclidll = NULL; -HMODULE hcryptbasedll = NULL; -HMODULE hdwmapidll = NULL; -HMODULE hmsasn1dll = NULL; -HMODULE hcrypt32dll = NULL; -HMODULE hbcryptdll = NULL; -HMODULE hbcryptprimitivesdll = NULL; -HMODULE hMsls31 = NULL; -HMODULE hntmartadll = NULL; -HMODULE hwinscarddll = NULL; -HMODULE hmsvcrtdll = NULL; -HMODULE hWinTrustLib = NULL; -HMODULE hAdvapi32Dll = NULL; - -#define FREE_DLL(h) if (h) { FreeLibrary (h); h = NULL;} - -#ifndef BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE -#define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE 0x00000001 -#endif - -#ifndef BASE_SEARCH_PATH_PERMANENT -#define BASE_SEARCH_PATH_PERMANENT 0x00008000 -#endif #ifndef LOAD_LIBRARY_SEARCH_SYSTEM32 #define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 #endif - -typedef BOOL (WINAPI *SetDllDirectoryPtr)(LPCWSTR lpPathName); -typedef BOOL (WINAPI *SetSearchPathModePtr)(DWORD Flags); typedef BOOL (WINAPI *SetDefaultDllDirectoriesPtr)(DWORD DirectoryFlags); - -typedef void (WINAPI *InitCommonControlsPtr)(void); -typedef HIMAGELIST (WINAPI *ImageList_CreatePtr)(int cx, int cy, UINT flags, int cInitial, int cGrow); -typedef int (WINAPI *ImageList_AddPtr)(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask); - -typedef VOID (WINAPI *SetupCloseInfFilePtr)(HINF InfHandle); -typedef HKEY (WINAPI *SetupDiOpenClassRegKeyPtr)(CONST GUID *ClassGuid,REGSAM samDesired); -typedef BOOL (WINAPI *SetupInstallFromInfSectionWPtr)(HWND,HINF,PCWSTR,UINT,HKEY,PCWSTR,UINT,PSP_FILE_CALLBACK_W,PVOID,HDEVINFO,PSP_DEVINFO_DATA); -typedef HINF (WINAPI *SetupOpenInfFileWPtr)(PCWSTR FileName,PCWSTR InfClass,DWORD InfStyle,PUINT ErrorLine); - -typedef LSTATUS (STDAPICALLTYPE *SHDeleteKeyWPtr)(HKEY hkey, LPCWSTR pszSubKey); - -typedef HRESULT (STDAPICALLTYPE *SHStrDupWPtr)(LPCWSTR psz, LPWSTR *ppwsz); - -typedef HRESULT (STDAPICALLTYPE *UrlUnescapeWPtr)( - PWSTR pszUrl, - PWSTR pszUnescaped, - DWORD *pcchUnescaped, - DWORD dwFlags -); - -// ChangeWindowMessageFilter -typedef BOOL (WINAPI *ChangeWindowMessageFilterPtr) (UINT, DWORD); - -typedef BOOL (WINAPI *CreateProcessWithTokenWFn)( - __in HANDLE hToken, - __in DWORD dwLogonFlags, - __in_opt LPCWSTR lpApplicationName, - __inout_opt LPWSTR lpCommandLine, - __in DWORD dwCreationFlags, - __in_opt LPVOID lpEnvironment, - __in_opt LPCWSTR lpCurrentDirectory, - __in LPSTARTUPINFOW lpStartupInfo, - __out LPPROCESS_INFORMATION lpProcessInformation - ); - -typedef HRESULT (WINAPI *IUnknown_QueryServiceFn)( - __in IUnknown* punk, - __in REFGUID guidService, - __in REFIID riid, - __deref_out void ** ppvOut); - -SetDllDirectoryPtr SetDllDirectoryFn = NULL; -SetSearchPathModePtr SetSearchPathModeFn = NULL; -SetDefaultDllDirectoriesPtr SetDefaultDllDirectoriesFn = NULL; - -ImageList_CreatePtr ImageList_CreateFn = NULL; -ImageList_AddPtr ImageList_AddFn = NULL; - -SetupCloseInfFilePtr SetupCloseInfFileFn = NULL; -SetupDiOpenClassRegKeyPtr SetupDiOpenClassRegKeyFn = NULL; -SetupInstallFromInfSectionWPtr SetupInstallFromInfSectionWFn = NULL; -SetupOpenInfFileWPtr SetupOpenInfFileWFn = NULL; -SHDeleteKeyWPtr SHDeleteKeyWFn = NULL; -SHStrDupWPtr SHStrDupWFn = NULL; -UrlUnescapeWPtr UrlUnescapeWFn = NULL; -ChangeWindowMessageFilterPtr ChangeWindowMessageFilterFn = NULL; -CreateProcessWithTokenWFn CreateProcessWithTokenWPtr = NULL; -IUnknown_QueryServiceFn IUnknown_QueryServicePtr = NULL; - -typedef LONG (WINAPI *WINVERIFYTRUST)(HWND hwnd, GUID *pgActionID, LPVOID pWVTData); -typedef CRYPT_PROVIDER_DATA* (WINAPI *WTHELPERPROVDATAFROMSTATEDATA)(HANDLE hStateData); -typedef CRYPT_PROVIDER_SGNR* (WINAPI *WTHELPERGETPROVSIGNERFROMCHAIN)(CRYPT_PROVIDER_DATA *pProvData, - DWORD idxSigner, - BOOL fCounterSigner, - DWORD idxCounterSigner); -typedef CRYPT_PROVIDER_CERT* (WINAPI *WTHELPERGETPROVCERTFROMCHAIN)(CRYPT_PROVIDER_SGNR *pSgnr, - DWORD idxCert); - -static WINVERIFYTRUST WinVerifyTrustFn = NULL; -static WTHELPERPROVDATAFROMSTATEDATA WTHelperProvDataFromStateDataFn = NULL; -static WTHELPERGETPROVSIGNERFROMCHAIN WTHelperGetProvSignerFromChainFn = NULL; -static WTHELPERGETPROVCERTFROMCHAIN WTHelperGetProvCertFromChainFn = NULL; - static unsigned char gpbSha512CodeSignCertFingerprint[64] = { 0x9C, 0xA0, 0x21, 0xD3, 0x7C, 0x90, 0x61, 0x88, 0xEF, 0x5F, 0x99, 0x3D, 0x54, 0x9F, 0xB8, 0xCE, 0x72, 0x32, 0x4F, 0x57, 0x4F, 0x19, 0xD2, 0xA4, 0xDC, 0x84, 0xFF, 0xE2, 0x84, 0x2B, 0xD4, 0x30, 0xAB, 0xA7, 0xE4, 0x63, 0x18, 0xD1, 0xD8, 0x32, 0x0E, 0xA4, 0x81, 0x3C, 0x19, 0xBF, 0x13, 0x11, 0xA4, 0x37, 0xD6, 0xDB, 0x26, 0xBA, 0xDC, 0x8F, 0x86, 0x96, 0x55, 0x96, 0xDB, 0x6F, 0xC0, 0x62 }; static unsigned char gpbSha512MSCodeSignCertFingerprint[64] = { 0xEB, 0x76, 0x2E, 0xD3, 0x5B, 0x4A, 0xB1, 0x0E, 0xF5, 0x3B, 0x99, 0x4E, 0xC1, 0xF7, 0x48, 0x88, 0xF6, 0xA0, 0xE9, 0xAC, 0x32, 0x69, 0xCF, 0x20, 0xE1, 0x60, 0xC4, 0x0C, 0xEF, 0x01, 0x1F, 0xCB, 0x41, 0x95, 0x72, 0xB9, 0xED, 0x63, 0x0C, 0x6B, 0xB9, 0xE9, 0xA2, 0x72, 0xA6, 0x78, 0x96, 0x4C, 0x69, 0x9F, 0x90, 0x3F, 0xB1, 0x3C, 0x64, 0xF2, 0xAB, 0xCF, 0x14, 0x1D, 0xEC, 0x7C, 0xB0, 0xC7 }; - -typedef HRESULT (WINAPI *SHGETKNOWNFOLDERPATH) ( - _In_ REFKNOWNFOLDERID rfid, - _In_ DWORD dwFlags, - _In_opt_ HANDLE hToken, - _Out_ PWSTR *ppszPath -); - /* Windows dialog class */ #define WINDOWS_DIALOG_CLASS L"#32770" /* Custom class names */ #define TC_DLG_CLASS L"VeraCryptCustomDlg" #define TC_SPLASH_CLASS L"VeraCryptSplashDlg" /* constant used by ChangeWindowMessageFilter calls */ #ifndef MSGFLT_ADD #define MSGFLT_ADD 1 #endif /* undocumented message sent during drag-n-drop */ #ifndef WM_COPYGLOBALDATA #define WM_COPYGLOBALDATA 0x0049 #endif /* Benchmarks */ #ifndef SETUP #define BENCHMARK_MAX_ITEMS 100 #define BENCHMARK_DEFAULT_BUF_SIZE BYTES_PER_MB #define HASH_FNC_BENCHMARKS FALSE // For development purposes only. Must be FALSE when building a public release. #define PKCS5_BENCHMARKS FALSE // For development purposes only. Must be FALSE when building a public release. #if PKCS5_BENCHMARKS && HASH_FNC_BENCHMARKS #error PKCS5_BENCHMARKS and HASH_FNC_BENCHMARKS are both TRUE (at least one of them should be FALSE). #endif enum @@ -946,184 +821,131 @@ BOOL TCCopyFileBase (HANDLE src, HANDLE dst) 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); + hResult = WinVerifyTrust(0, &gActionID, &WVTData); if (0 == hResult) { - PCRYPT_PROVIDER_DATA pProviderData = WTHelperProvDataFromStateDataFn (WVTData.hWVTStateData); + PCRYPT_PROVIDER_DATA pProviderData = WTHelperProvDataFromStateData (WVTData.hWVTStateData); if (pProviderData) { - PCRYPT_PROVIDER_SGNR pProviderSigner = WTHelperGetProvSignerFromChainFn (pProviderData, 0, FALSE, 0); + PCRYPT_PROVIDER_SGNR pProviderSigner = WTHelperGetProvSignerFromChain (pProviderData, 0, FALSE, 0); if (pProviderSigner) { - PCRYPT_PROVIDER_CERT pProviderCert = WTHelperGetProvCertFromChainFn (pProviderSigner, 0); + PCRYPT_PROVIDER_CERT pProviderCert = WTHelperGetProvCertFromChain (pProviderSigner, 0); if (pProviderCert && (pProviderCert->pCert)) { BYTE hashVal[64]; sha512 (hashVal, pProviderCert->pCert->pbCertEncoded, pProviderCert->pCert->cbCertEncoded); if ( (0 == memcmp (hashVal, gpbSha512CodeSignCertFingerprint, 64)) || (0 == memcmp (hashVal, gpbSha512MSCodeSignCertFingerprint, 64)) ) { bResult = TRUE; } } } } } WVTData.dwUIChoice = WTD_UI_NONE; WVTData.dwStateAction = WTD_STATEACTION_CLOSE; - WinVerifyTrustFn(0, &gActionID, &WVTData); - - FinalizeWintrust (); + WinVerifyTrust(0, &gActionID, &WVTData); 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, @@ -1338,159 +1160,78 @@ void InitOSVersionInfo () } #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); InitializeCriticalSection (&csMountableDevices); InitializeCriticalSection (&csVolumeIdCandidates); InitializeCriticalSection (&csSecureDesktop); } void FinalizeGlobalLocks () { DeleteCriticalSection (&csWNetCalls); DeleteCriticalSection (&csMountableDevices); DeleteCriticalSection (&csVolumeIdCandidates); DeleteCriticalSection (&csSecureDesktop); } void cleanup () { burn (&CmdTokenPin, sizeof (CmdTokenPin)); #ifndef SETUP KeyFileRemoveAll (&FirstKeyFile); KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); #endif /* Cleanup the GDI fonts */ if (hFixedFont != NULL) @@ -1992,60 +1733,142 @@ void AccommodateTextField (HWND hwndDlg, UINT ctrlId, BOOL bFirstUpdate, HFONT h alignPosDiff = horizSubOffset / 2; else if (windowInfo.dwStyle & SS_RIGHT) alignPosDiff = horizSubOffset; // Resize/move if (alignPosDiff > 0) { // Resize and move the text field MoveWindow (hwndCtrl, rec.left - wrec.left - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CXFIXEDFRAME)) + alignPosDiff, rec.top - wrec.top - vertOffset, origWidth - horizSubOffset, origHeight - vertSubOffset, TRUE); } else { // Resize the text field SetWindowPos (hwndCtrl, 0, 0, 0, origWidth - horizSubOffset, origHeight - vertSubOffset, SWP_NOMOVE | SWP_NOZORDER); } SetWindowPos (hwndCtrl, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); InvalidateRect (hwndCtrl, NULL, TRUE); } } +// Resizes width of a checkbox according to actual width in pixels of its label text (font size is taken into account) +void AccommodateCheckBoxTextWidth (HWND hwndDlg, UINT ctrlId) +{ + RECT rec; + HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); + int width, origWidth, origHeight; + int horizSubOffset; + wchar_t text [MAX_URL_LENGTH]; + HFONT hFont = (HFONT) SendDlgItemMessage (hwndDlg, ctrlId, WM_GETFONT, 0, 0); + + // Resize the field according to its length and font size and move if centered or right-aligned + + GetWindowTextW (hwndCtrl, text, sizeof (text) / sizeof (wchar_t)); + + width = GetTextGfxWidth (hwndCtrl, text, hFont); + + // add to width variable value the width of the checkbox square. We use SM_CXMENUCHECK which is a little larger than actual width + width += GetSystemMetrics(SM_CXMENUCHECK); + + + GetClientRect (hwndCtrl, &rec); + origWidth = rec.right; + origHeight = rec.bottom; + + if (width >= 0 + && (origWidth > width)) // The original width of the field is the maximum allowed size + { + horizSubOffset = origWidth - width; + + // Resize the text field + SetWindowPos (hwndCtrl, 0, 0, 0, + origWidth - horizSubOffset, + origHeight, + SWP_NOMOVE | SWP_NOZORDER); + + InvalidateRect (hwndCtrl, NULL, TRUE); + } +} + +// makes controls contiguous by moving the second control right next to the first one horizontally +void MakeControlsContiguous(HWND hwndDlg, UINT ctrl1ID, UINT ctrl2ID) { + HWND hwndCtrl1 = GetDlgItem(hwndDlg, ctrl1ID); + HWND hwndCtrl2 = GetDlgItem(hwndDlg, ctrl2ID); + RECT rect1, rect2; + POINT pt1, pt2; + int newLeftPosition; + + // Exit silently if one or both controls are missing + if (!hwndCtrl1 || !hwndCtrl2) { + return; + } + + + GetWindowRect(hwndCtrl1, &rect1); + GetWindowRect(hwndCtrl2, &rect2); + + // Convert the top-right point of the first control from screen to client coordinates + pt1.x = rect1.right; + pt1.y = rect1.top; + if (!ScreenToClient(hwndDlg, &pt1)) { + return; // Exit if the conversion fails + } + + // Convert the top-left point of the second control from screen to client coordinates + pt2.x = rect2.left; + pt2.y = rect2.top; + if (!ScreenToClient(hwndDlg, &pt2)) { + return; // Exit if the conversion fails + } + + // Ensure the second control is always placed to the right of the first one + newLeftPosition = pt1.x + 1; + + if (pt2.x < pt1.x) { // if the second control is to the left of the first one + newLeftPosition += (pt1.x - pt2.x); + } + + // Move the second control to its new position + SetWindowPos(hwndCtrl2, NULL, newLeftPosition, pt2.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); +} + + // Note that the user can still close the window by right-clicking its taskbar icon and selecting 'Close window', or by pressing Alt-F4, or using the Task Manager. void DisableCloseButton (HWND hwndDlg) { EnableMenuItem (GetSystemMenu (hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); } void EnableCloseButton (HWND hwndDlg) { EnableMenuItem (GetSystemMenu (hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_ENABLED); } void HandlePasswordEditWmChar (HWND hwnd, WPARAM wParam) { DWORD dwStartPos = 0, dwEndPos = 0; short vk = VkKeyScanW ((WCHAR) wParam); BYTE vkCode = LOBYTE (vk); BYTE vkState = HIBYTE (vk); bool ctrlPressed = (vkState & 2) && !(vkState & 4); int dwMaxPassLen = (int) SendMessage (hwnd, EM_GETLIMITTEXT, 0, 0); // check if there is a selected text SendMessage (hwnd, EM_GETSEL, (WPARAM) &dwStartPos, (LPARAM) &dwEndPos); if ((dwStartPos == dwEndPos) && (vkCode != VK_DELETE) && (vkCode != VK_BACK) && !ctrlPressed && (GetWindowTextLength (hwnd) == dwMaxPassLen)) { EDITBALLOONTIP ebt; @@ -2306,116 +2129,152 @@ BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam 0, 0, 0, 0, FALSE, TRUE); SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } // Version SendMessage (GetDlgItem (hwndDlg, IDT_ABOUT_VERSION), WM_SETFONT, (WPARAM) hUserBoldFont, 0); StringCbPrintfW (szTmp, sizeof(szTmp), L"VeraCrypt %s", _T(VERSION_STRING) _T(VERSION_STRING_SUFFIX)); #ifdef _WIN64 StringCbCatW (szTmp, sizeof(szTmp), L" (64-bit)"); #else StringCbCatW (szTmp, sizeof(szTmp), L" (32-bit)"); #endif #if (defined(_DEBUG) || defined(DEBUG)) StringCbCatW (szTmp, sizeof(szTmp), L" (debug)"); #endif SetDlgItemText (hwndDlg, IDT_ABOUT_VERSION, szTmp); SetDlgItemText (hwndDlg, IDT_ABOUT_RELEASE, TC_STR_RELEASED_BY); // Credits SendMessage (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS), WM_SETFONT, (WPARAM) hUserFont, (LPARAM) 0); SendMessage (hwndDlg, WM_APP, 0, 0); return 1; } case WM_APP: SetWindowText (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS), L"Based on TrueCrypt 7.1a, freely available at http://www.truecrypt.org/ .\r\n\r\n" L"Portions of this software:\r\n" - L"Copyright \xA9 2013-2023 IDRIX. All rights reserved.\r\n" + L"Copyright \xA9 2013-2024 IDRIX. All rights reserved.\r\n" L"Copyright \xA9 2003-2012 TrueCrypt Developers Association. All Rights Reserved.\r\n" L"Copyright \xA9 1998-2000 Paul Le Roux. All Rights Reserved.\r\n" L"Copyright \xA9 1998-2008 Brian Gladman. All Rights Reserved.\r\n" - L"Copyright \xA9 1995-2017 Jean-loup Gailly and Mark Adler.\r\n" + L"Copyright \xA9 1995-2023 Jean-loup Gailly and Mark Adler.\r\n" L"Copyright \xA9 2016 Disk Cryptography Services for EFI (DCS), Alex Kolotnikov.\r\n" - L"Copyright \xA9 1999-2020 Dieter Baron and Thomas Klausner.\r\n" + L"Copyright \xA9 1999-2023 Dieter Baron and Thomas Klausner.\r\n" L"Copyright \xA9 2013, Alexey Degtyarev. All rights reserved.\r\n" L"Copyright \xA9 1999-2016 Jack Lloyd. All rights reserved.\r\n" L"Copyright \xA9 2013-2019 Stephan Mueller <smueller@chronox.de>\r\n" - L"Copyright \xA9 1999-2021 Igor Pavlov\r\n\r\n" + L"Copyright \xA9 1999-2023 Igor Pavlov\r\n\r\n" L"This software as a whole:\r\n" - L"Copyright \xA9 2013-2023 IDRIX. All rights reserved.\r\n\r\n" + L"Copyright \xA9 2013-2024 IDRIX. All rights reserved.\r\n\r\n" L"An IDRIX Release"); return 1; case WM_COMMAND: if (lw == IDOK || lw == IDCANCEL) { PostMessage (hwndDlg, WM_CLOSE, 0, 0); return 1; } if (lw == IDC_HOMEPAGE) { Applink ("main"); return 1; } // Disallow modification of credits if (HIWORD (wParam) == EN_UPDATE) { SendMessage (hwndDlg, WM_APP, 0, 0); return 1; } return 0; case WM_CLOSE: /* Delete buffered bitmaps (if any) */ if (hbmTextualLogoBitmapRescaled != NULL) { DeleteObject ((HGDIOBJ) hbmTextualLogoBitmapRescaled); hbmTextualLogoBitmapRescaled = NULL; } EndDialog (hwndDlg, 0); return 1; } return 0; } +HWND CreateToolTip(int toolID, HWND hDlg, const char* strID) +{ + if (!toolID || !hDlg) + { + return FALSE; + } + + // Create the tooltip. + HWND hwndTip = CreateWindowExW(NULL, TOOLTIPS_CLASS, NULL, + WS_POPUP | TTS_ALWAYSTIP | TTS_NOPREFIX | TTS_BALLOON, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + hDlg, NULL, + hInst, NULL); + + if (!hwndTip) + { + return (HWND)NULL; + } + + // Associate the tooltip with the tool. + TOOLINFOW toolInfo = { 0 }; + toolInfo.cbSize = sizeof(toolInfo); + toolInfo.hwnd = hDlg; + toolInfo.uFlags = TTF_SUBCLASS | TTF_IDISHWND; + toolInfo.uId = (UINT_PTR) GetDlgItem(hDlg, toolID); + toolInfo.lpszText = GetString(strID); + + // set tooltip maximum width + SendMessage(hwndTip, TTM_SETMAXTIPWIDTH, 0, (LPARAM) 300); + + SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo); + + return hwndTip; +} + static HWND StaticModelessWaitDlgHandle = NULL; // Call DisplayStaticModelessWaitDlg() to open this dialog and CloseStaticModelessWaitDlg() to close it. static BOOL CALLBACK StaticModelessWaitDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); switch (msg) { case WM_INITDIALOG: { LocalizeDialog (hwndDlg, NULL); return 0; } case WM_COMMAND: if (lw == IDOK || lw == IDCANCEL) return 1; return 0; case WM_CLOSE: StaticModelessWaitDlgHandle = NULL; EndDialog (hwndDlg, 0); return 1; } @@ -2481,61 +2340,61 @@ void LeftPadString (wchar_t *szTmp, int len, int targetLen, wchar_t filler) be called only once in the dialogs WM_INITDIALOG message handler */ void InitDialog (HWND hwndDlg) { NONCLIENTMETRICSW metric; static BOOL aboutMenuAppended = FALSE; int nHeight; LOGFONTW lf; HMENU hMenu; Font *font; /* Fonts */ memset (&lf, 0, sizeof(lf)); // Normal font = GetFont ("font_normal"); metric.cbSize = sizeof (metric); SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(metric), &metric, 0); WindowTitleBarFont = CreateFontIndirectW (&metric.lfCaptionFont); metric.lfMessageFont.lfHeight = CompensateDPIFont (!font ? -11 : -font->Size); metric.lfMessageFont.lfWidth = 0; if (font && wcscmp (font->FaceName, L"default") != 0) { StringCbCopyW ((WCHAR *)metric.lfMessageFont.lfFaceName, sizeof (metric.lfMessageFont.lfFaceName), font->FaceName); } - else if (IsOSAtLeast (WIN_VISTA)) + else { // Vista's new default font (size and spacing) breaks compatibility with Windows 2k/XP applications. // Force use of Tahoma (as Microsoft does in many dialogs) until a native Vista look is implemented. StringCbCopyW ((WCHAR *)metric.lfMessageFont.lfFaceName, sizeof (metric.lfMessageFont.lfFaceName), L"Tahoma"); } hUserFont = CreateFontIndirectW (&metric.lfMessageFont); metric.lfMessageFont.lfUnderline = TRUE; hUserUnderlineFont = CreateFontIndirectW (&metric.lfMessageFont); metric.lfMessageFont.lfUnderline = FALSE; metric.lfMessageFont.lfWeight = FW_BOLD; hUserBoldFont = CreateFontIndirectW (&metric.lfMessageFont); metric.lfMessageFont.lfUnderline = TRUE; metric.lfMessageFont.lfWeight = FW_BOLD; hUserUnderlineBoldFont = CreateFontIndirectW (&metric.lfMessageFont); // Fixed-size (hexadecimal digits) nHeight = CompensateDPIFont (-12); lf.lfHeight = nHeight; lf.lfWidth = 0; lf.lfEscapement = 0; lf.lfOrientation = 0; lf.lfWeight = FW_NORMAL; lf.lfItalic = FALSE; lf.lfUnderline = FALSE; lf.lfStrikeOut = FALSE; lf.lfCharSet = DEFAULT_CHARSET; @@ -2998,61 +2857,61 @@ wchar_t *GetPathType (const wchar_t *path, BOOL bUpperCase, BOOL *bIsPartition) && wcsstr (path, L"Partition0") == NULL) { *bIsPartition = TRUE; return GetString (bUpperCase ? "PARTITION_UPPER_CASE" : "PARTITION_LOWER_CASE"); } else if (wcsstr (path, L"HarddiskVolume")) { *bIsPartition = TRUE; return GetString (bUpperCase ? "VOLUME_UPPER_CASE" : "VOLUME_LOWER_CASE"); } *bIsPartition = FALSE; return GetString (bUpperCase ? "DEVICE_UPPER_CASE" : "DEVICE_LOWER_CASE"); } LRESULT CALLBACK CustomDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_SETCURSOR && hCursor != NULL) { SetCursor (hCursor); return TRUE; } return DefDlgProcW (hwnd, uMsg, wParam, lParam); } /* static BOOL IsReturnAddress (DWORD64 address) { static size_t codeEnd = 0; - byte *sp = (byte *) address; + uint8 *sp = (uint8 *) address; if (codeEnd == 0) { MEMORY_BASIC_INFORMATION mi; if (VirtualQuery ((LPCVOID) 0x401000, &mi, sizeof (mi)) >= sizeof (mi)) codeEnd = (size_t) mi.BaseAddress + mi.RegionSize; } if (address < 0x401000 + 8 || address > codeEnd) return FALSE; return sp[-5] == 0xe8 // call ADDR || (sp[-6] == 0xff && sp[-5] == 0x15) // call [ADDR] || (sp[-2] == 0xff && (sp[-1] & 0xf0) == 0xd0); // call REG } */ typedef struct { EXCEPTION_POINTERS *ExceptionPointers; HANDLE ExceptionThread; } ExceptionHandlerThreadArgs; void ExceptionHandlerThread (void *threadArg) { ExceptionHandlerThreadArgs *args = (ExceptionHandlerThreadArgs *) threadArg; EXCEPTION_POINTERS *ep = args->ExceptionPointers; @@ -3132,61 +2991,61 @@ void ExceptionHandlerThread (void *threadArg) { for (size_t i = 0; i < symbol->NameLen; ++i) { if (!isalnum (symbol->Name[i])) symbol->Name[i] = '_'; } if (symbol->Name != lastSymbol) callStack << "&st" << frameNumber++ << "=" << symbol->Name; lastSymbol = symbol->Name; } else if (frameNumber == 0 || IsReturnAddress (frame.AddrPC.Offset)) { callStack << "&st" << frameNumber++ << "=0x" << hex << frame.AddrPC.Offset << dec; } } } } } // StackWalk64() may fail due to missing frame pointers list <DWORD> retAddrs; if (frameNumber == 0) retAddrs.push_back (ep->ContextRecord->Eip); retAddrs.push_back (0); MEMORY_BASIC_INFORMATION mi; VirtualQuery (sp, &mi, sizeof (mi)); - PDWORD stackTop = (PDWORD)((byte *) mi.BaseAddress + mi.RegionSize); + PDWORD stackTop = (PDWORD)((uint8 *) mi.BaseAddress + mi.RegionSize); int i = 0; while (retAddrs.size() < 16 && &sp[i] < stackTop) { if (IsReturnAddress (sp[i])) { bool duplicate = false; foreach (DWORD prevAddr, retAddrs) { if (sp[i] == prevAddr) { duplicate = true; break; } } if (!duplicate) retAddrs.push_back (sp[i]); } i++; } if (retAddrs.size() > 1) { foreach (DWORD addr, retAddrs) { callStack << "&st" << frameNumber++ << "=0x" << hex << addr << dec; } } @@ -3476,60 +3335,78 @@ uint32 ReadDriverConfigurationFlags () { DWORD configMap; if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", TC_DRIVER_CONFIG_REG_VALUE_NAME, &configMap)) configMap = 0; return configMap; } uint32 ReadServiceConfigurationFlags () { DWORD configMap; if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\" TC_SYSTEM_FAVORITES_SERVICE_NAME, TC_SYSTEM_FAVORITES_SERVICE_NAME L"Config", &configMap)) configMap = 0; return configMap; } uint32 ReadEncryptionThreadPoolFreeCpuCountLimit () { DWORD count; if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", TC_ENCRYPTION_FREE_CPU_COUNT_REG_VALUE_NAME, &count)) count = 0; return count; } +BOOL ReadMemoryProtectionConfig () +{ + DWORD config; + + if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", VC_ENABLE_MEMORY_PROTECTION, &config)) + { + // enabled by default + config = 1; + } + return (config)? TRUE: FALSE; +} + +BOOL WriteMemoryProtectionConfig (BOOL bEnable) +{ + DWORD config = bEnable? 1: 0; + + return WriteLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", VC_ENABLE_MEMORY_PROTECTION, config); +} BOOL LoadSysEncSettings () { BOOL status = TRUE; DWORD size = 0; char *sysEncCfgFileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION), &size); char *xml = sysEncCfgFileBuf; char paramName[100], paramVal[MAX_PATH]; // Defaults int newSystemEncryptionStatus = SYSENC_STATUS_NONE; WipeAlgorithmId newnWipeMode = TC_WIPE_NONE; if (!FileExists (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION))) { SystemEncryptionStatus = newSystemEncryptionStatus; nWipeMode = newnWipeMode; } if (xml == NULL) { return FALSE; } while (xml = XmlFindElement (xml, "config")) { XmlGetAttributeText (xml, "key", paramName, sizeof (paramName)); XmlGetNodeText (xml, paramVal, sizeof (paramVal)); if (strcmp (paramName, "SystemEncryptionStatus") == 0) @@ -3652,249 +3529,154 @@ void DoPostInstallTasks (HWND hwndDlg) BOOL bDone = FALSE; if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL))) { 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); } -static void LoadSystemDll (LPCTSTR szModuleName, HMODULE *pHandle, BOOL bIgnoreError, const char* srcPos) -{ - wchar_t dllPath[MAX_PATH]; - - /* Load dll explictely from System32 to avoid Dll hijacking attacks*/ - if (!GetSystemDirectory(dllPath, MAX_PATH)) - StringCbCopyW(dllPath, sizeof(dllPath), L"C:\\Windows\\System32"); +#ifndef SETUP_DLL +// Use an idea proposed in https://medium.com/@1ndahous3/safe-code-pitfalls-dll-side-loading-winapi-and-c-73baaf48bdf5 +// it allows to set safe DLL search mode for the entire process very early on, before even the CRT is initialized and global constructors are called +#pragma comment(linker, "/ENTRY:CustomMainCrtStartup") +extern "C" { + int wWinMainCRTStartup(); + int APIENTRY CustomMainCrtStartup() + { + SetDefaultDllDirectoriesPtr SetDefaultDllDirectoriesFn = NULL; + SetDefaultDllDirectoriesFn = (SetDefaultDllDirectoriesPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDefaultDllDirectories"); + if (SetDefaultDllDirectoriesFn) + { + /* remove current directory from dll search path */ + SetDllDirectoryW (L""); + // Force loading dlls from system32 directory only + SetDefaultDllDirectoriesFn (LOAD_LIBRARY_SEARCH_SYSTEM32); + } - StringCbCatW(dllPath, sizeof(dllPath), L"\\"); - StringCbCatW(dllPath, sizeof(dllPath), szModuleName); + // activate process mitigations (currently only ASLR, dynamic code and extensions points) + ActivateProcessMitigations(); - if (((*pHandle = LoadLibrary(dllPath)) == NULL) && !bIgnoreError) - { - // This error is fatal - handleWin32Error (NULL, srcPos); - AbortProcess ("INIT_DLL"); +#ifndef SETUP + // call ActivateMemoryProtection if corresponding setting has been enabled (default is enabled) + if (ReadMemoryProtectionConfig()) + { + ActivateMemoryProtection(); + } +#endif + return wWinMainCRTStartup(); } } +#endif /* InitApp - initialize the application, this function is called once in the applications WinMain function, but before the main dialog has been created */ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine) { WNDCLASSW wc; char langId[6]; - InitCommonControlsPtr InitCommonControlsFn = NULL; + SetDefaultDllDirectoriesPtr SetDefaultDllDirectoriesFn = NULL; +#if !defined(SETUP) wchar_t modPath[MAX_PATH]; - - GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath)); - - /* remove current directory from dll search path */ - SetDllDirectoryFn = (SetDllDirectoryPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDllDirectoryW"); - SetSearchPathModeFn = (SetSearchPathModePtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetSearchPathMode"); - SetDefaultDllDirectoriesFn = (SetDefaultDllDirectoriesPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDefaultDllDirectories"); - - if (SetDllDirectoryFn) - SetDllDirectoryFn (L""); - if (SetSearchPathModeFn) - SetSearchPathModeFn (BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT); - if (SetDefaultDllDirectoriesFn) - SetDefaultDllDirectoriesFn (LOAD_LIBRARY_SEARCH_SYSTEM32); - - InitOSVersionInfo(); - - VirtualLock (&CmdTokenPin, sizeof (CmdTokenPin)); - - InitGlobalLocks (); - - LoadSystemDll (L"msvcrt.dll", &hmsvcrtdll, TRUE, SRC_POS); - LoadSystemDll (L"ntmarta.dll", &hntmartadll, TRUE, SRC_POS); - LoadSystemDll (L"MPR.DLL", &hmprdll, TRUE, SRC_POS); -#ifdef SETUP - if (IsOSAtLeast (WIN_7)) - { - LoadSystemDll (L"ProfApi.DLL", &hProfApiDll, TRUE, SRC_POS); - LoadSystemDll (L"cryptbase.dll", &hcryptbasedll, TRUE, SRC_POS); - LoadSystemDll (L"sspicli.dll", &hsspiclidll, TRUE, SRC_POS); - } #endif - LoadSystemDll (L"psapi.dll", &hpsapidll, TRUE, SRC_POS); - LoadSystemDll (L"secur32.dll", &hsecur32dll, TRUE, SRC_POS); - LoadSystemDll (L"msasn1.dll", &hmsasn1dll, TRUE, SRC_POS); - LoadSystemDll (L"Usp10.DLL", &hUsp10Dll, TRUE, SRC_POS); - if (IsOSAtLeast (WIN_7)) - LoadSystemDll (L"dwmapi.dll", &hdwmapidll, TRUE, SRC_POS); - LoadSystemDll (L"UXTheme.dll", &hUXThemeDll, TRUE, SRC_POS); - - LoadSystemDll (L"msls31.dll", &hMsls31, TRUE, SRC_POS); - LoadSystemDll (L"SETUPAPI.DLL", &hSetupDll, FALSE, SRC_POS); - LoadSystemDll (L"SHLWAPI.DLL", &hShlwapiDll, FALSE, SRC_POS); + INITCOMMONCONTROLSEX InitCtrls; - LoadSystemDll (L"userenv.dll", &hUserenvDll, TRUE, SRC_POS); - LoadSystemDll (L"rsaenh.dll", &hRsaenhDll, TRUE, SRC_POS); + InitOSVersionInfo(); -#ifdef SETUP - if (nCurrentOS < WIN_7) + if (!IsOSAtLeast (WIN_7)) { - if (nCurrentOS == WIN_XP) - { - LoadSystemDll (L"imm32.dll", &himm32dll, TRUE, SRC_POS); - LoadSystemDll (L"MSCTF.dll", &hMSCTFdll, TRUE, SRC_POS); - LoadSystemDll (L"fltlib.dll", &hfltlibdll, TRUE, SRC_POS); - LoadSystemDll (L"wbem\\framedyn.dll", &hframedyndll, TRUE, SRC_POS); - } - - if (IsOSAtLeast (WIN_VISTA)) - { - LoadSystemDll (L"netapi32.dll", &hnetapi32dll, TRUE, SRC_POS); - LoadSystemDll (L"authz.dll", &hauthzdll, TRUE, SRC_POS); - LoadSystemDll (L"xmllite.dll", &hxmllitedll, TRUE, SRC_POS); - } + // abort using a message that says that VeraCrypt can run only on Windows 7 and later and that it is officially supported only on Windows 10 and later + AbortProcessDirect(L"VeraCrypt requires at least Windows 7 to run."); } - if (IsOSAtLeast (WIN_VISTA)) - { - LoadSystemDll (L"atl.dll", &hsppdll, TRUE, SRC_POS); - LoadSystemDll (L"vsstrace.dll", &hvsstracedll, TRUE, SRC_POS); - LoadSystemDll (L"vssapi.dll", &vssapidll, TRUE, SRC_POS); - LoadSystemDll (L"spp.dll", &hsppdll, TRUE, SRC_POS); - } -#endif - - LoadSystemDll (L"crypt32.dll", &hcrypt32dll, TRUE, SRC_POS); - - if (IsOSAtLeast (WIN_7)) + SetDefaultDllDirectoriesFn = (SetDefaultDllDirectoriesPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDefaultDllDirectories"); + if (!SetDefaultDllDirectoriesFn) { - LoadSystemDll (L"CryptSP.dll", &hCryptSpDll, TRUE, SRC_POS); - - LoadSystemDll (L"cfgmgr32.dll", &hcfgmgr32dll, TRUE, SRC_POS); - LoadSystemDll (L"devobj.dll", &hdevobjdll, TRUE, SRC_POS); - LoadSystemDll (L"powrprof.dll", &hpowrprofdll, TRUE, SRC_POS); - - LoadSystemDll (L"bcrypt.dll", &hbcryptdll, TRUE, SRC_POS); - LoadSystemDll (L"bcryptprimitives.dll", &hbcryptprimitivesdll, TRUE, SRC_POS); - } + // This can happen only if KB2533623 is missing from Windows 7 + AbortProcessDirect(L"VeraCrypt requires KB2533623 to be installed on Windows 7 and Windows Server 2008 R2 in order to run."); + } -#ifndef SETUP - LoadSystemDll (L"WINSCARD.DLL", &hwinscarddll, TRUE, SRC_POS); -#endif + VirtualLock (&CmdTokenPin, sizeof (CmdTokenPin)); - LoadSystemDll (L"COMCTL32.DLL", &hComctl32Dll, FALSE, SRC_POS); + InitGlobalLocks (); - // call InitCommonControls function - InitCommonControlsFn = (InitCommonControlsPtr) GetProcAddress (hComctl32Dll, "InitCommonControls"); - ImageList_AddFn = (ImageList_AddPtr) GetProcAddress (hComctl32Dll, "ImageList_Add"); - ImageList_CreateFn = (ImageList_CreatePtr) GetProcAddress (hComctl32Dll, "ImageList_Create"); - - if (InitCommonControlsFn && ImageList_AddFn && ImageList_CreateFn) - { - InitCommonControlsFn(); - } - else - AbortProcess ("INIT_DLL"); + // call InitCommonControlsEx function to initialize the common controls + InitCtrls.dwSize = sizeof (InitCtrls); + InitCtrls.dwICC = ICC_WIN95_CLASSES | ICC_PAGESCROLLER_CLASS | ICC_NATIVEFNTCTL_CLASS | ICC_STANDARD_CLASSES | ICC_LINK_CLASS; + InitCommonControlsEx (&InitCtrls); - LoadSystemDll (L"Riched20.dll", &hRichEditDll, FALSE, SRC_POS); - LoadSystemDll (L"Advapi32.dll", &hAdvapi32Dll, FALSE, SRC_POS); + // Load RichEdit library in order to be able to use RichEdit20W class + LoadLibraryEx (L"Riched20.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); #if !defined(SETUP) + GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath)); if (!VerifyModuleSignature (modPath)) - AbortProcess ("DIST_PACKAGE_CORRUPTED"); + AbortProcessDirect (L"This distribution package is damaged. Please try downloading it again (preferably from the official VeraCrypt website at https://www.veracrypt.fr)."); #endif - // Get SetupAPI functions pointers - SetupCloseInfFileFn = (SetupCloseInfFilePtr) GetProcAddress (hSetupDll, "SetupCloseInfFile"); - SetupDiOpenClassRegKeyFn = (SetupDiOpenClassRegKeyPtr) GetProcAddress (hSetupDll, "SetupDiOpenClassRegKey"); - SetupInstallFromInfSectionWFn = (SetupInstallFromInfSectionWPtr) GetProcAddress (hSetupDll, "SetupInstallFromInfSectionW"); - SetupOpenInfFileWFn = (SetupOpenInfFileWPtr) GetProcAddress (hSetupDll, "SetupOpenInfFileW"); - - if (!SetupCloseInfFileFn || !SetupDiOpenClassRegKeyFn || !SetupInstallFromInfSectionWFn || !SetupOpenInfFileWFn) - AbortProcess ("INIT_DLL"); - - // Get SHDeleteKeyW,SHStrDupW, UrlUnescapeW functions pointers - SHDeleteKeyWFn = (SHDeleteKeyWPtr) GetProcAddress (hShlwapiDll, "SHDeleteKeyW"); - SHStrDupWFn = (SHStrDupWPtr) GetProcAddress (hShlwapiDll, "SHStrDupW"); - UrlUnescapeWFn = (UrlUnescapeWPtr) GetProcAddress(hShlwapiDll, "UrlUnescapeW"); - IUnknown_QueryServicePtr = (IUnknown_QueryServiceFn) GetProcAddress(hShlwapiDll, "IUnknown_QueryService"); - if (!IUnknown_QueryServicePtr) - IUnknown_QueryServicePtr = (IUnknown_QueryServiceFn) GetProcAddress(hShlwapiDll, MAKEINTRESOURCEA(176)); - if (!SHDeleteKeyWFn || !SHStrDupWFn || !UrlUnescapeWFn || !IUnknown_QueryServicePtr) - AbortProcess ("INIT_DLL"); - - if (IsOSAtLeast (WIN_VISTA)) - { - /* Get ChangeWindowMessageFilter used to enable some messages bypasss UIPI (User Interface Privilege Isolation) */ - ChangeWindowMessageFilterFn = (ChangeWindowMessageFilterPtr) GetProcAddress (GetModuleHandle (L"user32.dll"), "ChangeWindowMessageFilter"); #ifndef SETUP - /* enable drag-n-drop when we are running elevated */ - AllowMessageInUIPI (WM_DROPFILES); - AllowMessageInUIPI (WM_COPYDATA); - AllowMessageInUIPI (WM_COPYGLOBALDATA); + /* enable drag-n-drop when we are running elevated */ + AllowMessageInUIPI (WM_DROPFILES); + AllowMessageInUIPI (WM_COPYDATA); + AllowMessageInUIPI (WM_COPYGLOBALDATA); #endif - } - - // Get CreateProcessWithTokenW function pointer - CreateProcessWithTokenWPtr = (CreateProcessWithTokenWFn) GetProcAddress(hAdvapi32Dll, "CreateProcessWithTokenW"); /* Save the instance handle for later */ hInst = hInstance; SetErrorMode (SetErrorMode (0) | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); - CoInitialize (NULL); + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); #ifndef SETUP // Application ID - typedef HRESULT (WINAPI *SetAppId_t) (PCWSTR appID); - SetAppId_t setAppId = (SetAppId_t) GetProcAddress (GetModuleHandle (L"shell32.dll"), "SetCurrentProcessExplicitAppUserModelID"); - - if (setAppId) - setAppId (TC_APPLICATION_ID); + SetCurrentProcessExplicitAppUserModelID (TC_APPLICATION_ID); #endif // Language langId[0] = 0; SetPreferredLangId (ConfigReadString ("Language", "", langId, sizeof (langId))); #ifndef SETUP if (langId[0] == 0) { // check if user selected a language during installation WCHAR uiLang[6]; ReadRegistryString (L"Software\\VeraCrypt", L"SetupUILanguage", L"", uiLang, sizeof (uiLang)); if (0 < WideCharToMultiByte (CP_ACP, 0, uiLang, -1, langId, sizeof (langId), NULL, NULL)) { SetPreferredLangId (langId); bLanguageSetInSetup = TRUE; } } #ifndef VCEXPANDER // delete the registry key created by the installer (if any) DeleteRegistryKey (HKEY_CURRENT_USER, L"Software\\VeraCrypt"); #endif #endif if (langId[0] == 0) { if (IsNonInstallMode ()) { @@ -3918,246 +3700,143 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine) // A new instance of the application must be created with elevated privileges. if (IsNonInstallMode () && !IsAdmin () && IsUacSupported ()) { if (wcsstr (lpszCommandLine, L"/q UAC ") == lpszCommandLine) { Error ("UAC_INIT_ERROR", NULL); exit (1); } if (LaunchElevatedProcess (NULL, modPath, lpszCommandLine)) exit (0); else exit (1); } #endif SetUnhandledExceptionFilter (ExceptionHandler); _set_invalid_parameter_handler (InvalidParameterHandler); RemoteSession = GetSystemMetrics (SM_REMOTESESSION) != 0; #ifndef VC_SKIP_OS_DRIVER_REQ_CHECK if (!IsSupportedOS()) { MessageBoxW (NULL, GetString ("UNSUPPORTED_OS"), lpszTitle, MB_ICONSTOP); exit (1); } #else - // in TESTSIGNING mode, we support only Windows Vista, Windows 7, Windows 8/8.1 - if ( !IsOSVersionAtLeast(WIN_VISTA, 0) + // in TESTSIGNING mode, we support only Windows 7 and Windows 8/8.1 + if ( #ifndef SETUP - || IsOSVersionAtLeast(WIN_10, 0) + IsOSVersionAtLeast(WIN_10, 0) #else || (IsOSVersionAtLeast(WIN_10, 0) && !bMakePackage) #endif ) { MessageBoxW (NULL, L"TESTSIGNING version of VeraCrypt targets only Windows Vista, Windows 7 and Windows 8/8.1.\n\nPlease use the standard version of VeraCrypt instead.", lpszTitle, MB_ICONSTOP); exit (1); } else if ( !IsTestSigningModeEnabled() #ifdef SETUP && !bMakePackage #endif ) { MessageBoxW (NULL, L"Test-Signing Mode, which is required to run VeraCrypt TESTSIGNING binaries, is not enabled in Windows.\n\nExecution aborted!", lpszTitle, MB_ICONSTOP); exit (1); } #endif - else - { - // Service pack check & warnings about critical MS issues - switch (nCurrentOS) - { - case WIN_XP: - if (CurrentOSServicePack < 1) - { - HKEY k; - // PE environment does not report version of SP - if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\minint", 0, KEY_READ, &k) != ERROR_SUCCESS) - Warning ("LARGE_IDE_WARNING_XP", NULL); - else - RegCloseKey (k); - } - break; - } - } /* Get the attributes for the standard dialog class */ if ((GetClassInfoW (hInst, WINDOWS_DIALOG_CLASS, &wc)) == 0) { handleWin32Error (NULL, SRC_POS); AbortProcess ("INIT_REGISTER"); } #ifndef SETUP wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_TRUECRYPT_ICON)); #else #include "../setup/resource.h" wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_SETUP)); #endif wc.lpszClassName = TC_DLG_CLASS; wc.lpfnWndProc = &CustomDlgProc; wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.cbWndExtra = DLGWINDOWEXTRA; hDlgClass = RegisterClassW (&wc); if (hDlgClass == 0) { handleWin32Error (NULL, SRC_POS); AbortProcess ("INIT_REGISTER"); } wc.lpszClassName = TC_SPLASH_CLASS; wc.lpfnWndProc = &SplashDlgProc; wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.cbWndExtra = DLGWINDOWEXTRA; hSplashClass = RegisterClassW (&wc); if (hSplashClass == 0) { handleWin32Error (NULL, SRC_POS); AbortProcess ("INIT_REGISTER"); } // DPI and GUI aspect ratio DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_AUXILIARY_DLG), NULL, (DLGPROC) AuxiliaryDlgProc, (LPARAM) 1); InitHelpFileName (); #ifndef SETUP #ifdef _WIN64 - if (IsOSAtLeast (WIN_7)) + EnableRamEncryption ((ReadDriverConfigurationFlags() & VC_DRIVER_CONFIG_ENABLE_RAM_ENCRYPTION) ? TRUE : FALSE); + if (IsRamEncryptionEnabled()) { - EnableRamEncryption ((ReadDriverConfigurationFlags() & VC_DRIVER_CONFIG_ENABLE_RAM_ENCRYPTION) ? TRUE : FALSE); - if (IsRamEncryptionEnabled()) - { - if (!InitializeSecurityParameters(GetAppRandomSeed)) - AbortProcess("OUTOFMEMORY"); - } + if (!InitializeSecurityParameters(GetAppRandomSeed)) + AbortProcess("OUTOFMEMORY"); } #endif if (!EncryptionThreadPoolStart (ReadEncryptionThreadPoolFreeCpuCountLimit())) { handleWin32Error (NULL, SRC_POS); - 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); } #endif } -void FinalizeApp (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); -} - void InitHelpFileName (void) { wchar_t *lpszTmp; GetModuleFileNameW (NULL, szHelpFile, ARRAYSIZE (szHelpFile)); lpszTmp = wcsrchr (szHelpFile, L'\\'); if (lpszTmp) { wchar_t szTemp[TC_MAX_PATH]; ++lpszTmp; *lpszTmp = 0; // add null terminating character to prepare for append operations // Primary file name if (strcmp (GetPreferredLangId(), "en") == 0 || strlen(GetPreferredLangId()) == 0) { StringCbCatW (szHelpFile, sizeof(szHelpFile), L"docs\\VeraCrypt User Guide.chm"); } else { StringCbPrintfW (szTemp, sizeof(szTemp), L"docs\\VeraCrypt User Guide.%S.chm", GetPreferredLangId()); StringCbCatW (szHelpFile, sizeof(szHelpFile), szTemp); } // Secondary file name (used when localized documentation is not found). GetModuleFileNameW (NULL, szHelpFile2, ARRAYSIZE (szHelpFile2)); lpszTmp = wcsrchr (szHelpFile2, L'\\'); if (lpszTmp) { @@ -4239,78 +3918,75 @@ BOOL GetDriveLabel (int driveNo, wchar_t *label, int labelSize) DWORD fileSystemFlags; wchar_t root[] = { L'A' + (wchar_t) driveNo, L':', L'\\', 0 }; return GetVolumeInformationW (root, label, labelSize / 2, NULL, NULL, &fileSystemFlags, NULL, 0); } #ifndef SETUP /* Stores the device path of the system partition in SysPartitionDevicePath and the device path of the system drive in SysDriveDevicePath. IMPORTANT: As this may take a very long time if called for the first time, it should be called only before performing a dangerous operation (such as header backup restore or formatting a supposedly non-system device) never at WM_INITDIALOG or any other GUI events -- instead call IsSystemDevicePath (path, hwndDlg, FALSE) for very fast preliminary GUI checks; also note that right after the "Select Device" dialog exits with an OK return code, you can use the global flags bSysPartitionSelected and bSysDriveSelected to see if the user selected the system partition/device. After this function completes successfully, the results are cached for the rest of the session and repeated executions complete very fast. Returns TRUE if successful (otherwise FALSE). */ BOOL GetSysDevicePaths (HWND hwndDlg) { if (!bCachedSysDevicePathsValid || wcslen (SysPartitionDevicePath) <= 1 || wcslen (SysDriveDevicePath) <= 1) { foreach (const HostDevice &device, GetAvailableHostDevices (false, true)) { if (device.ContainsSystem) StringCchCopyW (device.IsPartition ? SysPartitionDevicePath : SysDriveDevicePath, TC_MAX_PATH, device.Path.c_str()); } - if (IsOSAtLeast (WIN_7)) + // Find extra boot partition + foreach (const HostDevice &drive, GetAvailableHostDevices (false, false)) { - // Find extra boot partition - foreach (const HostDevice &drive, GetAvailableHostDevices (false, false)) + if (drive.ContainsSystem) { - if (drive.ContainsSystem) + foreach (const HostDevice &sysDrivePartition, drive.Partitions) { - foreach (const HostDevice &sysDrivePartition, drive.Partitions) + if (sysDrivePartition.Bootable) { - if (sysDrivePartition.Bootable) - { - if (sysDrivePartition.Size <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE) - ExtraBootPartitionDevicePath = sysDrivePartition.Path; - break; - } + if (sysDrivePartition.Size <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE) + ExtraBootPartitionDevicePath = sysDrivePartition.Path; + break; } - break; } + break; } } bCachedSysDevicePathsValid = 1; } return (bCachedSysDevicePathsValid && wcslen (SysPartitionDevicePath) > 1 && wcslen (SysDriveDevicePath) > 1); } /* Determines whether the device path is the path of the system partition or of the system drive (or neither). If bReliableRequired is TRUE, very fast execution is guaranteed, but the results cannot be relied upon. If it's FALSE and the function is called for the first time, execution may take up to one minute but the results are reliable. IMPORTANT: As the execution may take a very long time if called for the first time with bReliableRequired set to TRUE, it should be called with bReliableRequired set to TRUE only before performing a dangerous operation (such as header backup restore or formatting a supposedly non-system device) never at WM_INITDIALOG or any other GUI events (use IsSystemDevicePath(path, hwndDlg, FALSE) for fast preliminary GUI checks; also note that right after the "Select Device" dialog exits with an OK return code, you can use the global flags bSysPartitionSelected and bSysDriveSelected to see if the user selected the system partition/device). After this function completes successfully, the results are cached for the rest of the session, bReliableRequired is ignored (TRUE implied), repeated executions complete very fast, and the results are always reliable. Return codes: 1 - it is the system partition path (e.g. \Device\Harddisk0\Partition1) 2 - it is the system drive path (e.g. \Device\Harddisk0\Partition0) 3 - it is the extra boot partition path 0 - it's not the system partition/drive path -1 - the result can't be determined, isn't reliable, or there was an error. */ @@ -4462,103 +4138,143 @@ struct _TEXT_EDIT_DIALOG_PARAM { _TEXT_EDIT_DIALOG_PARAM (const _TEXT_EDIT_DIALOG_PARAM& other) : ReadOnly (other.ReadOnly), Text (other.Text), Title (other.Title) {} _TEXT_EDIT_DIALOG_PARAM(BOOL _readOnly, const WCHAR* title, std::string& _text) : ReadOnly(_readOnly), Text(_text), Title(title) {} _TEXT_EDIT_DIALOG_PARAM& operator=( const _TEXT_EDIT_DIALOG_PARAM& other) { if (this != &other) { ReadOnly = other.ReadOnly; Text = other.Text; Title = other.Title; } return *this; } }; typedef struct _TEXT_EDIT_DIALOG_PARAM TEXT_INFO_DIALOG_PARAM,*TEXT_INFO_DIALOG_PARAM_PTR; INT_PTR TextEditDialogBox (BOOL readOnly, HWND parent, const WCHAR* Title, std::string& text) { TEXT_INFO_DIALOG_PARAM pm(readOnly, Title, text); return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_EDIT_DLG), parent, (DLGPROC) TextEditDlgProc, (LPARAM) &pm); } BOOL CALLBACK TextEditDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); static int nID = 0; static TEXT_INFO_DIALOG_PARAM_PTR prm; switch (msg) { case WM_INITDIALOG: { prm = (TEXT_INFO_DIALOG_PARAM_PTR)lParam; + LocalizeDialog (hwndDlg, NULL); // increase size limit of rich edit control SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_EXLIMITTEXT, 0, -1); SetWindowTextW (hwndDlg, prm->Title); // Left margin for rich edit text field SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4)); if (prm->ReadOnly) { // switch rich edit control to ReadOnly - SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), ES_READONLY, TRUE, 0); + SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETREADONLY , TRUE, 0); // hide cancel button - ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_HIDE); + HWND hwndCancel = GetDlgItem(hwndDlg, IDCANCEL); + ShowWindow(hwndCancel, SW_HIDE); + + // Reposition OK button to Cancel button's position + HWND hwndOK = GetDlgItem(hwndDlg, IDOK); + if (hwndOK && hwndCancel) + { + // Get Cancel button's position in screen coordinates + RECT rectCancel; + if (GetWindowRect(hwndCancel, &rectCancel)) + { + // Convert Cancel button's position to dialog's client coordinates + POINT ptCancel = { rectCancel.left, rectCancel.top }; + ScreenToClient(hwndDlg, &ptCancel); + + // Get OK button's current size + RECT rectOK; + if (GetWindowRect(hwndOK, &rectOK)) + { + int width = rectOK.right - rectOK.left; + int height = rectOK.bottom - rectOK.top; + + // Move OK button to Cancel button's position + SetWindowPos( + hwndOK, + NULL, + ptCancel.x, + ptCancel.y, + width, + height, + SWP_NOZORDER | SWP_NOACTIVATE + ); + } + } + } } SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0); } return 0; case WM_COMMAND: if (lw == IDOK ) { if (!prm->ReadOnly) { - prm->Text.resize(GetWindowTextLengthA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT)) + 1); - GetWindowTextA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), &(prm->Text)[0], (int) prm->Text.size()); + // read content of the text box as UTF16 and then convert it to UTF8 + HWND hEdit = GetDlgItem(hwndDlg, IDC_INFO_BOX_TEXT); + int size = GetWindowTextLengthW(hEdit); + std::vector<WCHAR> buffer(size + 1); + GetWindowTextW(hEdit, buffer.data(), size + 1); + prm->Text = WideToUtf8String(buffer.data()); } NormalCursor (); EndDialog (hwndDlg, IDOK); return 1; } if (lw == IDCANCEL ) { NormalCursor (); EndDialog (hwndDlg, IDCANCEL); return 1; } return 0; case TC_APPMSG_LOAD_TEXT_BOX_CONTENT: { - SetWindowTextA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), prm->Text.c_str()); + // convert prm->Text to UTF16 using Utf8StringToWide + SetWindowTextW(GetDlgItem(hwndDlg, IDC_INFO_BOX_TEXT), Utf8StringToWide(prm->Text).c_str()); } return 0; case WM_CLOSE: NormalCursor (); EndDialog (hwndDlg, 0); return 1; } return 0; } INT_PTR TextInfoDialogBox (int nID) { return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_INFO_DIALOG_BOX_DLG), MainDlg, (DLGPROC) TextInfoDialogBoxDlgProc, (LPARAM) nID); } BOOL CALLBACK TextInfoDialogBoxDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); static int nID = 0; switch (msg) { case WM_INITDIALOG: { nID = (int) lParam; // increase size limit of rich edit control SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_EXLIMITTEXT, 0, -1); @@ -5419,300 +5135,367 @@ load: CloseHandle (hDriver); hDriver = INVALID_HANDLE_VALUE; return ERR_DRIVER_VERSION; } } #else if (!bResult) DriverVersion = 0; #endif } return 0; } void ResetCurrentDirectory () { wchar_t p[MAX_PATH]; if (!IsNonInstallMode () && SHGetFolderPath (NULL, CSIDL_PROFILE, NULL, 0, p) == ERROR_SUCCESS) { SetCurrentDirectory (p); } else { GetModPath (p, ARRAYSIZE (p)); SetCurrentDirectory (p); } } -BOOL BrowseFiles (HWND hwndDlg, char *stringId, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter) +BOOL BrowseFiles (HWND hwndDlg, char *stringId, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode) { - return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, browseFilter); + return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, NULL); } - -BOOL BrowseFilesInDir (HWND hwndDlg, char *stringId, wchar_t *initialDir, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter, const wchar_t *initialFileName, const wchar_t *defaultExtension) +BOOL BrowseFilesInDir(HWND hwndDlg, char *stringId, wchar_t *initialDir, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter, const wchar_t *initialFileName, const wchar_t *defaultExtension) { - OPENFILENAMEW ofn; - wchar_t file[TC_MAX_PATH] = { 0 }; + IFileDialog *pfd = NULL; + HRESULT hr; wchar_t filter[1024]; BOOL status = FALSE; - CoInitialize (NULL); - - ZeroMemory (&ofn, sizeof (ofn)); - *lpszFileName = 0; - - if (initialDir) + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if (FAILED(hr)) { - ofn.lpstrInitialDir = initialDir; + return FALSE; } - if (initialFileName) - StringCchCopyW (file, array_capacity (file), initialFileName); - - ofn.lStructSize = sizeof (ofn); - ofn.hwndOwner = hwndDlg; - - StringCbPrintfW (filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c", - GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0); - ofn.lpstrFilter = browseFilter ? browseFilter : filter; - ofn.nFilterIndex = 1; - ofn.lpstrFile = file; - ofn.nMaxFile = sizeof (file) / sizeof (file[0]); - ofn.lpstrTitle = GetString (stringId); - ofn.lpstrDefExt = defaultExtension; - ofn.Flags = OFN_HIDEREADONLY - | OFN_PATHMUSTEXIST - | (keepHistory ? 0 : OFN_DONTADDTORECENT) - | (saveMode ? OFN_OVERWRITEPROMPT : 0); - - if (!keepHistory) - CleanLastVisitedMRU (); - - SystemFileSelectorCallerThreadId = GetCurrentThreadId(); - SystemFileSelectorCallPending = TRUE; - - if (!saveMode) + // Choose between the File Open or File Save dialog depending on the saveMode. + if (saveMode) { - if (!GetOpenFileNameW (&ofn)) - goto ret; + hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd)); } else { - if (!GetSaveFileNameW (&ofn)) - goto ret; + hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd)); } - SystemFileSelectorCallPending = FALSE; + if (SUCCEEDED(hr)) + { + // Set the options for the dialog. + DWORD dwFlags; + hr = pfd->GetOptions(&dwFlags); + if (SUCCEEDED(hr)) + { + dwFlags |= FOS_NOCHANGEDIR | FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE; + if (!keepHistory) + dwFlags |= FOS_DONTADDTORECENT; + if (saveMode) + dwFlags |= FOS_NOTESTFILECREATE | FOS_OVERWRITEPROMPT | FOS_DEFAULTNOMINIMODE; + hr = pfd->SetOptions(dwFlags); + } - StringCchCopyW (lpszFileName, MAX_PATH, file); + // Set the initial directory, if provided. + if (initialDir) + { + IShellItem *psi; + hr = SHCreateItemFromParsingName(initialDir, NULL, IID_PPV_ARGS(&psi)); + if (SUCCEEDED(hr)) + { + pfd->SetFolder(psi); + psi->Release(); + } + } - if (!keepHistory) - CleanLastVisitedMRU (); + // Set the initial file name, if provided. + if (initialFileName) + { + pfd->SetFileName(initialFileName); + } - status = TRUE; + // Set the title. + pfd->SetTitle(GetString(stringId)); -ret: - SystemFileSelectorCallPending = FALSE; - ResetCurrentDirectory(); - CoUninitialize(); + // Set the default extension. + if (defaultExtension) + { + pfd->SetDefaultExtension(defaultExtension); + } - return status; -} + // Prepare the filter + COMDLG_FILTERSPEC filterSpec[5]; + UINT cfilterSpec = 0; + if (!browseFilter) + { + StringCbPrintfW(filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c", + GetString("ALL_FILES"), 0, 0, GetString("TC_VOLUMES"), 0, 0, 0); + browseFilter = filter; + } -static wchar_t SelectMultipleFilesPath[131072]; -static int SelectMultipleFilesOffset; + // Assume browseFilter is a formatted wide string like L"Text Files (*.txt)\0*.txt\0" + // loop over all the filters in the string and add them to filterSpec array + while (*browseFilter) + { + filterSpec[cfilterSpec].pszName = browseFilter; + browseFilter += wcslen(browseFilter) + 1; + filterSpec[cfilterSpec].pszSpec = browseFilter; + browseFilter += wcslen(browseFilter) + 1; + cfilterSpec++; -BOOL SelectMultipleFiles (HWND hwndDlg, const char *stringId, wchar_t *lpszFileName, size_t cbFileName,BOOL keepHistory) -{ - OPENFILENAMEW ofn; - wchar_t filter[1024]; - BOOL status = FALSE; + if (cfilterSpec >= ARRAYSIZE(filterSpec)) + break; + } - CoInitialize (NULL); - - ZeroMemory (&ofn, sizeof (ofn)); - - SelectMultipleFilesPath[0] = 0; - *lpszFileName = 0; - ofn.lStructSize = sizeof (ofn); - ofn.hwndOwner = hwndDlg; - StringCbPrintfW (filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c", - GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0); - ofn.lpstrFilter = filter; - ofn.nFilterIndex = 1; - ofn.lpstrFile = SelectMultipleFilesPath; - ofn.nMaxFile = 0xffff * 2; // The size must not exceed 0xffff*2 due to a bug in Windows 2000 and XP SP1 - ofn.lpstrTitle = GetString (stringId); - ofn.Flags = OFN_HIDEREADONLY - | OFN_EXPLORER - | OFN_PATHMUSTEXIST - | OFN_ALLOWMULTISELECT - | (keepHistory ? 0 : OFN_DONTADDTORECENT); - - if (!keepHistory) - CleanLastVisitedMRU (); + // Set the file types filter. + hr = pfd->SetFileTypes(cfilterSpec, filterSpec); + hr = pfd->SetFileTypeIndex(1); - SystemFileSelectorCallerThreadId = GetCurrentThreadId(); - SystemFileSelectorCallPending = TRUE; + if (!keepHistory) + CleanLastVisitedMRU(); - if (!GetOpenFileNameW (&ofn)) - goto ret; + SystemFileSelectorCallerThreadId = GetCurrentThreadId(); + SystemFileSelectorCallPending = TRUE; - SystemFileSelectorCallPending = FALSE; + // Show the dialog. + hr = pfd->Show(hwndDlg); - if (SelectMultipleFilesPath[ofn.nFileOffset - 1] != 0) - { - // Single file selected - StringCbCopyW (lpszFileName, cbFileName, SelectMultipleFilesPath); - SelectMultipleFilesOffset = 0; - SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath)); - } - else - { - // Multiple files selected - SelectMultipleFilesOffset = ofn.nFileOffset; - SelectMultipleFilesNext (lpszFileName, cbFileName); - } + // Obtain the result if the user clicked the "OK" button. + if (SUCCEEDED(hr)) + { + IShellItem *pItem; + hr = pfd->GetResult(&pItem); + if (SUCCEEDED(hr)) + { + PWSTR pszFilePath; + hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath); + if (SUCCEEDED(hr)) + { + StringCchCopyW(lpszFileName, MAX_PATH, pszFilePath); + CoTaskMemFree(pszFilePath); + status = TRUE; + } + pItem->Release(); + } + } - if (!keepHistory) - CleanLastVisitedMRU (); + pfd->Release(); + + if (!keepHistory) + CleanLastVisitedMRU(); + } - status = TRUE; - -ret: SystemFileSelectorCallPending = FALSE; ResetCurrentDirectory(); CoUninitialize(); return status; } - -BOOL SelectMultipleFilesNext (wchar_t *lpszFileName, size_t cbFileName) +BOOL SelectMultipleFiles(HWND hwndDlg, const char *stringId, BOOL keepHistory, std::vector<std::wstring> &filesList) { - if (SelectMultipleFilesOffset == 0) + IFileOpenDialog *pfd = NULL; + HRESULT hr; + BOOL status = FALSE; + + filesList.clear(); + + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if (FAILED(hr)) + { return FALSE; + } - StringCbCopyW (lpszFileName, cbFileName,SelectMultipleFilesPath); - lpszFileName[TC_MAX_PATH - 1] = 0; + // Create the File Open Dialog object. + hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd)); + if (SUCCEEDED(hr)) + { + DWORD dwFlags; + hr = pfd->GetOptions(&dwFlags); + if (SUCCEEDED(hr)) + { + dwFlags |= FOS_ALLOWMULTISELECT | FOS_NOCHANGEDIR | FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE; + if (!keepHistory) + dwFlags |= FOS_DONTADDTORECENT; - if (lpszFileName[wcslen (lpszFileName) - 1] != L'\\') - StringCbCatW (lpszFileName, cbFileName,L"\\"); + hr = pfd->SetOptions(dwFlags); + } - StringCbCatW (lpszFileName, cbFileName,SelectMultipleFilesPath + SelectMultipleFilesOffset); + // Set the title and filter + pfd->SetTitle(GetString(stringId)); - SelectMultipleFilesOffset += (int) wcslen (SelectMultipleFilesPath + SelectMultipleFilesOffset) + 1; - if (SelectMultipleFilesPath[SelectMultipleFilesOffset] == 0) - { - SelectMultipleFilesOffset = 0; - SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath)); - } + wchar_t allFilesfilter[512]; + wchar_t volumesfilter[512]; - return TRUE; -} + StringCbPrintfW(allFilesfilter, sizeof(allFilesfilter), L"%ls (*.*)", GetString("ALL_FILES")); + StringCbPrintfW(volumesfilter, sizeof(volumesfilter), L"%ls (*.hc)", GetString("TC_VOLUMES")); + COMDLG_FILTERSPEC rgSpec[] = + { + {allFilesfilter, L"*.*"}, + {volumesfilter, L"*.hc"}}; + hr = pfd->SetFileTypes(ARRAYSIZE(rgSpec), rgSpec); -static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) -{ - switch(uMsg) { - case BFFM_INITIALIZED: - { - /* WParam is TRUE since we are passing a path. - It would be FALSE if we were passing a pidl. */ - SendMessageW (hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)pData); - break; - } + if (!keepHistory) + CleanLastVisitedMRU(); - case BFFM_SELCHANGED: - { - wchar_t szDir[TC_MAX_PATH]; + // Show the dialog + hr = pfd->Show(hwndDlg); + if (SUCCEEDED(hr)) + { + IShellItemArray *psiaResults; + hr = pfd->GetResults(&psiaResults); + if (SUCCEEDED(hr)) + { + DWORD count; + hr = psiaResults->GetCount(&count); + if (SUCCEEDED(hr)) + { + for (DWORD i = 0; i < count; ++i) + { + IShellItem *psi; + hr = psiaResults->GetItemAt(i, &psi); + if (SUCCEEDED(hr)) + { + PWSTR pszFilePath; + hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath); + if (SUCCEEDED(hr)) + { + filesList.push_back(pszFilePath); + CoTaskMemFree(pszFilePath); + } + psi->Release(); + } + } - /* Set the status window to the currently selected path. */ - if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir)) - { - SendMessage (hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir); - } - break; - } + status = TRUE; + } + psiaResults->Release(); + } + } - default: - break; + if (!keepHistory) + CleanLastVisitedMRU(); + + pfd->Release(); } - return 0; + CoUninitialize(); + return status; } - -BOOL BrowseDirectories (HWND hwndDlg, char *lpszTitle, wchar_t *dirName) +BOOL BrowseDirectories(HWND hwndDlg, char *lpszTitle, wchar_t *dirName, const wchar_t *initialDir) { - BROWSEINFOW bi; - LPITEMIDLIST pidl; - LPMALLOC pMalloc; - BOOL bOK = FALSE; + IFileDialog *pfd = NULL; + HRESULT hr; + BOOL bOK = FALSE; - CoInitialize (NULL); + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if (FAILED(hr)) + { + return FALSE; + } - if (SUCCEEDED (SHGetMalloc (&pMalloc))) + hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd)); + if (SUCCEEDED(hr)) { - ZeroMemory (&bi, sizeof(bi)); - bi.hwndOwner = hwndDlg; - bi.pszDisplayName = 0; - bi.lpszTitle = GetString (lpszTitle); - bi.pidlRoot = 0; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT; - bi.lpfn = BrowseCallbackProc; - bi.lParam = (LPARAM)dirName; + // Set the options on the dialog. + DWORD dwFlags; + hr = pfd->GetOptions(&dwFlags); + if (SUCCEEDED(hr)) + { + dwFlags |= FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM | FOS_NOCHANGEDIR; // Important to enable folder-picking mode + hr = pfd->SetOptions(dwFlags); + } + + // Set the title. + if (lpszTitle) + { + pfd->SetTitle(GetString(lpszTitle)); + } - pidl = SHBrowseForFolderW (&bi); - if (pidl != NULL) + IShellItem *psi; + if (initialDir) + { + // Set the initial directory, if provided. + hr = SHCreateItemFromParsingName(initialDir, NULL, IID_PPV_ARGS(&psi)); + } + else { - if (SHGetPathFromIDList(pidl, dirName)) + // set folder to "This PC" shel item + hr = SHCreateItemInKnownFolder(FOLDERID_ComputerFolder, 0, NULL, IID_PPV_ARGS(&psi)); + } + if (SUCCEEDED(hr)) + { + pfd->SetFolder(psi); + psi->Release(); + } + + // Show the dialog. + hr = pfd->Show(hwndDlg); + if (SUCCEEDED(hr)) + { + // Obtain the result when the user clicks the "OK" button. + // The result is an IShellItem object. + IShellItem *pItem; + hr = pfd->GetResult(&pItem); + if (SUCCEEDED(hr)) { - bOK = TRUE; + PWSTR pszFolderPath; + hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFolderPath); + if (SUCCEEDED(hr)) + { + StringCchCopyW(dirName, MAX_PATH, pszFolderPath); + CoTaskMemFree(pszFolderPath); + bOK = TRUE; + } + pItem->Release(); } - - pMalloc->Free (pidl); - pMalloc->Release(); } + pfd->Release(); } CoUninitialize(); - return bOK; } - std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg) { WCHAR szTmp[8192]; StringCbPrintfW (szTmp, sizeof(szTmp), GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_WRONG" : "PASSWORD_WRONG")); if (CheckCapsLock (hwndDlg, TRUE)) StringCbCatW (szTmp, sizeof(szTmp), GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); #ifdef TCMOUNT wchar_t szDevicePath [TC_MAX_PATH+1] = {0}; GetWindowText (GetDlgItem (MainDlg, IDC_VOLUME), szDevicePath, ARRAYSIZE (szDevicePath)); if (TCBootLoaderOnInactiveSysEncDrive (szDevicePath)) { StringCbPrintfW (szTmp, sizeof(szTmp), GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_OR_MODE_WRONG" : "PASSWORD_OR_MODE_WRONG")); if (CheckCapsLock (hwndDlg, TRUE)) StringCbCatW (szTmp, sizeof(szTmp), GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); StringCbCatW (szTmp, sizeof(szTmp), GetString ("SYSENC_MOUNT_WITHOUT_PBA_NOTE")); } #endif wstring msg = szTmp; #ifdef TCMOUNT if (KeyFilesEnable && HiddenFilesPresentInKeyfilePath) { msg += GetString ("HIDDEN_FILES_PRESENT_IN_KEYFILE_PATH"); HiddenFilesPresentInKeyfilePath = FALSE; @@ -5807,60 +5590,68 @@ void handleError (HWND hwndDlg, int code, const char* srcPos) case ERR_NONSYS_INPLACE_ENC_INCOMPLETE: Error ("ERR_NONSYS_INPLACE_ENC_INCOMPLETE", hwndDlg); break; case ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG: Error ("ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG", hwndDlg); break; case ERR_PARAMETER_INCORRECT: Error ("ERR_PARAMETER_INCORRECT", hwndDlg); break; case ERR_USER_ABORT: case ERR_DONT_REPORT: // A non-error break; #ifndef SETUP case ERR_RAND_INIT_FAILED: StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("INIT_RAND"), SRC_POS, GetLastError ()); MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, MB_ICONERROR); break; case ERR_CAPI_INIT_FAILED: StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("CAPI_RAND"), SRC_POS, CryptoAPILastError); MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, MB_ICONERROR); break; #endif + case ERR_XTS_MASTERKEY_VULNERABLE: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_XTS_MASTERKEY_VULNERABLE"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + + case ERR_SYSENC_XTS_MASTERKEY_VULNERABLE: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_SYSENC_XTS_MASTERKEY_VULNERABLE"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + default: StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("ERR_UNKNOWN"), code); MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, ICON_HAND); } } BOOL CheckFileStreamWriteErrors (HWND hwndDlg, FILE *file, const wchar_t *fileName) { if (ferror (file)) { wchar_t s[TC_MAX_PATH]; StringCbPrintfW (s, sizeof (s), GetString ("CANNOT_WRITE_FILE_X"), fileName); ErrorDirect (s, hwndDlg); return FALSE; } return TRUE; } static BOOL CALLBACK LocalizeDialogEnum( HWND hwnd, LPARAM font) { // Localization of controls if (LocalizationActive) { int ctrlId = GetDlgCtrlID (hwnd); if (ctrlId != 0) @@ -6026,78 +5817,78 @@ wstring GetUserFriendlyVersionString (int version) versionString.insert (version > 0xfff ? 2 : 1,L"."); return (versionString); } wstring IntToWideString (int val) { wchar_t szTmp [64]; StringCbPrintfW (szTmp, sizeof(szTmp), L"%d", val); return szTmp; } wstring ArrayToHexWideString (const unsigned char* pbData, int cbData) { static wchar_t* hexChar = L"0123456789ABCDEF"; wstring result; if (pbData) { for (int i = 0; i < cbData; i++) { result += hexChar[pbData[i] >> 4]; result += hexChar[pbData[i] & 0x0F]; } } return result; } -bool HexToByte (wchar_t c, byte& b) +bool HexToByte (wchar_t c, uint8& b) { bool bRet = true; if (c >= L'0' && c <= L'9') - b = (byte) (c - L'0'); + b = (uint8) (c - L'0'); else if (c >= L'a' && c <= L'z') - b = (byte) (c - L'a' + 10); + b = (uint8) (c - L'a' + 10); else if (c >= L'A' && c <= L'Z') - b = (byte) (c - L'A' + 10); + b = (uint8) (c - L'A' + 10); else bRet = false; return bRet; } -bool HexWideStringToArray (const wchar_t* hexStr, std::vector<byte>& arr) +bool HexWideStringToArray (const wchar_t* hexStr, std::vector<uint8>& arr) { - byte b1, b2; + uint8 b1, b2; size_t i, len = wcslen (hexStr); arr.clear(); if (len %2) return false; for (i = 0; i < len/2; i++) { if (!HexToByte (*hexStr++, b1) || !HexToByte (*hexStr++, b2)) return false; arr.push_back (b1 << 4 | b2); } return true; } wstring GetTempPathString () { wchar_t tempPath[MAX_PATH]; DWORD tempLen = ::GetTempPath (ARRAYSIZE (tempPath), tempPath); if (tempLen == 0 || tempLen > ARRAYSIZE (tempPath)) throw ParameterIncorrect (SRC_POS); return wstring (tempPath); } void GetSizeString (unsigned __int64 size, wchar_t *str, size_t cbStr) { static wchar_t *b, *kb, *mb, *gb, *tb, *pb; static int serNo; @@ -6373,174 +6164,178 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg) if (ci) crypto_close (ci); MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); return FALSE; } if (benchmarkType != BENCHMARK_TYPE_PRF) { lpTestBuffer = (BYTE *) _aligned_malloc(benchmarkBufferSize - (benchmarkBufferSize % 16), 16); if (lpTestBuffer == NULL) { if (ci) crypto_close (ci); MessageBoxW (hwndDlg, GetString ("ERR_MEM_ALLOC"), lpszTitle, ICON_HAND); return FALSE; } VirtualLock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); } WaitCursor (); benchmarkTotalItems = 0; switch(benchmarkType) { case BENCHMARK_TYPE_HASH: /* Measures the speed at which each of the hash algorithms processes the message to produce a single digest. */ { BYTE digest [MAX_DIGESTSIZE]; - WHIRLPOOL_CTX wctx; - blake2s_state bctx; + #ifndef WOLFCRYPT_BACKEND + WHIRLPOOL_CTX wctx; + STREEBOG_CTX stctx; + blake2s_state bctx; + #endif sha512_ctx s2ctx; sha256_ctx s256ctx; - STREEBOG_CTX stctx; int hid, i; for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) { if (QueryPerformanceCounter (&performanceCountStart) == 0) goto counter_error; for (i = 1; i <= 2; i++) { switch (hid) { case SHA512: sha512_begin (&s2ctx); sha512_hash (lpTestBuffer, benchmarkBufferSize, &s2ctx); sha512_end ((unsigned char *) digest, &s2ctx); break; case SHA256: sha256_begin (&s256ctx); sha256_hash (lpTestBuffer, benchmarkBufferSize, &s256ctx); sha256_end ((unsigned char *) digest, &s256ctx); break; - + #ifndef WOLFCRYPT_BACKEND case BLAKE2S: blake2s_init(&bctx); blake2s_update(&bctx, lpTestBuffer, benchmarkBufferSize); blake2s_final(&bctx, (unsigned char *) digest); break; case WHIRLPOOL: WHIRLPOOL_init (&wctx); WHIRLPOOL_add (lpTestBuffer, benchmarkBufferSize, &wctx); WHIRLPOOL_finalize (&wctx, (unsigned char *) digest); break; case STREEBOG: STREEBOG_init(&stctx); STREEBOG_add(&stctx, lpTestBuffer, benchmarkBufferSize); STREEBOG_finalize(&stctx, (unsigned char *)digest); break; } - } + #endif + } if (QueryPerformanceCounter (&performanceCountEnd) == 0) goto counter_error; benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; benchmarkTable[benchmarkTotalItems].decSpeed = benchmarkTable[benchmarkTotalItems].encSpeed; benchmarkTable[benchmarkTotalItems].id = hid; benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart / 2)); StringCbPrintfW (benchmarkTable[benchmarkTotalItems].name, sizeof(benchmarkTable[benchmarkTotalItems].name),L"%s", HashGetName(hid)); benchmarkTotalItems++; } } break; case BENCHMARK_TYPE_PRF: /* Measures the time that it takes for the PKCS-5 routine to derive a header key using each of the implemented PRF algorithms. */ { int thid, i; char dk[MASTER_KEYDATA_SIZE]; char *tmp_salt = {"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"}; for (thid = FIRST_PRF_ID; thid <= LAST_PRF_ID; thid++) { if (benchmarkPreBoot && !benchmarkGPT && !HashForSystemEncryption (thid)) continue; if (QueryPerformanceCounter (&performanceCountStart) == 0) goto counter_error; for (i = 1; i <= 2; i++) { switch (thid) { case SHA512: /* PKCS-5 test with HMAC-SHA-512 used as the PRF */ derive_key_sha512 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE); break; case SHA256: /* PKCS-5 test with HMAC-SHA-256 used as the PRF */ derive_key_sha256 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE); break; - + #ifndef WOLFCRYPT_BACKEND case BLAKE2S: /* PKCS-5 test with HMAC-BLAKE2s used as the PRF */ derive_key_blake2s ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE); break; case WHIRLPOOL: /* PKCS-5 test with HMAC-Whirlpool used as the PRF */ derive_key_whirlpool ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE); break; case STREEBOG: /* PKCS-5 test with HMAC-STREEBOG used as the PRF */ derive_key_streebog("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE); break; } - } + #endif + } if (QueryPerformanceCounter (&performanceCountEnd) == 0) goto counter_error; benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; benchmarkTable[benchmarkTotalItems].id = thid; benchmarkTable[benchmarkTotalItems].decSpeed = get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot); benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (unsigned __int64) (1000 * ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart / 2)); if (benchmarkPreBoot) { /* heuristics for boot times */ if (benchmarkGPT) { benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 8) / 5; } else { if (thid == SHA256) { #ifdef _WIN64 benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 26); #else benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 24); #endif } else { #ifdef _WIN64 benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 21) / 5; #else @@ -7188,60 +6983,62 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP AddComboPair (hSizeUnit, GetString ("KB"), 1); AddComboPair (hSizeUnit, GetString ("MB"), 2); AddComboPair (hSizeUnit, GetString ("GB"), 3); // set default keyfiles size unit SendMessage (hSizeUnit, CB_SETCURSEL, 0, 0); SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents); hEntropyBar = GetDlgItem (hwndDlg, IDC_ENTROPY_BAR); SendMessage (hEntropyBar, PBM_SETRANGE32, 0, maxEntropyLevel); SendMessage (hEntropyBar, PBM_SETSTEP, 1, 0); SendMessage (hEntropyBar, PBM_SETSTATE, PBST_ERROR, 0); #ifndef VOLFORMAT if (Randinit ()) { handleError (hwndDlg, (CryptoAPILastError == ERROR_SUCCESS)? ERR_RAND_INIT_FAILED : ERR_CAPI_INIT_FAILED, SRC_POS); EndDialog (hwndDlg, IDCLOSE); } #endif SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); // 9-digit limit for the number of keyfiles (more than enough!) SendMessage (GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), EM_SETLIMITTEXT, (WPARAM) 9, 0); SetWindowText(GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), L"1"); // maximum keyfile size is 1048576, so limit the edit control to 7 characters SendMessage (GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), EM_SETLIMITTEXT, (WPARAM) 7, 0); SetWindowText(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), L"64"); // set the maximum length of the keyfile base name to (TC_MAX_PATH - 1) SendMessage (GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), EM_SETLIMITTEXT, (WPARAM) (TC_MAX_PATH - 1), 0); + + ToHyperlink (hwndDlg, IDC_LINK_KEYFILES_EXTENSIONS_WARNING); return 1; } case WM_TIMER: { wchar_t tmp[4]; unsigned char tmpByte; int col, row; DWORD mouseEventsCounter; RandpeekBytes (hwndDlg, randPool, sizeof (randPool), &mouseEventsCounter); ProcessEntropyEstimate (hEntropyBar, &mouseEventsInitialCount, mouseEventsCounter, maxEntropyLevel, &mouseEntropyGathered); if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) { outputDispBuffer[0] = 0; for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) { for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) { if (bDisplayPoolContents) { tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; StringCbPrintfW (tmp, sizeof(tmp), bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != L'&') ? L" %c " : L" . ") : L"%02X ", tmpByte); } else if (bUseMask) { /* use mask to compute a randomized ASCII representation */ @@ -7275,60 +7072,66 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP goto exit; } if (lw == IDC_PRF_ID && hw == CBN_SELCHANGE) { hid = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETCURSEL, 0, 0); hash_algo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETITEMDATA, hid, 0); RandSetHashFunction (hash_algo); return 1; } if (lw == IDC_DISPLAY_POOL_CONTENTS) { if (!(bDisplayPoolContents = GetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS))) { wchar_t tmp[RNG_POOL_SIZE+1]; wmemset (tmp, L' ', ARRAYSIZE(tmp)); tmp [RNG_POOL_SIZE] = 0; SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); } return 1; } if (lw == IDC_KEYFILES_RANDOM_SIZE) { EnableWindow(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), !GetCheckBox (hwndDlg, IDC_KEYFILES_RANDOM_SIZE)); EnableWindow(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE_UNIT), !GetCheckBox (hwndDlg, IDC_KEYFILES_RANDOM_SIZE)); } + if (lw == IDC_LINK_KEYFILES_EXTENSIONS_WARNING) + { + Applink ("keyfilesextensions"); + return 1; + } + if (lw == IDC_GENERATE_AND_SAVE_KEYFILE) { wchar_t szNumber[16] = {0}; wchar_t szFileBaseName[TC_MAX_PATH]; wchar_t szDirName[TC_MAX_PATH]; wchar_t szFileName [2*TC_MAX_PATH + 16]; unsigned char *keyfile = NULL; int fhKeyfile = -1, status; long keyfilesCount = 0, i; unsigned long long keyfilesSize = 0, remainingBytes = 0; int selectedUnitIndex, selectedUnitFactor, loopIndex, rndBytesLength; DWORD dwLastError = 0; wchar_t* fileExtensionPtr = 0; wchar_t szSuffix[32]; BOOL bRandomSize = GetCheckBox (hwndDlg, IDC_KEYFILES_RANDOM_SIZE); if (!GetWindowText(GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), szNumber, ARRAYSIZE(szNumber))) szNumber[0] = 0; keyfilesCount = wcstoul(szNumber, NULL, 0); if (keyfilesCount <= 0 || keyfilesCount == LONG_MAX) { Warning("KEYFILE_INCORRECT_NUMBER", hwndDlg); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), TRUE); return 1; } if (!bRandomSize) { if (!GetWindowText(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), szNumber, ARRAYSIZE(szNumber))) @@ -7346,61 +7149,61 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP if (keyfilesSize < 64) { Warning("KEYFILE_INCORRECT_SIZE", hwndDlg); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), TRUE); return 1; } } if (!GetWindowText(GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), szFileBaseName, TC_MAX_PATH)) szFileBaseName[0] = 0; // Trim trailing space if (TrimWhiteSpace(szFileBaseName) == 0) { Warning("KEYFILE_EMPTY_BASE_NAME", hwndDlg); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), TRUE); return 1; } if (!IsValidFileName(szFileBaseName)) { Warning("KEYFILE_INVALID_BASE_NAME", hwndDlg); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), TRUE); return 1; } fileExtensionPtr = wcsrchr(szFileBaseName, L'.'); /* Select directory */ - if (!BrowseDirectories (hwndDlg, "SELECT_KEYFILE_GENERATION_DIRECTORY", szDirName)) + if (!BrowseDirectories (hwndDlg, "SELECT_KEYFILE_GENERATION_DIRECTORY", szDirName, NULL)) return 1; if (szDirName[wcslen(szDirName) - 1] != L'\\' && szDirName[wcslen(szDirName) - 1] != L'/') StringCbCat(szDirName, sizeof(szDirName), L"\\"); WaitCursor(); keyfile = (unsigned char*) TCalloc(KEYFILE_MAX_READ_LEN); for (i= 0; i < keyfilesCount; i++) { StringCbCopyW(szFileName, sizeof(szFileName), szDirName); if (i > 0) { StringCbPrintfW(szSuffix, sizeof(szSuffix), L"_%d", i); // Append the counter to the name if (fileExtensionPtr) { StringCchCatN(szFileName, ARRAYSIZE(szFileName), szFileBaseName, (size_t) (fileExtensionPtr - szFileBaseName)); StringCbCat(szFileName, sizeof(szFileName), szSuffix); StringCbCat(szFileName, sizeof(szFileName), fileExtensionPtr); } else { StringCbCat(szFileName, sizeof(szFileName), szFileBaseName); StringCbCat(szFileName, sizeof(szFileName), szSuffix); } } else @@ -8419,61 +8222,61 @@ int DriverUnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forced) && !Silent) { wchar_t msg[4096]; VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo] = TRUE; StringCbPrintfW (msg, sizeof(msg), GetString ("DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"), nDosDriveNo + L'A'); SetForegroundWindow (hwndDlg); MessageBoxW (hwndDlg, msg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); } #endif // #ifdef TCMOUNT return unmount.nReturnCode; } void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap) { DEV_BROADCAST_VOLUME dbv; DWORD_PTR dwResult; LONG eventId = 0; int i; if (DeviceChangeBroadcastDisabled) return; if (message == DBT_DEVICEARRIVAL) eventId = SHCNE_DRIVEADD; else if (message == DBT_DEVICEREMOVECOMPLETE) eventId = SHCNE_DRIVEREMOVED; - else if (IsOSAtLeast (WIN_7) && message == DBT_DEVICEREMOVEPENDING) // Explorer on Windows 7 holds open handles of all drives when 'Computer' is expanded in navigation pane. SHCNE_DRIVEREMOVED must be used as DBT_DEVICEREMOVEPENDING is ignored. + else if (message == DBT_DEVICEREMOVEPENDING) // Explorer on Windows 7 holds open handles of all drives when 'Computer' is expanded in navigation pane. SHCNE_DRIVEREMOVED must be used as DBT_DEVICEREMOVEPENDING is ignored. eventId = SHCNE_DRIVEREMOVED; if (driveMap == 0) driveMap = (1 << nDosDriveNo); if (eventId != 0) { for (i = 0; i < 26; i++) { if (driveMap & (1 << i)) { wchar_t root[] = { (wchar_t) i + L'A', L':', L'\\', 0 }; SHChangeNotify (eventId, SHCNF_PATH, root, NULL); } } } dbv.dbcv_size = sizeof (dbv); dbv.dbcv_devicetype = DBT_DEVTYP_VOLUME; dbv.dbcv_reserved = 0; dbv.dbcv_unitmask = driveMap; dbv.dbcv_flags = 0; UINT timeOut = 1000; // SHChangeNotify() works on Vista, so the Explorer does not require WM_DEVICECHANGE if (CurrentOSMajor >= 6) timeOut = 100; @@ -8934,147 +8737,144 @@ retry: mount.bMountReadOnly = mountOptions->ReadOnly; mount.bMountRemovable = mountOptions->Removable; mount.bPreserveTimestamp = mountOptions->PreserveTimestamp; if (mountOptions->DisableMountManager) mount.bMountManager = FALSE; else mount.bMountManager = TRUE; mount.pkcs5_prf = pkcs5; mount.VolumePim = pim; wstring path = volumePath; if (path.find (L"\\\\?\\") == 0) { // Remove \\?\ prefix path = path.substr (4); StringCchCopyW (volumePath, TC_MAX_PATH, path.c_str()); } if (path.find (L"Volume{") == 0 && path.rfind (L"}\\") == path.size() - 2) { wstring resolvedPath = VolumeGuidPathToDevicePath (path); if (!resolvedPath.empty()) StringCchCopyW (volumePath, TC_MAX_PATH, resolvedPath.c_str()); } if ((path.length () >= 3) && (_wcsnicmp (path.c_str(), L"ID:", 3) == 0)) { - std::vector<byte> arr; + std::vector<uint8> arr; if ( (path.length() == (3 + 2*VOLUME_ID_SIZE)) && HexWideStringToArray (path.c_str() + 3, arr) && (arr.size() == VOLUME_ID_SIZE) ) { useVolumeID = TRUE; bDevice = TRUE; memcpy (volumeID, &arr[0], VOLUME_ID_SIZE); } else { if (!quiet) Error ("VOLUME_ID_INVALID", hwndDlg); SetLastError (ERROR_INVALID_PARAMETER); return -1; } } else CreateFullVolumePath (mount.wszVolume, sizeof(mount.wszVolume), volumePath, &bDevice); if (!bDevice) { // put default values mount.BytesPerSector = 512; mount.BytesPerPhysicalSector = 512; mount.MaximumTransferLength = 65536; mount.MaximumPhysicalPages = 17; mount.AlignmentMask = 0; // UNC path if (path.find (L"\\\\") == 0) { StringCbCopyW (mount.wszVolume, sizeof (mount.wszVolume), (L"UNC" + path.substr (1)).c_str()); } if (GetVolumePathName (volumePath, root, ARRAYSIZE (root) - 1)) { DWORD bps, flags, d; if (GetDiskFreeSpace (root, &d, &bps, &d, &d)) { mount.BytesPerSector = bps; mount.BytesPerPhysicalSector = bps; } - if (IsOSAtLeast (WIN_VISTA)) + if ( (wcslen(root) >= 2) + && (root[1] == L':') + && (towupper(root[0]) >= L'A' && towupper(root[0]) <= L'Z') + ) { - if ( (wcslen(root) >= 2) - && (root[1] == L':') - && (towupper(root[0]) >= L'A' && towupper(root[0]) <= L'Z') - ) - { - wstring drivePath = L"\\\\.\\X:"; - HANDLE dev = INVALID_HANDLE_VALUE; - VOLUME_DISK_EXTENTS extents = {0}; - DWORD dwResult = 0; - drivePath[4] = root[0]; + wstring drivePath = L"\\\\.\\X:"; + HANDLE dev = INVALID_HANDLE_VALUE; + VOLUME_DISK_EXTENTS extents = {0}; + DWORD dwResult = 0; + drivePath[4] = root[0]; - if ((dev = CreateFile (drivePath.c_str(),0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) + if ((dev = CreateFile (drivePath.c_str(),0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) + { + if (DeviceIoControl (dev, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extents, sizeof(extents), &dwResult, NULL)) { - if (DeviceIoControl (dev, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extents, sizeof(extents), &dwResult, NULL)) + if (extents.NumberOfDiskExtents > 0) { - if (extents.NumberOfDiskExtents > 0) + STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR accessDesc; + STORAGE_ADAPTER_DESCRIPTOR adapterDesc; + + if (GetPhysicalDriveStorageInformation (extents.Extents[0].DiskNumber, &accessDesc, &adapterDesc)) { - STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR accessDesc; - STORAGE_ADAPTER_DESCRIPTOR adapterDesc; + if (accessDesc.Size >= sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR)) + { + mount.BytesPerSector = accessDesc.BytesPerLogicalSector; + mount.BytesPerPhysicalSector = accessDesc.BytesPerPhysicalSector; + } - if (GetPhysicalDriveStorageInformation (extents.Extents[0].DiskNumber, &accessDesc, &adapterDesc)) + if (adapterDesc.Size >= sizeof (STORAGE_ADAPTER_DESCRIPTOR)) { - if (accessDesc.Size >= sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR)) - { - mount.BytesPerSector = accessDesc.BytesPerLogicalSector; - mount.BytesPerPhysicalSector = accessDesc.BytesPerPhysicalSector; - } - - if (adapterDesc.Size >= sizeof (STORAGE_ADAPTER_DESCRIPTOR)) - { - mount.MaximumTransferLength = adapterDesc.MaximumTransferLength; - mount.MaximumPhysicalPages = adapterDesc.MaximumPhysicalPages; - mount.AlignmentMask = adapterDesc.AlignmentMask; - } + mount.MaximumTransferLength = adapterDesc.MaximumTransferLength; + mount.MaximumPhysicalPages = adapterDesc.MaximumPhysicalPages; + mount.AlignmentMask = adapterDesc.AlignmentMask; } } } - CloseHandle (dev); } + CloseHandle (dev); } } // Read-only host filesystem if (!mount.bMountReadOnly && GetVolumeInformation (root, NULL, 0, NULL, &d, &flags, NULL, 0)) mount.bMountReadOnly = (flags & FILE_READ_ONLY_VOLUME) != 0; } } if (mountOptions->PartitionInInactiveSysEncScope) { if (mount.wszVolume == NULL || swscanf_s ((const wchar_t *) mount.wszVolume, WIDE("\\Device\\Harddisk%d\\Partition"), &mount.nPartitionInInactiveSysEncScopeDriveNo) != 1) { if (!quiet) Warning ("NO_SYSENC_PARTITION_SELECTED", hwndDlg); return -1; } mount.bPartitionInInactiveSysEncScope = TRUE; } if (!quiet) { MountThreadParam mountThreadParam; mountThreadParam.pmount = &mount; mountThreadParam.useVolumeID = useVolumeID; memcpy (mountThreadParam.volumeID, volumeID, VOLUME_ID_SIZE); mountThreadParam.pbResult = &bResult; @@ -9174,112 +8974,129 @@ retry: if (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, &openTestStruct, sizeof (OPEN_TEST_STRUCT), &openTestStruct, sizeof (OPEN_TEST_STRUCT), &dwResult, NULL) && openTestStruct.TCBootLoaderDetected) WarningDirect ((GetWrongPasswordErrorMessage (hwndDlg) + L"\n\n" + GetString ("HIDDEN_VOL_PROT_PASSWORD_US_KEYB_LAYOUT")).c_str(), hwndDlg); else handleError (hwndDlg, mount.nReturnCode, SRC_POS); } } else handleError (hwndDlg, mount.nReturnCode, SRC_POS); } return 0; } if (!quiet) handleError (hwndDlg, mount.nReturnCode, SRC_POS); return 0; } // Mount successful if (mount.UseBackupHeader != mountOptions->UseBackupHeader && mount.UseBackupHeader) { if (bReportWrongPassword && !Silent) Warning ("HEADER_DAMAGED_AUTO_USED_HEADER_BAK", hwndDlg); } LastMountedVolumeDirty = mount.FilesystemDirty; + if (mount.VolumeMasterKeyVulnerable + && !Silent) + { + Warning ("ERR_XTS_MASTERKEY_VULNERABLE", hwndDlg); + } + if (mount.FilesystemDirty) { wchar_t msg[1024]; wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_VOLUME_DIRTY"), mountPoint); if (AskWarnYesNoStringTopmost (msg, hwndDlg) == IDYES) CheckFilesystem (hwndDlg, driveNo, TRUE); } if (mount.VolumeMountedReadOnlyAfterAccessDenied && !Silent && !bDevice && !FileHasReadOnlyAttribute (volumePath) && !IsFileOnReadOnlyFilesystem (volumePath)) { wchar_t msg[1024]; wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_CONTAINER_FORCED_READ_ONLY"), mountPoint); WarningDirect (msg, hwndDlg); } if (mount.VolumeMountedReadOnlyAfterAccessDenied && !Silent && bDevice) { wchar_t msg[1024]; wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_DEVICE_FORCED_READ_ONLY"), mountPoint); WarningDirect (msg, hwndDlg); } if (mount.VolumeMountedReadOnlyAfterDeviceWriteProtected && !Silent && wcsstr (volumePath, L"\\Device\\Harddisk") == volumePath) { wchar_t msg[1024]; wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_DEVICE_FORCED_READ_ONLY_WRITE_PROTECTION"), mountPoint); WarningDirect (msg, hwndDlg); if (CurrentOSMajor >= 6 && wcsstr (volumePath, L"\\Device\\HarddiskVolume") != volumePath && AskNoYes ("ASK_REMOVE_DEVICE_WRITE_PROTECTION", hwndDlg) == IDYES) { RemoveDeviceWriteProtection (hwndDlg, volumePath); } } + if (mount.VolumeMountedReadOnlyAfterPartialSysEnc + && !Silent + && bDevice) + { + wchar_t msg[1024]; + wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; + StringCbPrintfW (msg, sizeof(msg), GetString ("PARTIAL_SYSENC_MOUNT_READONLY"), mountPoint); + + WarningDirect (msg, hwndDlg); + } + if (mount.wszLabel[0] && !mount.bDriverSetLabel) { // try setting the drive label on user-mode using registry UpdateDriveCustomLabel (driveNo, mount.wszLabel, TRUE); } ResetWrongPwdRetryCount (); BroadcastDeviceChange (DBT_DEVICEARRIVAL, driveNo, 0); if (mount.bExclusiveAccess == FALSE) return 2; return 1; } #endif typedef struct { int nDosDriveNo; BOOL forced; int dismountMaxRetries; DWORD retryDelay; int* presult; DWORD dwLastError; } UnmountThreadParam; void CALLBACK UnmountWaitThreadProc(void* pArg, HWND hwnd) { @@ -9312,66 +9129,63 @@ static BOOL UnmountVolumeBase (HWND hwndDlg, int nDosDriveNo, BOOL forceUnmount, retry: BroadcastDeviceChange (DBT_DEVICEREMOVEPENDING, nDosDriveNo, 0); param.nDosDriveNo = nDosDriveNo; param.forced = forced; param.dismountMaxRetries = dismountMaxRetries; param.retryDelay = retryDelay; param.presult = &result; if (Silent) { UnmountWaitThreadProc (¶m, hwndDlg); } else { ShowWaitDialog (hwndDlg, FALSE, UnmountWaitThreadProc, ¶m); } SetLastError (param.dwLastError); if (result != 0) { if (result == ERR_FILES_OPEN && !Silent) { if (IDYES == AskWarnYesNoTopmost ("UNMOUNT_LOCK_FAILED", hwndDlg)) { forced = TRUE; goto retry; } - if (IsOSAtLeast (WIN_7)) - { - // Undo SHCNE_DRIVEREMOVED - wchar_t root[] = { (wchar_t) nDosDriveNo + L'A', L':', L'\\', 0 }; - SHChangeNotify (SHCNE_DRIVEADD, SHCNF_PATH, root, NULL); - } + // Undo SHCNE_DRIVEREMOVED + wchar_t root[] = { (wchar_t) nDosDriveNo + L'A', L':', L'\\', 0 }; + SHChangeNotify (SHCNE_DRIVEADD, SHCNF_PATH, root, NULL); return FALSE; } Error ("UNMOUNT_FAILED", hwndDlg); return FALSE; } BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, nDosDriveNo, 0); return TRUE; } BOOL UnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forceUnmount) { return UnmountVolumeBase (hwndDlg, nDosDriveNo, forceUnmount, FALSE); } BOOL UnmountVolumeAfterFormatExCall (HWND hwndDlg, int nDosDriveNo) { return UnmountVolumeBase (hwndDlg, nDosDriveNo, FALSE, TRUE); } BOOL IsPasswordCacheEmpty (void) { DWORD dw; return !DeviceIoControl (hDriver, TC_IOCTL_GET_PASSWORD_CACHE_STATUS, 0, 0, 0, 0, &dw, 0); } @@ -9381,61 +9195,61 @@ BOOL IsMountedVolumeID (BYTE volumeID[VOLUME_ID_SIZE]) DWORD dwResult; int i; memset (&mlist, 0, sizeof (mlist)); if ( !DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, sizeof (mlist), &mlist, sizeof (mlist), &dwResult, NULL) || (mlist.ulMountedDrives >= (1 << 26)) ) { return FALSE; } if (mlist.ulMountedDrives) { for (i=0 ; i<26; i++) { if ((mlist.ulMountedDrives & (1 << i)) && (0 == memcmp (mlist.volumeID[i], volumeID, VOLUME_ID_SIZE))) return TRUE; } } return FALSE; } BOOL IsMountedVolume (const wchar_t *volname) { if ((wcslen (volname) == (3 + 2*VOLUME_ID_SIZE)) && _wcsnicmp (volname, L"ID:", 3) == 0) { /* Volume ID specified. Use it for matching mounted volumes. */ - std::vector<byte> arr; + std::vector<uint8> arr; if (HexWideStringToArray (&volname[3], arr) && (arr.size() == VOLUME_ID_SIZE)) { return IsMountedVolumeID (&arr[0]); } } else { MOUNT_LIST_STRUCT mlist; DWORD dwResult; int i; wchar_t volume[TC_MAX_PATH*2+16]; StringCbCopyW (volume, sizeof(volume), volname); if (wcsstr (volname, L"\\Device\\") != volname) StringCbPrintfW(volume, sizeof(volume), L"\\??\\%s", volname); wstring resolvedPath = VolumeGuidPathToDevicePath (volname); if (!resolvedPath.empty()) StringCbCopyW (volume, sizeof (volume), resolvedPath.c_str()); memset (&mlist, 0, sizeof (mlist)); if ( !DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, sizeof (mlist), &mlist, sizeof (mlist), &dwResult, NULL) || (mlist.ulMountedDrives >= (1 << 26)) ) { return FALSE; } @@ -9517,63 +9331,60 @@ BOOL IsBuiltInAdmin () { HANDLE procToken; DWORD size; if (!IsAdmin() || !OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &procToken)) return FALSE; finally_do_arg (HANDLE, procToken, { CloseHandle (finally_arg); }); if (GetTokenInformation (procToken, TokenUser, NULL, 0, &size) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE; TOKEN_USER *tokenUser = (TOKEN_USER *) malloc (size); if (!tokenUser) return FALSE; finally_do_arg (void *, tokenUser, { free (finally_arg); }); if (!GetTokenInformation (procToken, TokenUser, tokenUser, size, &size)) return FALSE; return IsWellKnownSid (tokenUser->User.Sid, WinAccountAdministratorSid); } BOOL IsUacSupported () { HKEY hkey; DWORD value = 1, size = sizeof (DWORD); - if (!IsOSAtLeast (WIN_VISTA)) - return FALSE; - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 0, KEY_READ, &hkey) == ERROR_SUCCESS) { if (RegQueryValueEx (hkey, L"EnableLUA", 0, 0, (LPBYTE) &value, &size) != ERROR_SUCCESS) value = 1; RegCloseKey (hkey); } return value != 0; } BOOL ResolveSymbolicLink (const wchar_t *symLinkName, PWSTR targetName, size_t cbTargetName) { BOOL bResult; DWORD dwResult; RESOLVE_SYMLINK_STRUCT resolve; memset (&resolve, 0, sizeof(resolve)); StringCbCopyW (resolve.symLinkName, sizeof(resolve.symLinkName), symLinkName); bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_RESOLVED_SYMLINK, &resolve, sizeof (resolve), &resolve, sizeof (resolve), &dwResult, NULL); StringCbCopyW (targetName, cbTargetName, resolve.targetName); return bResult; } @@ -10186,123 +9997,101 @@ void ManageStartupSeqWiz (BOOL bRemove, const wchar_t *arg) if (wcslen (arg) > 0) { StringCchCatW (exe, exeSize, L"\" "); StringCchCatW (exe, exeSize, arg); } WriteRegistryString (regk, L"VeraCrypt Format", exe); free(exe); } else DeleteRegistryValue (regk, L"VeraCrypt Format"); } // Delete the last used Windows file selector path for TrueCrypt from the registry void CleanLastVisitedMRU (void) { WCHAR exeFilename[MAX_PATH]; WCHAR *strToMatch; WCHAR strTmp[4096]; WCHAR regPath[128]; WCHAR key[64]; int id, len; GetModuleFileNameW (NULL, exeFilename, sizeof (exeFilename) / sizeof(exeFilename[0])); strToMatch = wcsrchr (exeFilename, L'\\') + 1; - StringCbPrintfW (regPath, sizeof(regPath), L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisited%sMRU", IsOSAtLeast (WIN_VISTA) ? L"Pidl" : L""); + StringCbCopyW (regPath, sizeof(regPath), L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU"); - for (id = (IsOSAtLeast (WIN_VISTA) ? 0 : L'a'); id <= (IsOSAtLeast (WIN_VISTA) ? 1000 : L'z'); id++) + for (id = 0; id <= 1000; id++) { *strTmp = 0; - StringCbPrintfW (key, sizeof(key), (IsOSAtLeast (WIN_VISTA) ? L"%d" : L"%c"), id); + StringCbPrintfW (key, sizeof(key), L"%d", id); if ((len = ReadRegistryBytes (regPath, key, (char *) strTmp, sizeof (strTmp))) > 0) { if (_wcsicmp (strTmp, strToMatch) == 0) { char buf[65536], bufout[sizeof (buf)]; // Overwrite the entry with zeroes while keeping its original size memset (strTmp, 0, len); if (!WriteRegistryBytes (regPath, key, (char *) strTmp, len)) MessageBoxW (NULL, GetString ("CLEAN_WINMRU_FAILED"), lpszTitle, ICON_HAND); DeleteRegistryValue (regPath, key); // Remove ID from MRUList - if (IsOSAtLeast (WIN_VISTA)) - { - int *p = (int *)buf; - int *pout = (int *)bufout; - int l; - - l = len = ReadRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", buf, sizeof (buf)); - while (l > 0) - { - l -= sizeof (int); + int *p = (int *)buf; + int *pout = (int *)bufout; + int l; - if (*p == id) - { - p++; - len -= sizeof (int); - continue; - } - *pout++ = *p++; - } - - WriteRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", bufout, len); - } - else + l = len = ReadRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", buf, sizeof (buf)); + while (l > 0) { - wchar_t *p = (wchar_t*) buf; - wchar_t *pout = (wchar_t*) bufout; + l -= sizeof (int); - ReadRegistryString (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", L"MRUList", L"", (wchar_t*) buf, sizeof (buf)); - while (*p) + if (*p == id) { - if (*p == id) - { - p++; - continue; - } - *pout++ = *p++; + p++; + len -= sizeof (int); + continue; } - *pout++ = 0; - - WriteRegistryString (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", L"MRUList", (wchar_t*) bufout); + *pout++ = *p++; } + WriteRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", bufout, len); + break; } } } } #ifndef SETUP void ClearHistory (HWND hwndDlgItem) { ArrowWaitCursor (); ClearCombo (hwndDlgItem); DumpCombo (hwndDlgItem, TRUE); CleanLastVisitedMRU (); NormalCursor (); } #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; @@ -10429,61 +10218,61 @@ std::wstring GetServiceConfigPath (const wchar_t *fileName, bool useLegacy) } // Returns 0 if an error occurs or the drive letter (as an upper-case char) of the system partition (e.g. 'C'); wchar_t GetSystemDriveLetter (void) { wchar_t systemDir [MAX_PATH]; if (GetSystemDirectory (systemDir, ARRAYSIZE (systemDir))) return (wchar_t) (towupper (systemDir [0])); else return 0; } void TaskBarIconDisplayBalloonTooltip (HWND hwnd, wchar_t *headline, wchar_t *text, BOOL warning) { NOTIFYICONDATAW tnid; ZeroMemory (&tnid, sizeof (tnid)); tnid.cbSize = sizeof (tnid); tnid.hWnd = hwnd; tnid.uID = IDI_TRUECRYPT_ICON; //tnid.uVersion = (IsOSAtLeast (WIN_VISTA) ? NOTIFYICON_VERSION_4 : NOTIFYICON_VERSION); //Shell_NotifyIconW (NIM_SETVERSION, &tnid); tnid.uFlags = NIF_INFO; tnid.dwInfoFlags = (warning ? NIIF_WARNING : NIIF_INFO); - tnid.uTimeout = (IsOSAtLeast (WIN_VISTA) ? 1000 : 5000); // in ms + tnid.uTimeout = 1000; // in ms StringCbCopyW (tnid.szInfoTitle, sizeof(tnid.szInfoTitle), headline); StringCbCopyW (tnid.szInfo, sizeof(tnid.szInfo),text); // Display the balloon tooltip quickly twice in a row to avoid the slow and unwanted "fade-in" phase Shell_NotifyIconW (NIM_MODIFY, &tnid); Shell_NotifyIconW (NIM_MODIFY, &tnid); } // Either of the pointers may be NULL void InfoBalloon (char *headingStringId, char *textStringId, HWND hwnd) { if (Silent) return; TaskBarIconDisplayBalloonTooltip (hwnd, headingStringId == NULL ? L"VeraCrypt" : GetString (headingStringId), textStringId == NULL ? L" " : GetString (textStringId), FALSE); } // Either of the pointers may be NULL void InfoBalloonDirect (wchar_t *headingString, wchar_t *textString, HWND hwnd) { if (Silent) return; TaskBarIconDisplayBalloonTooltip (hwnd, @@ -11026,71 +10815,62 @@ void Debug (char *format, ...) } void DebugMsgBox (char *format, ...) { char buf[1024]; va_list val; va_start(val, format); StringCbVPrintfA (buf, sizeof (buf), format, val); va_end(val); MessageBoxA (MainDlg, buf, "VeraCrypt debug", 0); } BOOL IsSupportedOS () { BOOL bRet = FALSE; #ifdef SETUP static const wchar_t* szWin7KBs[] = {L"KB3033929", L"KB4474419"}; static const wchar_t* szWinVistaKBs[] = {L"KB4039648", L"KB4474419"}; if (IsOSAtLeast(WIN_8)) bRet = TRUE; else if (IsOSAtLeast(WIN_7)) { if (OneOfKBsInstalled(szWin7KBs, 2)) bRet = TRUE; else MessageBoxW (NULL, L"SHA-2 support missing from Windows.\n\nPlease Install KB3033929 or KB4474419", lpszTitle, MB_ICONWARNING); } - else if (IsOSAtLeast(WIN_VISTA)) - { - if (OneOfKBsInstalled(szWinVistaKBs, 2)) - bRet = TRUE; - else - MessageBoxW (NULL, L"SHA-2 support missing from Windows.\n\nPlease Install KB4039648 or KB4474419", lpszTitle, MB_ICONWARNING); - } - else if (IsOSAtLeast(WIN_XP)) - bRet = TRUE; #else - if (IsOSAtLeast(WIN_XP)) + if (IsOSAtLeast(WIN_7)) bRet = TRUE; #endif return bRet; } BOOL Is64BitOs() { #ifdef _WIN64 return TRUE; #else static BOOL isWow64 = FALSE; static BOOL valid = FALSE; typedef BOOL(__stdcall* LPFN_ISWOW64PROCESS) (HANDLE hProcess, PBOOL Wow64Process); typedef BOOL(__stdcall* LPFN_ISWOW64PROCESS2)( HANDLE hProcess, USHORT* pProcessMachine, USHORT* pNativeMachine ); LPFN_ISWOW64PROCESS fnIsWow64Process; LPFN_ISWOW64PROCESS2 fnIsWow64Process2; if (valid) return isWow64; fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process"); fnIsWow64Process2 = (LPFN_ISWOW64PROCESS2)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process2"); if (fnIsWow64Process2) { @@ -11374,60 +11154,64 @@ void Applink (const char *dest) } else if (strcmp(dest, "beginnerstutorial") == 0 || strcmp(dest,"tutorial") == 0) { StringCbCopyW (page, sizeof (page),L"Beginner%27s%20Tutorial.html"); } else if (strcmp(dest, "releasenotes") == 0 || strcmp(dest, "history") == 0) { StringCbCopyW (page, sizeof (page),L"Release%20Notes.html"); } else if (strcmp(dest, "hwacceleration") == 0) { StringCbCopyW (page, sizeof (page),L"Hardware%20Acceleration.html"); } else if (strcmp(dest, "parallelization") == 0) { StringCbCopyW (page, sizeof (page),L"Parallelization.html"); } else if (strcmp(dest, "help") == 0) { StringCbCopyW (page, sizeof (page),L"Documentation.html"); } else if (strcmp(dest, "onlinehelp") == 0) { StringCbCopyW (url, sizeof (url),L"https://www.veracrypt.fr/en/Documentation.html"); buildUrl = FALSE; } else if (strcmp(dest, "keyfiles") == 0) { StringCbCopyW (page, sizeof (page),L"Keyfiles.html"); } + else if (strcmp(dest, "keyfilesextensions") == 0) + { + StringCbCopyW (page, sizeof (page),L"Avoid%20Third-Party%20File%20Extensions.html"); + } else if (strcmp(dest, "introcontainer") == 0) { StringCbCopyW (page, sizeof (page),L"Creating%20New%20Volumes.html"); } else if (strcmp(dest, "introsysenc") == 0) { StringCbCopyW (page, sizeof (page),L"System%20Encryption.html"); } else if (strcmp(dest, "hiddensysenc") == 0) { StringCbCopyW (page, sizeof (page),L"VeraCrypt%20Hidden%20Operating%20System.html"); } else if (strcmp(dest, "sysencprogressinfo") == 0) { StringCbCopyW (page, sizeof (page),L"System%20Encryption.html"); } else if (strcmp(dest, "hiddenvolume") == 0) { StringCbCopyW (page, sizeof (page),L"Hidden%20Volume.html"); } else if (strcmp(dest, "aes") == 0) { StringCbCopyW (page, sizeof (page),L"AES.html"); } else if (strcmp(dest, "serpent") == 0) { StringCbCopyW (page, sizeof (page),L"Serpent.html"); } else if (strcmp(dest, "twofish") == 0) { @@ -11459,83 +11243,101 @@ void Applink (const char *dest) StringCbCopyW (page, sizeof (page),L"System%20Favorite%20Volumes.html"); } else if (strcmp(dest, "favorites") == 0) { StringCbCopyW (page, sizeof (page),L"Favorite%20Volumes.html"); } else if (strcmp(dest, "hiddenvolprotection") == 0) { StringCbCopyW (page, sizeof (page),L"Protection%20of%20Hidden%20Volumes.html"); } else if (strcmp(dest, "faq") == 0) { StringCbCopyW (page, sizeof (page),L"FAQ.html"); } else if (strcmp(dest, "downloads") == 0) { StringCbCopyW (page, sizeof (page),L"Downloads.html"); } else if (strcmp(dest, "news") == 0) { StringCbCopyW (page, sizeof (page),L"News.html"); } else if (strcmp(dest, "contact") == 0) { StringCbCopyW (page, sizeof (page),L"Contact.html"); } else if (strcmp(dest, "pim") == 0) { StringCbCopyW (page, sizeof (page),L"Personal%20Iterations%20Multiplier%20%28PIM%29.html"); } + else if (strcmp(dest, "memoryprotection") == 0) + { + StringCbCopyW (page, sizeof (page),L"VeraCrypt%20Memory%20Protection.html"); + } else { StringCbCopyW (url, sizeof (url),TC_APPLINK); buildUrl = FALSE; } if (buildUrl) { + // in case of setup, open the online documentation if we are connected to Internet because existing documentation may be outdated +#ifdef SETUP + if (IsInternetConnected()) + { + StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page); + buildUrl = FALSE; + } + else + { + StringCbPrintfW (url, sizeof (url), L"file:///%sdocs/html/en/%s", installDir, page); + CorrectURL (url); + } +#else StringCbPrintfW (url, sizeof (url), L"file:///%sdocs/html/en/%s", installDir, page); CorrectURL (url); +#endif } - if (IsOSAtLeast (WIN_VISTA) && IsAdmin ()) + if (IsAdmin ()) { int openDone = 0; if (buildUrl) { wchar_t pageFileName [TC_MAX_PATH] = {0}; DWORD cchUnescaped = ARRAYSIZE(pageFileName); StringCbCopyW (pageFileName, sizeof(pageFileName), page); /* remove escape sequences from the page name before calling FileExists function */ - if (S_OK == UrlUnescapeWFn (pageFileName, pageFileName, &cchUnescaped, URL_UNESCAPE_INPLACE)) + if (S_OK == UrlUnescapeW (pageFileName, pageFileName, &cchUnescaped, URL_UNESCAPE_INPLACE)) { std::wstring pageFullPath = installDir; pageFullPath += L"docs\\html\\en\\"; pageFullPath += pageFileName; if (!FileExists (pageFullPath.c_str())) { // fallback to online resources StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page); SafeOpenURL (url); openDone = 1; } } } if (!openDone) { SafeOpenURL (url); } } else { r = (int) ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL); if (((r == ERROR_FILE_NOT_FOUND) || (r == ERROR_PATH_NOT_FOUND)) && buildUrl) { // fallback to online resources StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page); ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL); } @@ -11553,77 +11355,76 @@ wchar_t *RelativePath2Absolute (wchar_t *szFileName) && wcsstr (szFileName, L"Volume{") != szFileName) { wchar_t path[MAX_PATH*2]; GetCurrentDirectory (MAX_PATH, path); if (path[wcslen (path) - 1] != L'\\') StringCbCatW (path, (MAX_PATH * 2), L"\\"); StringCbCatW (path, (MAX_PATH * 2), szFileName); StringCbCopyW (szFileName, MAX_PATH + 1, path); // szFileName size is always at least (MAX_PATH + 1) } return szFileName; } void HandleDriveNotReadyError (HWND hwnd) { HKEY hkey = 0; DWORD value = 0, size = sizeof (DWORD); if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\MountMgr", 0, KEY_READ, &hkey) != ERROR_SUCCESS) return; if (RegQueryValueEx (hkey, L"NoAutoMount", 0, 0, (LPBYTE) &value, &size) == ERROR_SUCCESS && value != 0) { Warning ("SYS_AUTOMOUNT_DISABLED", hwnd); } - else if (nCurrentOS == WIN_VISTA && CurrentOSServicePack < 1) - Warning ("SYS_ASSIGN_DRIVE_LETTER", hwnd); else Warning ("DEVICE_NOT_READY_ERROR", hwnd); RegCloseKey (hkey); } BOOL CALLBACK CloseTCWindowsEnum (HWND hwnd, LPARAM lParam) { LONG_PTR userDataVal = GetWindowLongPtrW (hwnd, GWLP_USERDATA); if ((userDataVal == (LONG_PTR) 'VERA') || (userDataVal == (LONG_PTR) 'TRUE')) // Prior to 1.0e, 'TRUE' was used for VeraCrypt dialogs { wchar_t name[1024] = { 0 }; GetWindowText (hwnd, name, ARRAYSIZE (name) - 1); - if (hwnd != MainDlg && wcsstr (name, L"VeraCrypt")) + // check if the window is a VeraCrypt window, excluding current process main dialog and VeraCrypt Setup window + if (hwnd != MainDlg && wcsstr (name, L"VeraCrypt") && !wcsstr (name, L"VeraCrypt Setup")) { PostMessage (hwnd, TC_APPMSG_CLOSE_BKG_TASK, 0, 0); PostMessage (hwnd, WM_CLOSE, 0, 0); if (lParam != 0) *((BOOL *)lParam) = TRUE; } } return TRUE; } BOOL CALLBACK FindTCWindowEnum (HWND hwnd, LPARAM lParam) { if (*(HWND *)lParam == hwnd) return TRUE; LONG_PTR userDataVal = GetWindowLongPtrW (hwnd, GWLP_USERDATA); if ((userDataVal == (LONG_PTR) 'VERA') || (userDataVal == (LONG_PTR) 'TRUE')) // Prior to 1.0e, 'TRUE' was used for VeraCrypt dialogs { wchar_t name[32] = { 0 }; GetWindowText (hwnd, name, ARRAYSIZE (name) - 1); if (hwnd != MainDlg && wcscmp (name, L"VeraCrypt") == 0) { if (lParam != 0) *((HWND *)lParam) = hwnd; } } return TRUE; } @@ -11803,61 +11604,61 @@ int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password context->HostSize = fileSize.QuadPart; } for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++) { // Seek the volume header switch (volumeType) { case TC_VOLUME_TYPE_NORMAL: headerOffset.QuadPart = useBackupHeader ? context->HostSize - TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET; break; case TC_VOLUME_TYPE_HIDDEN: if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > context->HostSize) continue; headerOffset.QuadPart = useBackupHeader ? context->HostSize - TC_VOLUME_HEADER_SIZE : TC_HIDDEN_VOLUME_HEADER_OFFSET; break; } if (!SetFilePointerEx ((HANDLE) context->HostFileHandle, headerOffset, NULL, FILE_BEGIN)) { status = ERR_OS_ERROR; goto error; } // Read volume header DWORD bytesRead; - if (!ReadEffectiveVolumeHeader (context->IsDevice, context->HostFileHandle, (byte *) buffer, &bytesRead)) + if (!ReadEffectiveVolumeHeader (context->IsDevice, context->HostFileHandle, (uint8 *) buffer, &bytesRead)) { status = ERR_OS_ERROR; goto error; } if (bytesRead != sizeof (buffer) && context->IsDevice) { // If FSCTL_ALLOW_EXTENDED_DASD_IO failed and there is a live filesystem on the partition, then the // filesystem driver may report EOF when we are reading hidden sectors (when the filesystem is // shorter than the partition). This can happen for example after the user quick-formats a dismounted // partition-hosted TrueCrypt volume and then tries to read the embedded backup header. memset (buffer, 0, sizeof (buffer)); } // Decrypt volume header status = ReadVolumeHeader (FALSE, buffer, password, pkcs5_prf, pim, &context->CryptoInfo, NULL); if (status == ERR_PASSWORD_WRONG) continue; // Try next volume type break; } if (status == ERR_SUCCESS) return status; error: DWORD sysError = GetLastError (); @@ -12385,142 +12186,142 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam { BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); BOOL deletable = selected; // Multiple key files can be selected. // Therefore, if one of them is not deletable, it means the delete button must be disabled for all. foreach (const shared_ptr<TokenKeyfile> &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) { if (!keyfile->Token->isEditable()) { deletable = false; break; } } EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), deletable); return 1; } if (msg == WM_COMMAND) { switch (lw) { case IDCANCEL: EndDialog (hwndDlg, IDCANCEL); return 1; case IDC_IMPORT_KEYFILE: { wchar_t keyfilePath[TC_MAX_PATH]; - if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE, NULL)) + if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE)) { DWORD keyfileSize; - byte *keyfileData = (byte *) LoadFile (keyfilePath, &keyfileSize); + uint8 *keyfileData = (uint8 *) LoadFile (keyfilePath, &keyfileSize); if (!keyfileData) { handleWin32Error (hwndDlg, SRC_POS); return 1; } if (keyfileSize != 0) { NewSecurityTokenKeyfileDlgProcParams newParams; newParams.Name = WideToUtf8String (keyfilePath); size_t lastBackSlash = newParams.Name.find_last_of ('\\'); if (lastBackSlash != string::npos) newParams.Name = newParams.Name.substr (lastBackSlash + 1); if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_NEW_TOKEN_KEYFILE), hwndDlg, (DLGPROC) NewSecurityTokenKeyfileDlgProc, (LPARAM) &newParams) == IDOK) { - vector <byte> keyfileDataVector (keyfileSize); + vector <uint8> keyfileDataVector (keyfileSize); memcpy (&keyfileDataVector.front(), keyfileData, keyfileSize); try { WaitCursor(); finally_do ({ NormalCursor(); }); SecurityToken::CreateKeyfile (newParams.SlotId, keyfileDataVector, newParams.Name); keyfiles = Token::GetAvailableKeyfiles(EMVSupportEnabled? true : false); SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); } catch (Exception &e) { e.Show (hwndDlg); } burn (&keyfileDataVector.front(), keyfileSize); } } else { SetLastError (ERROR_HANDLE_EOF); handleWin32Error (hwndDlg, SRC_POS); } burn (keyfileData, keyfileSize); TCfree (keyfileData); } return 1; } case IDC_EXPORT: { try { foreach (const shared_ptr<TokenKeyfile> &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) { wchar_t keyfilePath[TC_MAX_PATH]; - if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE, NULL)) + if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE)) break; { WaitCursor(); finally_do ({ NormalCursor(); }); - vector <byte> keyfileData; + vector <uint8> keyfileData; keyfile->GetKeyfileData (keyfileData); if (keyfileData.empty()) { SetLastError (ERROR_HANDLE_EOF); handleWin32Error (hwndDlg, SRC_POS); return 1; } - finally_do_arg (vector <byte> *, &keyfileData, { burn (&finally_arg->front(), finally_arg->size()); }); + finally_do_arg (vector <uint8> *, &keyfileData, { burn (&finally_arg->front(), finally_arg->size()); }); if (!SaveBufferToFile ((char *) &keyfileData.front(), keyfilePath, (DWORD) keyfileData.size(), FALSE, FALSE)) throw SystemException (SRC_POS); } Info ("KEYFILE_EXPORTED", hwndDlg); } } catch (Exception &e) { e.Show (hwndDlg); } return 1; } case IDC_DELETE: { if (AskNoYes ("CONFIRM_SEL_FILES_DELETE", hwndDlg) == IDNO) return 1; try { WaitCursor(); finally_do ({ NormalCursor(); }); foreach (const shared_ptr<TokenKeyfile> keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) { SecurityToken::DeleteKeyfile (dynamic_cast<SecurityTokenKeyfile&>(*keyfile.get())); } @@ -13249,85 +13050,85 @@ BOOL IsFileOnReadOnlyFilesystem (const wchar_t *path) DWORD flags, d; if (!GetVolumeInformation (root, NULL, 0, NULL, &d, &flags, NULL, 0)) return FALSE; return (flags & FILE_READ_ONLY_VOLUME) ? TRUE : FALSE; } void CheckFilesystem (HWND hwndDlg, int driveNo, BOOL fixErrors) { wchar_t msg[1024], param[1024], cmdPath[MAX_PATH]; wchar_t driveRoot[] = { L'A' + (wchar_t) driveNo, L':', 0 }; if (fixErrors && AskWarnYesNo ("FILESYS_REPAIR_CONFIRM_BACKUP", hwndDlg) == IDNO) return; StringCbPrintfW (msg, sizeof(msg), GetString (fixErrors ? "REPAIRING_FS" : "CHECKING_FS"), driveRoot); StringCbPrintfW (param, sizeof(param), fixErrors ? L"/C echo %s & chkdsk %s /F /X & pause" : L"/C echo %s & chkdsk %s & pause", msg, driveRoot); if (GetSystemDirectoryW(cmdPath, MAX_PATH)) { StringCbCatW(cmdPath, sizeof(cmdPath), L"\\cmd.exe"); } else StringCbCopyW(cmdPath, sizeof(cmdPath), L"C:\\Windows\\System32\\cmd.exe"); ShellExecuteW (NULL, (!IsAdmin() && IsUacSupported()) ? L"runas" : L"open", cmdPath, param, NULL, SW_SHOW); } -BOOL BufferContainsPattern (const byte *buffer, size_t bufferSize, const byte *pattern, size_t patternSize) +BOOL BufferContainsPattern (const uint8 *buffer, size_t bufferSize, const uint8 *pattern, size_t patternSize) { if (bufferSize < patternSize) return FALSE; bufferSize -= patternSize; for (size_t i = 0; i < bufferSize; ++i) { if (memcmp (buffer + i, pattern, patternSize) == 0) return TRUE; } return FALSE; } -BOOL BufferContainsString (const byte *buffer, size_t bufferSize, const char *str) +BOOL BufferContainsString (const uint8 *buffer, size_t bufferSize, const char *str) { - return BufferContainsPattern (buffer, bufferSize, (const byte*) str, strlen (str)); + return BufferContainsPattern (buffer, bufferSize, (const uint8*) str, strlen (str)); } -BOOL BufferContainsWideString (const byte *buffer, size_t bufferSize, const wchar_t *str) +BOOL BufferContainsWideString (const uint8 *buffer, size_t bufferSize, const wchar_t *str) { - return BufferContainsPattern (buffer, bufferSize, (const byte*) str, 2 * wcslen (str)); + return BufferContainsPattern (buffer, bufferSize, (const uint8*) str, 2 * wcslen (str)); } #ifndef SETUP int AskNonSysInPlaceEncryptionResume (HWND hwndDlg, BOOL *pbDecrypt) { if (AskWarnYesNo ("NONSYS_INPLACE_ENC_RESUME_PROMPT", hwndDlg) == IDYES) { char *tmpStr[] = {0, "CHOOSE_ENCRYPT_OR_DECRYPT", "ENCRYPT", "DECRYPT", "IDCANCEL", 0}; switch (AskMultiChoice ((void **) tmpStr, FALSE, hwndDlg)) { case 1: *pbDecrypt = FALSE; return IDYES; case 2: *pbDecrypt = TRUE; return IDYES; default: break; } } char *multiChoiceStr[] = { 0, "ASK_NONSYS_INPLACE_ENC_NOTIFICATION_REMOVAL", "DO_NOT_PROMPT_ME", "KEEP_PROMPTING_ME", 0 }; @@ -13463,65 +13264,60 @@ BOOL VolumePathExists (const wchar_t *volumePath) UpperCaseCopy (upperCasePath, sizeof(upperCasePath), volumePath); if (wcsstr (upperCasePath, L"\\DEVICE\\") == upperCasePath) return OpenDevice (volumePath, &openTest, FALSE, FALSE); wstring path = volumePath; if (path.find (L"\\\\?\\Volume{") == 0 && path.rfind (L"}\\") == path.size() - 2) { wchar_t devicePath[TC_MAX_PATH]; if (QueryDosDevice (path.substr (4, path.size() - 5).c_str(), devicePath, TC_MAX_PATH) != 0) return TRUE; } if (_waccess (volumePath, 0) == 0) return TRUE; else { DWORD dwResult = GetLastError (); if (dwResult == ERROR_SHARING_VIOLATION) return TRUE; else return FALSE; } } BOOL IsWindowsIsoBurnerAvailable () { wchar_t path[MAX_PATH*2] = { 0 }; - if (!IsOSAtLeast (WIN_7)) - { - return FALSE; - } - if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_SYSTEM, NULL, 0, path))) { StringCbCatW (path, MAX_PATH*2, L"\\" ISO_BURNER_TOOL); return (FileExists (path)); } return FALSE; } BOOL LaunchWindowsIsoBurner (HWND hwnd, const wchar_t *isoPath) { wchar_t path[MAX_PATH*2] = { 0 }; int r; if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_SYSTEM, NULL, 0, path))) StringCbCatW (path, MAX_PATH*2, L"\\" ISO_BURNER_TOOL); else StringCbCopyW (path, MAX_PATH*2, L"C:\\Windows\\System32\\" ISO_BURNER_TOOL); r = (int) ShellExecute (hwnd, L"open", path, (wstring (L"\"") + isoPath + L"\"").c_str(), NULL, SW_SHOWNORMAL); if (r <= 32) { SetLastError (r); handleWin32Error (hwnd, SRC_POS); return FALSE; } @@ -13738,165 +13534,160 @@ void HandleShowPasswordFieldAction (HWND hwndDlg, UINT checkBoxId, UINT edit1Id, } SendMessageW (GetDlgItem (hwndDlg, edit1Id), EM_SETPASSWORDCHAR, GetCheckBox (hwndDlg, checkBoxId) ? 0 : EditPasswordChar, 0); InvalidateRect (GetDlgItem (hwndDlg, edit1Id), NULL, TRUE); if (edit2Id) { SendMessageW (GetDlgItem (hwndDlg, edit2Id), EM_SETPASSWORDCHAR, GetCheckBox (hwndDlg, checkBoxId) ? 0 : EditPasswordChar, 0); InvalidateRect (GetDlgItem (hwndDlg, edit2Id), NULL, TRUE); } } void RegisterDriverInf (bool registerFilter, const string& filter, const string& filterReg, HWND ParentWindow, HKEY regKey) { wstring infFileName = GetTempPathString() + L"\\veracrypt_driver_setup.inf"; File infFile (infFileName, false, true); finally_do_arg (wstring, infFileName, { DeleteFile (finally_arg.c_str()); }); string infTxt = "[veracrypt]\r\n" + string (registerFilter ? "Add" : "Del") + "Reg=veracrypt_reg\r\n\r\n" "[veracrypt_reg]\r\n" "HKR,,\"" + filterReg + "\",0x0001" + string (registerFilter ? "0008" : "8002") + ",\"" + filter + "\"\r\n"; - infFile.Write ((byte *) infTxt.c_str(), (DWORD) infTxt.size()); + infFile.Write ((uint8 *) infTxt.c_str(), (DWORD) infTxt.size()); infFile.Close(); - HINF hInf = SetupOpenInfFileWFn (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); + HINF hInf = SetupOpenInfFileW (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); throw_sys_if (hInf == INVALID_HANDLE_VALUE); - finally_do_arg (HINF, hInf, { SetupCloseInfFileFn (finally_arg); }); + finally_do_arg (HINF, hInf, { SetupCloseInfFile (finally_arg); }); - throw_sys_if (!SetupInstallFromInfSectionWFn (ParentWindow, hInf, L"veracrypt", SPINST_REGISTRY, regKey, NULL, 0, NULL, NULL, NULL, NULL)); + throw_sys_if (!SetupInstallFromInfSectionW (ParentWindow, hInf, L"veracrypt", SPINST_REGISTRY, regKey, NULL, 0, NULL, NULL, NULL, NULL)); } HKEY OpenDeviceClassRegKey (const GUID *deviceClassGuid) { - return SetupDiOpenClassRegKeyFn (deviceClassGuid, KEY_READ | KEY_WRITE); + return SetupDiOpenClassRegKey (deviceClassGuid, KEY_READ | KEY_WRITE); } LSTATUS DeleteRegistryKey (HKEY hKey, LPCTSTR keyName) { - return SHDeleteKeyWFn(hKey, keyName); + return SHDeleteKeyW(hKey, keyName); } HIMAGELIST CreateImageList(int cx, int cy, UINT flags, int cInitial, int cGrow) { - return ImageList_CreateFn(cx, cy, flags, cInitial, cGrow); + return ImageList_Create(cx, cy, flags, cInitial, cGrow); } int AddBitmapToImageList(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask) { - return ImageList_AddFn(himl, hbmImage, hbmMask); + return ImageList_Add(himl, hbmImage, hbmMask); } HRESULT VCStrDupW(LPCWSTR psz, LPWSTR *ppwsz) { - return SHStrDupWFn (psz, ppwsz); + return SHStrDupW (psz, ppwsz); } void ProcessEntropyEstimate (HWND hProgress, DWORD* pdwInitialValue, DWORD dwCounter, DWORD dwMaxLevel, DWORD* pdwEntropy) { /* conservative estimate: 1 mouse move event brings 1 bit of entropy * https://security.stackexchange.com/questions/32844/for-how-much-time-should-i-randomly-move-the-mouse-for-generating-encryption-key/32848#32848 */ if (*pdwEntropy == 0xFFFFFFFF) { *pdwInitialValue = dwCounter; *pdwEntropy = 0; } else { if ( *pdwEntropy < dwMaxLevel && (dwCounter >= *pdwInitialValue) && (dwCounter - *pdwInitialValue) <= dwMaxLevel) *pdwEntropy = dwCounter - *pdwInitialValue; else *pdwEntropy = dwMaxLevel; - if (IsOSAtLeast (WIN_VISTA)) - { - int state = PBST_ERROR; - if (*pdwEntropy >= (dwMaxLevel/2)) - state = PBST_NORMAL; - else if (*pdwEntropy >= (dwMaxLevel/4)) - state = PBST_PAUSED; + int state = PBST_ERROR; + if (*pdwEntropy >= (dwMaxLevel/2)) + state = PBST_NORMAL; + else if (*pdwEntropy >= (dwMaxLevel/4)) + state = PBST_PAUSED; - SendMessage (hProgress, PBM_SETSTATE, state, 0); - } + SendMessage (hProgress, PBM_SETSTATE, state, 0); SendMessage (hProgress, PBM_SETPOS, (WPARAM) (*pdwEntropy), 0); } } void AllowMessageInUIPI (UINT msg) { - if (ChangeWindowMessageFilterFn) - { - ChangeWindowMessageFilterFn (msg, MSGFLT_ADD); - } + /* ChangeWindowMessageFilter is used to enable some messages bypasss UIPI (User Interface Privilege Isolation) */ + ChangeWindowMessageFilter (msg, MSGFLT_ADD); } -BOOL IsRepeatedByteArray (byte value, const byte* buffer, size_t bufferSize) +BOOL IsRepeatedByteArray (uint8 value, const uint8* buffer, size_t bufferSize) { if (buffer && bufferSize) { size_t i; for (i = 0; i < bufferSize; i++) { if (*buffer++ != value) return FALSE; } return TRUE; } else return FALSE; } #ifndef SETUP BOOL TranslateVolumeID (HWND hwndDlg, wchar_t* pathValue, size_t cchPathValue) { BOOL bRet = TRUE; size_t pathLen = pathValue? wcslen (pathValue) : 0; if ((pathLen >= 3) && (_wcsnicmp (pathValue, L"ID:", 3) == 0)) { - std::vector<byte> arr; + std::vector<uint8> arr; if ( (pathLen == (3 + 2*VOLUME_ID_SIZE)) && HexWideStringToArray (pathValue + 3, arr) && (arr.size() == VOLUME_ID_SIZE) ) { std::wstring devicePath = FindDeviceByVolumeID (&arr[0], FALSE); if (devicePath.length() > 0) StringCchCopyW (pathValue, cchPathValue, devicePath.c_str()); else { if (!Silent && !MultipleMountOperationInProgress) Error ("VOLUME_ID_NOT_FOUND", hwndDlg); SetLastError (ERROR_PATH_NOT_FOUND); bRet = FALSE; } } else { if (!Silent) Error ("VOLUME_ID_INVALID", hwndDlg); SetLastError (ERROR_INVALID_PARAMETER); bRet = FALSE; } } return bRet; } #endif @@ -13928,121 +13719,156 @@ BOOL CopyTextToClipboard (LPCWSTR txtValue) } BOOL GetFreeDriveLetter(WCHAR* pCh) { DWORD dwUsedDrives = GetLogicalDrives(); WCHAR l; for (l = L'A'; l <= L'Z'; l++) { if ((dwUsedDrives & 1) == 0) { *pCh = l; return TRUE; } dwUsedDrives = dwUsedDrives >> 1; } return FALSE; } BOOL SetPrivilege(LPTSTR szPrivilegeName, BOOL bEnable) { HANDLE hToken; TOKEN_PRIVILEGES tkp; BOOL bRet = FALSE; DWORD dwLastError = 0; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { if (LookupPrivilegeValue(NULL, szPrivilegeName, &tkp.Privileges[0].Luid)) { tkp.PrivilegeCount = 1; - tkp.Privileges[0].Attributes = bEnable? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED; + tkp.Privileges[0].Attributes = bEnable? SE_PRIVILEGE_ENABLED : 0; bRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, NULL); dwLastError = GetLastError (); - if ( ERROR_SUCCESS != dwLastError) + if (bRet && (ERROR_NOT_ALL_ASSIGNED == dwLastError)) { bRet = FALSE; } } else dwLastError = GetLastError (); CloseHandle(hToken); } else dwLastError = GetLastError (); SetLastError (dwLastError); return bRet; } +BOOL IsPrivilegeEnabled (LPTSTR szPrivilegeName) +{ + HANDLE hToken; + TOKEN_PRIVILEGES tkp; + BOOL bRet = FALSE; + DWORD dwLastError = 0; + + if (OpenProcessToken(GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + &hToken)) + { + if (LookupPrivilegeValue(NULL, szPrivilegeName, + &tkp.Privileges[0].Luid)) + { + DWORD dwSize = sizeof (tkp); + if (GetTokenInformation (hToken, TokenPrivileges, &tkp, dwSize, &dwSize)) + { + bRet = (tkp.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED) != 0; + } + else + dwLastError = GetLastError (); + } + else + dwLastError = GetLastError (); + + CloseHandle(hToken); + } + else + dwLastError = GetLastError (); + + SetLastError (dwLastError); + + return bRet; +} + BOOL DeleteDirectory (const wchar_t* szDirName) { BOOL bStatus = RemoveDirectory (szDirName); if (!bStatus) { /* force removal of the non empty directory */ wchar_t szOpPath[TC_MAX_PATH + 1] = {0}; SHFILEOPSTRUCTW op; StringCchCopyW(szOpPath, ARRAYSIZE(szOpPath)-1, szDirName); ZeroMemory(&op, sizeof(op)); op.wFunc = FO_DELETE; op.pFrom = szOpPath; op.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR; if ((0 == SHFileOperation(&op)) && (!op.fAnyOperationsAborted)) bStatus = TRUE; } return bStatus; } #if defined (TCMOUNT) || defined (VOLFORMAT) /*********************************************************************/ static BOOL GenerateRandomString (HWND hwndDlg, LPTSTR szName, DWORD maxCharsCount) { BOOL bRet = FALSE; int alreadyInitialized = 0; if (RandinitWithCheck (&alreadyInitialized) != ERR_SUCCESS) { handleError (hwndDlg, (CryptoAPILastError == ERROR_SUCCESS)? ERR_RAND_INIT_FAILED : ERR_CAPI_INIT_FAILED, SRC_POS); } else { BYTE* indexes = (BYTE*) malloc (maxCharsCount + 1); bRet = RandgetBytesFull (hwndDlg, indexes, maxCharsCount + 1, TRUE, TRUE); if (bRet) { - static LPCTSTR chars = _T("0123456789@#$%^&_-*abcdefghijklmnopqrstuvwxyz"); + static LPCTSTR chars = _T("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"); DWORD i, charsLen = (DWORD) _tcslen (chars); DWORD effectiveLen = (indexes[0] % (64 - 16)) + 16; // random length between 16 to 64 effectiveLen = (effectiveLen > maxCharsCount)? maxCharsCount : effectiveLen; for (i = 0; i < effectiveLen; i++) { szName[i] = chars[indexes[i + 1] % charsLen]; } szName[effectiveLen] = 0; } burn (indexes, maxCharsCount + 1); free (indexes); /* If RNG was not initialized before us, then stop it in order to * stop the fast poll thread which consumes CPU. Next time a critical operation * that requires RNG is performed, it will be initialized again. * * We do this because since the addition of secure desktop support, every time * secure desktop is displayed, the RNG fast poll thread was started even if the * user will never perform any critical operation that requires random bytes. */ if (!alreadyInitialized) { RandStop (FALSE); } } return bRet; } @@ -14070,260 +13896,308 @@ typedef struct // This thread checks if VeraCrypt secure desktop is the one that has user input // and if it is not then it will call SwitchDesktop to make it the input desktop static unsigned int __stdcall SecureDesktopMonitoringThread( LPVOID lpThreadParameter ) { SecureDesktopMonitoringThreadParam* pMonitorParam = (SecureDesktopMonitoringThreadParam*) lpThreadParameter; if (pMonitorParam) { HANDLE hStopEvent = pMonitorParam->hStopEvent; LPCWSTR szVCDesktopName = pMonitorParam->szVCDesktopName; HDESK hVcDesktop = pMonitorParam->hVcDesktop; // loop until the stop event is signaled while (WaitForSingleObject (hStopEvent, SECUREDESKTOP_MONOTIR_PERIOD) == WAIT_TIMEOUT) { // check that our secure desktop is still the input desktop // otherwise, switch to it BOOL bPerformSwitch = FALSE; HDESK currentDesk = OpenInputDesktop (0, FALSE, GENERIC_READ); if (currentDesk) { LPWSTR szName = NULL; DWORD dwLen = 0; if (!GetUserObjectInformation (currentDesk, UOI_NAME, NULL, 0, &dwLen)) { szName = (LPWSTR) malloc (dwLen); if (szName) { if (GetUserObjectInformation (currentDesk, UOI_NAME, szName, dwLen, &dwLen)) { - if (0 != _wcsicmp (szName, szVCDesktopName)) + if (0 == _wcsicmp(szName, L"Default")) // default input desktop for the interactive window station + bPerformSwitch = TRUE; + else if (0 != _wcsicmp (szName, szVCDesktopName)) bPerformSwitch = TRUE; } free (szName); } } CloseDesktop (currentDesk); } if (bPerformSwitch) SwitchDesktop (hVcDesktop); } } return 0; } static unsigned int __stdcall SecureDesktopThread( LPVOID lpThreadParameter ) { HANDLE hMonitoringThread = NULL; unsigned int monitoringThreadID = 0; SecureDesktopThreadParam* pParam = (SecureDesktopThreadParam*) lpThreadParameter; SecureDesktopMonitoringThreadParam monitorParam; BOOL bNewDesktopSet = FALSE; + HDESK hSecureDesk; + DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS; - // wait for SwitchDesktop to succeed before using it for current thread - while (true) + hSecureDesk = CreateDesktop (pParam->szDesktopName, NULL, NULL, 0, desktopAccess, NULL); + if (!hSecureDesk) { - if (SwitchDesktop (pParam->hDesk)) - { - break; - } - Sleep (SECUREDESKTOP_MONOTIR_PERIOD); + return 0; } + + StringCbCopy(SecureDesktopName, sizeof (SecureDesktopName), pParam->szDesktopName); + pParam->hDesk = hSecureDesk; - bNewDesktopSet = SetThreadDesktop (pParam->hDesk); + bNewDesktopSet = SetThreadDesktop (hSecureDesk); if (bNewDesktopSet) { + // call ImmDisableIME from imm32.dll to disable IME since it can create issue with secure desktop + // cf: https://keepass.info/help/kb/sec_desk.html#ime + HMODULE hImmDll = LoadLibraryEx (L"imm32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (hImmDll) + { + typedef BOOL (WINAPI *ImmDisableIME_t)(DWORD); + ImmDisableIME_t ImmDisableIME = (ImmDisableIME_t) GetProcAddress (hImmDll, "ImmDisableIME"); + if (ImmDisableIME) + { + ImmDisableIME (0); + } + } + + // wait for SwitchDesktop to succeed before using it for current thread + while (true) + { + if (SwitchDesktop (hSecureDesk)) + { + break; + } + Sleep (SECUREDESKTOP_MONOTIR_PERIOD); + } + // create the thread that will ensure that VeraCrypt secure desktop has always user input // this is done only if the stop event is created successfully HANDLE hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (hStopEvent) { monitorParam.szVCDesktopName = pParam->szDesktopName; - monitorParam.hVcDesktop = pParam->hDesk; + monitorParam.hVcDesktop = hSecureDesk; monitorParam.hStopEvent = hStopEvent; hMonitoringThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopMonitoringThread, (LPVOID) &monitorParam, 0, &monitoringThreadID); } pParam->retValue = DialogBoxParamW (pParam->hInstance, pParam->lpTemplateName, NULL, pParam->lpDialogFunc, pParam->dwInitParam); if (hMonitoringThread) { // notify the monitoring thread to stop SetEvent(hStopEvent); WaitForSingleObject (hMonitoringThread, INFINITE); CloseHandle (hMonitoringThread); } if (hStopEvent) { CloseHandle (hStopEvent); } pParam->bDlgDisplayed = TRUE; + + // free imm32.dll handle + if (hImmDll) + { + FreeLibrary (hImmDll); + } } else { pParam->bDlgDisplayed = FALSE; } return 0; } static void GetCtfMonProcessIdList (map<DWORD, BOOL>& processIdList) { HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); PROCESSENTRY32 pEntry; BOOL hRes; pEntry.dwSize = sizeof (pEntry); processIdList.clear(); hRes = Process32First(hSnapShot, &pEntry); while (hRes) { LPTSTR szFileName = PathFindFileName (pEntry.szExeFile); if (_wcsicmp(szFileName, L"ctfmon.exe") == 0) { processIdList[pEntry.th32ProcessID] = TRUE; } hRes = Process32Next(hSnapShot, &pEntry); } CloseHandle(hSnapShot); } static void KillProcess (DWORD dwProcessId) { HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, dwProcessId); if (hProcess != NULL) { TerminateProcess(hProcess, (UINT) -1); CloseHandle(hProcess); } } INT_PTR SecureDesktopDialogBoxParam( HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { TCHAR szDesktopName[65] = {0}; BOOL bSuccess = FALSE; INT_PTR retValue = 0; BOOL bEffectiveUseSecureDesktop = bCmdUseSecureDesktopValid? bCmdUseSecureDesktop : bUseSecureDesktop; if (bEffectiveUseSecureDesktop && !IsThreadInSecureDesktop(GetCurrentThreadId())) { + BOOL bRandomNameGenerated = FALSE; + HDESK existedDesk = NULL; EnterCriticalSection (&csSecureDesktop); bSecureDesktopOngoing = TRUE; finally_do ({ bSecureDesktopOngoing = FALSE; LeaveCriticalSection (&csSecureDesktop); }); - if (GenerateRandomString (hWndParent, szDesktopName, 64)) + // ensure that the randomly generated name is not already used + do + { + if (existedDesk) + { + CloseDesktop (existedDesk); + existedDesk = NULL; + } + if (GenerateRandomString (hWndParent, szDesktopName, 64)) + { + existedDesk = OpenDesktop (szDesktopName, 0, FALSE, GENERIC_READ); + if (!existedDesk) + { + bRandomNameGenerated = TRUE; + } + } + } while (existedDesk); + + if (bRandomNameGenerated) { map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList; - DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS; - HDESK hSecureDesk; - HDESK hOriginalDesk = GetThreadDesktop (GetCurrentThreadId()); + HDESK hOriginalDesk = NULL; + SecureDesktopThreadParam param; - HDESK hInputDesk = NULL; // wait for the input desktop to be available before switching to // secure desktop. Under Windows 10, the user session can be started // in the background even before the user has authenticated and in this // case, we wait for the user to be really authenticated before starting // secure desktop mechanism - while (!(hInputDesk = OpenInputDesktop (0, TRUE, GENERIC_READ))) + while (!(hOriginalDesk = OpenInputDesktop (0, TRUE, GENERIC_ALL))) { Sleep (SECUREDESKTOP_MONOTIR_PERIOD); } - - CloseDesktop (hInputDesk); // get the initial list of ctfmon.exe processes before creating new desktop GetCtfMonProcessIdList (ctfmonBeforeList); - hSecureDesk = CreateDesktop (szDesktopName, NULL, NULL, 0, desktopAccess, NULL); - if (hSecureDesk) + param.hDesk = NULL; + param.szDesktopName = szDesktopName; + param.hInstance = hInstance; + param.lpTemplateName = lpTemplateName; + param.lpDialogFunc = lpDialogFunc; + param.dwInitParam = dwInitParam; + param.retValue = 0; + param.bDlgDisplayed = FALSE; + + // use _beginthreadex instead of CreateThread because lpDialogFunc may be using the C runtime library + HANDLE hThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopThread, (LPVOID) ¶m, 0, NULL); + if (hThread) { - SecureDesktopThreadParam param; - - param.hDesk = hSecureDesk; - param.szDesktopName = szDesktopName; - param.hInstance = hInstance; - param.lpTemplateName = lpTemplateName; - param.lpDialogFunc = lpDialogFunc; - param.dwInitParam = dwInitParam; - param.retValue = 0; - param.bDlgDisplayed = FALSE; - - // use _beginthreadex instead of CreateThread because lpDialogFunc may be using the C runtime library - HANDLE hThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopThread, (LPVOID) ¶m, 0, NULL); - if (hThread) - { - StringCbCopy(SecureDesktopName, sizeof (SecureDesktopName), szDesktopName); + WaitForSingleObject (hThread, INFINITE); + CloseHandle (hThread); - WaitForSingleObject (hThread, INFINITE); - CloseHandle (hThread); + if (param.bDlgDisplayed) + { + // dialog box was indeed displayed in Secure Desktop + retValue = param.retValue; + bSuccess = TRUE; - if (param.bDlgDisplayed) + // switch back to the original desktop + while (!SwitchDesktop (hOriginalDesk)) { - // dialog box was indeed displayed in Secure Desktop - retValue = param.retValue; - bSuccess = TRUE; + Sleep (SECUREDESKTOP_MONOTIR_PERIOD); } - // switch back to original desktop - SwitchDesktop (hOriginalDesk); + SetThreadDesktop (hOriginalDesk); } - CloseDesktop (hSecureDesk); + if (param.hDesk) + { + CloseDesktop (param.hDesk); + } + } - // get the new list of ctfmon.exe processes in order to find the ID of the - // ctfmon.exe instance that corresponds to the desktop we create so that - // we can kill it, otherwise it would remain running - GetCtfMonProcessIdList (ctfmonAfterList); + // get the new list of ctfmon.exe processes in order to find the ID of the + // ctfmon.exe instance that corresponds to the desktop we create so that + // we can kill it, otherwise it would remain running + GetCtfMonProcessIdList (ctfmonAfterList); - for (map<DWORD, BOOL>::iterator It = ctfmonAfterList.begin(); - It != ctfmonAfterList.end(); It++) + for (map<DWORD, BOOL>::iterator It = ctfmonAfterList.begin(); + It != ctfmonAfterList.end(); It++) + { + if (ctfmonBeforeList[It->first] != TRUE) { - if (ctfmonBeforeList[It->first] != TRUE) - { - // Kill process - KillProcess (It->first); - } + // Kill process + KillProcess (It->first); } } CloseDesktop(hOriginalDesk); burn (szDesktopName, sizeof (szDesktopName)); } } if (!bSuccess) { // fallback to displaying in normal desktop retValue = DialogBoxParamW (hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); } return retValue; } #endif void GetInstallationPath (HWND hwndDlg, wchar_t* szInstallPath, DWORD cchSize, BOOL* pbInstallPathDetermined) { HKEY hkey; BOOL bInstallPathDetermined = FALSE; wchar_t path[MAX_PATH+20]; ITEMIDLIST *itemList; memset (szInstallPath, 0, cchSize * sizeof (wchar_t)); // Determine if VeraCrypt is already installed and try to determine its "Program Files" location if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt", 0, KEY_READ | KEY_WOW64_32KEY, &hkey) == ERROR_SUCCESS) @@ -14368,239 +14242,343 @@ void GetInstallationPath (HWND hwndDlg, wchar_t* szInstallPath, DWORD cchSize, B if (Is64BitOs()) { // Use a unified default installation path (registry redirection of %ProgramFiles% does not work if the installation path is user-selectable) wstring s = path; size_t p = s.find (L" (x86)"); if (p != wstring::npos) { s = s.substr (0, p); if (_waccess (s.c_str(), 0) != -1) StringCbCopyW (path, sizeof (path), s.c_str()); } } StringCbCatW (path, sizeof(path), L"\\VeraCrypt\\"); StringCbCopyW (szInstallPath, cchSize, path); } // Make sure the path ends with a backslash if (szInstallPath [wcslen (szInstallPath) - 1] != L'\\') { StringCbCatW (szInstallPath, cchSize, L"\\"); } if (pbInstallPathDetermined) *pbInstallPathDetermined = bInstallPathDetermined; } BOOL GetSetupconfigLocation (wchar_t* path, DWORD cchSize) { - wchar_t szShell32Path[MAX_PATH] = {0}; - HMODULE hShell32 = NULL; BOOL bResult = FALSE; path[0] = 0; - if (GetSystemDirectory(szShell32Path, MAX_PATH)) - StringCchCatW (szShell32Path, MAX_PATH, L"\\Shell32.dll"); - else - StringCchCopyW (szShell32Path, MAX_PATH, L"C:\\Windows\\System32\\Shell32.dll"); - - hShell32 = LoadLibrary (szShell32Path); - if (hShell32) + wchar_t* pszUsersPath = NULL; + if (S_OK == SHGetKnownFolderPath (FOLDERID_UserProfiles, 0, NULL, &pszUsersPath)) { - SHGETKNOWNFOLDERPATH SHGetKnownFolderPathFn = (SHGETKNOWNFOLDERPATH) GetProcAddress (hShell32, "SHGetKnownFolderPath"); - if (SHGetKnownFolderPathFn) - { - wchar_t* pszUsersPath = NULL; - if (S_OK == SHGetKnownFolderPathFn (FOLDERID_UserProfiles, 0, NULL, &pszUsersPath)) - { - StringCchPrintfW (path, cchSize, L"%s\\Default\\AppData\\Local\\Microsoft\\Windows\\WSUS\\", pszUsersPath); - CoTaskMemFree (pszUsersPath); - bResult = TRUE; - } - } - FreeLibrary (hShell32); + StringCchPrintfW (path, cchSize, L"%s\\Default\\AppData\\Local\\Microsoft\\Windows\\WSUS\\", pszUsersPath); + CoTaskMemFree (pszUsersPath); + bResult = TRUE; } if (!bResult && CurrentOSMajor >= 10) { - StringCchPrintfW (path, cchSize, L"%c:\\Users\\Default\\AppData\\Local\\Microsoft\\Windows\\WSUS\\", szShell32Path[0]); + wchar_t szSys32Path[MAX_PATH]; + if (!GetSystemDirectory (szSys32Path, ARRAYSIZE (szSys32Path))) + { + StringCchCopy(szSys32Path, ARRAYSIZE (szSys32Path), L"C:\\Windows\\System32"); + } + StringCchPrintfW (path, cchSize, L"%c:\\Users\\Default\\AppData\\Local\\Microsoft\\Windows\\WSUS\\", szSys32Path[0]); bResult = TRUE; } return bResult; } BOOL BufferHasPattern (const unsigned char* buffer, size_t bufferLen, const void* pattern, size_t patternLen) { BOOL bRet = FALSE; if (patternLen <= bufferLen) { size_t i; for (i = 0; i <= (bufferLen - patternLen); ++i) { if (memcmp (&buffer[i], pattern, patternLen) == 0) { bRet = TRUE; break; } } } return bRet; } -/* Implementation borrowed from KeePassXC source code (https://github.com/keepassxreboot/keepassxc/blob/release/2.4.0/src/core/Bootstrap.cpp#L150) +/* Implementation borrowed from KeePassXC source code (https://github.com/keepassxreboot/keepassxc/blob/2.7.8/src/core/Bootstrap.cpp#L121) * * Reduce current user acess rights for this process to the minimum in order to forbid non-admin users from reading the process memory. + * Restrict access to changing DACL's after the process is started. This prevents the creator of veracrypt process from simply adding + * the permission to read memory back to the DACL list. */ -BOOL EnableProcessProtection() +BOOL ActivateMemoryProtection() { BOOL bSuccess = FALSE; // Process token and user HANDLE hToken = NULL; PTOKEN_USER pTokenUser = NULL; DWORD cbBufferSize = 0; + PSID pOwnerRightsSid = NULL; + DWORD pOwnerRightsSidSize = SECURITY_MAX_SID_SIZE; // Access control list PACL pACL = NULL; DWORD cbACL = 0; // Acces mask DWORD dwAccessMask = SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE; // same as protected process - + + if (MemoryProtectionActivated) + return TRUE; + if (IsAdmin ()) { // if we are running elevated, we allow CreateProcessXXX calls alongside PROCESS_DUP_HANDLE and PROCESS_QUERY_INFORMATION in order to be able // to implement secure way to open URLs (cf RunAsDesktopUser) // we are still protecting against memory access from non-admon processes dwAccessMask |= PROCESS_CREATE_PROCESS | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; } // Open the access token associated with the calling process if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { goto Cleanup; } // Retrieve the token information in a TOKEN_USER structure GetTokenInformation(hToken, TokenUser, NULL, 0, &cbBufferSize); pTokenUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbBufferSize); if (pTokenUser == NULL) { goto Cleanup; } if (!GetTokenInformation(hToken, TokenUser, pTokenUser, cbBufferSize, &cbBufferSize)) { goto Cleanup; } if (!IsValidSid(pTokenUser->User.Sid)) { goto Cleanup; } + // Retrieve CreaterOwnerRights SID + pOwnerRightsSid = (PSID) HeapAlloc(GetProcessHeap(), 0, pOwnerRightsSidSize); + if (pOwnerRightsSid == NULL) { + goto Cleanup; + } + + if (!CreateWellKnownSid(WinCreatorOwnerRightsSid, NULL, pOwnerRightsSid, &pOwnerRightsSidSize)) { + goto Cleanup; + } + // Calculate the amount of memory that must be allocated for the DACL - cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid); + cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid) + + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pOwnerRightsSid); // Create and initialize an ACL pACL = (PACL) HeapAlloc(GetProcessHeap(), 0, cbACL); if (pACL == NULL) { goto Cleanup; } if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) { goto Cleanup; } // Add allowed access control entries, everything else is denied if (!AddAccessAllowedAce( pACL, ACL_REVISION, dwAccessMask, pTokenUser->User.Sid // pointer to the trustee's SID )) { goto Cleanup; } + // Explicitly set "Process Owner" rights to Read Only. The default is Full Control. + if (!AddAccessAllowedAce( + pACL, + ACL_REVISION, + READ_CONTROL, + pOwnerRightsSid + )) { + goto Cleanup; + } + + // Set discretionary access control list bSuccess = (ERROR_SUCCESS == SetSecurityInfo(GetCurrentProcess(), // object handle SE_KERNEL_OBJECT, // type of object DACL_SECURITY_INFORMATION, // change only the objects DACL NULL, NULL, // do not change owner or group pACL, // DACL specified NULL // do not change SACL ))? TRUE: FALSE; + if (bSuccess) + MemoryProtectionActivated = TRUE; + Cleanup: if (pACL != NULL) { HeapFree(GetProcessHeap(), 0, pACL); } + if (pOwnerRightsSid != NULL) { + HeapFree(GetProcessHeap(), 0, pOwnerRightsSid); + } if (pTokenUser != NULL) { HeapFree(GetProcessHeap(), 0, pTokenUser); } if (hToken != NULL) { CloseHandle(hToken); } return bSuccess; } +// define missing structures Windows 8 +#if (_WIN32_WINNT < 0x0602) + +typedef struct _PROCESS_MITIGATION_ASLR_POLICY { + union { + DWORD Flags; + struct { + DWORD EnableBottomUpRandomization : 1; + DWORD EnableForceRelocateImages : 1; + DWORD EnableHighEntropy : 1; + DWORD DisallowStrippedImages : 1; + DWORD ReservedFlags : 28; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; +} PROCESS_MITIGATION_ASLR_POLICY, *PPROCESS_MITIGATION_ASLR_POLICY; + +typedef struct _PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY { + union { + DWORD Flags; + struct { + DWORD DisableExtensionPoints : 1; + DWORD ReservedFlags : 31; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; +} PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY, *PPROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY; + +typedef struct _PROCESS_MITIGATION_DYNAMIC_CODE_POLICY { + union { + DWORD Flags; + struct { + DWORD ProhibitDynamicCode : 1; + DWORD AllowThreadOptOut : 1; + DWORD AllowRemoteDowngrade : 1; + DWORD AuditProhibitDynamicCode : 1; + DWORD ReservedFlags : 28; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; +} PROCESS_MITIGATION_DYNAMIC_CODE_POLICY, *PPROCESS_MITIGATION_DYNAMIC_CODE_POLICY; + +typedef enum _PROCESS_MITIGATION_POLICY { + ProcessDEPPolicy, + ProcessASLRPolicy, + ProcessDynamicCodePolicy, + ProcessStrictHandleCheckPolicy, + ProcessSystemCallDisablePolicy, + ProcessMitigationOptionsMask, + ProcessExtensionPointDisablePolicy, + ProcessControlFlowGuardPolicy, + ProcessSignaturePolicy, + ProcessFontDisablePolicy, + ProcessImageLoadPolicy, + ProcessSystemCallFilterPolicy, + ProcessPayloadRestrictionPolicy, + ProcessChildProcessPolicy, + ProcessSideChannelIsolationPolicy, + ProcessUserShadowStackPolicy, + MaxProcessMitigationPolicy +} PROCESS_MITIGATION_POLICY, *PPROCESS_MITIGATION_POLICY; + +#endif + +void ActivateProcessMitigations() +{ + // we load the function pointer of SetProcessMitigationPolicy dynamically because we are building with Windows 7 SDK that does not have the definition of this function + typedef BOOL (WINAPI *SetProcessMitigationPolicyFunc) (PROCESS_MITIGATION_POLICY MitigationPolicy, PVOID lpBuffer, SIZE_T dwLength); + SetProcessMitigationPolicyFunc SetProcessMitigationPolicyPtr = (SetProcessMitigationPolicyFunc) GetProcAddress (GetModuleHandle (L"kernel32.dll"), "SetProcessMitigationPolicy"); + if (SetProcessMitigationPolicyPtr) + { + PROCESS_MITIGATION_ASLR_POLICY aslrPolicy = { 0 }; + PROCESS_MITIGATION_DYNAMIC_CODE_POLICY dynCodePolicy = { 0 }; + PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY extensionPointDisablePolicy = { 0 }; + + aslrPolicy.EnableBottomUpRandomization = TRUE; + aslrPolicy.EnableForceRelocateImages = TRUE; + aslrPolicy.EnableHighEntropy = TRUE; + + dynCodePolicy.ProhibitDynamicCode = TRUE; + + extensionPointDisablePolicy.DisableExtensionPoints = TRUE; + + SetProcessMitigationPolicyPtr (ProcessASLRPolicy, &aslrPolicy, sizeof (aslrPolicy)); + SetProcessMitigationPolicyPtr (ProcessDynamicCodePolicy, &dynCodePolicy, sizeof (dynCodePolicy)); + SetProcessMitigationPolicyPtr (ProcessExtensionPointDisablePolicy, &extensionPointDisablePolicy, sizeof (extensionPointDisablePolicy)); + } +} + // Based on sample code from: // https://blogs.msdn.microsoft.com/aaron_margosis/2009/06/06/faq-how-do-i-start-a-program-as-the-desktop-user-from-an-elevated-app/ // start a program non-elevated as the desktop user from an elevated app static bool RunAsDesktopUser( __in const wchar_t * szApp, __in wchar_t * szCmdLine) { HANDLE hThreadToken = NULL, hShellProcess = NULL, hShellProcessToken = NULL, hPrimaryToken = NULL; HWND hwnd = NULL; DWORD dwPID = 0; BOOL ret; DWORD dwLastErr; STARTUPINFOW si; PROCESS_INFORMATION pi; bool retval = false; SecureZeroMemory(&si, sizeof(si)); SecureZeroMemory(&pi, sizeof(pi)); si.cb = sizeof(si); - // locate CreateProcessWithTokenW in Advapi32.dll - if (!CreateProcessWithTokenWPtr) - { - return false; - } - if (!ImpersonateSelf (SecurityImpersonation)) { return false; } if (!OpenThreadToken (GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, TRUE, &hThreadToken)) { return false; } else { TOKEN_PRIVILEGES tkp; tkp.PrivilegeCount = 1; LookupPrivilegeValueW(NULL, SE_INCREASE_QUOTA_NAME, &tkp.Privileges[0].Luid); tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!SetThreadToken(NULL, NULL)) { goto cleanup; } AdjustTokenPrivileges(hThreadToken, FALSE, &tkp, 0, NULL, NULL); dwLastErr = GetLastError(); if (ERROR_SUCCESS != dwLastErr) { goto cleanup; } } // From this point down, we have handles to close, so make sure to clean up. @@ -14624,61 +14602,61 @@ static bool RunAsDesktopUser( goto cleanup; } // Open the desktop shell process in order to query it (get the token) hShellProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID); if (!hShellProcess) { dwLastErr = GetLastError(); goto cleanup; } // Get the process token of the desktop shell. ret = OpenProcessToken(hShellProcess, TOKEN_DUPLICATE, &hShellProcessToken); if (!ret) { dwLastErr = GetLastError(); goto cleanup; } // Duplicate the shell's process token to get a primary token. // Based on experimentation, this is the minimal set of rights required for CreateProcessWithTokenW (contrary to current documentation). const DWORD dwTokenRights = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID; ret = DuplicateTokenEx(hShellProcessToken, dwTokenRights, NULL, SecurityImpersonation, TokenPrimary, &hPrimaryToken); if (!ret) { dwLastErr = GetLastError(); goto cleanup; } // Start the target process with the new token. - ret = CreateProcessWithTokenWPtr( + ret = CreateProcessWithTokenW( hPrimaryToken, 0, szApp, szCmdLine, 0, NULL, NULL, &si, &pi); if (!ret) { dwLastErr = GetLastError(); goto cleanup; } // Make sure to close HANDLEs return in the PROCESS_INFORMATION. CloseHandle(pi.hProcess); CloseHandle(pi.hThread); retval = true; cleanup: // Clean up resources if (hShellProcessToken) CloseHandle(hShellProcessToken); if (hPrimaryToken) CloseHandle(hPrimaryToken); if (hShellProcess) CloseHandle(hShellProcess); if (hThreadToken) CloseHandle(hThreadToken); if (!RevertToSelf()) return false; @@ -14698,190 +14676,190 @@ BOOL IsElevated() if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { if(GetTokenInformation(hToken, TokenElevation, &tokenInformation, sizeof(TOKEN_ELEVATION), &dwSize)) { if (tokenInformation.TokenIsElevated) bReturn = TRUE; } CloseHandle(hToken); } return bReturn; } // Based on code from: // https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/winui/shell/appplatform/ExecInExplorer/ExecInExplorer.cpp HRESULT GetShellViewForDesktop(REFIID riid, void **ppv) { *ppv = NULL; IShellWindows *psw; HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&psw)); if (SUCCEEDED(hr)) { HWND hwnd; IDispatch* pdisp; VARIANT vEmpty = {}; // VT_EMPTY if (S_OK == psw->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, (long*)&hwnd, SWFO_NEEDDISPATCH, &pdisp)) { IShellBrowser *psb; - hr = IUnknown_QueryServicePtr(pdisp, SID_STopLevelBrowser, IID_PPV_ARGS(&psb)); + hr = IUnknown_QueryService(pdisp, SID_STopLevelBrowser, IID_PPV_ARGS(&psb)); if (SUCCEEDED(hr)) { IShellView *psv; hr = psb->QueryActiveShellView(&psv); if (SUCCEEDED(hr)) { hr = psv->QueryInterface(riid, ppv); psv->Release(); } psb->Release(); } pdisp->Release(); } else { hr = E_FAIL; } psw->Release(); } return hr; } HRESULT GetShellDispatchFromView(IShellView *psv, REFIID riid, void **ppv) { *ppv = NULL; IDispatch *pdispBackground; HRESULT hr = psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&pdispBackground)); if (SUCCEEDED(hr)) { IShellFolderViewDual *psfvd; hr = pdispBackground->QueryInterface(IID_PPV_ARGS(&psfvd)); if (SUCCEEDED(hr)) { IDispatch *pdisp; hr = psfvd->get_Application(&pdisp); if (SUCCEEDED(hr)) { hr = pdisp->QueryInterface(riid, ppv); pdisp->Release(); } psfvd->Release(); } pdispBackground->Release(); } return hr; } HRESULT ShellExecInExplorerProcess(PCWSTR pszFile) { IShellView *psv; - CoInitialize(NULL); + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); HRESULT hr = GetShellViewForDesktop(IID_PPV_ARGS(&psv)); if (SUCCEEDED(hr)) { IShellDispatch2 *psd; hr = GetShellDispatchFromView(psv, IID_PPV_ARGS(&psd)); if (SUCCEEDED(hr)) { BSTR bstrFile = SysAllocString(pszFile); hr = bstrFile ? S_OK : E_OUTOFMEMORY; if (SUCCEEDED(hr)) { VARIANT vtEmpty = {}; // VT_EMPTY hr = psd->ShellExecuteW(bstrFile, vtEmpty, vtEmpty, vtEmpty, vtEmpty); SysFreeString(bstrFile); } psd->Release(); } psv->Release(); } CoUninitialize(); return hr; } // This function always loads a URL in a non-privileged mode // If current process has admin privileges, we execute the command "rundll32 url.dll,FileProtocolHandler URL" as non-elevated // Use this security mechanism only starting from Windows Vista and only if we can get the window of the Shell's desktop since // we rely on the Shell to be already running in a non-privileges mode. If the Shell is not running or if it has been modified, // then we can't protect the user in such non standard environment void SafeOpenURL (LPCWSTR szUrl) { BOOL bFallback = TRUE; - if (IsOSAtLeast (WIN_VISTA) && IsUacSupported() && IsAdmin () && IsElevated() && GetShellWindow()) + if (IsUacSupported() && IsAdmin () && IsElevated() && GetShellWindow()) { WCHAR szRunDllPath[TC_MAX_PATH]; WCHAR szUrlDllPath[TC_MAX_PATH]; WCHAR szSystemPath[TC_MAX_PATH]; LPWSTR szCommandLine = new WCHAR[1024]; if (!GetSystemDirectory(szSystemPath, MAX_PATH)) StringCbCopyW(szSystemPath, sizeof(szSystemPath), L"C:\\Windows\\System32"); StringCbPrintfW(szRunDllPath, sizeof(szRunDllPath), L"%s\\%s", szSystemPath, L"rundll32.exe"); StringCbPrintfW(szUrlDllPath, sizeof(szUrlDllPath), L"%s\\%s", szSystemPath, L"url.dll"); StringCchPrintfW(szCommandLine, 1024, L"%s %s,FileProtocolHandler %s", szRunDllPath, szUrlDllPath, szUrl); if (RunAsDesktopUser (NULL, szCommandLine)) { bFallback = FALSE; } else { // fallback to IShellDispatch2::ShellExecuteW if (SUCCEEDED(ShellExecInExplorerProcess(szUrl))) { bFallback = FALSE; } } delete [] szCommandLine; } if (bFallback) { ShellExecuteW (NULL, L"open", szUrl, NULL, NULL, SW_SHOWNORMAL); } } #if !defined(SETUP) && defined(_WIN64) #define RtlGenRandom SystemFunction036 extern "C" BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed) { LARGE_INTEGER iSeed; SYSTEMTIME sysTime; - byte digest[WHIRLPOOL_DIGESTSIZE]; + uint8 digest[WHIRLPOOL_DIGESTSIZE]; WHIRLPOOL_CTX tctx; size_t count; while (cbRandSeed) { WHIRLPOOL_init (&tctx); // we hash current content of digest buffer which is uninitialized the first time WHIRLPOOL_add (digest, WHIRLPOOL_DIGESTSIZE, &tctx); // we use various time information as source of entropy GetSystemTime (&sysTime); WHIRLPOOL_add ((unsigned char *) &sysTime, sizeof(sysTime), &tctx); if (QueryPerformanceCounter (&iSeed)) WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); if (QueryPerformanceFrequency (&iSeed)) WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); /* use Windows random generator as entropy source */ if (RtlGenRandom (digest, sizeof (digest))) WHIRLPOOL_add (digest, sizeof(digest), &tctx); /* use JitterEntropy library to get good quality random bytes based on CPU timing jitter */ if (0 == jent_entropy_init ()) { struct rand_data *ec = jent_entropy_collector_alloc (1, 0); if (ec) { ssize_t rndLen = jent_read_entropy (ec, (char*) digest, sizeof (digest)); if (rndLen > 0) WHIRLPOOL_add (digest, (unsigned int) rndLen, &tctx); @@ -14922,123 +14900,103 @@ typedef enum BitLockerProtectionState { BL_State_FullyDecrypted = 0, BL_State_FullyEncrypted = 1, BL_State_EncryptionInProgress = 2, BL_State_DecryptionInProgress = 3, BL_State_EncryptionSuspended = 4, BL_State_DecryptionSuspended = 5, BL_State_FullyEncryptedWipeInProgress = 6, BL_State_FullyEncryptedWipeSuspended = 7 } BitLockerProtectionState; typedef HRESULT (WINAPI *SHCreateItemFromParsingNameFn)( PCWSTR pszPath, IBindCtx* pbc, REFIID riid, void** ppv ); typedef HRESULT (WINAPI *PSGetPropertyKeyFromNameFn)( _In_ PCWSTR pszName, _Out_ PROPERTYKEY* ppropkey); /* Code derived from https://stackoverflow.com/questions/23841973/how-to-tell-if-drive-is-bitlocker-encrypted-without-admin-privilege/47192128#47192128 */ BitLockerEncryptionStatus GetBitLockerEncryptionStatus(WCHAR driveLetter) { HRESULT hr; BitLockerEncryptionStatus blStatus = BL_Status_Unknown; - wchar_t szDllPath[MAX_PATH] = { 0 }; - HMODULE hShell32 = NULL; + wchar_t szDllPath[MAX_PATH] = { 0 }; + HMODULE hPropsys = NULL; - CoInitialize(NULL); + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); if (GetSystemDirectory(szDllPath, MAX_PATH)) - StringCchCatW(szDllPath, MAX_PATH, L"\\Shell32.dll"); + StringCchCatW(szDllPath, MAX_PATH, L"\\Propsys.dll"); else - StringCchCopyW(szDllPath, MAX_PATH, L"C:\\Windows\\System32\\Shell32.dll"); + StringCchCopyW(szDllPath, MAX_PATH, L"C:\\Windows\\System32\\Propsys.dll"); - hShell32 = LoadLibrary(szDllPath); - if (hShell32) + hPropsys = LoadLibrary(szDllPath); + if (hPropsys) { - SHCreateItemFromParsingNameFn SHCreateItemFromParsingNamePtr = (SHCreateItemFromParsingNameFn)GetProcAddress(hShell32, "SHCreateItemFromParsingName"); - if (SHCreateItemFromParsingNamePtr) + PSGetPropertyKeyFromNameFn PSGetPropertyKeyFromNamePtr = (PSGetPropertyKeyFromNameFn)GetProcAddress(hPropsys, "PSGetPropertyKeyFromName"); + if (PSGetPropertyKeyFromNamePtr) { - HMODULE hPropsys = NULL; - - if (GetSystemDirectory(szDllPath, MAX_PATH)) - StringCchCatW(szDllPath, MAX_PATH, L"\\Propsys.dll"); - else - StringCchCopyW(szDllPath, MAX_PATH, L"C:\\Windows\\System32\\Propsys.dll"); - - hPropsys = LoadLibrary(szDllPath); - if (hPropsys) - { - PSGetPropertyKeyFromNameFn PSGetPropertyKeyFromNamePtr = (PSGetPropertyKeyFromNameFn)GetProcAddress(hPropsys, "PSGetPropertyKeyFromName"); - if (PSGetPropertyKeyFromNamePtr) - { - WCHAR parsingName[3] = {driveLetter, L':', 0}; - IShellItem2* drive = NULL; - hr = SHCreateItemFromParsingNamePtr(parsingName, NULL, IID_PPV_ARGS(&drive)); + WCHAR parsingName[3] = {driveLetter, L':', 0}; + IShellItem2* drive = NULL; + hr = SHCreateItemFromParsingName(parsingName, NULL, IID_PPV_ARGS(&drive)); + if (SUCCEEDED(hr)) { + PROPERTYKEY pKey; + hr = PSGetPropertyKeyFromNamePtr(L"System.Volume.BitLockerProtection", &pKey); + if (SUCCEEDED(hr)) { + PROPVARIANT prop; + PropVariantInit(&prop); + hr = drive->GetProperty(pKey, &prop); if (SUCCEEDED(hr)) { - PROPERTYKEY pKey; - hr = PSGetPropertyKeyFromNamePtr(L"System.Volume.BitLockerProtection", &pKey); - if (SUCCEEDED(hr)) { - PROPVARIANT prop; - PropVariantInit(&prop); - hr = drive->GetProperty(pKey, &prop); - if (SUCCEEDED(hr)) { - int status = prop.intVal; - if (status == BL_State_FullyEncrypted || status == BL_State_DecryptionInProgress || status == BL_State_DecryptionSuspended) - blStatus = BL_Status_Protected; - else - blStatus = BL_Status_Unprotected; - } - } + int status = prop.intVal; + if (status == BL_State_FullyEncrypted || status == BL_State_DecryptionInProgress || status == BL_State_DecryptionSuspended) + blStatus = BL_Status_Protected; + else + blStatus = BL_Status_Unprotected; } - if (drive) - drive->Release(); } - - FreeLibrary(hPropsys); } - } - else - { - blStatus = BL_Status_Unprotected; // before Vista, there was no Bitlocker + if (drive) + drive->Release(); } - FreeLibrary(hShell32); + FreeLibrary(hPropsys); } + CoUninitialize(); return blStatus; } //////////////////////////////////////////////////////////////////////////////////////// static CLIPFORMAT g_supportedFormats[] = { CF_UNICODETEXT, CF_TEXT, CF_OEMTEXT}; //************************************************************* // GenericDropTarget //************************************************************* GenericDropTarget::GenericDropTarget(CLIPFORMAT* pFormats, size_t count) : m_DropTargetWnd(NULL), m_dwRefCount(1), m_KeyState(0L), m_Data(NULL) { m_DropPoint.x = 0; m_DropPoint.y = 0; if (pFormats && count) { for (size_t i = 0; i < count; i++) { m_SupportedFormat.push_back (pFormats[i]); } } } GenericDropTarget::~GenericDropTarget() @@ -15393,60 +15351,87 @@ void PasswordEditDropTarget::GotDrop(CLIPFORMAT format) { EDITBALLOONTIP ebt; DWORD dwTextSize = (DWORD) wcslen (GetString ("PASSWORD_PASTED_TRUNCATED")) + 16; WCHAR* szErrorText = (WCHAR*) malloc (dwTextSize * sizeof (WCHAR)); StringCchPrintf (szErrorText, dwTextSize, GetString ("PASSWORD_PASTED_TRUNCATED"), maxLen); ebt.cbStruct = sizeof( EDITBALLOONTIP ); ebt.pszText = szErrorText; ebt.pszTitle = lpszTitle; ebt.ttiIcon = TTI_WARNING_LARGE; // tooltip warning icon SendMessage(hChild, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt); MessageBeep (0xFFFFFFFF); free (szErrorText); } } if (bFree) { burn (wszText, wlen * sizeof (WCHAR)); delete [] wszText; } } } } +// check if the PC is connected to the internet using INetworkListManager interface +BOOL IsInternetConnected() +{ + HRESULT hr; + BOOL isConnected = FALSE; + INetworkListManager* pNetworkListManager = nullptr; + + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if (SUCCEEDED(hr)) + { + hr = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pNetworkListManager)); + if (SUCCEEDED(hr)) + { + VARIANT_BOOL isConnectedVariant; + hr = pNetworkListManager->get_IsConnectedToInternet(&isConnectedVariant); + if (SUCCEEDED(hr)) + { + isConnected = isConnectedVariant == VARIANT_TRUE; + } + pNetworkListManager->Release(); + } + CoUninitialize(); + } + + return isConnected; +} + /* * Query the status of Hibernate and Fast Startup */ typedef BOOLEAN (WINAPI *GetPwrCapabilitiesFn)( PSYSTEM_POWER_CAPABILITIES lpspc ); BOOL GetHibernateStatus (BOOL& bHibernateEnabled, BOOL& bHiberbootEnabled) { wchar_t szPowrProfPath[MAX_PATH] = {0}; HMODULE hPowrProf = NULL; BOOL bResult = FALSE; bHibernateEnabled = bHiberbootEnabled = FALSE; if (GetSystemDirectory(szPowrProfPath, MAX_PATH)) StringCchCatW (szPowrProfPath, MAX_PATH, L"\\PowrProf.dll"); else StringCchCopyW (szPowrProfPath, MAX_PATH, L"C:\\Windows\\System32\\PowrProf.dll"); hPowrProf = LoadLibrary (szPowrProfPath); if (hPowrProf) { GetPwrCapabilitiesFn GetPwrCapabilitiesPtr = (GetPwrCapabilitiesFn) GetProcAddress (hPowrProf, "GetPwrCapabilities"); if ( GetPwrCapabilitiesPtr) { SYSTEM_POWER_CAPABILITIES spc; BOOLEAN bRet = GetPwrCapabilitiesPtr (&spc); if (bRet) @@ -15501,61 +15486,61 @@ BOOL GetHibernateStatus (BOOL& bHibernateEnabled, BOOL& bHiberbootEnabled) BOOL IsTestSigningModeEnabled () { BOOL bEnabled = FALSE; NtQuerySystemInformationFn NtQuerySystemInformationPtr = (NtQuerySystemInformationFn) GetProcAddress (GetModuleHandle (L"ntdll.dll"), "NtQuerySystemInformation"); if(NtQuerySystemInformationPtr) { SYSTEM_CODEINTEGRITY_INFORMATION info = {0}; ULONG cbReturnedData = 0; info.Length = sizeof(info); if ( (NtQuerySystemInformationPtr((SYSTEM_INFORMATION_CLASS) SYSTEMCODEINTEGRITYINFORMATION, &info, sizeof(info), &cbReturnedData) >= 0) && (cbReturnedData == sizeof(info)) ) { if ((info.CodeIntegrityOptions & (CODEINTEGRITY_OPTION_TESTSIGN | CODEINTEGRITY_OPTION_ENABLED)) == (CODEINTEGRITY_OPTION_TESTSIGN | CODEINTEGRITY_OPTION_ENABLED)) { bEnabled = TRUE; } } } return bEnabled; } // Adapted from https://docs.microsoft.com/en-us/windows/win32/wmisdk/example-creating-a-wmi-application bool GetKbList (std::vector<std::wstring>& kbList) { HRESULT hres; kbList.clear(); // Initialize COM. - hres = CoInitialize(NULL); + hres = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); if (FAILED(hres)) { return false; } // Initialize hres = CoInitializeSecurity( NULL, -1, // COM negotiates service NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); if (FAILED(hres)) { CoUninitialize(); return false; } // Obtain the initial locator to Windows Management // on a particular host computer. IWbemLocator *pLoc = 0; hres = CoCreateInstance( @@ -15716,31 +15701,81 @@ DWORD SendServiceNotification (DWORD dwNotificationCmd) { DWORD dwRet = ERROR_INVALID_PARAMETER; // We only support clearing keys on new device insertion if (VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION == dwNotificationCmd) { DWORD dwServiceControlCode = VC_SERVICE_CONTROL_BUILD_DEVICE_LIST; // send this control code to VeraCrypt SystemFavorites service SC_HANDLE hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT); if (hSCManager != NULL) { SC_HANDLE hService = OpenService (hSCManager, TC_SYSTEM_FAVORITES_SERVICE_NAME, SERVICE_ALL_ACCESS); if (hService != NULL) { SERVICE_STATUS ss; if (ControlService (hService, dwServiceControlCode, &ss)) dwRet = ERROR_SUCCESS; else dwRet = GetLastError (); CloseServiceHandle (hService); } else dwRet = GetLastError (); CloseServiceHandle (hSCManager); } else dwRet = GetLastError (); } return dwRet; } -#endif // VC_COMREG
\ No newline at end of file + +DWORD FastResizeFile (const wchar_t* filePath, __int64 fileSize) +{ + DWORD dwRet = ERROR_INVALID_PARAMETER; + if (filePath && fileSize > 0) + { + // we set required privileges to speedup file creation before we create the file so that the file handle inherits the privileges + BOOL bPrivilegesSet = IsPrivilegeEnabled (SE_MANAGE_VOLUME_NAME); + if (!bPrivilegesSet && !SetPrivilege(SE_MANAGE_VOLUME_NAME, TRUE)) + { + dwRet = GetLastError (); + } + else + { + HANDLE dev = CreateFile (filePath, GENERIC_WRITE | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (dev != INVALID_HANDLE_VALUE) + { + LARGE_INTEGER liSize; + liSize.QuadPart = fileSize; + // Preallocate the file with desired size + if (!SetFilePointerEx (dev, liSize, NULL, FILE_BEGIN) + || !SetEndOfFile (dev)) + { + dwRet = GetLastError (); + } + else + { + if (!SetFileValidData (dev, fileSize)) + { + dwRet = GetLastError (); + } + else + { + dwRet = ERROR_SUCCESS; + } + } + + FlushFileBuffers (dev); + CloseHandle (dev); + } + else + dwRet = GetLastError (); + + if (!bPrivilegesSet) + SetPrivilege(SE_MANAGE_VOLUME_NAME, FALSE); + } + } + + return dwRet; +} +#endif // VC_COMREG |