From fc37cc4a02ed13d1a73b941a9f80975600fd1b99 Mon Sep 17 00:00:00 2001 From: David Foerster Date: Tue, 10 May 2016 20:20:14 +0200 Subject: Normalize all line terminators --- src/Common/Dlgcode.c | 23780 ++++++++++++++++++++++++------------------------- 1 file changed, 11890 insertions(+), 11890 deletions(-) (limited to 'src/Common/Dlgcode.c') diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index 97dd5247..ef6a942f 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -1,11890 +1,11890 @@ -/* - 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-2016 IDRIX - and are governed by the Apache License 2.0 the full text of which is - contained in the file License.txt included in VeraCrypt binary and source - code distribution packages. */ - -#include "Tcdefs.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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" - -#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 - -using namespace VeraCrypt; - -LONG DriverVersion; - -char *LastDialogId; -wchar_t szHelpFile[TC_MAX_PATH]; -wchar_t szHelpFile2[TC_MAX_PATH]; -wchar_t SecurityTokenLibraryPath[TC_MAX_PATH]; - -HFONT hFixedDigitFont = NULL; -HFONT hBoldFont = NULL; -HFONT hTitleFont = NULL; -HFONT hFixedFont = NULL; - -HFONT hUserFont = NULL; -HFONT hUserUnderlineFont = NULL; -HFONT hUserBoldFont = NULL; -HFONT hUserUnderlineBoldFont = NULL; - -HFONT WindowTitleBarFont; - -WCHAR EditPasswordChar = 0; - -int ScreenDPI = USER_DEFAULT_SCREEN_DPI; -double DPIScaleFactorX = 1; -double DPIScaleFactorY = 1; -double DlgAspectRatio = 1; - -HWND MainDlg = NULL; -wchar_t *lpszTitle = NULL; - -BOOL Silent = FALSE; -BOOL bPreserveTimestamp = TRUE; -BOOL bShowDisconnectedNetworkDrives = FALSE; -BOOL bHideWaitingDialog = FALSE; -BOOL bCmdHideWaitingDialog = FALSE; -BOOL bCmdHideWaitingDialogValid = FALSE; -BOOL bStartOnLogon = FALSE; -BOOL bMountDevicesOnLogon = FALSE; -BOOL bMountFavoritesOnLogon = FALSE; - -BOOL bHistory = FALSE; - -// Status of detection of hidden sectors (whole-system-drive encryption). -// 0 - Unknown/undetermined/completed, 1: Detection is or was in progress (but did not complete e.g. due to system crash). -int HiddenSectorDetectionStatus = 0; - -OSVersionEnum nCurrentOS = WIN_UNKNOWN; -int CurrentOSMajor = 0; -int CurrentOSMinor = 0; -int CurrentOSServicePack = 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; - -BOOL IgnoreWmDeviceChange = FALSE; -BOOL DeviceChangeBroadcastDisabled = FALSE; -BOOL LastMountedVolumeDirty; -BOOL MountVolumesAsSystemFavorite = FALSE; -BOOL FavoriteMountOnArrivalInProgress = FALSE; -BOOL MultipleMountOperationInProgress = 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; - -HINSTANCE hInst = NULL; -HCURSOR hCursor = NULL; - -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; - -#define FREE_DLL(h) if (h) { FreeLibrary (h); h = NULL;} - -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); - -// ChangeWindowMessageFilter -typedef BOOL (WINAPI *ChangeWindowMessageFilterPtr) (UINT, DWORD); - -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; -ChangeWindowMessageFilterPtr ChangeWindowMessageFilterFn = NULL; - -/* 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 -{ - BENCHMARK_SORT_BY_NAME = 0, - BENCHMARK_SORT_BY_SPEED -}; - -typedef struct -{ - int id; - wchar_t name[100]; - unsigned __int64 encSpeed; - unsigned __int64 decSpeed; - unsigned __int64 meanBytesPerSec; -} BENCHMARK_REC; - -BENCHMARK_REC benchmarkTable [BENCHMARK_MAX_ITEMS]; -int benchmarkTotalItems = 0; -int benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; -int benchmarkLastBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; -int benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED; -LARGE_INTEGER benchmarkPerformanceFrequency; - -#endif // #ifndef SETUP - - -typedef struct -{ - void *strings; - BOOL bold; - -} MULTI_CHOICE_DLGPROC_PARAMS; - - -void cleanup () -{ - /* Cleanup the GDI fonts */ - if (hFixedFont != NULL) - DeleteObject (hFixedFont); - if (hFixedDigitFont != NULL) - DeleteObject (hFixedDigitFont); - if (hBoldFont != NULL) - DeleteObject (hBoldFont); - if (hTitleFont != NULL) - DeleteObject (hTitleFont); - if (hUserFont != NULL) - DeleteObject (hUserFont); - if (hUserUnderlineFont != NULL) - DeleteObject (hUserUnderlineFont); - if (hUserBoldFont != NULL) - DeleteObject (hUserBoldFont); - if (hUserUnderlineBoldFont != NULL) - DeleteObject (hUserUnderlineBoldFont); - - /* Cleanup our dialog class */ - if (hDlgClass) - UnregisterClassW (TC_DLG_CLASS, hInst); - if (hSplashClass) - UnregisterClassW (TC_SPLASH_CLASS, hInst); - - /* Close the device driver handle */ - if (hDriver != INVALID_HANDLE_VALUE) - { - // Unload driver mode if possible (non-install mode) - if (IsNonInstallMode ()) - { - // If a dismount was forced in the lifetime of the driver, Windows may later prevent it to be loaded again from - // the same path. Therefore, the driver will not be unloaded even though it was loaded in non-install mode. - int driverUnloadDisabled; - DWORD dwResult; - - if (!DeviceIoControl (hDriver, TC_IOCTL_IS_DRIVER_UNLOAD_DISABLED, NULL, 0, &driverUnloadDisabled, sizeof (driverUnloadDisabled), &dwResult, NULL)) - driverUnloadDisabled = 0; - - if (!driverUnloadDisabled) - DriverUnload (); - else - { - CloseHandle (hDriver); - hDriver = INVALID_HANDLE_VALUE; - } - } - else - { - CloseHandle (hDriver); - hDriver = INVALID_HANDLE_VALUE; - } - } - - if (ConfigBuffer != NULL) - { - free (ConfigBuffer); - ConfigBuffer = NULL; - } - - CoUninitialize (); - - CloseSysEncMutex (); - -#ifndef SETUP - try - { - if (SecurityToken::IsInitialized()) - SecurityToken::CloseLibrary(); - } - catch (...) { } - - EncryptionThreadPoolStop(); -#endif - - DeleteCriticalSection (&csWNetCalls); -} - - -void LowerCaseCopy (wchar_t *lpszDest, const wchar_t *lpszSource) -{ - size_t i = wcslen (lpszSource) + 1; - - lpszDest[i - 1] = 0; - while (--i > 0) - { - lpszDest[i - 1] = (wchar_t) towlower (lpszSource[i - 1]); - } - -} - -void UpperCaseCopy (wchar_t *lpszDest, size_t cbDest, const wchar_t *lpszSource) -{ - if (lpszDest && cbDest) - { - size_t i = wcslen (lpszSource); - if (i >= cbDest) - i = cbDest - 1; - - lpszDest[i] = 0; - i++; - while (--i > 0) - { - lpszDest[i - 1] = (wchar_t) towupper (lpszSource[i - 1]); - } - } -} - - -std::wstring ToUpperCase (const std::wstring &str) -{ - wstring u; - foreach (wchar_t c, str) - { - u += (wchar_t) towupper (c); - } - - return u; -} - -size_t TrimWhiteSpace(wchar_t *str) -{ - wchar_t *end, *ptr = str; - size_t out_size; - - if(!str || *str == 0) - return 0; - - // Trim leading space - while(iswspace(*ptr)) ptr++; - - if(*ptr == 0) // All spaces? - { - *str = 0; - return 0; - } - - // Trim trailing space - end = str + wcslen(str) - 1; - while(end > ptr && iswspace(*end)) end--; - end++; - - // Set output size to trimmed string length - out_size = (end - ptr); - - // Copy trimmed string and add null terminator - wmemmove(str, ptr, out_size); - str[out_size] = 0; - - return out_size; -} - -// check the validity of a file name -BOOL IsValidFileName(const wchar_t* str) -{ - static wchar_t invalidChars[9] = {L'<', L'>', L':', L'"', L'/', L'\\', L'|', L'?', L'*'}; - wchar_t c; - int i; - BOOL bNotDotOnly = FALSE; - while ((c = *str)) - { - if (c != L'.') - bNotDotOnly = TRUE; - for (i= 0; i < ARRAYSIZE(invalidChars); i++) - if (c == invalidChars[i]) - return FALSE; - str++; - } - - return bNotDotOnly; -} - -BOOL IsVolumeDeviceHosted (const wchar_t *lpszDiskFile) -{ - return wcsstr (lpszDiskFile, L"\\Device\\") == lpszDiskFile - || wcsstr (lpszDiskFile, L"\\DEVICE\\") == lpszDiskFile; -} - - -void CreateFullVolumePath (wchar_t *lpszDiskFile, size_t cbDiskFile, const wchar_t *lpszFileName, BOOL * bDevice) -{ - UpperCaseCopy (lpszDiskFile, cbDiskFile, lpszFileName); - - *bDevice = FALSE; - - if (wmemcmp (lpszDiskFile, L"\\DEVICE", 7) == 0) - { - *bDevice = TRUE; - } - - StringCbCopyW (lpszDiskFile, cbDiskFile, lpszFileName); - -#if _DEBUG - OutputDebugString (L"CreateFullVolumePath: "); - OutputDebugString (lpszDiskFile); - OutputDebugString (L"\n"); -#endif - -} - -int FakeDosNameForDevice (const wchar_t *lpszDiskFile , wchar_t *lpszDosDevice , size_t cbDosDevice, wchar_t *lpszCFDevice , size_t cbCFDevice, BOOL bNameOnly) -{ - BOOL bDosLinkCreated = TRUE; - StringCbPrintfW (lpszDosDevice, cbDosDevice,L"veracrypt%lu", GetCurrentProcessId ()); - - if (bNameOnly == FALSE) - bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile); - - if (bDosLinkCreated == FALSE) - return ERR_OS_ERROR; - else - StringCbPrintfW (lpszCFDevice, cbCFDevice,L"\\\\.\\%s", lpszDosDevice); - - return 0; -} - -int RemoveFakeDosName (wchar_t *lpszDiskFile, wchar_t *lpszDosDevice) -{ - BOOL bDosLinkRemoved = DefineDosDevice (DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | - DDD_REMOVE_DEFINITION, lpszDosDevice, lpszDiskFile); - if (bDosLinkRemoved == FALSE) - { - return ERR_OS_ERROR; - } - - return 0; -} - - -void AbortProcessDirect (wchar_t *abortMsg) -{ - // Note that this function also causes localcleanup() to be called (see atexit()) - MessageBeep (MB_ICONEXCLAMATION); - MessageBoxW (NULL, abortMsg, lpszTitle, ICON_HAND); - FREE_DLL (hRichEditDll); - FREE_DLL (hComctl32Dll); - FREE_DLL (hSetupDll); - FREE_DLL (hShlwapiDll); - FREE_DLL (hProfApiDll); - FREE_DLL (hUsp10Dll); - FREE_DLL (hCryptSpDll); - FREE_DLL (hUXThemeDll); - FREE_DLL (hUserenvDll); - FREE_DLL (hRsaenhDll); - FREE_DLL (himm32dll); - FREE_DLL (hMSCTFdll); - FREE_DLL (hfltlibdll); - FREE_DLL (hframedyndll); - FREE_DLL (hpsapidll); - FREE_DLL (hsecur32dll); - FREE_DLL (hnetapi32dll); - FREE_DLL (hauthzdll); - FREE_DLL (hxmllitedll); - FREE_DLL (hmprdll); - FREE_DLL (hsppdll); - FREE_DLL (vssapidll); - FREE_DLL (hvsstracedll); - FREE_DLL (hCryptSpDll); - FREE_DLL (hcfgmgr32dll); - FREE_DLL (hdevobjdll); - FREE_DLL (hpowrprofdll); - FREE_DLL (hsspiclidll); - FREE_DLL (hcryptbasedll); - FREE_DLL (hdwmapidll); - FREE_DLL (hmsasn1dll); - FREE_DLL (hcrypt32dll); - FREE_DLL (hbcryptdll); - FREE_DLL (hbcryptprimitivesdll); - FREE_DLL (hMsls31); - FREE_DLL (hntmartadll); - FREE_DLL (hwinscarddll); - - exit (1); -} - -void AbortProcess (char *stringId) -{ - // Note that this function also causes localcleanup() to be called (see atexit()) - AbortProcessDirect (GetString (stringId)); -} - -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); - - // Note that this function also causes localcleanup() to be called (see atexit()) - exit (1); -} - - -#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; -} - - -BOOL IsDiskReadError (DWORD error) -{ - return (error == ERROR_CRC - || error == ERROR_IO_DEVICE - || error == ERROR_BAD_CLUSTERS - || error == ERROR_SECTOR_NOT_FOUND - || error == ERROR_READ_FAULT - || error == ERROR_INVALID_FUNCTION // I/O error may be reported as ERROR_INVALID_FUNCTION by buggy chipset drivers - || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT -} - - -BOOL IsDiskWriteError (DWORD error) -{ - return (error == ERROR_IO_DEVICE - || error == ERROR_BAD_CLUSTERS - || error == ERROR_SECTOR_NOT_FOUND - || error == ERROR_WRITE_FAULT - || error == ERROR_INVALID_FUNCTION // I/O error may be reported as ERROR_INVALID_FUNCTION by buggy chipset drivers - || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT -} - - -BOOL IsDiskError (DWORD error) -{ - return IsDiskReadError (error) || IsDiskWriteError (error); -} - - -DWORD handleWin32Error (HWND hwndDlg, const char* srcPos) -{ - PWSTR lpMsgBuf; - DWORD dwError = GetLastError (); - wchar_t szErrorValue[32]; - wchar_t* pszDesc; - - if (Silent || dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE) - return dwError; - - // Access denied - if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ()) - { - ErrorDirect ( AppendSrcPos (GetString ("ERR_ACCESS_DENIED"), srcPos).c_str (), hwndDlg); - SetLastError (dwError); // Preserve the original error code - return dwError; - } - - FormatMessageW ( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dwError, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ - (PWSTR) &lpMsgBuf, - 0, - NULL - ); - - if (lpMsgBuf) - pszDesc = (wchar_t*) lpMsgBuf; - else - { - StringCchPrintfW (szErrorValue, ARRAYSIZE (szErrorValue), L"Error 0x%.8X", dwError); - pszDesc = szErrorValue; - } - - MessageBoxW (hwndDlg, AppendSrcPos (pszDesc, srcPos).c_str (), lpszTitle, ICON_HAND); - if (lpMsgBuf) LocalFree (lpMsgBuf); - - // User-friendly hardware error explanation - if (IsDiskError (dwError)) - Error ("ERR_HARDWARE_ERROR", hwndDlg); - - // Device not ready - if (dwError == ERROR_NOT_READY) - HandleDriveNotReadyError(hwndDlg); - - SetLastError (dwError); // Preserve the original error code - - return dwError; -} - -BOOL translateWin32Error (wchar_t *lpszMsgBuf, int nWSizeOfBuf) -{ - DWORD dwError = GetLastError (); - - if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ - lpszMsgBuf, nWSizeOfBuf, NULL)) - { - SetLastError (dwError); // Preserve the original error code - return TRUE; - } - - SetLastError (dwError); // Preserve the original error code - return FALSE; -} - -// If the user has a non-default screen DPI, all absolute font sizes must be -// converted using this function. -int CompensateDPIFont (int val) -{ - if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) - return val; - else - { - double tmpVal = (double) val * DPIScaleFactorY * DlgAspectRatio * 0.999; - - if (tmpVal > 0) - return (int) floor(tmpVal); - else - return (int) ceil(tmpVal); - } -} - - -// If the user has a non-default screen DPI, some screen coordinates and sizes must -// be converted using this function -int CompensateXDPI (int val) -{ - if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) - return val; - else - { - double tmpVal = (double) val * DPIScaleFactorX; - - if (tmpVal > 0) - return (int) floor(tmpVal); - else - return (int) ceil(tmpVal); - } -} - - -// If the user has a non-default screen DPI, some screen coordinates and sizes must -// be converted using this function -int CompensateYDPI (int val) -{ - if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) - return val; - else - { - double tmpVal = (double) val * DPIScaleFactorY; - - if (tmpVal > 0) - return (int) floor(tmpVal); - else - return (int) ceil(tmpVal); - } -} - - -int GetTextGfxWidth (HWND hwndDlgItem, const wchar_t *text, HFONT hFont) -{ - SIZE sizes; - TEXTMETRIC textMetrics; - HDC hdc = GetDC (hwndDlgItem); - - SelectObject(hdc, (HGDIOBJ) hFont); - - GetTextExtentPoint32W (hdc, text, (int) wcslen (text), &sizes); - - GetTextMetrics(hdc, &textMetrics); // Necessary for non-TrueType raster fonts (tmOverhang) - - ReleaseDC (hwndDlgItem, hdc); - - return ((int) sizes.cx - (int) textMetrics.tmOverhang); -} - - -int GetTextGfxHeight (HWND hwndDlgItem, const wchar_t *text, HFONT hFont) -{ - SIZE sizes; - HDC hdc = GetDC (hwndDlgItem); - - SelectObject(hdc, (HGDIOBJ) hFont); - - GetTextExtentPoint32W (hdc, text, (int) wcslen (text), &sizes); - - ReleaseDC (hwndDlgItem, hdc); - - return ((int) sizes.cy); -} - - -std::wstring FitPathInGfxWidth (HWND hwnd, HFONT hFont, LONG width, const std::wstring &path) -{ - wstring newPath; - - RECT rect; - rect.left = 0; - rect.top = 0; - rect.right = width; - rect.bottom = LONG_MAX; - - HDC hdc = GetDC (hwnd); - SelectObject (hdc, (HGDIOBJ) hFont); - - wchar_t pathBuf[TC_MAX_PATH]; - StringCchCopyW (pathBuf, ARRAYSIZE (pathBuf), path.c_str()); - - if (DrawText (hdc, pathBuf, (int) path.size(), &rect, DT_CALCRECT | DT_MODIFYSTRING | DT_PATH_ELLIPSIS | DT_SINGLELINE) != 0) - newPath = pathBuf; - - ReleaseDC (hwnd, hdc); - return newPath; -} - - -static LRESULT CALLBACK HyperlinkProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA); - - switch (message) - { - case WM_SETCURSOR: - if (!bHyperLinkBeingTracked) - { - TRACKMOUSEEVENT trackMouseEvent; - - trackMouseEvent.cbSize = sizeof(trackMouseEvent); - trackMouseEvent.dwFlags = TME_LEAVE; - trackMouseEvent.hwndTrack = hwnd; - - bHyperLinkBeingTracked = TrackMouseEvent(&trackMouseEvent); - - HandCursor(); - } - return 0; - - case WM_MOUSELEAVE: - bHyperLinkBeingTracked = FALSE; - NormalCursor(); - return 0; - } - - return CallWindowProcW (wp, hwnd, message, wParam, lParam); -} - - -BOOL ToHyperlink (HWND hwndDlg, UINT ctrlId) -{ - return ToCustHyperlink (hwndDlg, ctrlId, hUserUnderlineFont); -} - - -BOOL ToCustHyperlink (HWND hwndDlg, UINT ctrlId, HFONT hFont) -{ - HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); - - SendMessageW (hwndCtrl, WM_SETFONT, (WPARAM) hFont, 0); - - SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC)); - SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) HyperlinkProc); - - // Resize the field according to its actual size in pixels and move it if centered or right-aligned. - // This should be done again if the link text changes. - AccommodateTextField (hwndDlg, ctrlId, TRUE, hFont); - - return TRUE; -} - - -// Resizes a text field according to its actual width and height in pixels (font size is taken into account) and moves -// it accordingly if the field is centered or right-aligned. Should be used on all hyperlinks upon dialog init -// after localization (bFirstUpdate should be TRUE) and later whenever a hyperlink text changes (bFirstUpdate -// must be FALSE). -void AccommodateTextField (HWND hwndDlg, UINT ctrlId, BOOL bFirstUpdate, HFONT hFont) -{ - RECT rec, wrec, trec; - HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); - int width, origWidth, height, origHeight; - int horizSubOffset, vertSubOffset, vertOffset, alignPosDiff = 0; - wchar_t text [MAX_URL_LENGTH]; - WINDOWINFO windowInfo; - BOOL bBorderlessWindow = !(GetWindowLongPtrW (hwndDlg, GWL_STYLE) & (WS_BORDER | WS_DLGFRAME)); - - // 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); - height = GetTextGfxHeight (hwndCtrl, text, hFont); - - GetClientRect (hwndCtrl, &rec); - origWidth = rec.right; - origHeight = rec.bottom; - - if (width >= 0 - && (!bFirstUpdate || origWidth > width)) // The original width of the field is the maximum allowed size - { - horizSubOffset = origWidth - width; - vertSubOffset = origHeight - height; - - // Window coords - GetWindowRect(hwndDlg, &wrec); - GetClientRect(hwndDlg, &trec); - - // Vertical "title bar" offset - vertOffset = wrec.bottom - wrec.top - trec.bottom - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CYFIXEDFRAME)); - - // Text field coords - GetWindowRect(hwndCtrl, &rec); - - // Alignment offset - windowInfo.cbSize = sizeof(windowInfo); - GetWindowInfo (hwndCtrl, &windowInfo); - - if (windowInfo.dwStyle & SS_CENTER) - 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); - } -} - -// 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); -} - -// Protects an input field from having its content updated by a Paste action (call ToBootPwdField() to use this). -static LRESULT CALLBACK BootPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA); - - switch (message) - { - case WM_PASTE: - return 1; - } - - return CallWindowProcW (wp, hwnd, message, wParam, lParam); -} - - -// Protects an input field from having its content updated by a Paste action. Used for pre-boot password -// input fields (only the US keyboard layout is supported in pre-boot environment so we must prevent the -// user from pasting a password typed using a non-US keyboard layout). -void ToBootPwdField (HWND hwndDlg, UINT ctrlId) -{ - HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); - - SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC)); - SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) BootPwdFieldProc); -} - - - -// This function currently serves the following purposes: -// - Determines scaling factors for current screen DPI and GUI aspect ratio. -// - Determines how Windows skews the GUI aspect ratio (which happens when the user has a non-default DPI). -// The determined values must be used when performing some GUI operations and calculations. -BOOL CALLBACK AuxiliaryDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_INITDIALOG: - { - HDC hDC = GetDC (hwndDlg); - - if (hDC) - { - ScreenDPI = GetDeviceCaps (hDC, LOGPIXELSY); - ReleaseDC (hwndDlg, hDC); - } - - DPIScaleFactorX = 1; - DPIScaleFactorY = 1; - DlgAspectRatio = 1; - - if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) - { - // Windows skews the GUI aspect ratio if the user has a non-default DPI. Hence, working with - // actual screen DPI is redundant and leads to incorrect results. What really matters here is - // how Windows actually renders our GUI. This is determined by comparing the expected and current - // sizes of a hidden calibration text field. - - RECT trec; - - trec.right = 0; - trec.bottom = 0; - - GetClientRect (GetDlgItem (hwndDlg, IDC_ASPECT_RATIO_CALIBRATION_BOX), &trec); - - if (trec.right != 0 && trec.bottom != 0) - { - // The size of the 282x282 IDC_ASPECT_RATIO_CALIBRATION_BOX rendered at the default DPI (96) is 423x458 - DPIScaleFactorX = (double) trec.right / 423; - DPIScaleFactorY = (double) trec.bottom / 458; - DlgAspectRatio = DPIScaleFactorX / DPIScaleFactorY; - } - } - - EndDialog (hwndDlg, 0); - return 1; - } - - case WM_CLOSE: - EndDialog (hwndDlg, 0); - return 1; - } - - return 0; -} - - -/* Except in response to the WM_INITDIALOG message, the dialog box procedure - should return nonzero if it processes the message, and zero if it does - not. - see DialogProc */ -BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - static HBITMAP hbmTextualLogoBitmapRescaled = NULL; - - switch (msg) - { - case WM_INITDIALOG: - { - wchar_t szTmp[100]; - RECT rec; - - LocalizeDialog (hwndDlg, "IDD_ABOUT_DLG"); - - // Hyperlink - SetWindowText (GetDlgItem (hwndDlg, IDC_HOMEPAGE), L"www.idrix.fr"); - ToHyperlink (hwndDlg, IDC_HOMEPAGE); - - // Logo area background (must not keep aspect ratio; must retain Windows-imposed distortion) - GetClientRect (GetDlgItem (hwndDlg, IDC_ABOUT_LOGO_AREA), &rec); - SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, rec.right, rec.bottom, SWP_NOMOVE); - - // Resize the logo bitmap if the user has a non-default DPI - if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) - { - // Logo (must recreate and keep the original aspect ratio as Windows distorts it) - hbmTextualLogoBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_TEXTUAL_LOGO_288DPI), - GetDlgItem (hwndDlg, IDC_TEXTUAL_LOGO_IMG), - 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)); -#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-2016 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 2002-2004 Mark Adler. All Rights Reserved.\r\n\r\n" - - L"This software as a whole:\r\n" - L"Copyright \xA9 2013-2016 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", TRUE, ""); - 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; -} - - -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; - } - - return 0; -} - - -// Opens a dialog window saying "Please wait..." which is not modal and does not need any GUI refresh after initialization. -void DisplayStaticModelessWaitDlg (HWND parent) -{ - if (StaticModelessWaitDlgHandle != NULL) - return; // Already shown - - StaticModelessWaitDlgHandle = CreateDialogParamW (hInst, MAKEINTRESOURCEW (IDD_STATIC_MODELESS_WAIT_DLG), parent, (DLGPROC) StaticModelessWaitDlgProc, (LPARAM) 0); - - ShowWindow (StaticModelessWaitDlgHandle, SW_SHOWNORMAL); - - // Allow synchronous use with the GUI being instantly and fully rendered - ProcessPaintMessages (StaticModelessWaitDlgHandle, 500); -} - - -void CloseStaticModelessWaitDlg (void) -{ - if (StaticModelessWaitDlgHandle == NULL) - return; // Not shown - - DestroyWindow (StaticModelessWaitDlgHandle); -} - - -BOOL IsButtonChecked (HWND hButton) -{ - if (SendMessage (hButton, BM_GETCHECK, 0, 0) == BST_CHECKED) - return TRUE; - else - return FALSE; -} - - -void CheckButton (HWND hButton) -{ - SendMessage (hButton, BM_SETCHECK, BST_CHECKED, 0); -} - - -void LeftPadString (wchar_t *szTmp, int len, int targetLen, wchar_t filler) -{ - int i; - - if (targetLen <= len) - return; - - for (i = targetLen-1; i >= (targetLen-len); i--) - szTmp [i] = szTmp [i-(targetLen-len)]; - - wmemset (szTmp, filler, targetLen-len); - szTmp [targetLen] = 0; -} - -/* InitDialog - initialize the applications main dialog, this function should - 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)) - { - // 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; - lf.lfOutPrecision = OUT_DEFAULT_PRECIS; - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfQuality = PROOF_QUALITY; - lf.lfPitchAndFamily = FF_DONTCARE; - StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName), L"Courier New"); - hFixedDigitFont = CreateFontIndirectW (&lf); - if (hFixedDigitFont == NULL) - { - handleWin32Error (hwndDlg, SRC_POS); - AbortProcess ("NOFONT"); - } - - // Bold - font = GetFont ("font_bold"); - - nHeight = CompensateDPIFont (!font ? -13 : -font->Size); - lf.lfHeight = nHeight; - lf.lfWeight = FW_BLACK; - StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName), !font ? L"Arial" : font->FaceName); - hBoldFont = CreateFontIndirectW (&lf); - if (hBoldFont == NULL) - { - handleWin32Error (hwndDlg, SRC_POS); - AbortProcess ("NOFONT"); - } - - // Title - font = GetFont ("font_title"); - - nHeight = CompensateDPIFont (!font ? -21 : -font->Size); - lf.lfHeight = nHeight; - lf.lfWeight = FW_REGULAR; - StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName),!font ? L"Times New Roman" : font->FaceName); - hTitleFont = CreateFontIndirectW (&lf); - if (hTitleFont == NULL) - { - handleWin32Error (hwndDlg, SRC_POS); - AbortProcess ("NOFONT"); - } - - // Fixed-size - font = GetFont ("font_fixed"); - - nHeight = CompensateDPIFont (!font ? -12 : -font->Size); - 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; - lf.lfOutPrecision = OUT_DEFAULT_PRECIS; - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfQuality = PROOF_QUALITY; - lf.lfPitchAndFamily = FF_DONTCARE; - StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName),!font ? L"Lucida Console" : font->FaceName); - hFixedFont = CreateFontIndirectW (&lf); - if (hFixedFont == NULL) - { - handleWin32Error (hwndDlg, SRC_POS); - AbortProcess ("NOFONT"); - } - - if (!aboutMenuAppended) - { - hMenu = GetSystemMenu (hwndDlg, FALSE); - AppendMenu (hMenu, MF_SEPARATOR, 0, L""); - AppendMenuW (hMenu, MF_ENABLED | MF_STRING, IDC_ABOUT, GetString ("ABOUTBOX")); - - aboutMenuAppended = TRUE; - } -} - - -// The parameter maxMessagesToProcess prevents endless processing of paint messages -void ProcessPaintMessages (HWND hwnd, int maxMessagesToProcess) -{ - MSG paintMsg; - int msgCounter = maxMessagesToProcess; - - while (PeekMessageW (&paintMsg, hwnd, 0, 0, PM_REMOVE | PM_QS_PAINT) != 0 && msgCounter-- > 0) - { - DispatchMessageW (&paintMsg); - } -} - - -HDC CreateMemBitmap (HINSTANCE hInstance, HWND hwnd, wchar_t *resource) -{ - HBITMAP picture = LoadBitmap (hInstance, resource); - HDC viewDC = GetDC (hwnd), dcMem; - - dcMem = CreateCompatibleDC (viewDC); - - SetMapMode (dcMem, MM_TEXT); - - SelectObject (dcMem, picture); - - DeleteObject (picture); - - ReleaseDC (hwnd, viewDC); - - return dcMem; -} - - -/* Renders the specified bitmap at the specified location and stretches it to fit (anti-aliasing is applied). -If bDirectRender is FALSE and both nWidth and nHeight are zero, the width and height of hwndDest are -retrieved and adjusted according to screen DPI (the width and height of the resultant image are adjusted the -same way); furthermore, if bKeepAspectRatio is TRUE, the smaller DPI factor of the two (i.e. horiz. or vert.) -is used both for horiz. and vert. scaling (note that the overall GUI aspect ratio changes irregularly in -both directions depending on the DPI). If bDirectRender is TRUE, bKeepAspectRatio is ignored. -This function returns a handle to the scaled bitmap. When the bitmap is no longer needed, it should be -deleted by calling DeleteObject() with the handle passed as the parameter. -Known Windows issues: -- For some reason, anti-aliasing is not applied if the source bitmap contains less than 16K pixels. -- Windows 2000 may produce slightly inaccurate colors even when source, buffer, and target are 24-bit true color. */ -HBITMAP RenderBitmap (wchar_t *resource, HWND hwndDest, int x, int y, int nWidth, int nHeight, BOOL bDirectRender, BOOL bKeepAspectRatio) -{ - LRESULT lResult = 0; - - HDC hdcSrc = CreateMemBitmap (hInst, hwndDest, resource); - if (!hdcSrc) - return NULL; - - HGDIOBJ picture = GetCurrentObject (hdcSrc, OBJ_BITMAP); - - HBITMAP hbmpRescaled = NULL; - BITMAP bitmap; - - HDC hdcRescaled; - - if (!bDirectRender && nWidth == 0 && nHeight == 0) - { - RECT rec; - - GetClientRect (hwndDest, &rec); - - if (bKeepAspectRatio) - { - if (DlgAspectRatio > 1) - { - // Do not fix this, it's correct. We use the Y scale factor intentionally for both - // directions to maintain aspect ratio (see above for more info). - nWidth = CompensateYDPI (rec.right); - nHeight = CompensateYDPI (rec.bottom); - } - else - { - // Do not fix this, it's correct. We use the X scale factor intentionally for both - // directions to maintain aspect ratio (see above for more info). - nWidth = CompensateXDPI (rec.right); - nHeight = CompensateXDPI (rec.bottom); - } - } - else - { - nWidth = CompensateXDPI (rec.right); - nHeight = CompensateYDPI (rec.bottom); - } - } - - GetObject (picture, sizeof (BITMAP), &bitmap); - - hdcRescaled = CreateCompatibleDC (hdcSrc); - - if (hdcRescaled) - { - hbmpRescaled = CreateCompatibleBitmap (hdcSrc, nWidth, nHeight); - - SelectObject (hdcRescaled, hbmpRescaled); - - /* Anti-aliasing mode (HALFTONE is the only anti-aliasing algorithm natively supported by Windows 2000. - TODO: GDI+ offers higher quality -- InterpolationModeHighQualityBicubic) */ - SetStretchBltMode (hdcRescaled, HALFTONE); - - StretchBlt (hdcRescaled, - 0, - 0, - nWidth, - nHeight, - hdcSrc, - 0, - 0, - bitmap.bmWidth, - bitmap.bmHeight, - SRCCOPY); - - DeleteDC (hdcSrc); - - if (bDirectRender) - { - HDC hdcDest = GetDC (hwndDest); - if (hdcDest) - { - BitBlt (hdcDest, x, y, nWidth, nHeight, hdcRescaled, 0, 0, SRCCOPY); - ReleaseDC (hwndDest, hdcDest); - } - } - else - { - lResult = SendMessage (hwndDest, (UINT) STM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) (HANDLE) hbmpRescaled); - } - - if ((HGDIOBJ) lResult != NULL && (HGDIOBJ) lResult != (HGDIOBJ) hbmpRescaled) - DeleteObject ((HGDIOBJ) lResult); - - DeleteDC (hdcRescaled); - } - - return hbmpRescaled; -} - - -LRESULT CALLBACK -RedTick (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_CREATE) - { - } - else if (uMsg == WM_DESTROY) - { - } - else if (uMsg == WM_TIMER) - { - } - else if (uMsg == WM_PAINT) - { - PAINTSTRUCT tmp; - HPEN hPen; - HDC hDC; - BOOL bEndPaint; - RECT Rect; - - if (GetUpdateRect (hwnd, NULL, FALSE)) - { - hDC = BeginPaint (hwnd, &tmp); - bEndPaint = TRUE; - if (hDC == NULL) - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - else - { - hDC = GetDC (hwnd); - bEndPaint = FALSE; - } - - GetClientRect (hwnd, &Rect); - - hPen = CreatePen (PS_SOLID, 2, RGB (0, 255, 0)); - if (hPen != NULL) - { - HGDIOBJ hObj = SelectObject (hDC, hPen); - WORD bx = LOWORD (GetDialogBaseUnits ()); - WORD by = HIWORD (GetDialogBaseUnits ()); - - MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL); - LineTo (hDC, Rect.right, Rect.top); - MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL); - - LineTo (hDC, (3 * bx) / 4, (2 * by) / 8); - - SelectObject (hDC, hObj); - DeleteObject (hPen); - } - - if (bEndPaint) - EndPaint (hwnd, &tmp); - else - ReleaseDC (hwnd, hDC); - - return TRUE; - } - - return DefWindowProcW (hwnd, uMsg, wParam, lParam); -} - -BOOL -RegisterRedTick (HINSTANCE hInstance) -{ - WNDCLASSW wc; - ULONG rc; - - memset(&wc, 0 , sizeof wc); - - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.cbClsExtra = 0; - wc.cbWndExtra = 4; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); - wc.hCursor = NULL; - wc.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH); - wc.lpszClassName = L"VCREDTICK"; - wc.lpfnWndProc = &RedTick; - - rc = (ULONG) RegisterClassW (&wc); - - return rc == 0 ? FALSE : TRUE; -} - -BOOL -UnregisterRedTick (HINSTANCE hInstance) -{ - return UnregisterClassW (L"VCREDTICK", hInstance); -} - -LRESULT CALLBACK -SplashDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return DefDlgProcW (hwnd, uMsg, wParam, lParam); -} - -static int g_waitCursorCounter = 0; - -void -WaitCursor () -{ - static HCURSOR hcWait; - if (hcWait == NULL) - hcWait = LoadCursor (NULL, IDC_WAIT); - - if ((g_waitCursorCounter == 0) || (hCursor != hcWait)) - { - SetCursor (hcWait); - hCursor = hcWait; - } - g_waitCursorCounter++; -} - -void -NormalCursor () -{ - static HCURSOR hcArrow; - if (hcArrow == NULL) - hcArrow = LoadCursor (NULL, IDC_ARROW); - if (g_waitCursorCounter > 0) - g_waitCursorCounter--; - if (g_waitCursorCounter == 0) - { - SetCursor (hcArrow); - hCursor = NULL; - } -} - -void -ArrowWaitCursor () -{ - static HCURSOR hcArrowWait; - if (hcArrowWait == NULL) - hcArrowWait = LoadCursor (NULL, IDC_APPSTARTING); - if ((g_waitCursorCounter == 0) || (hCursor != hcArrowWait)) - { - SetCursor (hcArrowWait); - hCursor = hcArrowWait; - } - g_waitCursorCounter++; -} - -void HandCursor () -{ - static HCURSOR hcHand; - if (hcHand == NULL) - hcHand = LoadCursor (NULL, IDC_HAND); - SetCursor (hcHand); - hCursor = hcHand; -} - -void -AddComboPair (HWND hComboBox, const wchar_t *lpszItem, int value) -{ - LPARAM nIndex; - - nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) lpszItem); - nIndex = SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) value); -} - -void -SelectAlgo (HWND hComboBox, int *algo_id) -{ - LPARAM nCount = SendMessage (hComboBox, CB_GETCOUNT, 0, 0); - LPARAM x, i; - - for (i = 0; i < nCount; i++) - { - x = SendMessage (hComboBox, CB_GETITEMDATA, i, 0); - if (x == (LPARAM) *algo_id) - { - SendMessage (hComboBox, CB_SETCURSEL, i, 0); - return; - } - } - - /* Something went wrong ; couldn't find the requested algo id so we drop - back to a default */ - - *algo_id = (int) SendMessage (hComboBox, CB_GETITEMDATA, 0, 0); - - SendMessage (hComboBox, CB_SETCURSEL, 0, 0); - -} - -void PopulateWipeModeCombo (HWND hComboBox, BOOL bNA, BOOL bInPlaceEncryption, BOOL bHeaderWipe) -{ - if (bNA) - { - AddComboPair (hComboBox, GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"), TC_WIPE_NONE); - } - else - { - if (!bHeaderWipe) - { - AddComboPair (hComboBox, GetString ("WIPE_MODE_NONE"), TC_WIPE_NONE); - } - - AddComboPair (hComboBox, GetString ("WIPE_MODE_1_RAND"), TC_WIPE_1_RAND); - AddComboPair (hComboBox, GetString ("WIPE_MODE_3_DOD_5220"), TC_WIPE_3_DOD_5220); - AddComboPair (hComboBox, GetString ("WIPE_MODE_7_DOD_5220"), TC_WIPE_7_DOD_5220); - AddComboPair (hComboBox, GetString ("WIPE_MODE_35_GUTMANN"), TC_WIPE_35_GUTMANN); - - if (bHeaderWipe) - AddComboPair (hComboBox, GetString ("WIPE_MODE_256"), TC_WIPE_256); // paranoid wipe for volume header - } -} - -wchar_t *GetWipeModeName (WipeAlgorithmId modeId) -{ - switch (modeId) - { - case TC_WIPE_NONE: - return GetString ("WIPE_MODE_NONE"); - - case TC_WIPE_1_RAND: - return GetString ("WIPE_MODE_1_RAND"); - - case TC_WIPE_3_DOD_5220: - return GetString ("WIPE_MODE_3_DOD_5220"); - - case TC_WIPE_7_DOD_5220: - return GetString ("WIPE_MODE_7_DOD_5220"); - - case TC_WIPE_35_GUTMANN: - return GetString ("WIPE_MODE_35_GUTMANN"); - - case TC_WIPE_256: - return GetString ("WIPE_MODE_256"); - - default: - return GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"); - } -} - -wchar_t *GetPathType (const wchar_t *path, BOOL bUpperCase, BOOL *bIsPartition) -{ - if (wcsstr (path, L"Partition") - && 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; - - 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; - //DWORD addr; - DWORD exCode = ep->ExceptionRecord->ExceptionCode; - // SYSTEM_INFO si; - // wchar_t msg[8192]; - // char modPath[MAX_PATH]; - // int crc = 0; - // char url[MAX_URL_LENGTH]; - // char lpack[128]; - // stringstream callStack; - // addr = (DWORD) ep->ExceptionRecord->ExceptionAddress; - // PDWORD sp = (PDWORD) ep->ContextRecord->Esp; - // int frameNumber = 0; - - switch (exCode) - { - case STATUS_IN_PAGE_ERROR: - case 0xeedfade: - // Exception not caused by VeraCrypt - MessageBoxW (0, GetString ("EXCEPTION_REPORT_EXT"), - GetString ("EXCEPTION_REPORT_TITLE"), - MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST); - return; - } - - // Call stack -/* HMODULE dbgDll = LoadLibrary ("dbghelp.dll"); - if (dbgDll) - { - typedef DWORD (__stdcall *SymGetOptions_t) (); - typedef DWORD (__stdcall *SymSetOptions_t) (DWORD SymOptions); - typedef BOOL (__stdcall *SymInitialize_t) (HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess); - typedef BOOL (__stdcall *StackWalk64_t) (DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); - typedef BOOL (__stdcall * SymFromAddr_t) (HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol); - - SymGetOptions_t DbgHelpSymGetOptions = (SymGetOptions_t) GetProcAddress (dbgDll, "SymGetOptions"); - SymSetOptions_t DbgHelpSymSetOptions = (SymSetOptions_t) GetProcAddress (dbgDll, "SymSetOptions"); - SymInitialize_t DbgHelpSymInitialize = (SymInitialize_t) GetProcAddress (dbgDll, "SymInitialize"); - PFUNCTION_TABLE_ACCESS_ROUTINE64 DbgHelpSymFunctionTableAccess64 = (PFUNCTION_TABLE_ACCESS_ROUTINE64) GetProcAddress (dbgDll, "SymFunctionTableAccess64"); - PGET_MODULE_BASE_ROUTINE64 DbgHelpSymGetModuleBase64 = (PGET_MODULE_BASE_ROUTINE64) GetProcAddress (dbgDll, "SymGetModuleBase64"); - StackWalk64_t DbgHelpStackWalk64 = (StackWalk64_t) GetProcAddress (dbgDll, "StackWalk64"); - SymFromAddr_t DbgHelpSymFromAddr = (SymFromAddr_t) GetProcAddress (dbgDll, "SymFromAddr"); - - if (DbgHelpSymGetOptions && DbgHelpSymSetOptions && DbgHelpSymInitialize && DbgHelpSymFunctionTableAccess64 && DbgHelpSymGetModuleBase64 && DbgHelpStackWalk64 && DbgHelpSymFromAddr) - { - DbgHelpSymSetOptions (DbgHelpSymGetOptions() | SYMOPT_DEFERRED_LOADS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_NO_CPP); - - if (DbgHelpSymInitialize (GetCurrentProcess(), NULL, TRUE)) - { - STACKFRAME64 frame; - memset (&frame, 0, sizeof (frame)); - - frame.AddrPC.Offset = ep->ContextRecord->Eip; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrStack.Offset = ep->ContextRecord->Esp; - frame.AddrStack.Mode = AddrModeFlat; - frame.AddrFrame.Offset = ep->ContextRecord->Ebp; - frame.AddrFrame.Mode = AddrModeFlat; - - string lastSymbol; - - while (frameNumber < 32 && DbgHelpStackWalk64 (IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), args->ExceptionThread, &frame, ep->ContextRecord, NULL, DbgHelpSymFunctionTableAccess64, DbgHelpSymGetModuleBase64, NULL)) - { - if (!frame.AddrPC.Offset) - continue; - - ULONG64 symbolBuffer[(sizeof (SYMBOL_INFO) + MAX_SYM_NAME * sizeof (TCHAR) + sizeof (ULONG64) - 1) / sizeof (ULONG64)]; - memset (symbolBuffer, 0, sizeof (symbolBuffer)); - - PSYMBOL_INFO symbol = (PSYMBOL_INFO) symbolBuffer; - symbol->SizeOfStruct = sizeof (SYMBOL_INFO); - symbol->MaxNameLen = MAX_SYM_NAME; - - if (DbgHelpSymFromAddr (GetCurrentProcess(), frame.AddrPC.Offset, NULL, symbol) && symbol->NameLen > 0) - { - 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 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); - 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; - } - } - - // Checksum of the module - if (GetModuleFileName (NULL, modPath, sizeof (modPath))) - { - HANDLE h = CreateFile (modPath, FILE_READ_DATA | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (h != INVALID_HANDLE_VALUE) - { - BY_HANDLE_FILE_INFORMATION fi; - if (GetFileInformationByHandle (h, &fi)) - { - char *buf = (char *) malloc (fi.nFileSizeLow); - if (buf) - { - DWORD bytesRead; - if (ReadFile (h, buf, fi.nFileSizeLow, &bytesRead, NULL) && bytesRead == fi.nFileSizeLow) - crc = GetCrc32 ((unsigned char *) buf, fi.nFileSizeLow); - free (buf); - } - } - CloseHandle (h); - } - } - - GetSystemInfo (&si); - - if (LocalizationActive) - sprintf_s (lpack, sizeof (lpack), "&langpack=%s_%s", GetPreferredLangId (), GetActiveLangPackVersion ()); - else - lpack[0] = 0; - - - sprintf (url, TC_APPLINK_SECURE "&dest=err-report%s&os=%s&osver=%d.%d.%d&arch=%s&cpus=%d&app=%s&cksum=%x&dlg=%s&err=%x&addr=%x" - , lpack - , GetWindowsEdition().c_str() - , CurrentOSMajor - , CurrentOSMinor - , CurrentOSServicePack - , Is64BitOs () ? "x64" : "x86" - , si.dwNumberOfProcessors -#ifdef TCMOUNT - ,"main" -#endif -#ifdef VOLFORMAT - ,"format" -#endif -#ifdef SETUP - ,"setup" -#endif - , crc - , LastDialogId ? LastDialogId : "-" - , exCode - , addr); - - string urlStr = url + callStack.str(); - - _snwprintf (msg, array_capacity (msg), GetString ("EXCEPTION_REPORT"), urlStr.c_str()); - - if (IDYES == MessageBoxW (0, msg, GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1)) - ShellExecute (NULL, "open", urlStr.c_str(), NULL, NULL, SW_SHOWNORMAL); - else */ - UnhandledExceptionFilter (ep); -} - - -LONG __stdcall ExceptionHandler (EXCEPTION_POINTERS *ep) -{ - SetUnhandledExceptionFilter (NULL); - - if (SystemFileSelectorCallPending && SystemFileSelectorCallerThreadId == GetCurrentThreadId()) - { - MessageBoxW (NULL, GetString ("EXCEPTION_REPORT_EXT_FILESEL"), GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST); - - UnhandledExceptionFilter (ep); - return EXCEPTION_EXECUTE_HANDLER; - } - - ExceptionHandlerThreadArgs args; - args.ExceptionPointers = ep; - args.ExceptionThread = GetCurrentThread(); - - WaitForSingleObject ((HANDLE) _beginthread (ExceptionHandlerThread, 0, &args), INFINITE); - - return EXCEPTION_EXECUTE_HANDLER; -} - - -void InvalidParameterHandler (const wchar_t *expression, const wchar_t *function, const wchar_t *file, unsigned int line, uintptr_t reserved) -{ - TC_THROW_FATAL_EXCEPTION; -} - - -static LRESULT CALLBACK NonInstallUacWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return DefWindowProcW (hWnd, message, wParam, lParam); -} - - -// Mutex handling to prevent multiple instances of the wizard or main app from dealing with system encryption. -// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). -BOOL CreateSysEncMutex (void) -{ - return TCCreateMutex (&hSysEncMutex, TC_MUTEX_NAME_SYSENC); -} - - -BOOL InstanceHasSysEncMutex (void) -{ - return (hSysEncMutex != NULL); -} - - -// Mutex handling to prevent multiple instances of the wizard from dealing with system encryption -void CloseSysEncMutex (void) -{ - TCCloseMutex (&hSysEncMutex); -} - - -// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). -BOOL CreateNonSysInplaceEncMutex (void) -{ - return TCCreateMutex (&hNonSysInplaceEncMutex, TC_MUTEX_NAME_NONSYS_INPLACE_ENC); -} - - -BOOL InstanceHasNonSysInplaceEncMutex (void) -{ - return (hNonSysInplaceEncMutex != NULL); -} - - -void CloseNonSysInplaceEncMutex (void) -{ - TCCloseMutex (&hNonSysInplaceEncMutex); -} - - -// Returns TRUE if another instance of the wizard is preparing, resuming or performing non-system in-place encryption -BOOL NonSysInplaceEncInProgressElsewhere (void) -{ - return (!InstanceHasNonSysInplaceEncMutex () - && MutexExistsOnSystem (TC_MUTEX_NAME_NONSYS_INPLACE_ENC)); -} - - -// Mutex handling 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. -// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). -BOOL CreateDriverSetupMutex (void) -{ - return TCCreateMutex (&hDriverSetupMutex, TC_MUTEX_NAME_DRIVER_SETUP); -} - - -void CloseDriverSetupMutex (void) -{ - TCCloseMutex (&hDriverSetupMutex); -} - - -BOOL CreateAppSetupMutex (void) -{ - return TCCreateMutex (&hAppSetupMutex, TC_MUTEX_NAME_APP_SETUP); -} - - -void CloseAppSetupMutex (void) -{ - TCCloseMutex (&hAppSetupMutex); -} - - -BOOL IsTrueCryptInstallerRunning (void) -{ - return (MutexExistsOnSystem (TC_MUTEX_NAME_APP_SETUP)); -} - - -// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). -BOOL TCCreateMutex (volatile HANDLE *hMutex, wchar_t *name) -{ - if (*hMutex != NULL) - return TRUE; // This instance already has the mutex - - *hMutex = CreateMutex (NULL, TRUE, name); - if (*hMutex == NULL) - { - // In multi-user configurations, the OS returns "Access is denied" here when a user attempts - // to acquire the mutex if another user already has. However, on Vista, "Access is denied" is - // returned also if the mutex is owned by a process with admin rights while we have none. - - return FALSE; - } - - if (GetLastError () == ERROR_ALREADY_EXISTS) - { - ReleaseMutex (*hMutex); - CloseHandle (*hMutex); - - *hMutex = NULL; - return FALSE; - } - - return TRUE; -} - - -void TCCloseMutex (volatile HANDLE *hMutex) -{ - if (*hMutex != NULL) - { - if (ReleaseMutex (*hMutex) - && CloseHandle (*hMutex)) - *hMutex = NULL; - } -} - - -// Returns TRUE if a process running on the system has the specified mutex (otherwise FALSE). -BOOL MutexExistsOnSystem (wchar_t *name) -{ - if (name[0] == 0) - return FALSE; - - HANDLE hMutex = OpenMutex (MUTEX_ALL_ACCESS, FALSE, name); - - if (hMutex == NULL) - { - if (GetLastError () == ERROR_FILE_NOT_FOUND) - return FALSE; - - if (GetLastError () == ERROR_ACCESS_DENIED) // On Vista, this is returned if the owner of the mutex is elevated while we are not - return TRUE; - - // The call failed and it is not certain whether the mutex exists or not - return FALSE; - } - - CloseHandle (hMutex); - return TRUE; -} - - -uint32 ReadDriverConfigurationFlags () -{ - DWORD configMap; - - if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", TC_DRIVER_CONFIG_REG_VALUE_NAME, &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 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) - { - newSystemEncryptionStatus = atoi (paramVal); - } - else if (strcmp (paramName, "WipeMode") == 0) - { - newnWipeMode = (WipeAlgorithmId) atoi (paramVal); - } - - xml++; - } - - SystemEncryptionStatus = newSystemEncryptionStatus; - nWipeMode = newnWipeMode; - - free (sysEncCfgFileBuf); - return status; -} - - -// Returns the number of partitions where non-system in-place encryption is progress or had been in progress -// but was interrupted. In addition, via the passed pointer, returns the last selected wipe algorithm ID. -int LoadNonSysInPlaceEncSettings (WipeAlgorithmId *wipeAlgorithm) -{ - char *fileBuf = NULL; - char *fileBuf2 = NULL; - DWORD size, size2; - int count; - - *wipeAlgorithm = TC_WIPE_NONE; - - if (!FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC))) - return 0; - - if ((fileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), &size)) == NULL) - return 0; - - if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) - { - if ((fileBuf2 = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE), &size2)) != NULL) - *wipeAlgorithm = (WipeAlgorithmId) atoi (fileBuf2); - } - - count = atoi (fileBuf); - - if (fileBuf != NULL) - TCfree (fileBuf); - - if (fileBuf2 != NULL) - TCfree (fileBuf2); - - return (count); -} - - -void RemoveNonSysInPlaceEncNotifications (void) -{ - if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC))) - _wremove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC)); - - if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) - _wremove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE)); - - if (!IsNonInstallMode () && SystemEncryptionStatus == SYSENC_STATUS_NONE) - ManageStartupSeqWiz (TRUE, L""); -} - - -void SavePostInstallTasksSettings (int command) -{ - FILE *f = NULL; - - if (IsNonInstallMode() && command != TC_POST_INSTALL_CFG_REMOVE_ALL) - return; - - switch (command) - { - case TC_POST_INSTALL_CFG_REMOVE_ALL: - _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL)); - _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES)); - break; - - case TC_POST_INSTALL_CFG_TUTORIAL: - f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL), L"w"); - break; - - case TC_POST_INSTALL_CFG_RELEASE_NOTES: - f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES), L"w"); - break; - - default: - return; - } - - if (f == NULL) - return; - - if (fputws (L"1", f) < 0) - { - // Error - fclose (f); - return; - } - - TCFlushFile (f); - - fclose (f); -} - - -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", TRUE, ""); - - bDone = TRUE; - } - - if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES))) - { - if (AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES", hwndDlg) == IDYES) - Applink ("releasenotes", TRUE, ""); - - bDone = TRUE; - } - - if (bDone) - SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_REMOVE_ALL); -} - - -void InitOSVersionInfo () -{ - OSVERSIONINFOEXW os; - os.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); - - if (GetVersionExW ((LPOSVERSIONINFOW) &os) == FALSE) - AbortProcess ("NO_OS_VER"); - - CurrentOSMajor = os.dwMajorVersion; - CurrentOSMinor = os.dwMinorVersion; - CurrentOSServicePack = os.wServicePackMajor; - - if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 0) - nCurrentOS = WIN_2000; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 1) - nCurrentOS = WIN_XP; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 2) - { - if (os.wProductType == VER_NT_SERVER || os.wProductType == VER_NT_DOMAIN_CONTROLLER) - nCurrentOS = WIN_SERVER_2003; - else - nCurrentOS = WIN_XP64; - } - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 0) - { - if (os.wProductType != VER_NT_WORKSTATION) - nCurrentOS = WIN_SERVER_2008; - else - nCurrentOS = WIN_VISTA; - } - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 1) - nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2008_R2 : WIN_7); - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 2) - nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012 : WIN_8); - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 3) - nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012_R2 : WIN_8_1); - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 10 && CurrentOSMinor == 0) - nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2016 : WIN_10); - else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 4) - nCurrentOS = WIN_NT4; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 0) - nCurrentOS = WIN_95; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 10) - nCurrentOS = WIN_98; - else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 90) - nCurrentOS = WIN_ME; - else if (os.dwPlatformId == VER_PLATFORM_WIN32s) - nCurrentOS = WIN_31; - else - nCurrentOS = WIN_UNKNOWN; -} - -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"); - - StringCbCatW(dllPath, sizeof(dllPath), L"\\"); - StringCbCatW(dllPath, sizeof(dllPath), szModuleName); - - if (((*pHandle = LoadLibrary(dllPath)) == NULL) && !bIgnoreError) - { - // This error is fatal - handleWin32Error (NULL, srcPos); - AbortProcess ("INIT_DLL"); - } -} - -/* 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; - - InitOSVersionInfo(); - - InitializeCriticalSection (&csWNetCalls); - - 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); - 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); - - LoadSystemDll (L"userenv.dll", &hUserenvDll, TRUE, SRC_POS); - LoadSystemDll (L"rsaenh.dll", &hRsaenhDll, TRUE, SRC_POS); - -#ifdef SETUP - if (nCurrentOS < 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); - } - } - - if (IsOSAtLeast (WIN_VISTA)) - { - LoadSystemDll (L"spp.dll", &hsppdll, TRUE, SRC_POS); - LoadSystemDll (L"vssapi.dll", &vssapidll, TRUE, SRC_POS); - LoadSystemDll (L"vsstrace.dll", &hvsstracedll, TRUE, SRC_POS); - - if (IsOSAtLeast (WIN_7)) - { - 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"dwmapi.dll", &hdwmapidll, TRUE, SRC_POS); - - LoadSystemDll (L"crypt32.dll", &hcrypt32dll, TRUE, SRC_POS); - - LoadSystemDll (L"bcrypt.dll", &hbcryptdll, TRUE, SRC_POS); - LoadSystemDll (L"bcryptprimitives.dll", &hbcryptprimitivesdll, TRUE, SRC_POS); - } - } -#else - LoadSystemDll (L"WINSCARD.DLL", &hwinscarddll, TRUE, SRC_POS); -#endif - - LoadSystemDll (L"COMCTL32.DLL", &hComctl32Dll, FALSE, SRC_POS); - - // 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"); - - LoadSystemDll (L"Riched20.dll", &hRichEditDll, FALSE, SRC_POS); - - // 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 function pointer - SHDeleteKeyWFn = (SHDeleteKeyWPtr) GetProcAddress (hShlwapiDll, "SHDeleteKeyW"); - SHStrDupWFn = (SHStrDupWPtr) GetProcAddress (hShlwapiDll, "SHStrDupW"); - if (!SHDeleteKeyWFn || !SHStrDupWFn) - 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); -#endif - } - - /* Save the instance handle for later */ - hInst = hInstance; - - SetErrorMode (SetErrorMode (0) | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); - CoInitialize (NULL); - -#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); -#endif - - // Language - langId[0] = 0; - SetPreferredLangId (ConfigReadString ("Language", "", langId, sizeof (langId))); - - if (langId[0] == 0) - { - if (IsNonInstallMode ()) - { - // only support automatic use of a language file in portable mode - // this is achieved by placing a unique language XML file in the same - // place as portable VeraCrypt binaries. - DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_LANGUAGE), NULL, - (DLGPROC) LanguageDlgProc, (LPARAM) 1); - } - else - { - // when installed, force using English as default language - SetPreferredLangId ("en"); - } - } - - LoadLanguageFile (); - -#ifndef SETUP - // UAC elevation moniker cannot be used in portable mode. - // A new instance of the application must be created with elevated privileges. - if (IsNonInstallMode () && !IsAdmin () && IsUacSupported ()) - { - wchar_t modPath[MAX_PATH], newCmdLine[4096]; - WNDCLASSEXW wcex; - HWND hWnd; - - if (wcsstr (lpszCommandLine, L"/q UAC ") == lpszCommandLine) - { - Error ("UAC_INIT_ERROR", NULL); - exit (1); - } - - memset (&wcex, 0, sizeof (wcex)); - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.lpfnWndProc = (WNDPROC) NonInstallUacWndProc; - wcex.hInstance = hInstance; - wcex.lpszClassName = L"VeraCrypt"; - RegisterClassExW (&wcex); - - // A small transparent window is necessary to bring the new instance to foreground - hWnd = CreateWindowExW (WS_EX_TOOLWINDOW | WS_EX_LAYERED, - L"VeraCrypt", L"VeraCrypt", 0, - GetSystemMetrics (SM_CXSCREEN)/2, - GetSystemMetrics (SM_CYSCREEN)/2, - 1, 1, NULL, NULL, hInstance, NULL); - - SetLayeredWindowAttributes (hWnd, 0, 0, LWA_ALPHA); - ShowWindow (hWnd, SW_SHOWNORMAL); - - GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath)); - - StringCbCopyW (newCmdLine, sizeof(newCmdLine), L"/q UAC "); - StringCbCatW (newCmdLine, sizeof (newCmdLine), lpszCommandLine); - - if ((int)ShellExecuteW (hWnd, L"runas", modPath, newCmdLine, NULL, SW_SHOWNORMAL) <= 32) - exit (1); - - Sleep (2000); - exit (0); - } -#endif - - SetUnhandledExceptionFilter (ExceptionHandler); - _set_invalid_parameter_handler (InvalidParameterHandler); - - RemoteSession = GetSystemMetrics (SM_REMOTESESSION) != 0; - - // OS version check - if (CurrentOSMajor < 5) - { - MessageBoxW (NULL, GetString ("UNSUPPORTED_OS"), lpszTitle, MB_ICONSTOP); - exit (1); - } - else - { - // Service pack check & warnings about critical MS issues - switch (nCurrentOS) - { - case WIN_2000: - if (CurrentOSServicePack < 3) - Warning ("LARGE_IDE_WARNING_2K", NULL); - else - { - DWORD val = 0, size = sizeof(val); - HKEY hkey; - - if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Atapi\\Parameters", 0, KEY_READ, &hkey) == ERROR_SUCCESS) - { - if (RegQueryValueExW (hkey, L"EnableBigLba", 0, 0, (LPBYTE) &val, &size) != ERROR_SUCCESS - || val != 1) - { - Warning ("LARGE_IDE_WARNING_2K_REGISTRY", NULL); - } - RegCloseKey (hkey); - } - } - break; - - 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 - 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); - 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); -} - -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"VeraCrypt User Guide.pdf"); - } - else - { - StringCbPrintfW (szTemp, sizeof(szTemp), L"VeraCrypt User Guide.%S.pdf", 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) - { - ++lpszTmp; - *lpszTmp = 0; - StringCbCatW (szHelpFile2, sizeof(szHelpFile2), L"VeraCrypt User Guide.pdf"); - } - } -} - -BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem, BOOL matchVolumeID, const BYTE* pbVolumeID) -{ - DWORD dwResult; - BOOL bResult; - wchar_t wszFileName[TC_MAX_PATH]; - - StringCbCopyW (wszFileName, sizeof(wszFileName), lpszPath); - - memset (driver, 0, sizeof (OPEN_TEST_STRUCT)); - memcpy (driver->wszFileName, wszFileName, sizeof (wszFileName)); - - driver->bDetectTCBootLoader = FALSE; - driver->DetectFilesystem = detectFilesystem; - driver->bMatchVolumeID = matchVolumeID; - if (matchVolumeID && pbVolumeID) - memcpy (driver->volumeID, pbVolumeID, VOLUME_ID_SIZE); - - bResult = DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, - driver, sizeof (OPEN_TEST_STRUCT), - driver, sizeof (OPEN_TEST_STRUCT), - &dwResult, NULL); - - // check variable driver - if ( bResult - && ( (driver->bDetectTCBootLoader != TRUE && driver->bDetectTCBootLoader != FALSE) || - (driver->TCBootLoaderDetected != TRUE && driver->TCBootLoaderDetected != FALSE) || - (driver->DetectFilesystem != TRUE && driver->DetectFilesystem != FALSE) || - (driver->FilesystemDetected != TRUE && driver->FilesystemDetected != FALSE) || - (wcscmp (wszFileName, driver->wszFileName)) - ) - ) - { - return FALSE; - } - - if (bResult == FALSE) - { - dwResult = GetLastError (); - - if (dwResult == ERROR_SHARING_VIOLATION || dwResult == ERROR_NOT_READY) - { - driver->TCBootLoaderDetected = FALSE; - driver->FilesystemDetected = FALSE; - driver->VolumeIDMatched = FALSE; - return TRUE; - } - else - return FALSE; - } - - return TRUE; -} - - -// Tells the driver that it's running in portable mode -void NotifyDriverOfPortableMode (void) -{ - if (hDriver != INVALID_HANDLE_VALUE) - { - DWORD dwResult; - - DeviceIoControl (hDriver, TC_IOCTL_SET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dwResult, NULL); - } -} - - -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); -} - - -/* 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)) - { - if (drive.ContainsSystem) - { - foreach (const HostDevice &sysDrivePartition, drive.Partitions) - { - if (sysDrivePartition.Bootable) - { - if (sysDrivePartition.Size <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE) - ExtraBootPartitionDevicePath = sysDrivePartition.Path; - 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. */ -int IsSystemDevicePath (const wchar_t *path, HWND hwndDlg, BOOL bReliableRequired) -{ - if (!bCachedSysDevicePathsValid - && bReliableRequired) - { - if (!GetSysDevicePaths (hwndDlg)) - return -1; - } - - if (wcslen (SysPartitionDevicePath) <= 1 || wcslen (SysDriveDevicePath) <= 1) - return -1; - - if (!path) - return -1; - - if (wcsncmp (path, SysPartitionDevicePath, max (wcslen(path), wcslen(SysPartitionDevicePath))) == 0) - return 1; - else if (wcsncmp (path, SysDriveDevicePath, max (wcslen(path), wcslen(SysDriveDevicePath))) == 0) - return 2; - else if (ExtraBootPartitionDevicePath == path) - return 3; - - return 0; -} - - -/* Determines whether the path points to a non-system partition on the system drive. -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, never at WM_INITDIALOG or any other GUI events. -Return codes: -0 - it isn't a non-system partition on the system drive -1 - it's a non-system partition on the system drive --1 - the result can't be determined, isn't reliable, or there was an error. */ -int IsNonSysPartitionOnSysDrive (const wchar_t *path) -{ - wchar_t tmpPath [TC_MAX_PATH + 1]; - int pos; - - if (!GetSysDevicePaths (MainDlg)) - return -1; - - if (wcslen (SysPartitionDevicePath) <= 1 || wcslen (SysDriveDevicePath) <= 1) - return -1; - - if (wcsncmp (path, SysPartitionDevicePath, max (wcslen(path), wcslen(SysPartitionDevicePath))) == 0 - || wcsncmp (path, SysDriveDevicePath, max (wcslen(path), wcslen(SysDriveDevicePath))) == 0) - { - // It is the system partition/drive path (it isn't a non-system partition) - return 0; - } - - memset (tmpPath, 0, sizeof (tmpPath)); - wcsncpy (tmpPath, path, ARRAYSIZE (tmpPath) - 1); - - - pos = (int) FindString ((const char*) tmpPath, (const char*) L"Partition", (int) wcslen (tmpPath) * 2, (int) wcslen (L"Partition") * 2, 0); - - if (pos < 0) - return -1; - - pos /= 2; - pos += (int) strlen ("Partition"); - - if (pos + 1 > ARRAYSIZE (tmpPath) - 1) - return -1; - - tmpPath [pos] = L'0'; - tmpPath [pos + 1] = 0; - - if (wcsncmp (tmpPath, SysDriveDevicePath, max (wcslen(tmpPath), wcslen(SysDriveDevicePath))) == 0) - { - // It is a non-system partition on the system drive - return 1; - } - else - { - // The partition is not on the system drive - return 0; - } -} - - -wstring GetSysEncryptionPretestInfo2String (void) -{ - // This huge string is divided into smaller portions to make it easier for translators to - // re-translate it when a minor modification is made to it (the whole huge string will not be - // reverted to English, so they will have to translate only a small portion of it). - return (wstring (L"\n") - + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_1") - + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_2") - + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_3") - + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_4")); -} - - -wstring GetRescueDiskHelpString (void) -{ - // This huge string is divided into smaller portions to make it easier for translators to - // re-translate it when a minor modification is made to it (the whole huge string will not be - // reverted to English, so they will have to translate only a small portion of it). - return (wstring ( - GetString ("RESCUE_DISK_HELP_PORTION_1")) - + GetString ("RESCUE_DISK_HELP_PORTION_2") - + GetString ("RESCUE_DISK_HELP_PORTION_3") - + GetString ("RESCUE_DISK_HELP_PORTION_4") - + GetString ("RESCUE_DISK_HELP_PORTION_5") - + GetString ("RESCUE_DISK_HELP_PORTION_6") - + GetString ("RESCUE_DISK_HELP_PORTION_7") - + GetString ("RESCUE_DISK_HELP_PORTION_8") - + GetString ("RESCUE_DISK_HELP_PORTION_9")); -} - - -wstring GetDecoyOsInstructionsString (void) -{ - // This huge string is divided into smaller portions to make it easier for translators to - // re-translate it when a minor modification is made to it (the whole huge string will not be - // reverted to English, so they will have to translate only a small portion of it). - return (wstring ( - GetString ("DECOY_OS_INSTRUCTIONS_PORTION_1")) - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_2") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_3") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_4") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_5") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_6") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_7") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_8") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_9") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_10") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_11") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_12") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_13") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_14") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_15") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_16") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_17") - + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_18")); -} - - -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; - - // Left margin for rich edit text field - SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4)); - - ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_HIDE); - - switch (nID) - { - case TC_TBXID_LEGAL_NOTICES: - LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE"); - break; - - case TC_TBXID_SYS_ENCRYPTION_PRETEST: - LocalizeDialog (hwndDlg, NULL); - ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); - break; - - case TC_TBXID_SYS_ENC_RESCUE_DISK: - LocalizeDialog (hwndDlg, NULL); - ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); - break; - - case TC_TBXID_DECOY_OS_INSTRUCTIONS: - LocalizeDialog (hwndDlg, NULL); - ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); - break; - - case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: - LocalizeDialog (hwndDlg, NULL); - ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); - break; - } - - SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0); - } - return 0; - - case WM_COMMAND: - if (lw == IDOK || lw == IDCANCEL) - { - NormalCursor (); - EndDialog (hwndDlg, 0); - return 1; - } - - if (lw == IDC_PRINT) - { - switch (nID) - { - case TC_TBXID_SYS_ENCRYPTION_PRETEST: - PrintHardCopyTextUTF16 ((wchar_t *) GetSysEncryptionPretestInfo2String ().c_str(), L"Pre-Boot Troubleshooting", GetSysEncryptionPretestInfo2String ().length () * 2); - break; - - case TC_TBXID_SYS_ENC_RESCUE_DISK: - PrintHardCopyTextUTF16 ((wchar_t *) GetRescueDiskHelpString ().c_str(), L"VeraCrypt Rescue Disk Help", GetRescueDiskHelpString ().length () * 2); - break; - - case TC_TBXID_DECOY_OS_INSTRUCTIONS: - PrintHardCopyTextUTF16 ((wchar_t *) GetDecoyOsInstructionsString ().c_str(), L"How to Create Decoy OS", GetDecoyOsInstructionsString ().length () * 2); - break; - - case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: - PrintHardCopyTextUTF16 (GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS"), L"How to Remove Extra Boot Partition", wcslen (GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS")) * 2); - break; - } - return 1; - } - - return 0; - - case TC_APPMSG_LOAD_TEXT_BOX_CONTENT: - { - char *r = NULL; - - switch (nID) - { - case TC_TBXID_LEGAL_NOTICES: - LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE"); - r = GetLegalNotices (); - if (r != NULL) - { - SETTEXTEX TextInfo = {0}; - - TextInfo.flags = ST_SELECTION; - TextInfo.codepage = CP_ACP; - - SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETTEXTEX, (WPARAM)&TextInfo, (LPARAM)r); - free (r); - } - break; - - case TC_TBXID_SYS_ENCRYPTION_PRETEST: - LocalizeDialog (hwndDlg, NULL); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetSysEncryptionPretestInfo2String ().c_str()); - break; - - case TC_TBXID_SYS_ENC_RESCUE_DISK: - LocalizeDialog (hwndDlg, NULL); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetRescueDiskHelpString ().c_str()); - break; - - case TC_TBXID_DECOY_OS_INSTRUCTIONS: - LocalizeDialog (hwndDlg, NULL); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetDecoyOsInstructionsString ().c_str()); - break; - - case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: - LocalizeDialog (hwndDlg, NULL); - SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS")); - break; - } - } - return 1; - - case WM_CLOSE: - NormalCursor (); - EndDialog (hwndDlg, 0); - return 1; - } - - return 0; -} - - -char * GetLegalNotices () -{ - static char *resource; - static DWORD size; - char *buf = NULL; - - if (resource == NULL) - resource = (char *) MapResource (L"Text", IDR_LICENSE, &size); - - if (resource != NULL) - { - buf = (char *) malloc (size + 1); - if (buf != NULL) - { - memcpy (buf, resource, size); - buf[size] = 0; - } - } - - return buf; -} - - -BOOL CALLBACK RawDevicesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static wchar_t *lpszFileName; // This is actually a pointer to a GLOBAL array - static vector devices; - static map itemToDeviceMap; - - WORD lw = LOWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - LVCOLUMNW LvCol; - HWND hList = GetDlgItem (hwndDlg, IDC_DEVICELIST); - RawDevicesDlgParam* pDlgParam = (RawDevicesDlgParam *) lParam; - - LocalizeDialog (hwndDlg, "IDD_RAWDEVICES_DLG"); - - SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, - LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP - ); - - memset (&LvCol,0,sizeof(LvCol)); - LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; - LvCol.pszText = GetString ("DEVICE"); - LvCol.cx = CompensateXDPI (186); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("DRIVE"); - LvCol.cx = CompensateXDPI (38); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("SIZE"); - LvCol.cx = CompensateXDPI (64); - LvCol.fmt = LVCFMT_RIGHT; - SendMessage (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("LABEL"); - LvCol.cx = CompensateXDPI (128); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol); - - devices.clear(); - itemToDeviceMap.clear(); - - if (pDlgParam->devices.empty()) - { - WaitCursor(); - devices = GetAvailableHostDevices (false, true, false); - NormalCursor(); - } - else - devices = pDlgParam->devices; - - if (devices.empty()) - { - MessageBoxW (hwndDlg, GetString ("RAWDEVICES"), lpszTitle, ICON_HAND); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - int line = 1; - LVITEM item; - memset (&item, 0, sizeof (item)); - item.mask = LVIF_TEXT; - - foreach (const HostDevice &device, devices) - { - item.iSubItem = 1; - - if (device.ContainsSystem) - { - if (device.IsPartition) - StringCbCopyW (SysPartitionDevicePath, sizeof (SysPartitionDevicePath), device.Path.c_str()); - else - StringCbCopyW (SysDriveDevicePath, sizeof (SysDriveDevicePath), device.Path.c_str()); - } - - // Path - if (!device.IsPartition || device.DynamicVolume) - { - if (!device.Floppy && (device.Size == 0) - && (device.IsPartition || device.Partitions.empty() || device.Partitions[0].Size == 0) - ) - continue; - - if (line > 1) - { - ListItemAdd (hList, item.iItem, L""); - item.iItem = line++; - } - - if (device.Floppy || device.DynamicVolume) - { - ListItemAdd (hList, item.iItem, (wchar_t *) device.Path.c_str()); - } - else - { - wchar_t s[1024]; - if (device.Removable) - StringCbPrintfW (s, sizeof(s), L"%s %d", GetString ("REMOVABLE_DISK"), device.SystemNumber); - else - StringCbPrintfW (s, sizeof(s), L"%s %d", GetString ("HARDDISK"), device.SystemNumber); - - if (!device.Partitions.empty()) - StringCbCatW (s, sizeof(s), L":"); - - ListItemAdd (hList, item.iItem, s); - } - } - else - { - ListItemAdd (hList, item.iItem, (wchar_t *) device.Path.c_str()); - } - - itemToDeviceMap[item.iItem] = device; - - // Size - if (device.Size != 0) - { - wchar_t size[100] = { 0 }; - GetSizeString (device.Size, size, sizeof(size)); - ListSubItemSet (hList, item.iItem, 2, size); - } - - // Mount point - if (!device.MountPoint.empty()) - ListSubItemSet (hList, item.iItem, 1, (wchar_t *) device.MountPoint.c_str()); - - // Label - if (!device.Name.empty()) - ListSubItemSet (hList, item.iItem, 3, (wchar_t *) device.Name.c_str()); -#ifdef TCMOUNT - else - { - bool useInExplorer = false; - wstring favoriteLabel = GetFavoriteVolumeLabel (device.Path, useInExplorer); - if (!favoriteLabel.empty()) - ListSubItemSet (hList, item.iItem, 3, (wchar_t *) favoriteLabel.c_str()); - } -#endif - - item.iItem = line++; - } - - SendMessageW(hList, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); - SendMessageW(hList, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); - SendMessageW(hList, LVM_SETCOLUMNWIDTH, 2, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); - SendMessageW(hList, LVM_SETCOLUMNWIDTH, 3, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); - - lpszFileName = pDlgParam->pszFileName; - -#ifdef VOLFORMAT - EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); -#endif - return 1; - } - - case WM_COMMAND: - case WM_NOTIFY: - // catch non-device line selected - if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED )) - { - BOOL bEnableOkButton = FALSE; - LVITEM LvItem; - memset(&LvItem,0,sizeof(LvItem)); - LvItem.mask = LVIF_TEXT | LVIF_PARAM; - LvItem.iItem = ((LPNMLISTVIEW) lParam)->iItem; - LvItem.pszText = lpszFileName; - LvItem.cchTextMax = TC_MAX_PATH; - - lpszFileName[0] = 0; - SendMessage (GetDlgItem (hwndDlg, IDC_DEVICELIST), LVM_GETITEM, LvItem.iItem, (LPARAM) &LvItem); - if (lpszFileName[0] != 0 && lpszFileName[0] != ' ') - { - bEnableOkButton = TRUE; -#ifdef VOLFORMAT - if ( bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE) - && LvItem.iItem != -1 && itemToDeviceMap.find (LvItem.iItem) != itemToDeviceMap.end() - ) - { - const HostDevice selectedDevice = itemToDeviceMap[LvItem.iItem]; - if (selectedDevice.ContainsSystem) - { - bEnableOkButton = FALSE; - } - } -#endif - } - EnableWindow (GetDlgItem ((HWND) hwndDlg, IDOK), bEnableOkButton); - - return 1; - } - - if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE) - { - int selectedItem = ListView_GetSelectionMark (GetDlgItem (hwndDlg, IDC_DEVICELIST)); - - if (selectedItem == -1 || itemToDeviceMap.find (selectedItem) == itemToDeviceMap.end()) - return 1; // non-device line selected - - const HostDevice selectedDevice = itemToDeviceMap[selectedItem]; - StringCchCopyW (lpszFileName, TC_MAX_PATH, selectedDevice.Path.c_str()); - -#ifdef VOLFORMAT - if (selectedDevice.ContainsSystem && selectedDevice.IsPartition) - { - if (WizardMode != WIZARD_MODE_SYS_DEVICE) - { - if (bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE)) - { - // disable selection - return 1; - } - - if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE", hwndDlg) == IDNO) - { - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - bSysPartitionSelected = TRUE; - bSysDriveSelected = FALSE; - lpszFileName[0] = 0; - SwitchWizardToSysEncMode (); - - NormalCursor (); - EndDialog (hwndDlg, IDOK); - return 1; - } - else - { - // This should never be the case because the Select Device dialog is not available in this wizard mode - bSysPartitionSelected = TRUE; - bSysDriveSelected = FALSE; - lpszFileName[0] = 0; - SwitchWizardToSysEncMode (); - NormalCursor (); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - } - - if (!(selectedDevice.ContainsSystem && !selectedDevice.IsPartition)) - { - if (bWarnDeviceFormatAdvanced - && !bHiddenVolDirect - && AskWarnNoYes("FORMAT_DEVICE_FOR_ADVANCED_ONLY", hwndDlg) == IDNO) - { - if (AskNoYes("CONFIRM_CHANGE_WIZARD_MODE_TO_FILE_CONTAINER", hwndDlg) == IDYES) - { - SwitchWizardToFileContainerMode (); - } - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - if (!bHiddenVolDirect) - bWarnDeviceFormatAdvanced = FALSE; - } - -#else // #ifdef VOLFORMAT - - bSysPartitionSelected = (selectedDevice.ContainsSystem && selectedDevice.IsPartition); - bSysDriveSelected = FALSE; - -#endif // #ifdef VOLFORMAT - - if (!selectedDevice.IsPartition && !selectedDevice.Floppy) - { - // Whole device selected - -#ifdef VOLFORMAT - if (selectedDevice.ContainsSystem && !selectedDevice.IsPartition) - { - if (WizardMode != WIZARD_MODE_SYS_DEVICE) - { - if (bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE)) - { - // disable selection - return 1; - } - - if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE", hwndDlg) == IDNO) - { - NormalCursor (); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - bSysDriveSelected = TRUE; - bSysPartitionSelected = FALSE; - lpszFileName[0] = 0; - SwitchWizardToSysEncMode (); - - NormalCursor (); - EndDialog (hwndDlg, IDOK); - return 1; - } - else - { - // This should never be the case because the Select Device dialog is not available in this wizard mode - bSysDriveSelected = TRUE; - bSysPartitionSelected = FALSE; - lpszFileName[0] = 0; - SwitchWizardToSysEncMode (); - NormalCursor (); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - } - - // Disallow format if the device contains partitions, but not if the partition is virtual or system - if (!selectedDevice.IsVirtualPartition - && !bHiddenVolDirect) - { - if (!selectedDevice.Partitions.empty()) - { - EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); - Error ("DEVICE_PARTITIONS_ERR_W_INPLACE_ENC_NOTE", hwndDlg); - return 1; - } - - if (AskWarnNoYes ("WHOLE_NONSYS_DEVICE_ENC_CONFIRM", hwndDlg) == IDNO) - return 1; - } -#else // #ifdef VOLFORMAT - - bSysDriveSelected = (selectedDevice.ContainsSystem && !selectedDevice.IsPartition); - bSysPartitionSelected = FALSE; - -#endif // #ifdef VOLFORMAT - } - else - bSysDriveSelected = FALSE; - -#ifdef VOLFORMAT - bRemovableHostDevice = selectedDevice.Removable; -#endif - NormalCursor (); - EndDialog (hwndDlg, IDOK); - return 1; - } - - if ((msg == WM_COMMAND) && (lw == IDCANCEL)) - { - NormalCursor (); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - return 0; - } - return 0; -} - - -BOOL DoDriverInstall (HWND hwndDlg) -{ -#ifdef SETUP - if (SystemEncryptionUpdate) - return TRUE; -#endif - - SC_HANDLE hManager, hService = NULL; - BOOL bOK = FALSE, bRet; - - hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (hManager == NULL) - goto error; - -#ifdef SETUP - StatusMessage (hwndDlg, "INSTALLING_DRIVER"); -#endif - - hService = CreateService (hManager, L"veracrypt", L"veracrypt", - SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_SYSTEM_START, SERVICE_ERROR_NORMAL, - L"System32\\drivers\\veracrypt.sys", - NULL, NULL, NULL, NULL, NULL); - - if (hService == NULL) - goto error; - else - CloseServiceHandle (hService); - - hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS); - if (hService == NULL) - goto error; - -#ifdef SETUP - StatusMessage (hwndDlg, "STARTING_DRIVER"); -#endif - - bRet = StartService (hService, 0, NULL); - if (bRet == FALSE) - goto error; - - bOK = TRUE; - -error: - if (bOK == FALSE && GetLastError () != ERROR_SERVICE_ALREADY_RUNNING) - { - handleWin32Error (hwndDlg, SRC_POS); - MessageBoxW (hwndDlg, GetString ("DRIVER_INSTALL_FAILED"), lpszTitle, MB_ICONHAND); - } - else - bOK = TRUE; - - if (hService != NULL) - CloseServiceHandle (hService); - - if (hManager != NULL) - CloseServiceHandle (hManager); - - return bOK; -} - - -// Install and start driver service and mark it for removal (non-install mode) -static int DriverLoad () -{ - HANDLE file; - WIN32_FIND_DATA find; - SC_HANDLE hManager, hService = NULL; - wchar_t driverPath[TC_MAX_PATH*2]; - BOOL res; - wchar_t *tmp; - DWORD startType; - - if (ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", L"Start", &startType) && startType == SERVICE_BOOT_START) - return ERR_PARAMETER_INCORRECT; - - GetModuleFileName (NULL, driverPath, ARRAYSIZE (driverPath)); - tmp = wcsrchr (driverPath, L'\\'); - if (!tmp) - { - driverPath[0] = L'.'; - driverPath[1] = 0; - } - else - *tmp = 0; - - StringCbCatW (driverPath, sizeof(driverPath), !Is64BitOs () ? L"\\veracrypt.sys" : L"\\veracrypt-x64.sys"); - - file = FindFirstFile (driverPath, &find); - - if (file == INVALID_HANDLE_VALUE) - { - MessageBoxW (0, GetString ("DRIVER_NOT_FOUND"), lpszTitle, ICON_HAND); - return ERR_DONT_REPORT; - } - - FindClose (file); - - hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (hManager == NULL) - { - if (GetLastError () == ERROR_ACCESS_DENIED) - { - MessageBoxW (0, GetString ("ADMIN_PRIVILEGES_DRIVER"), lpszTitle, ICON_HAND); - return ERR_DONT_REPORT; - } - - return ERR_OS_ERROR; - } - - hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS); - if (hService != NULL) - { - // Remove stale service (driver is not loaded but service exists) - DeleteService (hService); - CloseServiceHandle (hService); - Sleep (500); - } - - hService = CreateService (hManager, L"veracrypt", L"veracrypt", - SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, - driverPath, NULL, NULL, NULL, NULL, NULL); - - if (hService == NULL) - { - CloseServiceHandle (hManager); - return ERR_OS_ERROR; - } - - res = StartService (hService, 0, NULL); - DeleteService (hService); - - CloseServiceHandle (hManager); - CloseServiceHandle (hService); - - return !res ? ERR_OS_ERROR : ERROR_SUCCESS; -} - - -BOOL DriverUnload () -{ - MOUNT_LIST_STRUCT driver; - int refCount; - int volumesMounted; - DWORD dwResult; - BOOL bResult; - - SC_HANDLE hManager, hService = NULL; - BOOL bRet; - SERVICE_STATUS status; - int x; - BOOL driverUnloaded = FALSE; - - if (hDriver == INVALID_HANDLE_VALUE) - return TRUE; - - try - { - if (BootEncryption (NULL).GetStatus().DeviceFilterActive) - return FALSE; - } - catch (...) { } - - // Test for mounted volumes - bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL); - - if (!bResult) - { - bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL); - if (bResult) - volumesMounted = driver.ulMountedDrives; - } - - if (bResult) - { - if (volumesMounted != 0) - return FALSE; - } - else - return TRUE; - - // Test for any applications attached to driver - refCount = GetDriverRefCount (); - - if (refCount > 1) - return FALSE; - - CloseHandle (hDriver); - hDriver = INVALID_HANDLE_VALUE; - - // Stop driver service - - hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (hManager == NULL) - goto error; - - hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS); - if (hService == NULL) - goto error; - - bRet = QueryServiceStatus (hService, &status); - if (bRet != TRUE) - goto error; - - if (status.dwCurrentState != SERVICE_STOPPED) - { - ControlService (hService, SERVICE_CONTROL_STOP, &status); - - for (x = 0; x < 10; x++) - { - bRet = QueryServiceStatus (hService, &status); - if (bRet != TRUE) - goto error; - - if (status.dwCurrentState == SERVICE_STOPPED) - { - driverUnloaded = TRUE; - break; - } - - Sleep (200); - } - } - else - driverUnloaded = TRUE; - -error: - if (hService != NULL) - CloseServiceHandle (hService); - - if (hManager != NULL) - CloseServiceHandle (hManager); - - if (driverUnloaded) - { - hDriver = INVALID_HANDLE_VALUE; - return TRUE; - } - - return FALSE; -} - - -int DriverAttach (void) -{ - /* Try to open a handle to the device driver. It will be closed later. */ - -#ifndef SETUP - - int nLoadRetryCount = 0; -start: - -#endif - - hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (hDriver == INVALID_HANDLE_VALUE) - { -#ifndef SETUP - - LoadSysEncSettings (); - - if (!CreateDriverSetupMutex ()) - { - // Another instance is already attempting to install, register or start the driver - - while (!CreateDriverSetupMutex ()) - { - Sleep (100); // Wait until the other instance finishes - } - - // Try to open a handle to the driver again (keep the mutex in case the other instance failed) - goto start; - } - else - { - // No other instance is currently attempting to install, register or start the driver - - if (SystemEncryptionStatus != SYSENC_STATUS_NONE) - { - // This is an inconsistent state. The config file indicates system encryption should be - // active, but the driver is not running. This may happen e.g. when the pretest fails and - // the user selects "Last Known Good Configuration" from the Windows boot menu. - // To fix this, we're going to reinstall the driver, start it, and register it for boot. - - if (DoDriverInstall (NULL)) - { - Sleep (1000); - hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - try - { - BootEncryption bootEnc (NULL); - bootEnc.RegisterBootDriver (bootEnc.GetHiddenOSCreationPhase() != TC_HIDDEN_OS_CREATION_PHASE_NONE ? true : false); - } - catch (Exception &e) - { - e.Show (NULL); - } - } - - CloseDriverSetupMutex (); - } - else - { - // Attempt to load the driver (non-install/portable mode) -load: - BOOL res = DriverLoad (); - - CloseDriverSetupMutex (); - - if (res != ERROR_SUCCESS) - return res; - - bPortableModeConfirmed = TRUE; - - if (hDriver != INVALID_HANDLE_VALUE) - CloseHandle (hDriver); - hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - } - - if (bPortableModeConfirmed) - NotifyDriverOfPortableMode (); - } - -#endif // #ifndef SETUP - - if (hDriver == INVALID_HANDLE_VALUE) - return ERR_OS_ERROR; - } - - CloseDriverSetupMutex (); - - if (hDriver != INVALID_HANDLE_VALUE) - { - DWORD dwResult; - - BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL); - - if (!bResult) - bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL); - -#ifndef SETUP // Don't check version during setup to allow removal of another version - if (bResult == FALSE) - { - return ERR_OS_ERROR; - } - else if (DriverVersion != VERSION_NUM) - { - // Unload an incompatbile version of the driver loaded in non-install mode and load the required version - if (IsNonInstallMode () && CreateDriverSetupMutex () && DriverUnload () && nLoadRetryCount++ < 3) - goto load; - - CloseDriverSetupMutex (); - 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) -{ - return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, browseFilter); -} - - -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 }; - wchar_t filter[1024]; - BOOL status = FALSE; - - CoInitialize (NULL); - - ZeroMemory (&ofn, sizeof (ofn)); - *lpszFileName = 0; - - if (initialDir) - { - ofn.lpstrInitialDir = initialDir; - } - - 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) - { - if (!GetOpenFileNameW (&ofn)) - goto ret; - } - else - { - if (!GetSaveFileNameW (&ofn)) - goto ret; - } - - SystemFileSelectorCallPending = FALSE; - - StringCchCopyW (lpszFileName, MAX_PATH, file); - - if (!keepHistory) - CleanLastVisitedMRU (); - - status = TRUE; - -ret: - SystemFileSelectorCallPending = FALSE; - ResetCurrentDirectory(); - CoUninitialize(); - - return status; -} - - -static wchar_t SelectMultipleFilesPath[131072]; -static int SelectMultipleFilesOffset; - -BOOL SelectMultipleFiles (HWND hwndDlg, const char *stringId, wchar_t *lpszFileName, size_t cbFileName,BOOL keepHistory) -{ - OPENFILENAMEW ofn; - wchar_t filter[1024]; - BOOL status = FALSE; - - 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 (); - - SystemFileSelectorCallerThreadId = GetCurrentThreadId(); - SystemFileSelectorCallPending = TRUE; - - if (!GetOpenFileNameW (&ofn)) - goto ret; - - SystemFileSelectorCallPending = FALSE; - - 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); - } - - if (!keepHistory) - CleanLastVisitedMRU (); - - status = TRUE; - -ret: - SystemFileSelectorCallPending = FALSE; - ResetCurrentDirectory(); - CoUninitialize(); - - return status; -} - - -BOOL SelectMultipleFilesNext (wchar_t *lpszFileName, size_t cbFileName) -{ - if (SelectMultipleFilesOffset == 0) - return FALSE; - - StringCbCopyW (lpszFileName, cbFileName,SelectMultipleFilesPath); - lpszFileName[TC_MAX_PATH - 1] = 0; - - if (lpszFileName[wcslen (lpszFileName) - 1] != L'\\') - StringCbCatW (lpszFileName, cbFileName,L"\\"); - - StringCbCatW (lpszFileName, cbFileName,SelectMultipleFilesPath + SelectMultipleFilesOffset); - - SelectMultipleFilesOffset += (int) wcslen (SelectMultipleFilesPath + SelectMultipleFilesOffset) + 1; - if (SelectMultipleFilesPath[SelectMultipleFilesOffset] == 0) - { - SelectMultipleFilesOffset = 0; - SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath)); - } - - return TRUE; -} - - -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; - } - - case BFFM_SELCHANGED: - { - wchar_t szDir[TC_MAX_PATH]; - - /* Set the status window to the currently selected path. */ - if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir)) - { - SendMessage (hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir); - } - break; - } - - default: - break; - } - - return 0; -} - - -BOOL BrowseDirectories (HWND hwndDlg, char *lpszTitle, wchar_t *dirName) -{ - BROWSEINFOW bi; - LPITEMIDLIST pidl; - LPMALLOC pMalloc; - BOOL bOK = FALSE; - - CoInitialize (NULL); - - if (SUCCEEDED (SHGetMalloc (&pMalloc))) - { - 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; - - pidl = SHBrowseForFolderW (&bi); - if (pidl != NULL) - { - if (SHGetPathFromIDList(pidl, dirName)) - { - bOK = TRUE; - } - - pMalloc->Free (pidl); - pMalloc->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; - } -#endif - - return msg; -} - - -void handleError (HWND hwndDlg, int code, const char* srcPos) -{ - WCHAR szTmp[4096]; - - if (Silent) return; - - switch (code & 0x0000FFFF) - { - case ERR_OS_ERROR: - handleWin32Error (hwndDlg, srcPos); - break; - case ERR_OUTOFMEMORY: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OUTOFMEMORY"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - - case ERR_PASSWORD_WRONG: - MessageBoxW (hwndDlg, AppendSrcPos (GetWrongPasswordErrorMessage (hwndDlg).c_str(), srcPos).c_str(), lpszTitle, MB_ICONWARNING); - break; - - case ERR_DRIVE_NOT_FOUND: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NOT_FOUND"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_FILES_OPEN: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OPENFILES_DRIVER"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_FILES_OPEN_LOCK: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OPENFILES_LOCK"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_VOL_SIZE_WRONG: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_SIZE_WRONG"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_COMPRESSION_NOT_SUPPORTED: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("COMPRESSION_NOT_SUPPORTED"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_PASSWORD_CHANGE_VOL_TYPE: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("WRONG_VOL_TYPE"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_VOL_SEEKING: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_SEEKING"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_CIPHER_INIT_FAILURE: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_CIPHER_INIT_FAILURE"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_CIPHER_INIT_WEAK_KEY: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_CIPHER_INIT_WEAK_KEY"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_VOL_ALREADY_MOUNTED: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_ALREADY_MOUNTED"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_FILE_OPEN_FAILED: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("FILE_OPEN_FAILED"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_VOL_MOUNT_FAILED: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_MOUNT_FAILED"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_NO_FREE_DRIVES: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NO_FREE_DRIVES"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - case ERR_ACCESS_DENIED: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ACCESS_DENIED"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - - case ERR_DRIVER_VERSION: - Error ("DRIVER_VERSION", hwndDlg); - break; - - case ERR_NEW_VERSION_REQUIRED: - MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NEW_VERSION_REQUIRED"), srcPos).c_str(), lpszTitle, ICON_HAND); - break; - - case ERR_SELF_TESTS_FAILED: - Error ("ERR_SELF_TESTS_FAILED", hwndDlg); - break; - - case ERR_VOL_FORMAT_BAD: - Error ("ERR_VOL_FORMAT_BAD", hwndDlg); - break; - - case ERR_ENCRYPTION_NOT_COMPLETED: - Error ("ERR_ENCRYPTION_NOT_COMPLETED", hwndDlg); - break; - - 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; - - case ERR_UNSUPPORTED_TRUECRYPT_FORMAT: - StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("UNSUPPORTED_TRUECRYPT_FORMAT"), (code >> 24), (code >> 16) & 0x000000FF); - MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, ICON_HAND); - 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 - - 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) - { - WCHAR name[10] = { 0 }; - GetClassNameW (hwnd, name, array_capacity (name)); - - if (_wcsicmp (name, L"Button") == 0 || _wcsicmp (name, L"Static") == 0) - { - wchar_t *str = (wchar_t *) GetDictionaryValueByInt (ctrlId); - if (str != NULL) - SetWindowTextW (hwnd, str); - } - } - } - - // Font - SendMessageW (hwnd, WM_SETFONT, (WPARAM) font, 0); - - return TRUE; -} - -void LocalizeDialog (HWND hwnd, char *stringId) -{ - LastDialogId = stringId; - SetWindowLongPtrW (hwnd, GWLP_USERDATA, (LONG_PTR) 'VERA'); - SendMessageW (hwnd, WM_SETFONT, (WPARAM) hUserFont, 0); - - if (stringId == NULL) - SetWindowTextW (hwnd, L"VeraCrypt"); - else - SetWindowTextW (hwnd, GetString (stringId)); - - if (hUserFont != 0) - EnumChildWindows (hwnd, LocalizeDialogEnum, (LPARAM) hUserFont); -} - -void OpenVolumeExplorerWindow (int driveNo) -{ - wchar_t dosName[5]; - SHFILEINFO fInfo; - - StringCbPrintfW (dosName, sizeof(dosName), L"%c:\\", (wchar_t) driveNo + L'A'); - - // Force explorer to discover the drive - SHGetFileInfo (dosName, 0, &fInfo, sizeof (fInfo), 0); - - ShellExecute (NULL, L"open", dosName, NULL, NULL, SW_SHOWNORMAL); -} - -static BOOL explorerCloseSent; -static HWND explorerTopLevelWindow; - -static BOOL CALLBACK CloseVolumeExplorerWindowsChildEnum (HWND hwnd, LPARAM driveStr) -{ - WCHAR s[MAX_PATH]; - SendMessageW (hwnd, WM_GETTEXT, array_capacity (s), (LPARAM) s); - - if (wcsstr (s, (WCHAR *) driveStr) != NULL) - { - PostMessageW (explorerTopLevelWindow, WM_CLOSE, 0, 0); - explorerCloseSent = TRUE; - return FALSE; - } - - return TRUE; -} - -static BOOL CALLBACK CloseVolumeExplorerWindowsEnum (HWND hwnd, LPARAM driveNo) -{ - WCHAR driveStr[10]; - WCHAR s[MAX_PATH]; - - StringCbPrintfW (driveStr, sizeof(driveStr), L"%c:\\", driveNo + L'A'); - - GetClassNameW (hwnd, s, array_capacity (s)); - if (wcscmp (s, L"CabinetWClass") == 0) - { - GetWindowTextW (hwnd, s, array_capacity (s)); - if (wcsstr (s, driveStr) != NULL) - { - PostMessageW (hwnd, WM_CLOSE, 0, 0); - explorerCloseSent = TRUE; - return TRUE; - } - - explorerTopLevelWindow = hwnd; - EnumChildWindows (hwnd, CloseVolumeExplorerWindowsChildEnum, (LPARAM) driveStr); - } - - return TRUE; -} - -BOOL CloseVolumeExplorerWindows (HWND hwnd, int driveNo) -{ - if (driveNo >= 0) - { - explorerCloseSent = FALSE; - EnumWindows (CloseVolumeExplorerWindowsEnum, (LPARAM) driveNo); - } - - return explorerCloseSent; -} - -BOOL UpdateDriveCustomLabel (int driveNo, wchar_t* effectiveLabel, BOOL bSetValue) -{ - wchar_t wszRegPath[MAX_PATH]; - wchar_t driveStr[] = {L'A' + (wchar_t) driveNo, 0}; - HKEY hKey; - LSTATUS lStatus; - DWORD cbLabelLen = (DWORD) ((wcslen (effectiveLabel) + 1) * sizeof (wchar_t)); - BOOL bToBeDeleted = FALSE; - - StringCbPrintfW (wszRegPath, sizeof (wszRegPath), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%s\\DefaultLabel", driveStr); - - if (bSetValue) - lStatus = RegCreateKeyExW (HKEY_CURRENT_USER, wszRegPath, NULL, NULL, 0, - KEY_READ | KEY_WRITE | KEY_SET_VALUE, NULL, &hKey, NULL); - else - lStatus = RegOpenKeyExW (HKEY_CURRENT_USER, wszRegPath, 0, KEY_READ | KEY_WRITE | KEY_SET_VALUE, &hKey); - if (ERROR_SUCCESS == lStatus) - { - if (bSetValue) - lStatus = RegSetValueExW (hKey, NULL, NULL, REG_SZ, (LPCBYTE) effectiveLabel, cbLabelLen); - else - { - wchar_t storedLabel[34] = {0}; - DWORD cbStoredLen = sizeof (storedLabel) - 1, dwType; - lStatus = RegQueryValueExW (hKey, NULL, NULL, &dwType, (LPBYTE) storedLabel, &cbStoredLen); - if ((ERROR_SUCCESS == lStatus) && (REG_SZ == dwType) && (0 == wcscmp(storedLabel, effectiveLabel))) - { - // same label stored. mark key for deletion - bToBeDeleted = TRUE; - } - } - RegCloseKey (hKey); - } - - if (bToBeDeleted) - { - StringCbPrintfW (wszRegPath, sizeof (wszRegPath), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%s", driveStr); - lStatus = RegOpenKeyExW (HKEY_CURRENT_USER, wszRegPath, 0, KEY_READ | KEY_WRITE | KEY_SET_VALUE, &hKey); - if (ERROR_SUCCESS == lStatus) - { - lStatus = RegDeleteKeyW (hKey, L"DefaultLabel"); - RegCloseKey (hKey); - } - - // delete drive letter of nothing else is present under it - RegDeleteKeyW (HKEY_CURRENT_USER, wszRegPath); - - } - - return (ERROR_SUCCESS == lStatus)? TRUE : FALSE; -} - -wstring GetUserFriendlyVersionString (int version) -{ - wchar_t szTmp [64]; - StringCbPrintfW (szTmp, sizeof(szTmp), L"%x", version); - - wstring versionString (szTmp); - - versionString.insert (version > 0xfff ? 2 : 1,L"."); - - if (versionString[versionString.length()-1] == L'0') - versionString.erase (versionString.length()-1, 1); - - 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 bRet = true; - if (c >= L'0' && c <= L'9') - b = (byte) (c - L'0'); - else if (c >= L'a' && c <= L'z') - b = (byte) (c - L'a' + 10); - else if (c >= L'A' && c <= L'Z') - b = (byte) (c - L'A' + 10); - else - bRet = false; - - return bRet; -} - -bool HexWideStringToArray (const wchar_t* hexStr, std::vector& arr) -{ - byte 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; - - if (b == NULL || serNo != LocalizationSerialNo) - { - serNo = LocalizationSerialNo; - kb = GetString ("KB"); - mb = GetString ("MB"); - gb = GetString ("GB"); - tb = GetString ("TB"); - pb = GetString ("PB"); - b = GetString ("BYTE"); - } - - if (size > 1024I64*1024*1024*1024*1024*99) - StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024/1024/1024/1024/1024, pb); - else if (size > 1024I64*1024*1024*1024*1024) - StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024/1024/1024), pb); - else if (size > 1024I64*1024*1024*1024*99) - StringCbPrintfW (str, cbStr, L"%I64d %s",size/1024/1024/1024/1024, tb); - else if (size > 1024I64*1024*1024*1024) - StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024/1024), tb); - else if (size > 1024I64*1024*1024*99) - StringCbPrintfW (str, cbStr, L"%I64d %s",size/1024/1024/1024, gb); - else if (size > 1024I64*1024*1024) - StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024), gb); - else if (size > 1024I64*1024*99) - StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024/1024, mb); - else if (size > 1024I64*1024) - StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024), mb); - else if (size >= 1024I64) - StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024, kb); - else - StringCbPrintfW (str, cbStr, L"%I64d %s", size, b); -} - -#ifndef SETUP -void GetSpeedString (unsigned __int64 speed, wchar_t *str, size_t cbStr) -{ - static wchar_t *b, *kb, *mb, *gb, *tb, *pb; - static int serNo; - - if (b == NULL || serNo != LocalizationSerialNo) - { - serNo = LocalizationSerialNo; - kb = GetString ("KB_PER_SEC"); - mb = GetString ("MB_PER_SEC"); - gb = GetString ("GB_PER_SEC"); - tb = GetString ("TB_PER_SEC"); - pb = GetString ("PB_PER_SEC"); - b = GetString ("B_PER_SEC"); - } - - if (speed > 1024I64*1024*1024*1024*1024*99) - StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024/1024/1024/1024/1024, pb); - else if (speed > 1024I64*1024*1024*1024*1024) - StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024/1024), pb); - else if (speed > 1024I64*1024*1024*1024*99) - StringCbPrintfW (str, cbStr, L"%I64d %s",speed/1024/1024/1024/1024, tb); - else if (speed > 1024I64*1024*1024*1024) - StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024), tb); - else if (speed > 1024I64*1024*1024*99) - StringCbPrintfW (str, cbStr, L"%I64d %s",speed/1024/1024/1024, gb); - else if (speed > 1024I64*1024*1024) - StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024), gb); - else if (speed > 1024I64*1024*99) - StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024/1024, mb); - else if (speed > 1024I64*1024) - StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024), mb); - else if (speed > 1024I64) - StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024, kb); - else - StringCbPrintfW (str, cbStr, L"%I64d %s", speed, b); -} - -static void DisplayBenchmarkResults (HWND hwndDlg) -{ - wchar_t item1[100]={0}; - LVITEMW LvItem; - HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); - int ea, i; - BOOL unsorted = TRUE; - BENCHMARK_REC tmp_line; - - /* Sort the list */ - - switch (benchmarkSortMethod) - { - case BENCHMARK_SORT_BY_SPEED: - - while (unsorted) - { - unsorted = FALSE; - for (i = 0; i < benchmarkTotalItems - 1; i++) - { - if (benchmarkTable[i].meanBytesPerSec < benchmarkTable[i+1].meanBytesPerSec) - { - unsorted = TRUE; - memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC)); - memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC)); - memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC)); - } - } - } - break; - - case BENCHMARK_SORT_BY_NAME: - - while (unsorted) - { - unsorted = FALSE; - for (i = 0; i < benchmarkTotalItems - 1; i++) - { - if (benchmarkTable[i].id > benchmarkTable[i+1].id) - { - unsorted = TRUE; - memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC)); - memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC)); - memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC)); - } - } - } - break; - } - - /* Render the results */ - - SendMessage (hList,LVM_DELETEALLITEMS,0,(LPARAM)&LvItem); - - for (i = 0; i < benchmarkTotalItems; i++) - { - ea = benchmarkTable[i].id; - - memset (&LvItem,0,sizeof(LvItem)); - LvItem.mask = LVIF_TEXT; - LvItem.iItem = i; - LvItem.iSubItem = 0; - LvItem.pszText = (LPWSTR) benchmarkTable[i].name; - SendMessageW (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); - -#if PKCS5_BENCHMARKS - wcscpy (item1, L"-"); -#else - GetSpeedString ((unsigned __int64) (benchmarkLastBufferSize / ((float) benchmarkTable[i].encSpeed / benchmarkPerformanceFrequency.QuadPart)), item1, sizeof(item1)); -#endif - LvItem.iSubItem = 1; - LvItem.pszText = item1; - - SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); - -#if PKCS5_BENCHMARKS - wcscpy (item1, L"-"); -#else - GetSpeedString ((unsigned __int64) (benchmarkLastBufferSize / ((float) benchmarkTable[i].decSpeed / benchmarkPerformanceFrequency.QuadPart)), item1, sizeof(item1)); -#endif - LvItem.iSubItem = 2; - LvItem.pszText = item1; - - SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); - -#if PKCS5_BENCHMARKS - swprintf (item1, L"%d t", benchmarkTable[i].encSpeed); -#else - GetSpeedString (benchmarkTable[i].meanBytesPerSec, item1, sizeof(item1)); -#endif - LvItem.iSubItem = 3; - LvItem.pszText = item1; - - SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); - } - - SendMessageW(hList, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); - SendMessageW(hList, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); - SendMessageW(hList, LVM_SETCOLUMNWIDTH, 2, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); - SendMessageW(hList, LVM_SETCOLUMNWIDTH, 3, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); -} - -// specific implementation for support of benchmark operation in wait dialog mechanism - -typedef struct -{ - HWND hBenchDlg; - BOOL bStatus; -} BenchmarkThreadParam; - -static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg); - -void CALLBACK BenchmarkThreadProc(void* pArg, HWND hwndDlg) -{ - BenchmarkThreadParam* pThreadParam = (BenchmarkThreadParam*) pArg; - - pThreadParam->bStatus = PerformBenchmark (pThreadParam->hBenchDlg, hwndDlg); -} - -static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg) -{ - LARGE_INTEGER performanceCountStart, performanceCountEnd; - BYTE *lpTestBuffer; - PCRYPTO_INFO ci = NULL; - UINT64_STRUCT startDataUnitNo; - - startDataUnitNo.Value = 0; - -#if !(PKCS5_BENCHMARKS || HASH_FNC_BENCHMARKS) - ci = crypto_open (); - if (!ci) - return FALSE; -#endif - - if (QueryPerformanceFrequency (&benchmarkPerformanceFrequency) == 0) - { - if (ci) - crypto_close (ci); - MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); - return FALSE; - } - - lpTestBuffer = (BYTE *) malloc(benchmarkBufferSize - (benchmarkBufferSize % 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; - -#if !(PKCS5_BENCHMARKS || HASH_FNC_BENCHMARKS) - // CPU "warm up" (an attempt to prevent skewed results on systems where CPU frequency - // gradually changes depending on CPU load). - ci->ea = EAGetFirst(); - if (!EAInit (ci->ea, ci->master_keydata, ci->ks)) - { - ci->mode = FIRST_MODE_OF_OPERATION_ID; - if (EAInitMode (ci)) - { - int i; - - for (i = 0; i < 10; i++) - { - EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); - DecryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); - } - } - } -#endif - -#if HASH_FNC_BENCHMARKS - - /* Measures the speed at which each of the hash algorithms processes the message to produce - a single digest. - - The hash algorithm benchmarks are included here for development purposes only. Do not enable - them when building a public release (the benchmark GUI strings wouldn't make sense). */ - - { - BYTE *digest [MAX_DIGESTSIZE]; - WHIRLPOOL_CTX wctx; - RMD160_CTX rctx; - sha512_ctx s2ctx; - sha256_ctx s256ctx; - int hid; - - for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) - { - if (QueryPerformanceCounter (&performanceCountStart) == 0) - goto counter_error; - - 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; - - case RIPEMD160: - RMD160Init(&rctx); - RMD160Update(&rctx, lpTestBuffer, benchmarkBufferSize); - RMD160Final((unsigned char *) digest, &rctx); - break; - - case WHIRLPOOL: - WHIRLPOOL_init (&wctx); - WHIRLPOOL_add (lpTestBuffer, benchmarkBufferSize * 8, &wctx); - WHIRLPOOL_finalize (&wctx, (unsigned char *) digest); - break; - } - - 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)) + (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].decSpeed / benchmarkPerformanceFrequency.QuadPart))) / 2; - StringCbPrintfA (benchmarkTable[benchmarkTotalItems].name, sizeof(benchmarkTable[benchmarkTotalItems].name),"%s", HashGetName(hid)); - - benchmarkTotalItems++; - } - } - -#elif PKCS5_BENCHMARKS // #if HASH_FNC_BENCHMARKS - - /* Measures the time that it takes for the PKCS-5 routine to derive a header key using - each of the implemented PRF algorithms. - - The PKCS-5 benchmarks are included here for development purposes only. Do not enable - them when building a public release (the benchmark GUI strings wouldn't make sense). */ - { - 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 (QueryPerformanceCounter (&performanceCountStart) == 0) - goto counter_error; - - for (i = 1; i <= 5; 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, 0, FALSE, FALSE), 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, 0, FALSE, FALSE), dk, MASTER_KEYDATA_SIZE); - break; - - case RIPEMD160: - /* PKCS-5 test with HMAC-RIPEMD-160 used as the PRF */ - derive_key_ripemd160 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, 0, FALSE, FALSE), 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, 0, FALSE, FALSE), dk, MASTER_KEYDATA_SIZE); - break; - } - } - - if (QueryPerformanceCounter (&performanceCountEnd) == 0) - goto counter_error; - - benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; - benchmarkTable[benchmarkTotalItems].id = thid; - StringCbPrintfW (benchmarkTable[benchmarkTotalItems].name, sizeof(benchmarkTable[benchmarkTable[benchmarkTotalItems].name),L"%s", get_pkcs5_prf_name (thid)); - - benchmarkTotalItems++; - } - } - -#else // #elif PKCS5_BENCHMARKS - - /* Encryption algorithm benchmarks */ - - for (ci->ea = EAGetFirst(); ci->ea != 0; ci->ea = EAGetNext(ci->ea)) - { - if (!EAIsFormatEnabled (ci->ea)) - continue; - - if (ERR_CIPHER_INIT_FAILURE == EAInit (ci->ea, ci->master_keydata, ci->ks)) - goto counter_error; - - ci->mode = FIRST_MODE_OF_OPERATION_ID; - if (!EAInitMode (ci)) - goto counter_error; - - if (QueryPerformanceCounter (&performanceCountStart) == 0) - goto counter_error; - - EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); - - if (QueryPerformanceCounter (&performanceCountEnd) == 0) - goto counter_error; - - benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; - - if (QueryPerformanceCounter (&performanceCountStart) == 0) - goto counter_error; - - DecryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); - - if (QueryPerformanceCounter (&performanceCountEnd) == 0) - goto counter_error; - - benchmarkTable[benchmarkTotalItems].decSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; - benchmarkTable[benchmarkTotalItems].id = ci->ea; - benchmarkTable[benchmarkTotalItems].meanBytesPerSec = ((unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart)) + (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].decSpeed / benchmarkPerformanceFrequency.QuadPart))) / 2; - EAGetName (benchmarkTable[benchmarkTotalItems].name, ci->ea, 1); - - benchmarkTotalItems++; - } - -#endif // #elif PKCS5_BENCHMARKS (#else) - - if (ci) - crypto_close (ci); - - VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); - - free(lpTestBuffer); - - benchmarkLastBufferSize = benchmarkBufferSize; - - DisplayBenchmarkResults(hBenchDlg); - - EnableWindow (GetDlgItem (hBenchDlg, IDC_PERFORM_BENCHMARK), TRUE); - EnableWindow (GetDlgItem (hBenchDlg, IDCLOSE), TRUE); - - NormalCursor (); - return TRUE; - -counter_error: - - if (ci) - crypto_close (ci); - - VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); - - free(lpTestBuffer); - - NormalCursor (); - - EnableWindow (GetDlgItem (hBenchDlg, IDC_PERFORM_BENCHMARK), TRUE); - EnableWindow (GetDlgItem (hBenchDlg, IDCLOSE), TRUE); - - MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); - return FALSE; -} - - -BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - LPARAM nIndex; - HWND hCboxSortMethod = GetDlgItem (hwndDlg, IDC_BENCHMARK_SORT_METHOD); - HWND hCboxBufferSize = GetDlgItem (hwndDlg, IDC_BENCHMARK_BUFFER_SIZE); - - switch (msg) - { - case WM_INITDIALOG: - { - LVCOLUMNW LvCol; - wchar_t s[128]; - HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); - - LocalizeDialog (hwndDlg, "IDD_BENCHMARK_DLG"); - - benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; - benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED; - - SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, - LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP - ); - - memset (&LvCol,0,sizeof(LvCol)); - LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; - LvCol.pszText = GetString ("ALGORITHM"); - LvCol.cx = CompensateXDPI (114); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("ENCRYPTION"); - LvCol.cx = CompensateXDPI (80); - LvCol.fmt = LVCFMT_RIGHT; - SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("DECRYPTION"); - LvCol.cx = CompensateXDPI (80); - LvCol.fmt = LVCFMT_RIGHT; - SendMessageW (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); - - LvCol.pszText = GetString ("MEAN"); - LvCol.cx = CompensateXDPI (80); - LvCol.fmt = LVCFMT_RIGHT; - SendMessageW (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol); - - /* Combo boxes */ - - // Sort method - - SendMessage (hCboxSortMethod, CB_RESETCONTENT, 0, 0); - - nIndex = SendMessageW (hCboxSortMethod, CB_ADDSTRING, 0, (LPARAM) GetString ("ALPHABETICAL_CATEGORIZED")); - SendMessage (hCboxSortMethod, CB_SETITEMDATA, nIndex, (LPARAM) 0); - - nIndex = SendMessageW (hCboxSortMethod, CB_ADDSTRING, 0, (LPARAM) GetString ("MEAN_SPEED")); - SendMessage (hCboxSortMethod, CB_SETITEMDATA, nIndex, (LPARAM) 0); - - SendMessage (hCboxSortMethod, CB_SETCURSEL, 1, 0); // Default sort method - - // Buffer size - - SendMessage (hCboxBufferSize, CB_RESETCONTENT, 0, 0); - - StringCbPrintfW (s, sizeof(s), L"100 %s", GetString ("KB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 100 * BYTES_PER_KB); - - StringCbPrintfW (s, sizeof(s), L"500 %s", GetString ("KB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 500 * BYTES_PER_KB); - - StringCbPrintfW (s, sizeof(s), L"1 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 1 * BYTES_PER_MB); - - StringCbPrintfW (s, sizeof(s), L"5 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 5 * BYTES_PER_MB); - - StringCbPrintfW (s, sizeof(s), L"10 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 10 * BYTES_PER_MB); - - StringCbPrintfW (s, sizeof(s), L"50 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 50 * BYTES_PER_MB); - - StringCbPrintfW (s, sizeof(s), L"100 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 100 * BYTES_PER_MB); - - StringCbPrintfW (s, sizeof(s), L"200 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 200 * BYTES_PER_MB); - - StringCbPrintfW (s, sizeof(s), L"500 %s", GetString ("MB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 500 * BYTES_PER_MB); - - StringCbPrintfW (s, sizeof(s), L"1 %s", GetString ("GB")); - nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); - SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 1 * BYTES_PER_GB); - - SendMessage (hCboxBufferSize, CB_SETCURSEL, 5, 0); // Default buffer size - - - uint32 driverConfig = ReadDriverConfigurationFlags(); - - SetDlgItemTextW (hwndDlg, IDC_HW_AES, (wstring (L" ") + (GetString (is_aes_hw_cpu_supported() ? ((driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION) ? "UISTR_DISABLED" : "UISTR_YES") : "NOT_APPLICABLE_OR_NOT_AVAILABLE"))).c_str()); - - ToHyperlink (hwndDlg, IDC_HW_AES_LABEL_LINK); - - if (is_aes_hw_cpu_supported() && (driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION)) - { - Warning ("DISABLED_HW_AES_AFFECTS_PERFORMANCE", hwndDlg); - } - - SYSTEM_INFO sysInfo; - GetSystemInfo (&sysInfo); - - size_t nbrThreads = GetEncryptionThreadCount(); - - wchar_t nbrThreadsStr [300]; - if (sysInfo.dwNumberOfProcessors < 2) - { - StringCbCopyW (nbrThreadsStr, sizeof(nbrThreadsStr), GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE")); - } - else if (nbrThreads < 2) - { - StringCbCopyW (nbrThreadsStr, sizeof(nbrThreadsStr), GetString ("UISTR_DISABLED")); - } - else - { - StringCbPrintfW (nbrThreadsStr, sizeof(nbrThreadsStr), GetString ("NUMBER_OF_THREADS"), nbrThreads); - } - - SetDlgItemTextW (hwndDlg, IDC_PARALLELIZATION, (wstring (L" ") + nbrThreadsStr).c_str()); - - ToHyperlink (hwndDlg, IDC_PARALLELIZATION_LABEL_LINK); - - if (nbrThreads < min (sysInfo.dwNumberOfProcessors, GetMaxEncryptionThreadCount()) - && sysInfo.dwNumberOfProcessors > 1) - { - Warning ("LIMITED_THREAD_COUNT_AFFECTS_PERFORMANCE", hwndDlg); - } - - return 1; - } - break; - - case WM_COMMAND: - - switch (lw) - { - case IDC_BENCHMARK_SORT_METHOD: - - nIndex = SendMessage (hCboxSortMethod, CB_GETCURSEL, 0, 0); - if (nIndex != benchmarkSortMethod) - { - benchmarkSortMethod = (int) nIndex; - DisplayBenchmarkResults (hwndDlg); - } - return 1; - - case IDC_PERFORM_BENCHMARK: - - nIndex = SendMessage (hCboxBufferSize, CB_GETCURSEL, 0, 0); - benchmarkBufferSize = (int) SendMessage (hCboxBufferSize, CB_GETITEMDATA, nIndex, 0); - - BenchmarkThreadParam threadParam; - threadParam.hBenchDlg = hwndDlg; - threadParam.bStatus = FALSE; - - WaitCursor (); - - ShowWaitDialog (hwndDlg, TRUE, BenchmarkThreadProc, &threadParam); - - NormalCursor (); - - if (threadParam.bStatus == FALSE) - { - EndDialog (hwndDlg, IDCLOSE); - } - return 1; - - case IDC_HW_AES_LABEL_LINK: - - Applink ("hwacceleration", TRUE, ""); - return 1; - - case IDC_PARALLELIZATION_LABEL_LINK: - - Applink ("parallelization", TRUE, ""); - return 1; - - case IDCLOSE: - case IDCANCEL: - - EndDialog (hwndDlg, IDCLOSE); - return 1; - } - return 0; - - break; - - case WM_CLOSE: - EndDialog (hwndDlg, IDCLOSE); - return 1; - - break; - - } - return 0; -} - - -static BOOL CALLBACK RandomPoolEnrichementDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - static unsigned char randPool [RNG_POOL_SIZE]; - static unsigned char lastRandPool [RNG_POOL_SIZE]; - static unsigned char maskRandPool [RNG_POOL_SIZE]; - static BOOL bUseMask = FALSE; - static DWORD mouseEntropyGathered = 0xFFFFFFFF; - static DWORD mouseEventsInitialCount = 0; - /* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */ - static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8; - static HWND hEntropyBar = NULL; - static wchar_t outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; - static BOOL bDisplayPoolContents = FALSE; - static BOOL bRandPoolDispAscii = FALSE; - int hash_algo = RandGetHashFunction(); - int hid; - - switch (msg) - { - case WM_INITDIALOG: - { - HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); - HCRYPTPROV hRngProv = NULL; - - VirtualLock (randPool, sizeof(randPool)); - VirtualLock (lastRandPool, sizeof(lastRandPool)); - VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); - VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); - VirtualLock (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); - VirtualLock (maskRandPool, sizeof(maskRandPool)); - - mouseEntropyGathered = 0xFFFFFFFF; - mouseEventsInitialCount = 0; - bUseMask = FALSE; - if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) - { - if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool)) - bUseMask = TRUE; - CryptReleaseContext (hRngProv, 0); - } - - LocalizeDialog (hwndDlg, "IDD_RANDOM_POOL_ENRICHMENT"); - - SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); - for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) - { - if (!HashIsDeprecated (hid)) - AddComboPair (hComboBox, HashGetName(hid), hid); - } - SelectAlgo (hComboBox, &hash_algo); - - SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents); - - SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); - SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); - - 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); - 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 */ - tmpByte = (randPool[row * RANDPOOL_DISPLAY_COLUMNS + col] - - lastRandPool[row * RANDPOOL_DISPLAY_COLUMNS + col]) ^ maskRandPool [row * RANDPOOL_DISPLAY_COLUMNS + col]; - tmp[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*'); - tmp[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*'); - tmp[2] = L' '; - tmp[3] = 0; - } - else - { - StringCbCopyW (tmp, sizeof(tmp), L"** "); - } - - StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), tmp); - } - StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), L"\n"); - } - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); - - memcpy (lastRandPool, randPool, sizeof(lastRandPool)); - } - return 1; - } - - case WM_COMMAND: - if (lw == IDC_CONTINUE) - lw = IDOK; - - if (lw == IDOK || lw == IDCLOSE || lw == IDCANCEL) - { - 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; - } - - return 0; - - case WM_CLOSE: - { - wchar_t tmp[RNG_POOL_SIZE+1]; -exit: - KillTimer (hwndDlg, 0xfd); - - burn (randPool, sizeof(randPool)); - burn (lastRandPool, sizeof(lastRandPool)); - burn (outputDispBuffer, sizeof(outputDispBuffer)); - burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); - burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); - burn (maskRandPool, sizeof(maskRandPool)); - - // Attempt to wipe the pool contents in the GUI text area - wmemset (tmp, L' ', RNG_POOL_SIZE); - tmp [RNG_POOL_SIZE] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); - - if (msg == WM_COMMAND && lw == IDOK) - EndDialog (hwndDlg, IDOK); - else - EndDialog (hwndDlg, IDCLOSE); - - return 1; - } - } - return 0; -} - -/* Randinit is always called before UserEnrichRandomPool, so we don't need - * the extra Randinit call here since it will always succeed but we keep it - * for clarity purposes - */ -void UserEnrichRandomPool (HWND hwndDlg) -{ - if ((0 == Randinit()) && !IsRandomPoolEnrichedByUser()) - { - INT_PTR result = DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_RANDOM_POOL_ENRICHMENT), hwndDlg ? hwndDlg : MainDlg, (DLGPROC) RandomPoolEnrichementDlgProc, (LPARAM) 0); - SetRandomPoolEnrichedByUserStatus (result == IDOK); - } -} - - -/* Except in response to the WM_INITDIALOG message, the dialog box procedure - should return nonzero if it processes the message, and zero if it does - not. - see DialogProc */ -BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - static unsigned char randPool [RNG_POOL_SIZE]; - static unsigned char lastRandPool [RNG_POOL_SIZE]; - static unsigned char maskRandPool [RNG_POOL_SIZE]; - static BOOL bUseMask = FALSE; - static DWORD mouseEntropyGathered = 0xFFFFFFFF; - static DWORD mouseEventsInitialCount = 0; - /* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */ - static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8; - static HWND hEntropyBar = NULL; - static wchar_t outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; - static BOOL bDisplayPoolContents = FALSE; - static BOOL bRandPoolDispAscii = FALSE; - int hash_algo = RandGetHashFunction(); - int hid; - - switch (msg) - { - case WM_INITDIALOG: - { - HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); - HCRYPTPROV hRngProv = NULL; - - VirtualLock (randPool, sizeof(randPool)); - VirtualLock (lastRandPool, sizeof(lastRandPool)); - VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); - VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); - VirtualLock (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); - VirtualLock (maskRandPool, sizeof(maskRandPool)); - - mouseEntropyGathered = 0xFFFFFFFF; - mouseEventsInitialCount = 0; - bUseMask = FALSE; - if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) - { - if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool)) - bUseMask = TRUE; - CryptReleaseContext (hRngProv, 0); - } - - LocalizeDialog (hwndDlg, "IDD_KEYFILE_GENERATOR"); - - SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); - for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) - { - if (!HashIsDeprecated (hid)) - AddComboPair (hComboBox, HashGetName(hid), hid); - } - SelectAlgo (hComboBox, &hash_algo); - - 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); - 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 */ - tmpByte = (randPool[row * RANDPOOL_DISPLAY_COLUMNS + col] - - lastRandPool[row * RANDPOOL_DISPLAY_COLUMNS + col]) ^ maskRandPool [row * RANDPOOL_DISPLAY_COLUMNS + col]; - tmp[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*'); - tmp[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*'); - tmp[2] = L' '; - tmp[3] = 0; - } - else - { - StringCbCopyW (tmp, sizeof(tmp), L"** "); - } - - StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), tmp); - } - StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), L"\n"); - } - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); - - memcpy (lastRandPool, randPool, sizeof(lastRandPool)); - } - return 1; - } - - case WM_COMMAND: - - if (lw == IDCLOSE || lw == IDCANCEL) - { - 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)); - } - - 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, keyfilesSize = 0, i; - 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))) - szNumber[0] = 0; - - keyfilesSize = wcstoul(szNumber, NULL, 0); - if (keyfilesSize < 64 || keyfilesSize > 1024*1024) - { - 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)) - return 1; - - if (szDirName[wcslen(szDirName) - 1] != L'\\' && szDirName[wcslen(szDirName) - 1] != L'/') - StringCbCat(szDirName, sizeof(szDirName), L"\\"); - - WaitCursor(); - - keyfile = (unsigned char*) TCalloc( bRandomSize? KEYFILE_MAX_READ_LEN : keyfilesSize ); - - 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 - StringCbCat(szFileName, sizeof(szFileName), szFileBaseName); - - // check if the file exists - if ((fhKeyfile = _wopen(szFileName, _O_RDONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) != -1) - { - WCHAR s[4*TC_MAX_PATH] = {0}; - - _close (fhKeyfile); - - StringCbPrintfW (s, sizeof(s), GetString ("KEYFILE_ALREADY_EXISTS"), szFileName); - status = AskWarnNoYesString (s, hwndDlg); - if (status == IDNO) - { - TCfree(keyfile); - NormalCursor(); - return 1; - } - } - - /* Conceive the file */ - if ((fhKeyfile = _wopen(szFileName, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) == -1) - { - TCfree(keyfile); - NormalCursor(); - handleWin32Error (hwndDlg, SRC_POS); - return 1; - } - - if (bRandomSize) - { - /* Generate a random size */ - if (!RandgetBytes (hwndDlg, (unsigned char*) &keyfilesSize, sizeof(keyfilesSize), FALSE)) - { - _close (fhKeyfile); - DeleteFile (szFileName); - TCfree(keyfile); - NormalCursor(); - return 1; - } - - /* since keyfilesSize < 1024 * 1024, we mask with 0x000FFFFF */ - keyfilesSize = (long) (((unsigned long) keyfilesSize) & 0x000FFFFF); - - keyfilesSize %= ((KEYFILE_MAX_READ_LEN - 64) + 1); - keyfilesSize += 64; - } - - /* Generate the keyfile */ - if (!RandgetBytesFull (hwndDlg, keyfile, keyfilesSize, TRUE, TRUE)) - { - _close (fhKeyfile); - DeleteFile (szFileName); - TCfree(keyfile); - NormalCursor(); - return 1; - } - - /* Write the keyfile */ - status = _write (fhKeyfile, keyfile, keyfilesSize); - burn (keyfile, keyfilesSize); - _close (fhKeyfile); - - if (status == -1) - { - TCfree(keyfile); - NormalCursor(); - handleWin32Error (hwndDlg, SRC_POS); - return 1; - } - } - - TCfree(keyfile); - NormalCursor(); - - Info("KEYFILE_CREATED", hwndDlg); - - return 1; - } - return 0; - - case WM_CLOSE: - { - wchar_t tmp[RNG_POOL_SIZE+1]; -exit: - WaitCursor(); - KillTimer (hwndDlg, 0xfd); - -#ifndef VOLFORMAT - RandStop (FALSE); -#endif - /* Cleanup */ - - burn (randPool, sizeof(randPool)); - burn (lastRandPool, sizeof(lastRandPool)); - burn (outputDispBuffer, sizeof(outputDispBuffer)); - burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); - burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); - burn (maskRandPool, sizeof(maskRandPool)); - - // Attempt to wipe the pool contents in the GUI text area - wmemset (tmp, L' ', RNG_POOL_SIZE); - tmp [RNG_POOL_SIZE] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); - - EndDialog (hwndDlg, IDCLOSE); - NormalCursor (); - return 1; - } - } - return 0; -} - - - -/* Except in response to the WM_INITDIALOG message, the dialog box procedure -should return nonzero if it processes the message, and zero if it does -not. - see DialogProc */ -BOOL CALLBACK -CipherTestDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static int idTestCipher = -1; /* Currently selected cipher for the test vector facility (none = -1). */ - static BOOL bXTSTestEnabled = FALSE; - - PCRYPTO_INFO ci; - WORD lw = LOWORD (wParam); - WORD hw = HIWORD (wParam); - - switch (uMsg) - { - case WM_INITDIALOG: - { - int ea; - wchar_t buf[100]; - - LocalizeDialog (hwndDlg, "IDD_CIPHER_TEST_DLG"); - - SendMessage(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), WM_SETFONT, (WPARAM)hBoldFont, MAKELPARAM(TRUE,0)); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY), EM_LIMITTEXT, 128,0); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT), EM_LIMITTEXT,64,0); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); - SendMessage(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), EM_LIMITTEXT,64,0); - SendMessage(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); - SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), EM_LIMITTEXT, 128,0); - SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); - SendMessage(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), EM_LIMITTEXT,32,0); - SendMessage(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); - SetCheckBox (hwndDlg, IDC_XTS_MODE_ENABLED, bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_SECONDARY_KEY), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_SECONDARY_KEY), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_BLOCK_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); - - if (idTestCipher == -1) - idTestCipher = (int) lParam; - - SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_RESETCONTENT, 0, 0); - for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) - { - if (EAGetCipherCount (ea) == 1 && EAIsFormatEnabled (ea)) - AddComboPair (GetDlgItem (hwndDlg, IDC_CIPHER), EAGetName (buf, ea, 1), EAGetFirstCipher (ea)); - } - - ResetCipherTest(hwndDlg, idTestCipher); - - SelectAlgo (GetDlgItem (hwndDlg, IDC_CIPHER), &idTestCipher); - - return 1; - } - - case WM_COMMAND: - - if (hw == CBN_SELCHANGE && lw == IDC_CIPHER) - { - idTestCipher = (int) SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_GETCURSEL, 0, 0), 0); - ResetCipherTest(hwndDlg, idTestCipher); - SendMessage (hwndDlg, WM_INITDIALOG, 0, 0); - return 1; - } - - if (hw == CBN_SELCHANGE && lw == IDC_KEY_SIZE) - { - // NOP - return 1; - } - - if (lw == IDC_RESET) - { - ResetCipherTest(hwndDlg, idTestCipher); - - return 1; - } - - if (lw == IDC_AUTO) - { - WaitCursor (); - if (!AutoTestAlgorithms()) - { - ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL); - SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_FAILED")); - } - else - { - ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL); - SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_PASSED")); - ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_SHOWNORMAL); - } - NormalCursor (); - - return 1; - - } - - if (lw == IDC_XTS_MODE_ENABLED) - { - bXTSTestEnabled = GetCheckBox (hwndDlg, IDC_XTS_MODE_ENABLED); - EnableWindow (GetDlgItem (hwndDlg, IDC_SECONDARY_KEY), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_SECONDARY_KEY), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_BLOCK_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); - EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); - if (bXTSTestEnabled) - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, 0,0); - } - - if (lw == IDOK || lw == IDC_ENCRYPT || lw == IDC_DECRYPT) - { - char key[128+1], inputtext[128+1], secondaryKey[64+1], dataUnitNo[16+1]; - wchar_t szTmp[128+1]; - int ks, pt, n, tlen, blockNo = 0; - BOOL bEncrypt; - - ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_HIDE); - - ks = (int) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_GETCURSEL, 0,0); - ks = (int) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_GETITEMDATA, ks,0); - pt = (int) SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_GETITEMDATA, 0,0); - - bEncrypt = lw == IDC_ENCRYPT; - - memset(key,0,sizeof(key)); - memset(szTmp,0,sizeof(szTmp)); - n = GetWindowText(GetDlgItem(hwndDlg, IDC_KEY), szTmp, ARRAYSIZE(szTmp)); - if (n != ks * 2) - { - Warning ("TEST_KEY_SIZE", hwndDlg); - return 1; - } - - for (n = 0; n < ks; n ++) - { - wchar_t szTmp2[3], *ptr; - long x; - - szTmp2[2] = 0; - szTmp2[0] = szTmp[n * 2]; - szTmp2[1] = szTmp[n * 2 + 1]; - - x = wcstol(szTmp2, &ptr, 16); - - key[n] = (char) x; - } - - memset(inputtext, 0, sizeof(inputtext)); - memset(secondaryKey, 0, sizeof(secondaryKey)); - memset(dataUnitNo, 0, sizeof(dataUnitNo)); - memset(szTmp, 0, sizeof(szTmp)); - - if (bEncrypt) - { - n = GetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), szTmp, ARRAYSIZE(szTmp)); - } - else - { - n = GetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), szTmp, ARRAYSIZE(szTmp)); - } - - if (n != pt * 2) - { - if (bEncrypt) - { - Warning ("TEST_PLAINTEXT_SIZE", hwndDlg); - return 1; - } - else - { - Warning ("TEST_CIPHERTEXT_SIZE", hwndDlg); - return 1; - } - } - - for (n = 0; n < pt; n ++) - { - wchar_t szTmp2[3], *ptr; - long x; - - szTmp2[2] = 0; - szTmp2[0] = szTmp[n * 2]; - szTmp2[1] = szTmp[n * 2 + 1]; - - x = wcstol(szTmp2, &ptr, 16); - - inputtext[n] = (char) x; - } - - // XTS - if (bXTSTestEnabled) - { - // Secondary key - - if (GetWindowText(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), szTmp, ARRAYSIZE(szTmp)) != 64) - { - Warning ("TEST_INCORRECT_SECONDARY_KEY_SIZE", hwndDlg); - return 1; - } - - for (n = 0; n < 64; n ++) - { - wchar_t szTmp2[3], *ptr; - long x; - - szTmp2[2] = 0; - szTmp2[0] = szTmp[n * 2]; - szTmp2[1] = szTmp[n * 2 + 1]; - - x = wcstol(szTmp2, &ptr, 16); - - secondaryKey[n] = (char) x; - } - - // Data unit number - - tlen = GetWindowText(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), szTmp, ARRAYSIZE(szTmp)); - - if (tlen > 16 || tlen < 1) - { - Warning ("TEST_INCORRECT_TEST_DATA_UNIT_SIZE", hwndDlg); - return 1; - } - - LeftPadString (szTmp, tlen, 16, L'0'); - - for (n = 0; n < 16; n ++) - { - wchar_t szTmp2[3], *ptr; - long x; - - szTmp2[2] = 0; - szTmp2[0] = szTmp[n * 2]; - szTmp2[1] = szTmp[n * 2 + 1]; - - x = wcstol(szTmp2, &ptr, 16); - - dataUnitNo[n] = (char) x; - } - - // Block number - - blockNo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_GETCURSEL, 0, 0), 0); - } // if (bXTSTestEnabled) - - - /* Perform the actual tests */ - - if (ks != CB_ERR && pt != CB_ERR) - { - char tmp[128]; - int tmpRetVal; - - /* Copy the plain/ciphertext */ - memcpy(tmp,inputtext, pt); - - if (bXTSTestEnabled) - { - UINT64_STRUCT structDataUnitNo; - - /* XTS mode */ - - ci = crypto_open (); - if (!ci) - return 1; - - ci->mode = XTS; - - for (ci->ea = EAGetFirst (); ci->ea != 0 ; ci->ea = EAGetNext (ci->ea)) - if (EAGetCipherCount (ci->ea) == 1 && EAGetFirstCipher (ci->ea) == idTestCipher) - break; - - if ((tmpRetVal = EAInit (ci->ea, (unsigned char *) key, ci->ks)) != ERR_SUCCESS) - { - handleError (hwndDlg, tmpRetVal, SRC_POS); - crypto_close (ci); - return 1; - } - - memcpy (&ci->k2, secondaryKey, sizeof (secondaryKey)); - if (!EAInitMode (ci)) - { - crypto_close (ci); - return 1; - } - - structDataUnitNo.Value = BE64(((unsigned __int64 *)dataUnitNo)[0]); - - if (bEncrypt) - EncryptBufferXTS ((unsigned char *) tmp, pt, &structDataUnitNo, blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, idTestCipher); - else - DecryptBufferXTS ((unsigned char *) tmp, pt, &structDataUnitNo, blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, idTestCipher); - - crypto_close (ci); - } - else - { - - CipherInit2(idTestCipher, key, ks_tmp, ks); - - if (bEncrypt) - { - EncipherBlock(idTestCipher, tmp, ks_tmp); - } - else - { - DecipherBlock(idTestCipher, tmp, ks_tmp); - } - - } - *szTmp = 0; - - for (n = 0; n < pt; n ++) - { - wchar_t szTmp2[3]; - StringCbPrintfW(szTmp2, sizeof(szTmp2), L"%02x", (int)((unsigned char)tmp[n])); - StringCbCatW(szTmp, sizeof(szTmp), szTmp2); - } - - if (bEncrypt) - SetWindowText(GetDlgItem(hwndDlg,IDC_CIPHERTEXT), szTmp); - else - SetWindowText(GetDlgItem(hwndDlg,IDC_PLAINTEXT), szTmp); - } - - return 1; - } - - if (lw == IDCLOSE || lw == IDCANCEL) - { - idTestCipher = -1; - EndDialog (hwndDlg, 0); - return 1; - } - break; - - case WM_CLOSE: - idTestCipher = -1; - EndDialog (hwndDlg, 0); - return 1; - } - - return 0; -} - -void -ResetCipherTest(HWND hwndDlg, int idTestCipher) -{ - int ndx; - - ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_HIDE); - - EnableWindow(GetDlgItem(hwndDlg,IDC_KEY_SIZE), FALSE); - - /* Setup the keysize and plaintext sizes for the selected cipher */ - - SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_RESETCONTENT, 0,0); - SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_RESETCONTENT, 0,0); - SendMessage (GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_RESETCONTENT, 0,0); - - ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_ADDSTRING, 0,(LPARAM) L"64"); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 8); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETCURSEL, ndx,0); - - for (ndx = 0; ndx < BLOCKS_PER_XTS_DATA_UNIT; ndx++) - { - wchar_t tmpStr [16]; - - StringCbPrintfW (tmpStr, sizeof(tmpStr), L"%d", ndx); - - ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_ADDSTRING, 0,(LPARAM) tmpStr); - SendMessage(GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_SETITEMDATA, ndx,(LPARAM) ndx); - } - - SendMessage(GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_SETCURSEL, 0, 0); - - SetWindowText(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), L"0000000000000000000000000000000000000000000000000000000000000000"); - SetWindowText(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), L"0"); - - SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), L"0000000000000000"); - SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), L"0000000000000000"); - - if (idTestCipher == AES || idTestCipher == SERPENT || idTestCipher == TWOFISH) - { - ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) L"256"); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 32); - SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, ndx,0); - - SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_RESETCONTENT, 0,0); - ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_ADDSTRING, 0,(LPARAM) L"128"); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 16); - SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETCURSEL, ndx,0); - - SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), L"0000000000000000000000000000000000000000000000000000000000000000"); - SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), L"00000000000000000000000000000000"); - SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), L"00000000000000000000000000000000"); - } -} - -#endif // #ifndef SETUP - - -BOOL CALLBACK MultiChoiceDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - int nChoiceIDs [MAX_MULTI_CHOICES+1] = { IDC_MULTI_CHOICE_MSG, IDC_CHOICE1, IDC_CHOICE2, IDC_CHOICE3, - IDC_CHOICE4, IDC_CHOICE5, IDC_CHOICE6, IDC_CHOICE7, IDC_CHOICE8, IDC_CHOICE9, IDC_CHOICE10 }; - int nBaseButtonWidth = 0; - int nBaseButtonHeight = 0; - int nActiveChoices = -1; - int nStr = 0; - int vertSubOffset, horizSubOffset, vertMsgHeightOffset; - int vertOffset = 0; - int nLongestButtonCaptionWidth = 6; - int nLongestButtonCaptionCharLen = 1; - int nTextGfxLineHeight = 0; - int nMainTextLenInChars = 0; - int newLineSeqCount = 0; - RECT rec, wrec, wtrec, trec; - BOOL bResolve; - - WORD lw = LOWORD (wParam); - - switch (uMsg) - { - case WM_INITDIALOG: - { - char **pStr = (char **) ((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->strings; - char **pStrOrig = pStr; - wchar_t **pwStr = (wchar_t **) ((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->strings; - wchar_t **pwStrOrig = pwStr; - - LocalizeDialog (hwndDlg, NULL); - - SetWindowPos (hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - SetWindowPos (hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - - bResolve = (*pStr == NULL); - - // Style - if (((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->bold) - { - SendMessage (GetDlgItem (hwndDlg, IDC_MULTI_CHOICE_MSG), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); - } - - // Process the strings - pStr++; - pwStr++; - - do - { - if (*pStr != 0) - { - SetWindowTextW (GetDlgItem(hwndDlg, nChoiceIDs[nStr]), bResolve ? GetString(*pStr) : *pwStr); - - if (nStr > 0) - { - nLongestButtonCaptionWidth = max ( - GetTextGfxWidth (GetDlgItem(hwndDlg, IDC_CHOICE1), - bResolve ? GetString(*pStr) : *pwStr, - hUserFont), - nLongestButtonCaptionWidth); - - nLongestButtonCaptionCharLen = max (nLongestButtonCaptionCharLen, - (int) wcslen ((const wchar_t *) (bResolve ? GetString(*pStr) : *pwStr))); - } - - nActiveChoices++; - pStr++; - pwStr++; - } - else - { - ShowWindow(GetDlgItem(hwndDlg, nChoiceIDs[nStr]), SW_HIDE); - } - nStr++; - - } while (nStr < MAX_MULTI_CHOICES+1); - - // Length of main message in characters (not bytes) - nMainTextLenInChars = (int) wcslen ((const wchar_t *) (bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1))); - - if (nMainTextLenInChars > 200 - && nMainTextLenInChars / nLongestButtonCaptionCharLen >= 10) - { - // As the main text is longer than 200 characters, we will "pad" the widest button caption with - // spaces (if it is not wide enough) so as to increase the width of the whole dialog window. - // Otherwise, it would look too tall (dialog boxes look better when they are more wide than tall). - nLongestButtonCaptionWidth = CompensateXDPI (max ( - nLongestButtonCaptionWidth, - min (350, nMainTextLenInChars))); - } - - // Get the window coords - GetWindowRect(hwndDlg, &wrec); - - // Get the base button size - GetClientRect(GetDlgItem(hwndDlg, IDC_CHOICE1), &rec); - nBaseButtonWidth = rec.right + 2; - nBaseButtonHeight = rec.bottom + 2; - - // Increase in width based on the gfx length of the widest button caption - horizSubOffset = min (CompensateXDPI (500), max (0, nLongestButtonCaptionWidth + CompensateXDPI (50) - nBaseButtonWidth)); - - // Vertical "title bar" offset - GetClientRect(hwndDlg, &wtrec); - vertOffset = wrec.bottom - wrec.top - wtrec.bottom - GetSystemMetrics(SM_CYFIXEDFRAME); - - // Height/width of the message text - GetClientRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &trec); - - // Determine the number of newlines contained in the message text - { - int64 offset = -1; - - do - { - offset = FindString ((char *) (bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1)), - (char *) L"\n", - nMainTextLenInChars * 2, - (int) wcslen (L"\n") * 2, - offset + 1); - - newLineSeqCount++; - - } while (offset != -1); - } - - nTextGfxLineHeight = GetTextGfxHeight (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), - bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1), - hUserFont); - - vertMsgHeightOffset = ((GetTextGfxWidth (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), - bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1), - hUserFont) / (trec.right + horizSubOffset) + 1) * nTextGfxLineHeight) - trec.bottom; - - vertMsgHeightOffset = min (CompensateYDPI (350), vertMsgHeightOffset + newLineSeqCount * nTextGfxLineHeight + (trec.bottom + vertMsgHeightOffset) / 10); // As reserve, we are adding 10% and the number of lines equal to the number of newlines in the message - - // Reduction in height according to the number of shown buttons - vertSubOffset = ((MAX_MULTI_CHOICES - nActiveChoices) * nBaseButtonHeight); - - if (horizSubOffset > 0 - || vertMsgHeightOffset > 0 - || vertOffset > 0) - { - // Resize/move each button if necessary - for (nStr = 1; nStr < MAX_MULTI_CHOICES+1; nStr++) - { - GetWindowRect(GetDlgItem(hwndDlg, nChoiceIDs[nStr]), &rec); - - MoveWindow (GetDlgItem(hwndDlg, nChoiceIDs[nStr]), - rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), - rec.top - wrec.top - vertOffset + vertMsgHeightOffset, - nBaseButtonWidth + horizSubOffset, - nBaseButtonHeight, - TRUE); - } - - // Resize/move the remaining GUI elements - GetWindowRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &rec); - GetClientRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &trec); - MoveWindow (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), - rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), - rec.top - wrec.top - vertOffset, - trec.right + 2 + horizSubOffset, - trec.bottom + 2 + vertMsgHeightOffset, - TRUE); - - GetWindowRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), &rec); - GetClientRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), &trec); - MoveWindow (GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), - rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), - rec.top - wrec.top - vertOffset, - trec.right + 2 + horizSubOffset, - trec.bottom + 2, - TRUE); - - GetWindowRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), &rec); - GetClientRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), &trec); - MoveWindow (GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), - rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), - rec.top - wrec.top - vertOffset + vertMsgHeightOffset, - trec.right + 2 + horizSubOffset, - trec.bottom + 2, - TRUE); - } - - // Resize the window according to number of shown buttons and the longest button caption - MoveWindow (hwndDlg, - wrec.left - horizSubOffset / 2, - wrec.top + vertSubOffset / 2 - vertMsgHeightOffset / 2, - wrec.right - wrec.left + horizSubOffset, - wrec.bottom - wrec.top - vertSubOffset + 1 + vertMsgHeightOffset, - TRUE); - - DisableCloseButton (hwndDlg); - - return 1; - } - - case WM_COMMAND: - - if (lw == IDCLOSE || lw == IDCANCEL) - { - EndDialog (hwndDlg, 0); - return 1; - } - - for (nStr = 1; nStr < MAX_MULTI_CHOICES+1; nStr++) - { - if (lw == nChoiceIDs[nStr]) - { - EndDialog (hwndDlg, nStr); - return 1; - } - } - break; - - case WM_CLOSE: - // This prevents the window from being closed by pressing Alt-F4 (the Close button is hidden). - // Note that the OS handles modal MessageBox() dialog windows the same way. - return 1; - } - - return 0; -} - - -BOOL CheckCapsLock (HWND hwnd, BOOL quiet) -{ - if ((GetKeyState(VK_CAPITAL) & 1) != 0) - { - if (!quiet) - { - MessageBoxW (hwnd, GetString ("CAPSLOCK_ON"), lpszTitle, MB_ICONEXCLAMATION); - } - return TRUE; - } - return FALSE; -} - - -// Checks whether the file extension is not used for executable files or similarly problematic, which often -// causes Windows and antivirus software to interfere with the container. -BOOL CheckFileExtension (wchar_t *fileName) -{ - int i = 0; - wchar_t *ext = wcsrchr (fileName, L'.'); - static wchar_t *problemFileExt[] = { - // These are protected by the Windows Resource Protection - L".asa", L".asp", L".aspx", L".ax", L".bas", L".bat", L".bin", L".cer", L".chm", L".clb", L".cmd", L".cnt", L".cnv", - L".com", L".cpl", L".cpx", L".crt", L".csh", L".dll", L".drv", L".dtd", L".exe", L".fxp", L".grp", L".h1s", L".hlp", - L".hta", L".ime", L".inf", L".ins", L".isp", L".its", L".js", L".jse", L".ksh", L".lnk", L".mad", L".maf", L".mag", - L".mam", L".man", L".maq", L".mar", L".mas", L".mat", L".mau", L".mav", L".maw", L".mda", L".mdb", L".mde", L".mdt", - L".mdw", L".mdz", L".msc", L".msi", L".msp", L".mst", L".mui", L".nls", L".ocx", L".ops", L".pal", L".pcd", L".pif", - L".prf", L".prg", L".pst", L".reg", L".scf", L".scr", L".sct", L".shb", L".shs", L".sys", L".tlb", L".tsp", L".url", - L".vb", L".vbe", L".vbs", L".vsmacros", L".vss", L".vst", L".vsw", L".ws", L".wsc", L".wsf", L".wsh", L".xsd", L".xsl", - // These additional file extensions are usually watched by antivirus programs - L".386", L".acm", L".ade", L".adp", L".ani", L".app", L".asd", L".asf", L".asx", L".awx", L".ax", L".boo", L".bz2", L".cdf", - L".class", L".dhtm", L".dhtml",L".dlo", L".emf", L".eml", L".flt", L".fot", L".gz", L".hlp", L".htm", L".html", L".ini", - L".j2k", L".jar", L".jff", L".jif", L".jmh", L".jng", L".jp2", L".jpe", L".jpeg", L".jpg", L".lsp", L".mod", L".nws", - L".obj", L".olb", L".osd", L".ov1", L".ov2", L".ov3", L".ovl", L".ovl", L".ovr", L".pdr", L".pgm", L".php", L".pkg", - L".pl", L".png", L".pot", L".pps", L".ppt", L".ps1", L".ps1xml", L".psc1", L".rar", L".rpl", L".rtf", L".sbf", L".script", L".sh", L".sha", L".shtm", - L".shtml", L".spl", L".swf", L".tar", L".tgz", L".tmp", L".ttf", L".vcs", L".vlm", L".vxd", L".vxo", L".wiz", L".wll", L".wmd", - L".wmf", L".wms", L".wmz", L".wpc", L".wsc", L".wsh", L".wwk", L".xhtm", L".xhtml", L".xl", L".xml", L".zip", L".7z", 0}; - - if (!ext) - return FALSE; - - while (problemFileExt[i]) - { - if (!_wcsicmp (ext, problemFileExt[i++])) - return TRUE; - } - - return FALSE; -} - -void CorrectFileName (wchar_t* fileName) -{ - /* replace '/' by '\' */ - size_t i, len = wcslen (fileName); - for (i = 0; i < len; i++) - { - if (fileName [i] == L'/') - fileName [i] = L'\\'; - } -} - -void IncreaseWrongPwdRetryCount (int count) -{ - WrongPwdRetryCounter += count; -} - - -void ResetWrongPwdRetryCount (void) -{ - WrongPwdRetryCounter = 0; -} - - -BOOL WrongPwdRetryCountOverLimit (void) -{ - return (WrongPwdRetryCounter > TC_TRY_HEADER_BAK_AFTER_NBR_WRONG_PWD_TRIES); -} - -DWORD GetUsedLogicalDrives (void) -{ - DWORD dwUsedDrives = GetLogicalDrives(); - if (!bShowDisconnectedNetworkDrives) - { - static DWORD g_dwLastMappedDrives = 0; - static time_t g_lastCallTime = 0; - - EnterCriticalSection (&csWNetCalls); - - finally_do ({ LeaveCriticalSection (&csWNetCalls); }); - - /* update values every 2 seconds to reduce CPU consumption */ - if ((time (NULL) - g_lastCallTime) > 2) - { - /* detect disconnected mapped network shares and removed - * their associated drives from the list - */ - WCHAR remotePath[512]; - WCHAR drive[3] = {L'A', L':', 0}; - DWORD dwLen, status; - g_dwLastMappedDrives = 0; - for (WCHAR i = 0; i <= MAX_MOUNTED_VOLUME_DRIVE_NUMBER; i++) - { - if ((dwUsedDrives & (1 << i)) == 0) - { - drive[0] = L'A' + i; - dwLen = ARRAYSIZE (remotePath); - status = WNetGetConnection (drive, remotePath, &dwLen); - if ((NO_ERROR == status) || (status == ERROR_CONNECTION_UNAVAIL)) - { - /* this is a mapped network share, mark it as used */ - g_dwLastMappedDrives |= (1 << i); - } - } - } - - g_lastCallTime = time (NULL); - } - - dwUsedDrives |= g_dwLastMappedDrives; - } - - return dwUsedDrives; -} - - -int GetFirstAvailableDrive () -{ - DWORD dwUsedDrives = GetUsedLogicalDrives(); - int i, drive; - - /* let A: and B: be used as last resort since they can introduce side effects */ - for (i = 2; i < 28; i++) - { - drive = (i < 26) ? i : (i - 26); - if (!(dwUsedDrives & 1 << drive)) - return i; - } - - return -1; -} - - -int GetLastAvailableDrive () -{ - DWORD dwUsedDrives = GetUsedLogicalDrives(); - int i; - - for (i = 25; i >= 0; i--) - { - if (!(dwUsedDrives & 1 << i)) - return i; - } - - return -1; -} - - -BOOL IsDriveAvailable (int driveNo) -{ - return (GetUsedLogicalDrives() & (1 << driveNo)) == 0; -} - - -BOOL IsDeviceMounted (wchar_t *deviceName) -{ - BOOL bResult = FALSE; - DWORD dwResult; - HANDLE dev = INVALID_HANDLE_VALUE; - - if ((dev = CreateFile (deviceName, - GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - 0, - NULL)) != INVALID_HANDLE_VALUE) - { - bResult = DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL); - CloseHandle (dev); - } - - return bResult; -} - - -int DriverUnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forced) -{ - UNMOUNT_STRUCT unmount; - DWORD dwResult; - VOLUME_PROPERTIES_STRUCT prop; - BOOL bResult; - WCHAR wszLabel[33] = {0}; - BOOL bDriverSetLabel = FALSE; - - memset (&prop, 0, sizeof(prop)); - prop.driveNo = nDosDriveNo; - - if ( DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &dwResult, NULL) - && prop.driveNo == nDosDriveNo - ) - { - memcpy (wszLabel, prop.wszLabel, sizeof (wszLabel)); - bDriverSetLabel = prop.bDriverSetLabel; - } - - unmount.nDosDriveNo = nDosDriveNo; - unmount.ignoreOpenFiles = forced; - - bResult = DeviceIoControl (hDriver, TC_IOCTL_DISMOUNT_VOLUME, &unmount, - sizeof (unmount), &unmount, sizeof (unmount), &dwResult, NULL); - - if (bResult == FALSE) - { - handleWin32Error (hwndDlg, SRC_POS); - return 1; - } - else if ((unmount.nReturnCode == ERR_SUCCESS) && bDriverSetLabel && wszLabel[0]) - UpdateDriveCustomLabel (nDosDriveNo, wszLabel, FALSE); - -#ifdef TCMOUNT - - if (unmount.nReturnCode == ERR_SUCCESS - && unmount.HiddenVolumeProtectionTriggered - && !VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo] - && !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. - 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; - - IgnoreWmDeviceChange = TRUE; - SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), SMTO_ABORTIFHUNG, timeOut, &dwResult); - - // Explorer prior Vista sometimes fails to register a new drive - if (CurrentOSMajor < 6 && message == DBT_DEVICEARRIVAL) - SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), SMTO_ABORTIFHUNG, 200, &dwResult); - - IgnoreWmDeviceChange = FALSE; -} - -BOOL GetPhysicalDriveAlignment(UINT nDriveNumber, STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR* pDesc) -{ - DWORD dwRet = NO_ERROR; - - if (!pDesc) - return FALSE; - - // Format physical drive path (may be '\\.\PhysicalDrive0', '\\.\PhysicalDrive1' and so on). - TCHAR strDrivePath[512]; - StringCbPrintf(strDrivePath, sizeof(strDrivePath), _T("\\\\.\\PhysicalDrive%u"), nDriveNumber); - - // Get a handle to physical drive - HANDLE hDevice = ::CreateFile(strDrivePath, 0, FILE_SHARE_READ, - NULL, OPEN_EXISTING, 0, NULL); - - if(INVALID_HANDLE_VALUE == hDevice) - return FALSE; - - // Set the input data structure - STORAGE_PROPERTY_QUERY storagePropertyQuery; - ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY)); - storagePropertyQuery.PropertyId = StorageAccessAlignmentProperty; - storagePropertyQuery.QueryType = PropertyStandardQuery; - - // Get the necessary output buffer size - DWORD dwBytesReturned = 0; - BOOL bRet = ::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, - &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), - pDesc, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), - &dwBytesReturned, NULL); - dwRet = ::GetLastError(); - ::CloseHandle(hDevice); - - if (!bRet) - { - SetLastError (dwRet); - return FALSE; - } - else - return TRUE; -} - -/************************************************************/ - -// implementation of the generic wait dialog mechanism - -static UINT g_wmWaitDlg = ::RegisterWindowMessage(L"VeraCryptWaitDlgMessage"); - -typedef struct -{ - HWND hwnd; - void* pArg; - WaitThreadProc callback; -} WaitThreadParam; - -static void _cdecl WaitThread (void* pParam) -{ - WaitThreadParam* pThreadParam = (WaitThreadParam*) pParam; - - pThreadParam->callback(pThreadParam->pArg, pThreadParam->hwnd); - - /* close the wait dialog */ - PostMessage (pThreadParam->hwnd, g_wmWaitDlg, 0, 0); -} - -BOOL CALLBACK WaitDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - WaitThreadParam* thParam = (WaitThreadParam*) lParam; - - // set the progress bar type to MARQUEE (indefinite progress) - HWND hProgress = GetDlgItem (hwndDlg, IDC_WAIT_PROGRESS_BAR); - if (hProgress) - { - SetWindowLongPtrW (hProgress, GWL_STYLE, PBS_MARQUEE | GetWindowLongPtrW (hProgress, GWL_STYLE)); - ::SendMessageW(hProgress, PBM_SETMARQUEE, (WPARAM) TRUE, (LPARAM) 0); - } - - thParam->hwnd = hwndDlg; - - // For now, we don't have system menu is the resources but we leave this code - // if it is enabled in the future - HMENU hSysMenu = GetSystemMenu(hwndDlg, FALSE); - if (hSysMenu) - { - //disable the X - EnableMenuItem(hSysMenu,SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); - - // set icons - HICON hIcon = (HICON)::LoadImage(hInst, MAKEINTRESOURCE(IDI_TRUECRYPT_ICON), IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR); - ::SendMessage(hwndDlg, WM_SETICON, TRUE, (LPARAM)hIcon); - HICON hIconSmall = (HICON)::LoadImage(hInst, MAKEINTRESOURCE(IDI_TRUECRYPT_ICON), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); - ::SendMessage(hwndDlg, WM_SETICON, FALSE, (LPARAM)hIconSmall); - } - - LocalizeDialog (hwndDlg, NULL); - _beginthread(WaitThread, 0, thParam); - return 0; - } - - case WM_COMMAND: - - if (lw == IDOK || lw == IDCANCEL) - return 1; - else - return 0; - - default: - if (msg == g_wmWaitDlg) - { - EndDialog (hwndDlg, IDOK); - return 1; - } - return 0; - } -} - - -void BringToForeground(HWND hWnd) -{ - if(!::IsWindow(hWnd)) return; - - DWORD lockTimeOut = 0; - HWND hCurrWnd = ::GetForegroundWindow(); - DWORD dwThisTID = ::GetCurrentThreadId(), - dwCurrTID = ::GetWindowThreadProcessId(hCurrWnd,0); - - if (hCurrWnd != hWnd) - { - if(dwThisTID != dwCurrTID) - { - ::AttachThreadInput(dwThisTID, dwCurrTID, TRUE); - - ::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT,0,&lockTimeOut,0); - ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,0,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); - - ::AllowSetForegroundWindow(ASFW_ANY); - } - - ::SetForegroundWindow(hWnd); - - if(dwThisTID != dwCurrTID) - { - ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,(PVOID)lockTimeOut,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); - ::AttachThreadInput(dwThisTID, dwCurrTID, FALSE); - } - } - -#ifdef TCMOUNT - if (hWnd == MainDlg) - { - SetFocus (hWnd); - ::SendMessage(hWnd, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hWnd, IDC_DRIVELIST), 1L); - } -#endif -} - -void ShowWaitDialog(HWND hwnd, BOOL bUseHwndAsParent, WaitThreadProc callback, void* pArg) -{ - HWND hParent = (hwnd && bUseHwndAsParent)? hwnd : GetDesktopWindow(); - BOOL bEffectiveHideWaitingDialog = bCmdHideWaitingDialogValid? bCmdHideWaitingDialog : bHideWaitingDialog; - WaitThreadParam threadParam; - threadParam.callback = callback; - threadParam.pArg = pArg; - - if (WaitDialogDisplaying || bEffectiveHideWaitingDialog) - { - if (!WaitDialogDisplaying) WaitCursor (); - callback (pArg, hwnd); - if (!WaitDialogDisplaying) NormalCursor (); - } - else - { - BOOL bIsForeground = FALSE; - WaitDialogDisplaying = TRUE; - if (hwnd) - { - if (GetForegroundWindow () == hwnd) - bIsForeground = TRUE; - EnableWindow (hwnd, FALSE); - } - else - EnableWindow (MainDlg, FALSE); - finally_do_arg2 (HWND, hwnd, BOOL, bIsForeground, { if (finally_arg) {EnableWindow(finally_arg, TRUE); if (finally_arg2) BringToForeground (finally_arg);} else EnableWindow (MainDlg, TRUE);}); - - DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_STATIC_MODAL_WAIT_DLG), hParent, - (DLGPROC) WaitDlgProc, (LPARAM) &threadParam); - - WaitDialogDisplaying = FALSE; - } -} - -/************************************************************************/ - -static BOOL PerformMountIoctl (MOUNT_STRUCT* pmount, LPDWORD pdwResult, BOOL useVolumeID, BYTE volumeID[VOLUME_ID_SIZE]) -{ - if (useVolumeID) - { - wstring devicePath = FindDeviceByVolumeID (volumeID); - if (devicePath == L"") - { - if (pdwResult) - *pdwResult = 0; - SetLastError (ERROR_PATH_NOT_FOUND); - return FALSE; - } - else - { - BOOL bDevice = FALSE; - CreateFullVolumePath (pmount->wszVolume, sizeof(pmount->wszVolume), devicePath.c_str(), &bDevice); - } - } - - return DeviceIoControl (hDriver, TC_IOCTL_MOUNT_VOLUME, pmount, - sizeof (MOUNT_STRUCT), pmount, sizeof (MOUNT_STRUCT), pdwResult, NULL); -} - -// specific definitions and implementation for support of mount operation -// in wait dialog mechanism - -typedef struct -{ - MOUNT_STRUCT* pmount; - BOOL useVolumeID; - BYTE volumeID[VOLUME_ID_SIZE]; - BOOL* pbResult; - DWORD* pdwResult; - DWORD dwLastError; -} MountThreadParam; - -void CALLBACK MountWaitThreadProc(void* pArg, HWND ) -{ - MountThreadParam* pThreadParam = (MountThreadParam*) pArg; - - *(pThreadParam->pbResult) = PerformMountIoctl (pThreadParam->pmount, pThreadParam->pdwResult, pThreadParam->useVolumeID, pThreadParam->volumeID); - - pThreadParam->dwLastError = GetLastError (); -} - -/************************************************************************/ - -// Use only cached passwords if password = NULL -// -// Returns: -// -1 = user aborted mount / error -// 0 = mount failed -// 1 = mount OK -// 2 = mount OK in shared mode -// -// Note that some code calling this relies on the content of the mountOptions struct -// to remain unmodified (don't remove the 'const' without proper revision). - -int MountVolume (HWND hwndDlg, - int driveNo, - wchar_t *volumePath, - Password *password, - int pkcs5, - int pim, - BOOL truecryptMode, - BOOL cachePassword, - BOOL cachePim, - BOOL sharedAccess, - const MountOptions* const mountOptions, - BOOL quiet, - BOOL bReportWrongPassword) -{ - MOUNT_STRUCT mount; - DWORD dwResult, dwLastError = ERROR_SUCCESS; - BOOL bResult, bDevice; - wchar_t root[MAX_PATH]; - int favoriteMountOnArrivalRetryCount = 0; - BOOL useVolumeID = FALSE; - BYTE volumeID[VOLUME_ID_SIZE] = {0}; - -#ifdef TCMOUNT - if (mountOptions->PartitionInInactiveSysEncScope) - { - if (!CheckSysEncMountWithoutPBA (hwndDlg, volumePath, quiet)) - return -1; - } -#endif - - if (IsMountedVolume (volumePath)) - { - if (!quiet) - Error ("VOL_ALREADY_MOUNTED", hwndDlg); - return -1; - } - - if (!IsDriveAvailable (driveNo)) - { - if (!quiet) - Error ("DRIVE_LETTER_UNAVAILABLE", hwndDlg); - - return -1; - } - - // If using cached passwords, check cache status first - if (password == NULL && IsPasswordCacheEmpty ()) - return 0; - - ZeroMemory (&mount, sizeof (mount)); - mount.bExclusiveAccess = sharedAccess ? FALSE : TRUE; - mount.SystemFavorite = MountVolumesAsSystemFavorite; - mount.UseBackupHeader = mountOptions->UseBackupHeader; - mount.RecoveryMode = mountOptions->RecoveryMode; - StringCbCopyW (mount.wszLabel, sizeof (mount.wszLabel), mountOptions->Label); - -retry: - mount.nDosDriveNo = driveNo; - mount.bCache = cachePassword; - mount.bCachePim = cachePim; - - mount.bPartitionInInactiveSysEncScope = FALSE; - - if (password != NULL) - mount.VolumePassword = *password; - else - mount.VolumePassword.Length = 0; - - if (!mountOptions->ReadOnly && mountOptions->ProtectHiddenVolume) - { - mount.ProtectedHidVolPassword = mountOptions->ProtectedHidVolPassword; - mount.bProtectHiddenVolume = TRUE; - mount.ProtectedHidVolPkcs5Prf = mountOptions->ProtectedHidVolPkcs5Prf; - mount.ProtectedHidVolPim = mountOptions->ProtectedHidVolPim; - } - else - mount.bProtectHiddenVolume = FALSE; - - mount.bMountReadOnly = mountOptions->ReadOnly; - mount.bMountRemovable = mountOptions->Removable; - mount.bPreserveTimestamp = mountOptions->PreserveTimestamp; - - mount.bMountManager = TRUE; - mount.pkcs5_prf = pkcs5; - mount.bTrueCryptMode = truecryptMode; - mount.VolumePim = pim; - - // Windows 2000 mount manager causes problems with remounted volumes - if (CurrentOSMajor == 5 && CurrentOSMinor == 0) - mount.bMountManager = FALSE; - - 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 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) - { - // 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') - ) - { - 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 (DeviceIoControl (dev, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extents, sizeof(extents), &dwResult, NULL)) - { - if (extents.NumberOfDiskExtents > 0) - { - STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR desc; - if (GetPhysicalDriveAlignment (extents.Extents[0].DiskNumber, &desc)) - { - mount.BytesPerSector = desc.BytesPerLogicalSector; - mount.BytesPerPhysicalSector = desc.BytesPerPhysicalSector; - } - } - } - 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, - sizeof(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; - mountThreadParam.pdwResult = &dwResult; - mountThreadParam.dwLastError = ERROR_SUCCESS; - - ShowWaitDialog (hwndDlg, FALSE, MountWaitThreadProc, &mountThreadParam); - - dwLastError = mountThreadParam.dwLastError; - } - else - { - bResult = PerformMountIoctl (&mount, &dwResult, useVolumeID, volumeID); - - dwLastError = GetLastError (); - } - - burn (&mount.VolumePassword, sizeof (mount.VolumePassword)); - burn (&mount.ProtectedHidVolPassword, sizeof (mount.ProtectedHidVolPassword)); - burn (&mount.pkcs5_prf, sizeof (mount.pkcs5_prf)); - burn (&mount.bTrueCryptMode, sizeof (mount.bTrueCryptMode)); - burn (&mount.ProtectedHidVolPkcs5Prf, sizeof (mount.ProtectedHidVolPkcs5Prf)); - - SetLastError (dwLastError); - if (bResult == FALSE) - { - // Volume already open by another process - if (GetLastError () == ERROR_SHARING_VIOLATION) - { - if (FavoriteMountOnArrivalInProgress && ++favoriteMountOnArrivalRetryCount < 10) - { - Sleep (500); - goto retry; - } - - if (mount.bExclusiveAccess == FALSE) - { - if (!quiet) - Error ("FILE_IN_USE_FAILED", hwndDlg); - - return -1; - } - else - { - if (quiet) - { - mount.bExclusiveAccess = FALSE; - goto retry; - } - - // Ask user - if (IDYES == AskWarnNoYes ("FILE_IN_USE", hwndDlg)) - { - mount.bExclusiveAccess = FALSE; - goto retry; - } - } - - return -1; - } - - if (!quiet && (!MultipleMountOperationInProgress || GetLastError() != ERROR_NOT_READY)) - handleWin32Error (hwndDlg, SRC_POS); - - return -1; - } - - if (mount.nReturnCode != 0) - { - if (mount.nReturnCode == ERR_PASSWORD_WRONG) - { - // Do not report wrong password, if not instructed to - if (bReportWrongPassword) - { - IncreaseWrongPwdRetryCount (1); // We increase the count here only if bReportWrongPassword is TRUE, because "Auto-Mount All Devices" and other callers do it separately - - if (WrongPwdRetryCountOverLimit () - && !mount.UseBackupHeader) - { - // Retry using embedded header backup (if any) - mount.UseBackupHeader = TRUE; - goto retry; - } - - if (bDevice && mount.bProtectHiddenVolume) - { - int driveNo; - - if (swscanf (volumePath, L"\\Device\\Harddisk%d\\Partition", &driveNo) == 1) - { - OPEN_TEST_STRUCT openTestStruct; - memset (&openTestStruct, 0, sizeof (openTestStruct)); - - openTestStruct.bDetectTCBootLoader = TRUE; - StringCchPrintfW ((wchar_t *) openTestStruct.wszFileName, array_capacity (openTestStruct.wszFileName), L"\\Device\\Harddisk%d\\Partition0", driveNo); - - DWORD dwResult; - 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.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.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; -} - -typedef struct -{ - int nDosDriveNo; - BOOL forced; - int dismountMaxRetries; - DWORD retryDelay; - int* presult; - DWORD dwLastError; -} UnmountThreadParam; - -void CALLBACK UnmountWaitThreadProc(void* pArg, HWND hwnd) -{ - UnmountThreadParam* pThreadParam = (UnmountThreadParam*) pArg; - int dismountMaxRetries = pThreadParam->dismountMaxRetries; - DWORD retryDelay = pThreadParam->retryDelay; - - do - { - *pThreadParam->presult = DriverUnmountVolume (hwnd, pThreadParam->nDosDriveNo, pThreadParam->forced); - - if (*pThreadParam->presult == ERR_FILES_OPEN) - Sleep (retryDelay); - else - break; - - } while (--dismountMaxRetries > 0); - - pThreadParam->dwLastError = GetLastError (); -} - -static BOOL UnmountVolumeBase (HWND hwndDlg, int nDosDriveNo, BOOL forceUnmount, BOOL ntfsFormatCase) -{ - int result; - BOOL forced = forceUnmount; - int dismountMaxRetries = ntfsFormatCase? 5 : UNMOUNT_MAX_AUTO_RETRIES; - DWORD retryDelay = ntfsFormatCase? 2000: UNMOUNT_AUTO_RETRY_DELAY; - UnmountThreadParam param; - -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); - } - - 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); -} - -BOOL IsMountedVolumeID (BYTE volumeID[VOLUME_ID_SIZE]) -{ - MOUNT_LIST_STRUCT mlist; - DWORD dwResult; - int i; - - memset (&mlist, 0, sizeof (mlist)); - DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, - sizeof (mlist), &mlist, sizeof (mlist), &dwResult, - NULL); - - for (i=0 ; i<26; i++) - if (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 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)); - DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, - sizeof (mlist), &mlist, sizeof (mlist), &dwResult, - NULL); - - for (i=0 ; i<26; i++) - if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], volume)) - return TRUE; - } - - return FALSE; -} - - -int GetMountedVolumeDriveNo (wchar_t *volname) -{ - MOUNT_LIST_STRUCT mlist; - DWORD dwResult; - int i; - wchar_t volume[TC_MAX_PATH*2+16]; - - if (volname == NULL) - return -1; - - 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)); - DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, - sizeof (mlist), &mlist, sizeof (mlist), &dwResult, - NULL); - - for (i=0 ; i<26; i++) - if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], (WCHAR *)volume)) - return i; - - return -1; -} - - -BOOL IsAdmin (void) -{ - return IsUserAnAdmin (); -} - - -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; -} - - -BOOL GetPartitionInfo (const wchar_t *deviceName, PPARTITION_INFORMATION rpartInfo) -{ - BOOL bResult; - DWORD dwResult; - DISK_PARTITION_INFO_STRUCT dpi; - - memset (&dpi, 0, sizeof(dpi)); - StringCbCopyW ((PWSTR) &dpi.deviceName, sizeof(dpi.deviceName), deviceName); - - bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, &dpi, - sizeof (dpi), &dpi, sizeof (dpi), &dwResult, NULL); - - memcpy (rpartInfo, &dpi.partInfo, sizeof (PARTITION_INFORMATION)); - return bResult; -} - - -BOOL GetDeviceInfo (const wchar_t *deviceName, DISK_PARTITION_INFO_STRUCT *info) -{ - DWORD dwResult; - - memset (info, 0, sizeof(*info)); - StringCbCopyW ((PWSTR) &info->deviceName, sizeof(info->deviceName), deviceName); - - return DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, info, sizeof (*info), info, sizeof (*info), &dwResult, NULL); -} - - -BOOL GetDriveGeometry (const wchar_t *deviceName, PDISK_GEOMETRY diskGeometry) -{ - BOOL bResult; - DWORD dwResult; - DISK_GEOMETRY_STRUCT dg; - - memset (&dg, 0, sizeof(dg)); - StringCbCopyW ((PWSTR) &dg.deviceName, sizeof(dg.deviceName), deviceName); - - bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_GEOMETRY, &dg, - sizeof (dg), &dg, sizeof (dg), &dwResult, NULL); - - if (bResult && (dwResult == sizeof (dg)) && dg.diskGeometry.BytesPerSector) - { - memcpy (diskGeometry, &dg.diskGeometry, sizeof (DISK_GEOMETRY)); - return TRUE; - } - else - return FALSE; -} - -BOOL GetPhysicalDriveGeometry (int driveNumber, PDISK_GEOMETRY diskGeometry) -{ - HANDLE hDev; - BOOL bResult = FALSE; - TCHAR devicePath[MAX_PATH]; - - StringCchPrintfW (devicePath, ARRAYSIZE (devicePath), L"\\\\.\\PhysicalDrive%d", driveNumber); - - if ((hDev = CreateFileW (devicePath, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) - { - DWORD bytesRead = 0; - - ZeroMemory (diskGeometry, sizeof (DISK_GEOMETRY)); - - if ( DeviceIoControl (hDev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, diskGeometry, sizeof (DISK_GEOMETRY), &bytesRead, NULL) - && (bytesRead == sizeof (DISK_GEOMETRY)) - && diskGeometry->BytesPerSector) - { - bResult = TRUE; - } - - CloseHandle (hDev); - } - - return bResult; -} - - -// Returns drive letter number assigned to device (-1 if none) -int GetDiskDeviceDriveLetter (PWSTR deviceName) -{ - int i; - WCHAR link[MAX_PATH]; - WCHAR target[MAX_PATH]; - WCHAR device[MAX_PATH]; - - if (!ResolveSymbolicLink (deviceName, device, sizeof(device))) - StringCchCopyW (device, MAX_PATH, deviceName); - - for (i = 0; i < 26; i++) - { - WCHAR drive[] = { (WCHAR) i + L'A', L':', 0 }; - - StringCchCopyW (link, MAX_PATH, L"\\DosDevices\\"); - StringCchCatW (link, MAX_PATH, drive); - - if ( ResolveSymbolicLink (link, target, sizeof(target)) - && (wcscmp (device, target) == 0) - ) - { - return i; - } - } - - return -1; -} - - -// WARNING: This function does NOT provide 100% reliable results -- do NOT use it for critical/dangerous operations! -// Return values: 0 - filesystem does not appear empty, 1 - filesystem appears empty, -1 - an error occurred -int FileSystemAppearsEmpty (const wchar_t *devicePath) -{ - float percentFreeSpace = 0.0; - __int64 occupiedBytes = 0; - - if (GetStatsFreeSpaceOnPartition (devicePath, &percentFreeSpace, &occupiedBytes, TRUE) != -1) - { - if (occupiedBytes > BYTES_PER_GB && percentFreeSpace < 99.99 // "percentFreeSpace < 99.99" is needed because an NTFS filesystem larger than several terabytes can have more than 1GB of data in use, even if there are no files stored on it. - || percentFreeSpace < 88) // A 24-MB NTFS filesystem has 11.5% of space in use even if there are no files stored on it. - { - return 0; - } - else - return 1; - } - else - return -1; -} - - -// Returns the free space on the specified partition (volume) in bytes. If the 'occupiedBytes' pointer -// is not NULL, size of occupied space (in bytes) is written to the pointed location. In addition, if the -// 'percent' pointer is not NULL, % of free space is stored in the pointed location. If there's an error, -// returns -1. -__int64 GetStatsFreeSpaceOnPartition (const wchar_t *devicePath, float *percentFree, __int64 *occupiedBytes, BOOL silent) -{ - WCHAR devPath [MAX_PATH]; - int driveLetterNo = -1; - wchar_t szRootPath[4] = {0, L':', L'\\', 0}; - ULARGE_INTEGER freeSpaceSize; - ULARGE_INTEGER totalNumberOfBytes; - ULARGE_INTEGER totalNumberOfFreeBytes; - - StringCbCopyW (devPath, sizeof(devPath), devicePath); - - driveLetterNo = GetDiskDeviceDriveLetter (devPath); - szRootPath[0] = (wchar_t) driveLetterNo + L'A'; - - - if (!GetDiskFreeSpaceEx (szRootPath, &freeSpaceSize, &totalNumberOfBytes, &totalNumberOfFreeBytes)) - { - if (!silent) - { - handleWin32Error (MainDlg, SRC_POS); - Error ("CANNOT_CALC_SPACE", MainDlg); - } - - return -1; - } - - - if (percentFree != NULL || occupiedBytes != NULL) - { - // Determine occupied space and % of free space - - PARTITION_INFORMATION partitionInfo; - - if (!GetPartitionInfo (devicePath, &partitionInfo)) - { - if (!silent) - { - handleWin32Error (MainDlg, SRC_POS); - Error ("CANT_GET_VOLSIZE", MainDlg); - } - return -1; - } - - if (occupiedBytes != NULL) - *occupiedBytes = partitionInfo.PartitionLength.QuadPart - freeSpaceSize.QuadPart; - - if (percentFree != NULL) - *percentFree = (float) ((double) freeSpaceSize.QuadPart / (double) partitionInfo.PartitionLength.QuadPart * 100.0); - } - - return freeSpaceSize.QuadPart; -} - - -// Returns -1 if there's an error. -__int64 GetDeviceSize (const wchar_t *devicePath) -{ - PARTITION_INFORMATION partitionInfo; - - if (!GetPartitionInfo (devicePath, &partitionInfo)) - return -1; - - return partitionInfo.PartitionLength.QuadPart; -} - - -HANDLE DismountDrive (wchar_t *devName, wchar_t *devicePath) -{ - DWORD dwResult; - HANDLE hVolume; - BOOL bResult = FALSE; - int attempt = UNMOUNT_MAX_AUTO_RETRIES; - int driveLetterNo = -1; - WCHAR devPath [MAX_PATH]; - - StringCbCopyW (devPath, sizeof(devPath), devicePath); - driveLetterNo = GetDiskDeviceDriveLetter (devPath); - - - hVolume = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (hVolume == INVALID_HANDLE_VALUE) - return INVALID_HANDLE_VALUE; - - - // Try to lock the volume first so that dismount is not forced. - // If we fail, we will dismount anyway even if it needs to be forced. - - CloseVolumeExplorerWindows (MainDlg, driveLetterNo); - - while (!(bResult = DeviceIoControl (hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) - && attempt > 0) - { - Sleep (UNMOUNT_AUTO_RETRY_DELAY); - attempt--; - } - - - // Try to dismount the volume - - attempt = UNMOUNT_MAX_AUTO_RETRIES; - - while (!(bResult = DeviceIoControl (hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) - && attempt > 0) - { - Sleep (UNMOUNT_AUTO_RETRY_DELAY); - attempt--; - } - - if (!bResult) - CloseHandle (hVolume); - - return (bResult ? hVolume : INVALID_HANDLE_VALUE); -} - -// Returns -1 if the specified string is not found in the buffer. Otherwise, returns the -// offset of the first occurrence of the string. The string and the buffer may contain zeroes, -// which do NOT terminate them. -int64 FindString (const char *buf, const char *str, int64 bufLen, int64 strLen, int64 startOffset) -{ - if (buf == NULL - || str == NULL - || strLen > bufLen - || bufLen < 1 - || strLen < 1 - || startOffset > bufLen - strLen) - { - return -1; - } - - for (int64 i = startOffset; i <= bufLen - strLen; i++) - { - if (memcmp (buf + i, str, (size_t) strLen) == 0) - return i; - } - - return -1; -} - -// Returns TRUE if the file or directory exists (both may be enclosed in quotation marks). -BOOL FileExists (const wchar_t *filePathPtr) -{ - wchar_t filePath [TC_MAX_PATH * 2 + 1]; - - // Strip quotation marks (if any) - if (filePathPtr [0] == L'"') - { - StringCbCopyW (filePath, sizeof(filePath), filePathPtr + 1); - } - else - { - StringCbCopyW (filePath, sizeof(filePath), filePathPtr); - } - - // Strip quotation marks (if any) - if (filePath [wcslen (filePath) - 1] == L'"') - filePath [wcslen (filePath) - 1] = 0; - - return (_waccess (filePath, 0) != -1); -} - -// Searches the file from its end for the LAST occurrence of the string str. -// The string may contain zeroes, which do NOT terminate the string. -// If the string is found, its offset from the start of the file is returned. -// If the string isn't found or if any error occurs, -1 is returned. -__int64 FindStringInFile (const wchar_t *filePath, const char* str, int strLen) -{ - int bufSize = 64 * BYTES_PER_KB; - char *buffer = (char *) err_malloc (bufSize); - HANDLE src = NULL; - DWORD bytesRead; - BOOL readRetVal; - __int64 filePos = GetFileSize64 (filePath); - int bufPos = 0; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL bExit = FALSE; - int filePosStep; - __int64 retVal = -1; - - if (filePos <= 0 - || buffer == NULL - || strLen > bufSize - || strLen < 1) - { - if (buffer) - free (buffer); - return -1; - } - - src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src == INVALID_HANDLE_VALUE) - { - free (buffer); - return -1; - } - - filePosStep = bufSize - strLen + 1; - - do - { - filePos -= filePosStep; - - if (filePos < 0) - { - filePos = 0; - bExit = TRUE; - } - - seekOffset.QuadPart = filePos; - - if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - goto fsif_end; - - if ((readRetVal = ReadFile (src, buffer, bufSize, &bytesRead, NULL)) == 0 - || bytesRead == 0) - goto fsif_end; - - bufPos = bytesRead - strLen; - - while (bufPos > 0) - { - if (memcmp (buffer + bufPos, str, strLen) == 0) - { - // String found - retVal = filePos + bufPos; - goto fsif_end; - } - bufPos--; - } - - } while (!bExit); - -fsif_end: - CloseHandle (src); - free (buffer); - - return retVal; -} - -// System CopyFile() copies source file attributes (like FILE_ATTRIBUTE_ENCRYPTED) -// so we need to use our own copy function -BOOL TCCopyFileBase (HANDLE src, HANDLE dst) -{ - __int8 *buffer; - FILETIME fileTime; - DWORD bytesRead, bytesWritten; - BOOL res; - - buffer = (char *) malloc (64 * 1024); - if (!buffer) - { - CloseHandle (src); - CloseHandle (dst); - return FALSE; - } - - while (res = ReadFile (src, buffer, 64 * 1024, &bytesRead, NULL)) - { - if (bytesRead == 0) - { - res = 1; - break; - } - - if (!WriteFile (dst, buffer, bytesRead, &bytesWritten, NULL) - || bytesRead != bytesWritten) - { - res = 0; - break; - } - } - - if (GetFileTime (src, NULL, NULL, &fileTime)) - SetFileTime (dst, NULL, NULL, &fileTime); - - CloseHandle (src); - CloseHandle (dst); - - free (buffer); - return res != 0; -} - -BOOL TCCopyFile (wchar_t *sourceFileName, wchar_t *destinationFile) -{ - HANDLE src, dst; - - src = CreateFileW (sourceFileName, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src == INVALID_HANDLE_VALUE) - return FALSE; - - dst = CreateFileW (destinationFile, - GENERIC_WRITE, - 0, NULL, CREATE_ALWAYS, 0, NULL); - - if (dst == INVALID_HANDLE_VALUE) - { - CloseHandle (src); - return FALSE; - } - - return TCCopyFileBase (src, dst); -} - -// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file -// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE). -BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed) -{ - HANDLE dst; - DWORD bytesWritten; - BOOL res = TRUE; - DWORD dwLastError = 0; - - dst = CreateFile (destinationFile, - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); - - dwLastError = GetLastError(); - if (!bAppend && bRenameIfFailed && (dst == INVALID_HANDLE_VALUE) && (GetLastError () == ERROR_SHARING_VIOLATION)) - { - wchar_t renamedPath[TC_MAX_PATH + 1]; - StringCbCopyW (renamedPath, sizeof(renamedPath), destinationFile); - StringCbCatW (renamedPath, sizeof(renamedPath), VC_FILENAME_RENAMED_SUFFIX); - - /* rename the locked file in order to be able to create a new one */ - if (MoveFileEx (destinationFile, renamedPath, MOVEFILE_REPLACE_EXISTING)) - { - dst = CreateFile (destinationFile, - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); - dwLastError = GetLastError(); - if (dst == INVALID_HANDLE_VALUE) - { - /* restore the original file name */ - MoveFileEx (renamedPath, destinationFile, MOVEFILE_REPLACE_EXISTING); - } - else - { - /* delete the renamed file when the machine reboots */ - MoveFileEx (renamedPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); - } - } - } - - if (dst == INVALID_HANDLE_VALUE) - { - SetLastError (dwLastError); - handleWin32Error (MainDlg, SRC_POS); - return FALSE; - } - - if (bAppend) - SetFilePointer (dst, 0, NULL, FILE_END); - - if (!WriteFile (dst, inputBuffer, inputLength, &bytesWritten, NULL) - || inputLength != bytesWritten) - { - res = FALSE; - } - - if (!res) - { - // If CREATE_ALWAYS is used, ERROR_ALREADY_EXISTS is returned after successful overwrite - // of an existing file (it's not an error) - if (! (GetLastError() == ERROR_ALREADY_EXISTS && !bAppend) ) - handleWin32Error (MainDlg, SRC_POS); - } - - CloseHandle (dst); - - if (!res && !bAppend) - _wremove (destinationFile); - - return res; -} - - -// Proper flush for Windows systems. Returns TRUE if successful. -BOOL TCFlushFile (FILE *f) -{ - HANDLE hf = (HANDLE) _get_osfhandle (_fileno (f)); - - fflush (f); - - if (hf == INVALID_HANDLE_VALUE) - return FALSE; - - return FlushFileBuffers (hf) != 0; -} - - -// Prints a UTF-16 text (note that this involves a real printer, not a screen). -// textByteLen - length of the text in bytes -// title - printed as part of the page header and used as the filename for a temporary file -BOOL PrintHardCopyTextUTF16 (wchar_t *text, wchar_t *title, size_t textByteLen) -{ - wchar_t cl [MAX_PATH*3] = {L"/p \""}; - wchar_t path [MAX_PATH * 2] = { 0 }; - wchar_t filename [MAX_PATH + 1] = { 0 }; - - StringCbCopyW (filename, sizeof(filename), title); - //strcat (filename, ".txt"); - - GetTempPath (ARRAYSIZE (path), path); - - if (!FileExists (path)) - { - StringCbCopyW (path, sizeof(path), GetConfigPath (filename)); - - if (wcslen(path) < 2) - return FALSE; - } - else - { - StringCbCatW (path, sizeof(path), filename); - } - - // Write the Unicode signature - if (!SaveBufferToFile ("\xFF\xFE", path, 2, FALSE, FALSE)) - { - _wremove (path); - return FALSE; - } - - // Write the actual text - if (!SaveBufferToFile ((char *) text, path, (DWORD) textByteLen, TRUE, FALSE)) - { - _wremove (path); - return FALSE; - } - - StringCbCatW (cl, sizeof(cl), path); - StringCbCatW (cl, sizeof(cl), L"\""); - - // Get the absolute path for notepad - if (GetWindowsDirectory(filename, MAX_PATH)) - { - if (filename[wcslen (filename) - 1] != L'\\') - StringCbCatW (filename, sizeof(filename), L"\\"); - StringCbCatW(filename, sizeof(filename), PRINT_TOOL); - } - else - StringCbCopyW(filename, sizeof(filename), L"C:\\Windows\\" PRINT_TOOL); - - WaitCursor (); - ShellExecute (NULL, L"open", filename, cl, NULL, SW_HIDE); - Sleep (6000); - NormalCursor(); - - _wremove (path); - - return TRUE; -} - - -BOOL IsNonInstallMode () -{ - HKEY hkey; - DWORD dw; - - if (bPortableModeConfirmed) - return TRUE; - - if (hDriver != INVALID_HANDLE_VALUE) - { - // The driver is running - if (DeviceIoControl (hDriver, TC_IOCTL_GET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dw, 0)) - { - bPortableModeConfirmed = TRUE; - return TRUE; - } - else - { - // This is also returned if we fail to determine the status (it does not mean that portable mode is disproved). - return FALSE; - } - } - else - { - // The tests in this block are necessary because this function is in some cases called before DriverAttach(). - - HANDLE hDriverTmp = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (hDriverTmp == INVALID_HANDLE_VALUE) - { - // The driver was not found in the system path - - wchar_t path[MAX_PATH * 2] = { 0 }; - - // We can't use GetConfigPath() here because it would call us back (indirect recursion) - if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path))) - { - StringCbCatW (path, MAX_PATH * 2, L"\\VeraCrypt\\"); - StringCbCatW (path, MAX_PATH * 2, TC_APPD_FILENAME_SYSTEM_ENCRYPTION); - - if (FileExists (path)) - { - // To maintain consistency and safety, if the system encryption config file exits, we cannot - // allow portable mode. (This happens e.g. when the pretest fails and the user selects - // "Last Known Good Configuration" from the Windows boot menu.) - - // However, if UAC elevation is needed, we have to confirm portable mode first (after we are elevated, we won't). - if (!IsAdmin () && IsUacSupported ()) - return TRUE; - - return FALSE; - } - } - - // As the driver was not found in the system path, we can predict that we will run in portable mode - return TRUE; - } - else - CloseHandle (hDriverTmp); - } - - // The following test may be unreliable in some cases (e.g. after the user selects restore "Last Known Good - // Configuration" from the Windows boot menu). - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt", 0, KEY_READ | KEY_WOW64_32KEY, &hkey) == ERROR_SUCCESS) - { - RegCloseKey (hkey); - return FALSE; - } - else - return TRUE; -} - - -LRESULT SetCheckBox (HWND hwndDlg, int dlgItem, BOOL state) -{ - return SendDlgItemMessage (hwndDlg, dlgItem, BM_SETCHECK, state ? BST_CHECKED : BST_UNCHECKED, 0); -} - - -BOOL GetCheckBox (HWND hwndDlg, int dlgItem) -{ - return IsButtonChecked (GetDlgItem (hwndDlg, dlgItem)); -} - - -// Scroll the listview vertically so that the item with index of topMostVisibleItem is the topmost visible item. -void SetListScrollHPos (HWND hList, int topMostVisibleItem) -{ - int testedPos = 0; - - do - { - SendMessage (hList, LVM_SCROLL, 0, testedPos); - - } while (ListView_GetTopIndex (hList) < topMostVisibleItem && ++testedPos < 10000); -} - - -// Adds or removes TrueCrypt.exe to/from the system startup sequence (with appropriate command line arguments) -void ManageStartupSeq (void) -{ - if (!IsNonInstallMode ()) - { - wchar_t regk [64]; - - GetStartupRegKeyName (regk, sizeof(regk)); - - if (bStartOnLogon || bMountDevicesOnLogon || bMountFavoritesOnLogon) - { - wchar_t exe[MAX_PATH * 2] = { L'"' }; - - GetModuleFileName (NULL, exe + 1, ARRAYSIZE (exe) - 1); - -#ifdef VOLFORMAT - { - wchar_t *tmp = NULL; - - if (tmp = wcsrchr (exe, L'\\')) - { - *tmp = 0; - StringCbCatW (exe, MAX_PATH * 2, L"\\VeraCrypt.exe"); - } - } -#endif - StringCbCatW (exe, MAX_PATH * 2, L"\" /q preferences /a logon"); - - if (bMountDevicesOnLogon) StringCbCatW (exe, MAX_PATH * 2, L" /a devices"); - if (bMountFavoritesOnLogon) StringCbCatW (exe, MAX_PATH * 2, L" /a favorites"); - - WriteRegistryString (regk, L"VeraCrypt", exe); - } - else - DeleteRegistryValue (regk, L"VeraCrypt"); - } -} - - -// Adds or removes the VeraCrypt Volume Creation Wizard to/from the system startup sequence -void ManageStartupSeqWiz (BOOL bRemove, const wchar_t *arg) -{ - wchar_t regk [64]; - - GetStartupRegKeyName (regk, sizeof(regk)); - - if (!bRemove) - { - size_t exeSize = (MAX_PATH * 2) + 3 + 20 + wcslen (arg); // enough room for all concatenation operations - wchar_t* exe = (wchar_t*) calloc(1, exeSize * sizeof (wchar_t)); - exe[0] = L'"'; - GetModuleFileName (NULL, exe + 1, (DWORD) (exeSize - 1)); - -#ifndef VOLFORMAT - { - wchar_t *tmp = NULL; - - if (tmp = wcsrchr (exe, L'\\')) - { - *tmp = 0; - - StringCchCatW (exe, exeSize, L"\\VeraCrypt Format.exe"); - } - } -#endif - - 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""); - - for (id = (IsOSAtLeast (WIN_VISTA) ? 0 : L'a'); id <= (IsOSAtLeast (WIN_VISTA) ? 1000 : L'z'); id++) - { - *strTmp = 0; - StringCbPrintfW (key, sizeof(key), (IsOSAtLeast (WIN_VISTA) ? L"%d" : L"%c"), 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); - - if (*p == id) - { - p++; - len -= sizeof (int); - continue; - } - *pout++ = *p++; - } - - WriteRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", bufout, len); - } - else - { - wchar_t *p = (wchar_t*) buf; - wchar_t *pout = (wchar_t*) bufout; - - ReadRegistryString (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", L"MRUList", L"", (wchar_t*) buf, sizeof (buf)); - while (*p) - { - if (*p == id) - { - p++; - continue; - } - *pout++ = *p++; - } - *pout++ = 0; - - WriteRegistryString (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", L"MRUList", (wchar_t*) bufout); - } - - 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; - li.iSubItem = 0; - return ListView_InsertItem (list, &li); -} - - -LRESULT ListSubItemSet (HWND list, int index, int subIndex, const wchar_t *string) -{ - LVITEM li; - memset (&li, 0, sizeof(li)); - - li.mask = LVIF_TEXT; - li.pszText = (wchar_t*) string; - li.iItem = index; - li.iSubItem = subIndex; - return ListView_SetItem (list, &li); -} - - -BOOL GetMountList (MOUNT_LIST_STRUCT *list) -{ - DWORD dwResult; - - memset (list, 0, sizeof (*list)); - return DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, list, - sizeof (*list), list, sizeof (*list), &dwResult, - NULL); -} - - -int GetDriverRefCount () -{ - DWORD dwResult; - BOOL bResult; - int refCount; - - bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount, - sizeof (refCount), &dwResult, NULL); - - if (bResult) - return refCount; - else - return -1; -} - -// Loads a 32-bit integer from the file at the specified file offset. The saved value is assumed to have been -// processed by mputLong(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). -BOOL LoadInt32 (const wchar_t *filePath, unsigned __int32 *result, __int64 fileOffset) -{ - DWORD bufSize = sizeof(__int32); - unsigned char *buffer = (unsigned char *) malloc (bufSize); - unsigned char *bufferPtr = buffer; - HANDLE src = NULL; - DWORD bytesRead; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL retVal = FALSE; - - if (buffer == NULL) - return -1; - - src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src == INVALID_HANDLE_VALUE) - { - free (buffer); - return FALSE; - } - - seekOffset.QuadPart = fileOffset; - - if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - goto fsif_end; - - if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 - || bytesRead != bufSize) - goto fsif_end; - - - retVal = TRUE; - - *result = mgetLong(bufferPtr); - -fsif_end: - CloseHandle (src); - free (buffer); - - return retVal; -} - -// Loads a 16-bit integer from the file at the specified file offset. The saved value is assumed to have been -// processed by mputWord(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). -BOOL LoadInt16 (const wchar_t *filePath, int *result, __int64 fileOffset) -{ - DWORD bufSize = sizeof(__int16); - unsigned char *buffer = (unsigned char *) malloc (bufSize); - unsigned char *bufferPtr = buffer; - HANDLE src = NULL; - DWORD bytesRead; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL retVal = FALSE; - - if (buffer == NULL) - return -1; - - src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (src == INVALID_HANDLE_VALUE) - { - free (buffer); - return FALSE; - } - - seekOffset.QuadPart = fileOffset; - - if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - goto fsif_end; - - if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 - || bytesRead != bufSize) - goto fsif_end; - - - retVal = TRUE; - - *result = mgetWord(bufferPtr); - -fsif_end: - CloseHandle (src); - free (buffer); - - return retVal; -} - -// Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated. -char *LoadFile (const wchar_t *fileName, DWORD *size) -{ - char *buf; - DWORD fileSize = INVALID_FILE_SIZE; - HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (h == INVALID_HANDLE_VALUE) - return NULL; - - if ((fileSize = GetFileSize (h, NULL)) == INVALID_FILE_SIZE) - { - CloseHandle (h); - return NULL; - } - - *size = fileSize; - buf = (char *) calloc (*size + 1, 1); - - if (buf == NULL) - { - CloseHandle (h); - return NULL; - } - - if (!ReadFile (h, buf, *size, size, NULL)) - { - free (buf); - buf = NULL; - } - - CloseHandle (h); - return buf; -} - - -// Returns NULL if there's any error. -char *LoadFileBlock (const wchar_t *fileName, __int64 fileOffset, DWORD count) -{ - char *buf; - DWORD bytesRead = 0; - LARGE_INTEGER seekOffset, seekOffsetNew; - BOOL bStatus; - - HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (h == INVALID_HANDLE_VALUE) - return NULL; - - seekOffset.QuadPart = fileOffset; - - if (SetFilePointerEx (h, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) - { - CloseHandle (h); - return NULL; - } - - buf = (char *) calloc (count, 1); - - if (buf == NULL) - { - CloseHandle (h); - return NULL; - } - - bStatus = ReadFile (h, buf, count, &bytesRead, NULL); - - CloseHandle (h); - - if (!bStatus || (bytesRead != count)) - { - free (buf); - return NULL; - } - - return buf; -} - - -// Returns -1 if there is an error, or the size of the file. -__int64 GetFileSize64 (const wchar_t *path) -{ - HANDLE h = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - LARGE_INTEGER size; - __int64 retSize = -1; - - if (h) - { - if (GetFileSizeEx (h, &size)) - { - retSize = size.QuadPart; - } - - CloseHandle (h); - } - - return retSize; -} - - -wchar_t *GetModPath (wchar_t *path, int maxSize) -{ - GetModuleFileName (NULL, path, maxSize); - wchar_t* ptr = wcsrchr (path, L'\\'); - if (ptr) - ptr[1] = 0; - return path; -} - - -wchar_t *GetConfigPath (wchar_t *fileName) -{ - static wchar_t path[MAX_PATH * 2] = { 0 }; - - if (IsNonInstallMode ()) - { - GetModPath (path, ARRAYSIZE (path)); - StringCchCatW (path, (MAX_PATH * 2), fileName); - - return path; - } - - if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) - { - StringCchCatW (path, (MAX_PATH * 2), L"\\VeraCrypt\\"); - CreateDirectory (path, NULL); - StringCchCatW (path, (MAX_PATH * 2), fileName); - } - else - path[0] = 0; - - return path; -} - - -wchar_t *GetProgramConfigPath (wchar_t *fileName) -{ - static wchar_t path[MAX_PATH * 2] = { 0 }; - - if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) - { - StringCchCatW (path, (MAX_PATH * 2), L"\\VeraCrypt\\"); - CreateDirectory (path, NULL); - StringCchCatW (path, (MAX_PATH * 2), fileName); - } - else - path[0] = 0; - - return path; -} - - -std::wstring GetServiceConfigPath (const wchar_t *fileName, bool useLegacy) -{ - wchar_t sysPath[TC_MAX_PATH]; - - if (Is64BitOs() && useLegacy) - { - typedef UINT (WINAPI *GetSystemWow64Directory_t) (LPWSTR lpBuffer, UINT uSize); - - GetSystemWow64Directory_t getSystemWow64Directory = (GetSystemWow64Directory_t) GetProcAddress (GetModuleHandle (L"kernel32"), "GetSystemWow64DirectoryW"); - getSystemWow64Directory (sysPath, ARRAYSIZE (sysPath)); - } - else - GetSystemDirectory (sysPath, ARRAYSIZE (sysPath)); - - return wstring (sysPath) + L"\\" + fileName; -} - - -// 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) -{ - if (nCurrentOS == WIN_2000) - { - MessageBoxW (MainDlg, text, headline, warning ? MB_ICONWARNING : MB_ICONINFORMATION); - return; - } - - 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 - - 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, - headingString == NULL ? L"VeraCrypt" : headingString, - textString == NULL ? L" " : textString, - FALSE); -} - - -// Either of the pointers may be NULL -void WarningBalloon (char *headingStringId, char *textStringId, HWND hwnd) -{ - if (Silent) - return; - - TaskBarIconDisplayBalloonTooltip (hwnd, - headingStringId == NULL ? L"VeraCrypt" : GetString (headingStringId), - textStringId == NULL ? L" " : GetString (textStringId), - TRUE); -} - - -// Either of the pointers may be NULL -void WarningBalloonDirect (wchar_t *headingString, wchar_t *textString, HWND hwnd) -{ - if (Silent) - return; - - TaskBarIconDisplayBalloonTooltip (hwnd, - headingString == NULL ? L"VeraCrypt" : headingString, - textString == NULL ? L" " : textString, - TRUE); -} - - -int Info (char *stringId, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONINFORMATION); -} - - -int InfoTopMost (char *stringId, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); -} - - -int InfoDirect (const wchar_t *msg, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, msg, lpszTitle, MB_ICONINFORMATION); -} - - -int Warning (char *stringId, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING); -} - - -int WarningTopMost (char *stringId, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); -} - - -int WarningDirect (const wchar_t *warnMsg, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, warnMsg, lpszTitle, MB_ICONWARNING); -} - - -int Error (char *stringId, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR); -} - -int ErrorRetryCancel (char *stringId, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_RETRYCANCEL); -} - -int ErrorTopMost (char *stringId, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); -} - - -int ErrorDirect (const wchar_t *errMsg, HWND hwnd) -{ - if (Silent) return 0; - return MessageBoxW (hwnd, errMsg, lpszTitle, MB_ICONERROR); -} - - -int AskYesNo (char *stringId, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1); -} - - -int AskYesNoString (const wchar_t *str, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, str, lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1); -} - - -int AskYesNoTopmost (char *stringId, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1 | MB_SETFOREGROUND | MB_TOPMOST); -} - - -int AskNoYes (char *stringId, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); -} - -int AskNoYesString (const wchar_t *string, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, string, lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); -} - -int AskOkCancel (char *stringId, HWND hwnd) -{ - if (Silent) return IDCANCEL; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_OKCANCEL | MB_DEFBUTTON1); -} - - -int AskWarnYesNo (char *stringId, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1); -} - - -int AskWarnYesNoString (const wchar_t *string, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1); -} - - -int AskWarnYesNoTopmost (char *stringId, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1 | MB_SETFOREGROUND | MB_TOPMOST); -} - - -int AskWarnYesNoStringTopmost (const wchar_t *string, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1 | MB_SETFOREGROUND | MB_TOPMOST); -} - - -int AskWarnNoYes (char *stringId, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); -} - - -int AskWarnNoYesString (const wchar_t *string, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); -} - - -int AskWarnNoYesTopmost (char *stringId, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2 | MB_SETFOREGROUND | MB_TOPMOST); -} - - -int AskWarnOkCancel (char *stringId, HWND hwnd) -{ - if (Silent) return IDCANCEL; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON1); -} - - -int AskWarnCancelOk (char *stringId, HWND hwnd) -{ - if (Silent) return IDCANCEL; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2); -} - - -int AskErrYesNo (char *stringId, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1); -} - - -int AskErrNoYes (char *stringId, HWND hwnd) -{ - if (Silent) return IDNO; - return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_YESNO | MB_DEFBUTTON2); -} - - -// The function accepts two input formats: -// Input format 1: {0, "MESSAGE_STRING_ID", "BUTTON_1_STRING_ID", ... "LAST_BUTTON_STRING_ID", 0}; -// Input format 2: {L"", L"Message text", L"Button caption 1", ... L"Last button caption", 0}; -// The second format is to be used if any of the strings contains format specification (e.g. %s, %d) or -// in any other cases where a string needs to be resolved before calling this function. -// The returned value is the ordinal number of the choice the user selected (1..MAX_MULTI_CHOICES) -int AskMultiChoice (void *strings[], BOOL bBold, HWND hwnd) -{ - MULTI_CHOICE_DLGPROC_PARAMS params; - - params.strings = &strings[0]; - params.bold = bBold; - - return (int) DialogBoxParamW (hInst, - MAKEINTRESOURCEW (IDD_MULTI_CHOICE_DLG), hwnd, - (DLGPROC) MultiChoiceDialogProc, (LPARAM) ¶ms); -} - - -BOOL ConfigWriteBegin () -{ - DWORD size; - if (ConfigFileHandle != NULL) - return FALSE; - - if (ConfigBuffer == NULL) - ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); - - ConfigFileHandle = _wfopen (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), L"w,ccs=UTF-8"); - if (ConfigFileHandle == NULL) - { - free (ConfigBuffer); - ConfigBuffer = NULL; - return FALSE; - } - XmlWriteHeader (ConfigFileHandle); - fputws (L"\n\t", ConfigFileHandle); - - return TRUE; -} - - -BOOL ConfigWriteEnd (HWND hwnd) -{ - char *xml = ConfigBuffer; - char key[128], value[2048]; - - if (ConfigFileHandle == NULL) return FALSE; - - // Write unmodified values - while (xml && (xml = XmlFindElement (xml, "config"))) - { - XmlGetAttributeText (xml, "key", key, sizeof (key)); - XmlGetNodeText (xml, value, sizeof (value)); - - fwprintf (ConfigFileHandle, L"\n\t\t%hs", key, value); - xml++; - } - - fputws (L"\n\t", ConfigFileHandle); - XmlWriteFooter (ConfigFileHandle); - - TCFlushFile (ConfigFileHandle); - - CheckFileStreamWriteErrors (hwnd, ConfigFileHandle, TC_APPD_FILENAME_CONFIGURATION); - - fclose (ConfigFileHandle); - ConfigFileHandle = NULL; - - if (ConfigBuffer != NULL) - { - DWORD size; - free (ConfigBuffer); - ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); - } - - return TRUE; -} - - -BOOL ConfigWriteString (char *configKey, char *configValue) -{ - char *c; - if (ConfigFileHandle == NULL) - return FALSE; - - // Mark previous config value as updated - if (ConfigBuffer != NULL) - { - c = XmlFindElementByAttributeValue (ConfigBuffer, "config", "key", configKey); - if (c != NULL) - c[1] = '!'; - } - - return 0 != fwprintf ( - ConfigFileHandle, L"\n\t\t%hs", - configKey, configValue); -} - -BOOL ConfigWriteStringW (char *configKey, wchar_t *configValue) -{ - char *c; - if (ConfigFileHandle == NULL) - return FALSE; - - // Mark previous config value as updated - if (ConfigBuffer != NULL) - { - c = XmlFindElementByAttributeValue (ConfigBuffer, "config", "key", configKey); - if (c != NULL) - c[1] = '!'; - } - - return 0 != fwprintf ( - ConfigFileHandle, L"\n\t\t%ls", - configKey, configValue); -} - -BOOL ConfigWriteInt (char *configKey, int configValue) -{ - char val[32]; - StringCbPrintfA (val, sizeof(val), "%d", configValue); - return ConfigWriteString (configKey, val); -} - - -static BOOL ConfigRead (char *configKey, char *configValue, int maxValueSize) -{ - DWORD size; - char *xml; - - if (ConfigBuffer == NULL) - ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); - - xml = ConfigBuffer; - if (xml != NULL) - { - xml = XmlFindElementByAttributeValue (xml, "config", "key", configKey); - if (xml != NULL) - { - XmlGetNodeText (xml, configValue, maxValueSize); - return TRUE; - } - } - - return FALSE; -} - - -int ConfigReadInt (char *configKey, int defaultValue) -{ - char s[32]; - - if (ConfigRead (configKey, s, sizeof (s))) - return atoi (s); - else - return defaultValue; -} - - -char *ConfigReadString (char *configKey, char *defaultValue, char *str, int maxLen) -{ - if (ConfigRead (configKey, str, maxLen)) - return str; - else - { - StringCbCopyA (str, maxLen, defaultValue); - return defaultValue; - } -} - -void ConfigReadCompareInt(char *configKey, int defaultValue, int* pOutputValue, BOOL bOnlyCheckModified, BOOL* pbModified) -{ - int intValue = ConfigReadInt (configKey, defaultValue); - if (pOutputValue) - { - if (pbModified && (*pOutputValue != intValue)) - *pbModified = TRUE; - if (!bOnlyCheckModified) - *pOutputValue = intValue; - } -} - -void ConfigReadCompareString (char *configKey, char *defaultValue, char *str, int maxLen, BOOL bOnlyCheckModified, BOOL *pbModified) -{ - char *strValue = (char*) malloc (maxLen); - if (strValue) - { - memcpy (strValue, str, maxLen); - - ConfigReadString (configKey, defaultValue, strValue, maxLen); - - if (pbModified && strcmp (str, strValue)) - *pbModified = TRUE; - if (!bOnlyCheckModified) - memcpy(str, strValue, maxLen); - - free (strValue); - } - else - { - /* allocation failed. Suppose that value changed */ - if (pbModified) - *pbModified = TRUE; - if (!bOnlyCheckModified) - ConfigReadString (configKey, defaultValue, str, maxLen); - - } -} - -void OpenPageHelp (HWND hwndDlg, int nPage) -{ - int r = (int)ShellExecuteW (NULL, L"open", szHelpFile, NULL, NULL, SW_SHOWNORMAL); - - if (r == ERROR_FILE_NOT_FOUND) - { - // Try the secondary help file - r = (int)ShellExecuteW (NULL, L"open", szHelpFile2, NULL, NULL, SW_SHOWNORMAL); - - if (r == ERROR_FILE_NOT_FOUND) - { - OpenOnlineHelp (); - return; - } - } - - if (r == SE_ERR_NOASSOC) - { - if (AskYesNo ("HELP_READER_ERROR", MainDlg) == IDYES) - OpenOnlineHelp (); - } -} - - -void OpenOnlineHelp () -{ - Applink ("help", TRUE, ""); -} - - -#ifndef SETUP - -void RestoreDefaultKeyFilesParam (void) -{ - KeyFileRemoveAll (&FirstKeyFile); - if (defaultKeyFilesParam.FirstKeyFile != NULL) - { - KeyFileCloneAll (defaultKeyFilesParam.FirstKeyFile, &FirstKeyFile); - KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles; - } - else - KeyFilesEnable = FALSE; -} - - -BOOL LoadDefaultKeyFilesParam (void) -{ - BOOL status = TRUE; - DWORD size; - char *defaultKeyfilesFile = LoadFile (GetConfigPath (TC_APPD_FILENAME_DEFAULT_KEYFILES), &size); - char *xml = defaultKeyfilesFile; - KeyFile *kf; - - if (xml == NULL) - return FALSE; - - KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); - - while (xml = XmlFindElement (xml, "keyfile")) - { - kf = (KeyFile *) malloc (sizeof (KeyFile)); - if (kf) - { - char fileName [MAX_PATH + 1]; - if (XmlGetNodeText (xml, fileName, sizeof (fileName)) != NULL) - { - std::wstring wszFileName = Utf8StringToWide(fileName); - StringCbCopyW (kf->FileName, sizeof (kf->FileName), wszFileName.c_str ()); - defaultKeyFilesParam.FirstKeyFile = KeyFileAdd (defaultKeyFilesParam.FirstKeyFile, kf); - } - else - free (kf); - } - else - { - KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); - status = FALSE; - break; - } - - xml++; - } - - free (defaultKeyfilesFile); - if (status) - KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles; - - return status; -} - -#endif /* #ifndef SETUP */ - - -void Debug (char *format, ...) -{ - char buf[1024]; - va_list val; - - va_start(val, format); - StringCbVPrintfA (buf, sizeof (buf), format, val); - va_end(val); - - OutputDebugStringA (buf); -} - - -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 IsOSAtLeast (OSVersionEnum reqMinOS) -{ - return IsOSVersionAtLeast (reqMinOS, 0); -} - - -// Returns TRUE if the operating system is at least reqMinOS and service pack at least reqMinServicePack. -// Example 1: IsOSVersionAtLeast (WIN_VISTA, 1) called under Windows 2008, returns TRUE. -// Example 2: IsOSVersionAtLeast (WIN_XP, 3) called under Windows XP SP1, returns FALSE. -// Example 3: IsOSVersionAtLeast (WIN_XP, 3) called under Windows Vista SP1, returns TRUE. -BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack) -{ - /* When updating this function, update IsOSAtLeast() in Ntdriver.c too. */ - - if (CurrentOSMajor <= 0) - TC_THROW_FATAL_EXCEPTION; - - int major = 0, minor = 0; - - switch (reqMinOS) - { - case WIN_2000: major = 5; minor = 0; break; - case WIN_XP: major = 5; minor = 1; break; - case WIN_SERVER_2003: major = 5; minor = 2; break; - case WIN_VISTA: major = 6; minor = 0; break; - case WIN_7: major = 6; minor = 1; break; - case WIN_8: major = 6; minor = 2; break; - case WIN_8_1: major = 6; minor = 3; break; - case WIN_10: major = 10; minor = 0; break; - - default: - TC_THROW_FATAL_EXCEPTION; - break; - } - - return ((CurrentOSMajor << 16 | CurrentOSMinor << 8 | CurrentOSServicePack) - >= (major << 16 | minor << 8 | reqMinServicePack)); -} - - -BOOL Is64BitOs () -{ -#ifdef _WIN64 - return TRUE; -#else - static BOOL isWow64 = FALSE; - static BOOL valid = FALSE; - typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS ) (HANDLE hProcess,PBOOL Wow64Process); - LPFN_ISWOW64PROCESS fnIsWow64Process; - - if (valid) - return isWow64; - - fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle(L"kernel32"), "IsWow64Process"); - - if (fnIsWow64Process != NULL) - if (!fnIsWow64Process (GetCurrentProcess(), &isWow64)) - isWow64 = FALSE; - - valid = TRUE; - return isWow64; -#endif -} - - -BOOL IsServerOS () -{ - OSVERSIONINFOEXW osVer; - osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); - GetVersionExW ((LPOSVERSIONINFOW) &osVer); - - return (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER); -} - - -// Returns TRUE, if the currently running operating system is installed in a hidden volume. If it's not, or if -// there's an error, returns FALSE. -BOOL IsHiddenOSRunning (void) -{ - static BOOL statusCached = FALSE; - static BOOL hiddenOSRunning; - - if (!statusCached) - { - try - { - hiddenOSRunning = BootEncryption (MainDlg).IsHiddenSystemRunning(); - } - catch (...) - { - hiddenOSRunning = FALSE; - } - - statusCached = TRUE; - } - - return hiddenOSRunning; -} - - -BOOL EnableWow64FsRedirection (BOOL enable) -{ - typedef BOOLEAN (__stdcall *Wow64EnableWow64FsRedirection_t) (BOOL enable); - Wow64EnableWow64FsRedirection_t wow64EnableWow64FsRedirection = (Wow64EnableWow64FsRedirection_t) GetProcAddress (GetModuleHandle (L"kernel32"), "Wow64EnableWow64FsRedirection"); - - if (!wow64EnableWow64FsRedirection) - return FALSE; - - return wow64EnableWow64FsRedirection (enable); -} - - -BOOL RestartComputer (void) -{ - TOKEN_PRIVILEGES tokenPrivil; - HANDLE hTkn; - - if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hTkn)) - { - return false; - } - - LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, &tokenPrivil.Privileges[0].Luid); - tokenPrivil.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - tokenPrivil.PrivilegeCount = 1; - - AdjustTokenPrivileges (hTkn, false, &tokenPrivil, 0, (PTOKEN_PRIVILEGES) NULL, 0); - if (GetLastError() != ERROR_SUCCESS) - { - CloseHandle(hTkn); - return false; - } - - if (!ExitWindowsEx (EWX_REBOOT, - SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED)) - { - CloseHandle(hTkn); - return false; - } - - CloseHandle(hTkn); - return true; -} - - -std::wstring GetWindowsEdition () -{ - wstring osname = L"win"; - - OSVERSIONINFOEXW osVer; - osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); - GetVersionExW ((LPOSVERSIONINFOW) &osVer); - - BOOL home = (osVer.wSuiteMask & VER_SUITE_PERSONAL); - BOOL server = (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER); - - HKEY hkey; - wchar_t productName[300] = {0}; - DWORD productNameSize = sizeof (productName); - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) - { - if (RegQueryValueEx (hkey, L"ProductName", 0, 0, (LPBYTE) &productName, &productNameSize) != ERROR_SUCCESS || productNameSize < 1) - productName[0] = 0; - - RegCloseKey (hkey); - } - - switch (nCurrentOS) - { - case WIN_2000: - osname += L"2000"; - break; - - case WIN_XP: - case WIN_XP64: - osname += L"xp"; - osname += home ? L"-home" : L"-pro"; - break; - - case WIN_SERVER_2003: - osname += L"2003"; - break; - - case WIN_VISTA: - osname += L"vista"; - break; - - case WIN_SERVER_2008: - osname += L"2008"; - break; - - case WIN_7: - osname += L"7"; - break; - - case WIN_SERVER_2008_R2: - osname += L"2008r2"; - break; - - default: - wstringstream s; - s << CurrentOSMajor << L"." << CurrentOSMinor; - osname += s.str(); - break; - } - - if (server) - osname += L"-server"; - - if (IsOSAtLeast (WIN_VISTA)) - { - if (home) - osname += L"-home"; - else if (wcsstr (productName, L"Standard") != 0) - osname += L"-standard"; - else if (wcsstr (productName, L"Professional") != 0) - osname += L"-pro"; - else if (wcsstr (productName, L"Business") != 0) - osname += L"-business"; - else if (wcsstr (productName, L"Enterprise") != 0) - osname += L"-enterprise"; - else if (wcsstr (productName, L"Datacenter") != 0) - osname += L"-datacenter"; - else if (wcsstr (productName, L"Ultimate") != 0) - osname += L"-ultimate"; - } - - if (GetSystemMetrics (SM_STARTER)) - osname += L"-starter"; - else if (wcsstr (productName, L"Basic") != 0) - osname += L"-basic"; - - if (Is64BitOs()) - osname += L"-x64"; - - if (CurrentOSServicePack > 0) - { - wstringstream s; - s << L"-sp" << CurrentOSServicePack; - osname += s.str(); - } - - return osname; -} - - -void Applink (char *dest, BOOL bSendOS, char *extraOutput) -{ - char url [MAX_URL_LENGTH]; - - ArrowWaitCursor (); - - // sprintf_s (url, sizeof (url), TC_APPLINK "%s%s&dest=%s", bSendOS ? ("&os=" + GetWindowsEdition()).c_str() : "", extraOutput, dest); - if (strcmp(dest, "donate") == 0) - { - StringCbCopyA (url, sizeof (url),"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5BCXVMTTNJDCY"); - } - else if (strcmp(dest, "main") == 0) - { - StringCbCopyA (url, sizeof (url),TC_HOMEPAGE); - } - else if (strcmp(dest,"localizations") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Language%20Packs"); - } - else if (strcmp(dest, "beginnerstutorial") == 0 || strcmp(dest,"tutorial") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Beginner%27s%20Tutorial"); - } - else if (strcmp(dest, "releasenotes") == 0 || strcmp(dest, "history") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Release%20Notes"); - } - else if (strcmp(dest, "hwacceleration") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Hardware%20Acceleration"); - } - else if (strcmp(dest, "parallelization") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Parallelization"); - } - else if (strcmp(dest, "help") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/documentation"); - } - else if (strcmp(dest, "keyfiles") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Keyfiles"); - } - else if (strcmp(dest, "introcontainer") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Creating%20New%20Volumes"); - } - else if (strcmp(dest, "introsysenc") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=System%20Encryption"); - } - else if (strcmp(dest, "hiddensysenc") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=VeraCrypt%20Hidden%20Operating%20System"); - } - else if (strcmp(dest, "sysencprogressinfo") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=System%20Encryption"); - } - else if (strcmp(dest, "hiddenvolume") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Hidden%20Volume"); - } - else if (strcmp(dest, "aes") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=AES"); - } - else if (strcmp(dest, "serpent") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Serpent"); - } - else if (strcmp(dest, "twofish") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Twofish"); - } - else if (strcmp(dest, "cascades") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Cascades"); - } - else if (strcmp(dest, "hashalgorithms") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Hash%20Algorithms"); - } - else if (strcmp(dest, "isoburning") == 0) - { - StringCbCopyA (url, sizeof (url),"https://cdburnerxp.se/en/home"); - } - else if (strcmp(dest, "sysfavorites") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=System%20Favorite%20Volumes"); - } - else if (strcmp(dest, "favorites") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Favorite%20Volumes"); - } - else if (strcmp(dest, "hiddenvolprotection") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Protection%20of%20Hidden%20Volumes"); - } - else if (strcmp(dest, "faq") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=FAQ"); - } - else if (strcmp(dest, "downloads") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Downloads"); - } - else if (strcmp(dest, "news") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=News"); - } - else if (strcmp(dest, "contact") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Contact"); - } - else if (strcmp(dest, "pim") == 0) - { - StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Personal%20Iterations%20Multiplier%20%28PIM%29"); - } - else - { - StringCbCopyA (url, sizeof (url),TC_APPLINK); - } - ShellExecuteA (NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); - - Sleep (200); - NormalCursor (); -} - - -wchar_t *RelativePath2Absolute (wchar_t *szFileName) -{ - if (szFileName[0] != L'\\' - && wcschr (szFileName, L':') == 0 - && 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")) - { - 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; -} - - -BYTE *MapResource (wchar_t *resourceType, int resourceId, PDWORD size) -{ - HGLOBAL hResL; - HRSRC hRes; - - hRes = FindResource (NULL, MAKEINTRESOURCE(resourceId), resourceType); - hResL = LoadResource (NULL, hRes); - - if (size != NULL) - *size = SizeofResource (NULL, hRes); - - return (BYTE *) LockResource (hResL); -} - - -void InconsistencyResolved (char *techInfo) -{ - wchar_t finalMsg[8024]; - - StringCbPrintfW (finalMsg, sizeof(finalMsg), GetString ("INCONSISTENCY_RESOLVED"), techInfo); - MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); -} - - -void ReportUnexpectedState (char *techInfo) -{ - wchar_t finalMsg[8024]; - - StringCbPrintfW (finalMsg, sizeof(finalMsg), GetString ("UNEXPECTED_STATE"), techInfo); - MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); -} - - -#ifndef SETUP - -int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password *password, int pkcs5_prf, int pim, BOOL truecryptMode, BOOL write, BOOL preserveTimestamps, BOOL useBackupHeader) -{ - int status = ERR_PARAMETER_INCORRECT; - int volumeType; - wchar_t szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; - wchar_t szDosDevice[TC_MAX_PATH]; - char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; - LARGE_INTEGER headerOffset; - DWORD dwResult; - DISK_GEOMETRY deviceGeometry; - - context->VolumeIsOpen = FALSE; - context->CryptoInfo = NULL; - context->HostFileHandle = INVALID_HANDLE_VALUE; - context->TimestampsValid = FALSE; - - CreateFullVolumePath (szDiskFile, sizeof(szDiskFile), volumePath, &context->IsDevice); - - if (context->IsDevice) - { - status = FakeDosNameForDevice (szDiskFile, szDosDevice, sizeof(szDosDevice), szCFDevice, sizeof(szCFDevice), FALSE); - if (status != 0) - return status; - - preserveTimestamps = FALSE; - - if (!GetDriveGeometry (volumePath, &deviceGeometry)) - { - status = ERR_OS_ERROR; - goto error; - } - } - else - StringCbCopyW (szCFDevice, sizeof(szCFDevice), szDiskFile); - - if (preserveTimestamps) - write = TRUE; - - context->HostFileHandle = CreateFile (szCFDevice, GENERIC_READ | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (context->HostFileHandle == INVALID_HANDLE_VALUE) - { - status = ERR_OS_ERROR; - goto error; - } - - if (context->IsDevice) - { - // Try to gain "raw" access to the partition in case there is a live filesystem on it (otherwise, - // the NTFS driver guards hidden sectors and prevents e.g. header backup restore after the user - // accidentally quick-formats a dismounted partition-hosted TrueCrypt volume as NTFS, etc.) - - DeviceIoControl (context->HostFileHandle, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwResult, NULL); - } - - context->VolumeIsOpen = TRUE; - - // Remember the container modification/creation date and time - if (!context->IsDevice && preserveTimestamps) - { - if (GetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime) == 0) - context->TimestampsValid = FALSE; - else - context->TimestampsValid = TRUE; - } - - // Determine host size - if (context->IsDevice) - { - PARTITION_INFORMATION diskInfo; - - if (GetPartitionInfo (volumePath, &diskInfo)) - { - context->HostSize = diskInfo.PartitionLength.QuadPart; - } - else - { - DISK_GEOMETRY driveInfo; - - if (!DeviceIoControl (context->HostFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL)) - { - status = ERR_OS_ERROR; - goto error; - } - - context->HostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; - } - - if (context->HostSize == 0) - { - status = ERR_VOL_SIZE_WRONG; - goto error; - } - } - else - { - LARGE_INTEGER fileSize; - if (!GetFileSizeEx (context->HostFileHandle, &fileSize)) - { - status = ERR_OS_ERROR; - goto error; - } - - 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)) - { - 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, truecryptMode, &context->CryptoInfo, NULL); - - if (status == ERR_PASSWORD_WRONG) - continue; // Try next volume type - - break; - } - - if (status == ERR_SUCCESS) - return status; - -error: - DWORD sysError = GetLastError (); - - CloseVolume (context); - - SetLastError (sysError); - return status; -} - - -void CloseVolume (OpenVolumeContext *context) -{ - if (!context->VolumeIsOpen) - return; - - if (context->HostFileHandle != INVALID_HANDLE_VALUE) - { - if (context->TimestampsValid) - SetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime); - - CloseHandle (context->HostFileHandle); - context->HostFileHandle = INVALID_HANDLE_VALUE; - } - - if (context->CryptoInfo) - { - crypto_close (context->CryptoInfo); - context->CryptoInfo = NULL; - } - - context->VolumeIsOpen = FALSE; -} - - -int ReEncryptVolumeHeader (HWND hwndDlg, char *buffer, BOOL bBoot, CRYPTO_INFO *cryptoInfo, Password *password, int pim, BOOL wipeMode) -{ - CRYPTO_INFO *newCryptoInfo = NULL; - - RandSetHashFunction (cryptoInfo->pkcs5); - - if (Randinit() != ERR_SUCCESS) - { - if (CryptoAPILastError == ERROR_SUCCESS) - return ERR_RAND_INIT_FAILED; - else - return ERR_CAPI_INIT_FAILED; - } - - UserEnrichRandomPool (NULL); - - int status = CreateVolumeHeaderInMemory (hwndDlg, bBoot, - buffer, - cryptoInfo->ea, - cryptoInfo->mode, - password, - cryptoInfo->pkcs5, - pim, - (char *) cryptoInfo->master_keydata, - &newCryptoInfo, - cryptoInfo->VolumeSize.Value, - cryptoInfo->hiddenVolume ? cryptoInfo->hiddenVolumeSize : 0, - cryptoInfo->EncryptedAreaStart.Value, - cryptoInfo->EncryptedAreaLength.Value, - cryptoInfo->RequiredProgramVersion, - cryptoInfo->HeaderFlags, - cryptoInfo->SectorSize, - wipeMode); - - if (newCryptoInfo != NULL) - crypto_close (newCryptoInfo); - - return status; -} - -#endif // !SETUP - - -BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) -{ - // GlobalMemoryStatusEx() cannot be used to determine if a paging file is active - - wchar_t data[65536]; - DWORD size = sizeof (data); - - if (IsPagingFileWildcardActive()) - return TRUE; - - if (ReadLocalMachineRegistryMultiString (L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", L"PagingFiles", data, &size) - && size > 24 && !checkNonWindowsPartitionsOnly) - return TRUE; - - if (!IsAdmin()) - AbortProcess ("UAC_INIT_ERROR"); - - for (wchar_t drive = L'C'; drive <= L'Z'; ++drive) - { - // Query geometry of the drive first to prevent "no medium" pop-ups - wstring drivePath = L"\\\\.\\X:"; - drivePath[4] = drive; - - if (checkNonWindowsPartitionsOnly) - { - wchar_t sysDir[MAX_PATH]; - if (GetSystemDirectory (sysDir, ARRAYSIZE (sysDir)) != 0 && towupper (sysDir[0]) == drive) - continue; - } - - HANDLE handle = CreateFile (drivePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (handle == INVALID_HANDLE_VALUE) - continue; - - DISK_GEOMETRY driveInfo; - DWORD dwResult; - - if (!DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL)) - { - CloseHandle (handle); - continue; - } - - CloseHandle (handle); - - // Test if a paging file exists and is locked by another process - wstring path = L"X:\\pagefile.sys"; - path[0] = drive; - - handle = CreateFile (path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - - if (handle != INVALID_HANDLE_VALUE) - CloseHandle (handle); - else if (GetLastError() == ERROR_SHARING_VIOLATION) - return TRUE; - } - - return FALSE; -} - - -BOOL IsPagingFileWildcardActive () -{ - wchar_t pagingFiles[65536]; - DWORD size = sizeof (pagingFiles); - wchar_t *mmKey = L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management"; - - if (!ReadLocalMachineRegistryString (mmKey, L"PagingFiles", pagingFiles, &size)) - { - size = sizeof (pagingFiles); - if (!ReadLocalMachineRegistryMultiString (mmKey, L"PagingFiles", pagingFiles, &size)) - size = 0; - } - - return size > 0 && wcsstr (pagingFiles, L"?:\\") == pagingFiles; -} - - -BOOL DisablePagingFile () -{ - wchar_t empty[] = { 0, 0 }; - return WriteLocalMachineRegistryMultiString (L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", L"PagingFiles", empty, sizeof (empty)); -} - - -std::wstring SingleStringToWide (const std::string &singleString) -{ - if (singleString.empty()) - return std::wstring(); - - WCHAR wbuf[65536]; - int wideLen = MultiByteToWideChar (CP_ACP, 0, singleString.c_str(), -1, wbuf, array_capacity (wbuf) - 1); - - // We don't throw exception here and only return empty string. - // All calls to this function use valid strings. - // throw_sys_if (wideLen == 0); - - wbuf[wideLen] = 0; - return wbuf; -} - - -std::wstring Utf8StringToWide (const std::string &utf8String) -{ - if (utf8String.empty()) - return std::wstring(); - - WCHAR wbuf[65536]; - int wideLen = MultiByteToWideChar (CP_UTF8, 0, utf8String.c_str(), -1, wbuf, array_capacity (wbuf) - 1); - throw_sys_if (wideLen == 0); - - wbuf[wideLen] = 0; - return wbuf; -} - - -std::string WideToUtf8String (const std::wstring &wideString) -{ - if (wideString.empty()) - return std::string(); - - char buf[65536]; - int len = WideCharToMultiByte (CP_UTF8, 0, wideString.c_str(), -1, buf, array_capacity (buf) - 1, NULL, NULL); - throw_sys_if (len == 0); - - buf[len] = 0; - return buf; -} - - -#ifndef SETUP - -BOOL CALLBACK SecurityTokenPasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - WORD lw = LOWORD (wParam); - static string *password; - - switch (msg) - { - case WM_INITDIALOG: - { - password = (string *) lParam; - LocalizeDialog (hwndDlg, "IDD_TOKEN_PASSWORD"); - - wchar_t s[1024]; - StringCbPrintfW (s, sizeof(s), GetString ("ENTER_TOKEN_PASSWORD"), Utf8StringToWide (password->c_str()).c_str()); - SetWindowTextW (GetDlgItem (hwndDlg, IDT_TOKEN_PASSWORD_INFO), s); - - SendMessage (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), EM_LIMITTEXT, SecurityToken::MaxPasswordLength, 0); - - SetForegroundWindow (hwndDlg); - SetFocus (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD)); - } - return 0; - - case WM_COMMAND: - if (lw == IDCANCEL || lw == IDOK) - { - if (lw == IDOK) - { - wchar_t passwordWide[SecurityToken::MaxPasswordLength + 1]; - - if (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), passwordWide, SecurityToken::MaxPasswordLength + 1) == 0) - { - handleWin32Error (hwndDlg, SRC_POS); - break; - } - - char passwordUtf8[SecurityToken::MaxPasswordLength + 1]; - - int len = WideCharToMultiByte (CP_UTF8, 0, passwordWide, -1, passwordUtf8, array_capacity (passwordUtf8) - 1, nullptr, nullptr); - passwordUtf8[len] = 0; - *password = passwordUtf8; - - burn (passwordWide, sizeof (passwordWide)); - burn (passwordUtf8, sizeof (passwordUtf8)); - } - - // Attempt to wipe password stored in the input field buffer - wchar_t tmp[SecurityToken::MaxPasswordLength+1]; - wmemset (tmp, 'X', SecurityToken::MaxPasswordLength); - tmp[SecurityToken::MaxPasswordLength] = 0; - SetWindowText (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), tmp); - - EndDialog (hwndDlg, lw); - } - return 1; - } - - return 0; -} - - -struct NewSecurityTokenKeyfileDlgProcParams -{ - CK_SLOT_ID SlotId; - string Name; -}; - -static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static NewSecurityTokenKeyfileDlgProcParams *newParams; - - WORD lw = LOWORD (wParam); - switch (msg) - { - case WM_INITDIALOG: - { - LocalizeDialog (hwndDlg, "IDD_NEW_TOKEN_KEYFILE"); - - newParams = (NewSecurityTokenKeyfileDlgProcParams *) lParam; - - WaitCursor(); - finally_do ({ NormalCursor(); }); - - list tokens; - - try - { - tokens = SecurityToken::GetAvailableTokens(); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - if (tokens.empty()) - { - Error ("NO_TOKENS_FOUND", hwndDlg); - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - foreach (const SecurityTokenInfo &token, tokens) - { - wstringstream tokenLabel; - tokenLabel << L"[" << token.SlotId << L"] " << token.Label; - - AddComboPair (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), tokenLabel.str().c_str(), token.SlotId); - } - - ComboBox_SetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), 0); - - SetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), Utf8StringToWide (newParams->Name).c_str()); - return 1; - } - - case WM_COMMAND: - switch (lw) - { - case IDOK: - { - int selectedToken = ComboBox_GetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN)); - if (selectedToken == CB_ERR) - { - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - newParams->SlotId = (CK_SLOT_ID) ComboBox_GetItemData (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), selectedToken); - - wchar_t name[1024]; - if (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), name, array_capacity (name)) != 0) - { - try - { - newParams->Name = WideToUtf8String (name); - } - catch (...) { } - } - - EndDialog (hwndDlg, IDOK); - return 1; - } - - case IDCANCEL: - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - - if (HIWORD (wParam) == EN_CHANGE) - { - wchar_t name[2]; - EnableWindow (GetDlgItem (hwndDlg, IDOK), (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), name, array_capacity (name)) != 0)); - return 1; - } - } - - return 0; -} - - -static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector &keyfiles) -{ - HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); - LVITEMW lvItem; - int line = 0; - - ListView_DeleteAllItems (tokenListControl); - - foreach (const SecurityTokenKeyfile &keyfile, keyfiles) - { - memset (&lvItem, 0, sizeof(lvItem)); - lvItem.mask = LVIF_TEXT; - lvItem.iItem = line++; - - wstringstream s; - s << keyfile.SlotId; - - ListItemAdd (tokenListControl, lvItem.iItem, (wchar_t *) s.str().c_str()); - ListSubItemSet (tokenListControl, lvItem.iItem, 1, (wchar_t *) keyfile.Token.Label.c_str()); - ListSubItemSet (tokenListControl, lvItem.iItem, 2, (wchar_t *) keyfile.Id.c_str()); - } - - BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); - EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); - EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); -} - - -static list SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector &keyfiles) -{ - HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); - list selectedKeyfiles; - - int itemId = -1; - while ((itemId = ListView_GetNextItem (tokenListControl, itemId, LVIS_SELECTED)) != -1) - { - selectedKeyfiles.push_back (keyfiles[itemId]); - } - - return selectedKeyfiles; -} - - -BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static list *selectedTokenKeyfiles; - static vector keyfiles; - - WORD lw = LOWORD (wParam); - - switch (msg) - { - case WM_INITDIALOG: - { - selectedTokenKeyfiles = (list *) lParam; - - LVCOLUMNW LvCol; - HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); - - LocalizeDialog (hwndDlg, selectedTokenKeyfiles ? "SELECT_TOKEN_KEYFILES" : "IDD_TOKEN_KEYFILES"); - - SendMessage (tokenListControl,LVM_SETEXTENDEDLISTVIEWSTYLE, 0, - LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP - ); - - memset (&LvCol, 0, sizeof(LvCol)); - LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; - LvCol.pszText = GetString ("TOKEN_SLOT_ID"); - LvCol.cx = CompensateXDPI (40); - LvCol.fmt = LVCFMT_CENTER; - SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 1, (LPARAM)&LvCol); - - LvCol.pszText = GetString ("TOKEN_NAME"); - LvCol.cx = CompensateXDPI (128); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 2, (LPARAM)&LvCol); - - LvCol.pszText = GetString ("TOKEN_DATA_OBJECT_LABEL"); - LvCol.cx = CompensateXDPI (195); - LvCol.fmt = LVCFMT_LEFT; - SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 3, (LPARAM)&LvCol); - - keyfiles.clear(); - - try - { - WaitCursor(); - finally_do ({ NormalCursor(); }); - - keyfiles = SecurityToken::GetAvailableKeyfiles(); - } - catch (UserAbort&) - { - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - catch (Exception &e) - { - e.Show (hwndDlg); - - if (keyfiles.empty()) - { - EndDialog (hwndDlg, IDCANCEL); - return 1; - } - } - - SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); - return 1; - } - - case WM_COMMAND: - case WM_NOTIFY: - if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE) - { - if (selectedTokenKeyfiles) - { - foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) - { - selectedTokenKeyfiles->push_back (SecurityTokenKeyfilePath (keyfile)); - } - } - - EndDialog (hwndDlg, IDOK); - return 1; - } - - if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) - { - BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); - EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); - EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); - 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)) - { - DWORD keyfileSize; - byte *keyfileData = (byte *) 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 keyfileDataVector (keyfileSize); - memcpy (&keyfileDataVector.front(), keyfileData, keyfileSize); - - try - { - WaitCursor(); - finally_do ({ NormalCursor(); }); - - SecurityToken::CreateKeyfile (newParams.SlotId, keyfileDataVector, newParams.Name); - - keyfiles = SecurityToken::GetAvailableKeyfiles(); - 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 SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) - { - wchar_t keyfilePath[TC_MAX_PATH]; - - if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE, NULL)) - break; - - { - WaitCursor(); - finally_do ({ NormalCursor(); }); - - vector keyfileData; - - SecurityToken::GetKeyfileData (keyfile, keyfileData); - - if (keyfileData.empty()) - { - SetLastError (ERROR_HANDLE_EOF); - handleWin32Error (hwndDlg, SRC_POS); - return 1; - } - - finally_do_arg (vector *, &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 SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) - { - SecurityToken::DeleteKeyfile (keyfile); - } - - keyfiles = SecurityToken::GetAvailableKeyfiles(); - SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); - } - catch (Exception &e) - { - e.Show (hwndDlg); - } - - return 1; - } - } - } - return 0; - } - return 0; -} - - -BOOL InitSecurityTokenLibrary (HWND hwndDlg) -{ - if (SecurityTokenLibraryPath[0] == 0) - { - Error ("NO_PKCS11_MODULE_SPECIFIED", hwndDlg); - return FALSE; - } - - struct PinRequestHandler : public GetPinFunctor - { - HWND m_hwnd; - PinRequestHandler(HWND hwnd) : m_hwnd(hwnd) {} - virtual void operator() (string &str) - { - HWND hParent = IsWindow (m_hwnd)? m_hwnd : GetActiveWindow(); - if (!hParent) - hParent = GetForegroundWindow (); - if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_PASSWORD), hParent, (DLGPROC) SecurityTokenPasswordDlgProc, (LPARAM) &str) == IDCANCEL) - throw UserAbort (SRC_POS); - - if (hCursor != NULL) - SetCursor (hCursor); - } - }; - - struct WarningHandler : public SendExceptionFunctor - { - HWND m_hwnd; - WarningHandler(HWND hwnd) : m_hwnd(hwnd) {} - virtual void operator() (const Exception &e) - { - HWND hParent = IsWindow (m_hwnd)? m_hwnd : GetActiveWindow(); - if (!hParent) - hParent = GetForegroundWindow (); - e.Show (hParent); - } - }; - - try - { - SecurityToken::InitLibrary (SecurityTokenLibraryPath, auto_ptr (new PinRequestHandler(MainDlg)), auto_ptr (new WarningHandler(MainDlg))); - } - catch (Exception &e) - { - e.Show (hwndDlg); - Error ("PKCS11_MODULE_INIT_FAILED", hwndDlg); - return FALSE; - } - - return TRUE; -} - -#endif // !SETUP - -std::vector GetAvailableHostDevices (bool noDeviceProperties, bool singleList, bool noFloppy, bool detectUnencryptedFilesystems) -{ - vector devices; - size_t dev0; - - for (int devNumber = 0; devNumber < MAX_HOST_DRIVE_NUMBER; devNumber++) - { - for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++) - { - wstringstream strm; - strm << L"\\Device\\Harddisk" << devNumber << L"\\Partition" << partNumber; - wstring devPathStr (strm.str()); - const wchar_t *devPath = devPathStr.c_str(); - - OPEN_TEST_STRUCT openTest = {0}; - if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems && partNumber != 0, FALSE, NULL)) - { - if (partNumber == 0) - break; - - continue; - } - - HostDevice device; - device.SystemNumber = devNumber; - device.Path = devPath; - - PARTITION_INFORMATION partInfo; - - if (GetPartitionInfo (devPath, &partInfo)) - { - device.Bootable = partInfo.BootIndicator ? true : false; - device.Size = partInfo.PartitionLength.QuadPart; - } - else - { - // retrieve size using DISK_GEOMETRY - DISK_GEOMETRY deviceGeometry = {0}; - if ( GetDriveGeometry (devPath, &deviceGeometry) - || ((partNumber == 0) && GetPhysicalDriveGeometry (devNumber, &deviceGeometry)) - ) - { - device.Size = deviceGeometry.Cylinders.QuadPart * (LONGLONG) deviceGeometry.BytesPerSector - * (LONGLONG) deviceGeometry.SectorsPerTrack * (LONGLONG) deviceGeometry.TracksPerCylinder; - } - } - - device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false; - - if (!noDeviceProperties) - { - DISK_GEOMETRY geometry; - - int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) devPathStr.c_str()); - - if (driveNumber >= 0) - { - device.MountPoint += (wchar_t) (driveNumber + L'A'); - device.MountPoint += L":"; - - wchar_t name[64]; - if (GetDriveLabel (driveNumber, name, sizeof (name))) - device.Name = name; - - if (GetSystemDriveLetter() == L'A' + driveNumber) - device.ContainsSystem = true; - } - - if (partNumber == 0 && GetDriveGeometry (devPath, &geometry)) - device.Removable = (geometry.MediaType == RemovableMedia); - } - - if (partNumber == 0) - { - devices.push_back (device); - dev0 = devices.size() - 1; - } - else - { - // System creates a virtual partition1 for some storage devices without - // partition table. We try to detect this case by comparing sizes of - // partition0 and partition1. If they match, no partition of the device - // is displayed to the user to avoid confusion. Drive letter assigned by - // system to partition1 is assigned partition0 - if (partNumber == 1 && devices[dev0].Size == device.Size) - { - devices[dev0].IsVirtualPartition = true; - devices[dev0].MountPoint = device.MountPoint; - devices[dev0].Name = device.Name; - devices[dev0].Path = device.Path; - devices[dev0].HasUnencryptedFilesystem = device.HasUnencryptedFilesystem; - break; - } - - device.IsPartition = true; - device.SystemNumber = partNumber; - device.Removable = devices[dev0].Removable; - - if (device.ContainsSystem) - devices[dev0].ContainsSystem = true; - - if (singleList) - devices.push_back (device); - - devices[dev0].Partitions.push_back (device); - } - } - } - - // Vista does not create partition links for dynamic volumes so it is necessary to scan \\Device\\HarddiskVolumeX devices - if (CurrentOSMajor >= 6) - { - for (int devNumber = 0; devNumber < 256; devNumber++) - { - wstringstream strm; - strm << L"\\Device\\HarddiskVolume" << devNumber; - wstring devPathStr (strm.str()); - const wchar_t *devPath = devPathStr.c_str(); - - OPEN_TEST_STRUCT openTest = {0}; - if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems, FALSE, NULL)) - continue; - - DISK_PARTITION_INFO_STRUCT info; - if (GetDeviceInfo (devPath, &info) && info.IsDynamic) - { - HostDevice device; - device.DynamicVolume = true; - device.IsPartition = true; - device.SystemNumber = devNumber; - device.Path = devPath; - device.Size = info.partInfo.PartitionLength.QuadPart; - device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false; - - if (!noDeviceProperties) - { - int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) devPathStr.c_str()); - - if (driveNumber >= 0) - { - device.MountPoint += (wchar_t) (driveNumber + L'A'); - device.MountPoint += L":"; - - wchar_t name[64]; - if (GetDriveLabel (driveNumber, name, sizeof (name))) - device.Name = name; - - if (GetSystemDriveLetter() == L'A' + driveNumber) - device.ContainsSystem = true; - } - } - - devices.push_back (device); - } - } - } - - return devices; -} - -wstring FindDeviceByVolumeID (const BYTE volumeID [VOLUME_ID_SIZE]) -{ - /* if it is already mounted, get the real path name used for mounting */ - MOUNT_LIST_STRUCT mlist; - DWORD dwResult; - - memset (&mlist, 0, sizeof (mlist)); - DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, - sizeof (mlist), &mlist, sizeof (mlist), &dwResult, - NULL); - - for (int i=0 ; i < 26; i++) - { - if (0 == memcmp (mlist.volumeID[i], volumeID, VOLUME_ID_SIZE)) - return mlist.wszVolume[i]; - } - - /* not mounted. Look for it in the local drives*/ - for (int devNumber = 0; devNumber < MAX_HOST_DRIVE_NUMBER; devNumber++) - { - for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++) - { - wstringstream strm; - strm << L"\\Device\\Harddisk" << devNumber << L"\\Partition" << partNumber; - wstring devPathStr (strm.str()); - const wchar_t *devPath = devPathStr.c_str(); - - OPEN_TEST_STRUCT openTest = {0}; - if (!OpenDevice (devPath, &openTest, FALSE, TRUE, volumeID)) - { - continue; - } - - if (openTest.VolumeIDMatched) - return devPath; - } - } - - return L""; -} - -BOOL FileHasReadOnlyAttribute (const wchar_t *path) -{ - DWORD attributes = GetFileAttributes (path); - return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_READONLY) != 0; -} - - -BOOL IsFileOnReadOnlyFilesystem (const wchar_t *path) -{ - wchar_t root[MAX_PATH]; - if (!GetVolumePathName (path, root, ARRAYSIZE (root))) - return FALSE; - - 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 BufferContainsString (const byte *buffer, size_t bufferSize, const char *str) -{ - size_t strLen = strlen (str); - - if (bufferSize < strLen) - return FALSE; - - bufferSize -= strLen; - - for (size_t i = 0; i < bufferSize; ++i) - { - if (memcmp (buffer + i, str, strLen) == 0) - return TRUE; - } - - return FALSE; -} - - -#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 }; - - switch (AskMultiChoice ((void **) multiChoiceStr, FALSE, hwndDlg)) - { - case 1: - RemoveNonSysInPlaceEncNotifications(); - Warning ("NONSYS_INPLACE_ENC_NOTIFICATION_REMOVAL_NOTE", hwndDlg); - break; - - default: - // NOP - break; - } - - return IDNO; -} - -#endif // !SETUP - - -BOOL RemoveDeviceWriteProtection (HWND hwndDlg, wchar_t *devicePath) -{ - int driveNumber; - int partitionNumber; - - wchar_t temp[MAX_PATH*2]; - wchar_t cmdBatch[MAX_PATH*2]; - wchar_t diskpartScript[MAX_PATH*2]; - - if (swscanf (devicePath, L"\\Device\\Harddisk%d\\Partition%d", &driveNumber, &partitionNumber) != 2) - return FALSE; - - if (GetTempPath (ARRAYSIZE (temp), temp) == 0) - return FALSE; - - StringCbPrintfW (cmdBatch, sizeof (cmdBatch), L"%s\\VeraCrypt_Write_Protection_Removal.cmd", temp); - StringCbPrintfW (diskpartScript, sizeof (diskpartScript), L"%s\\VeraCrypt_Write_Protection_Removal.diskpart", temp); - - FILE *f = _wfopen (cmdBatch, L"w"); - if (!f) - { - handleWin32Error (hwndDlg, SRC_POS); - return FALSE; - } - - fwprintf (f, L"@diskpart /s \"%s\"\n@pause\n@del \"%s\" \"%s\"", diskpartScript, diskpartScript, cmdBatch); - - CheckFileStreamWriteErrors (hwndDlg, f, cmdBatch); - fclose (f); - - f = _wfopen (diskpartScript, L"w"); - if (!f) - { - handleWin32Error (hwndDlg, SRC_POS); - DeleteFile (cmdBatch); - return FALSE; - } - - fwprintf (f, L"select disk %d\nattributes disk clear readonly\n", driveNumber); - - if (partitionNumber != 0) - fwprintf (f, L"select partition %d\nattributes volume clear readonly\n", partitionNumber); - - fwprintf (f, L"exit\n"); - - CheckFileStreamWriteErrors (hwndDlg, f, diskpartScript); - fclose (f); - - ShellExecute (NULL, (!IsAdmin() && IsUacSupported()) ? L"runas" : L"open", cmdBatch, NULL, NULL, SW_SHOW); - - return TRUE; -} - - -static LRESULT CALLBACK EnableElevatedCursorChangeWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return DefWindowProcW (hWnd, message, wParam, lParam); -} - - -void EnableElevatedCursorChange (HWND parent) -{ - // Create a transparent window to work around a UAC issue preventing change of the cursor - if (UacElevated) - { - const wchar_t *className = L"VeraCryptEnableElevatedCursorChange"; - WNDCLASSEXW winClass; - HWND hWnd; - - memset (&winClass, 0, sizeof (winClass)); - winClass.cbSize = sizeof (WNDCLASSEX); - winClass.lpfnWndProc = (WNDPROC) EnableElevatedCursorChangeWndProc; - winClass.hInstance = hInst; - winClass.lpszClassName = className; - RegisterClassExW (&winClass); - - hWnd = CreateWindowExW (WS_EX_TOOLWINDOW | WS_EX_LAYERED, className, L"VeraCrypt UAC", 0, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), parent, NULL, hInst, NULL); - if (hWnd) - { - SetLayeredWindowAttributes (hWnd, 0, 1, LWA_ALPHA); - ShowWindow (hWnd, SW_SHOWNORMAL); - - DestroyWindow (hWnd); - } - UnregisterClassW (className, hInst); - } -} - - -BOOL DisableFileCompression (HANDLE file) -{ - USHORT format; - DWORD bytesOut; - - if (!DeviceIoControl (file, FSCTL_GET_COMPRESSION, NULL, 0, &format, sizeof (format), &bytesOut, NULL)) - return FALSE; - - if (format == COMPRESSION_FORMAT_NONE) - return TRUE; - - format = COMPRESSION_FORMAT_NONE; - return DeviceIoControl (file, FSCTL_SET_COMPRESSION, &format, sizeof (format), NULL, 0, &bytesOut, NULL); -} - - -BOOL VolumePathExists (const wchar_t *volumePath) -{ - OPEN_TEST_STRUCT openTest = {0}; - wchar_t upperCasePath[TC_MAX_PATH + 1]; - - UpperCaseCopy (upperCasePath, sizeof(upperCasePath), volumePath); - - if (wcsstr (upperCasePath, L"\\DEVICE\\") == upperCasePath) - return OpenDevice (volumePath, &openTest, FALSE, FALSE, NULL); - - 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; - } - - return TRUE; -} - - -std::wstring VolumeGuidPathToDevicePath (std::wstring volumeGuidPath) -{ - if (volumeGuidPath.find (L"\\\\?\\") == 0) - volumeGuidPath = volumeGuidPath.substr (4); - - if (volumeGuidPath.find (L"Volume{") != 0 || volumeGuidPath.rfind (L"}\\") != volumeGuidPath.size() - 2) - return wstring(); - - wchar_t volDevPath[TC_MAX_PATH]; - if (QueryDosDevice (volumeGuidPath.substr (0, volumeGuidPath.size() - 1).c_str(), volDevPath, TC_MAX_PATH) == 0) - return wstring(); - - wstring partitionPath = HarddiskVolumePathToPartitionPath (volDevPath); - - return partitionPath.empty() ? volDevPath : partitionPath; -} - - -std::wstring HarddiskVolumePathToPartitionPath (const std::wstring &harddiskVolumePath) -{ - for (int driveNumber = 0; driveNumber < MAX_HOST_DRIVE_NUMBER; driveNumber++) - { - for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++) - { - wchar_t partitionPath[TC_MAX_PATH]; - StringCchPrintfW (partitionPath, ARRAYSIZE (partitionPath), L"\\Device\\Harddisk%d\\Partition%d", driveNumber, partNumber); - - wchar_t resolvedPath[TC_MAX_PATH]; - if (ResolveSymbolicLink (partitionPath, resolvedPath, sizeof(resolvedPath))) - { - if (harddiskVolumePath == resolvedPath) - return partitionPath; - } - else if (partNumber == 0) - break; - } - } - - return wstring(); -} - - -BOOL IsApplicationInstalled (const wchar_t *appName, BOOL b32bitApp) -{ - const wchar_t *uninstallRegName = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; - BOOL installed = FALSE; - HKEY unistallKey; - LONG res = RegOpenKeyEx (HKEY_LOCAL_MACHINE, uninstallRegName, 0, KEY_READ | (b32bitApp? KEY_WOW64_32KEY: KEY_WOW64_64KEY), &unistallKey); - if (res != ERROR_SUCCESS) - { - SetLastError (res); - return FALSE; - } - - wchar_t regName[1024]; - DWORD regNameSize = sizeof (regName); - DWORD index = 0; - while (RegEnumKeyEx (unistallKey, index++, regName, ®NameSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) - { - if (wcsstr (regName, L"{") == regName) - { - regNameSize = sizeof (regName); - if (!ReadLocalMachineRegistryStringNonReflected ((wstring (uninstallRegName) + L"\\" + regName).c_str(), L"DisplayName", regName, ®NameSize, b32bitApp)) - regName[0] = 0; - } - - if (_wcsicmp (regName, appName) == 0) - { - installed = TRUE; - break; - } - - regNameSize = sizeof (regName); - } - - RegCloseKey (unistallKey); - return installed; -} - - -std::wstring FindLatestFileOrDirectory (const std::wstring &directory, const wchar_t *namePattern, bool findDirectory, bool findFile) -{ - wstring name; - ULARGE_INTEGER latestTime; - latestTime.QuadPart = 0; - WIN32_FIND_DATA findData; - - HANDLE find = FindFirstFile ((directory + L"\\" + namePattern).c_str(), &findData); - if (find != INVALID_HANDLE_VALUE) - { - do - { - if (wcscmp (findData.cFileName, L".") == 0 || wcscmp (findData.cFileName, L"..") == 0) - continue; - - ULARGE_INTEGER writeTime; - writeTime.LowPart = findData.ftLastWriteTime.dwLowDateTime; - writeTime.HighPart = findData.ftLastWriteTime.dwHighDateTime; - - if ((!findFile && !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - || (!findDirectory && (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))) - continue; - - if (latestTime.QuadPart < writeTime.QuadPart) - { - latestTime = writeTime; - name = findData.cFileName; - } - } - while (FindNextFile (find, &findData)); - - FindClose (find); - } - - if (name.empty()) - return name; - - return wstring (directory) + L"\\" + name; -} - -int GetPim (HWND hwndDlg, UINT ctrlId) -{ - int pim = 0; - HWND hCtrl = GetDlgItem (hwndDlg, ctrlId); - if (IsWindowEnabled (hCtrl) && IsWindowVisible (hCtrl)) - { - wchar_t szTmp[MAX_PIM + 1] = {0}; - if (GetDlgItemText (hwndDlg, ctrlId, szTmp, MAX_PIM + 1) > 0) - { - wchar_t* endPtr = NULL; - pim = wcstol(szTmp, &endPtr, 10); - if (pim < 0 || endPtr == szTmp || !endPtr || *endPtr != L'\0') - pim = 0; - } - } - return pim; -} - -void SetPim (HWND hwndDlg, UINT ctrlId, int pim) -{ - if (pim > 0) - { - wchar_t szTmp[MAX_PIM + 1]; - StringCbPrintfW (szTmp, sizeof(szTmp), L"%d", pim); - SetDlgItemText (hwndDlg, ctrlId, szTmp); - } - else - SetDlgItemText (hwndDlg, ctrlId, L""); -} - -BOOL GetPassword (HWND hwndDlg, UINT ctrlID, char* passValue, int bufSize, BOOL bShowError) -{ - wchar_t tmp [MAX_PASSWORD + 1]; - int utf8Len; - BOOL bRet = FALSE; - - GetWindowText (GetDlgItem (hwndDlg, ctrlID), tmp, ARRAYSIZE (tmp)); - utf8Len = WideCharToMultiByte (CP_UTF8, 0, tmp, -1, passValue, bufSize, NULL, NULL); - burn (tmp, sizeof (tmp)); - if (utf8Len > 0) - { - bRet = TRUE; - } - else - { - passValue [0] = 0; - if (bShowError) - { - SetFocus (GetDlgItem(hwndDlg, ctrlID)); - if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) - Error ("PASSWORD_UTF8_TOO_LONG", hwndDlg); - else - Error ("PASSWORD_UTF8_INVALID", hwndDlg); - } - } - - return bRet; -} - -void SetPassword (HWND hwndDlg, UINT ctrlID, char* passValue) -{ - wchar_t tmp [MAX_PASSWORD + 1] = {0}; - MultiByteToWideChar (CP_UTF8, 0, passValue, -1, tmp, MAX_PASSWORD + 1); - SetWindowText ( GetDlgItem (hwndDlg, ctrlID), tmp); - burn (tmp, sizeof (tmp)); -} - -void HandleShowPasswordFieldAction (HWND hwndDlg, UINT checkBoxId, UINT edit1Id, UINT edit2Id) -{ - if ((EditPasswordChar == 0) && GetCheckBox (hwndDlg, checkBoxId)) - { - EditPasswordChar = (WCHAR) SendMessageW (GetDlgItem (hwndDlg, edit1Id), EM_GETPASSWORDCHAR, 0, 0); - } - - 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.Close(); - - HINF hInf = SetupOpenInfFileWFn (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); }); - - throw_sys_if (!SetupInstallFromInfSectionWFn (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); -} - -LSTATUS DeleteRegistryKey (HKEY hKey, LPCTSTR keyName) -{ - return SHDeleteKeyWFn(hKey, keyName); -} - -HIMAGELIST CreateImageList(int cx, int cy, UINT flags, int cInitial, int cGrow) -{ - return ImageList_CreateFn(cx, cy, flags, cInitial, cGrow); -} - -int AddBitmapToImageList(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask) -{ - return ImageList_AddFn(himl, hbmImage, hbmMask); -} - -HRESULT VCStrDupW(LPCWSTR psz, LPWSTR *ppwsz) -{ - return SHStrDupWFn (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; - - SendMessage (hProgress, PBM_SETSTATE, state, 0); - } - - SendMessage (hProgress, PBM_SETPOS, - (WPARAM) (*pdwEntropy), - 0); - } -} - -void AllowMessageInUIPI (UINT msg) -{ - if (ChangeWindowMessageFilterFn) - { - ChangeWindowMessageFilterFn (msg, MSGFLT_ADD); - } -} - -BOOL IsRepeatedByteArray (byte value, const byte* 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; -} - -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 arr; - if ( (pathLen == (3 + 2*VOLUME_ID_SIZE)) - && HexWideStringToArray (pathValue + 3, arr) - && (arr.size() == VOLUME_ID_SIZE) - ) - { - std::wstring devicePath = FindDeviceByVolumeID (&arr[0]); - 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; -} - -BOOL CopyTextToClipboard (LPCWSTR txtValue) -{ - size_t txtLen = wcslen(txtValue); - HGLOBAL hdst; - LPWSTR dst; - BOOL bRet = FALSE; - - // Allocate string for cwd - hdst = GlobalAlloc(GMEM_MOVEABLE, (txtLen + 1) * sizeof(WCHAR)); - if (hdst) - { - dst = (LPWSTR)GlobalLock(hdst); - wmemcpy(dst, txtValue, txtLen + 1); - GlobalUnlock(hdst); - - if (OpenClipboard(NULL)) - { - EmptyClipboard(); - SetClipboardData(CF_UNICODETEXT, hdst); - CloseClipboard(); - } - } - - return bRet; -} +/* + 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-2016 IDRIX + and are governed by the Apache License 2.0 the full text of which is + contained in the file License.txt included in VeraCrypt binary and source + code distribution packages. */ + +#include "Tcdefs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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" + +#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 + +using namespace VeraCrypt; + +LONG DriverVersion; + +char *LastDialogId; +wchar_t szHelpFile[TC_MAX_PATH]; +wchar_t szHelpFile2[TC_MAX_PATH]; +wchar_t SecurityTokenLibraryPath[TC_MAX_PATH]; + +HFONT hFixedDigitFont = NULL; +HFONT hBoldFont = NULL; +HFONT hTitleFont = NULL; +HFONT hFixedFont = NULL; + +HFONT hUserFont = NULL; +HFONT hUserUnderlineFont = NULL; +HFONT hUserBoldFont = NULL; +HFONT hUserUnderlineBoldFont = NULL; + +HFONT WindowTitleBarFont; + +WCHAR EditPasswordChar = 0; + +int ScreenDPI = USER_DEFAULT_SCREEN_DPI; +double DPIScaleFactorX = 1; +double DPIScaleFactorY = 1; +double DlgAspectRatio = 1; + +HWND MainDlg = NULL; +wchar_t *lpszTitle = NULL; + +BOOL Silent = FALSE; +BOOL bPreserveTimestamp = TRUE; +BOOL bShowDisconnectedNetworkDrives = FALSE; +BOOL bHideWaitingDialog = FALSE; +BOOL bCmdHideWaitingDialog = FALSE; +BOOL bCmdHideWaitingDialogValid = FALSE; +BOOL bStartOnLogon = FALSE; +BOOL bMountDevicesOnLogon = FALSE; +BOOL bMountFavoritesOnLogon = FALSE; + +BOOL bHistory = FALSE; + +// Status of detection of hidden sectors (whole-system-drive encryption). +// 0 - Unknown/undetermined/completed, 1: Detection is or was in progress (but did not complete e.g. due to system crash). +int HiddenSectorDetectionStatus = 0; + +OSVersionEnum nCurrentOS = WIN_UNKNOWN; +int CurrentOSMajor = 0; +int CurrentOSMinor = 0; +int CurrentOSServicePack = 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; + +BOOL IgnoreWmDeviceChange = FALSE; +BOOL DeviceChangeBroadcastDisabled = FALSE; +BOOL LastMountedVolumeDirty; +BOOL MountVolumesAsSystemFavorite = FALSE; +BOOL FavoriteMountOnArrivalInProgress = FALSE; +BOOL MultipleMountOperationInProgress = 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; + +HINSTANCE hInst = NULL; +HCURSOR hCursor = NULL; + +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; + +#define FREE_DLL(h) if (h) { FreeLibrary (h); h = NULL;} + +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); + +// ChangeWindowMessageFilter +typedef BOOL (WINAPI *ChangeWindowMessageFilterPtr) (UINT, DWORD); + +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; +ChangeWindowMessageFilterPtr ChangeWindowMessageFilterFn = NULL; + +/* 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 +{ + BENCHMARK_SORT_BY_NAME = 0, + BENCHMARK_SORT_BY_SPEED +}; + +typedef struct +{ + int id; + wchar_t name[100]; + unsigned __int64 encSpeed; + unsigned __int64 decSpeed; + unsigned __int64 meanBytesPerSec; +} BENCHMARK_REC; + +BENCHMARK_REC benchmarkTable [BENCHMARK_MAX_ITEMS]; +int benchmarkTotalItems = 0; +int benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; +int benchmarkLastBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; +int benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED; +LARGE_INTEGER benchmarkPerformanceFrequency; + +#endif // #ifndef SETUP + + +typedef struct +{ + void *strings; + BOOL bold; + +} MULTI_CHOICE_DLGPROC_PARAMS; + + +void cleanup () +{ + /* Cleanup the GDI fonts */ + if (hFixedFont != NULL) + DeleteObject (hFixedFont); + if (hFixedDigitFont != NULL) + DeleteObject (hFixedDigitFont); + if (hBoldFont != NULL) + DeleteObject (hBoldFont); + if (hTitleFont != NULL) + DeleteObject (hTitleFont); + if (hUserFont != NULL) + DeleteObject (hUserFont); + if (hUserUnderlineFont != NULL) + DeleteObject (hUserUnderlineFont); + if (hUserBoldFont != NULL) + DeleteObject (hUserBoldFont); + if (hUserUnderlineBoldFont != NULL) + DeleteObject (hUserUnderlineBoldFont); + + /* Cleanup our dialog class */ + if (hDlgClass) + UnregisterClassW (TC_DLG_CLASS, hInst); + if (hSplashClass) + UnregisterClassW (TC_SPLASH_CLASS, hInst); + + /* Close the device driver handle */ + if (hDriver != INVALID_HANDLE_VALUE) + { + // Unload driver mode if possible (non-install mode) + if (IsNonInstallMode ()) + { + // If a dismount was forced in the lifetime of the driver, Windows may later prevent it to be loaded again from + // the same path. Therefore, the driver will not be unloaded even though it was loaded in non-install mode. + int driverUnloadDisabled; + DWORD dwResult; + + if (!DeviceIoControl (hDriver, TC_IOCTL_IS_DRIVER_UNLOAD_DISABLED, NULL, 0, &driverUnloadDisabled, sizeof (driverUnloadDisabled), &dwResult, NULL)) + driverUnloadDisabled = 0; + + if (!driverUnloadDisabled) + DriverUnload (); + else + { + CloseHandle (hDriver); + hDriver = INVALID_HANDLE_VALUE; + } + } + else + { + CloseHandle (hDriver); + hDriver = INVALID_HANDLE_VALUE; + } + } + + if (ConfigBuffer != NULL) + { + free (ConfigBuffer); + ConfigBuffer = NULL; + } + + CoUninitialize (); + + CloseSysEncMutex (); + +#ifndef SETUP + try + { + if (SecurityToken::IsInitialized()) + SecurityToken::CloseLibrary(); + } + catch (...) { } + + EncryptionThreadPoolStop(); +#endif + + DeleteCriticalSection (&csWNetCalls); +} + + +void LowerCaseCopy (wchar_t *lpszDest, const wchar_t *lpszSource) +{ + size_t i = wcslen (lpszSource) + 1; + + lpszDest[i - 1] = 0; + while (--i > 0) + { + lpszDest[i - 1] = (wchar_t) towlower (lpszSource[i - 1]); + } + +} + +void UpperCaseCopy (wchar_t *lpszDest, size_t cbDest, const wchar_t *lpszSource) +{ + if (lpszDest && cbDest) + { + size_t i = wcslen (lpszSource); + if (i >= cbDest) + i = cbDest - 1; + + lpszDest[i] = 0; + i++; + while (--i > 0) + { + lpszDest[i - 1] = (wchar_t) towupper (lpszSource[i - 1]); + } + } +} + + +std::wstring ToUpperCase (const std::wstring &str) +{ + wstring u; + foreach (wchar_t c, str) + { + u += (wchar_t) towupper (c); + } + + return u; +} + +size_t TrimWhiteSpace(wchar_t *str) +{ + wchar_t *end, *ptr = str; + size_t out_size; + + if(!str || *str == 0) + return 0; + + // Trim leading space + while(iswspace(*ptr)) ptr++; + + if(*ptr == 0) // All spaces? + { + *str = 0; + return 0; + } + + // Trim trailing space + end = str + wcslen(str) - 1; + while(end > ptr && iswspace(*end)) end--; + end++; + + // Set output size to trimmed string length + out_size = (end - ptr); + + // Copy trimmed string and add null terminator + wmemmove(str, ptr, out_size); + str[out_size] = 0; + + return out_size; +} + +// check the validity of a file name +BOOL IsValidFileName(const wchar_t* str) +{ + static wchar_t invalidChars[9] = {L'<', L'>', L':', L'"', L'/', L'\\', L'|', L'?', L'*'}; + wchar_t c; + int i; + BOOL bNotDotOnly = FALSE; + while ((c = *str)) + { + if (c != L'.') + bNotDotOnly = TRUE; + for (i= 0; i < ARRAYSIZE(invalidChars); i++) + if (c == invalidChars[i]) + return FALSE; + str++; + } + + return bNotDotOnly; +} + +BOOL IsVolumeDeviceHosted (const wchar_t *lpszDiskFile) +{ + return wcsstr (lpszDiskFile, L"\\Device\\") == lpszDiskFile + || wcsstr (lpszDiskFile, L"\\DEVICE\\") == lpszDiskFile; +} + + +void CreateFullVolumePath (wchar_t *lpszDiskFile, size_t cbDiskFile, const wchar_t *lpszFileName, BOOL * bDevice) +{ + UpperCaseCopy (lpszDiskFile, cbDiskFile, lpszFileName); + + *bDevice = FALSE; + + if (wmemcmp (lpszDiskFile, L"\\DEVICE", 7) == 0) + { + *bDevice = TRUE; + } + + StringCbCopyW (lpszDiskFile, cbDiskFile, lpszFileName); + +#if _DEBUG + OutputDebugString (L"CreateFullVolumePath: "); + OutputDebugString (lpszDiskFile); + OutputDebugString (L"\n"); +#endif + +} + +int FakeDosNameForDevice (const wchar_t *lpszDiskFile , wchar_t *lpszDosDevice , size_t cbDosDevice, wchar_t *lpszCFDevice , size_t cbCFDevice, BOOL bNameOnly) +{ + BOOL bDosLinkCreated = TRUE; + StringCbPrintfW (lpszDosDevice, cbDosDevice,L"veracrypt%lu", GetCurrentProcessId ()); + + if (bNameOnly == FALSE) + bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile); + + if (bDosLinkCreated == FALSE) + return ERR_OS_ERROR; + else + StringCbPrintfW (lpszCFDevice, cbCFDevice,L"\\\\.\\%s", lpszDosDevice); + + return 0; +} + +int RemoveFakeDosName (wchar_t *lpszDiskFile, wchar_t *lpszDosDevice) +{ + BOOL bDosLinkRemoved = DefineDosDevice (DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | + DDD_REMOVE_DEFINITION, lpszDosDevice, lpszDiskFile); + if (bDosLinkRemoved == FALSE) + { + return ERR_OS_ERROR; + } + + return 0; +} + + +void AbortProcessDirect (wchar_t *abortMsg) +{ + // Note that this function also causes localcleanup() to be called (see atexit()) + MessageBeep (MB_ICONEXCLAMATION); + MessageBoxW (NULL, abortMsg, lpszTitle, ICON_HAND); + FREE_DLL (hRichEditDll); + FREE_DLL (hComctl32Dll); + FREE_DLL (hSetupDll); + FREE_DLL (hShlwapiDll); + FREE_DLL (hProfApiDll); + FREE_DLL (hUsp10Dll); + FREE_DLL (hCryptSpDll); + FREE_DLL (hUXThemeDll); + FREE_DLL (hUserenvDll); + FREE_DLL (hRsaenhDll); + FREE_DLL (himm32dll); + FREE_DLL (hMSCTFdll); + FREE_DLL (hfltlibdll); + FREE_DLL (hframedyndll); + FREE_DLL (hpsapidll); + FREE_DLL (hsecur32dll); + FREE_DLL (hnetapi32dll); + FREE_DLL (hauthzdll); + FREE_DLL (hxmllitedll); + FREE_DLL (hmprdll); + FREE_DLL (hsppdll); + FREE_DLL (vssapidll); + FREE_DLL (hvsstracedll); + FREE_DLL (hCryptSpDll); + FREE_DLL (hcfgmgr32dll); + FREE_DLL (hdevobjdll); + FREE_DLL (hpowrprofdll); + FREE_DLL (hsspiclidll); + FREE_DLL (hcryptbasedll); + FREE_DLL (hdwmapidll); + FREE_DLL (hmsasn1dll); + FREE_DLL (hcrypt32dll); + FREE_DLL (hbcryptdll); + FREE_DLL (hbcryptprimitivesdll); + FREE_DLL (hMsls31); + FREE_DLL (hntmartadll); + FREE_DLL (hwinscarddll); + + exit (1); +} + +void AbortProcess (char *stringId) +{ + // Note that this function also causes localcleanup() to be called (see atexit()) + AbortProcessDirect (GetString (stringId)); +} + +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); + + // Note that this function also causes localcleanup() to be called (see atexit()) + exit (1); +} + + +#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; +} + + +BOOL IsDiskReadError (DWORD error) +{ + return (error == ERROR_CRC + || error == ERROR_IO_DEVICE + || error == ERROR_BAD_CLUSTERS + || error == ERROR_SECTOR_NOT_FOUND + || error == ERROR_READ_FAULT + || error == ERROR_INVALID_FUNCTION // I/O error may be reported as ERROR_INVALID_FUNCTION by buggy chipset drivers + || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT +} + + +BOOL IsDiskWriteError (DWORD error) +{ + return (error == ERROR_IO_DEVICE + || error == ERROR_BAD_CLUSTERS + || error == ERROR_SECTOR_NOT_FOUND + || error == ERROR_WRITE_FAULT + || error == ERROR_INVALID_FUNCTION // I/O error may be reported as ERROR_INVALID_FUNCTION by buggy chipset drivers + || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT +} + + +BOOL IsDiskError (DWORD error) +{ + return IsDiskReadError (error) || IsDiskWriteError (error); +} + + +DWORD handleWin32Error (HWND hwndDlg, const char* srcPos) +{ + PWSTR lpMsgBuf; + DWORD dwError = GetLastError (); + wchar_t szErrorValue[32]; + wchar_t* pszDesc; + + if (Silent || dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE) + return dwError; + + // Access denied + if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ()) + { + ErrorDirect ( AppendSrcPos (GetString ("ERR_ACCESS_DENIED"), srcPos).c_str (), hwndDlg); + SetLastError (dwError); // Preserve the original error code + return dwError; + } + + FormatMessageW ( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dwError, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + (PWSTR) &lpMsgBuf, + 0, + NULL + ); + + if (lpMsgBuf) + pszDesc = (wchar_t*) lpMsgBuf; + else + { + StringCchPrintfW (szErrorValue, ARRAYSIZE (szErrorValue), L"Error 0x%.8X", dwError); + pszDesc = szErrorValue; + } + + MessageBoxW (hwndDlg, AppendSrcPos (pszDesc, srcPos).c_str (), lpszTitle, ICON_HAND); + if (lpMsgBuf) LocalFree (lpMsgBuf); + + // User-friendly hardware error explanation + if (IsDiskError (dwError)) + Error ("ERR_HARDWARE_ERROR", hwndDlg); + + // Device not ready + if (dwError == ERROR_NOT_READY) + HandleDriveNotReadyError(hwndDlg); + + SetLastError (dwError); // Preserve the original error code + + return dwError; +} + +BOOL translateWin32Error (wchar_t *lpszMsgBuf, int nWSizeOfBuf) +{ + DWORD dwError = GetLastError (); + + if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + lpszMsgBuf, nWSizeOfBuf, NULL)) + { + SetLastError (dwError); // Preserve the original error code + return TRUE; + } + + SetLastError (dwError); // Preserve the original error code + return FALSE; +} + +// If the user has a non-default screen DPI, all absolute font sizes must be +// converted using this function. +int CompensateDPIFont (int val) +{ + if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) + return val; + else + { + double tmpVal = (double) val * DPIScaleFactorY * DlgAspectRatio * 0.999; + + if (tmpVal > 0) + return (int) floor(tmpVal); + else + return (int) ceil(tmpVal); + } +} + + +// If the user has a non-default screen DPI, some screen coordinates and sizes must +// be converted using this function +int CompensateXDPI (int val) +{ + if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) + return val; + else + { + double tmpVal = (double) val * DPIScaleFactorX; + + if (tmpVal > 0) + return (int) floor(tmpVal); + else + return (int) ceil(tmpVal); + } +} + + +// If the user has a non-default screen DPI, some screen coordinates and sizes must +// be converted using this function +int CompensateYDPI (int val) +{ + if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) + return val; + else + { + double tmpVal = (double) val * DPIScaleFactorY; + + if (tmpVal > 0) + return (int) floor(tmpVal); + else + return (int) ceil(tmpVal); + } +} + + +int GetTextGfxWidth (HWND hwndDlgItem, const wchar_t *text, HFONT hFont) +{ + SIZE sizes; + TEXTMETRIC textMetrics; + HDC hdc = GetDC (hwndDlgItem); + + SelectObject(hdc, (HGDIOBJ) hFont); + + GetTextExtentPoint32W (hdc, text, (int) wcslen (text), &sizes); + + GetTextMetrics(hdc, &textMetrics); // Necessary for non-TrueType raster fonts (tmOverhang) + + ReleaseDC (hwndDlgItem, hdc); + + return ((int) sizes.cx - (int) textMetrics.tmOverhang); +} + + +int GetTextGfxHeight (HWND hwndDlgItem, const wchar_t *text, HFONT hFont) +{ + SIZE sizes; + HDC hdc = GetDC (hwndDlgItem); + + SelectObject(hdc, (HGDIOBJ) hFont); + + GetTextExtentPoint32W (hdc, text, (int) wcslen (text), &sizes); + + ReleaseDC (hwndDlgItem, hdc); + + return ((int) sizes.cy); +} + + +std::wstring FitPathInGfxWidth (HWND hwnd, HFONT hFont, LONG width, const std::wstring &path) +{ + wstring newPath; + + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = width; + rect.bottom = LONG_MAX; + + HDC hdc = GetDC (hwnd); + SelectObject (hdc, (HGDIOBJ) hFont); + + wchar_t pathBuf[TC_MAX_PATH]; + StringCchCopyW (pathBuf, ARRAYSIZE (pathBuf), path.c_str()); + + if (DrawText (hdc, pathBuf, (int) path.size(), &rect, DT_CALCRECT | DT_MODIFYSTRING | DT_PATH_ELLIPSIS | DT_SINGLELINE) != 0) + newPath = pathBuf; + + ReleaseDC (hwnd, hdc); + return newPath; +} + + +static LRESULT CALLBACK HyperlinkProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA); + + switch (message) + { + case WM_SETCURSOR: + if (!bHyperLinkBeingTracked) + { + TRACKMOUSEEVENT trackMouseEvent; + + trackMouseEvent.cbSize = sizeof(trackMouseEvent); + trackMouseEvent.dwFlags = TME_LEAVE; + trackMouseEvent.hwndTrack = hwnd; + + bHyperLinkBeingTracked = TrackMouseEvent(&trackMouseEvent); + + HandCursor(); + } + return 0; + + case WM_MOUSELEAVE: + bHyperLinkBeingTracked = FALSE; + NormalCursor(); + return 0; + } + + return CallWindowProcW (wp, hwnd, message, wParam, lParam); +} + + +BOOL ToHyperlink (HWND hwndDlg, UINT ctrlId) +{ + return ToCustHyperlink (hwndDlg, ctrlId, hUserUnderlineFont); +} + + +BOOL ToCustHyperlink (HWND hwndDlg, UINT ctrlId, HFONT hFont) +{ + HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); + + SendMessageW (hwndCtrl, WM_SETFONT, (WPARAM) hFont, 0); + + SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC)); + SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) HyperlinkProc); + + // Resize the field according to its actual size in pixels and move it if centered or right-aligned. + // This should be done again if the link text changes. + AccommodateTextField (hwndDlg, ctrlId, TRUE, hFont); + + return TRUE; +} + + +// Resizes a text field according to its actual width and height in pixels (font size is taken into account) and moves +// it accordingly if the field is centered or right-aligned. Should be used on all hyperlinks upon dialog init +// after localization (bFirstUpdate should be TRUE) and later whenever a hyperlink text changes (bFirstUpdate +// must be FALSE). +void AccommodateTextField (HWND hwndDlg, UINT ctrlId, BOOL bFirstUpdate, HFONT hFont) +{ + RECT rec, wrec, trec; + HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); + int width, origWidth, height, origHeight; + int horizSubOffset, vertSubOffset, vertOffset, alignPosDiff = 0; + wchar_t text [MAX_URL_LENGTH]; + WINDOWINFO windowInfo; + BOOL bBorderlessWindow = !(GetWindowLongPtrW (hwndDlg, GWL_STYLE) & (WS_BORDER | WS_DLGFRAME)); + + // 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); + height = GetTextGfxHeight (hwndCtrl, text, hFont); + + GetClientRect (hwndCtrl, &rec); + origWidth = rec.right; + origHeight = rec.bottom; + + if (width >= 0 + && (!bFirstUpdate || origWidth > width)) // The original width of the field is the maximum allowed size + { + horizSubOffset = origWidth - width; + vertSubOffset = origHeight - height; + + // Window coords + GetWindowRect(hwndDlg, &wrec); + GetClientRect(hwndDlg, &trec); + + // Vertical "title bar" offset + vertOffset = wrec.bottom - wrec.top - trec.bottom - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CYFIXEDFRAME)); + + // Text field coords + GetWindowRect(hwndCtrl, &rec); + + // Alignment offset + windowInfo.cbSize = sizeof(windowInfo); + GetWindowInfo (hwndCtrl, &windowInfo); + + if (windowInfo.dwStyle & SS_CENTER) + 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); + } +} + +// 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); +} + +// Protects an input field from having its content updated by a Paste action (call ToBootPwdField() to use this). +static LRESULT CALLBACK BootPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA); + + switch (message) + { + case WM_PASTE: + return 1; + } + + return CallWindowProcW (wp, hwnd, message, wParam, lParam); +} + + +// Protects an input field from having its content updated by a Paste action. Used for pre-boot password +// input fields (only the US keyboard layout is supported in pre-boot environment so we must prevent the +// user from pasting a password typed using a non-US keyboard layout). +void ToBootPwdField (HWND hwndDlg, UINT ctrlId) +{ + HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); + + SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC)); + SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) BootPwdFieldProc); +} + + + +// This function currently serves the following purposes: +// - Determines scaling factors for current screen DPI and GUI aspect ratio. +// - Determines how Windows skews the GUI aspect ratio (which happens when the user has a non-default DPI). +// The determined values must be used when performing some GUI operations and calculations. +BOOL CALLBACK AuxiliaryDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + HDC hDC = GetDC (hwndDlg); + + if (hDC) + { + ScreenDPI = GetDeviceCaps (hDC, LOGPIXELSY); + ReleaseDC (hwndDlg, hDC); + } + + DPIScaleFactorX = 1; + DPIScaleFactorY = 1; + DlgAspectRatio = 1; + + if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) + { + // Windows skews the GUI aspect ratio if the user has a non-default DPI. Hence, working with + // actual screen DPI is redundant and leads to incorrect results. What really matters here is + // how Windows actually renders our GUI. This is determined by comparing the expected and current + // sizes of a hidden calibration text field. + + RECT trec; + + trec.right = 0; + trec.bottom = 0; + + GetClientRect (GetDlgItem (hwndDlg, IDC_ASPECT_RATIO_CALIBRATION_BOX), &trec); + + if (trec.right != 0 && trec.bottom != 0) + { + // The size of the 282x282 IDC_ASPECT_RATIO_CALIBRATION_BOX rendered at the default DPI (96) is 423x458 + DPIScaleFactorX = (double) trec.right / 423; + DPIScaleFactorY = (double) trec.bottom / 458; + DlgAspectRatio = DPIScaleFactorX / DPIScaleFactorY; + } + } + + EndDialog (hwndDlg, 0); + return 1; + } + + case WM_CLOSE: + EndDialog (hwndDlg, 0); + return 1; + } + + return 0; +} + + +/* Except in response to the WM_INITDIALOG message, the dialog box procedure + should return nonzero if it processes the message, and zero if it does + not. - see DialogProc */ +BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + static HBITMAP hbmTextualLogoBitmapRescaled = NULL; + + switch (msg) + { + case WM_INITDIALOG: + { + wchar_t szTmp[100]; + RECT rec; + + LocalizeDialog (hwndDlg, "IDD_ABOUT_DLG"); + + // Hyperlink + SetWindowText (GetDlgItem (hwndDlg, IDC_HOMEPAGE), L"www.idrix.fr"); + ToHyperlink (hwndDlg, IDC_HOMEPAGE); + + // Logo area background (must not keep aspect ratio; must retain Windows-imposed distortion) + GetClientRect (GetDlgItem (hwndDlg, IDC_ABOUT_LOGO_AREA), &rec); + SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, rec.right, rec.bottom, SWP_NOMOVE); + + // Resize the logo bitmap if the user has a non-default DPI + if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) + { + // Logo (must recreate and keep the original aspect ratio as Windows distorts it) + hbmTextualLogoBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_TEXTUAL_LOGO_288DPI), + GetDlgItem (hwndDlg, IDC_TEXTUAL_LOGO_IMG), + 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)); +#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-2016 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 2002-2004 Mark Adler. All Rights Reserved.\r\n\r\n" + + L"This software as a whole:\r\n" + L"Copyright \xA9 2013-2016 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", TRUE, ""); + 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; +} + + +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; + } + + return 0; +} + + +// Opens a dialog window saying "Please wait..." which is not modal and does not need any GUI refresh after initialization. +void DisplayStaticModelessWaitDlg (HWND parent) +{ + if (StaticModelessWaitDlgHandle != NULL) + return; // Already shown + + StaticModelessWaitDlgHandle = CreateDialogParamW (hInst, MAKEINTRESOURCEW (IDD_STATIC_MODELESS_WAIT_DLG), parent, (DLGPROC) StaticModelessWaitDlgProc, (LPARAM) 0); + + ShowWindow (StaticModelessWaitDlgHandle, SW_SHOWNORMAL); + + // Allow synchronous use with the GUI being instantly and fully rendered + ProcessPaintMessages (StaticModelessWaitDlgHandle, 500); +} + + +void CloseStaticModelessWaitDlg (void) +{ + if (StaticModelessWaitDlgHandle == NULL) + return; // Not shown + + DestroyWindow (StaticModelessWaitDlgHandle); +} + + +BOOL IsButtonChecked (HWND hButton) +{ + if (SendMessage (hButton, BM_GETCHECK, 0, 0) == BST_CHECKED) + return TRUE; + else + return FALSE; +} + + +void CheckButton (HWND hButton) +{ + SendMessage (hButton, BM_SETCHECK, BST_CHECKED, 0); +} + + +void LeftPadString (wchar_t *szTmp, int len, int targetLen, wchar_t filler) +{ + int i; + + if (targetLen <= len) + return; + + for (i = targetLen-1; i >= (targetLen-len); i--) + szTmp [i] = szTmp [i-(targetLen-len)]; + + wmemset (szTmp, filler, targetLen-len); + szTmp [targetLen] = 0; +} + +/* InitDialog - initialize the applications main dialog, this function should + 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)) + { + // 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; + lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = PROOF_QUALITY; + lf.lfPitchAndFamily = FF_DONTCARE; + StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName), L"Courier New"); + hFixedDigitFont = CreateFontIndirectW (&lf); + if (hFixedDigitFont == NULL) + { + handleWin32Error (hwndDlg, SRC_POS); + AbortProcess ("NOFONT"); + } + + // Bold + font = GetFont ("font_bold"); + + nHeight = CompensateDPIFont (!font ? -13 : -font->Size); + lf.lfHeight = nHeight; + lf.lfWeight = FW_BLACK; + StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName), !font ? L"Arial" : font->FaceName); + hBoldFont = CreateFontIndirectW (&lf); + if (hBoldFont == NULL) + { + handleWin32Error (hwndDlg, SRC_POS); + AbortProcess ("NOFONT"); + } + + // Title + font = GetFont ("font_title"); + + nHeight = CompensateDPIFont (!font ? -21 : -font->Size); + lf.lfHeight = nHeight; + lf.lfWeight = FW_REGULAR; + StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName),!font ? L"Times New Roman" : font->FaceName); + hTitleFont = CreateFontIndirectW (&lf); + if (hTitleFont == NULL) + { + handleWin32Error (hwndDlg, SRC_POS); + AbortProcess ("NOFONT"); + } + + // Fixed-size + font = GetFont ("font_fixed"); + + nHeight = CompensateDPIFont (!font ? -12 : -font->Size); + 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; + lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = PROOF_QUALITY; + lf.lfPitchAndFamily = FF_DONTCARE; + StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName),!font ? L"Lucida Console" : font->FaceName); + hFixedFont = CreateFontIndirectW (&lf); + if (hFixedFont == NULL) + { + handleWin32Error (hwndDlg, SRC_POS); + AbortProcess ("NOFONT"); + } + + if (!aboutMenuAppended) + { + hMenu = GetSystemMenu (hwndDlg, FALSE); + AppendMenu (hMenu, MF_SEPARATOR, 0, L""); + AppendMenuW (hMenu, MF_ENABLED | MF_STRING, IDC_ABOUT, GetString ("ABOUTBOX")); + + aboutMenuAppended = TRUE; + } +} + + +// The parameter maxMessagesToProcess prevents endless processing of paint messages +void ProcessPaintMessages (HWND hwnd, int maxMessagesToProcess) +{ + MSG paintMsg; + int msgCounter = maxMessagesToProcess; + + while (PeekMessageW (&paintMsg, hwnd, 0, 0, PM_REMOVE | PM_QS_PAINT) != 0 && msgCounter-- > 0) + { + DispatchMessageW (&paintMsg); + } +} + + +HDC CreateMemBitmap (HINSTANCE hInstance, HWND hwnd, wchar_t *resource) +{ + HBITMAP picture = LoadBitmap (hInstance, resource); + HDC viewDC = GetDC (hwnd), dcMem; + + dcMem = CreateCompatibleDC (viewDC); + + SetMapMode (dcMem, MM_TEXT); + + SelectObject (dcMem, picture); + + DeleteObject (picture); + + ReleaseDC (hwnd, viewDC); + + return dcMem; +} + + +/* Renders the specified bitmap at the specified location and stretches it to fit (anti-aliasing is applied). +If bDirectRender is FALSE and both nWidth and nHeight are zero, the width and height of hwndDest are +retrieved and adjusted according to screen DPI (the width and height of the resultant image are adjusted the +same way); furthermore, if bKeepAspectRatio is TRUE, the smaller DPI factor of the two (i.e. horiz. or vert.) +is used both for horiz. and vert. scaling (note that the overall GUI aspect ratio changes irregularly in +both directions depending on the DPI). If bDirectRender is TRUE, bKeepAspectRatio is ignored. +This function returns a handle to the scaled bitmap. When the bitmap is no longer needed, it should be +deleted by calling DeleteObject() with the handle passed as the parameter. +Known Windows issues: +- For some reason, anti-aliasing is not applied if the source bitmap contains less than 16K pixels. +- Windows 2000 may produce slightly inaccurate colors even when source, buffer, and target are 24-bit true color. */ +HBITMAP RenderBitmap (wchar_t *resource, HWND hwndDest, int x, int y, int nWidth, int nHeight, BOOL bDirectRender, BOOL bKeepAspectRatio) +{ + LRESULT lResult = 0; + + HDC hdcSrc = CreateMemBitmap (hInst, hwndDest, resource); + if (!hdcSrc) + return NULL; + + HGDIOBJ picture = GetCurrentObject (hdcSrc, OBJ_BITMAP); + + HBITMAP hbmpRescaled = NULL; + BITMAP bitmap; + + HDC hdcRescaled; + + if (!bDirectRender && nWidth == 0 && nHeight == 0) + { + RECT rec; + + GetClientRect (hwndDest, &rec); + + if (bKeepAspectRatio) + { + if (DlgAspectRatio > 1) + { + // Do not fix this, it's correct. We use the Y scale factor intentionally for both + // directions to maintain aspect ratio (see above for more info). + nWidth = CompensateYDPI (rec.right); + nHeight = CompensateYDPI (rec.bottom); + } + else + { + // Do not fix this, it's correct. We use the X scale factor intentionally for both + // directions to maintain aspect ratio (see above for more info). + nWidth = CompensateXDPI (rec.right); + nHeight = CompensateXDPI (rec.bottom); + } + } + else + { + nWidth = CompensateXDPI (rec.right); + nHeight = CompensateYDPI (rec.bottom); + } + } + + GetObject (picture, sizeof (BITMAP), &bitmap); + + hdcRescaled = CreateCompatibleDC (hdcSrc); + + if (hdcRescaled) + { + hbmpRescaled = CreateCompatibleBitmap (hdcSrc, nWidth, nHeight); + + SelectObject (hdcRescaled, hbmpRescaled); + + /* Anti-aliasing mode (HALFTONE is the only anti-aliasing algorithm natively supported by Windows 2000. + TODO: GDI+ offers higher quality -- InterpolationModeHighQualityBicubic) */ + SetStretchBltMode (hdcRescaled, HALFTONE); + + StretchBlt (hdcRescaled, + 0, + 0, + nWidth, + nHeight, + hdcSrc, + 0, + 0, + bitmap.bmWidth, + bitmap.bmHeight, + SRCCOPY); + + DeleteDC (hdcSrc); + + if (bDirectRender) + { + HDC hdcDest = GetDC (hwndDest); + if (hdcDest) + { + BitBlt (hdcDest, x, y, nWidth, nHeight, hdcRescaled, 0, 0, SRCCOPY); + ReleaseDC (hwndDest, hdcDest); + } + } + else + { + lResult = SendMessage (hwndDest, (UINT) STM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) (HANDLE) hbmpRescaled); + } + + if ((HGDIOBJ) lResult != NULL && (HGDIOBJ) lResult != (HGDIOBJ) hbmpRescaled) + DeleteObject ((HGDIOBJ) lResult); + + DeleteDC (hdcRescaled); + } + + return hbmpRescaled; +} + + +LRESULT CALLBACK +RedTick (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_CREATE) + { + } + else if (uMsg == WM_DESTROY) + { + } + else if (uMsg == WM_TIMER) + { + } + else if (uMsg == WM_PAINT) + { + PAINTSTRUCT tmp; + HPEN hPen; + HDC hDC; + BOOL bEndPaint; + RECT Rect; + + if (GetUpdateRect (hwnd, NULL, FALSE)) + { + hDC = BeginPaint (hwnd, &tmp); + bEndPaint = TRUE; + if (hDC == NULL) + return DefWindowProcW (hwnd, uMsg, wParam, lParam); + } + else + { + hDC = GetDC (hwnd); + bEndPaint = FALSE; + } + + GetClientRect (hwnd, &Rect); + + hPen = CreatePen (PS_SOLID, 2, RGB (0, 255, 0)); + if (hPen != NULL) + { + HGDIOBJ hObj = SelectObject (hDC, hPen); + WORD bx = LOWORD (GetDialogBaseUnits ()); + WORD by = HIWORD (GetDialogBaseUnits ()); + + MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL); + LineTo (hDC, Rect.right, Rect.top); + MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL); + + LineTo (hDC, (3 * bx) / 4, (2 * by) / 8); + + SelectObject (hDC, hObj); + DeleteObject (hPen); + } + + if (bEndPaint) + EndPaint (hwnd, &tmp); + else + ReleaseDC (hwnd, hDC); + + return TRUE; + } + + return DefWindowProcW (hwnd, uMsg, wParam, lParam); +} + +BOOL +RegisterRedTick (HINSTANCE hInstance) +{ + WNDCLASSW wc; + ULONG rc; + + memset(&wc, 0 , sizeof wc); + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.cbClsExtra = 0; + wc.cbWndExtra = 4; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); + wc.hCursor = NULL; + wc.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH); + wc.lpszClassName = L"VCREDTICK"; + wc.lpfnWndProc = &RedTick; + + rc = (ULONG) RegisterClassW (&wc); + + return rc == 0 ? FALSE : TRUE; +} + +BOOL +UnregisterRedTick (HINSTANCE hInstance) +{ + return UnregisterClassW (L"VCREDTICK", hInstance); +} + +LRESULT CALLBACK +SplashDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return DefDlgProcW (hwnd, uMsg, wParam, lParam); +} + +static int g_waitCursorCounter = 0; + +void +WaitCursor () +{ + static HCURSOR hcWait; + if (hcWait == NULL) + hcWait = LoadCursor (NULL, IDC_WAIT); + + if ((g_waitCursorCounter == 0) || (hCursor != hcWait)) + { + SetCursor (hcWait); + hCursor = hcWait; + } + g_waitCursorCounter++; +} + +void +NormalCursor () +{ + static HCURSOR hcArrow; + if (hcArrow == NULL) + hcArrow = LoadCursor (NULL, IDC_ARROW); + if (g_waitCursorCounter > 0) + g_waitCursorCounter--; + if (g_waitCursorCounter == 0) + { + SetCursor (hcArrow); + hCursor = NULL; + } +} + +void +ArrowWaitCursor () +{ + static HCURSOR hcArrowWait; + if (hcArrowWait == NULL) + hcArrowWait = LoadCursor (NULL, IDC_APPSTARTING); + if ((g_waitCursorCounter == 0) || (hCursor != hcArrowWait)) + { + SetCursor (hcArrowWait); + hCursor = hcArrowWait; + } + g_waitCursorCounter++; +} + +void HandCursor () +{ + static HCURSOR hcHand; + if (hcHand == NULL) + hcHand = LoadCursor (NULL, IDC_HAND); + SetCursor (hcHand); + hCursor = hcHand; +} + +void +AddComboPair (HWND hComboBox, const wchar_t *lpszItem, int value) +{ + LPARAM nIndex; + + nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) lpszItem); + nIndex = SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) value); +} + +void +SelectAlgo (HWND hComboBox, int *algo_id) +{ + LPARAM nCount = SendMessage (hComboBox, CB_GETCOUNT, 0, 0); + LPARAM x, i; + + for (i = 0; i < nCount; i++) + { + x = SendMessage (hComboBox, CB_GETITEMDATA, i, 0); + if (x == (LPARAM) *algo_id) + { + SendMessage (hComboBox, CB_SETCURSEL, i, 0); + return; + } + } + + /* Something went wrong ; couldn't find the requested algo id so we drop + back to a default */ + + *algo_id = (int) SendMessage (hComboBox, CB_GETITEMDATA, 0, 0); + + SendMessage (hComboBox, CB_SETCURSEL, 0, 0); + +} + +void PopulateWipeModeCombo (HWND hComboBox, BOOL bNA, BOOL bInPlaceEncryption, BOOL bHeaderWipe) +{ + if (bNA) + { + AddComboPair (hComboBox, GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"), TC_WIPE_NONE); + } + else + { + if (!bHeaderWipe) + { + AddComboPair (hComboBox, GetString ("WIPE_MODE_NONE"), TC_WIPE_NONE); + } + + AddComboPair (hComboBox, GetString ("WIPE_MODE_1_RAND"), TC_WIPE_1_RAND); + AddComboPair (hComboBox, GetString ("WIPE_MODE_3_DOD_5220"), TC_WIPE_3_DOD_5220); + AddComboPair (hComboBox, GetString ("WIPE_MODE_7_DOD_5220"), TC_WIPE_7_DOD_5220); + AddComboPair (hComboBox, GetString ("WIPE_MODE_35_GUTMANN"), TC_WIPE_35_GUTMANN); + + if (bHeaderWipe) + AddComboPair (hComboBox, GetString ("WIPE_MODE_256"), TC_WIPE_256); // paranoid wipe for volume header + } +} + +wchar_t *GetWipeModeName (WipeAlgorithmId modeId) +{ + switch (modeId) + { + case TC_WIPE_NONE: + return GetString ("WIPE_MODE_NONE"); + + case TC_WIPE_1_RAND: + return GetString ("WIPE_MODE_1_RAND"); + + case TC_WIPE_3_DOD_5220: + return GetString ("WIPE_MODE_3_DOD_5220"); + + case TC_WIPE_7_DOD_5220: + return GetString ("WIPE_MODE_7_DOD_5220"); + + case TC_WIPE_35_GUTMANN: + return GetString ("WIPE_MODE_35_GUTMANN"); + + case TC_WIPE_256: + return GetString ("WIPE_MODE_256"); + + default: + return GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"); + } +} + +wchar_t *GetPathType (const wchar_t *path, BOOL bUpperCase, BOOL *bIsPartition) +{ + if (wcsstr (path, L"Partition") + && 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; + + 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; + //DWORD addr; + DWORD exCode = ep->ExceptionRecord->ExceptionCode; + // SYSTEM_INFO si; + // wchar_t msg[8192]; + // char modPath[MAX_PATH]; + // int crc = 0; + // char url[MAX_URL_LENGTH]; + // char lpack[128]; + // stringstream callStack; + // addr = (DWORD) ep->ExceptionRecord->ExceptionAddress; + // PDWORD sp = (PDWORD) ep->ContextRecord->Esp; + // int frameNumber = 0; + + switch (exCode) + { + case STATUS_IN_PAGE_ERROR: + case 0xeedfade: + // Exception not caused by VeraCrypt + MessageBoxW (0, GetString ("EXCEPTION_REPORT_EXT"), + GetString ("EXCEPTION_REPORT_TITLE"), + MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST); + return; + } + + // Call stack +/* HMODULE dbgDll = LoadLibrary ("dbghelp.dll"); + if (dbgDll) + { + typedef DWORD (__stdcall *SymGetOptions_t) (); + typedef DWORD (__stdcall *SymSetOptions_t) (DWORD SymOptions); + typedef BOOL (__stdcall *SymInitialize_t) (HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess); + typedef BOOL (__stdcall *StackWalk64_t) (DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); + typedef BOOL (__stdcall * SymFromAddr_t) (HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol); + + SymGetOptions_t DbgHelpSymGetOptions = (SymGetOptions_t) GetProcAddress (dbgDll, "SymGetOptions"); + SymSetOptions_t DbgHelpSymSetOptions = (SymSetOptions_t) GetProcAddress (dbgDll, "SymSetOptions"); + SymInitialize_t DbgHelpSymInitialize = (SymInitialize_t) GetProcAddress (dbgDll, "SymInitialize"); + PFUNCTION_TABLE_ACCESS_ROUTINE64 DbgHelpSymFunctionTableAccess64 = (PFUNCTION_TABLE_ACCESS_ROUTINE64) GetProcAddress (dbgDll, "SymFunctionTableAccess64"); + PGET_MODULE_BASE_ROUTINE64 DbgHelpSymGetModuleBase64 = (PGET_MODULE_BASE_ROUTINE64) GetProcAddress (dbgDll, "SymGetModuleBase64"); + StackWalk64_t DbgHelpStackWalk64 = (StackWalk64_t) GetProcAddress (dbgDll, "StackWalk64"); + SymFromAddr_t DbgHelpSymFromAddr = (SymFromAddr_t) GetProcAddress (dbgDll, "SymFromAddr"); + + if (DbgHelpSymGetOptions && DbgHelpSymSetOptions && DbgHelpSymInitialize && DbgHelpSymFunctionTableAccess64 && DbgHelpSymGetModuleBase64 && DbgHelpStackWalk64 && DbgHelpSymFromAddr) + { + DbgHelpSymSetOptions (DbgHelpSymGetOptions() | SYMOPT_DEFERRED_LOADS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_NO_CPP); + + if (DbgHelpSymInitialize (GetCurrentProcess(), NULL, TRUE)) + { + STACKFRAME64 frame; + memset (&frame, 0, sizeof (frame)); + + frame.AddrPC.Offset = ep->ContextRecord->Eip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrStack.Offset = ep->ContextRecord->Esp; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrFrame.Offset = ep->ContextRecord->Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + + string lastSymbol; + + while (frameNumber < 32 && DbgHelpStackWalk64 (IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), args->ExceptionThread, &frame, ep->ContextRecord, NULL, DbgHelpSymFunctionTableAccess64, DbgHelpSymGetModuleBase64, NULL)) + { + if (!frame.AddrPC.Offset) + continue; + + ULONG64 symbolBuffer[(sizeof (SYMBOL_INFO) + MAX_SYM_NAME * sizeof (TCHAR) + sizeof (ULONG64) - 1) / sizeof (ULONG64)]; + memset (symbolBuffer, 0, sizeof (symbolBuffer)); + + PSYMBOL_INFO symbol = (PSYMBOL_INFO) symbolBuffer; + symbol->SizeOfStruct = sizeof (SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + + if (DbgHelpSymFromAddr (GetCurrentProcess(), frame.AddrPC.Offset, NULL, symbol) && symbol->NameLen > 0) + { + 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 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); + 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; + } + } + + // Checksum of the module + if (GetModuleFileName (NULL, modPath, sizeof (modPath))) + { + HANDLE h = CreateFile (modPath, FILE_READ_DATA | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (h != INVALID_HANDLE_VALUE) + { + BY_HANDLE_FILE_INFORMATION fi; + if (GetFileInformationByHandle (h, &fi)) + { + char *buf = (char *) malloc (fi.nFileSizeLow); + if (buf) + { + DWORD bytesRead; + if (ReadFile (h, buf, fi.nFileSizeLow, &bytesRead, NULL) && bytesRead == fi.nFileSizeLow) + crc = GetCrc32 ((unsigned char *) buf, fi.nFileSizeLow); + free (buf); + } + } + CloseHandle (h); + } + } + + GetSystemInfo (&si); + + if (LocalizationActive) + sprintf_s (lpack, sizeof (lpack), "&langpack=%s_%s", GetPreferredLangId (), GetActiveLangPackVersion ()); + else + lpack[0] = 0; + + + sprintf (url, TC_APPLINK_SECURE "&dest=err-report%s&os=%s&osver=%d.%d.%d&arch=%s&cpus=%d&app=%s&cksum=%x&dlg=%s&err=%x&addr=%x" + , lpack + , GetWindowsEdition().c_str() + , CurrentOSMajor + , CurrentOSMinor + , CurrentOSServicePack + , Is64BitOs () ? "x64" : "x86" + , si.dwNumberOfProcessors +#ifdef TCMOUNT + ,"main" +#endif +#ifdef VOLFORMAT + ,"format" +#endif +#ifdef SETUP + ,"setup" +#endif + , crc + , LastDialogId ? LastDialogId : "-" + , exCode + , addr); + + string urlStr = url + callStack.str(); + + _snwprintf (msg, array_capacity (msg), GetString ("EXCEPTION_REPORT"), urlStr.c_str()); + + if (IDYES == MessageBoxW (0, msg, GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1)) + ShellExecute (NULL, "open", urlStr.c_str(), NULL, NULL, SW_SHOWNORMAL); + else */ + UnhandledExceptionFilter (ep); +} + + +LONG __stdcall ExceptionHandler (EXCEPTION_POINTERS *ep) +{ + SetUnhandledExceptionFilter (NULL); + + if (SystemFileSelectorCallPending && SystemFileSelectorCallerThreadId == GetCurrentThreadId()) + { + MessageBoxW (NULL, GetString ("EXCEPTION_REPORT_EXT_FILESEL"), GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST); + + UnhandledExceptionFilter (ep); + return EXCEPTION_EXECUTE_HANDLER; + } + + ExceptionHandlerThreadArgs args; + args.ExceptionPointers = ep; + args.ExceptionThread = GetCurrentThread(); + + WaitForSingleObject ((HANDLE) _beginthread (ExceptionHandlerThread, 0, &args), INFINITE); + + return EXCEPTION_EXECUTE_HANDLER; +} + + +void InvalidParameterHandler (const wchar_t *expression, const wchar_t *function, const wchar_t *file, unsigned int line, uintptr_t reserved) +{ + TC_THROW_FATAL_EXCEPTION; +} + + +static LRESULT CALLBACK NonInstallUacWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProcW (hWnd, message, wParam, lParam); +} + + +// Mutex handling to prevent multiple instances of the wizard or main app from dealing with system encryption. +// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). +BOOL CreateSysEncMutex (void) +{ + return TCCreateMutex (&hSysEncMutex, TC_MUTEX_NAME_SYSENC); +} + + +BOOL InstanceHasSysEncMutex (void) +{ + return (hSysEncMutex != NULL); +} + + +// Mutex handling to prevent multiple instances of the wizard from dealing with system encryption +void CloseSysEncMutex (void) +{ + TCCloseMutex (&hSysEncMutex); +} + + +// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). +BOOL CreateNonSysInplaceEncMutex (void) +{ + return TCCreateMutex (&hNonSysInplaceEncMutex, TC_MUTEX_NAME_NONSYS_INPLACE_ENC); +} + + +BOOL InstanceHasNonSysInplaceEncMutex (void) +{ + return (hNonSysInplaceEncMutex != NULL); +} + + +void CloseNonSysInplaceEncMutex (void) +{ + TCCloseMutex (&hNonSysInplaceEncMutex); +} + + +// Returns TRUE if another instance of the wizard is preparing, resuming or performing non-system in-place encryption +BOOL NonSysInplaceEncInProgressElsewhere (void) +{ + return (!InstanceHasNonSysInplaceEncMutex () + && MutexExistsOnSystem (TC_MUTEX_NAME_NONSYS_INPLACE_ENC)); +} + + +// Mutex handling 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. +// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). +BOOL CreateDriverSetupMutex (void) +{ + return TCCreateMutex (&hDriverSetupMutex, TC_MUTEX_NAME_DRIVER_SETUP); +} + + +void CloseDriverSetupMutex (void) +{ + TCCloseMutex (&hDriverSetupMutex); +} + + +BOOL CreateAppSetupMutex (void) +{ + return TCCreateMutex (&hAppSetupMutex, TC_MUTEX_NAME_APP_SETUP); +} + + +void CloseAppSetupMutex (void) +{ + TCCloseMutex (&hAppSetupMutex); +} + + +BOOL IsTrueCryptInstallerRunning (void) +{ + return (MutexExistsOnSystem (TC_MUTEX_NAME_APP_SETUP)); +} + + +// Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). +BOOL TCCreateMutex (volatile HANDLE *hMutex, wchar_t *name) +{ + if (*hMutex != NULL) + return TRUE; // This instance already has the mutex + + *hMutex = CreateMutex (NULL, TRUE, name); + if (*hMutex == NULL) + { + // In multi-user configurations, the OS returns "Access is denied" here when a user attempts + // to acquire the mutex if another user already has. However, on Vista, "Access is denied" is + // returned also if the mutex is owned by a process with admin rights while we have none. + + return FALSE; + } + + if (GetLastError () == ERROR_ALREADY_EXISTS) + { + ReleaseMutex (*hMutex); + CloseHandle (*hMutex); + + *hMutex = NULL; + return FALSE; + } + + return TRUE; +} + + +void TCCloseMutex (volatile HANDLE *hMutex) +{ + if (*hMutex != NULL) + { + if (ReleaseMutex (*hMutex) + && CloseHandle (*hMutex)) + *hMutex = NULL; + } +} + + +// Returns TRUE if a process running on the system has the specified mutex (otherwise FALSE). +BOOL MutexExistsOnSystem (wchar_t *name) +{ + if (name[0] == 0) + return FALSE; + + HANDLE hMutex = OpenMutex (MUTEX_ALL_ACCESS, FALSE, name); + + if (hMutex == NULL) + { + if (GetLastError () == ERROR_FILE_NOT_FOUND) + return FALSE; + + if (GetLastError () == ERROR_ACCESS_DENIED) // On Vista, this is returned if the owner of the mutex is elevated while we are not + return TRUE; + + // The call failed and it is not certain whether the mutex exists or not + return FALSE; + } + + CloseHandle (hMutex); + return TRUE; +} + + +uint32 ReadDriverConfigurationFlags () +{ + DWORD configMap; + + if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", TC_DRIVER_CONFIG_REG_VALUE_NAME, &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 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) + { + newSystemEncryptionStatus = atoi (paramVal); + } + else if (strcmp (paramName, "WipeMode") == 0) + { + newnWipeMode = (WipeAlgorithmId) atoi (paramVal); + } + + xml++; + } + + SystemEncryptionStatus = newSystemEncryptionStatus; + nWipeMode = newnWipeMode; + + free (sysEncCfgFileBuf); + return status; +} + + +// Returns the number of partitions where non-system in-place encryption is progress or had been in progress +// but was interrupted. In addition, via the passed pointer, returns the last selected wipe algorithm ID. +int LoadNonSysInPlaceEncSettings (WipeAlgorithmId *wipeAlgorithm) +{ + char *fileBuf = NULL; + char *fileBuf2 = NULL; + DWORD size, size2; + int count; + + *wipeAlgorithm = TC_WIPE_NONE; + + if (!FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC))) + return 0; + + if ((fileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), &size)) == NULL) + return 0; + + if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) + { + if ((fileBuf2 = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE), &size2)) != NULL) + *wipeAlgorithm = (WipeAlgorithmId) atoi (fileBuf2); + } + + count = atoi (fileBuf); + + if (fileBuf != NULL) + TCfree (fileBuf); + + if (fileBuf2 != NULL) + TCfree (fileBuf2); + + return (count); +} + + +void RemoveNonSysInPlaceEncNotifications (void) +{ + if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC))) + _wremove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC)); + + if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) + _wremove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE)); + + if (!IsNonInstallMode () && SystemEncryptionStatus == SYSENC_STATUS_NONE) + ManageStartupSeqWiz (TRUE, L""); +} + + +void SavePostInstallTasksSettings (int command) +{ + FILE *f = NULL; + + if (IsNonInstallMode() && command != TC_POST_INSTALL_CFG_REMOVE_ALL) + return; + + switch (command) + { + case TC_POST_INSTALL_CFG_REMOVE_ALL: + _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL)); + _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES)); + break; + + case TC_POST_INSTALL_CFG_TUTORIAL: + f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL), L"w"); + break; + + case TC_POST_INSTALL_CFG_RELEASE_NOTES: + f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES), L"w"); + break; + + default: + return; + } + + if (f == NULL) + return; + + if (fputws (L"1", f) < 0) + { + // Error + fclose (f); + return; + } + + TCFlushFile (f); + + fclose (f); +} + + +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", TRUE, ""); + + bDone = TRUE; + } + + if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES))) + { + if (AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES", hwndDlg) == IDYES) + Applink ("releasenotes", TRUE, ""); + + bDone = TRUE; + } + + if (bDone) + SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_REMOVE_ALL); +} + + +void InitOSVersionInfo () +{ + OSVERSIONINFOEXW os; + os.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); + + if (GetVersionExW ((LPOSVERSIONINFOW) &os) == FALSE) + AbortProcess ("NO_OS_VER"); + + CurrentOSMajor = os.dwMajorVersion; + CurrentOSMinor = os.dwMinorVersion; + CurrentOSServicePack = os.wServicePackMajor; + + if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 0) + nCurrentOS = WIN_2000; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 1) + nCurrentOS = WIN_XP; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 2) + { + if (os.wProductType == VER_NT_SERVER || os.wProductType == VER_NT_DOMAIN_CONTROLLER) + nCurrentOS = WIN_SERVER_2003; + else + nCurrentOS = WIN_XP64; + } + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 0) + { + if (os.wProductType != VER_NT_WORKSTATION) + nCurrentOS = WIN_SERVER_2008; + else + nCurrentOS = WIN_VISTA; + } + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 1) + nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2008_R2 : WIN_7); + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 2) + nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012 : WIN_8); + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 3) + nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012_R2 : WIN_8_1); + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 10 && CurrentOSMinor == 0) + nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2016 : WIN_10); + else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 4) + nCurrentOS = WIN_NT4; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 0) + nCurrentOS = WIN_95; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 10) + nCurrentOS = WIN_98; + else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 90) + nCurrentOS = WIN_ME; + else if (os.dwPlatformId == VER_PLATFORM_WIN32s) + nCurrentOS = WIN_31; + else + nCurrentOS = WIN_UNKNOWN; +} + +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"); + + StringCbCatW(dllPath, sizeof(dllPath), L"\\"); + StringCbCatW(dllPath, sizeof(dllPath), szModuleName); + + if (((*pHandle = LoadLibrary(dllPath)) == NULL) && !bIgnoreError) + { + // This error is fatal + handleWin32Error (NULL, srcPos); + AbortProcess ("INIT_DLL"); + } +} + +/* 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; + + InitOSVersionInfo(); + + InitializeCriticalSection (&csWNetCalls); + + 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); + 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); + + LoadSystemDll (L"userenv.dll", &hUserenvDll, TRUE, SRC_POS); + LoadSystemDll (L"rsaenh.dll", &hRsaenhDll, TRUE, SRC_POS); + +#ifdef SETUP + if (nCurrentOS < 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); + } + } + + if (IsOSAtLeast (WIN_VISTA)) + { + LoadSystemDll (L"spp.dll", &hsppdll, TRUE, SRC_POS); + LoadSystemDll (L"vssapi.dll", &vssapidll, TRUE, SRC_POS); + LoadSystemDll (L"vsstrace.dll", &hvsstracedll, TRUE, SRC_POS); + + if (IsOSAtLeast (WIN_7)) + { + 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"dwmapi.dll", &hdwmapidll, TRUE, SRC_POS); + + LoadSystemDll (L"crypt32.dll", &hcrypt32dll, TRUE, SRC_POS); + + LoadSystemDll (L"bcrypt.dll", &hbcryptdll, TRUE, SRC_POS); + LoadSystemDll (L"bcryptprimitives.dll", &hbcryptprimitivesdll, TRUE, SRC_POS); + } + } +#else + LoadSystemDll (L"WINSCARD.DLL", &hwinscarddll, TRUE, SRC_POS); +#endif + + LoadSystemDll (L"COMCTL32.DLL", &hComctl32Dll, FALSE, SRC_POS); + + // 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"); + + LoadSystemDll (L"Riched20.dll", &hRichEditDll, FALSE, SRC_POS); + + // 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 function pointer + SHDeleteKeyWFn = (SHDeleteKeyWPtr) GetProcAddress (hShlwapiDll, "SHDeleteKeyW"); + SHStrDupWFn = (SHStrDupWPtr) GetProcAddress (hShlwapiDll, "SHStrDupW"); + if (!SHDeleteKeyWFn || !SHStrDupWFn) + 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); +#endif + } + + /* Save the instance handle for later */ + hInst = hInstance; + + SetErrorMode (SetErrorMode (0) | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); + CoInitialize (NULL); + +#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); +#endif + + // Language + langId[0] = 0; + SetPreferredLangId (ConfigReadString ("Language", "", langId, sizeof (langId))); + + if (langId[0] == 0) + { + if (IsNonInstallMode ()) + { + // only support automatic use of a language file in portable mode + // this is achieved by placing a unique language XML file in the same + // place as portable VeraCrypt binaries. + DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_LANGUAGE), NULL, + (DLGPROC) LanguageDlgProc, (LPARAM) 1); + } + else + { + // when installed, force using English as default language + SetPreferredLangId ("en"); + } + } + + LoadLanguageFile (); + +#ifndef SETUP + // UAC elevation moniker cannot be used in portable mode. + // A new instance of the application must be created with elevated privileges. + if (IsNonInstallMode () && !IsAdmin () && IsUacSupported ()) + { + wchar_t modPath[MAX_PATH], newCmdLine[4096]; + WNDCLASSEXW wcex; + HWND hWnd; + + if (wcsstr (lpszCommandLine, L"/q UAC ") == lpszCommandLine) + { + Error ("UAC_INIT_ERROR", NULL); + exit (1); + } + + memset (&wcex, 0, sizeof (wcex)); + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.lpfnWndProc = (WNDPROC) NonInstallUacWndProc; + wcex.hInstance = hInstance; + wcex.lpszClassName = L"VeraCrypt"; + RegisterClassExW (&wcex); + + // A small transparent window is necessary to bring the new instance to foreground + hWnd = CreateWindowExW (WS_EX_TOOLWINDOW | WS_EX_LAYERED, + L"VeraCrypt", L"VeraCrypt", 0, + GetSystemMetrics (SM_CXSCREEN)/2, + GetSystemMetrics (SM_CYSCREEN)/2, + 1, 1, NULL, NULL, hInstance, NULL); + + SetLayeredWindowAttributes (hWnd, 0, 0, LWA_ALPHA); + ShowWindow (hWnd, SW_SHOWNORMAL); + + GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath)); + + StringCbCopyW (newCmdLine, sizeof(newCmdLine), L"/q UAC "); + StringCbCatW (newCmdLine, sizeof (newCmdLine), lpszCommandLine); + + if ((int)ShellExecuteW (hWnd, L"runas", modPath, newCmdLine, NULL, SW_SHOWNORMAL) <= 32) + exit (1); + + Sleep (2000); + exit (0); + } +#endif + + SetUnhandledExceptionFilter (ExceptionHandler); + _set_invalid_parameter_handler (InvalidParameterHandler); + + RemoteSession = GetSystemMetrics (SM_REMOTESESSION) != 0; + + // OS version check + if (CurrentOSMajor < 5) + { + MessageBoxW (NULL, GetString ("UNSUPPORTED_OS"), lpszTitle, MB_ICONSTOP); + exit (1); + } + else + { + // Service pack check & warnings about critical MS issues + switch (nCurrentOS) + { + case WIN_2000: + if (CurrentOSServicePack < 3) + Warning ("LARGE_IDE_WARNING_2K", NULL); + else + { + DWORD val = 0, size = sizeof(val); + HKEY hkey; + + if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Atapi\\Parameters", 0, KEY_READ, &hkey) == ERROR_SUCCESS) + { + if (RegQueryValueExW (hkey, L"EnableBigLba", 0, 0, (LPBYTE) &val, &size) != ERROR_SUCCESS + || val != 1) + { + Warning ("LARGE_IDE_WARNING_2K_REGISTRY", NULL); + } + RegCloseKey (hkey); + } + } + break; + + 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 + 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); + 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); +} + +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"VeraCrypt User Guide.pdf"); + } + else + { + StringCbPrintfW (szTemp, sizeof(szTemp), L"VeraCrypt User Guide.%S.pdf", 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) + { + ++lpszTmp; + *lpszTmp = 0; + StringCbCatW (szHelpFile2, sizeof(szHelpFile2), L"VeraCrypt User Guide.pdf"); + } + } +} + +BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem, BOOL matchVolumeID, const BYTE* pbVolumeID) +{ + DWORD dwResult; + BOOL bResult; + wchar_t wszFileName[TC_MAX_PATH]; + + StringCbCopyW (wszFileName, sizeof(wszFileName), lpszPath); + + memset (driver, 0, sizeof (OPEN_TEST_STRUCT)); + memcpy (driver->wszFileName, wszFileName, sizeof (wszFileName)); + + driver->bDetectTCBootLoader = FALSE; + driver->DetectFilesystem = detectFilesystem; + driver->bMatchVolumeID = matchVolumeID; + if (matchVolumeID && pbVolumeID) + memcpy (driver->volumeID, pbVolumeID, VOLUME_ID_SIZE); + + bResult = DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, + driver, sizeof (OPEN_TEST_STRUCT), + driver, sizeof (OPEN_TEST_STRUCT), + &dwResult, NULL); + + // check variable driver + if ( bResult + && ( (driver->bDetectTCBootLoader != TRUE && driver->bDetectTCBootLoader != FALSE) || + (driver->TCBootLoaderDetected != TRUE && driver->TCBootLoaderDetected != FALSE) || + (driver->DetectFilesystem != TRUE && driver->DetectFilesystem != FALSE) || + (driver->FilesystemDetected != TRUE && driver->FilesystemDetected != FALSE) || + (wcscmp (wszFileName, driver->wszFileName)) + ) + ) + { + return FALSE; + } + + if (bResult == FALSE) + { + dwResult = GetLastError (); + + if (dwResult == ERROR_SHARING_VIOLATION || dwResult == ERROR_NOT_READY) + { + driver->TCBootLoaderDetected = FALSE; + driver->FilesystemDetected = FALSE; + driver->VolumeIDMatched = FALSE; + return TRUE; + } + else + return FALSE; + } + + return TRUE; +} + + +// Tells the driver that it's running in portable mode +void NotifyDriverOfPortableMode (void) +{ + if (hDriver != INVALID_HANDLE_VALUE) + { + DWORD dwResult; + + DeviceIoControl (hDriver, TC_IOCTL_SET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dwResult, NULL); + } +} + + +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); +} + + +/* 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)) + { + if (drive.ContainsSystem) + { + foreach (const HostDevice &sysDrivePartition, drive.Partitions) + { + if (sysDrivePartition.Bootable) + { + if (sysDrivePartition.Size <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE) + ExtraBootPartitionDevicePath = sysDrivePartition.Path; + 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. */ +int IsSystemDevicePath (const wchar_t *path, HWND hwndDlg, BOOL bReliableRequired) +{ + if (!bCachedSysDevicePathsValid + && bReliableRequired) + { + if (!GetSysDevicePaths (hwndDlg)) + return -1; + } + + if (wcslen (SysPartitionDevicePath) <= 1 || wcslen (SysDriveDevicePath) <= 1) + return -1; + + if (!path) + return -1; + + if (wcsncmp (path, SysPartitionDevicePath, max (wcslen(path), wcslen(SysPartitionDevicePath))) == 0) + return 1; + else if (wcsncmp (path, SysDriveDevicePath, max (wcslen(path), wcslen(SysDriveDevicePath))) == 0) + return 2; + else if (ExtraBootPartitionDevicePath == path) + return 3; + + return 0; +} + + +/* Determines whether the path points to a non-system partition on the system drive. +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, never at WM_INITDIALOG or any other GUI events. +Return codes: +0 - it isn't a non-system partition on the system drive +1 - it's a non-system partition on the system drive +-1 - the result can't be determined, isn't reliable, or there was an error. */ +int IsNonSysPartitionOnSysDrive (const wchar_t *path) +{ + wchar_t tmpPath [TC_MAX_PATH + 1]; + int pos; + + if (!GetSysDevicePaths (MainDlg)) + return -1; + + if (wcslen (SysPartitionDevicePath) <= 1 || wcslen (SysDriveDevicePath) <= 1) + return -1; + + if (wcsncmp (path, SysPartitionDevicePath, max (wcslen(path), wcslen(SysPartitionDevicePath))) == 0 + || wcsncmp (path, SysDriveDevicePath, max (wcslen(path), wcslen(SysDriveDevicePath))) == 0) + { + // It is the system partition/drive path (it isn't a non-system partition) + return 0; + } + + memset (tmpPath, 0, sizeof (tmpPath)); + wcsncpy (tmpPath, path, ARRAYSIZE (tmpPath) - 1); + + + pos = (int) FindString ((const char*) tmpPath, (const char*) L"Partition", (int) wcslen (tmpPath) * 2, (int) wcslen (L"Partition") * 2, 0); + + if (pos < 0) + return -1; + + pos /= 2; + pos += (int) strlen ("Partition"); + + if (pos + 1 > ARRAYSIZE (tmpPath) - 1) + return -1; + + tmpPath [pos] = L'0'; + tmpPath [pos + 1] = 0; + + if (wcsncmp (tmpPath, SysDriveDevicePath, max (wcslen(tmpPath), wcslen(SysDriveDevicePath))) == 0) + { + // It is a non-system partition on the system drive + return 1; + } + else + { + // The partition is not on the system drive + return 0; + } +} + + +wstring GetSysEncryptionPretestInfo2String (void) +{ + // This huge string is divided into smaller portions to make it easier for translators to + // re-translate it when a minor modification is made to it (the whole huge string will not be + // reverted to English, so they will have to translate only a small portion of it). + return (wstring (L"\n") + + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_1") + + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_2") + + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_3") + + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_4")); +} + + +wstring GetRescueDiskHelpString (void) +{ + // This huge string is divided into smaller portions to make it easier for translators to + // re-translate it when a minor modification is made to it (the whole huge string will not be + // reverted to English, so they will have to translate only a small portion of it). + return (wstring ( + GetString ("RESCUE_DISK_HELP_PORTION_1")) + + GetString ("RESCUE_DISK_HELP_PORTION_2") + + GetString ("RESCUE_DISK_HELP_PORTION_3") + + GetString ("RESCUE_DISK_HELP_PORTION_4") + + GetString ("RESCUE_DISK_HELP_PORTION_5") + + GetString ("RESCUE_DISK_HELP_PORTION_6") + + GetString ("RESCUE_DISK_HELP_PORTION_7") + + GetString ("RESCUE_DISK_HELP_PORTION_8") + + GetString ("RESCUE_DISK_HELP_PORTION_9")); +} + + +wstring GetDecoyOsInstructionsString (void) +{ + // This huge string is divided into smaller portions to make it easier for translators to + // re-translate it when a minor modification is made to it (the whole huge string will not be + // reverted to English, so they will have to translate only a small portion of it). + return (wstring ( + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_1")) + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_2") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_3") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_4") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_5") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_6") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_7") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_8") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_9") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_10") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_11") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_12") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_13") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_14") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_15") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_16") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_17") + + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_18")); +} + + +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; + + // Left margin for rich edit text field + SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4)); + + ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_HIDE); + + switch (nID) + { + case TC_TBXID_LEGAL_NOTICES: + LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE"); + break; + + case TC_TBXID_SYS_ENCRYPTION_PRETEST: + LocalizeDialog (hwndDlg, NULL); + ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); + break; + + case TC_TBXID_SYS_ENC_RESCUE_DISK: + LocalizeDialog (hwndDlg, NULL); + ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); + break; + + case TC_TBXID_DECOY_OS_INSTRUCTIONS: + LocalizeDialog (hwndDlg, NULL); + ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); + break; + + case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: + LocalizeDialog (hwndDlg, NULL); + ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); + break; + } + + SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0); + } + return 0; + + case WM_COMMAND: + if (lw == IDOK || lw == IDCANCEL) + { + NormalCursor (); + EndDialog (hwndDlg, 0); + return 1; + } + + if (lw == IDC_PRINT) + { + switch (nID) + { + case TC_TBXID_SYS_ENCRYPTION_PRETEST: + PrintHardCopyTextUTF16 ((wchar_t *) GetSysEncryptionPretestInfo2String ().c_str(), L"Pre-Boot Troubleshooting", GetSysEncryptionPretestInfo2String ().length () * 2); + break; + + case TC_TBXID_SYS_ENC_RESCUE_DISK: + PrintHardCopyTextUTF16 ((wchar_t *) GetRescueDiskHelpString ().c_str(), L"VeraCrypt Rescue Disk Help", GetRescueDiskHelpString ().length () * 2); + break; + + case TC_TBXID_DECOY_OS_INSTRUCTIONS: + PrintHardCopyTextUTF16 ((wchar_t *) GetDecoyOsInstructionsString ().c_str(), L"How to Create Decoy OS", GetDecoyOsInstructionsString ().length () * 2); + break; + + case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: + PrintHardCopyTextUTF16 (GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS"), L"How to Remove Extra Boot Partition", wcslen (GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS")) * 2); + break; + } + return 1; + } + + return 0; + + case TC_APPMSG_LOAD_TEXT_BOX_CONTENT: + { + char *r = NULL; + + switch (nID) + { + case TC_TBXID_LEGAL_NOTICES: + LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE"); + r = GetLegalNotices (); + if (r != NULL) + { + SETTEXTEX TextInfo = {0}; + + TextInfo.flags = ST_SELECTION; + TextInfo.codepage = CP_ACP; + + SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETTEXTEX, (WPARAM)&TextInfo, (LPARAM)r); + free (r); + } + break; + + case TC_TBXID_SYS_ENCRYPTION_PRETEST: + LocalizeDialog (hwndDlg, NULL); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetSysEncryptionPretestInfo2String ().c_str()); + break; + + case TC_TBXID_SYS_ENC_RESCUE_DISK: + LocalizeDialog (hwndDlg, NULL); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetRescueDiskHelpString ().c_str()); + break; + + case TC_TBXID_DECOY_OS_INSTRUCTIONS: + LocalizeDialog (hwndDlg, NULL); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetDecoyOsInstructionsString ().c_str()); + break; + + case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: + LocalizeDialog (hwndDlg, NULL); + SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS")); + break; + } + } + return 1; + + case WM_CLOSE: + NormalCursor (); + EndDialog (hwndDlg, 0); + return 1; + } + + return 0; +} + + +char * GetLegalNotices () +{ + static char *resource; + static DWORD size; + char *buf = NULL; + + if (resource == NULL) + resource = (char *) MapResource (L"Text", IDR_LICENSE, &size); + + if (resource != NULL) + { + buf = (char *) malloc (size + 1); + if (buf != NULL) + { + memcpy (buf, resource, size); + buf[size] = 0; + } + } + + return buf; +} + + +BOOL CALLBACK RawDevicesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static wchar_t *lpszFileName; // This is actually a pointer to a GLOBAL array + static vector devices; + static map itemToDeviceMap; + + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + LVCOLUMNW LvCol; + HWND hList = GetDlgItem (hwndDlg, IDC_DEVICELIST); + RawDevicesDlgParam* pDlgParam = (RawDevicesDlgParam *) lParam; + + LocalizeDialog (hwndDlg, "IDD_RAWDEVICES_DLG"); + + SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, + LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP + ); + + memset (&LvCol,0,sizeof(LvCol)); + LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; + LvCol.pszText = GetString ("DEVICE"); + LvCol.cx = CompensateXDPI (186); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("DRIVE"); + LvCol.cx = CompensateXDPI (38); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("SIZE"); + LvCol.cx = CompensateXDPI (64); + LvCol.fmt = LVCFMT_RIGHT; + SendMessage (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("LABEL"); + LvCol.cx = CompensateXDPI (128); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol); + + devices.clear(); + itemToDeviceMap.clear(); + + if (pDlgParam->devices.empty()) + { + WaitCursor(); + devices = GetAvailableHostDevices (false, true, false); + NormalCursor(); + } + else + devices = pDlgParam->devices; + + if (devices.empty()) + { + MessageBoxW (hwndDlg, GetString ("RAWDEVICES"), lpszTitle, ICON_HAND); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + int line = 1; + LVITEM item; + memset (&item, 0, sizeof (item)); + item.mask = LVIF_TEXT; + + foreach (const HostDevice &device, devices) + { + item.iSubItem = 1; + + if (device.ContainsSystem) + { + if (device.IsPartition) + StringCbCopyW (SysPartitionDevicePath, sizeof (SysPartitionDevicePath), device.Path.c_str()); + else + StringCbCopyW (SysDriveDevicePath, sizeof (SysDriveDevicePath), device.Path.c_str()); + } + + // Path + if (!device.IsPartition || device.DynamicVolume) + { + if (!device.Floppy && (device.Size == 0) + && (device.IsPartition || device.Partitions.empty() || device.Partitions[0].Size == 0) + ) + continue; + + if (line > 1) + { + ListItemAdd (hList, item.iItem, L""); + item.iItem = line++; + } + + if (device.Floppy || device.DynamicVolume) + { + ListItemAdd (hList, item.iItem, (wchar_t *) device.Path.c_str()); + } + else + { + wchar_t s[1024]; + if (device.Removable) + StringCbPrintfW (s, sizeof(s), L"%s %d", GetString ("REMOVABLE_DISK"), device.SystemNumber); + else + StringCbPrintfW (s, sizeof(s), L"%s %d", GetString ("HARDDISK"), device.SystemNumber); + + if (!device.Partitions.empty()) + StringCbCatW (s, sizeof(s), L":"); + + ListItemAdd (hList, item.iItem, s); + } + } + else + { + ListItemAdd (hList, item.iItem, (wchar_t *) device.Path.c_str()); + } + + itemToDeviceMap[item.iItem] = device; + + // Size + if (device.Size != 0) + { + wchar_t size[100] = { 0 }; + GetSizeString (device.Size, size, sizeof(size)); + ListSubItemSet (hList, item.iItem, 2, size); + } + + // Mount point + if (!device.MountPoint.empty()) + ListSubItemSet (hList, item.iItem, 1, (wchar_t *) device.MountPoint.c_str()); + + // Label + if (!device.Name.empty()) + ListSubItemSet (hList, item.iItem, 3, (wchar_t *) device.Name.c_str()); +#ifdef TCMOUNT + else + { + bool useInExplorer = false; + wstring favoriteLabel = GetFavoriteVolumeLabel (device.Path, useInExplorer); + if (!favoriteLabel.empty()) + ListSubItemSet (hList, item.iItem, 3, (wchar_t *) favoriteLabel.c_str()); + } +#endif + + item.iItem = line++; + } + + SendMessageW(hList, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); + SendMessageW(hList, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); + SendMessageW(hList, LVM_SETCOLUMNWIDTH, 2, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); + SendMessageW(hList, LVM_SETCOLUMNWIDTH, 3, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); + + lpszFileName = pDlgParam->pszFileName; + +#ifdef VOLFORMAT + EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); +#endif + return 1; + } + + case WM_COMMAND: + case WM_NOTIFY: + // catch non-device line selected + if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED )) + { + BOOL bEnableOkButton = FALSE; + LVITEM LvItem; + memset(&LvItem,0,sizeof(LvItem)); + LvItem.mask = LVIF_TEXT | LVIF_PARAM; + LvItem.iItem = ((LPNMLISTVIEW) lParam)->iItem; + LvItem.pszText = lpszFileName; + LvItem.cchTextMax = TC_MAX_PATH; + + lpszFileName[0] = 0; + SendMessage (GetDlgItem (hwndDlg, IDC_DEVICELIST), LVM_GETITEM, LvItem.iItem, (LPARAM) &LvItem); + if (lpszFileName[0] != 0 && lpszFileName[0] != ' ') + { + bEnableOkButton = TRUE; +#ifdef VOLFORMAT + if ( bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE) + && LvItem.iItem != -1 && itemToDeviceMap.find (LvItem.iItem) != itemToDeviceMap.end() + ) + { + const HostDevice selectedDevice = itemToDeviceMap[LvItem.iItem]; + if (selectedDevice.ContainsSystem) + { + bEnableOkButton = FALSE; + } + } +#endif + } + EnableWindow (GetDlgItem ((HWND) hwndDlg, IDOK), bEnableOkButton); + + return 1; + } + + if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE) + { + int selectedItem = ListView_GetSelectionMark (GetDlgItem (hwndDlg, IDC_DEVICELIST)); + + if (selectedItem == -1 || itemToDeviceMap.find (selectedItem) == itemToDeviceMap.end()) + return 1; // non-device line selected + + const HostDevice selectedDevice = itemToDeviceMap[selectedItem]; + StringCchCopyW (lpszFileName, TC_MAX_PATH, selectedDevice.Path.c_str()); + +#ifdef VOLFORMAT + if (selectedDevice.ContainsSystem && selectedDevice.IsPartition) + { + if (WizardMode != WIZARD_MODE_SYS_DEVICE) + { + if (bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE)) + { + // disable selection + return 1; + } + + if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE", hwndDlg) == IDNO) + { + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + bSysPartitionSelected = TRUE; + bSysDriveSelected = FALSE; + lpszFileName[0] = 0; + SwitchWizardToSysEncMode (); + + NormalCursor (); + EndDialog (hwndDlg, IDOK); + return 1; + } + else + { + // This should never be the case because the Select Device dialog is not available in this wizard mode + bSysPartitionSelected = TRUE; + bSysDriveSelected = FALSE; + lpszFileName[0] = 0; + SwitchWizardToSysEncMode (); + NormalCursor (); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + } + + if (!(selectedDevice.ContainsSystem && !selectedDevice.IsPartition)) + { + if (bWarnDeviceFormatAdvanced + && !bHiddenVolDirect + && AskWarnNoYes("FORMAT_DEVICE_FOR_ADVANCED_ONLY", hwndDlg) == IDNO) + { + if (AskNoYes("CONFIRM_CHANGE_WIZARD_MODE_TO_FILE_CONTAINER", hwndDlg) == IDYES) + { + SwitchWizardToFileContainerMode (); + } + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + if (!bHiddenVolDirect) + bWarnDeviceFormatAdvanced = FALSE; + } + +#else // #ifdef VOLFORMAT + + bSysPartitionSelected = (selectedDevice.ContainsSystem && selectedDevice.IsPartition); + bSysDriveSelected = FALSE; + +#endif // #ifdef VOLFORMAT + + if (!selectedDevice.IsPartition && !selectedDevice.Floppy) + { + // Whole device selected + +#ifdef VOLFORMAT + if (selectedDevice.ContainsSystem && !selectedDevice.IsPartition) + { + if (WizardMode != WIZARD_MODE_SYS_DEVICE) + { + if (bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE)) + { + // disable selection + return 1; + } + + if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE", hwndDlg) == IDNO) + { + NormalCursor (); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + bSysDriveSelected = TRUE; + bSysPartitionSelected = FALSE; + lpszFileName[0] = 0; + SwitchWizardToSysEncMode (); + + NormalCursor (); + EndDialog (hwndDlg, IDOK); + return 1; + } + else + { + // This should never be the case because the Select Device dialog is not available in this wizard mode + bSysDriveSelected = TRUE; + bSysPartitionSelected = FALSE; + lpszFileName[0] = 0; + SwitchWizardToSysEncMode (); + NormalCursor (); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + } + + // Disallow format if the device contains partitions, but not if the partition is virtual or system + if (!selectedDevice.IsVirtualPartition + && !bHiddenVolDirect) + { + if (!selectedDevice.Partitions.empty()) + { + EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); + Error ("DEVICE_PARTITIONS_ERR_W_INPLACE_ENC_NOTE", hwndDlg); + return 1; + } + + if (AskWarnNoYes ("WHOLE_NONSYS_DEVICE_ENC_CONFIRM", hwndDlg) == IDNO) + return 1; + } +#else // #ifdef VOLFORMAT + + bSysDriveSelected = (selectedDevice.ContainsSystem && !selectedDevice.IsPartition); + bSysPartitionSelected = FALSE; + +#endif // #ifdef VOLFORMAT + } + else + bSysDriveSelected = FALSE; + +#ifdef VOLFORMAT + bRemovableHostDevice = selectedDevice.Removable; +#endif + NormalCursor (); + EndDialog (hwndDlg, IDOK); + return 1; + } + + if ((msg == WM_COMMAND) && (lw == IDCANCEL)) + { + NormalCursor (); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + return 0; + } + return 0; +} + + +BOOL DoDriverInstall (HWND hwndDlg) +{ +#ifdef SETUP + if (SystemEncryptionUpdate) + return TRUE; +#endif + + SC_HANDLE hManager, hService = NULL; + BOOL bOK = FALSE, bRet; + + hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hManager == NULL) + goto error; + +#ifdef SETUP + StatusMessage (hwndDlg, "INSTALLING_DRIVER"); +#endif + + hService = CreateService (hManager, L"veracrypt", L"veracrypt", + SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_SYSTEM_START, SERVICE_ERROR_NORMAL, + L"System32\\drivers\\veracrypt.sys", + NULL, NULL, NULL, NULL, NULL); + + if (hService == NULL) + goto error; + else + CloseServiceHandle (hService); + + hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS); + if (hService == NULL) + goto error; + +#ifdef SETUP + StatusMessage (hwndDlg, "STARTING_DRIVER"); +#endif + + bRet = StartService (hService, 0, NULL); + if (bRet == FALSE) + goto error; + + bOK = TRUE; + +error: + if (bOK == FALSE && GetLastError () != ERROR_SERVICE_ALREADY_RUNNING) + { + handleWin32Error (hwndDlg, SRC_POS); + MessageBoxW (hwndDlg, GetString ("DRIVER_INSTALL_FAILED"), lpszTitle, MB_ICONHAND); + } + else + bOK = TRUE; + + if (hService != NULL) + CloseServiceHandle (hService); + + if (hManager != NULL) + CloseServiceHandle (hManager); + + return bOK; +} + + +// Install and start driver service and mark it for removal (non-install mode) +static int DriverLoad () +{ + HANDLE file; + WIN32_FIND_DATA find; + SC_HANDLE hManager, hService = NULL; + wchar_t driverPath[TC_MAX_PATH*2]; + BOOL res; + wchar_t *tmp; + DWORD startType; + + if (ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", L"Start", &startType) && startType == SERVICE_BOOT_START) + return ERR_PARAMETER_INCORRECT; + + GetModuleFileName (NULL, driverPath, ARRAYSIZE (driverPath)); + tmp = wcsrchr (driverPath, L'\\'); + if (!tmp) + { + driverPath[0] = L'.'; + driverPath[1] = 0; + } + else + *tmp = 0; + + StringCbCatW (driverPath, sizeof(driverPath), !Is64BitOs () ? L"\\veracrypt.sys" : L"\\veracrypt-x64.sys"); + + file = FindFirstFile (driverPath, &find); + + if (file == INVALID_HANDLE_VALUE) + { + MessageBoxW (0, GetString ("DRIVER_NOT_FOUND"), lpszTitle, ICON_HAND); + return ERR_DONT_REPORT; + } + + FindClose (file); + + hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hManager == NULL) + { + if (GetLastError () == ERROR_ACCESS_DENIED) + { + MessageBoxW (0, GetString ("ADMIN_PRIVILEGES_DRIVER"), lpszTitle, ICON_HAND); + return ERR_DONT_REPORT; + } + + return ERR_OS_ERROR; + } + + hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS); + if (hService != NULL) + { + // Remove stale service (driver is not loaded but service exists) + DeleteService (hService); + CloseServiceHandle (hService); + Sleep (500); + } + + hService = CreateService (hManager, L"veracrypt", L"veracrypt", + SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + driverPath, NULL, NULL, NULL, NULL, NULL); + + if (hService == NULL) + { + CloseServiceHandle (hManager); + return ERR_OS_ERROR; + } + + res = StartService (hService, 0, NULL); + DeleteService (hService); + + CloseServiceHandle (hManager); + CloseServiceHandle (hService); + + return !res ? ERR_OS_ERROR : ERROR_SUCCESS; +} + + +BOOL DriverUnload () +{ + MOUNT_LIST_STRUCT driver; + int refCount; + int volumesMounted; + DWORD dwResult; + BOOL bResult; + + SC_HANDLE hManager, hService = NULL; + BOOL bRet; + SERVICE_STATUS status; + int x; + BOOL driverUnloaded = FALSE; + + if (hDriver == INVALID_HANDLE_VALUE) + return TRUE; + + try + { + if (BootEncryption (NULL).GetStatus().DeviceFilterActive) + return FALSE; + } + catch (...) { } + + // Test for mounted volumes + bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL); + + if (!bResult) + { + bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL); + if (bResult) + volumesMounted = driver.ulMountedDrives; + } + + if (bResult) + { + if (volumesMounted != 0) + return FALSE; + } + else + return TRUE; + + // Test for any applications attached to driver + refCount = GetDriverRefCount (); + + if (refCount > 1) + return FALSE; + + CloseHandle (hDriver); + hDriver = INVALID_HANDLE_VALUE; + + // Stop driver service + + hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hManager == NULL) + goto error; + + hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS); + if (hService == NULL) + goto error; + + bRet = QueryServiceStatus (hService, &status); + if (bRet != TRUE) + goto error; + + if (status.dwCurrentState != SERVICE_STOPPED) + { + ControlService (hService, SERVICE_CONTROL_STOP, &status); + + for (x = 0; x < 10; x++) + { + bRet = QueryServiceStatus (hService, &status); + if (bRet != TRUE) + goto error; + + if (status.dwCurrentState == SERVICE_STOPPED) + { + driverUnloaded = TRUE; + break; + } + + Sleep (200); + } + } + else + driverUnloaded = TRUE; + +error: + if (hService != NULL) + CloseServiceHandle (hService); + + if (hManager != NULL) + CloseServiceHandle (hManager); + + if (driverUnloaded) + { + hDriver = INVALID_HANDLE_VALUE; + return TRUE; + } + + return FALSE; +} + + +int DriverAttach (void) +{ + /* Try to open a handle to the device driver. It will be closed later. */ + +#ifndef SETUP + + int nLoadRetryCount = 0; +start: + +#endif + + hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (hDriver == INVALID_HANDLE_VALUE) + { +#ifndef SETUP + + LoadSysEncSettings (); + + if (!CreateDriverSetupMutex ()) + { + // Another instance is already attempting to install, register or start the driver + + while (!CreateDriverSetupMutex ()) + { + Sleep (100); // Wait until the other instance finishes + } + + // Try to open a handle to the driver again (keep the mutex in case the other instance failed) + goto start; + } + else + { + // No other instance is currently attempting to install, register or start the driver + + if (SystemEncryptionStatus != SYSENC_STATUS_NONE) + { + // This is an inconsistent state. The config file indicates system encryption should be + // active, but the driver is not running. This may happen e.g. when the pretest fails and + // the user selects "Last Known Good Configuration" from the Windows boot menu. + // To fix this, we're going to reinstall the driver, start it, and register it for boot. + + if (DoDriverInstall (NULL)) + { + Sleep (1000); + hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + try + { + BootEncryption bootEnc (NULL); + bootEnc.RegisterBootDriver (bootEnc.GetHiddenOSCreationPhase() != TC_HIDDEN_OS_CREATION_PHASE_NONE ? true : false); + } + catch (Exception &e) + { + e.Show (NULL); + } + } + + CloseDriverSetupMutex (); + } + else + { + // Attempt to load the driver (non-install/portable mode) +load: + BOOL res = DriverLoad (); + + CloseDriverSetupMutex (); + + if (res != ERROR_SUCCESS) + return res; + + bPortableModeConfirmed = TRUE; + + if (hDriver != INVALID_HANDLE_VALUE) + CloseHandle (hDriver); + hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + } + + if (bPortableModeConfirmed) + NotifyDriverOfPortableMode (); + } + +#endif // #ifndef SETUP + + if (hDriver == INVALID_HANDLE_VALUE) + return ERR_OS_ERROR; + } + + CloseDriverSetupMutex (); + + if (hDriver != INVALID_HANDLE_VALUE) + { + DWORD dwResult; + + BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL); + + if (!bResult) + bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL); + +#ifndef SETUP // Don't check version during setup to allow removal of another version + if (bResult == FALSE) + { + return ERR_OS_ERROR; + } + else if (DriverVersion != VERSION_NUM) + { + // Unload an incompatbile version of the driver loaded in non-install mode and load the required version + if (IsNonInstallMode () && CreateDriverSetupMutex () && DriverUnload () && nLoadRetryCount++ < 3) + goto load; + + CloseDriverSetupMutex (); + 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) +{ + return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, browseFilter); +} + + +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 }; + wchar_t filter[1024]; + BOOL status = FALSE; + + CoInitialize (NULL); + + ZeroMemory (&ofn, sizeof (ofn)); + *lpszFileName = 0; + + if (initialDir) + { + ofn.lpstrInitialDir = initialDir; + } + + 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) + { + if (!GetOpenFileNameW (&ofn)) + goto ret; + } + else + { + if (!GetSaveFileNameW (&ofn)) + goto ret; + } + + SystemFileSelectorCallPending = FALSE; + + StringCchCopyW (lpszFileName, MAX_PATH, file); + + if (!keepHistory) + CleanLastVisitedMRU (); + + status = TRUE; + +ret: + SystemFileSelectorCallPending = FALSE; + ResetCurrentDirectory(); + CoUninitialize(); + + return status; +} + + +static wchar_t SelectMultipleFilesPath[131072]; +static int SelectMultipleFilesOffset; + +BOOL SelectMultipleFiles (HWND hwndDlg, const char *stringId, wchar_t *lpszFileName, size_t cbFileName,BOOL keepHistory) +{ + OPENFILENAMEW ofn; + wchar_t filter[1024]; + BOOL status = FALSE; + + 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 (); + + SystemFileSelectorCallerThreadId = GetCurrentThreadId(); + SystemFileSelectorCallPending = TRUE; + + if (!GetOpenFileNameW (&ofn)) + goto ret; + + SystemFileSelectorCallPending = FALSE; + + 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); + } + + if (!keepHistory) + CleanLastVisitedMRU (); + + status = TRUE; + +ret: + SystemFileSelectorCallPending = FALSE; + ResetCurrentDirectory(); + CoUninitialize(); + + return status; +} + + +BOOL SelectMultipleFilesNext (wchar_t *lpszFileName, size_t cbFileName) +{ + if (SelectMultipleFilesOffset == 0) + return FALSE; + + StringCbCopyW (lpszFileName, cbFileName,SelectMultipleFilesPath); + lpszFileName[TC_MAX_PATH - 1] = 0; + + if (lpszFileName[wcslen (lpszFileName) - 1] != L'\\') + StringCbCatW (lpszFileName, cbFileName,L"\\"); + + StringCbCatW (lpszFileName, cbFileName,SelectMultipleFilesPath + SelectMultipleFilesOffset); + + SelectMultipleFilesOffset += (int) wcslen (SelectMultipleFilesPath + SelectMultipleFilesOffset) + 1; + if (SelectMultipleFilesPath[SelectMultipleFilesOffset] == 0) + { + SelectMultipleFilesOffset = 0; + SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath)); + } + + return TRUE; +} + + +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; + } + + case BFFM_SELCHANGED: + { + wchar_t szDir[TC_MAX_PATH]; + + /* Set the status window to the currently selected path. */ + if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir)) + { + SendMessage (hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir); + } + break; + } + + default: + break; + } + + return 0; +} + + +BOOL BrowseDirectories (HWND hwndDlg, char *lpszTitle, wchar_t *dirName) +{ + BROWSEINFOW bi; + LPITEMIDLIST pidl; + LPMALLOC pMalloc; + BOOL bOK = FALSE; + + CoInitialize (NULL); + + if (SUCCEEDED (SHGetMalloc (&pMalloc))) + { + 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; + + pidl = SHBrowseForFolderW (&bi); + if (pidl != NULL) + { + if (SHGetPathFromIDList(pidl, dirName)) + { + bOK = TRUE; + } + + pMalloc->Free (pidl); + pMalloc->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; + } +#endif + + return msg; +} + + +void handleError (HWND hwndDlg, int code, const char* srcPos) +{ + WCHAR szTmp[4096]; + + if (Silent) return; + + switch (code & 0x0000FFFF) + { + case ERR_OS_ERROR: + handleWin32Error (hwndDlg, srcPos); + break; + case ERR_OUTOFMEMORY: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OUTOFMEMORY"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + + case ERR_PASSWORD_WRONG: + MessageBoxW (hwndDlg, AppendSrcPos (GetWrongPasswordErrorMessage (hwndDlg).c_str(), srcPos).c_str(), lpszTitle, MB_ICONWARNING); + break; + + case ERR_DRIVE_NOT_FOUND: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NOT_FOUND"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_FILES_OPEN: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OPENFILES_DRIVER"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_FILES_OPEN_LOCK: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OPENFILES_LOCK"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_VOL_SIZE_WRONG: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_SIZE_WRONG"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_COMPRESSION_NOT_SUPPORTED: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("COMPRESSION_NOT_SUPPORTED"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_PASSWORD_CHANGE_VOL_TYPE: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("WRONG_VOL_TYPE"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_VOL_SEEKING: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_SEEKING"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_CIPHER_INIT_FAILURE: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_CIPHER_INIT_FAILURE"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_CIPHER_INIT_WEAK_KEY: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_CIPHER_INIT_WEAK_KEY"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_VOL_ALREADY_MOUNTED: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_ALREADY_MOUNTED"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_FILE_OPEN_FAILED: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("FILE_OPEN_FAILED"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_VOL_MOUNT_FAILED: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_MOUNT_FAILED"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_NO_FREE_DRIVES: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NO_FREE_DRIVES"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + case ERR_ACCESS_DENIED: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ACCESS_DENIED"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + + case ERR_DRIVER_VERSION: + Error ("DRIVER_VERSION", hwndDlg); + break; + + case ERR_NEW_VERSION_REQUIRED: + MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NEW_VERSION_REQUIRED"), srcPos).c_str(), lpszTitle, ICON_HAND); + break; + + case ERR_SELF_TESTS_FAILED: + Error ("ERR_SELF_TESTS_FAILED", hwndDlg); + break; + + case ERR_VOL_FORMAT_BAD: + Error ("ERR_VOL_FORMAT_BAD", hwndDlg); + break; + + case ERR_ENCRYPTION_NOT_COMPLETED: + Error ("ERR_ENCRYPTION_NOT_COMPLETED", hwndDlg); + break; + + 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; + + case ERR_UNSUPPORTED_TRUECRYPT_FORMAT: + StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("UNSUPPORTED_TRUECRYPT_FORMAT"), (code >> 24), (code >> 16) & 0x000000FF); + MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, ICON_HAND); + 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 + + 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) + { + WCHAR name[10] = { 0 }; + GetClassNameW (hwnd, name, array_capacity (name)); + + if (_wcsicmp (name, L"Button") == 0 || _wcsicmp (name, L"Static") == 0) + { + wchar_t *str = (wchar_t *) GetDictionaryValueByInt (ctrlId); + if (str != NULL) + SetWindowTextW (hwnd, str); + } + } + } + + // Font + SendMessageW (hwnd, WM_SETFONT, (WPARAM) font, 0); + + return TRUE; +} + +void LocalizeDialog (HWND hwnd, char *stringId) +{ + LastDialogId = stringId; + SetWindowLongPtrW (hwnd, GWLP_USERDATA, (LONG_PTR) 'VERA'); + SendMessageW (hwnd, WM_SETFONT, (WPARAM) hUserFont, 0); + + if (stringId == NULL) + SetWindowTextW (hwnd, L"VeraCrypt"); + else + SetWindowTextW (hwnd, GetString (stringId)); + + if (hUserFont != 0) + EnumChildWindows (hwnd, LocalizeDialogEnum, (LPARAM) hUserFont); +} + +void OpenVolumeExplorerWindow (int driveNo) +{ + wchar_t dosName[5]; + SHFILEINFO fInfo; + + StringCbPrintfW (dosName, sizeof(dosName), L"%c:\\", (wchar_t) driveNo + L'A'); + + // Force explorer to discover the drive + SHGetFileInfo (dosName, 0, &fInfo, sizeof (fInfo), 0); + + ShellExecute (NULL, L"open", dosName, NULL, NULL, SW_SHOWNORMAL); +} + +static BOOL explorerCloseSent; +static HWND explorerTopLevelWindow; + +static BOOL CALLBACK CloseVolumeExplorerWindowsChildEnum (HWND hwnd, LPARAM driveStr) +{ + WCHAR s[MAX_PATH]; + SendMessageW (hwnd, WM_GETTEXT, array_capacity (s), (LPARAM) s); + + if (wcsstr (s, (WCHAR *) driveStr) != NULL) + { + PostMessageW (explorerTopLevelWindow, WM_CLOSE, 0, 0); + explorerCloseSent = TRUE; + return FALSE; + } + + return TRUE; +} + +static BOOL CALLBACK CloseVolumeExplorerWindowsEnum (HWND hwnd, LPARAM driveNo) +{ + WCHAR driveStr[10]; + WCHAR s[MAX_PATH]; + + StringCbPrintfW (driveStr, sizeof(driveStr), L"%c:\\", driveNo + L'A'); + + GetClassNameW (hwnd, s, array_capacity (s)); + if (wcscmp (s, L"CabinetWClass") == 0) + { + GetWindowTextW (hwnd, s, array_capacity (s)); + if (wcsstr (s, driveStr) != NULL) + { + PostMessageW (hwnd, WM_CLOSE, 0, 0); + explorerCloseSent = TRUE; + return TRUE; + } + + explorerTopLevelWindow = hwnd; + EnumChildWindows (hwnd, CloseVolumeExplorerWindowsChildEnum, (LPARAM) driveStr); + } + + return TRUE; +} + +BOOL CloseVolumeExplorerWindows (HWND hwnd, int driveNo) +{ + if (driveNo >= 0) + { + explorerCloseSent = FALSE; + EnumWindows (CloseVolumeExplorerWindowsEnum, (LPARAM) driveNo); + } + + return explorerCloseSent; +} + +BOOL UpdateDriveCustomLabel (int driveNo, wchar_t* effectiveLabel, BOOL bSetValue) +{ + wchar_t wszRegPath[MAX_PATH]; + wchar_t driveStr[] = {L'A' + (wchar_t) driveNo, 0}; + HKEY hKey; + LSTATUS lStatus; + DWORD cbLabelLen = (DWORD) ((wcslen (effectiveLabel) + 1) * sizeof (wchar_t)); + BOOL bToBeDeleted = FALSE; + + StringCbPrintfW (wszRegPath, sizeof (wszRegPath), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%s\\DefaultLabel", driveStr); + + if (bSetValue) + lStatus = RegCreateKeyExW (HKEY_CURRENT_USER, wszRegPath, NULL, NULL, 0, + KEY_READ | KEY_WRITE | KEY_SET_VALUE, NULL, &hKey, NULL); + else + lStatus = RegOpenKeyExW (HKEY_CURRENT_USER, wszRegPath, 0, KEY_READ | KEY_WRITE | KEY_SET_VALUE, &hKey); + if (ERROR_SUCCESS == lStatus) + { + if (bSetValue) + lStatus = RegSetValueExW (hKey, NULL, NULL, REG_SZ, (LPCBYTE) effectiveLabel, cbLabelLen); + else + { + wchar_t storedLabel[34] = {0}; + DWORD cbStoredLen = sizeof (storedLabel) - 1, dwType; + lStatus = RegQueryValueExW (hKey, NULL, NULL, &dwType, (LPBYTE) storedLabel, &cbStoredLen); + if ((ERROR_SUCCESS == lStatus) && (REG_SZ == dwType) && (0 == wcscmp(storedLabel, effectiveLabel))) + { + // same label stored. mark key for deletion + bToBeDeleted = TRUE; + } + } + RegCloseKey (hKey); + } + + if (bToBeDeleted) + { + StringCbPrintfW (wszRegPath, sizeof (wszRegPath), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%s", driveStr); + lStatus = RegOpenKeyExW (HKEY_CURRENT_USER, wszRegPath, 0, KEY_READ | KEY_WRITE | KEY_SET_VALUE, &hKey); + if (ERROR_SUCCESS == lStatus) + { + lStatus = RegDeleteKeyW (hKey, L"DefaultLabel"); + RegCloseKey (hKey); + } + + // delete drive letter of nothing else is present under it + RegDeleteKeyW (HKEY_CURRENT_USER, wszRegPath); + + } + + return (ERROR_SUCCESS == lStatus)? TRUE : FALSE; +} + +wstring GetUserFriendlyVersionString (int version) +{ + wchar_t szTmp [64]; + StringCbPrintfW (szTmp, sizeof(szTmp), L"%x", version); + + wstring versionString (szTmp); + + versionString.insert (version > 0xfff ? 2 : 1,L"."); + + if (versionString[versionString.length()-1] == L'0') + versionString.erase (versionString.length()-1, 1); + + 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 bRet = true; + if (c >= L'0' && c <= L'9') + b = (byte) (c - L'0'); + else if (c >= L'a' && c <= L'z') + b = (byte) (c - L'a' + 10); + else if (c >= L'A' && c <= L'Z') + b = (byte) (c - L'A' + 10); + else + bRet = false; + + return bRet; +} + +bool HexWideStringToArray (const wchar_t* hexStr, std::vector& arr) +{ + byte 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; + + if (b == NULL || serNo != LocalizationSerialNo) + { + serNo = LocalizationSerialNo; + kb = GetString ("KB"); + mb = GetString ("MB"); + gb = GetString ("GB"); + tb = GetString ("TB"); + pb = GetString ("PB"); + b = GetString ("BYTE"); + } + + if (size > 1024I64*1024*1024*1024*1024*99) + StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024/1024/1024/1024/1024, pb); + else if (size > 1024I64*1024*1024*1024*1024) + StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024/1024/1024), pb); + else if (size > 1024I64*1024*1024*1024*99) + StringCbPrintfW (str, cbStr, L"%I64d %s",size/1024/1024/1024/1024, tb); + else if (size > 1024I64*1024*1024*1024) + StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024/1024), tb); + else if (size > 1024I64*1024*1024*99) + StringCbPrintfW (str, cbStr, L"%I64d %s",size/1024/1024/1024, gb); + else if (size > 1024I64*1024*1024) + StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024), gb); + else if (size > 1024I64*1024*99) + StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024/1024, mb); + else if (size > 1024I64*1024) + StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024), mb); + else if (size >= 1024I64) + StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024, kb); + else + StringCbPrintfW (str, cbStr, L"%I64d %s", size, b); +} + +#ifndef SETUP +void GetSpeedString (unsigned __int64 speed, wchar_t *str, size_t cbStr) +{ + static wchar_t *b, *kb, *mb, *gb, *tb, *pb; + static int serNo; + + if (b == NULL || serNo != LocalizationSerialNo) + { + serNo = LocalizationSerialNo; + kb = GetString ("KB_PER_SEC"); + mb = GetString ("MB_PER_SEC"); + gb = GetString ("GB_PER_SEC"); + tb = GetString ("TB_PER_SEC"); + pb = GetString ("PB_PER_SEC"); + b = GetString ("B_PER_SEC"); + } + + if (speed > 1024I64*1024*1024*1024*1024*99) + StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024/1024/1024/1024/1024, pb); + else if (speed > 1024I64*1024*1024*1024*1024) + StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024/1024), pb); + else if (speed > 1024I64*1024*1024*1024*99) + StringCbPrintfW (str, cbStr, L"%I64d %s",speed/1024/1024/1024/1024, tb); + else if (speed > 1024I64*1024*1024*1024) + StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024), tb); + else if (speed > 1024I64*1024*1024*99) + StringCbPrintfW (str, cbStr, L"%I64d %s",speed/1024/1024/1024, gb); + else if (speed > 1024I64*1024*1024) + StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024), gb); + else if (speed > 1024I64*1024*99) + StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024/1024, mb); + else if (speed > 1024I64*1024) + StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024), mb); + else if (speed > 1024I64) + StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024, kb); + else + StringCbPrintfW (str, cbStr, L"%I64d %s", speed, b); +} + +static void DisplayBenchmarkResults (HWND hwndDlg) +{ + wchar_t item1[100]={0}; + LVITEMW LvItem; + HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); + int ea, i; + BOOL unsorted = TRUE; + BENCHMARK_REC tmp_line; + + /* Sort the list */ + + switch (benchmarkSortMethod) + { + case BENCHMARK_SORT_BY_SPEED: + + while (unsorted) + { + unsorted = FALSE; + for (i = 0; i < benchmarkTotalItems - 1; i++) + { + if (benchmarkTable[i].meanBytesPerSec < benchmarkTable[i+1].meanBytesPerSec) + { + unsorted = TRUE; + memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC)); + memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC)); + memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC)); + } + } + } + break; + + case BENCHMARK_SORT_BY_NAME: + + while (unsorted) + { + unsorted = FALSE; + for (i = 0; i < benchmarkTotalItems - 1; i++) + { + if (benchmarkTable[i].id > benchmarkTable[i+1].id) + { + unsorted = TRUE; + memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC)); + memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC)); + memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC)); + } + } + } + break; + } + + /* Render the results */ + + SendMessage (hList,LVM_DELETEALLITEMS,0,(LPARAM)&LvItem); + + for (i = 0; i < benchmarkTotalItems; i++) + { + ea = benchmarkTable[i].id; + + memset (&LvItem,0,sizeof(LvItem)); + LvItem.mask = LVIF_TEXT; + LvItem.iItem = i; + LvItem.iSubItem = 0; + LvItem.pszText = (LPWSTR) benchmarkTable[i].name; + SendMessageW (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); + +#if PKCS5_BENCHMARKS + wcscpy (item1, L"-"); +#else + GetSpeedString ((unsigned __int64) (benchmarkLastBufferSize / ((float) benchmarkTable[i].encSpeed / benchmarkPerformanceFrequency.QuadPart)), item1, sizeof(item1)); +#endif + LvItem.iSubItem = 1; + LvItem.pszText = item1; + + SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); + +#if PKCS5_BENCHMARKS + wcscpy (item1, L"-"); +#else + GetSpeedString ((unsigned __int64) (benchmarkLastBufferSize / ((float) benchmarkTable[i].decSpeed / benchmarkPerformanceFrequency.QuadPart)), item1, sizeof(item1)); +#endif + LvItem.iSubItem = 2; + LvItem.pszText = item1; + + SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); + +#if PKCS5_BENCHMARKS + swprintf (item1, L"%d t", benchmarkTable[i].encSpeed); +#else + GetSpeedString (benchmarkTable[i].meanBytesPerSec, item1, sizeof(item1)); +#endif + LvItem.iSubItem = 3; + LvItem.pszText = item1; + + SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); + } + + SendMessageW(hList, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); + SendMessageW(hList, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); + SendMessageW(hList, LVM_SETCOLUMNWIDTH, 2, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); + SendMessageW(hList, LVM_SETCOLUMNWIDTH, 3, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); +} + +// specific implementation for support of benchmark operation in wait dialog mechanism + +typedef struct +{ + HWND hBenchDlg; + BOOL bStatus; +} BenchmarkThreadParam; + +static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg); + +void CALLBACK BenchmarkThreadProc(void* pArg, HWND hwndDlg) +{ + BenchmarkThreadParam* pThreadParam = (BenchmarkThreadParam*) pArg; + + pThreadParam->bStatus = PerformBenchmark (pThreadParam->hBenchDlg, hwndDlg); +} + +static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg) +{ + LARGE_INTEGER performanceCountStart, performanceCountEnd; + BYTE *lpTestBuffer; + PCRYPTO_INFO ci = NULL; + UINT64_STRUCT startDataUnitNo; + + startDataUnitNo.Value = 0; + +#if !(PKCS5_BENCHMARKS || HASH_FNC_BENCHMARKS) + ci = crypto_open (); + if (!ci) + return FALSE; +#endif + + if (QueryPerformanceFrequency (&benchmarkPerformanceFrequency) == 0) + { + if (ci) + crypto_close (ci); + MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); + return FALSE; + } + + lpTestBuffer = (BYTE *) malloc(benchmarkBufferSize - (benchmarkBufferSize % 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; + +#if !(PKCS5_BENCHMARKS || HASH_FNC_BENCHMARKS) + // CPU "warm up" (an attempt to prevent skewed results on systems where CPU frequency + // gradually changes depending on CPU load). + ci->ea = EAGetFirst(); + if (!EAInit (ci->ea, ci->master_keydata, ci->ks)) + { + ci->mode = FIRST_MODE_OF_OPERATION_ID; + if (EAInitMode (ci)) + { + int i; + + for (i = 0; i < 10; i++) + { + EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); + DecryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); + } + } + } +#endif + +#if HASH_FNC_BENCHMARKS + + /* Measures the speed at which each of the hash algorithms processes the message to produce + a single digest. + + The hash algorithm benchmarks are included here for development purposes only. Do not enable + them when building a public release (the benchmark GUI strings wouldn't make sense). */ + + { + BYTE *digest [MAX_DIGESTSIZE]; + WHIRLPOOL_CTX wctx; + RMD160_CTX rctx; + sha512_ctx s2ctx; + sha256_ctx s256ctx; + int hid; + + for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) + { + if (QueryPerformanceCounter (&performanceCountStart) == 0) + goto counter_error; + + 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; + + case RIPEMD160: + RMD160Init(&rctx); + RMD160Update(&rctx, lpTestBuffer, benchmarkBufferSize); + RMD160Final((unsigned char *) digest, &rctx); + break; + + case WHIRLPOOL: + WHIRLPOOL_init (&wctx); + WHIRLPOOL_add (lpTestBuffer, benchmarkBufferSize * 8, &wctx); + WHIRLPOOL_finalize (&wctx, (unsigned char *) digest); + break; + } + + 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)) + (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].decSpeed / benchmarkPerformanceFrequency.QuadPart))) / 2; + StringCbPrintfA (benchmarkTable[benchmarkTotalItems].name, sizeof(benchmarkTable[benchmarkTotalItems].name),"%s", HashGetName(hid)); + + benchmarkTotalItems++; + } + } + +#elif PKCS5_BENCHMARKS // #if HASH_FNC_BENCHMARKS + + /* Measures the time that it takes for the PKCS-5 routine to derive a header key using + each of the implemented PRF algorithms. + + The PKCS-5 benchmarks are included here for development purposes only. Do not enable + them when building a public release (the benchmark GUI strings wouldn't make sense). */ + { + 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 (QueryPerformanceCounter (&performanceCountStart) == 0) + goto counter_error; + + for (i = 1; i <= 5; 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, 0, FALSE, FALSE), 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, 0, FALSE, FALSE), dk, MASTER_KEYDATA_SIZE); + break; + + case RIPEMD160: + /* PKCS-5 test with HMAC-RIPEMD-160 used as the PRF */ + derive_key_ripemd160 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, 0, FALSE, FALSE), 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, 0, FALSE, FALSE), dk, MASTER_KEYDATA_SIZE); + break; + } + } + + if (QueryPerformanceCounter (&performanceCountEnd) == 0) + goto counter_error; + + benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; + benchmarkTable[benchmarkTotalItems].id = thid; + StringCbPrintfW (benchmarkTable[benchmarkTotalItems].name, sizeof(benchmarkTable[benchmarkTable[benchmarkTotalItems].name),L"%s", get_pkcs5_prf_name (thid)); + + benchmarkTotalItems++; + } + } + +#else // #elif PKCS5_BENCHMARKS + + /* Encryption algorithm benchmarks */ + + for (ci->ea = EAGetFirst(); ci->ea != 0; ci->ea = EAGetNext(ci->ea)) + { + if (!EAIsFormatEnabled (ci->ea)) + continue; + + if (ERR_CIPHER_INIT_FAILURE == EAInit (ci->ea, ci->master_keydata, ci->ks)) + goto counter_error; + + ci->mode = FIRST_MODE_OF_OPERATION_ID; + if (!EAInitMode (ci)) + goto counter_error; + + if (QueryPerformanceCounter (&performanceCountStart) == 0) + goto counter_error; + + EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); + + if (QueryPerformanceCounter (&performanceCountEnd) == 0) + goto counter_error; + + benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; + + if (QueryPerformanceCounter (&performanceCountStart) == 0) + goto counter_error; + + DecryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); + + if (QueryPerformanceCounter (&performanceCountEnd) == 0) + goto counter_error; + + benchmarkTable[benchmarkTotalItems].decSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; + benchmarkTable[benchmarkTotalItems].id = ci->ea; + benchmarkTable[benchmarkTotalItems].meanBytesPerSec = ((unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart)) + (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].decSpeed / benchmarkPerformanceFrequency.QuadPart))) / 2; + EAGetName (benchmarkTable[benchmarkTotalItems].name, ci->ea, 1); + + benchmarkTotalItems++; + } + +#endif // #elif PKCS5_BENCHMARKS (#else) + + if (ci) + crypto_close (ci); + + VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); + + free(lpTestBuffer); + + benchmarkLastBufferSize = benchmarkBufferSize; + + DisplayBenchmarkResults(hBenchDlg); + + EnableWindow (GetDlgItem (hBenchDlg, IDC_PERFORM_BENCHMARK), TRUE); + EnableWindow (GetDlgItem (hBenchDlg, IDCLOSE), TRUE); + + NormalCursor (); + return TRUE; + +counter_error: + + if (ci) + crypto_close (ci); + + VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); + + free(lpTestBuffer); + + NormalCursor (); + + EnableWindow (GetDlgItem (hBenchDlg, IDC_PERFORM_BENCHMARK), TRUE); + EnableWindow (GetDlgItem (hBenchDlg, IDCLOSE), TRUE); + + MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); + return FALSE; +} + + +BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + LPARAM nIndex; + HWND hCboxSortMethod = GetDlgItem (hwndDlg, IDC_BENCHMARK_SORT_METHOD); + HWND hCboxBufferSize = GetDlgItem (hwndDlg, IDC_BENCHMARK_BUFFER_SIZE); + + switch (msg) + { + case WM_INITDIALOG: + { + LVCOLUMNW LvCol; + wchar_t s[128]; + HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); + + LocalizeDialog (hwndDlg, "IDD_BENCHMARK_DLG"); + + benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; + benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED; + + SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, + LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP + ); + + memset (&LvCol,0,sizeof(LvCol)); + LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; + LvCol.pszText = GetString ("ALGORITHM"); + LvCol.cx = CompensateXDPI (114); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("ENCRYPTION"); + LvCol.cx = CompensateXDPI (80); + LvCol.fmt = LVCFMT_RIGHT; + SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("DECRYPTION"); + LvCol.cx = CompensateXDPI (80); + LvCol.fmt = LVCFMT_RIGHT; + SendMessageW (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); + + LvCol.pszText = GetString ("MEAN"); + LvCol.cx = CompensateXDPI (80); + LvCol.fmt = LVCFMT_RIGHT; + SendMessageW (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol); + + /* Combo boxes */ + + // Sort method + + SendMessage (hCboxSortMethod, CB_RESETCONTENT, 0, 0); + + nIndex = SendMessageW (hCboxSortMethod, CB_ADDSTRING, 0, (LPARAM) GetString ("ALPHABETICAL_CATEGORIZED")); + SendMessage (hCboxSortMethod, CB_SETITEMDATA, nIndex, (LPARAM) 0); + + nIndex = SendMessageW (hCboxSortMethod, CB_ADDSTRING, 0, (LPARAM) GetString ("MEAN_SPEED")); + SendMessage (hCboxSortMethod, CB_SETITEMDATA, nIndex, (LPARAM) 0); + + SendMessage (hCboxSortMethod, CB_SETCURSEL, 1, 0); // Default sort method + + // Buffer size + + SendMessage (hCboxBufferSize, CB_RESETCONTENT, 0, 0); + + StringCbPrintfW (s, sizeof(s), L"100 %s", GetString ("KB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 100 * BYTES_PER_KB); + + StringCbPrintfW (s, sizeof(s), L"500 %s", GetString ("KB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 500 * BYTES_PER_KB); + + StringCbPrintfW (s, sizeof(s), L"1 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 1 * BYTES_PER_MB); + + StringCbPrintfW (s, sizeof(s), L"5 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 5 * BYTES_PER_MB); + + StringCbPrintfW (s, sizeof(s), L"10 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 10 * BYTES_PER_MB); + + StringCbPrintfW (s, sizeof(s), L"50 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 50 * BYTES_PER_MB); + + StringCbPrintfW (s, sizeof(s), L"100 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 100 * BYTES_PER_MB); + + StringCbPrintfW (s, sizeof(s), L"200 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 200 * BYTES_PER_MB); + + StringCbPrintfW (s, sizeof(s), L"500 %s", GetString ("MB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 500 * BYTES_PER_MB); + + StringCbPrintfW (s, sizeof(s), L"1 %s", GetString ("GB")); + nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); + SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 1 * BYTES_PER_GB); + + SendMessage (hCboxBufferSize, CB_SETCURSEL, 5, 0); // Default buffer size + + + uint32 driverConfig = ReadDriverConfigurationFlags(); + + SetDlgItemTextW (hwndDlg, IDC_HW_AES, (wstring (L" ") + (GetString (is_aes_hw_cpu_supported() ? ((driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION) ? "UISTR_DISABLED" : "UISTR_YES") : "NOT_APPLICABLE_OR_NOT_AVAILABLE"))).c_str()); + + ToHyperlink (hwndDlg, IDC_HW_AES_LABEL_LINK); + + if (is_aes_hw_cpu_supported() && (driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION)) + { + Warning ("DISABLED_HW_AES_AFFECTS_PERFORMANCE", hwndDlg); + } + + SYSTEM_INFO sysInfo; + GetSystemInfo (&sysInfo); + + size_t nbrThreads = GetEncryptionThreadCount(); + + wchar_t nbrThreadsStr [300]; + if (sysInfo.dwNumberOfProcessors < 2) + { + StringCbCopyW (nbrThreadsStr, sizeof(nbrThreadsStr), GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE")); + } + else if (nbrThreads < 2) + { + StringCbCopyW (nbrThreadsStr, sizeof(nbrThreadsStr), GetString ("UISTR_DISABLED")); + } + else + { + StringCbPrintfW (nbrThreadsStr, sizeof(nbrThreadsStr), GetString ("NUMBER_OF_THREADS"), nbrThreads); + } + + SetDlgItemTextW (hwndDlg, IDC_PARALLELIZATION, (wstring (L" ") + nbrThreadsStr).c_str()); + + ToHyperlink (hwndDlg, IDC_PARALLELIZATION_LABEL_LINK); + + if (nbrThreads < min (sysInfo.dwNumberOfProcessors, GetMaxEncryptionThreadCount()) + && sysInfo.dwNumberOfProcessors > 1) + { + Warning ("LIMITED_THREAD_COUNT_AFFECTS_PERFORMANCE", hwndDlg); + } + + return 1; + } + break; + + case WM_COMMAND: + + switch (lw) + { + case IDC_BENCHMARK_SORT_METHOD: + + nIndex = SendMessage (hCboxSortMethod, CB_GETCURSEL, 0, 0); + if (nIndex != benchmarkSortMethod) + { + benchmarkSortMethod = (int) nIndex; + DisplayBenchmarkResults (hwndDlg); + } + return 1; + + case IDC_PERFORM_BENCHMARK: + + nIndex = SendMessage (hCboxBufferSize, CB_GETCURSEL, 0, 0); + benchmarkBufferSize = (int) SendMessage (hCboxBufferSize, CB_GETITEMDATA, nIndex, 0); + + BenchmarkThreadParam threadParam; + threadParam.hBenchDlg = hwndDlg; + threadParam.bStatus = FALSE; + + WaitCursor (); + + ShowWaitDialog (hwndDlg, TRUE, BenchmarkThreadProc, &threadParam); + + NormalCursor (); + + if (threadParam.bStatus == FALSE) + { + EndDialog (hwndDlg, IDCLOSE); + } + return 1; + + case IDC_HW_AES_LABEL_LINK: + + Applink ("hwacceleration", TRUE, ""); + return 1; + + case IDC_PARALLELIZATION_LABEL_LINK: + + Applink ("parallelization", TRUE, ""); + return 1; + + case IDCLOSE: + case IDCANCEL: + + EndDialog (hwndDlg, IDCLOSE); + return 1; + } + return 0; + + break; + + case WM_CLOSE: + EndDialog (hwndDlg, IDCLOSE); + return 1; + + break; + + } + return 0; +} + + +static BOOL CALLBACK RandomPoolEnrichementDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + static unsigned char randPool [RNG_POOL_SIZE]; + static unsigned char lastRandPool [RNG_POOL_SIZE]; + static unsigned char maskRandPool [RNG_POOL_SIZE]; + static BOOL bUseMask = FALSE; + static DWORD mouseEntropyGathered = 0xFFFFFFFF; + static DWORD mouseEventsInitialCount = 0; + /* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */ + static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8; + static HWND hEntropyBar = NULL; + static wchar_t outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; + static BOOL bDisplayPoolContents = FALSE; + static BOOL bRandPoolDispAscii = FALSE; + int hash_algo = RandGetHashFunction(); + int hid; + + switch (msg) + { + case WM_INITDIALOG: + { + HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); + HCRYPTPROV hRngProv = NULL; + + VirtualLock (randPool, sizeof(randPool)); + VirtualLock (lastRandPool, sizeof(lastRandPool)); + VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); + VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); + VirtualLock (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); + VirtualLock (maskRandPool, sizeof(maskRandPool)); + + mouseEntropyGathered = 0xFFFFFFFF; + mouseEventsInitialCount = 0; + bUseMask = FALSE; + if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + { + if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool)) + bUseMask = TRUE; + CryptReleaseContext (hRngProv, 0); + } + + LocalizeDialog (hwndDlg, "IDD_RANDOM_POOL_ENRICHMENT"); + + SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); + for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) + { + if (!HashIsDeprecated (hid)) + AddComboPair (hComboBox, HashGetName(hid), hid); + } + SelectAlgo (hComboBox, &hash_algo); + + SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents); + + SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); + SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); + + 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); + 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 */ + tmpByte = (randPool[row * RANDPOOL_DISPLAY_COLUMNS + col] - + lastRandPool[row * RANDPOOL_DISPLAY_COLUMNS + col]) ^ maskRandPool [row * RANDPOOL_DISPLAY_COLUMNS + col]; + tmp[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*'); + tmp[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*'); + tmp[2] = L' '; + tmp[3] = 0; + } + else + { + StringCbCopyW (tmp, sizeof(tmp), L"** "); + } + + StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), tmp); + } + StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), L"\n"); + } + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); + + memcpy (lastRandPool, randPool, sizeof(lastRandPool)); + } + return 1; + } + + case WM_COMMAND: + if (lw == IDC_CONTINUE) + lw = IDOK; + + if (lw == IDOK || lw == IDCLOSE || lw == IDCANCEL) + { + 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; + } + + return 0; + + case WM_CLOSE: + { + wchar_t tmp[RNG_POOL_SIZE+1]; +exit: + KillTimer (hwndDlg, 0xfd); + + burn (randPool, sizeof(randPool)); + burn (lastRandPool, sizeof(lastRandPool)); + burn (outputDispBuffer, sizeof(outputDispBuffer)); + burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); + burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); + burn (maskRandPool, sizeof(maskRandPool)); + + // Attempt to wipe the pool contents in the GUI text area + wmemset (tmp, L' ', RNG_POOL_SIZE); + tmp [RNG_POOL_SIZE] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); + + if (msg == WM_COMMAND && lw == IDOK) + EndDialog (hwndDlg, IDOK); + else + EndDialog (hwndDlg, IDCLOSE); + + return 1; + } + } + return 0; +} + +/* Randinit is always called before UserEnrichRandomPool, so we don't need + * the extra Randinit call here since it will always succeed but we keep it + * for clarity purposes + */ +void UserEnrichRandomPool (HWND hwndDlg) +{ + if ((0 == Randinit()) && !IsRandomPoolEnrichedByUser()) + { + INT_PTR result = DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_RANDOM_POOL_ENRICHMENT), hwndDlg ? hwndDlg : MainDlg, (DLGPROC) RandomPoolEnrichementDlgProc, (LPARAM) 0); + SetRandomPoolEnrichedByUserStatus (result == IDOK); + } +} + + +/* Except in response to the WM_INITDIALOG message, the dialog box procedure + should return nonzero if it processes the message, and zero if it does + not. - see DialogProc */ +BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + static unsigned char randPool [RNG_POOL_SIZE]; + static unsigned char lastRandPool [RNG_POOL_SIZE]; + static unsigned char maskRandPool [RNG_POOL_SIZE]; + static BOOL bUseMask = FALSE; + static DWORD mouseEntropyGathered = 0xFFFFFFFF; + static DWORD mouseEventsInitialCount = 0; + /* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */ + static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8; + static HWND hEntropyBar = NULL; + static wchar_t outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; + static BOOL bDisplayPoolContents = FALSE; + static BOOL bRandPoolDispAscii = FALSE; + int hash_algo = RandGetHashFunction(); + int hid; + + switch (msg) + { + case WM_INITDIALOG: + { + HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); + HCRYPTPROV hRngProv = NULL; + + VirtualLock (randPool, sizeof(randPool)); + VirtualLock (lastRandPool, sizeof(lastRandPool)); + VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); + VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); + VirtualLock (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); + VirtualLock (maskRandPool, sizeof(maskRandPool)); + + mouseEntropyGathered = 0xFFFFFFFF; + mouseEventsInitialCount = 0; + bUseMask = FALSE; + if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + { + if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool)) + bUseMask = TRUE; + CryptReleaseContext (hRngProv, 0); + } + + LocalizeDialog (hwndDlg, "IDD_KEYFILE_GENERATOR"); + + SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); + for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) + { + if (!HashIsDeprecated (hid)) + AddComboPair (hComboBox, HashGetName(hid), hid); + } + SelectAlgo (hComboBox, &hash_algo); + + 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); + 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 */ + tmpByte = (randPool[row * RANDPOOL_DISPLAY_COLUMNS + col] - + lastRandPool[row * RANDPOOL_DISPLAY_COLUMNS + col]) ^ maskRandPool [row * RANDPOOL_DISPLAY_COLUMNS + col]; + tmp[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*'); + tmp[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*'); + tmp[2] = L' '; + tmp[3] = 0; + } + else + { + StringCbCopyW (tmp, sizeof(tmp), L"** "); + } + + StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), tmp); + } + StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), L"\n"); + } + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); + + memcpy (lastRandPool, randPool, sizeof(lastRandPool)); + } + return 1; + } + + case WM_COMMAND: + + if (lw == IDCLOSE || lw == IDCANCEL) + { + 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)); + } + + 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, keyfilesSize = 0, i; + 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))) + szNumber[0] = 0; + + keyfilesSize = wcstoul(szNumber, NULL, 0); + if (keyfilesSize < 64 || keyfilesSize > 1024*1024) + { + 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)) + return 1; + + if (szDirName[wcslen(szDirName) - 1] != L'\\' && szDirName[wcslen(szDirName) - 1] != L'/') + StringCbCat(szDirName, sizeof(szDirName), L"\\"); + + WaitCursor(); + + keyfile = (unsigned char*) TCalloc( bRandomSize? KEYFILE_MAX_READ_LEN : keyfilesSize ); + + 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 + StringCbCat(szFileName, sizeof(szFileName), szFileBaseName); + + // check if the file exists + if ((fhKeyfile = _wopen(szFileName, _O_RDONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) != -1) + { + WCHAR s[4*TC_MAX_PATH] = {0}; + + _close (fhKeyfile); + + StringCbPrintfW (s, sizeof(s), GetString ("KEYFILE_ALREADY_EXISTS"), szFileName); + status = AskWarnNoYesString (s, hwndDlg); + if (status == IDNO) + { + TCfree(keyfile); + NormalCursor(); + return 1; + } + } + + /* Conceive the file */ + if ((fhKeyfile = _wopen(szFileName, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) == -1) + { + TCfree(keyfile); + NormalCursor(); + handleWin32Error (hwndDlg, SRC_POS); + return 1; + } + + if (bRandomSize) + { + /* Generate a random size */ + if (!RandgetBytes (hwndDlg, (unsigned char*) &keyfilesSize, sizeof(keyfilesSize), FALSE)) + { + _close (fhKeyfile); + DeleteFile (szFileName); + TCfree(keyfile); + NormalCursor(); + return 1; + } + + /* since keyfilesSize < 1024 * 1024, we mask with 0x000FFFFF */ + keyfilesSize = (long) (((unsigned long) keyfilesSize) & 0x000FFFFF); + + keyfilesSize %= ((KEYFILE_MAX_READ_LEN - 64) + 1); + keyfilesSize += 64; + } + + /* Generate the keyfile */ + if (!RandgetBytesFull (hwndDlg, keyfile, keyfilesSize, TRUE, TRUE)) + { + _close (fhKeyfile); + DeleteFile (szFileName); + TCfree(keyfile); + NormalCursor(); + return 1; + } + + /* Write the keyfile */ + status = _write (fhKeyfile, keyfile, keyfilesSize); + burn (keyfile, keyfilesSize); + _close (fhKeyfile); + + if (status == -1) + { + TCfree(keyfile); + NormalCursor(); + handleWin32Error (hwndDlg, SRC_POS); + return 1; + } + } + + TCfree(keyfile); + NormalCursor(); + + Info("KEYFILE_CREATED", hwndDlg); + + return 1; + } + return 0; + + case WM_CLOSE: + { + wchar_t tmp[RNG_POOL_SIZE+1]; +exit: + WaitCursor(); + KillTimer (hwndDlg, 0xfd); + +#ifndef VOLFORMAT + RandStop (FALSE); +#endif + /* Cleanup */ + + burn (randPool, sizeof(randPool)); + burn (lastRandPool, sizeof(lastRandPool)); + burn (outputDispBuffer, sizeof(outputDispBuffer)); + burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); + burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); + burn (maskRandPool, sizeof(maskRandPool)); + + // Attempt to wipe the pool contents in the GUI text area + wmemset (tmp, L' ', RNG_POOL_SIZE); + tmp [RNG_POOL_SIZE] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); + + EndDialog (hwndDlg, IDCLOSE); + NormalCursor (); + return 1; + } + } + return 0; +} + + + +/* Except in response to the WM_INITDIALOG message, the dialog box procedure +should return nonzero if it processes the message, and zero if it does +not. - see DialogProc */ +BOOL CALLBACK +CipherTestDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static int idTestCipher = -1; /* Currently selected cipher for the test vector facility (none = -1). */ + static BOOL bXTSTestEnabled = FALSE; + + PCRYPTO_INFO ci; + WORD lw = LOWORD (wParam); + WORD hw = HIWORD (wParam); + + switch (uMsg) + { + case WM_INITDIALOG: + { + int ea; + wchar_t buf[100]; + + LocalizeDialog (hwndDlg, "IDD_CIPHER_TEST_DLG"); + + SendMessage(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), WM_SETFONT, (WPARAM)hBoldFont, MAKELPARAM(TRUE,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY), EM_LIMITTEXT, 128,0); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT), EM_LIMITTEXT,64,0); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), EM_LIMITTEXT,64,0); + SendMessage(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), EM_LIMITTEXT, 128,0); + SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); + SendMessage(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), EM_LIMITTEXT,32,0); + SendMessage(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); + SetCheckBox (hwndDlg, IDC_XTS_MODE_ENABLED, bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_SECONDARY_KEY), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_SECONDARY_KEY), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_BLOCK_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); + + if (idTestCipher == -1) + idTestCipher = (int) lParam; + + SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_RESETCONTENT, 0, 0); + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) + { + if (EAGetCipherCount (ea) == 1 && EAIsFormatEnabled (ea)) + AddComboPair (GetDlgItem (hwndDlg, IDC_CIPHER), EAGetName (buf, ea, 1), EAGetFirstCipher (ea)); + } + + ResetCipherTest(hwndDlg, idTestCipher); + + SelectAlgo (GetDlgItem (hwndDlg, IDC_CIPHER), &idTestCipher); + + return 1; + } + + case WM_COMMAND: + + if (hw == CBN_SELCHANGE && lw == IDC_CIPHER) + { + idTestCipher = (int) SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_GETCURSEL, 0, 0), 0); + ResetCipherTest(hwndDlg, idTestCipher); + SendMessage (hwndDlg, WM_INITDIALOG, 0, 0); + return 1; + } + + if (hw == CBN_SELCHANGE && lw == IDC_KEY_SIZE) + { + // NOP + return 1; + } + + if (lw == IDC_RESET) + { + ResetCipherTest(hwndDlg, idTestCipher); + + return 1; + } + + if (lw == IDC_AUTO) + { + WaitCursor (); + if (!AutoTestAlgorithms()) + { + ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL); + SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_FAILED")); + } + else + { + ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL); + SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_PASSED")); + ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_SHOWNORMAL); + } + NormalCursor (); + + return 1; + + } + + if (lw == IDC_XTS_MODE_ENABLED) + { + bXTSTestEnabled = GetCheckBox (hwndDlg, IDC_XTS_MODE_ENABLED); + EnableWindow (GetDlgItem (hwndDlg, IDC_SECONDARY_KEY), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_SECONDARY_KEY), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_BLOCK_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); + EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); + if (bXTSTestEnabled) + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, 0,0); + } + + if (lw == IDOK || lw == IDC_ENCRYPT || lw == IDC_DECRYPT) + { + char key[128+1], inputtext[128+1], secondaryKey[64+1], dataUnitNo[16+1]; + wchar_t szTmp[128+1]; + int ks, pt, n, tlen, blockNo = 0; + BOOL bEncrypt; + + ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_HIDE); + + ks = (int) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_GETCURSEL, 0,0); + ks = (int) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_GETITEMDATA, ks,0); + pt = (int) SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_GETITEMDATA, 0,0); + + bEncrypt = lw == IDC_ENCRYPT; + + memset(key,0,sizeof(key)); + memset(szTmp,0,sizeof(szTmp)); + n = GetWindowText(GetDlgItem(hwndDlg, IDC_KEY), szTmp, ARRAYSIZE(szTmp)); + if (n != ks * 2) + { + Warning ("TEST_KEY_SIZE", hwndDlg); + return 1; + } + + for (n = 0; n < ks; n ++) + { + wchar_t szTmp2[3], *ptr; + long x; + + szTmp2[2] = 0; + szTmp2[0] = szTmp[n * 2]; + szTmp2[1] = szTmp[n * 2 + 1]; + + x = wcstol(szTmp2, &ptr, 16); + + key[n] = (char) x; + } + + memset(inputtext, 0, sizeof(inputtext)); + memset(secondaryKey, 0, sizeof(secondaryKey)); + memset(dataUnitNo, 0, sizeof(dataUnitNo)); + memset(szTmp, 0, sizeof(szTmp)); + + if (bEncrypt) + { + n = GetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), szTmp, ARRAYSIZE(szTmp)); + } + else + { + n = GetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), szTmp, ARRAYSIZE(szTmp)); + } + + if (n != pt * 2) + { + if (bEncrypt) + { + Warning ("TEST_PLAINTEXT_SIZE", hwndDlg); + return 1; + } + else + { + Warning ("TEST_CIPHERTEXT_SIZE", hwndDlg); + return 1; + } + } + + for (n = 0; n < pt; n ++) + { + wchar_t szTmp2[3], *ptr; + long x; + + szTmp2[2] = 0; + szTmp2[0] = szTmp[n * 2]; + szTmp2[1] = szTmp[n * 2 + 1]; + + x = wcstol(szTmp2, &ptr, 16); + + inputtext[n] = (char) x; + } + + // XTS + if (bXTSTestEnabled) + { + // Secondary key + + if (GetWindowText(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), szTmp, ARRAYSIZE(szTmp)) != 64) + { + Warning ("TEST_INCORRECT_SECONDARY_KEY_SIZE", hwndDlg); + return 1; + } + + for (n = 0; n < 64; n ++) + { + wchar_t szTmp2[3], *ptr; + long x; + + szTmp2[2] = 0; + szTmp2[0] = szTmp[n * 2]; + szTmp2[1] = szTmp[n * 2 + 1]; + + x = wcstol(szTmp2, &ptr, 16); + + secondaryKey[n] = (char) x; + } + + // Data unit number + + tlen = GetWindowText(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), szTmp, ARRAYSIZE(szTmp)); + + if (tlen > 16 || tlen < 1) + { + Warning ("TEST_INCORRECT_TEST_DATA_UNIT_SIZE", hwndDlg); + return 1; + } + + LeftPadString (szTmp, tlen, 16, L'0'); + + for (n = 0; n < 16; n ++) + { + wchar_t szTmp2[3], *ptr; + long x; + + szTmp2[2] = 0; + szTmp2[0] = szTmp[n * 2]; + szTmp2[1] = szTmp[n * 2 + 1]; + + x = wcstol(szTmp2, &ptr, 16); + + dataUnitNo[n] = (char) x; + } + + // Block number + + blockNo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_GETCURSEL, 0, 0), 0); + } // if (bXTSTestEnabled) + + + /* Perform the actual tests */ + + if (ks != CB_ERR && pt != CB_ERR) + { + char tmp[128]; + int tmpRetVal; + + /* Copy the plain/ciphertext */ + memcpy(tmp,inputtext, pt); + + if (bXTSTestEnabled) + { + UINT64_STRUCT structDataUnitNo; + + /* XTS mode */ + + ci = crypto_open (); + if (!ci) + return 1; + + ci->mode = XTS; + + for (ci->ea = EAGetFirst (); ci->ea != 0 ; ci->ea = EAGetNext (ci->ea)) + if (EAGetCipherCount (ci->ea) == 1 && EAGetFirstCipher (ci->ea) == idTestCipher) + break; + + if ((tmpRetVal = EAInit (ci->ea, (unsigned char *) key, ci->ks)) != ERR_SUCCESS) + { + handleError (hwndDlg, tmpRetVal, SRC_POS); + crypto_close (ci); + return 1; + } + + memcpy (&ci->k2, secondaryKey, sizeof (secondaryKey)); + if (!EAInitMode (ci)) + { + crypto_close (ci); + return 1; + } + + structDataUnitNo.Value = BE64(((unsigned __int64 *)dataUnitNo)[0]); + + if (bEncrypt) + EncryptBufferXTS ((unsigned char *) tmp, pt, &structDataUnitNo, blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, idTestCipher); + else + DecryptBufferXTS ((unsigned char *) tmp, pt, &structDataUnitNo, blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, idTestCipher); + + crypto_close (ci); + } + else + { + + CipherInit2(idTestCipher, key, ks_tmp, ks); + + if (bEncrypt) + { + EncipherBlock(idTestCipher, tmp, ks_tmp); + } + else + { + DecipherBlock(idTestCipher, tmp, ks_tmp); + } + + } + *szTmp = 0; + + for (n = 0; n < pt; n ++) + { + wchar_t szTmp2[3]; + StringCbPrintfW(szTmp2, sizeof(szTmp2), L"%02x", (int)((unsigned char)tmp[n])); + StringCbCatW(szTmp, sizeof(szTmp), szTmp2); + } + + if (bEncrypt) + SetWindowText(GetDlgItem(hwndDlg,IDC_CIPHERTEXT), szTmp); + else + SetWindowText(GetDlgItem(hwndDlg,IDC_PLAINTEXT), szTmp); + } + + return 1; + } + + if (lw == IDCLOSE || lw == IDCANCEL) + { + idTestCipher = -1; + EndDialog (hwndDlg, 0); + return 1; + } + break; + + case WM_CLOSE: + idTestCipher = -1; + EndDialog (hwndDlg, 0); + return 1; + } + + return 0; +} + +void +ResetCipherTest(HWND hwndDlg, int idTestCipher) +{ + int ndx; + + ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_HIDE); + + EnableWindow(GetDlgItem(hwndDlg,IDC_KEY_SIZE), FALSE); + + /* Setup the keysize and plaintext sizes for the selected cipher */ + + SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_RESETCONTENT, 0,0); + SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_RESETCONTENT, 0,0); + SendMessage (GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_RESETCONTENT, 0,0); + + ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_ADDSTRING, 0,(LPARAM) L"64"); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 8); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETCURSEL, ndx,0); + + for (ndx = 0; ndx < BLOCKS_PER_XTS_DATA_UNIT; ndx++) + { + wchar_t tmpStr [16]; + + StringCbPrintfW (tmpStr, sizeof(tmpStr), L"%d", ndx); + + ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_ADDSTRING, 0,(LPARAM) tmpStr); + SendMessage(GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_SETITEMDATA, ndx,(LPARAM) ndx); + } + + SendMessage(GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_SETCURSEL, 0, 0); + + SetWindowText(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), L"0000000000000000000000000000000000000000000000000000000000000000"); + SetWindowText(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), L"0"); + + SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), L"0000000000000000"); + SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), L"0000000000000000"); + + if (idTestCipher == AES || idTestCipher == SERPENT || idTestCipher == TWOFISH) + { + ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) L"256"); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 32); + SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, ndx,0); + + SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_RESETCONTENT, 0,0); + ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_ADDSTRING, 0,(LPARAM) L"128"); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 16); + SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETCURSEL, ndx,0); + + SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), L"0000000000000000000000000000000000000000000000000000000000000000"); + SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), L"00000000000000000000000000000000"); + SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), L"00000000000000000000000000000000"); + } +} + +#endif // #ifndef SETUP + + +BOOL CALLBACK MultiChoiceDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + int nChoiceIDs [MAX_MULTI_CHOICES+1] = { IDC_MULTI_CHOICE_MSG, IDC_CHOICE1, IDC_CHOICE2, IDC_CHOICE3, + IDC_CHOICE4, IDC_CHOICE5, IDC_CHOICE6, IDC_CHOICE7, IDC_CHOICE8, IDC_CHOICE9, IDC_CHOICE10 }; + int nBaseButtonWidth = 0; + int nBaseButtonHeight = 0; + int nActiveChoices = -1; + int nStr = 0; + int vertSubOffset, horizSubOffset, vertMsgHeightOffset; + int vertOffset = 0; + int nLongestButtonCaptionWidth = 6; + int nLongestButtonCaptionCharLen = 1; + int nTextGfxLineHeight = 0; + int nMainTextLenInChars = 0; + int newLineSeqCount = 0; + RECT rec, wrec, wtrec, trec; + BOOL bResolve; + + WORD lw = LOWORD (wParam); + + switch (uMsg) + { + case WM_INITDIALOG: + { + char **pStr = (char **) ((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->strings; + char **pStrOrig = pStr; + wchar_t **pwStr = (wchar_t **) ((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->strings; + wchar_t **pwStrOrig = pwStr; + + LocalizeDialog (hwndDlg, NULL); + + SetWindowPos (hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + SetWindowPos (hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + + bResolve = (*pStr == NULL); + + // Style + if (((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->bold) + { + SendMessage (GetDlgItem (hwndDlg, IDC_MULTI_CHOICE_MSG), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); + } + + // Process the strings + pStr++; + pwStr++; + + do + { + if (*pStr != 0) + { + SetWindowTextW (GetDlgItem(hwndDlg, nChoiceIDs[nStr]), bResolve ? GetString(*pStr) : *pwStr); + + if (nStr > 0) + { + nLongestButtonCaptionWidth = max ( + GetTextGfxWidth (GetDlgItem(hwndDlg, IDC_CHOICE1), + bResolve ? GetString(*pStr) : *pwStr, + hUserFont), + nLongestButtonCaptionWidth); + + nLongestButtonCaptionCharLen = max (nLongestButtonCaptionCharLen, + (int) wcslen ((const wchar_t *) (bResolve ? GetString(*pStr) : *pwStr))); + } + + nActiveChoices++; + pStr++; + pwStr++; + } + else + { + ShowWindow(GetDlgItem(hwndDlg, nChoiceIDs[nStr]), SW_HIDE); + } + nStr++; + + } while (nStr < MAX_MULTI_CHOICES+1); + + // Length of main message in characters (not bytes) + nMainTextLenInChars = (int) wcslen ((const wchar_t *) (bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1))); + + if (nMainTextLenInChars > 200 + && nMainTextLenInChars / nLongestButtonCaptionCharLen >= 10) + { + // As the main text is longer than 200 characters, we will "pad" the widest button caption with + // spaces (if it is not wide enough) so as to increase the width of the whole dialog window. + // Otherwise, it would look too tall (dialog boxes look better when they are more wide than tall). + nLongestButtonCaptionWidth = CompensateXDPI (max ( + nLongestButtonCaptionWidth, + min (350, nMainTextLenInChars))); + } + + // Get the window coords + GetWindowRect(hwndDlg, &wrec); + + // Get the base button size + GetClientRect(GetDlgItem(hwndDlg, IDC_CHOICE1), &rec); + nBaseButtonWidth = rec.right + 2; + nBaseButtonHeight = rec.bottom + 2; + + // Increase in width based on the gfx length of the widest button caption + horizSubOffset = min (CompensateXDPI (500), max (0, nLongestButtonCaptionWidth + CompensateXDPI (50) - nBaseButtonWidth)); + + // Vertical "title bar" offset + GetClientRect(hwndDlg, &wtrec); + vertOffset = wrec.bottom - wrec.top - wtrec.bottom - GetSystemMetrics(SM_CYFIXEDFRAME); + + // Height/width of the message text + GetClientRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &trec); + + // Determine the number of newlines contained in the message text + { + int64 offset = -1; + + do + { + offset = FindString ((char *) (bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1)), + (char *) L"\n", + nMainTextLenInChars * 2, + (int) wcslen (L"\n") * 2, + offset + 1); + + newLineSeqCount++; + + } while (offset != -1); + } + + nTextGfxLineHeight = GetTextGfxHeight (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), + bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1), + hUserFont); + + vertMsgHeightOffset = ((GetTextGfxWidth (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), + bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1), + hUserFont) / (trec.right + horizSubOffset) + 1) * nTextGfxLineHeight) - trec.bottom; + + vertMsgHeightOffset = min (CompensateYDPI (350), vertMsgHeightOffset + newLineSeqCount * nTextGfxLineHeight + (trec.bottom + vertMsgHeightOffset) / 10); // As reserve, we are adding 10% and the number of lines equal to the number of newlines in the message + + // Reduction in height according to the number of shown buttons + vertSubOffset = ((MAX_MULTI_CHOICES - nActiveChoices) * nBaseButtonHeight); + + if (horizSubOffset > 0 + || vertMsgHeightOffset > 0 + || vertOffset > 0) + { + // Resize/move each button if necessary + for (nStr = 1; nStr < MAX_MULTI_CHOICES+1; nStr++) + { + GetWindowRect(GetDlgItem(hwndDlg, nChoiceIDs[nStr]), &rec); + + MoveWindow (GetDlgItem(hwndDlg, nChoiceIDs[nStr]), + rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), + rec.top - wrec.top - vertOffset + vertMsgHeightOffset, + nBaseButtonWidth + horizSubOffset, + nBaseButtonHeight, + TRUE); + } + + // Resize/move the remaining GUI elements + GetWindowRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &rec); + GetClientRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &trec); + MoveWindow (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), + rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), + rec.top - wrec.top - vertOffset, + trec.right + 2 + horizSubOffset, + trec.bottom + 2 + vertMsgHeightOffset, + TRUE); + + GetWindowRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), &rec); + GetClientRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), &trec); + MoveWindow (GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), + rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), + rec.top - wrec.top - vertOffset, + trec.right + 2 + horizSubOffset, + trec.bottom + 2, + TRUE); + + GetWindowRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), &rec); + GetClientRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), &trec); + MoveWindow (GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), + rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), + rec.top - wrec.top - vertOffset + vertMsgHeightOffset, + trec.right + 2 + horizSubOffset, + trec.bottom + 2, + TRUE); + } + + // Resize the window according to number of shown buttons and the longest button caption + MoveWindow (hwndDlg, + wrec.left - horizSubOffset / 2, + wrec.top + vertSubOffset / 2 - vertMsgHeightOffset / 2, + wrec.right - wrec.left + horizSubOffset, + wrec.bottom - wrec.top - vertSubOffset + 1 + vertMsgHeightOffset, + TRUE); + + DisableCloseButton (hwndDlg); + + return 1; + } + + case WM_COMMAND: + + if (lw == IDCLOSE || lw == IDCANCEL) + { + EndDialog (hwndDlg, 0); + return 1; + } + + for (nStr = 1; nStr < MAX_MULTI_CHOICES+1; nStr++) + { + if (lw == nChoiceIDs[nStr]) + { + EndDialog (hwndDlg, nStr); + return 1; + } + } + break; + + case WM_CLOSE: + // This prevents the window from being closed by pressing Alt-F4 (the Close button is hidden). + // Note that the OS handles modal MessageBox() dialog windows the same way. + return 1; + } + + return 0; +} + + +BOOL CheckCapsLock (HWND hwnd, BOOL quiet) +{ + if ((GetKeyState(VK_CAPITAL) & 1) != 0) + { + if (!quiet) + { + MessageBoxW (hwnd, GetString ("CAPSLOCK_ON"), lpszTitle, MB_ICONEXCLAMATION); + } + return TRUE; + } + return FALSE; +} + + +// Checks whether the file extension is not used for executable files or similarly problematic, which often +// causes Windows and antivirus software to interfere with the container. +BOOL CheckFileExtension (wchar_t *fileName) +{ + int i = 0; + wchar_t *ext = wcsrchr (fileName, L'.'); + static wchar_t *problemFileExt[] = { + // These are protected by the Windows Resource Protection + L".asa", L".asp", L".aspx", L".ax", L".bas", L".bat", L".bin", L".cer", L".chm", L".clb", L".cmd", L".cnt", L".cnv", + L".com", L".cpl", L".cpx", L".crt", L".csh", L".dll", L".drv", L".dtd", L".exe", L".fxp", L".grp", L".h1s", L".hlp", + L".hta", L".ime", L".inf", L".ins", L".isp", L".its", L".js", L".jse", L".ksh", L".lnk", L".mad", L".maf", L".mag", + L".mam", L".man", L".maq", L".mar", L".mas", L".mat", L".mau", L".mav", L".maw", L".mda", L".mdb", L".mde", L".mdt", + L".mdw", L".mdz", L".msc", L".msi", L".msp", L".mst", L".mui", L".nls", L".ocx", L".ops", L".pal", L".pcd", L".pif", + L".prf", L".prg", L".pst", L".reg", L".scf", L".scr", L".sct", L".shb", L".shs", L".sys", L".tlb", L".tsp", L".url", + L".vb", L".vbe", L".vbs", L".vsmacros", L".vss", L".vst", L".vsw", L".ws", L".wsc", L".wsf", L".wsh", L".xsd", L".xsl", + // These additional file extensions are usually watched by antivirus programs + L".386", L".acm", L".ade", L".adp", L".ani", L".app", L".asd", L".asf", L".asx", L".awx", L".ax", L".boo", L".bz2", L".cdf", + L".class", L".dhtm", L".dhtml",L".dlo", L".emf", L".eml", L".flt", L".fot", L".gz", L".hlp", L".htm", L".html", L".ini", + L".j2k", L".jar", L".jff", L".jif", L".jmh", L".jng", L".jp2", L".jpe", L".jpeg", L".jpg", L".lsp", L".mod", L".nws", + L".obj", L".olb", L".osd", L".ov1", L".ov2", L".ov3", L".ovl", L".ovl", L".ovr", L".pdr", L".pgm", L".php", L".pkg", + L".pl", L".png", L".pot", L".pps", L".ppt", L".ps1", L".ps1xml", L".psc1", L".rar", L".rpl", L".rtf", L".sbf", L".script", L".sh", L".sha", L".shtm", + L".shtml", L".spl", L".swf", L".tar", L".tgz", L".tmp", L".ttf", L".vcs", L".vlm", L".vxd", L".vxo", L".wiz", L".wll", L".wmd", + L".wmf", L".wms", L".wmz", L".wpc", L".wsc", L".wsh", L".wwk", L".xhtm", L".xhtml", L".xl", L".xml", L".zip", L".7z", 0}; + + if (!ext) + return FALSE; + + while (problemFileExt[i]) + { + if (!_wcsicmp (ext, problemFileExt[i++])) + return TRUE; + } + + return FALSE; +} + +void CorrectFileName (wchar_t* fileName) +{ + /* replace '/' by '\' */ + size_t i, len = wcslen (fileName); + for (i = 0; i < len; i++) + { + if (fileName [i] == L'/') + fileName [i] = L'\\'; + } +} + +void IncreaseWrongPwdRetryCount (int count) +{ + WrongPwdRetryCounter += count; +} + + +void ResetWrongPwdRetryCount (void) +{ + WrongPwdRetryCounter = 0; +} + + +BOOL WrongPwdRetryCountOverLimit (void) +{ + return (WrongPwdRetryCounter > TC_TRY_HEADER_BAK_AFTER_NBR_WRONG_PWD_TRIES); +} + +DWORD GetUsedLogicalDrives (void) +{ + DWORD dwUsedDrives = GetLogicalDrives(); + if (!bShowDisconnectedNetworkDrives) + { + static DWORD g_dwLastMappedDrives = 0; + static time_t g_lastCallTime = 0; + + EnterCriticalSection (&csWNetCalls); + + finally_do ({ LeaveCriticalSection (&csWNetCalls); }); + + /* update values every 2 seconds to reduce CPU consumption */ + if ((time (NULL) - g_lastCallTime) > 2) + { + /* detect disconnected mapped network shares and removed + * their associated drives from the list + */ + WCHAR remotePath[512]; + WCHAR drive[3] = {L'A', L':', 0}; + DWORD dwLen, status; + g_dwLastMappedDrives = 0; + for (WCHAR i = 0; i <= MAX_MOUNTED_VOLUME_DRIVE_NUMBER; i++) + { + if ((dwUsedDrives & (1 << i)) == 0) + { + drive[0] = L'A' + i; + dwLen = ARRAYSIZE (remotePath); + status = WNetGetConnection (drive, remotePath, &dwLen); + if ((NO_ERROR == status) || (status == ERROR_CONNECTION_UNAVAIL)) + { + /* this is a mapped network share, mark it as used */ + g_dwLastMappedDrives |= (1 << i); + } + } + } + + g_lastCallTime = time (NULL); + } + + dwUsedDrives |= g_dwLastMappedDrives; + } + + return dwUsedDrives; +} + + +int GetFirstAvailableDrive () +{ + DWORD dwUsedDrives = GetUsedLogicalDrives(); + int i, drive; + + /* let A: and B: be used as last resort since they can introduce side effects */ + for (i = 2; i < 28; i++) + { + drive = (i < 26) ? i : (i - 26); + if (!(dwUsedDrives & 1 << drive)) + return i; + } + + return -1; +} + + +int GetLastAvailableDrive () +{ + DWORD dwUsedDrives = GetUsedLogicalDrives(); + int i; + + for (i = 25; i >= 0; i--) + { + if (!(dwUsedDrives & 1 << i)) + return i; + } + + return -1; +} + + +BOOL IsDriveAvailable (int driveNo) +{ + return (GetUsedLogicalDrives() & (1 << driveNo)) == 0; +} + + +BOOL IsDeviceMounted (wchar_t *deviceName) +{ + BOOL bResult = FALSE; + DWORD dwResult; + HANDLE dev = INVALID_HANDLE_VALUE; + + if ((dev = CreateFile (deviceName, + GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL)) != INVALID_HANDLE_VALUE) + { + bResult = DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL); + CloseHandle (dev); + } + + return bResult; +} + + +int DriverUnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forced) +{ + UNMOUNT_STRUCT unmount; + DWORD dwResult; + VOLUME_PROPERTIES_STRUCT prop; + BOOL bResult; + WCHAR wszLabel[33] = {0}; + BOOL bDriverSetLabel = FALSE; + + memset (&prop, 0, sizeof(prop)); + prop.driveNo = nDosDriveNo; + + if ( DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &dwResult, NULL) + && prop.driveNo == nDosDriveNo + ) + { + memcpy (wszLabel, prop.wszLabel, sizeof (wszLabel)); + bDriverSetLabel = prop.bDriverSetLabel; + } + + unmount.nDosDriveNo = nDosDriveNo; + unmount.ignoreOpenFiles = forced; + + bResult = DeviceIoControl (hDriver, TC_IOCTL_DISMOUNT_VOLUME, &unmount, + sizeof (unmount), &unmount, sizeof (unmount), &dwResult, NULL); + + if (bResult == FALSE) + { + handleWin32Error (hwndDlg, SRC_POS); + return 1; + } + else if ((unmount.nReturnCode == ERR_SUCCESS) && bDriverSetLabel && wszLabel[0]) + UpdateDriveCustomLabel (nDosDriveNo, wszLabel, FALSE); + +#ifdef TCMOUNT + + if (unmount.nReturnCode == ERR_SUCCESS + && unmount.HiddenVolumeProtectionTriggered + && !VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo] + && !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. + 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; + + IgnoreWmDeviceChange = TRUE; + SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), SMTO_ABORTIFHUNG, timeOut, &dwResult); + + // Explorer prior Vista sometimes fails to register a new drive + if (CurrentOSMajor < 6 && message == DBT_DEVICEARRIVAL) + SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), SMTO_ABORTIFHUNG, 200, &dwResult); + + IgnoreWmDeviceChange = FALSE; +} + +BOOL GetPhysicalDriveAlignment(UINT nDriveNumber, STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR* pDesc) +{ + DWORD dwRet = NO_ERROR; + + if (!pDesc) + return FALSE; + + // Format physical drive path (may be '\\.\PhysicalDrive0', '\\.\PhysicalDrive1' and so on). + TCHAR strDrivePath[512]; + StringCbPrintf(strDrivePath, sizeof(strDrivePath), _T("\\\\.\\PhysicalDrive%u"), nDriveNumber); + + // Get a handle to physical drive + HANDLE hDevice = ::CreateFile(strDrivePath, 0, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, NULL); + + if(INVALID_HANDLE_VALUE == hDevice) + return FALSE; + + // Set the input data structure + STORAGE_PROPERTY_QUERY storagePropertyQuery; + ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY)); + storagePropertyQuery.PropertyId = StorageAccessAlignmentProperty; + storagePropertyQuery.QueryType = PropertyStandardQuery; + + // Get the necessary output buffer size + DWORD dwBytesReturned = 0; + BOOL bRet = ::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, + &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), + pDesc, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), + &dwBytesReturned, NULL); + dwRet = ::GetLastError(); + ::CloseHandle(hDevice); + + if (!bRet) + { + SetLastError (dwRet); + return FALSE; + } + else + return TRUE; +} + +/************************************************************/ + +// implementation of the generic wait dialog mechanism + +static UINT g_wmWaitDlg = ::RegisterWindowMessage(L"VeraCryptWaitDlgMessage"); + +typedef struct +{ + HWND hwnd; + void* pArg; + WaitThreadProc callback; +} WaitThreadParam; + +static void _cdecl WaitThread (void* pParam) +{ + WaitThreadParam* pThreadParam = (WaitThreadParam*) pParam; + + pThreadParam->callback(pThreadParam->pArg, pThreadParam->hwnd); + + /* close the wait dialog */ + PostMessage (pThreadParam->hwnd, g_wmWaitDlg, 0, 0); +} + +BOOL CALLBACK WaitDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + WaitThreadParam* thParam = (WaitThreadParam*) lParam; + + // set the progress bar type to MARQUEE (indefinite progress) + HWND hProgress = GetDlgItem (hwndDlg, IDC_WAIT_PROGRESS_BAR); + if (hProgress) + { + SetWindowLongPtrW (hProgress, GWL_STYLE, PBS_MARQUEE | GetWindowLongPtrW (hProgress, GWL_STYLE)); + ::SendMessageW(hProgress, PBM_SETMARQUEE, (WPARAM) TRUE, (LPARAM) 0); + } + + thParam->hwnd = hwndDlg; + + // For now, we don't have system menu is the resources but we leave this code + // if it is enabled in the future + HMENU hSysMenu = GetSystemMenu(hwndDlg, FALSE); + if (hSysMenu) + { + //disable the X + EnableMenuItem(hSysMenu,SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); + + // set icons + HICON hIcon = (HICON)::LoadImage(hInst, MAKEINTRESOURCE(IDI_TRUECRYPT_ICON), IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR); + ::SendMessage(hwndDlg, WM_SETICON, TRUE, (LPARAM)hIcon); + HICON hIconSmall = (HICON)::LoadImage(hInst, MAKEINTRESOURCE(IDI_TRUECRYPT_ICON), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); + ::SendMessage(hwndDlg, WM_SETICON, FALSE, (LPARAM)hIconSmall); + } + + LocalizeDialog (hwndDlg, NULL); + _beginthread(WaitThread, 0, thParam); + return 0; + } + + case WM_COMMAND: + + if (lw == IDOK || lw == IDCANCEL) + return 1; + else + return 0; + + default: + if (msg == g_wmWaitDlg) + { + EndDialog (hwndDlg, IDOK); + return 1; + } + return 0; + } +} + + +void BringToForeground(HWND hWnd) +{ + if(!::IsWindow(hWnd)) return; + + DWORD lockTimeOut = 0; + HWND hCurrWnd = ::GetForegroundWindow(); + DWORD dwThisTID = ::GetCurrentThreadId(), + dwCurrTID = ::GetWindowThreadProcessId(hCurrWnd,0); + + if (hCurrWnd != hWnd) + { + if(dwThisTID != dwCurrTID) + { + ::AttachThreadInput(dwThisTID, dwCurrTID, TRUE); + + ::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT,0,&lockTimeOut,0); + ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,0,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); + + ::AllowSetForegroundWindow(ASFW_ANY); + } + + ::SetForegroundWindow(hWnd); + + if(dwThisTID != dwCurrTID) + { + ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,(PVOID)lockTimeOut,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); + ::AttachThreadInput(dwThisTID, dwCurrTID, FALSE); + } + } + +#ifdef TCMOUNT + if (hWnd == MainDlg) + { + SetFocus (hWnd); + ::SendMessage(hWnd, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hWnd, IDC_DRIVELIST), 1L); + } +#endif +} + +void ShowWaitDialog(HWND hwnd, BOOL bUseHwndAsParent, WaitThreadProc callback, void* pArg) +{ + HWND hParent = (hwnd && bUseHwndAsParent)? hwnd : GetDesktopWindow(); + BOOL bEffectiveHideWaitingDialog = bCmdHideWaitingDialogValid? bCmdHideWaitingDialog : bHideWaitingDialog; + WaitThreadParam threadParam; + threadParam.callback = callback; + threadParam.pArg = pArg; + + if (WaitDialogDisplaying || bEffectiveHideWaitingDialog) + { + if (!WaitDialogDisplaying) WaitCursor (); + callback (pArg, hwnd); + if (!WaitDialogDisplaying) NormalCursor (); + } + else + { + BOOL bIsForeground = FALSE; + WaitDialogDisplaying = TRUE; + if (hwnd) + { + if (GetForegroundWindow () == hwnd) + bIsForeground = TRUE; + EnableWindow (hwnd, FALSE); + } + else + EnableWindow (MainDlg, FALSE); + finally_do_arg2 (HWND, hwnd, BOOL, bIsForeground, { if (finally_arg) {EnableWindow(finally_arg, TRUE); if (finally_arg2) BringToForeground (finally_arg);} else EnableWindow (MainDlg, TRUE);}); + + DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_STATIC_MODAL_WAIT_DLG), hParent, + (DLGPROC) WaitDlgProc, (LPARAM) &threadParam); + + WaitDialogDisplaying = FALSE; + } +} + +/************************************************************************/ + +static BOOL PerformMountIoctl (MOUNT_STRUCT* pmount, LPDWORD pdwResult, BOOL useVolumeID, BYTE volumeID[VOLUME_ID_SIZE]) +{ + if (useVolumeID) + { + wstring devicePath = FindDeviceByVolumeID (volumeID); + if (devicePath == L"") + { + if (pdwResult) + *pdwResult = 0; + SetLastError (ERROR_PATH_NOT_FOUND); + return FALSE; + } + else + { + BOOL bDevice = FALSE; + CreateFullVolumePath (pmount->wszVolume, sizeof(pmount->wszVolume), devicePath.c_str(), &bDevice); + } + } + + return DeviceIoControl (hDriver, TC_IOCTL_MOUNT_VOLUME, pmount, + sizeof (MOUNT_STRUCT), pmount, sizeof (MOUNT_STRUCT), pdwResult, NULL); +} + +// specific definitions and implementation for support of mount operation +// in wait dialog mechanism + +typedef struct +{ + MOUNT_STRUCT* pmount; + BOOL useVolumeID; + BYTE volumeID[VOLUME_ID_SIZE]; + BOOL* pbResult; + DWORD* pdwResult; + DWORD dwLastError; +} MountThreadParam; + +void CALLBACK MountWaitThreadProc(void* pArg, HWND ) +{ + MountThreadParam* pThreadParam = (MountThreadParam*) pArg; + + *(pThreadParam->pbResult) = PerformMountIoctl (pThreadParam->pmount, pThreadParam->pdwResult, pThreadParam->useVolumeID, pThreadParam->volumeID); + + pThreadParam->dwLastError = GetLastError (); +} + +/************************************************************************/ + +// Use only cached passwords if password = NULL +// +// Returns: +// -1 = user aborted mount / error +// 0 = mount failed +// 1 = mount OK +// 2 = mount OK in shared mode +// +// Note that some code calling this relies on the content of the mountOptions struct +// to remain unmodified (don't remove the 'const' without proper revision). + +int MountVolume (HWND hwndDlg, + int driveNo, + wchar_t *volumePath, + Password *password, + int pkcs5, + int pim, + BOOL truecryptMode, + BOOL cachePassword, + BOOL cachePim, + BOOL sharedAccess, + const MountOptions* const mountOptions, + BOOL quiet, + BOOL bReportWrongPassword) +{ + MOUNT_STRUCT mount; + DWORD dwResult, dwLastError = ERROR_SUCCESS; + BOOL bResult, bDevice; + wchar_t root[MAX_PATH]; + int favoriteMountOnArrivalRetryCount = 0; + BOOL useVolumeID = FALSE; + BYTE volumeID[VOLUME_ID_SIZE] = {0}; + +#ifdef TCMOUNT + if (mountOptions->PartitionInInactiveSysEncScope) + { + if (!CheckSysEncMountWithoutPBA (hwndDlg, volumePath, quiet)) + return -1; + } +#endif + + if (IsMountedVolume (volumePath)) + { + if (!quiet) + Error ("VOL_ALREADY_MOUNTED", hwndDlg); + return -1; + } + + if (!IsDriveAvailable (driveNo)) + { + if (!quiet) + Error ("DRIVE_LETTER_UNAVAILABLE", hwndDlg); + + return -1; + } + + // If using cached passwords, check cache status first + if (password == NULL && IsPasswordCacheEmpty ()) + return 0; + + ZeroMemory (&mount, sizeof (mount)); + mount.bExclusiveAccess = sharedAccess ? FALSE : TRUE; + mount.SystemFavorite = MountVolumesAsSystemFavorite; + mount.UseBackupHeader = mountOptions->UseBackupHeader; + mount.RecoveryMode = mountOptions->RecoveryMode; + StringCbCopyW (mount.wszLabel, sizeof (mount.wszLabel), mountOptions->Label); + +retry: + mount.nDosDriveNo = driveNo; + mount.bCache = cachePassword; + mount.bCachePim = cachePim; + + mount.bPartitionInInactiveSysEncScope = FALSE; + + if (password != NULL) + mount.VolumePassword = *password; + else + mount.VolumePassword.Length = 0; + + if (!mountOptions->ReadOnly && mountOptions->ProtectHiddenVolume) + { + mount.ProtectedHidVolPassword = mountOptions->ProtectedHidVolPassword; + mount.bProtectHiddenVolume = TRUE; + mount.ProtectedHidVolPkcs5Prf = mountOptions->ProtectedHidVolPkcs5Prf; + mount.ProtectedHidVolPim = mountOptions->ProtectedHidVolPim; + } + else + mount.bProtectHiddenVolume = FALSE; + + mount.bMountReadOnly = mountOptions->ReadOnly; + mount.bMountRemovable = mountOptions->Removable; + mount.bPreserveTimestamp = mountOptions->PreserveTimestamp; + + mount.bMountManager = TRUE; + mount.pkcs5_prf = pkcs5; + mount.bTrueCryptMode = truecryptMode; + mount.VolumePim = pim; + + // Windows 2000 mount manager causes problems with remounted volumes + if (CurrentOSMajor == 5 && CurrentOSMinor == 0) + mount.bMountManager = FALSE; + + 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 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) + { + // 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') + ) + { + 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 (DeviceIoControl (dev, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extents, sizeof(extents), &dwResult, NULL)) + { + if (extents.NumberOfDiskExtents > 0) + { + STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR desc; + if (GetPhysicalDriveAlignment (extents.Extents[0].DiskNumber, &desc)) + { + mount.BytesPerSector = desc.BytesPerLogicalSector; + mount.BytesPerPhysicalSector = desc.BytesPerPhysicalSector; + } + } + } + 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, + sizeof(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; + mountThreadParam.pdwResult = &dwResult; + mountThreadParam.dwLastError = ERROR_SUCCESS; + + ShowWaitDialog (hwndDlg, FALSE, MountWaitThreadProc, &mountThreadParam); + + dwLastError = mountThreadParam.dwLastError; + } + else + { + bResult = PerformMountIoctl (&mount, &dwResult, useVolumeID, volumeID); + + dwLastError = GetLastError (); + } + + burn (&mount.VolumePassword, sizeof (mount.VolumePassword)); + burn (&mount.ProtectedHidVolPassword, sizeof (mount.ProtectedHidVolPassword)); + burn (&mount.pkcs5_prf, sizeof (mount.pkcs5_prf)); + burn (&mount.bTrueCryptMode, sizeof (mount.bTrueCryptMode)); + burn (&mount.ProtectedHidVolPkcs5Prf, sizeof (mount.ProtectedHidVolPkcs5Prf)); + + SetLastError (dwLastError); + if (bResult == FALSE) + { + // Volume already open by another process + if (GetLastError () == ERROR_SHARING_VIOLATION) + { + if (FavoriteMountOnArrivalInProgress && ++favoriteMountOnArrivalRetryCount < 10) + { + Sleep (500); + goto retry; + } + + if (mount.bExclusiveAccess == FALSE) + { + if (!quiet) + Error ("FILE_IN_USE_FAILED", hwndDlg); + + return -1; + } + else + { + if (quiet) + { + mount.bExclusiveAccess = FALSE; + goto retry; + } + + // Ask user + if (IDYES == AskWarnNoYes ("FILE_IN_USE", hwndDlg)) + { + mount.bExclusiveAccess = FALSE; + goto retry; + } + } + + return -1; + } + + if (!quiet && (!MultipleMountOperationInProgress || GetLastError() != ERROR_NOT_READY)) + handleWin32Error (hwndDlg, SRC_POS); + + return -1; + } + + if (mount.nReturnCode != 0) + { + if (mount.nReturnCode == ERR_PASSWORD_WRONG) + { + // Do not report wrong password, if not instructed to + if (bReportWrongPassword) + { + IncreaseWrongPwdRetryCount (1); // We increase the count here only if bReportWrongPassword is TRUE, because "Auto-Mount All Devices" and other callers do it separately + + if (WrongPwdRetryCountOverLimit () + && !mount.UseBackupHeader) + { + // Retry using embedded header backup (if any) + mount.UseBackupHeader = TRUE; + goto retry; + } + + if (bDevice && mount.bProtectHiddenVolume) + { + int driveNo; + + if (swscanf (volumePath, L"\\Device\\Harddisk%d\\Partition", &driveNo) == 1) + { + OPEN_TEST_STRUCT openTestStruct; + memset (&openTestStruct, 0, sizeof (openTestStruct)); + + openTestStruct.bDetectTCBootLoader = TRUE; + StringCchPrintfW ((wchar_t *) openTestStruct.wszFileName, array_capacity (openTestStruct.wszFileName), L"\\Device\\Harddisk%d\\Partition0", driveNo); + + DWORD dwResult; + 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.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.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; +} + +typedef struct +{ + int nDosDriveNo; + BOOL forced; + int dismountMaxRetries; + DWORD retryDelay; + int* presult; + DWORD dwLastError; +} UnmountThreadParam; + +void CALLBACK UnmountWaitThreadProc(void* pArg, HWND hwnd) +{ + UnmountThreadParam* pThreadParam = (UnmountThreadParam*) pArg; + int dismountMaxRetries = pThreadParam->dismountMaxRetries; + DWORD retryDelay = pThreadParam->retryDelay; + + do + { + *pThreadParam->presult = DriverUnmountVolume (hwnd, pThreadParam->nDosDriveNo, pThreadParam->forced); + + if (*pThreadParam->presult == ERR_FILES_OPEN) + Sleep (retryDelay); + else + break; + + } while (--dismountMaxRetries > 0); + + pThreadParam->dwLastError = GetLastError (); +} + +static BOOL UnmountVolumeBase (HWND hwndDlg, int nDosDriveNo, BOOL forceUnmount, BOOL ntfsFormatCase) +{ + int result; + BOOL forced = forceUnmount; + int dismountMaxRetries = ntfsFormatCase? 5 : UNMOUNT_MAX_AUTO_RETRIES; + DWORD retryDelay = ntfsFormatCase? 2000: UNMOUNT_AUTO_RETRY_DELAY; + UnmountThreadParam param; + +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); + } + + 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); +} + +BOOL IsMountedVolumeID (BYTE volumeID[VOLUME_ID_SIZE]) +{ + MOUNT_LIST_STRUCT mlist; + DWORD dwResult; + int i; + + memset (&mlist, 0, sizeof (mlist)); + DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, + sizeof (mlist), &mlist, sizeof (mlist), &dwResult, + NULL); + + for (i=0 ; i<26; i++) + if (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 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)); + DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, + sizeof (mlist), &mlist, sizeof (mlist), &dwResult, + NULL); + + for (i=0 ; i<26; i++) + if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], volume)) + return TRUE; + } + + return FALSE; +} + + +int GetMountedVolumeDriveNo (wchar_t *volname) +{ + MOUNT_LIST_STRUCT mlist; + DWORD dwResult; + int i; + wchar_t volume[TC_MAX_PATH*2+16]; + + if (volname == NULL) + return -1; + + 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)); + DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, + sizeof (mlist), &mlist, sizeof (mlist), &dwResult, + NULL); + + for (i=0 ; i<26; i++) + if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], (WCHAR *)volume)) + return i; + + return -1; +} + + +BOOL IsAdmin (void) +{ + return IsUserAnAdmin (); +} + + +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; +} + + +BOOL GetPartitionInfo (const wchar_t *deviceName, PPARTITION_INFORMATION rpartInfo) +{ + BOOL bResult; + DWORD dwResult; + DISK_PARTITION_INFO_STRUCT dpi; + + memset (&dpi, 0, sizeof(dpi)); + StringCbCopyW ((PWSTR) &dpi.deviceName, sizeof(dpi.deviceName), deviceName); + + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, &dpi, + sizeof (dpi), &dpi, sizeof (dpi), &dwResult, NULL); + + memcpy (rpartInfo, &dpi.partInfo, sizeof (PARTITION_INFORMATION)); + return bResult; +} + + +BOOL GetDeviceInfo (const wchar_t *deviceName, DISK_PARTITION_INFO_STRUCT *info) +{ + DWORD dwResult; + + memset (info, 0, sizeof(*info)); + StringCbCopyW ((PWSTR) &info->deviceName, sizeof(info->deviceName), deviceName); + + return DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, info, sizeof (*info), info, sizeof (*info), &dwResult, NULL); +} + + +BOOL GetDriveGeometry (const wchar_t *deviceName, PDISK_GEOMETRY diskGeometry) +{ + BOOL bResult; + DWORD dwResult; + DISK_GEOMETRY_STRUCT dg; + + memset (&dg, 0, sizeof(dg)); + StringCbCopyW ((PWSTR) &dg.deviceName, sizeof(dg.deviceName), deviceName); + + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_GEOMETRY, &dg, + sizeof (dg), &dg, sizeof (dg), &dwResult, NULL); + + if (bResult && (dwResult == sizeof (dg)) && dg.diskGeometry.BytesPerSector) + { + memcpy (diskGeometry, &dg.diskGeometry, sizeof (DISK_GEOMETRY)); + return TRUE; + } + else + return FALSE; +} + +BOOL GetPhysicalDriveGeometry (int driveNumber, PDISK_GEOMETRY diskGeometry) +{ + HANDLE hDev; + BOOL bResult = FALSE; + TCHAR devicePath[MAX_PATH]; + + StringCchPrintfW (devicePath, ARRAYSIZE (devicePath), L"\\\\.\\PhysicalDrive%d", driveNumber); + + if ((hDev = CreateFileW (devicePath, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) + { + DWORD bytesRead = 0; + + ZeroMemory (diskGeometry, sizeof (DISK_GEOMETRY)); + + if ( DeviceIoControl (hDev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, diskGeometry, sizeof (DISK_GEOMETRY), &bytesRead, NULL) + && (bytesRead == sizeof (DISK_GEOMETRY)) + && diskGeometry->BytesPerSector) + { + bResult = TRUE; + } + + CloseHandle (hDev); + } + + return bResult; +} + + +// Returns drive letter number assigned to device (-1 if none) +int GetDiskDeviceDriveLetter (PWSTR deviceName) +{ + int i; + WCHAR link[MAX_PATH]; + WCHAR target[MAX_PATH]; + WCHAR device[MAX_PATH]; + + if (!ResolveSymbolicLink (deviceName, device, sizeof(device))) + StringCchCopyW (device, MAX_PATH, deviceName); + + for (i = 0; i < 26; i++) + { + WCHAR drive[] = { (WCHAR) i + L'A', L':', 0 }; + + StringCchCopyW (link, MAX_PATH, L"\\DosDevices\\"); + StringCchCatW (link, MAX_PATH, drive); + + if ( ResolveSymbolicLink (link, target, sizeof(target)) + && (wcscmp (device, target) == 0) + ) + { + return i; + } + } + + return -1; +} + + +// WARNING: This function does NOT provide 100% reliable results -- do NOT use it for critical/dangerous operations! +// Return values: 0 - filesystem does not appear empty, 1 - filesystem appears empty, -1 - an error occurred +int FileSystemAppearsEmpty (const wchar_t *devicePath) +{ + float percentFreeSpace = 0.0; + __int64 occupiedBytes = 0; + + if (GetStatsFreeSpaceOnPartition (devicePath, &percentFreeSpace, &occupiedBytes, TRUE) != -1) + { + if (occupiedBytes > BYTES_PER_GB && percentFreeSpace < 99.99 // "percentFreeSpace < 99.99" is needed because an NTFS filesystem larger than several terabytes can have more than 1GB of data in use, even if there are no files stored on it. + || percentFreeSpace < 88) // A 24-MB NTFS filesystem has 11.5% of space in use even if there are no files stored on it. + { + return 0; + } + else + return 1; + } + else + return -1; +} + + +// Returns the free space on the specified partition (volume) in bytes. If the 'occupiedBytes' pointer +// is not NULL, size of occupied space (in bytes) is written to the pointed location. In addition, if the +// 'percent' pointer is not NULL, % of free space is stored in the pointed location. If there's an error, +// returns -1. +__int64 GetStatsFreeSpaceOnPartition (const wchar_t *devicePath, float *percentFree, __int64 *occupiedBytes, BOOL silent) +{ + WCHAR devPath [MAX_PATH]; + int driveLetterNo = -1; + wchar_t szRootPath[4] = {0, L':', L'\\', 0}; + ULARGE_INTEGER freeSpaceSize; + ULARGE_INTEGER totalNumberOfBytes; + ULARGE_INTEGER totalNumberOfFreeBytes; + + StringCbCopyW (devPath, sizeof(devPath), devicePath); + + driveLetterNo = GetDiskDeviceDriveLetter (devPath); + szRootPath[0] = (wchar_t) driveLetterNo + L'A'; + + + if (!GetDiskFreeSpaceEx (szRootPath, &freeSpaceSize, &totalNumberOfBytes, &totalNumberOfFreeBytes)) + { + if (!silent) + { + handleWin32Error (MainDlg, SRC_POS); + Error ("CANNOT_CALC_SPACE", MainDlg); + } + + return -1; + } + + + if (percentFree != NULL || occupiedBytes != NULL) + { + // Determine occupied space and % of free space + + PARTITION_INFORMATION partitionInfo; + + if (!GetPartitionInfo (devicePath, &partitionInfo)) + { + if (!silent) + { + handleWin32Error (MainDlg, SRC_POS); + Error ("CANT_GET_VOLSIZE", MainDlg); + } + return -1; + } + + if (occupiedBytes != NULL) + *occupiedBytes = partitionInfo.PartitionLength.QuadPart - freeSpaceSize.QuadPart; + + if (percentFree != NULL) + *percentFree = (float) ((double) freeSpaceSize.QuadPart / (double) partitionInfo.PartitionLength.QuadPart * 100.0); + } + + return freeSpaceSize.QuadPart; +} + + +// Returns -1 if there's an error. +__int64 GetDeviceSize (const wchar_t *devicePath) +{ + PARTITION_INFORMATION partitionInfo; + + if (!GetPartitionInfo (devicePath, &partitionInfo)) + return -1; + + return partitionInfo.PartitionLength.QuadPart; +} + + +HANDLE DismountDrive (wchar_t *devName, wchar_t *devicePath) +{ + DWORD dwResult; + HANDLE hVolume; + BOOL bResult = FALSE; + int attempt = UNMOUNT_MAX_AUTO_RETRIES; + int driveLetterNo = -1; + WCHAR devPath [MAX_PATH]; + + StringCbCopyW (devPath, sizeof(devPath), devicePath); + driveLetterNo = GetDiskDeviceDriveLetter (devPath); + + + hVolume = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (hVolume == INVALID_HANDLE_VALUE) + return INVALID_HANDLE_VALUE; + + + // Try to lock the volume first so that dismount is not forced. + // If we fail, we will dismount anyway even if it needs to be forced. + + CloseVolumeExplorerWindows (MainDlg, driveLetterNo); + + while (!(bResult = DeviceIoControl (hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) + && attempt > 0) + { + Sleep (UNMOUNT_AUTO_RETRY_DELAY); + attempt--; + } + + + // Try to dismount the volume + + attempt = UNMOUNT_MAX_AUTO_RETRIES; + + while (!(bResult = DeviceIoControl (hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) + && attempt > 0) + { + Sleep (UNMOUNT_AUTO_RETRY_DELAY); + attempt--; + } + + if (!bResult) + CloseHandle (hVolume); + + return (bResult ? hVolume : INVALID_HANDLE_VALUE); +} + +// Returns -1 if the specified string is not found in the buffer. Otherwise, returns the +// offset of the first occurrence of the string. The string and the buffer may contain zeroes, +// which do NOT terminate them. +int64 FindString (const char *buf, const char *str, int64 bufLen, int64 strLen, int64 startOffset) +{ + if (buf == NULL + || str == NULL + || strLen > bufLen + || bufLen < 1 + || strLen < 1 + || startOffset > bufLen - strLen) + { + return -1; + } + + for (int64 i = startOffset; i <= bufLen - strLen; i++) + { + if (memcmp (buf + i, str, (size_t) strLen) == 0) + return i; + } + + return -1; +} + +// Returns TRUE if the file or directory exists (both may be enclosed in quotation marks). +BOOL FileExists (const wchar_t *filePathPtr) +{ + wchar_t filePath [TC_MAX_PATH * 2 + 1]; + + // Strip quotation marks (if any) + if (filePathPtr [0] == L'"') + { + StringCbCopyW (filePath, sizeof(filePath), filePathPtr + 1); + } + else + { + StringCbCopyW (filePath, sizeof(filePath), filePathPtr); + } + + // Strip quotation marks (if any) + if (filePath [wcslen (filePath) - 1] == L'"') + filePath [wcslen (filePath) - 1] = 0; + + return (_waccess (filePath, 0) != -1); +} + +// Searches the file from its end for the LAST occurrence of the string str. +// The string may contain zeroes, which do NOT terminate the string. +// If the string is found, its offset from the start of the file is returned. +// If the string isn't found or if any error occurs, -1 is returned. +__int64 FindStringInFile (const wchar_t *filePath, const char* str, int strLen) +{ + int bufSize = 64 * BYTES_PER_KB; + char *buffer = (char *) err_malloc (bufSize); + HANDLE src = NULL; + DWORD bytesRead; + BOOL readRetVal; + __int64 filePos = GetFileSize64 (filePath); + int bufPos = 0; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL bExit = FALSE; + int filePosStep; + __int64 retVal = -1; + + if (filePos <= 0 + || buffer == NULL + || strLen > bufSize + || strLen < 1) + { + if (buffer) + free (buffer); + return -1; + } + + src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + { + free (buffer); + return -1; + } + + filePosStep = bufSize - strLen + 1; + + do + { + filePos -= filePosStep; + + if (filePos < 0) + { + filePos = 0; + bExit = TRUE; + } + + seekOffset.QuadPart = filePos; + + if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + goto fsif_end; + + if ((readRetVal = ReadFile (src, buffer, bufSize, &bytesRead, NULL)) == 0 + || bytesRead == 0) + goto fsif_end; + + bufPos = bytesRead - strLen; + + while (bufPos > 0) + { + if (memcmp (buffer + bufPos, str, strLen) == 0) + { + // String found + retVal = filePos + bufPos; + goto fsif_end; + } + bufPos--; + } + + } while (!bExit); + +fsif_end: + CloseHandle (src); + free (buffer); + + return retVal; +} + +// System CopyFile() copies source file attributes (like FILE_ATTRIBUTE_ENCRYPTED) +// so we need to use our own copy function +BOOL TCCopyFileBase (HANDLE src, HANDLE dst) +{ + __int8 *buffer; + FILETIME fileTime; + DWORD bytesRead, bytesWritten; + BOOL res; + + buffer = (char *) malloc (64 * 1024); + if (!buffer) + { + CloseHandle (src); + CloseHandle (dst); + return FALSE; + } + + while (res = ReadFile (src, buffer, 64 * 1024, &bytesRead, NULL)) + { + if (bytesRead == 0) + { + res = 1; + break; + } + + if (!WriteFile (dst, buffer, bytesRead, &bytesWritten, NULL) + || bytesRead != bytesWritten) + { + res = 0; + break; + } + } + + if (GetFileTime (src, NULL, NULL, &fileTime)) + SetFileTime (dst, NULL, NULL, &fileTime); + + CloseHandle (src); + CloseHandle (dst); + + free (buffer); + return res != 0; +} + +BOOL TCCopyFile (wchar_t *sourceFileName, wchar_t *destinationFile) +{ + HANDLE src, dst; + + src = CreateFileW (sourceFileName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + return FALSE; + + dst = CreateFileW (destinationFile, + GENERIC_WRITE, + 0, NULL, CREATE_ALWAYS, 0, NULL); + + if (dst == INVALID_HANDLE_VALUE) + { + CloseHandle (src); + return FALSE; + } + + return TCCopyFileBase (src, dst); +} + +// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file +// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE). +BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed) +{ + HANDLE dst; + DWORD bytesWritten; + BOOL res = TRUE; + DWORD dwLastError = 0; + + dst = CreateFile (destinationFile, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); + + dwLastError = GetLastError(); + if (!bAppend && bRenameIfFailed && (dst == INVALID_HANDLE_VALUE) && (GetLastError () == ERROR_SHARING_VIOLATION)) + { + wchar_t renamedPath[TC_MAX_PATH + 1]; + StringCbCopyW (renamedPath, sizeof(renamedPath), destinationFile); + StringCbCatW (renamedPath, sizeof(renamedPath), VC_FILENAME_RENAMED_SUFFIX); + + /* rename the locked file in order to be able to create a new one */ + if (MoveFileEx (destinationFile, renamedPath, MOVEFILE_REPLACE_EXISTING)) + { + dst = CreateFile (destinationFile, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); + dwLastError = GetLastError(); + if (dst == INVALID_HANDLE_VALUE) + { + /* restore the original file name */ + MoveFileEx (renamedPath, destinationFile, MOVEFILE_REPLACE_EXISTING); + } + else + { + /* delete the renamed file when the machine reboots */ + MoveFileEx (renamedPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); + } + } + } + + if (dst == INVALID_HANDLE_VALUE) + { + SetLastError (dwLastError); + handleWin32Error (MainDlg, SRC_POS); + return FALSE; + } + + if (bAppend) + SetFilePointer (dst, 0, NULL, FILE_END); + + if (!WriteFile (dst, inputBuffer, inputLength, &bytesWritten, NULL) + || inputLength != bytesWritten) + { + res = FALSE; + } + + if (!res) + { + // If CREATE_ALWAYS is used, ERROR_ALREADY_EXISTS is returned after successful overwrite + // of an existing file (it's not an error) + if (! (GetLastError() == ERROR_ALREADY_EXISTS && !bAppend) ) + handleWin32Error (MainDlg, SRC_POS); + } + + CloseHandle (dst); + + if (!res && !bAppend) + _wremove (destinationFile); + + return res; +} + + +// Proper flush for Windows systems. Returns TRUE if successful. +BOOL TCFlushFile (FILE *f) +{ + HANDLE hf = (HANDLE) _get_osfhandle (_fileno (f)); + + fflush (f); + + if (hf == INVALID_HANDLE_VALUE) + return FALSE; + + return FlushFileBuffers (hf) != 0; +} + + +// Prints a UTF-16 text (note that this involves a real printer, not a screen). +// textByteLen - length of the text in bytes +// title - printed as part of the page header and used as the filename for a temporary file +BOOL PrintHardCopyTextUTF16 (wchar_t *text, wchar_t *title, size_t textByteLen) +{ + wchar_t cl [MAX_PATH*3] = {L"/p \""}; + wchar_t path [MAX_PATH * 2] = { 0 }; + wchar_t filename [MAX_PATH + 1] = { 0 }; + + StringCbCopyW (filename, sizeof(filename), title); + //strcat (filename, ".txt"); + + GetTempPath (ARRAYSIZE (path), path); + + if (!FileExists (path)) + { + StringCbCopyW (path, sizeof(path), GetConfigPath (filename)); + + if (wcslen(path) < 2) + return FALSE; + } + else + { + StringCbCatW (path, sizeof(path), filename); + } + + // Write the Unicode signature + if (!SaveBufferToFile ("\xFF\xFE", path, 2, FALSE, FALSE)) + { + _wremove (path); + return FALSE; + } + + // Write the actual text + if (!SaveBufferToFile ((char *) text, path, (DWORD) textByteLen, TRUE, FALSE)) + { + _wremove (path); + return FALSE; + } + + StringCbCatW (cl, sizeof(cl), path); + StringCbCatW (cl, sizeof(cl), L"\""); + + // Get the absolute path for notepad + if (GetWindowsDirectory(filename, MAX_PATH)) + { + if (filename[wcslen (filename) - 1] != L'\\') + StringCbCatW (filename, sizeof(filename), L"\\"); + StringCbCatW(filename, sizeof(filename), PRINT_TOOL); + } + else + StringCbCopyW(filename, sizeof(filename), L"C:\\Windows\\" PRINT_TOOL); + + WaitCursor (); + ShellExecute (NULL, L"open", filename, cl, NULL, SW_HIDE); + Sleep (6000); + NormalCursor(); + + _wremove (path); + + return TRUE; +} + + +BOOL IsNonInstallMode () +{ + HKEY hkey; + DWORD dw; + + if (bPortableModeConfirmed) + return TRUE; + + if (hDriver != INVALID_HANDLE_VALUE) + { + // The driver is running + if (DeviceIoControl (hDriver, TC_IOCTL_GET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dw, 0)) + { + bPortableModeConfirmed = TRUE; + return TRUE; + } + else + { + // This is also returned if we fail to determine the status (it does not mean that portable mode is disproved). + return FALSE; + } + } + else + { + // The tests in this block are necessary because this function is in some cases called before DriverAttach(). + + HANDLE hDriverTmp = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (hDriverTmp == INVALID_HANDLE_VALUE) + { + // The driver was not found in the system path + + wchar_t path[MAX_PATH * 2] = { 0 }; + + // We can't use GetConfigPath() here because it would call us back (indirect recursion) + if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path))) + { + StringCbCatW (path, MAX_PATH * 2, L"\\VeraCrypt\\"); + StringCbCatW (path, MAX_PATH * 2, TC_APPD_FILENAME_SYSTEM_ENCRYPTION); + + if (FileExists (path)) + { + // To maintain consistency and safety, if the system encryption config file exits, we cannot + // allow portable mode. (This happens e.g. when the pretest fails and the user selects + // "Last Known Good Configuration" from the Windows boot menu.) + + // However, if UAC elevation is needed, we have to confirm portable mode first (after we are elevated, we won't). + if (!IsAdmin () && IsUacSupported ()) + return TRUE; + + return FALSE; + } + } + + // As the driver was not found in the system path, we can predict that we will run in portable mode + return TRUE; + } + else + CloseHandle (hDriverTmp); + } + + // The following test may be unreliable in some cases (e.g. after the user selects restore "Last Known Good + // Configuration" from the Windows boot menu). + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt", 0, KEY_READ | KEY_WOW64_32KEY, &hkey) == ERROR_SUCCESS) + { + RegCloseKey (hkey); + return FALSE; + } + else + return TRUE; +} + + +LRESULT SetCheckBox (HWND hwndDlg, int dlgItem, BOOL state) +{ + return SendDlgItemMessage (hwndDlg, dlgItem, BM_SETCHECK, state ? BST_CHECKED : BST_UNCHECKED, 0); +} + + +BOOL GetCheckBox (HWND hwndDlg, int dlgItem) +{ + return IsButtonChecked (GetDlgItem (hwndDlg, dlgItem)); +} + + +// Scroll the listview vertically so that the item with index of topMostVisibleItem is the topmost visible item. +void SetListScrollHPos (HWND hList, int topMostVisibleItem) +{ + int testedPos = 0; + + do + { + SendMessage (hList, LVM_SCROLL, 0, testedPos); + + } while (ListView_GetTopIndex (hList) < topMostVisibleItem && ++testedPos < 10000); +} + + +// Adds or removes TrueCrypt.exe to/from the system startup sequence (with appropriate command line arguments) +void ManageStartupSeq (void) +{ + if (!IsNonInstallMode ()) + { + wchar_t regk [64]; + + GetStartupRegKeyName (regk, sizeof(regk)); + + if (bStartOnLogon || bMountDevicesOnLogon || bMountFavoritesOnLogon) + { + wchar_t exe[MAX_PATH * 2] = { L'"' }; + + GetModuleFileName (NULL, exe + 1, ARRAYSIZE (exe) - 1); + +#ifdef VOLFORMAT + { + wchar_t *tmp = NULL; + + if (tmp = wcsrchr (exe, L'\\')) + { + *tmp = 0; + StringCbCatW (exe, MAX_PATH * 2, L"\\VeraCrypt.exe"); + } + } +#endif + StringCbCatW (exe, MAX_PATH * 2, L"\" /q preferences /a logon"); + + if (bMountDevicesOnLogon) StringCbCatW (exe, MAX_PATH * 2, L" /a devices"); + if (bMountFavoritesOnLogon) StringCbCatW (exe, MAX_PATH * 2, L" /a favorites"); + + WriteRegistryString (regk, L"VeraCrypt", exe); + } + else + DeleteRegistryValue (regk, L"VeraCrypt"); + } +} + + +// Adds or removes the VeraCrypt Volume Creation Wizard to/from the system startup sequence +void ManageStartupSeqWiz (BOOL bRemove, const wchar_t *arg) +{ + wchar_t regk [64]; + + GetStartupRegKeyName (regk, sizeof(regk)); + + if (!bRemove) + { + size_t exeSize = (MAX_PATH * 2) + 3 + 20 + wcslen (arg); // enough room for all concatenation operations + wchar_t* exe = (wchar_t*) calloc(1, exeSize * sizeof (wchar_t)); + exe[0] = L'"'; + GetModuleFileName (NULL, exe + 1, (DWORD) (exeSize - 1)); + +#ifndef VOLFORMAT + { + wchar_t *tmp = NULL; + + if (tmp = wcsrchr (exe, L'\\')) + { + *tmp = 0; + + StringCchCatW (exe, exeSize, L"\\VeraCrypt Format.exe"); + } + } +#endif + + 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""); + + for (id = (IsOSAtLeast (WIN_VISTA) ? 0 : L'a'); id <= (IsOSAtLeast (WIN_VISTA) ? 1000 : L'z'); id++) + { + *strTmp = 0; + StringCbPrintfW (key, sizeof(key), (IsOSAtLeast (WIN_VISTA) ? L"%d" : L"%c"), 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); + + if (*p == id) + { + p++; + len -= sizeof (int); + continue; + } + *pout++ = *p++; + } + + WriteRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", bufout, len); + } + else + { + wchar_t *p = (wchar_t*) buf; + wchar_t *pout = (wchar_t*) bufout; + + ReadRegistryString (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", L"MRUList", L"", (wchar_t*) buf, sizeof (buf)); + while (*p) + { + if (*p == id) + { + p++; + continue; + } + *pout++ = *p++; + } + *pout++ = 0; + + WriteRegistryString (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", L"MRUList", (wchar_t*) bufout); + } + + 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; + li.iSubItem = 0; + return ListView_InsertItem (list, &li); +} + + +LRESULT ListSubItemSet (HWND list, int index, int subIndex, const wchar_t *string) +{ + LVITEM li; + memset (&li, 0, sizeof(li)); + + li.mask = LVIF_TEXT; + li.pszText = (wchar_t*) string; + li.iItem = index; + li.iSubItem = subIndex; + return ListView_SetItem (list, &li); +} + + +BOOL GetMountList (MOUNT_LIST_STRUCT *list) +{ + DWORD dwResult; + + memset (list, 0, sizeof (*list)); + return DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, list, + sizeof (*list), list, sizeof (*list), &dwResult, + NULL); +} + + +int GetDriverRefCount () +{ + DWORD dwResult; + BOOL bResult; + int refCount; + + bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount, + sizeof (refCount), &dwResult, NULL); + + if (bResult) + return refCount; + else + return -1; +} + +// Loads a 32-bit integer from the file at the specified file offset. The saved value is assumed to have been +// processed by mputLong(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). +BOOL LoadInt32 (const wchar_t *filePath, unsigned __int32 *result, __int64 fileOffset) +{ + DWORD bufSize = sizeof(__int32); + unsigned char *buffer = (unsigned char *) malloc (bufSize); + unsigned char *bufferPtr = buffer; + HANDLE src = NULL; + DWORD bytesRead; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL retVal = FALSE; + + if (buffer == NULL) + return -1; + + src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + { + free (buffer); + return FALSE; + } + + seekOffset.QuadPart = fileOffset; + + if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + goto fsif_end; + + if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 + || bytesRead != bufSize) + goto fsif_end; + + + retVal = TRUE; + + *result = mgetLong(bufferPtr); + +fsif_end: + CloseHandle (src); + free (buffer); + + return retVal; +} + +// Loads a 16-bit integer from the file at the specified file offset. The saved value is assumed to have been +// processed by mputWord(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). +BOOL LoadInt16 (const wchar_t *filePath, int *result, __int64 fileOffset) +{ + DWORD bufSize = sizeof(__int16); + unsigned char *buffer = (unsigned char *) malloc (bufSize); + unsigned char *bufferPtr = buffer; + HANDLE src = NULL; + DWORD bytesRead; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL retVal = FALSE; + + if (buffer == NULL) + return -1; + + src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (src == INVALID_HANDLE_VALUE) + { + free (buffer); + return FALSE; + } + + seekOffset.QuadPart = fileOffset; + + if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + goto fsif_end; + + if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 + || bytesRead != bufSize) + goto fsif_end; + + + retVal = TRUE; + + *result = mgetWord(bufferPtr); + +fsif_end: + CloseHandle (src); + free (buffer); + + return retVal; +} + +// Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated. +char *LoadFile (const wchar_t *fileName, DWORD *size) +{ + char *buf; + DWORD fileSize = INVALID_FILE_SIZE; + HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (h == INVALID_HANDLE_VALUE) + return NULL; + + if ((fileSize = GetFileSize (h, NULL)) == INVALID_FILE_SIZE) + { + CloseHandle (h); + return NULL; + } + + *size = fileSize; + buf = (char *) calloc (*size + 1, 1); + + if (buf == NULL) + { + CloseHandle (h); + return NULL; + } + + if (!ReadFile (h, buf, *size, size, NULL)) + { + free (buf); + buf = NULL; + } + + CloseHandle (h); + return buf; +} + + +// Returns NULL if there's any error. +char *LoadFileBlock (const wchar_t *fileName, __int64 fileOffset, DWORD count) +{ + char *buf; + DWORD bytesRead = 0; + LARGE_INTEGER seekOffset, seekOffsetNew; + BOOL bStatus; + + HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (h == INVALID_HANDLE_VALUE) + return NULL; + + seekOffset.QuadPart = fileOffset; + + if (SetFilePointerEx (h, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) + { + CloseHandle (h); + return NULL; + } + + buf = (char *) calloc (count, 1); + + if (buf == NULL) + { + CloseHandle (h); + return NULL; + } + + bStatus = ReadFile (h, buf, count, &bytesRead, NULL); + + CloseHandle (h); + + if (!bStatus || (bytesRead != count)) + { + free (buf); + return NULL; + } + + return buf; +} + + +// Returns -1 if there is an error, or the size of the file. +__int64 GetFileSize64 (const wchar_t *path) +{ + HANDLE h = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + LARGE_INTEGER size; + __int64 retSize = -1; + + if (h) + { + if (GetFileSizeEx (h, &size)) + { + retSize = size.QuadPart; + } + + CloseHandle (h); + } + + return retSize; +} + + +wchar_t *GetModPath (wchar_t *path, int maxSize) +{ + GetModuleFileName (NULL, path, maxSize); + wchar_t* ptr = wcsrchr (path, L'\\'); + if (ptr) + ptr[1] = 0; + return path; +} + + +wchar_t *GetConfigPath (wchar_t *fileName) +{ + static wchar_t path[MAX_PATH * 2] = { 0 }; + + if (IsNonInstallMode ()) + { + GetModPath (path, ARRAYSIZE (path)); + StringCchCatW (path, (MAX_PATH * 2), fileName); + + return path; + } + + if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) + { + StringCchCatW (path, (MAX_PATH * 2), L"\\VeraCrypt\\"); + CreateDirectory (path, NULL); + StringCchCatW (path, (MAX_PATH * 2), fileName); + } + else + path[0] = 0; + + return path; +} + + +wchar_t *GetProgramConfigPath (wchar_t *fileName) +{ + static wchar_t path[MAX_PATH * 2] = { 0 }; + + if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) + { + StringCchCatW (path, (MAX_PATH * 2), L"\\VeraCrypt\\"); + CreateDirectory (path, NULL); + StringCchCatW (path, (MAX_PATH * 2), fileName); + } + else + path[0] = 0; + + return path; +} + + +std::wstring GetServiceConfigPath (const wchar_t *fileName, bool useLegacy) +{ + wchar_t sysPath[TC_MAX_PATH]; + + if (Is64BitOs() && useLegacy) + { + typedef UINT (WINAPI *GetSystemWow64Directory_t) (LPWSTR lpBuffer, UINT uSize); + + GetSystemWow64Directory_t getSystemWow64Directory = (GetSystemWow64Directory_t) GetProcAddress (GetModuleHandle (L"kernel32"), "GetSystemWow64DirectoryW"); + getSystemWow64Directory (sysPath, ARRAYSIZE (sysPath)); + } + else + GetSystemDirectory (sysPath, ARRAYSIZE (sysPath)); + + return wstring (sysPath) + L"\\" + fileName; +} + + +// 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) +{ + if (nCurrentOS == WIN_2000) + { + MessageBoxW (MainDlg, text, headline, warning ? MB_ICONWARNING : MB_ICONINFORMATION); + return; + } + + 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 + + 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, + headingString == NULL ? L"VeraCrypt" : headingString, + textString == NULL ? L" " : textString, + FALSE); +} + + +// Either of the pointers may be NULL +void WarningBalloon (char *headingStringId, char *textStringId, HWND hwnd) +{ + if (Silent) + return; + + TaskBarIconDisplayBalloonTooltip (hwnd, + headingStringId == NULL ? L"VeraCrypt" : GetString (headingStringId), + textStringId == NULL ? L" " : GetString (textStringId), + TRUE); +} + + +// Either of the pointers may be NULL +void WarningBalloonDirect (wchar_t *headingString, wchar_t *textString, HWND hwnd) +{ + if (Silent) + return; + + TaskBarIconDisplayBalloonTooltip (hwnd, + headingString == NULL ? L"VeraCrypt" : headingString, + textString == NULL ? L" " : textString, + TRUE); +} + + +int Info (char *stringId, HWND hwnd) +{ + if (Silent) return 0; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONINFORMATION); +} + + +int InfoTopMost (char *stringId, HWND hwnd) +{ + if (Silent) return 0; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); +} + + +int InfoDirect (const wchar_t *msg, HWND hwnd) +{ + if (Silent) return 0; + return MessageBoxW (hwnd, msg, lpszTitle, MB_ICONINFORMATION); +} + + +int Warning (char *stringId, HWND hwnd) +{ + if (Silent) return 0; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING); +} + + +int WarningTopMost (char *stringId, HWND hwnd) +{ + if (Silent) return 0; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); +} + + +int WarningDirect (const wchar_t *warnMsg, HWND hwnd) +{ + if (Silent) return 0; + return MessageBoxW (hwnd, warnMsg, lpszTitle, MB_ICONWARNING); +} + + +int Error (char *stringId, HWND hwnd) +{ + if (Silent) return 0; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR); +} + +int ErrorRetryCancel (char *stringId, HWND hwnd) +{ + if (Silent) return 0; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_RETRYCANCEL); +} + +int ErrorTopMost (char *stringId, HWND hwnd) +{ + if (Silent) return 0; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); +} + + +int ErrorDirect (const wchar_t *errMsg, HWND hwnd) +{ + if (Silent) return 0; + return MessageBoxW (hwnd, errMsg, lpszTitle, MB_ICONERROR); +} + + +int AskYesNo (char *stringId, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1); +} + + +int AskYesNoString (const wchar_t *str, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, str, lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1); +} + + +int AskYesNoTopmost (char *stringId, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1 | MB_SETFOREGROUND | MB_TOPMOST); +} + + +int AskNoYes (char *stringId, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); +} + +int AskNoYesString (const wchar_t *string, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, string, lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); +} + +int AskOkCancel (char *stringId, HWND hwnd) +{ + if (Silent) return IDCANCEL; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_OKCANCEL | MB_DEFBUTTON1); +} + + +int AskWarnYesNo (char *stringId, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1); +} + + +int AskWarnYesNoString (const wchar_t *string, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1); +} + + +int AskWarnYesNoTopmost (char *stringId, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1 | MB_SETFOREGROUND | MB_TOPMOST); +} + + +int AskWarnYesNoStringTopmost (const wchar_t *string, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1 | MB_SETFOREGROUND | MB_TOPMOST); +} + + +int AskWarnNoYes (char *stringId, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); +} + + +int AskWarnNoYesString (const wchar_t *string, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); +} + + +int AskWarnNoYesTopmost (char *stringId, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2 | MB_SETFOREGROUND | MB_TOPMOST); +} + + +int AskWarnOkCancel (char *stringId, HWND hwnd) +{ + if (Silent) return IDCANCEL; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON1); +} + + +int AskWarnCancelOk (char *stringId, HWND hwnd) +{ + if (Silent) return IDCANCEL; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2); +} + + +int AskErrYesNo (char *stringId, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1); +} + + +int AskErrNoYes (char *stringId, HWND hwnd) +{ + if (Silent) return IDNO; + return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_YESNO | MB_DEFBUTTON2); +} + + +// The function accepts two input formats: +// Input format 1: {0, "MESSAGE_STRING_ID", "BUTTON_1_STRING_ID", ... "LAST_BUTTON_STRING_ID", 0}; +// Input format 2: {L"", L"Message text", L"Button caption 1", ... L"Last button caption", 0}; +// The second format is to be used if any of the strings contains format specification (e.g. %s, %d) or +// in any other cases where a string needs to be resolved before calling this function. +// The returned value is the ordinal number of the choice the user selected (1..MAX_MULTI_CHOICES) +int AskMultiChoice (void *strings[], BOOL bBold, HWND hwnd) +{ + MULTI_CHOICE_DLGPROC_PARAMS params; + + params.strings = &strings[0]; + params.bold = bBold; + + return (int) DialogBoxParamW (hInst, + MAKEINTRESOURCEW (IDD_MULTI_CHOICE_DLG), hwnd, + (DLGPROC) MultiChoiceDialogProc, (LPARAM) ¶ms); +} + + +BOOL ConfigWriteBegin () +{ + DWORD size; + if (ConfigFileHandle != NULL) + return FALSE; + + if (ConfigBuffer == NULL) + ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); + + ConfigFileHandle = _wfopen (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), L"w,ccs=UTF-8"); + if (ConfigFileHandle == NULL) + { + free (ConfigBuffer); + ConfigBuffer = NULL; + return FALSE; + } + XmlWriteHeader (ConfigFileHandle); + fputws (L"\n\t", ConfigFileHandle); + + return TRUE; +} + + +BOOL ConfigWriteEnd (HWND hwnd) +{ + char *xml = ConfigBuffer; + char key[128], value[2048]; + + if (ConfigFileHandle == NULL) return FALSE; + + // Write unmodified values + while (xml && (xml = XmlFindElement (xml, "config"))) + { + XmlGetAttributeText (xml, "key", key, sizeof (key)); + XmlGetNodeText (xml, value, sizeof (value)); + + fwprintf (ConfigFileHandle, L"\n\t\t%hs", key, value); + xml++; + } + + fputws (L"\n\t", ConfigFileHandle); + XmlWriteFooter (ConfigFileHandle); + + TCFlushFile (ConfigFileHandle); + + CheckFileStreamWriteErrors (hwnd, ConfigFileHandle, TC_APPD_FILENAME_CONFIGURATION); + + fclose (ConfigFileHandle); + ConfigFileHandle = NULL; + + if (ConfigBuffer != NULL) + { + DWORD size; + free (ConfigBuffer); + ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); + } + + return TRUE; +} + + +BOOL ConfigWriteString (char *configKey, char *configValue) +{ + char *c; + if (ConfigFileHandle == NULL) + return FALSE; + + // Mark previous config value as updated + if (ConfigBuffer != NULL) + { + c = XmlFindElementByAttributeValue (ConfigBuffer, "config", "key", configKey); + if (c != NULL) + c[1] = '!'; + } + + return 0 != fwprintf ( + ConfigFileHandle, L"\n\t\t%hs", + configKey, configValue); +} + +BOOL ConfigWriteStringW (char *configKey, wchar_t *configValue) +{ + char *c; + if (ConfigFileHandle == NULL) + return FALSE; + + // Mark previous config value as updated + if (ConfigBuffer != NULL) + { + c = XmlFindElementByAttributeValue (ConfigBuffer, "config", "key", configKey); + if (c != NULL) + c[1] = '!'; + } + + return 0 != fwprintf ( + ConfigFileHandle, L"\n\t\t%ls", + configKey, configValue); +} + +BOOL ConfigWriteInt (char *configKey, int configValue) +{ + char val[32]; + StringCbPrintfA (val, sizeof(val), "%d", configValue); + return ConfigWriteString (configKey, val); +} + + +static BOOL ConfigRead (char *configKey, char *configValue, int maxValueSize) +{ + DWORD size; + char *xml; + + if (ConfigBuffer == NULL) + ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); + + xml = ConfigBuffer; + if (xml != NULL) + { + xml = XmlFindElementByAttributeValue (xml, "config", "key", configKey); + if (xml != NULL) + { + XmlGetNodeText (xml, configValue, maxValueSize); + return TRUE; + } + } + + return FALSE; +} + + +int ConfigReadInt (char *configKey, int defaultValue) +{ + char s[32]; + + if (ConfigRead (configKey, s, sizeof (s))) + return atoi (s); + else + return defaultValue; +} + + +char *ConfigReadString (char *configKey, char *defaultValue, char *str, int maxLen) +{ + if (ConfigRead (configKey, str, maxLen)) + return str; + else + { + StringCbCopyA (str, maxLen, defaultValue); + return defaultValue; + } +} + +void ConfigReadCompareInt(char *configKey, int defaultValue, int* pOutputValue, BOOL bOnlyCheckModified, BOOL* pbModified) +{ + int intValue = ConfigReadInt (configKey, defaultValue); + if (pOutputValue) + { + if (pbModified && (*pOutputValue != intValue)) + *pbModified = TRUE; + if (!bOnlyCheckModified) + *pOutputValue = intValue; + } +} + +void ConfigReadCompareString (char *configKey, char *defaultValue, char *str, int maxLen, BOOL bOnlyCheckModified, BOOL *pbModified) +{ + char *strValue = (char*) malloc (maxLen); + if (strValue) + { + memcpy (strValue, str, maxLen); + + ConfigReadString (configKey, defaultValue, strValue, maxLen); + + if (pbModified && strcmp (str, strValue)) + *pbModified = TRUE; + if (!bOnlyCheckModified) + memcpy(str, strValue, maxLen); + + free (strValue); + } + else + { + /* allocation failed. Suppose that value changed */ + if (pbModified) + *pbModified = TRUE; + if (!bOnlyCheckModified) + ConfigReadString (configKey, defaultValue, str, maxLen); + + } +} + +void OpenPageHelp (HWND hwndDlg, int nPage) +{ + int r = (int)ShellExecuteW (NULL, L"open", szHelpFile, NULL, NULL, SW_SHOWNORMAL); + + if (r == ERROR_FILE_NOT_FOUND) + { + // Try the secondary help file + r = (int)ShellExecuteW (NULL, L"open", szHelpFile2, NULL, NULL, SW_SHOWNORMAL); + + if (r == ERROR_FILE_NOT_FOUND) + { + OpenOnlineHelp (); + return; + } + } + + if (r == SE_ERR_NOASSOC) + { + if (AskYesNo ("HELP_READER_ERROR", MainDlg) == IDYES) + OpenOnlineHelp (); + } +} + + +void OpenOnlineHelp () +{ + Applink ("help", TRUE, ""); +} + + +#ifndef SETUP + +void RestoreDefaultKeyFilesParam (void) +{ + KeyFileRemoveAll (&FirstKeyFile); + if (defaultKeyFilesParam.FirstKeyFile != NULL) + { + KeyFileCloneAll (defaultKeyFilesParam.FirstKeyFile, &FirstKeyFile); + KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles; + } + else + KeyFilesEnable = FALSE; +} + + +BOOL LoadDefaultKeyFilesParam (void) +{ + BOOL status = TRUE; + DWORD size; + char *defaultKeyfilesFile = LoadFile (GetConfigPath (TC_APPD_FILENAME_DEFAULT_KEYFILES), &size); + char *xml = defaultKeyfilesFile; + KeyFile *kf; + + if (xml == NULL) + return FALSE; + + KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); + + while (xml = XmlFindElement (xml, "keyfile")) + { + kf = (KeyFile *) malloc (sizeof (KeyFile)); + if (kf) + { + char fileName [MAX_PATH + 1]; + if (XmlGetNodeText (xml, fileName, sizeof (fileName)) != NULL) + { + std::wstring wszFileName = Utf8StringToWide(fileName); + StringCbCopyW (kf->FileName, sizeof (kf->FileName), wszFileName.c_str ()); + defaultKeyFilesParam.FirstKeyFile = KeyFileAdd (defaultKeyFilesParam.FirstKeyFile, kf); + } + else + free (kf); + } + else + { + KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); + status = FALSE; + break; + } + + xml++; + } + + free (defaultKeyfilesFile); + if (status) + KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles; + + return status; +} + +#endif /* #ifndef SETUP */ + + +void Debug (char *format, ...) +{ + char buf[1024]; + va_list val; + + va_start(val, format); + StringCbVPrintfA (buf, sizeof (buf), format, val); + va_end(val); + + OutputDebugStringA (buf); +} + + +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 IsOSAtLeast (OSVersionEnum reqMinOS) +{ + return IsOSVersionAtLeast (reqMinOS, 0); +} + + +// Returns TRUE if the operating system is at least reqMinOS and service pack at least reqMinServicePack. +// Example 1: IsOSVersionAtLeast (WIN_VISTA, 1) called under Windows 2008, returns TRUE. +// Example 2: IsOSVersionAtLeast (WIN_XP, 3) called under Windows XP SP1, returns FALSE. +// Example 3: IsOSVersionAtLeast (WIN_XP, 3) called under Windows Vista SP1, returns TRUE. +BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack) +{ + /* When updating this function, update IsOSAtLeast() in Ntdriver.c too. */ + + if (CurrentOSMajor <= 0) + TC_THROW_FATAL_EXCEPTION; + + int major = 0, minor = 0; + + switch (reqMinOS) + { + case WIN_2000: major = 5; minor = 0; break; + case WIN_XP: major = 5; minor = 1; break; + case WIN_SERVER_2003: major = 5; minor = 2; break; + case WIN_VISTA: major = 6; minor = 0; break; + case WIN_7: major = 6; minor = 1; break; + case WIN_8: major = 6; minor = 2; break; + case WIN_8_1: major = 6; minor = 3; break; + case WIN_10: major = 10; minor = 0; break; + + default: + TC_THROW_FATAL_EXCEPTION; + break; + } + + return ((CurrentOSMajor << 16 | CurrentOSMinor << 8 | CurrentOSServicePack) + >= (major << 16 | minor << 8 | reqMinServicePack)); +} + + +BOOL Is64BitOs () +{ +#ifdef _WIN64 + return TRUE; +#else + static BOOL isWow64 = FALSE; + static BOOL valid = FALSE; + typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS ) (HANDLE hProcess,PBOOL Wow64Process); + LPFN_ISWOW64PROCESS fnIsWow64Process; + + if (valid) + return isWow64; + + fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle(L"kernel32"), "IsWow64Process"); + + if (fnIsWow64Process != NULL) + if (!fnIsWow64Process (GetCurrentProcess(), &isWow64)) + isWow64 = FALSE; + + valid = TRUE; + return isWow64; +#endif +} + + +BOOL IsServerOS () +{ + OSVERSIONINFOEXW osVer; + osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); + GetVersionExW ((LPOSVERSIONINFOW) &osVer); + + return (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER); +} + + +// Returns TRUE, if the currently running operating system is installed in a hidden volume. If it's not, or if +// there's an error, returns FALSE. +BOOL IsHiddenOSRunning (void) +{ + static BOOL statusCached = FALSE; + static BOOL hiddenOSRunning; + + if (!statusCached) + { + try + { + hiddenOSRunning = BootEncryption (MainDlg).IsHiddenSystemRunning(); + } + catch (...) + { + hiddenOSRunning = FALSE; + } + + statusCached = TRUE; + } + + return hiddenOSRunning; +} + + +BOOL EnableWow64FsRedirection (BOOL enable) +{ + typedef BOOLEAN (__stdcall *Wow64EnableWow64FsRedirection_t) (BOOL enable); + Wow64EnableWow64FsRedirection_t wow64EnableWow64FsRedirection = (Wow64EnableWow64FsRedirection_t) GetProcAddress (GetModuleHandle (L"kernel32"), "Wow64EnableWow64FsRedirection"); + + if (!wow64EnableWow64FsRedirection) + return FALSE; + + return wow64EnableWow64FsRedirection (enable); +} + + +BOOL RestartComputer (void) +{ + TOKEN_PRIVILEGES tokenPrivil; + HANDLE hTkn; + + if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hTkn)) + { + return false; + } + + LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, &tokenPrivil.Privileges[0].Luid); + tokenPrivil.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + tokenPrivil.PrivilegeCount = 1; + + AdjustTokenPrivileges (hTkn, false, &tokenPrivil, 0, (PTOKEN_PRIVILEGES) NULL, 0); + if (GetLastError() != ERROR_SUCCESS) + { + CloseHandle(hTkn); + return false; + } + + if (!ExitWindowsEx (EWX_REBOOT, + SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED)) + { + CloseHandle(hTkn); + return false; + } + + CloseHandle(hTkn); + return true; +} + + +std::wstring GetWindowsEdition () +{ + wstring osname = L"win"; + + OSVERSIONINFOEXW osVer; + osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); + GetVersionExW ((LPOSVERSIONINFOW) &osVer); + + BOOL home = (osVer.wSuiteMask & VER_SUITE_PERSONAL); + BOOL server = (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER); + + HKEY hkey; + wchar_t productName[300] = {0}; + DWORD productNameSize = sizeof (productName); + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) + { + if (RegQueryValueEx (hkey, L"ProductName", 0, 0, (LPBYTE) &productName, &productNameSize) != ERROR_SUCCESS || productNameSize < 1) + productName[0] = 0; + + RegCloseKey (hkey); + } + + switch (nCurrentOS) + { + case WIN_2000: + osname += L"2000"; + break; + + case WIN_XP: + case WIN_XP64: + osname += L"xp"; + osname += home ? L"-home" : L"-pro"; + break; + + case WIN_SERVER_2003: + osname += L"2003"; + break; + + case WIN_VISTA: + osname += L"vista"; + break; + + case WIN_SERVER_2008: + osname += L"2008"; + break; + + case WIN_7: + osname += L"7"; + break; + + case WIN_SERVER_2008_R2: + osname += L"2008r2"; + break; + + default: + wstringstream s; + s << CurrentOSMajor << L"." << CurrentOSMinor; + osname += s.str(); + break; + } + + if (server) + osname += L"-server"; + + if (IsOSAtLeast (WIN_VISTA)) + { + if (home) + osname += L"-home"; + else if (wcsstr (productName, L"Standard") != 0) + osname += L"-standard"; + else if (wcsstr (productName, L"Professional") != 0) + osname += L"-pro"; + else if (wcsstr (productName, L"Business") != 0) + osname += L"-business"; + else if (wcsstr (productName, L"Enterprise") != 0) + osname += L"-enterprise"; + else if (wcsstr (productName, L"Datacenter") != 0) + osname += L"-datacenter"; + else if (wcsstr (productName, L"Ultimate") != 0) + osname += L"-ultimate"; + } + + if (GetSystemMetrics (SM_STARTER)) + osname += L"-starter"; + else if (wcsstr (productName, L"Basic") != 0) + osname += L"-basic"; + + if (Is64BitOs()) + osname += L"-x64"; + + if (CurrentOSServicePack > 0) + { + wstringstream s; + s << L"-sp" << CurrentOSServicePack; + osname += s.str(); + } + + return osname; +} + + +void Applink (char *dest, BOOL bSendOS, char *extraOutput) +{ + char url [MAX_URL_LENGTH]; + + ArrowWaitCursor (); + + // sprintf_s (url, sizeof (url), TC_APPLINK "%s%s&dest=%s", bSendOS ? ("&os=" + GetWindowsEdition()).c_str() : "", extraOutput, dest); + if (strcmp(dest, "donate") == 0) + { + StringCbCopyA (url, sizeof (url),"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5BCXVMTTNJDCY"); + } + else if (strcmp(dest, "main") == 0) + { + StringCbCopyA (url, sizeof (url),TC_HOMEPAGE); + } + else if (strcmp(dest,"localizations") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Language%20Packs"); + } + else if (strcmp(dest, "beginnerstutorial") == 0 || strcmp(dest,"tutorial") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Beginner%27s%20Tutorial"); + } + else if (strcmp(dest, "releasenotes") == 0 || strcmp(dest, "history") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Release%20Notes"); + } + else if (strcmp(dest, "hwacceleration") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Hardware%20Acceleration"); + } + else if (strcmp(dest, "parallelization") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Parallelization"); + } + else if (strcmp(dest, "help") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/documentation"); + } + else if (strcmp(dest, "keyfiles") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Keyfiles"); + } + else if (strcmp(dest, "introcontainer") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Creating%20New%20Volumes"); + } + else if (strcmp(dest, "introsysenc") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=System%20Encryption"); + } + else if (strcmp(dest, "hiddensysenc") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=VeraCrypt%20Hidden%20Operating%20System"); + } + else if (strcmp(dest, "sysencprogressinfo") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=System%20Encryption"); + } + else if (strcmp(dest, "hiddenvolume") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Hidden%20Volume"); + } + else if (strcmp(dest, "aes") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=AES"); + } + else if (strcmp(dest, "serpent") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Serpent"); + } + else if (strcmp(dest, "twofish") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Twofish"); + } + else if (strcmp(dest, "cascades") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Cascades"); + } + else if (strcmp(dest, "hashalgorithms") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Hash%20Algorithms"); + } + else if (strcmp(dest, "isoburning") == 0) + { + StringCbCopyA (url, sizeof (url),"https://cdburnerxp.se/en/home"); + } + else if (strcmp(dest, "sysfavorites") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=System%20Favorite%20Volumes"); + } + else if (strcmp(dest, "favorites") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Favorite%20Volumes"); + } + else if (strcmp(dest, "hiddenvolprotection") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Protection%20of%20Hidden%20Volumes"); + } + else if (strcmp(dest, "faq") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=FAQ"); + } + else if (strcmp(dest, "downloads") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Downloads"); + } + else if (strcmp(dest, "news") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=News"); + } + else if (strcmp(dest, "contact") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Contact"); + } + else if (strcmp(dest, "pim") == 0) + { + StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Personal%20Iterations%20Multiplier%20%28PIM%29"); + } + else + { + StringCbCopyA (url, sizeof (url),TC_APPLINK); + } + ShellExecuteA (NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); + + Sleep (200); + NormalCursor (); +} + + +wchar_t *RelativePath2Absolute (wchar_t *szFileName) +{ + if (szFileName[0] != L'\\' + && wcschr (szFileName, L':') == 0 + && 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")) + { + 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; +} + + +BYTE *MapResource (wchar_t *resourceType, int resourceId, PDWORD size) +{ + HGLOBAL hResL; + HRSRC hRes; + + hRes = FindResource (NULL, MAKEINTRESOURCE(resourceId), resourceType); + hResL = LoadResource (NULL, hRes); + + if (size != NULL) + *size = SizeofResource (NULL, hRes); + + return (BYTE *) LockResource (hResL); +} + + +void InconsistencyResolved (char *techInfo) +{ + wchar_t finalMsg[8024]; + + StringCbPrintfW (finalMsg, sizeof(finalMsg), GetString ("INCONSISTENCY_RESOLVED"), techInfo); + MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); +} + + +void ReportUnexpectedState (char *techInfo) +{ + wchar_t finalMsg[8024]; + + StringCbPrintfW (finalMsg, sizeof(finalMsg), GetString ("UNEXPECTED_STATE"), techInfo); + MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); +} + + +#ifndef SETUP + +int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password *password, int pkcs5_prf, int pim, BOOL truecryptMode, BOOL write, BOOL preserveTimestamps, BOOL useBackupHeader) +{ + int status = ERR_PARAMETER_INCORRECT; + int volumeType; + wchar_t szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; + wchar_t szDosDevice[TC_MAX_PATH]; + char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; + LARGE_INTEGER headerOffset; + DWORD dwResult; + DISK_GEOMETRY deviceGeometry; + + context->VolumeIsOpen = FALSE; + context->CryptoInfo = NULL; + context->HostFileHandle = INVALID_HANDLE_VALUE; + context->TimestampsValid = FALSE; + + CreateFullVolumePath (szDiskFile, sizeof(szDiskFile), volumePath, &context->IsDevice); + + if (context->IsDevice) + { + status = FakeDosNameForDevice (szDiskFile, szDosDevice, sizeof(szDosDevice), szCFDevice, sizeof(szCFDevice), FALSE); + if (status != 0) + return status; + + preserveTimestamps = FALSE; + + if (!GetDriveGeometry (volumePath, &deviceGeometry)) + { + status = ERR_OS_ERROR; + goto error; + } + } + else + StringCbCopyW (szCFDevice, sizeof(szCFDevice), szDiskFile); + + if (preserveTimestamps) + write = TRUE; + + context->HostFileHandle = CreateFile (szCFDevice, GENERIC_READ | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (context->HostFileHandle == INVALID_HANDLE_VALUE) + { + status = ERR_OS_ERROR; + goto error; + } + + if (context->IsDevice) + { + // Try to gain "raw" access to the partition in case there is a live filesystem on it (otherwise, + // the NTFS driver guards hidden sectors and prevents e.g. header backup restore after the user + // accidentally quick-formats a dismounted partition-hosted TrueCrypt volume as NTFS, etc.) + + DeviceIoControl (context->HostFileHandle, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwResult, NULL); + } + + context->VolumeIsOpen = TRUE; + + // Remember the container modification/creation date and time + if (!context->IsDevice && preserveTimestamps) + { + if (GetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime) == 0) + context->TimestampsValid = FALSE; + else + context->TimestampsValid = TRUE; + } + + // Determine host size + if (context->IsDevice) + { + PARTITION_INFORMATION diskInfo; + + if (GetPartitionInfo (volumePath, &diskInfo)) + { + context->HostSize = diskInfo.PartitionLength.QuadPart; + } + else + { + DISK_GEOMETRY driveInfo; + + if (!DeviceIoControl (context->HostFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL)) + { + status = ERR_OS_ERROR; + goto error; + } + + context->HostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; + } + + if (context->HostSize == 0) + { + status = ERR_VOL_SIZE_WRONG; + goto error; + } + } + else + { + LARGE_INTEGER fileSize; + if (!GetFileSizeEx (context->HostFileHandle, &fileSize)) + { + status = ERR_OS_ERROR; + goto error; + } + + 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)) + { + 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, truecryptMode, &context->CryptoInfo, NULL); + + if (status == ERR_PASSWORD_WRONG) + continue; // Try next volume type + + break; + } + + if (status == ERR_SUCCESS) + return status; + +error: + DWORD sysError = GetLastError (); + + CloseVolume (context); + + SetLastError (sysError); + return status; +} + + +void CloseVolume (OpenVolumeContext *context) +{ + if (!context->VolumeIsOpen) + return; + + if (context->HostFileHandle != INVALID_HANDLE_VALUE) + { + if (context->TimestampsValid) + SetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime); + + CloseHandle (context->HostFileHandle); + context->HostFileHandle = INVALID_HANDLE_VALUE; + } + + if (context->CryptoInfo) + { + crypto_close (context->CryptoInfo); + context->CryptoInfo = NULL; + } + + context->VolumeIsOpen = FALSE; +} + + +int ReEncryptVolumeHeader (HWND hwndDlg, char *buffer, BOOL bBoot, CRYPTO_INFO *cryptoInfo, Password *password, int pim, BOOL wipeMode) +{ + CRYPTO_INFO *newCryptoInfo = NULL; + + RandSetHashFunction (cryptoInfo->pkcs5); + + if (Randinit() != ERR_SUCCESS) + { + if (CryptoAPILastError == ERROR_SUCCESS) + return ERR_RAND_INIT_FAILED; + else + return ERR_CAPI_INIT_FAILED; + } + + UserEnrichRandomPool (NULL); + + int status = CreateVolumeHeaderInMemory (hwndDlg, bBoot, + buffer, + cryptoInfo->ea, + cryptoInfo->mode, + password, + cryptoInfo->pkcs5, + pim, + (char *) cryptoInfo->master_keydata, + &newCryptoInfo, + cryptoInfo->VolumeSize.Value, + cryptoInfo->hiddenVolume ? cryptoInfo->hiddenVolumeSize : 0, + cryptoInfo->EncryptedAreaStart.Value, + cryptoInfo->EncryptedAreaLength.Value, + cryptoInfo->RequiredProgramVersion, + cryptoInfo->HeaderFlags, + cryptoInfo->SectorSize, + wipeMode); + + if (newCryptoInfo != NULL) + crypto_close (newCryptoInfo); + + return status; +} + +#endif // !SETUP + + +BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) +{ + // GlobalMemoryStatusEx() cannot be used to determine if a paging file is active + + wchar_t data[65536]; + DWORD size = sizeof (data); + + if (IsPagingFileWildcardActive()) + return TRUE; + + if (ReadLocalMachineRegistryMultiString (L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", L"PagingFiles", data, &size) + && size > 24 && !checkNonWindowsPartitionsOnly) + return TRUE; + + if (!IsAdmin()) + AbortProcess ("UAC_INIT_ERROR"); + + for (wchar_t drive = L'C'; drive <= L'Z'; ++drive) + { + // Query geometry of the drive first to prevent "no medium" pop-ups + wstring drivePath = L"\\\\.\\X:"; + drivePath[4] = drive; + + if (checkNonWindowsPartitionsOnly) + { + wchar_t sysDir[MAX_PATH]; + if (GetSystemDirectory (sysDir, ARRAYSIZE (sysDir)) != 0 && towupper (sysDir[0]) == drive) + continue; + } + + HANDLE handle = CreateFile (drivePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (handle == INVALID_HANDLE_VALUE) + continue; + + DISK_GEOMETRY driveInfo; + DWORD dwResult; + + if (!DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL)) + { + CloseHandle (handle); + continue; + } + + CloseHandle (handle); + + // Test if a paging file exists and is locked by another process + wstring path = L"X:\\pagefile.sys"; + path[0] = drive; + + handle = CreateFile (path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + + if (handle != INVALID_HANDLE_VALUE) + CloseHandle (handle); + else if (GetLastError() == ERROR_SHARING_VIOLATION) + return TRUE; + } + + return FALSE; +} + + +BOOL IsPagingFileWildcardActive () +{ + wchar_t pagingFiles[65536]; + DWORD size = sizeof (pagingFiles); + wchar_t *mmKey = L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management"; + + if (!ReadLocalMachineRegistryString (mmKey, L"PagingFiles", pagingFiles, &size)) + { + size = sizeof (pagingFiles); + if (!ReadLocalMachineRegistryMultiString (mmKey, L"PagingFiles", pagingFiles, &size)) + size = 0; + } + + return size > 0 && wcsstr (pagingFiles, L"?:\\") == pagingFiles; +} + + +BOOL DisablePagingFile () +{ + wchar_t empty[] = { 0, 0 }; + return WriteLocalMachineRegistryMultiString (L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", L"PagingFiles", empty, sizeof (empty)); +} + + +std::wstring SingleStringToWide (const std::string &singleString) +{ + if (singleString.empty()) + return std::wstring(); + + WCHAR wbuf[65536]; + int wideLen = MultiByteToWideChar (CP_ACP, 0, singleString.c_str(), -1, wbuf, array_capacity (wbuf) - 1); + + // We don't throw exception here and only return empty string. + // All calls to this function use valid strings. + // throw_sys_if (wideLen == 0); + + wbuf[wideLen] = 0; + return wbuf; +} + + +std::wstring Utf8StringToWide (const std::string &utf8String) +{ + if (utf8String.empty()) + return std::wstring(); + + WCHAR wbuf[65536]; + int wideLen = MultiByteToWideChar (CP_UTF8, 0, utf8String.c_str(), -1, wbuf, array_capacity (wbuf) - 1); + throw_sys_if (wideLen == 0); + + wbuf[wideLen] = 0; + return wbuf; +} + + +std::string WideToUtf8String (const std::wstring &wideString) +{ + if (wideString.empty()) + return std::string(); + + char buf[65536]; + int len = WideCharToMultiByte (CP_UTF8, 0, wideString.c_str(), -1, buf, array_capacity (buf) - 1, NULL, NULL); + throw_sys_if (len == 0); + + buf[len] = 0; + return buf; +} + + +#ifndef SETUP + +BOOL CALLBACK SecurityTokenPasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WORD lw = LOWORD (wParam); + static string *password; + + switch (msg) + { + case WM_INITDIALOG: + { + password = (string *) lParam; + LocalizeDialog (hwndDlg, "IDD_TOKEN_PASSWORD"); + + wchar_t s[1024]; + StringCbPrintfW (s, sizeof(s), GetString ("ENTER_TOKEN_PASSWORD"), Utf8StringToWide (password->c_str()).c_str()); + SetWindowTextW (GetDlgItem (hwndDlg, IDT_TOKEN_PASSWORD_INFO), s); + + SendMessage (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), EM_LIMITTEXT, SecurityToken::MaxPasswordLength, 0); + + SetForegroundWindow (hwndDlg); + SetFocus (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD)); + } + return 0; + + case WM_COMMAND: + if (lw == IDCANCEL || lw == IDOK) + { + if (lw == IDOK) + { + wchar_t passwordWide[SecurityToken::MaxPasswordLength + 1]; + + if (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), passwordWide, SecurityToken::MaxPasswordLength + 1) == 0) + { + handleWin32Error (hwndDlg, SRC_POS); + break; + } + + char passwordUtf8[SecurityToken::MaxPasswordLength + 1]; + + int len = WideCharToMultiByte (CP_UTF8, 0, passwordWide, -1, passwordUtf8, array_capacity (passwordUtf8) - 1, nullptr, nullptr); + passwordUtf8[len] = 0; + *password = passwordUtf8; + + burn (passwordWide, sizeof (passwordWide)); + burn (passwordUtf8, sizeof (passwordUtf8)); + } + + // Attempt to wipe password stored in the input field buffer + wchar_t tmp[SecurityToken::MaxPasswordLength+1]; + wmemset (tmp, 'X', SecurityToken::MaxPasswordLength); + tmp[SecurityToken::MaxPasswordLength] = 0; + SetWindowText (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), tmp); + + EndDialog (hwndDlg, lw); + } + return 1; + } + + return 0; +} + + +struct NewSecurityTokenKeyfileDlgProcParams +{ + CK_SLOT_ID SlotId; + string Name; +}; + +static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static NewSecurityTokenKeyfileDlgProcParams *newParams; + + WORD lw = LOWORD (wParam); + switch (msg) + { + case WM_INITDIALOG: + { + LocalizeDialog (hwndDlg, "IDD_NEW_TOKEN_KEYFILE"); + + newParams = (NewSecurityTokenKeyfileDlgProcParams *) lParam; + + WaitCursor(); + finally_do ({ NormalCursor(); }); + + list tokens; + + try + { + tokens = SecurityToken::GetAvailableTokens(); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + if (tokens.empty()) + { + Error ("NO_TOKENS_FOUND", hwndDlg); + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + foreach (const SecurityTokenInfo &token, tokens) + { + wstringstream tokenLabel; + tokenLabel << L"[" << token.SlotId << L"] " << token.Label; + + AddComboPair (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), tokenLabel.str().c_str(), token.SlotId); + } + + ComboBox_SetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), 0); + + SetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), Utf8StringToWide (newParams->Name).c_str()); + return 1; + } + + case WM_COMMAND: + switch (lw) + { + case IDOK: + { + int selectedToken = ComboBox_GetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN)); + if (selectedToken == CB_ERR) + { + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + newParams->SlotId = (CK_SLOT_ID) ComboBox_GetItemData (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), selectedToken); + + wchar_t name[1024]; + if (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), name, array_capacity (name)) != 0) + { + try + { + newParams->Name = WideToUtf8String (name); + } + catch (...) { } + } + + EndDialog (hwndDlg, IDOK); + return 1; + } + + case IDCANCEL: + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + + if (HIWORD (wParam) == EN_CHANGE) + { + wchar_t name[2]; + EnableWindow (GetDlgItem (hwndDlg, IDOK), (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), name, array_capacity (name)) != 0)); + return 1; + } + } + + return 0; +} + + +static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector &keyfiles) +{ + HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); + LVITEMW lvItem; + int line = 0; + + ListView_DeleteAllItems (tokenListControl); + + foreach (const SecurityTokenKeyfile &keyfile, keyfiles) + { + memset (&lvItem, 0, sizeof(lvItem)); + lvItem.mask = LVIF_TEXT; + lvItem.iItem = line++; + + wstringstream s; + s << keyfile.SlotId; + + ListItemAdd (tokenListControl, lvItem.iItem, (wchar_t *) s.str().c_str()); + ListSubItemSet (tokenListControl, lvItem.iItem, 1, (wchar_t *) keyfile.Token.Label.c_str()); + ListSubItemSet (tokenListControl, lvItem.iItem, 2, (wchar_t *) keyfile.Id.c_str()); + } + + BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); + EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); + EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); +} + + +static list SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector &keyfiles) +{ + HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); + list selectedKeyfiles; + + int itemId = -1; + while ((itemId = ListView_GetNextItem (tokenListControl, itemId, LVIS_SELECTED)) != -1) + { + selectedKeyfiles.push_back (keyfiles[itemId]); + } + + return selectedKeyfiles; +} + + +BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static list *selectedTokenKeyfiles; + static vector keyfiles; + + WORD lw = LOWORD (wParam); + + switch (msg) + { + case WM_INITDIALOG: + { + selectedTokenKeyfiles = (list *) lParam; + + LVCOLUMNW LvCol; + HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); + + LocalizeDialog (hwndDlg, selectedTokenKeyfiles ? "SELECT_TOKEN_KEYFILES" : "IDD_TOKEN_KEYFILES"); + + SendMessage (tokenListControl,LVM_SETEXTENDEDLISTVIEWSTYLE, 0, + LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP + ); + + memset (&LvCol, 0, sizeof(LvCol)); + LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; + LvCol.pszText = GetString ("TOKEN_SLOT_ID"); + LvCol.cx = CompensateXDPI (40); + LvCol.fmt = LVCFMT_CENTER; + SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 1, (LPARAM)&LvCol); + + LvCol.pszText = GetString ("TOKEN_NAME"); + LvCol.cx = CompensateXDPI (128); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 2, (LPARAM)&LvCol); + + LvCol.pszText = GetString ("TOKEN_DATA_OBJECT_LABEL"); + LvCol.cx = CompensateXDPI (195); + LvCol.fmt = LVCFMT_LEFT; + SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 3, (LPARAM)&LvCol); + + keyfiles.clear(); + + try + { + WaitCursor(); + finally_do ({ NormalCursor(); }); + + keyfiles = SecurityToken::GetAvailableKeyfiles(); + } + catch (UserAbort&) + { + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + catch (Exception &e) + { + e.Show (hwndDlg); + + if (keyfiles.empty()) + { + EndDialog (hwndDlg, IDCANCEL); + return 1; + } + } + + SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); + return 1; + } + + case WM_COMMAND: + case WM_NOTIFY: + if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE) + { + if (selectedTokenKeyfiles) + { + foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) + { + selectedTokenKeyfiles->push_back (SecurityTokenKeyfilePath (keyfile)); + } + } + + EndDialog (hwndDlg, IDOK); + return 1; + } + + if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) + { + BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); + EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); + EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); + 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)) + { + DWORD keyfileSize; + byte *keyfileData = (byte *) 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 keyfileDataVector (keyfileSize); + memcpy (&keyfileDataVector.front(), keyfileData, keyfileSize); + + try + { + WaitCursor(); + finally_do ({ NormalCursor(); }); + + SecurityToken::CreateKeyfile (newParams.SlotId, keyfileDataVector, newParams.Name); + + keyfiles = SecurityToken::GetAvailableKeyfiles(); + 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 SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) + { + wchar_t keyfilePath[TC_MAX_PATH]; + + if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE, NULL)) + break; + + { + WaitCursor(); + finally_do ({ NormalCursor(); }); + + vector keyfileData; + + SecurityToken::GetKeyfileData (keyfile, keyfileData); + + if (keyfileData.empty()) + { + SetLastError (ERROR_HANDLE_EOF); + handleWin32Error (hwndDlg, SRC_POS); + return 1; + } + + finally_do_arg (vector *, &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 SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) + { + SecurityToken::DeleteKeyfile (keyfile); + } + + keyfiles = SecurityToken::GetAvailableKeyfiles(); + SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); + } + catch (Exception &e) + { + e.Show (hwndDlg); + } + + return 1; + } + } + } + return 0; + } + return 0; +} + + +BOOL InitSecurityTokenLibrary (HWND hwndDlg) +{ + if (SecurityTokenLibraryPath[0] == 0) + { + Error ("NO_PKCS11_MODULE_SPECIFIED", hwndDlg); + return FALSE; + } + + struct PinRequestHandler : public GetPinFunctor + { + HWND m_hwnd; + PinRequestHandler(HWND hwnd) : m_hwnd(hwnd) {} + virtual void operator() (string &str) + { + HWND hParent = IsWindow (m_hwnd)? m_hwnd : GetActiveWindow(); + if (!hParent) + hParent = GetForegroundWindow (); + if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_PASSWORD), hParent, (DLGPROC) SecurityTokenPasswordDlgProc, (LPARAM) &str) == IDCANCEL) + throw UserAbort (SRC_POS); + + if (hCursor != NULL) + SetCursor (hCursor); + } + }; + + struct WarningHandler : public SendExceptionFunctor + { + HWND m_hwnd; + WarningHandler(HWND hwnd) : m_hwnd(hwnd) {} + virtual void operator() (const Exception &e) + { + HWND hParent = IsWindow (m_hwnd)? m_hwnd : GetActiveWindow(); + if (!hParent) + hParent = GetForegroundWindow (); + e.Show (hParent); + } + }; + + try + { + SecurityToken::InitLibrary (SecurityTokenLibraryPath, auto_ptr (new PinRequestHandler(MainDlg)), auto_ptr (new WarningHandler(MainDlg))); + } + catch (Exception &e) + { + e.Show (hwndDlg); + Error ("PKCS11_MODULE_INIT_FAILED", hwndDlg); + return FALSE; + } + + return TRUE; +} + +#endif // !SETUP + +std::vector GetAvailableHostDevices (bool noDeviceProperties, bool singleList, bool noFloppy, bool detectUnencryptedFilesystems) +{ + vector devices; + size_t dev0; + + for (int devNumber = 0; devNumber < MAX_HOST_DRIVE_NUMBER; devNumber++) + { + for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++) + { + wstringstream strm; + strm << L"\\Device\\Harddisk" << devNumber << L"\\Partition" << partNumber; + wstring devPathStr (strm.str()); + const wchar_t *devPath = devPathStr.c_str(); + + OPEN_TEST_STRUCT openTest = {0}; + if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems && partNumber != 0, FALSE, NULL)) + { + if (partNumber == 0) + break; + + continue; + } + + HostDevice device; + device.SystemNumber = devNumber; + device.Path = devPath; + + PARTITION_INFORMATION partInfo; + + if (GetPartitionInfo (devPath, &partInfo)) + { + device.Bootable = partInfo.BootIndicator ? true : false; + device.Size = partInfo.PartitionLength.QuadPart; + } + else + { + // retrieve size using DISK_GEOMETRY + DISK_GEOMETRY deviceGeometry = {0}; + if ( GetDriveGeometry (devPath, &deviceGeometry) + || ((partNumber == 0) && GetPhysicalDriveGeometry (devNumber, &deviceGeometry)) + ) + { + device.Size = deviceGeometry.Cylinders.QuadPart * (LONGLONG) deviceGeometry.BytesPerSector + * (LONGLONG) deviceGeometry.SectorsPerTrack * (LONGLONG) deviceGeometry.TracksPerCylinder; + } + } + + device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false; + + if (!noDeviceProperties) + { + DISK_GEOMETRY geometry; + + int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) devPathStr.c_str()); + + if (driveNumber >= 0) + { + device.MountPoint += (wchar_t) (driveNumber + L'A'); + device.MountPoint += L":"; + + wchar_t name[64]; + if (GetDriveLabel (driveNumber, name, sizeof (name))) + device.Name = name; + + if (GetSystemDriveLetter() == L'A' + driveNumber) + device.ContainsSystem = true; + } + + if (partNumber == 0 && GetDriveGeometry (devPath, &geometry)) + device.Removable = (geometry.MediaType == RemovableMedia); + } + + if (partNumber == 0) + { + devices.push_back (device); + dev0 = devices.size() - 1; + } + else + { + // System creates a virtual partition1 for some storage devices without + // partition table. We try to detect this case by comparing sizes of + // partition0 and partition1. If they match, no partition of the device + // is displayed to the user to avoid confusion. Drive letter assigned by + // system to partition1 is assigned partition0 + if (partNumber == 1 && devices[dev0].Size == device.Size) + { + devices[dev0].IsVirtualPartition = true; + devices[dev0].MountPoint = device.MountPoint; + devices[dev0].Name = device.Name; + devices[dev0].Path = device.Path; + devices[dev0].HasUnencryptedFilesystem = device.HasUnencryptedFilesystem; + break; + } + + device.IsPartition = true; + device.SystemNumber = partNumber; + device.Removable = devices[dev0].Removable; + + if (device.ContainsSystem) + devices[dev0].ContainsSystem = true; + + if (singleList) + devices.push_back (device); + + devices[dev0].Partitions.push_back (device); + } + } + } + + // Vista does not create partition links for dynamic volumes so it is necessary to scan \\Device\\HarddiskVolumeX devices + if (CurrentOSMajor >= 6) + { + for (int devNumber = 0; devNumber < 256; devNumber++) + { + wstringstream strm; + strm << L"\\Device\\HarddiskVolume" << devNumber; + wstring devPathStr (strm.str()); + const wchar_t *devPath = devPathStr.c_str(); + + OPEN_TEST_STRUCT openTest = {0}; + if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems, FALSE, NULL)) + continue; + + DISK_PARTITION_INFO_STRUCT info; + if (GetDeviceInfo (devPath, &info) && info.IsDynamic) + { + HostDevice device; + device.DynamicVolume = true; + device.IsPartition = true; + device.SystemNumber = devNumber; + device.Path = devPath; + device.Size = info.partInfo.PartitionLength.QuadPart; + device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false; + + if (!noDeviceProperties) + { + int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) devPathStr.c_str()); + + if (driveNumber >= 0) + { + device.MountPoint += (wchar_t) (driveNumber + L'A'); + device.MountPoint += L":"; + + wchar_t name[64]; + if (GetDriveLabel (driveNumber, name, sizeof (name))) + device.Name = name; + + if (GetSystemDriveLetter() == L'A' + driveNumber) + device.ContainsSystem = true; + } + } + + devices.push_back (device); + } + } + } + + return devices; +} + +wstring FindDeviceByVolumeID (const BYTE volumeID [VOLUME_ID_SIZE]) +{ + /* if it is already mounted, get the real path name used for mounting */ + MOUNT_LIST_STRUCT mlist; + DWORD dwResult; + + memset (&mlist, 0, sizeof (mlist)); + DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, + sizeof (mlist), &mlist, sizeof (mlist), &dwResult, + NULL); + + for (int i=0 ; i < 26; i++) + { + if (0 == memcmp (mlist.volumeID[i], volumeID, VOLUME_ID_SIZE)) + return mlist.wszVolume[i]; + } + + /* not mounted. Look for it in the local drives*/ + for (int devNumber = 0; devNumber < MAX_HOST_DRIVE_NUMBER; devNumber++) + { + for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++) + { + wstringstream strm; + strm << L"\\Device\\Harddisk" << devNumber << L"\\Partition" << partNumber; + wstring devPathStr (strm.str()); + const wchar_t *devPath = devPathStr.c_str(); + + OPEN_TEST_STRUCT openTest = {0}; + if (!OpenDevice (devPath, &openTest, FALSE, TRUE, volumeID)) + { + continue; + } + + if (openTest.VolumeIDMatched) + return devPath; + } + } + + return L""; +} + +BOOL FileHasReadOnlyAttribute (const wchar_t *path) +{ + DWORD attributes = GetFileAttributes (path); + return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_READONLY) != 0; +} + + +BOOL IsFileOnReadOnlyFilesystem (const wchar_t *path) +{ + wchar_t root[MAX_PATH]; + if (!GetVolumePathName (path, root, ARRAYSIZE (root))) + return FALSE; + + 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 BufferContainsString (const byte *buffer, size_t bufferSize, const char *str) +{ + size_t strLen = strlen (str); + + if (bufferSize < strLen) + return FALSE; + + bufferSize -= strLen; + + for (size_t i = 0; i < bufferSize; ++i) + { + if (memcmp (buffer + i, str, strLen) == 0) + return TRUE; + } + + return FALSE; +} + + +#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 }; + + switch (AskMultiChoice ((void **) multiChoiceStr, FALSE, hwndDlg)) + { + case 1: + RemoveNonSysInPlaceEncNotifications(); + Warning ("NONSYS_INPLACE_ENC_NOTIFICATION_REMOVAL_NOTE", hwndDlg); + break; + + default: + // NOP + break; + } + + return IDNO; +} + +#endif // !SETUP + + +BOOL RemoveDeviceWriteProtection (HWND hwndDlg, wchar_t *devicePath) +{ + int driveNumber; + int partitionNumber; + + wchar_t temp[MAX_PATH*2]; + wchar_t cmdBatch[MAX_PATH*2]; + wchar_t diskpartScript[MAX_PATH*2]; + + if (swscanf (devicePath, L"\\Device\\Harddisk%d\\Partition%d", &driveNumber, &partitionNumber) != 2) + return FALSE; + + if (GetTempPath (ARRAYSIZE (temp), temp) == 0) + return FALSE; + + StringCbPrintfW (cmdBatch, sizeof (cmdBatch), L"%s\\VeraCrypt_Write_Protection_Removal.cmd", temp); + StringCbPrintfW (diskpartScript, sizeof (diskpartScript), L"%s\\VeraCrypt_Write_Protection_Removal.diskpart", temp); + + FILE *f = _wfopen (cmdBatch, L"w"); + if (!f) + { + handleWin32Error (hwndDlg, SRC_POS); + return FALSE; + } + + fwprintf (f, L"@diskpart /s \"%s\"\n@pause\n@del \"%s\" \"%s\"", diskpartScript, diskpartScript, cmdBatch); + + CheckFileStreamWriteErrors (hwndDlg, f, cmdBatch); + fclose (f); + + f = _wfopen (diskpartScript, L"w"); + if (!f) + { + handleWin32Error (hwndDlg, SRC_POS); + DeleteFile (cmdBatch); + return FALSE; + } + + fwprintf (f, L"select disk %d\nattributes disk clear readonly\n", driveNumber); + + if (partitionNumber != 0) + fwprintf (f, L"select partition %d\nattributes volume clear readonly\n", partitionNumber); + + fwprintf (f, L"exit\n"); + + CheckFileStreamWriteErrors (hwndDlg, f, diskpartScript); + fclose (f); + + ShellExecute (NULL, (!IsAdmin() && IsUacSupported()) ? L"runas" : L"open", cmdBatch, NULL, NULL, SW_SHOW); + + return TRUE; +} + + +static LRESULT CALLBACK EnableElevatedCursorChangeWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProcW (hWnd, message, wParam, lParam); +} + + +void EnableElevatedCursorChange (HWND parent) +{ + // Create a transparent window to work around a UAC issue preventing change of the cursor + if (UacElevated) + { + const wchar_t *className = L"VeraCryptEnableElevatedCursorChange"; + WNDCLASSEXW winClass; + HWND hWnd; + + memset (&winClass, 0, sizeof (winClass)); + winClass.cbSize = sizeof (WNDCLASSEX); + winClass.lpfnWndProc = (WNDPROC) EnableElevatedCursorChangeWndProc; + winClass.hInstance = hInst; + winClass.lpszClassName = className; + RegisterClassExW (&winClass); + + hWnd = CreateWindowExW (WS_EX_TOOLWINDOW | WS_EX_LAYERED, className, L"VeraCrypt UAC", 0, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), parent, NULL, hInst, NULL); + if (hWnd) + { + SetLayeredWindowAttributes (hWnd, 0, 1, LWA_ALPHA); + ShowWindow (hWnd, SW_SHOWNORMAL); + + DestroyWindow (hWnd); + } + UnregisterClassW (className, hInst); + } +} + + +BOOL DisableFileCompression (HANDLE file) +{ + USHORT format; + DWORD bytesOut; + + if (!DeviceIoControl (file, FSCTL_GET_COMPRESSION, NULL, 0, &format, sizeof (format), &bytesOut, NULL)) + return FALSE; + + if (format == COMPRESSION_FORMAT_NONE) + return TRUE; + + format = COMPRESSION_FORMAT_NONE; + return DeviceIoControl (file, FSCTL_SET_COMPRESSION, &format, sizeof (format), NULL, 0, &bytesOut, NULL); +} + + +BOOL VolumePathExists (const wchar_t *volumePath) +{ + OPEN_TEST_STRUCT openTest = {0}; + wchar_t upperCasePath[TC_MAX_PATH + 1]; + + UpperCaseCopy (upperCasePath, sizeof(upperCasePath), volumePath); + + if (wcsstr (upperCasePath, L"\\DEVICE\\") == upperCasePath) + return OpenDevice (volumePath, &openTest, FALSE, FALSE, NULL); + + 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; + } + + return TRUE; +} + + +std::wstring VolumeGuidPathToDevicePath (std::wstring volumeGuidPath) +{ + if (volumeGuidPath.find (L"\\\\?\\") == 0) + volumeGuidPath = volumeGuidPath.substr (4); + + if (volumeGuidPath.find (L"Volume{") != 0 || volumeGuidPath.rfind (L"}\\") != volumeGuidPath.size() - 2) + return wstring(); + + wchar_t volDevPath[TC_MAX_PATH]; + if (QueryDosDevice (volumeGuidPath.substr (0, volumeGuidPath.size() - 1).c_str(), volDevPath, TC_MAX_PATH) == 0) + return wstring(); + + wstring partitionPath = HarddiskVolumePathToPartitionPath (volDevPath); + + return partitionPath.empty() ? volDevPath : partitionPath; +} + + +std::wstring HarddiskVolumePathToPartitionPath (const std::wstring &harddiskVolumePath) +{ + for (int driveNumber = 0; driveNumber < MAX_HOST_DRIVE_NUMBER; driveNumber++) + { + for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++) + { + wchar_t partitionPath[TC_MAX_PATH]; + StringCchPrintfW (partitionPath, ARRAYSIZE (partitionPath), L"\\Device\\Harddisk%d\\Partition%d", driveNumber, partNumber); + + wchar_t resolvedPath[TC_MAX_PATH]; + if (ResolveSymbolicLink (partitionPath, resolvedPath, sizeof(resolvedPath))) + { + if (harddiskVolumePath == resolvedPath) + return partitionPath; + } + else if (partNumber == 0) + break; + } + } + + return wstring(); +} + + +BOOL IsApplicationInstalled (const wchar_t *appName, BOOL b32bitApp) +{ + const wchar_t *uninstallRegName = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; + BOOL installed = FALSE; + HKEY unistallKey; + LONG res = RegOpenKeyEx (HKEY_LOCAL_MACHINE, uninstallRegName, 0, KEY_READ | (b32bitApp? KEY_WOW64_32KEY: KEY_WOW64_64KEY), &unistallKey); + if (res != ERROR_SUCCESS) + { + SetLastError (res); + return FALSE; + } + + wchar_t regName[1024]; + DWORD regNameSize = sizeof (regName); + DWORD index = 0; + while (RegEnumKeyEx (unistallKey, index++, regName, ®NameSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) + { + if (wcsstr (regName, L"{") == regName) + { + regNameSize = sizeof (regName); + if (!ReadLocalMachineRegistryStringNonReflected ((wstring (uninstallRegName) + L"\\" + regName).c_str(), L"DisplayName", regName, ®NameSize, b32bitApp)) + regName[0] = 0; + } + + if (_wcsicmp (regName, appName) == 0) + { + installed = TRUE; + break; + } + + regNameSize = sizeof (regName); + } + + RegCloseKey (unistallKey); + return installed; +} + + +std::wstring FindLatestFileOrDirectory (const std::wstring &directory, const wchar_t *namePattern, bool findDirectory, bool findFile) +{ + wstring name; + ULARGE_INTEGER latestTime; + latestTime.QuadPart = 0; + WIN32_FIND_DATA findData; + + HANDLE find = FindFirstFile ((directory + L"\\" + namePattern).c_str(), &findData); + if (find != INVALID_HANDLE_VALUE) + { + do + { + if (wcscmp (findData.cFileName, L".") == 0 || wcscmp (findData.cFileName, L"..") == 0) + continue; + + ULARGE_INTEGER writeTime; + writeTime.LowPart = findData.ftLastWriteTime.dwLowDateTime; + writeTime.HighPart = findData.ftLastWriteTime.dwHighDateTime; + + if ((!findFile && !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + || (!findDirectory && (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))) + continue; + + if (latestTime.QuadPart < writeTime.QuadPart) + { + latestTime = writeTime; + name = findData.cFileName; + } + } + while (FindNextFile (find, &findData)); + + FindClose (find); + } + + if (name.empty()) + return name; + + return wstring (directory) + L"\\" + name; +} + +int GetPim (HWND hwndDlg, UINT ctrlId) +{ + int pim = 0; + HWND hCtrl = GetDlgItem (hwndDlg, ctrlId); + if (IsWindowEnabled (hCtrl) && IsWindowVisible (hCtrl)) + { + wchar_t szTmp[MAX_PIM + 1] = {0}; + if (GetDlgItemText (hwndDlg, ctrlId, szTmp, MAX_PIM + 1) > 0) + { + wchar_t* endPtr = NULL; + pim = wcstol(szTmp, &endPtr, 10); + if (pim < 0 || endPtr == szTmp || !endPtr || *endPtr != L'\0') + pim = 0; + } + } + return pim; +} + +void SetPim (HWND hwndDlg, UINT ctrlId, int pim) +{ + if (pim > 0) + { + wchar_t szTmp[MAX_PIM + 1]; + StringCbPrintfW (szTmp, sizeof(szTmp), L"%d", pim); + SetDlgItemText (hwndDlg, ctrlId, szTmp); + } + else + SetDlgItemText (hwndDlg, ctrlId, L""); +} + +BOOL GetPassword (HWND hwndDlg, UINT ctrlID, char* passValue, int bufSize, BOOL bShowError) +{ + wchar_t tmp [MAX_PASSWORD + 1]; + int utf8Len; + BOOL bRet = FALSE; + + GetWindowText (GetDlgItem (hwndDlg, ctrlID), tmp, ARRAYSIZE (tmp)); + utf8Len = WideCharToMultiByte (CP_UTF8, 0, tmp, -1, passValue, bufSize, NULL, NULL); + burn (tmp, sizeof (tmp)); + if (utf8Len > 0) + { + bRet = TRUE; + } + else + { + passValue [0] = 0; + if (bShowError) + { + SetFocus (GetDlgItem(hwndDlg, ctrlID)); + if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) + Error ("PASSWORD_UTF8_TOO_LONG", hwndDlg); + else + Error ("PASSWORD_UTF8_INVALID", hwndDlg); + } + } + + return bRet; +} + +void SetPassword (HWND hwndDlg, UINT ctrlID, char* passValue) +{ + wchar_t tmp [MAX_PASSWORD + 1] = {0}; + MultiByteToWideChar (CP_UTF8, 0, passValue, -1, tmp, MAX_PASSWORD + 1); + SetWindowText ( GetDlgItem (hwndDlg, ctrlID), tmp); + burn (tmp, sizeof (tmp)); +} + +void HandleShowPasswordFieldAction (HWND hwndDlg, UINT checkBoxId, UINT edit1Id, UINT edit2Id) +{ + if ((EditPasswordChar == 0) && GetCheckBox (hwndDlg, checkBoxId)) + { + EditPasswordChar = (WCHAR) SendMessageW (GetDlgItem (hwndDlg, edit1Id), EM_GETPASSWORDCHAR, 0, 0); + } + + 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.Close(); + + HINF hInf = SetupOpenInfFileWFn (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); }); + + throw_sys_if (!SetupInstallFromInfSectionWFn (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); +} + +LSTATUS DeleteRegistryKey (HKEY hKey, LPCTSTR keyName) +{ + return SHDeleteKeyWFn(hKey, keyName); +} + +HIMAGELIST CreateImageList(int cx, int cy, UINT flags, int cInitial, int cGrow) +{ + return ImageList_CreateFn(cx, cy, flags, cInitial, cGrow); +} + +int AddBitmapToImageList(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask) +{ + return ImageList_AddFn(himl, hbmImage, hbmMask); +} + +HRESULT VCStrDupW(LPCWSTR psz, LPWSTR *ppwsz) +{ + return SHStrDupWFn (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; + + SendMessage (hProgress, PBM_SETSTATE, state, 0); + } + + SendMessage (hProgress, PBM_SETPOS, + (WPARAM) (*pdwEntropy), + 0); + } +} + +void AllowMessageInUIPI (UINT msg) +{ + if (ChangeWindowMessageFilterFn) + { + ChangeWindowMessageFilterFn (msg, MSGFLT_ADD); + } +} + +BOOL IsRepeatedByteArray (byte value, const byte* 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; +} + +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 arr; + if ( (pathLen == (3 + 2*VOLUME_ID_SIZE)) + && HexWideStringToArray (pathValue + 3, arr) + && (arr.size() == VOLUME_ID_SIZE) + ) + { + std::wstring devicePath = FindDeviceByVolumeID (&arr[0]); + 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; +} + +BOOL CopyTextToClipboard (LPCWSTR txtValue) +{ + size_t txtLen = wcslen(txtValue); + HGLOBAL hdst; + LPWSTR dst; + BOOL bRet = FALSE; + + // Allocate string for cwd + hdst = GlobalAlloc(GMEM_MOVEABLE, (txtLen + 1) * sizeof(WCHAR)); + if (hdst) + { + dst = (LPWSTR)GlobalLock(hdst); + wmemcpy(dst, txtValue, txtLen + 1); + GlobalUnlock(hdst); + + if (OpenClipboard(NULL)) + { + EmptyClipboard(); + SetClipboardData(CF_UNICODETEXT, hdst); + CloseClipboard(); + } + } + + return bRet; +} -- cgit v1.2.3