VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/Dlgcode.c
diff options
context:
space:
mode:
authorDavid Foerster <david.foerster@informatik.hu-berlin.de>2016-05-10 20:20:14 +0200
committerDavid Foerster <david.foerster@informatik.hu-berlin.de>2016-05-10 20:20:14 +0200
commitfc37cc4a02ed13d1a73b941a9f80975600fd1b99 (patch)
treead9e5ac81111402b5c47dc06944cc5243824c4b5 /src/Common/Dlgcode.c
parent98b04198c6ea5bc07cca50956809068adf1fea82 (diff)
downloadVeraCrypt-fc37cc4a02ed13d1a73b941a9f80975600fd1b99.tar.gz
VeraCrypt-fc37cc4a02ed13d1a73b941a9f80975600fd1b99.zip
Normalize all line terminators
Diffstat (limited to 'src/Common/Dlgcode.c')
-rw-r--r--src/Common/Dlgcode.c23780
1 files changed, 11890 insertions, 11890 deletions
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 <windowsx.h>
-#include <dbghelp.h>
-#include <dbt.h>
-#include <Setupapi.h>
-#include <fcntl.h>
-#include <io.h>
-#include <math.h>
-#include <shlobj.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <time.h>
-#include <tchar.h>
-#include <Richedit.h>
-
-#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 <strsafe.h>
-
-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 <DWORD> retAddrs;
- if (frameNumber == 0)
- retAddrs.push_back (ep->ContextRecord->Eip);
-
- retAddrs.push_back (0);
-
- MEMORY_BASIC_INFORMATION mi;
- VirtualQuery (sp, &mi, sizeof (mi));
- PDWORD stackTop = (PDWORD)((byte *) mi.BaseAddress + mi.RegionSize);
- 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 <HostDevice> devices;
- static map <int, HostDevice> 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<byte>& 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<byte> 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 (&param, hwndDlg);
- }
- else
- {
- ShowWaitDialog (hwndDlg, FALSE, UnmountWaitThreadProc, &param);
- }
-
- 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<byte> 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) &params);
-}
-
-
-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<configuration>", 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<config key=\"%hs\">%hs</config>", key, value);
- xml++;
- }
-
- fputws (L"\n\t</configuration>", 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<config key=\"%hs\">%hs</config>",
- 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<config key=\"%hs\">%ls</config>",
- 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 <SecurityTokenInfo> 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 <SecurityTokenKeyfile> &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 <SecurityTokenKeyfile> SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector <SecurityTokenKeyfile> &keyfiles)
-{
- HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST);
- list <SecurityTokenKeyfile> 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 <SecurityTokenKeyfilePath> *selectedTokenKeyfiles;
- static vector <SecurityTokenKeyfile> keyfiles;
-
- WORD lw = LOWORD (wParam);
-
- switch (msg)
- {
- case WM_INITDIALOG:
- {
- selectedTokenKeyfiles = (list <SecurityTokenKeyfilePath> *) 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 <byte> 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 <byte> keyfileData;
-
- SecurityToken::GetKeyfileData (keyfile, keyfileData);
-
- if (keyfileData.empty())
- {
- SetLastError (ERROR_HANDLE_EOF);
- handleWin32Error (hwndDlg, SRC_POS);
- return 1;
- }
-
- finally_do_arg (vector <byte> *, &keyfileData, { burn (&finally_arg->front(), finally_arg->size()); });
-
- 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 <GetPinFunctor> (new PinRequestHandler(MainDlg)), auto_ptr <SendExceptionFunctor> (new WarningHandler(MainDlg)));
- }
- catch (Exception &e)
- {
- e.Show (hwndDlg);
- Error ("PKCS11_MODULE_INIT_FAILED", hwndDlg);
- return FALSE;
- }
-
- return TRUE;
-}
-
-#endif // !SETUP
-
-std::vector <HostDevice> GetAvailableHostDevices (bool noDeviceProperties, bool singleList, bool noFloppy, bool detectUnencryptedFilesystems)
-{
- vector <HostDevice> 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, &regNameSize, 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, &regNameSize, 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<byte> 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 <windowsx.h>
+#include <dbghelp.h>
+#include <dbt.h>
+#include <Setupapi.h>
+#include <fcntl.h>
+#include <io.h>
+#include <math.h>
+#include <shlobj.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <time.h>
+#include <tchar.h>
+#include <Richedit.h>
+
+#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 <strsafe.h>
+
+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 <DWORD> retAddrs;
+ if (frameNumber == 0)
+ retAddrs.push_back (ep->ContextRecord->Eip);
+
+ retAddrs.push_back (0);
+
+ MEMORY_BASIC_INFORMATION mi;
+ VirtualQuery (sp, &mi, sizeof (mi));
+ PDWORD stackTop = (PDWORD)((byte *) mi.BaseAddress + mi.RegionSize);
+ 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 <HostDevice> devices;
+ static map <int, HostDevice> 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<byte>& 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<byte> 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 (&param, hwndDlg);
+ }
+ else
+ {
+ ShowWaitDialog (hwndDlg, FALSE, UnmountWaitThreadProc, &param);
+ }
+
+ 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<byte> 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) &params);
+}
+
+
+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<configuration>", 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<config key=\"%hs\">%hs</config>", key, value);
+ xml++;
+ }
+
+ fputws (L"\n\t</configuration>", 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<config key=\"%hs\">%hs</config>",
+ 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<config key=\"%hs\">%ls</config>",
+ 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 <SecurityTokenInfo> 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 <SecurityTokenKeyfile> &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 <SecurityTokenKeyfile> SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector <SecurityTokenKeyfile> &keyfiles)
+{
+ HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST);
+ list <SecurityTokenKeyfile> 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 <SecurityTokenKeyfilePath> *selectedTokenKeyfiles;
+ static vector <SecurityTokenKeyfile> keyfiles;
+
+ WORD lw = LOWORD (wParam);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ selectedTokenKeyfiles = (list <SecurityTokenKeyfilePath> *) 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 <byte> 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 <byte> keyfileData;
+
+ SecurityToken::GetKeyfileData (keyfile, keyfileData);
+
+ if (keyfileData.empty())
+ {
+ SetLastError (ERROR_HANDLE_EOF);
+ handleWin32Error (hwndDlg, SRC_POS);
+ return 1;
+ }
+
+ finally_do_arg (vector <byte> *, &keyfileData, { burn (&finally_arg->front(), finally_arg->size()); });
+
+ 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 <GetPinFunctor> (new PinRequestHandler(MainDlg)), auto_ptr <SendExceptionFunctor> (new WarningHandler(MainDlg)));
+ }
+ catch (Exception &e)
+ {
+ e.Show (hwndDlg);
+ Error ("PKCS11_MODULE_INIT_FAILED", hwndDlg);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#endif // !SETUP
+
+std::vector <HostDevice> GetAvailableHostDevices (bool noDeviceProperties, bool singleList, bool noFloppy, bool detectUnencryptedFilesystems)
+{
+ vector <HostDevice> 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, &regNameSize, 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, &regNameSize, 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<byte> 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;
+}