"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/Dlgcode.c" (10 Oct 2018, 383120 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Dlgcode.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.22_Source_vs_1.23_Source.

    1 /*
    2  Legal Notice: Some portions of the source code contained in this file were
    3  derived from the source code of TrueCrypt 7.1a, which is 
    4  Copyright (c) 2003-2012 TrueCrypt Developers Association and which is 
    5  governed by the TrueCrypt License 3.0, also from the source code of
    6  Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
    7  and which is governed by the 'License Agreement for Encryption for the Masses' 
    8  Modifications and additions to the original source code (contained in this file) 
    9  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
   10  and are governed by the Apache License 2.0 the full text of which is
   11  contained in the file License.txt included in VeraCrypt binary and source
   12  code distribution packages. */
   13 
   14 #include "Tcdefs.h"
   15 
   16 #include <windowsx.h>
   17 #include <dbghelp.h>
   18 #include <dbt.h>
   19 #include <Setupapi.h>
   20 #include <fcntl.h>
   21 #include <io.h>
   22 #include <math.h>
   23 #include <shlobj.h>
   24 #include <sys/stat.h>
   25 #include <stdlib.h>
   26 #include <time.h>
   27 #include <tchar.h>
   28 #include <Richedit.h>
   29 #if defined (TCMOUNT) || defined (VOLFORMAT)
   30 #include <Shlwapi.h>
   31 #include <process.h>
   32 #include <Tlhelp32.h>
   33 #endif
   34 
   35 #include "Resource.h"
   36 
   37 #include "Platform/Finally.h"
   38 #include "Platform/ForEach.h"
   39 #include "Apidrvr.h"
   40 #include "BootEncryption.h"
   41 #include "Combo.h"
   42 #include "Crc.h"
   43 #include "Crypto.h"
   44 #include "Dictionary.h"
   45 #include "Dlgcode.h"
   46 #include "EncryptionThreadPool.h"
   47 #include "Endian.h"
   48 #include "Format/Inplace.h"
   49 #include "Language.h"
   50 #include "Keyfiles.h"
   51 #include "Pkcs5.h"
   52 #include "Random.h"
   53 #include "Registry.h"
   54 #include "SecurityToken.h"
   55 #include "Tests.h"
   56 #include "Volumes.h"
   57 #include "Wipe.h"
   58 #include "Xml.h"
   59 #include "Xts.h"
   60 #include "Boot/Windows/BootCommon.h"
   61 #include "Progress.h"
   62 #include "zip.h"
   63 
   64 #ifdef TCMOUNT
   65 #include "Mount/Mount.h"
   66 #include "Mount/resource.h"
   67 #endif
   68 
   69 #ifdef VOLFORMAT
   70 #include "Format/Tcformat.h"
   71 #endif
   72 
   73 #ifdef SETUP
   74 #include "Setup/Setup.h"
   75 #endif
   76 
   77 #include <Setupapi.h>
   78 #include <Softpub.h>
   79 #include <WinTrust.h>
   80 #include <strsafe.h>
   81 
   82 #pragma comment( lib, "setupapi.lib" )
   83 
   84 #ifndef TTI_INFO_LARGE
   85 #define TTI_INFO_LARGE          4
   86 #endif
   87 
   88 #ifndef TTI_WARNING_LARGE
   89 #define TTI_WARNING_LARGE       5
   90 #endif
   91 
   92 #ifndef TTI_ERROR_LARGE
   93 #define TTI_ERROR_LARGE         6
   94 #endif
   95 
   96 /* GPT Partition Type GUIDs */
   97 #define LOCAL_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID name = {l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8}
   98 LOCAL_DEFINE_GUID(PARTITION_ENTRY_UNUSED_GUID,   0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);    // Entry unused
   99 LOCAL_DEFINE_GUID(PARTITION_SYSTEM_GUID,         0xC12A7328L, 0xF81F, 0x11D2, 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B);    // EFI system partition
  100 LOCAL_DEFINE_GUID(PARTITION_MSFT_RESERVED_GUID,  0xE3C9E316L, 0x0B5C, 0x4DB8, 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE);    // Microsoft reserved space                                        
  101 LOCAL_DEFINE_GUID(PARTITION_BASIC_DATA_GUID,     0xEBD0A0A2L, 0xB9E5, 0x4433, 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7);    // Basic data partition
  102 LOCAL_DEFINE_GUID(PARTITION_LDM_METADATA_GUID,   0x5808C8AAL, 0x7E8F, 0x42E0, 0x85, 0xD2, 0xE1, 0xE9, 0x04, 0x34, 0xCF, 0xB3);    // Logical Disk Manager metadata partition
  103 LOCAL_DEFINE_GUID(PARTITION_LDM_DATA_GUID,       0xAF9B60A0L, 0x1431, 0x4F62, 0xBC, 0x68, 0x33, 0x11, 0x71, 0x4A, 0x69, 0xAD);    // Logical Disk Manager data partition
  104 LOCAL_DEFINE_GUID(PARTITION_MSFT_RECOVERY_GUID,  0xDE94BBA4L, 0x06D1, 0x4D40, 0xA1, 0x6A, 0xBF, 0xD5, 0x01, 0x79, 0xD6, 0xAC);    // Microsoft recovery partition
  105 LOCAL_DEFINE_GUID(PARTITION_CLUSTER_GUID,      0xdb97dba9L, 0x0840, 0x4bae, 0x97, 0xf0, 0xff, 0xb9, 0xa3, 0x27, 0xc7, 0xe1);    // Cluster metadata partition
  106 
  107 using namespace VeraCrypt;
  108 
  109 LONG DriverVersion;
  110 
  111 char *LastDialogId;
  112 wchar_t szHelpFile[TC_MAX_PATH];
  113 wchar_t szHelpFile2[TC_MAX_PATH];
  114 wchar_t SecurityTokenLibraryPath[TC_MAX_PATH];
  115 char CmdTokenPin [TC_MAX_PATH] = {0};
  116 
  117 HFONT hFixedDigitFont = NULL;
  118 HFONT hBoldFont = NULL;
  119 HFONT hTitleFont = NULL;
  120 HFONT hFixedFont = NULL;
  121 
  122 HFONT hUserFont = NULL;
  123 HFONT hUserUnderlineFont = NULL;
  124 HFONT hUserBoldFont = NULL;
  125 HFONT hUserUnderlineBoldFont = NULL;
  126 
  127 HFONT WindowTitleBarFont;
  128 
  129 WCHAR EditPasswordChar = 0;
  130 
  131 int ScreenDPI = USER_DEFAULT_SCREEN_DPI;
  132 double DPIScaleFactorX = 1;
  133 double DPIScaleFactorY = 1;
  134 double DlgAspectRatio = 1;
  135 
  136 HWND MainDlg = NULL;
  137 wchar_t *lpszTitle = NULL;
  138 
  139 BOOL Silent = FALSE;
  140 BOOL bPreserveTimestamp = TRUE;
  141 BOOL bShowDisconnectedNetworkDrives = FALSE;
  142 BOOL bHideWaitingDialog = FALSE;
  143 BOOL bCmdHideWaitingDialog = FALSE;
  144 BOOL bCmdHideWaitingDialogValid = FALSE;
  145 BOOL bUseSecureDesktop = FALSE;
  146 BOOL bCmdUseSecureDesktop = FALSE;
  147 BOOL bCmdUseSecureDesktopValid = FALSE;
  148 BOOL bStartOnLogon = FALSE;
  149 BOOL bMountDevicesOnLogon = FALSE;
  150 BOOL bMountFavoritesOnLogon = FALSE;
  151 
  152 BOOL bHistory = FALSE;
  153 
  154 #ifndef SETUP
  155 BOOL bLanguageSetInSetup = FALSE;
  156 #endif
  157 
  158 // Status of detection of hidden sectors (whole-system-drive encryption). 
  159 // 0 - Unknown/undetermined/completed, 1: Detection is or was in progress (but did not complete e.g. due to system crash).
  160 int HiddenSectorDetectionStatus = 0;    
  161 
  162 OSVersionEnum nCurrentOS = WIN_UNKNOWN;
  163 int CurrentOSMajor = 0;
  164 int CurrentOSMinor = 0;
  165 int CurrentOSServicePack = 0;
  166 int CurrentOSBuildNumber = 0;
  167 BOOL RemoteSession = FALSE;
  168 BOOL UacElevated = FALSE;
  169 
  170 BOOL bPortableModeConfirmed = FALSE;        // TRUE if it is certain that the instance is running in portable mode
  171 
  172 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.
  173 
  174 /* Globals used by Mount and Format (separately per instance) */ 
  175 BOOL PimEnable = FALSE;
  176 BOOL KeyFilesEnable = FALSE;
  177 KeyFile *FirstKeyFile = NULL;
  178 KeyFilesDlgParam        defaultKeyFilesParam;
  179 
  180 BOOL IgnoreWmDeviceChange = FALSE;
  181 BOOL DeviceChangeBroadcastDisabled = FALSE;
  182 BOOL LastMountedVolumeDirty;
  183 BOOL MountVolumesAsSystemFavorite = FALSE;
  184 BOOL FavoriteMountOnArrivalInProgress = FALSE;
  185 BOOL MultipleMountOperationInProgress = FALSE;
  186 
  187 BOOL WaitDialogDisplaying = FALSE;
  188 
  189 /* Handle to the device driver */
  190 HANDLE hDriver = INVALID_HANDLE_VALUE;
  191 
  192 /* This mutex is used to prevent multiple instances of the wizard or main app from dealing with system encryption */
  193 volatile HANDLE hSysEncMutex = NULL;        
  194 
  195 /* This mutex is used for non-system in-place encryption but only for informative (non-blocking) purposes,
  196 such as whether an app should prompt the user whether to resume scheduled process. */
  197 volatile HANDLE hNonSysInplaceEncMutex = NULL;
  198 
  199 /* This mutex is used to prevent multiple instances of the wizard or main app from trying to install or
  200 register the driver or from trying to launch it in portable mode at the same time. */
  201 volatile HANDLE hDriverSetupMutex = NULL;
  202 
  203 /* This mutex is used to prevent users from running the main TrueCrypt app or the wizard while an instance
  204 of the TrueCrypt installer is running (which is also useful for enforcing restart before the apps can be used). */
  205 volatile HANDLE hAppSetupMutex = NULL;
  206 
  207 /* Critical section used to protect access to global variables used in WNetGetConnection calls */
  208 CRITICAL_SECTION csWNetCalls;
  209 
  210 /* Critical section used to protect access to global list of physical drives */
  211 CRITICAL_SECTION csMountableDevices;
  212 CRITICAL_SECTION csVolumeIdCandidates;
  213 
  214 static std::vector<HostDevice> mountableDevices;
  215 static std::vector<HostDevice> rawHostDeviceList;
  216 
  217 HINSTANCE hInst = NULL;
  218 HCURSOR hCursor = NULL;
  219 
  220 ATOM hDlgClass, hSplashClass;
  221 
  222 /* This value may changed only by calling ChangeSystemEncryptionStatus(). Only the wizard can change it
  223 (others may still read it though). */
  224 int SystemEncryptionStatus = SYSENC_STATUS_NONE;    
  225 
  226 /* Only the wizard can change this value (others may only read it). */
  227 WipeAlgorithmId nWipeMode = TC_WIPE_NONE;
  228 
  229 BOOL bSysPartitionSelected = FALSE;     /* TRUE if the user selected the system partition via the Select Device dialog */
  230 BOOL bSysDriveSelected = FALSE;         /* TRUE if the user selected the system drive via the Select Device dialog */
  231 
  232 /* To populate these arrays, call GetSysDevicePaths(). If they contain valid paths, bCachedSysDevicePathsValid is TRUE. */
  233 wchar_t SysPartitionDevicePath [TC_MAX_PATH];
  234 wchar_t SysDriveDevicePath [TC_MAX_PATH];
  235 wstring ExtraBootPartitionDevicePath;
  236 char bCachedSysDevicePathsValid = FALSE;
  237 
  238 BOOL bHyperLinkBeingTracked = FALSE;
  239 
  240 int WrongPwdRetryCounter = 0;
  241 
  242 static FILE *ConfigFileHandle;
  243 char *ConfigBuffer;
  244 
  245 BOOL SystemFileSelectorCallPending = FALSE;
  246 DWORD SystemFileSelectorCallerThreadId;
  247 
  248 #define RANDPOOL_DISPLAY_REFRESH_INTERVAL   30
  249 #define RANDPOOL_DISPLAY_ROWS 16
  250 #define RANDPOOL_DISPLAY_COLUMNS 20
  251 
  252 HMODULE hRichEditDll = NULL;
  253 HMODULE hComctl32Dll = NULL;
  254 HMODULE hSetupDll = NULL;
  255 HMODULE hShlwapiDll = NULL;
  256 HMODULE hProfApiDll = NULL;
  257 HMODULE hUsp10Dll = NULL;
  258 HMODULE hCryptSpDll = NULL;
  259 HMODULE hUXThemeDll = NULL;
  260 HMODULE hUserenvDll = NULL;
  261 HMODULE hRsaenhDll = NULL;
  262 HMODULE himm32dll = NULL;
  263 HMODULE hMSCTFdll = NULL;
  264 HMODULE hfltlibdll = NULL;
  265 HMODULE hframedyndll = NULL;
  266 HMODULE hpsapidll = NULL;
  267 HMODULE hsecur32dll = NULL;
  268 HMODULE hnetapi32dll = NULL;
  269 HMODULE hauthzdll = NULL;
  270 HMODULE hxmllitedll = NULL;
  271 HMODULE hmprdll = NULL;
  272 HMODULE hsppdll = NULL;
  273 HMODULE vssapidll = NULL;
  274 HMODULE hvsstracedll = NULL;
  275 HMODULE hcfgmgr32dll = NULL;
  276 HMODULE hdevobjdll = NULL;
  277 HMODULE hpowrprofdll = NULL;
  278 HMODULE hsspiclidll = NULL;
  279 HMODULE hcryptbasedll = NULL;
  280 HMODULE hdwmapidll = NULL;
  281 HMODULE hmsasn1dll = NULL;
  282 HMODULE hcrypt32dll = NULL;
  283 HMODULE hbcryptdll = NULL;
  284 HMODULE hbcryptprimitivesdll = NULL;
  285 HMODULE hMsls31 = NULL;
  286 HMODULE hntmartadll = NULL;
  287 HMODULE hwinscarddll = NULL;
  288 HMODULE hmsvcrtdll = NULL;
  289 HMODULE hWinTrustLib = NULL;
  290 
  291 #define FREE_DLL(h) if (h) { FreeLibrary (h); h = NULL;}
  292 
  293 #ifndef BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE
  294 #define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE 0x00000001
  295 #endif
  296 
  297 #ifndef BASE_SEARCH_PATH_PERMANENT
  298 #define BASE_SEARCH_PATH_PERMANENT 0x00008000
  299 #endif
  300 
  301 #ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
  302 #define LOAD_LIBRARY_SEARCH_SYSTEM32   0x00000800
  303 #endif
  304 
  305 typedef BOOL (WINAPI *SetDllDirectoryPtr)(LPCWSTR lpPathName);
  306 typedef BOOL (WINAPI *SetSearchPathModePtr)(DWORD Flags);
  307 typedef BOOL (WINAPI *SetDefaultDllDirectoriesPtr)(DWORD DirectoryFlags);
  308 
  309 
  310 typedef void (WINAPI *InitCommonControlsPtr)(void);
  311 typedef HIMAGELIST  (WINAPI *ImageList_CreatePtr)(int cx, int cy, UINT flags, int cInitial, int cGrow);
  312 typedef int         (WINAPI *ImageList_AddPtr)(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask);
  313 
  314 typedef VOID (WINAPI *SetupCloseInfFilePtr)(HINF InfHandle);
  315 typedef HKEY (WINAPI *SetupDiOpenClassRegKeyPtr)(CONST GUID *ClassGuid,REGSAM samDesired);
  316 typedef BOOL (WINAPI *SetupInstallFromInfSectionWPtr)(HWND,HINF,PCWSTR,UINT,HKEY,PCWSTR,UINT,PSP_FILE_CALLBACK_W,PVOID,HDEVINFO,PSP_DEVINFO_DATA);
  317 typedef HINF (WINAPI *SetupOpenInfFileWPtr)(PCWSTR FileName,PCWSTR InfClass,DWORD InfStyle,PUINT ErrorLine);
  318 
  319 typedef LSTATUS (STDAPICALLTYPE *SHDeleteKeyWPtr)(HKEY hkey, LPCWSTR pszSubKey);
  320 
  321 typedef HRESULT (STDAPICALLTYPE *SHStrDupWPtr)(LPCWSTR psz, LPWSTR *ppwsz);
  322 
  323 // ChangeWindowMessageFilter
  324 typedef BOOL (WINAPI *ChangeWindowMessageFilterPtr) (UINT, DWORD);
  325 
  326 SetDllDirectoryPtr SetDllDirectoryFn = NULL;
  327 SetSearchPathModePtr SetSearchPathModeFn = NULL;
  328 SetDefaultDllDirectoriesPtr SetDefaultDllDirectoriesFn = NULL;
  329 
  330 ImageList_CreatePtr ImageList_CreateFn = NULL;
  331 ImageList_AddPtr ImageList_AddFn = NULL;
  332 
  333 SetupCloseInfFilePtr SetupCloseInfFileFn = NULL;
  334 SetupDiOpenClassRegKeyPtr SetupDiOpenClassRegKeyFn = NULL;
  335 SetupInstallFromInfSectionWPtr SetupInstallFromInfSectionWFn = NULL;
  336 SetupOpenInfFileWPtr SetupOpenInfFileWFn = NULL;
  337 SHDeleteKeyWPtr SHDeleteKeyWFn = NULL;
  338 SHStrDupWPtr SHStrDupWFn = NULL;
  339 ChangeWindowMessageFilterPtr ChangeWindowMessageFilterFn = NULL;
  340 
  341 typedef LONG (WINAPI *WINVERIFYTRUST)(HWND hwnd, GUID *pgActionID, LPVOID pWVTData);
  342 typedef CRYPT_PROVIDER_DATA* (WINAPI *WTHELPERPROVDATAFROMSTATEDATA)(HANDLE hStateData);
  343 typedef CRYPT_PROVIDER_SGNR* (WINAPI *WTHELPERGETPROVSIGNERFROMCHAIN)(CRYPT_PROVIDER_DATA *pProvData,
  344                                                                        DWORD idxSigner,
  345                                                                        BOOL fCounterSigner,
  346                                                                        DWORD idxCounterSigner);
  347 typedef CRYPT_PROVIDER_CERT* (WINAPI *WTHELPERGETPROVCERTFROMCHAIN)(CRYPT_PROVIDER_SGNR *pSgnr,
  348                                                                      DWORD idxCert);
  349 
  350 static WINVERIFYTRUST WinVerifyTrustFn = NULL;
  351 static WTHELPERPROVDATAFROMSTATEDATA WTHelperProvDataFromStateDataFn = NULL;
  352 static WTHELPERGETPROVSIGNERFROMCHAIN WTHelperGetProvSignerFromChainFn = NULL;
  353 static WTHELPERGETPROVCERTFROMCHAIN WTHelperGetProvCertFromChainFn = NULL;
  354 
  355 static unsigned char gpbSha1CodeSignCertFingerprint[64] = {
  356     0xCD, 0xF3, 0x05, 0xAD, 0xAE, 0xD3, 0x91, 0xF2, 0x0D, 0x95, 0x95, 0xAC,
  357     0x76, 0x09, 0x35, 0x53, 0x11, 0x00, 0x4D, 0xDD, 0x56, 0x02, 0xBD, 0x09,
  358     0x76, 0x57, 0xE1, 0xFA, 0xFA, 0xF4, 0x86, 0x09, 0x28, 0xA4, 0x0D, 0x1C,
  359     0x68, 0xE7, 0x68, 0x31, 0xD3, 0xB6, 0x62, 0x9C, 0x75, 0x91, 0xAB, 0xB5,
  360     0x6F, 0x1A, 0x75, 0xE7, 0x13, 0x2F, 0xF1, 0xB1, 0x14, 0xBF, 0x5F, 0x00,
  361     0x40, 0xCE, 0x17, 0x6C
  362 };
  363 
  364 typedef HRESULT (WINAPI *SHGETKNOWNFOLDERPATH) (
  365   _In_     REFKNOWNFOLDERID rfid,
  366   _In_     DWORD            dwFlags,
  367   _In_opt_ HANDLE           hToken,
  368   _Out_    PWSTR            *ppszPath
  369 );
  370 
  371 /* Windows dialog class */
  372 #define WINDOWS_DIALOG_CLASS L"#32770"
  373 
  374 /* Custom class names */
  375 #define TC_DLG_CLASS L"VeraCryptCustomDlg"
  376 #define TC_SPLASH_CLASS L"VeraCryptSplashDlg"
  377 
  378 /* constant used by ChangeWindowMessageFilter calls */
  379 #ifndef MSGFLT_ADD
  380 #define MSGFLT_ADD  1
  381 #endif
  382 
  383 /* undocumented message sent during drag-n-drop */
  384 #ifndef WM_COPYGLOBALDATA
  385 #define WM_COPYGLOBALDATA 0x0049
  386 #endif
  387 
  388 /* Benchmarks */
  389 
  390 #ifndef SETUP
  391 
  392 #define BENCHMARK_MAX_ITEMS 100
  393 #define BENCHMARK_DEFAULT_BUF_SIZE  BYTES_PER_MB
  394 #define HASH_FNC_BENCHMARKS FALSE   // For development purposes only. Must be FALSE when building a public release.
  395 #define PKCS5_BENCHMARKS    FALSE   // For development purposes only. Must be FALSE when building a public release.
  396 #if PKCS5_BENCHMARKS && HASH_FNC_BENCHMARKS
  397 #error PKCS5_BENCHMARKS and HASH_FNC_BENCHMARKS are both TRUE (at least one of them should be FALSE).
  398 #endif
  399 
  400 enum 
  401 {
  402     BENCHMARK_TYPE_ENCRYPTION = 0,
  403     BENCHMARK_TYPE_PRF,
  404     BENCHMARK_TYPE_HASH
  405 };
  406 
  407 enum 
  408 {
  409     BENCHMARK_SORT_BY_NAME = 0,
  410     BENCHMARK_SORT_BY_SPEED
  411 };
  412 
  413 typedef struct 
  414 {
  415     int id;
  416     wchar_t name[100];
  417     unsigned __int64 encSpeed;
  418     unsigned __int64 decSpeed;
  419     unsigned __int64 meanBytesPerSec;
  420 } BENCHMARK_REC;
  421 
  422 BENCHMARK_REC benchmarkTable [BENCHMARK_MAX_ITEMS];
  423 int benchmarkTotalItems = 0;
  424 int benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE;
  425 int benchmarkLastBufferSize = BENCHMARK_DEFAULT_BUF_SIZE;
  426 int benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED;
  427 LARGE_INTEGER benchmarkPerformanceFrequency;
  428 int benchmarkType = BENCHMARK_TYPE_ENCRYPTION;
  429 int benchmarkPim = -1;
  430 BOOL benchmarkPreBoot = FALSE;
  431 BOOL benchmarkGPT = FALSE;
  432 
  433 #endif  // #ifndef SETUP
  434 
  435 
  436 typedef struct 
  437 {
  438     void *strings;
  439     BOOL bold;
  440 
  441 } MULTI_CHOICE_DLGPROC_PARAMS;
  442 
  443 void InitGlobalLocks ()
  444 {
  445     InitializeCriticalSection (&csWNetCalls);
  446     InitializeCriticalSection (&csMountableDevices);
  447     InitializeCriticalSection (&csVolumeIdCandidates);
  448 }
  449 
  450 void FinalizeGlobalLocks ()
  451 {
  452     DeleteCriticalSection (&csWNetCalls);
  453     DeleteCriticalSection (&csMountableDevices);
  454     DeleteCriticalSection (&csVolumeIdCandidates);
  455 }
  456 
  457 void cleanup ()
  458 {
  459     burn (&CmdTokenPin, sizeof (CmdTokenPin));
  460 
  461     /* Cleanup the GDI fonts */
  462     if (hFixedFont != NULL)
  463         DeleteObject (hFixedFont);
  464     if (hFixedDigitFont != NULL)
  465         DeleteObject (hFixedDigitFont);
  466     if (hBoldFont != NULL)
  467         DeleteObject (hBoldFont);
  468     if (hTitleFont != NULL)
  469         DeleteObject (hTitleFont);
  470     if (hUserFont != NULL)
  471         DeleteObject (hUserFont);
  472     if (hUserUnderlineFont != NULL)
  473         DeleteObject (hUserUnderlineFont);
  474     if (hUserBoldFont != NULL)
  475         DeleteObject (hUserBoldFont);
  476     if (hUserUnderlineBoldFont != NULL)
  477         DeleteObject (hUserUnderlineBoldFont);
  478 
  479     /* Cleanup our dialog class */
  480     if (hDlgClass)
  481         UnregisterClassW (TC_DLG_CLASS, hInst);
  482     if (hSplashClass)
  483         UnregisterClassW (TC_SPLASH_CLASS, hInst);
  484 
  485     /* Close the device driver handle */
  486     if (hDriver != INVALID_HANDLE_VALUE)
  487     {
  488         // Unload driver mode if possible (non-install mode) 
  489         if (IsNonInstallMode ())
  490         {
  491             // If a dismount was forced in the lifetime of the driver, Windows may later prevent it to be loaded again from
  492             // the same path. Therefore, the driver will not be unloaded even though it was loaded in non-install mode.
  493             int driverUnloadDisabled;
  494             DWORD dwResult;
  495 
  496             if (!DeviceIoControl (hDriver, TC_IOCTL_IS_DRIVER_UNLOAD_DISABLED, NULL, 0, &driverUnloadDisabled, sizeof (driverUnloadDisabled), &dwResult, NULL))
  497                 driverUnloadDisabled = 0;
  498 
  499             if (!driverUnloadDisabled)
  500                 DriverUnload ();
  501             else
  502             {
  503                 CloseHandle (hDriver);
  504                 hDriver = INVALID_HANDLE_VALUE;
  505             }
  506         }
  507         else
  508         {
  509             CloseHandle (hDriver);
  510             hDriver = INVALID_HANDLE_VALUE;
  511         }
  512     }
  513 
  514     if (ConfigBuffer != NULL)
  515     {
  516         free (ConfigBuffer);
  517         ConfigBuffer = NULL;
  518     }
  519 
  520     CoUninitialize ();
  521 
  522     CloseSysEncMutex ();
  523 
  524 #ifndef SETUP
  525     try
  526     {
  527         if (SecurityToken::IsInitialized())
  528             SecurityToken::CloseLibrary();
  529     }
  530     catch (...) { }
  531 
  532     EncryptionThreadPoolStop();
  533 #endif
  534 
  535     FinalizeGlobalLocks ();
  536 }
  537 
  538 
  539 void LowerCaseCopy (wchar_t *lpszDest, const wchar_t *lpszSource)
  540 {
  541     size_t i = wcslen (lpszSource) + 1;
  542 
  543     lpszDest[i - 1] = 0;
  544     while (--i > 0)
  545     {
  546         lpszDest[i - 1] = (wchar_t) towlower (lpszSource[i - 1]);
  547     }
  548 
  549 }
  550 
  551 void UpperCaseCopy (wchar_t *lpszDest, size_t cbDest, const wchar_t *lpszSource)
  552 {
  553     if (lpszDest && cbDest)
  554     {
  555         size_t i = wcslen (lpszSource);
  556         if (i >= cbDest)
  557             i = cbDest - 1;
  558 
  559         lpszDest[i] = 0;
  560         i++;
  561         while (--i > 0)
  562         {
  563             lpszDest[i - 1] = (wchar_t) towupper (lpszSource[i - 1]);
  564         }
  565     }
  566 }
  567 
  568 
  569 std::wstring ToUpperCase (const std::wstring &str)
  570 {
  571     wstring u;
  572     foreach (wchar_t c, str)
  573     {
  574         u += (wchar_t) towupper (c);
  575     }
  576 
  577     return u;
  578 }
  579 
  580 size_t TrimWhiteSpace(wchar_t *str)
  581 {
  582   wchar_t *end, *ptr = str;
  583   size_t out_size;
  584 
  585   if(!str || *str == 0)
  586     return 0;
  587 
  588   // Trim leading space
  589   while(iswspace(*ptr)) ptr++;
  590 
  591   if(*ptr == 0)  // All spaces?
  592   {
  593     *str = 0;
  594     return 0;
  595   }
  596 
  597   // Trim trailing space
  598   end = str + wcslen(str) - 1;
  599   while(end > ptr && iswspace(*end)) end--;
  600   end++;
  601 
  602   // Set output size to trimmed string length
  603   out_size = (end - ptr);
  604 
  605   // Copy trimmed string and add null terminator
  606   wmemmove(str, ptr, out_size);
  607   str[out_size] = 0;
  608 
  609   return out_size;
  610 }
  611 
  612 BOOL IsNullTerminateString (const wchar_t* str, size_t cbSize)
  613 {
  614     if (str && cbSize)
  615     {
  616         for (size_t i = 0; i < cbSize; i++)
  617         {
  618             if (str[i] == 0)
  619                 return TRUE;
  620         }
  621     }
  622 
  623     return FALSE;
  624 }
  625 
  626 // check the validity of a file name
  627 BOOL IsValidFileName(const wchar_t* str)
  628 {
  629     static wchar_t invalidChars[9] = {L'<', L'>', L':', L'"', L'/', L'\\', L'|', L'?', L'*'};
  630     wchar_t c;
  631     int i;
  632     BOOL bNotDotOnly = FALSE;
  633     while ((c = *str))
  634     {
  635         if (c != L'.')
  636             bNotDotOnly = TRUE;
  637         for (i= 0; i < ARRAYSIZE(invalidChars); i++)
  638             if (c == invalidChars[i])
  639                 return FALSE;
  640         str++;
  641     }
  642 
  643     return bNotDotOnly;
  644 }
  645 
  646 BOOL IsVolumeDeviceHosted (const wchar_t *lpszDiskFile)
  647 {
  648     return wcsstr (lpszDiskFile, L"\\Device\\") == lpszDiskFile
  649         || wcsstr (lpszDiskFile, L"\\DEVICE\\") == lpszDiskFile;
  650 }
  651 
  652 
  653 void CreateFullVolumePath (wchar_t *lpszDiskFile, size_t cbDiskFile, const wchar_t *lpszFileName, BOOL * bDevice)
  654 {
  655     UpperCaseCopy (lpszDiskFile, cbDiskFile, lpszFileName);
  656 
  657     *bDevice = FALSE;
  658 
  659     if (wmemcmp (lpszDiskFile, L"\\DEVICE", 7) == 0)
  660     {
  661         *bDevice = TRUE;
  662     }
  663 
  664     StringCbCopyW (lpszDiskFile, cbDiskFile, lpszFileName);
  665 
  666 #if _DEBUG
  667     OutputDebugString (L"CreateFullVolumePath: ");
  668     OutputDebugString (lpszDiskFile);
  669     OutputDebugString (L"\n");
  670 #endif
  671 
  672 }
  673 
  674 int FakeDosNameForDevice (const wchar_t *lpszDiskFile , wchar_t *lpszDosDevice , size_t cbDosDevice, wchar_t *lpszCFDevice , size_t cbCFDevice, BOOL bNameOnly)
  675 {
  676     BOOL bDosLinkCreated = TRUE;
  677     StringCbPrintfW (lpszDosDevice, cbDosDevice,L"veracrypt%lu", GetCurrentProcessId ());
  678 
  679     if (bNameOnly == FALSE)
  680         bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile);
  681 
  682     if (bDosLinkCreated == FALSE)
  683         return ERR_OS_ERROR;
  684     else
  685         StringCbPrintfW (lpszCFDevice, cbCFDevice,L"\\\\.\\%s", lpszDosDevice);
  686 
  687     return 0;
  688 }
  689 
  690 int RemoveFakeDosName (wchar_t *lpszDiskFile, wchar_t *lpszDosDevice)
  691 {
  692     BOOL bDosLinkRemoved = DefineDosDevice (DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE |
  693             DDD_REMOVE_DEFINITION, lpszDosDevice, lpszDiskFile);
  694     if (bDosLinkRemoved == FALSE)
  695     {
  696         return ERR_OS_ERROR;
  697     }
  698 
  699     return 0;
  700 }
  701 
  702 
  703 void AbortProcessDirect (wchar_t *abortMsg)
  704 {
  705     // Note that this function also causes localcleanup() to be called (see atexit())
  706     MessageBeep (MB_ICONEXCLAMATION);
  707     MessageBoxW (NULL, abortMsg, lpszTitle, ICON_HAND);
  708     FREE_DLL (hRichEditDll);
  709     FREE_DLL (hComctl32Dll);
  710     FREE_DLL (hSetupDll);
  711     FREE_DLL (hShlwapiDll);
  712     FREE_DLL (hProfApiDll);
  713     FREE_DLL (hUsp10Dll);
  714     FREE_DLL (hCryptSpDll);
  715     FREE_DLL (hUXThemeDll);
  716     FREE_DLL (hUserenvDll);
  717     FREE_DLL (hRsaenhDll);
  718     FREE_DLL (himm32dll);
  719     FREE_DLL (hMSCTFdll);
  720     FREE_DLL (hfltlibdll);
  721     FREE_DLL (hframedyndll);
  722     FREE_DLL (hpsapidll);
  723     FREE_DLL (hsecur32dll);
  724     FREE_DLL (hnetapi32dll);
  725     FREE_DLL (hauthzdll);
  726     FREE_DLL (hxmllitedll);
  727     FREE_DLL (hmprdll);
  728     FREE_DLL (hsppdll);
  729     FREE_DLL (vssapidll);
  730     FREE_DLL (hvsstracedll);
  731     FREE_DLL (hCryptSpDll);
  732     FREE_DLL (hcfgmgr32dll);
  733     FREE_DLL (hdevobjdll);
  734     FREE_DLL (hpowrprofdll);
  735     FREE_DLL (hsspiclidll);
  736     FREE_DLL (hcryptbasedll);
  737     FREE_DLL (hdwmapidll);
  738     FREE_DLL (hmsasn1dll);
  739     FREE_DLL (hcrypt32dll);
  740     FREE_DLL (hbcryptdll);
  741     FREE_DLL (hbcryptprimitivesdll);
  742     FREE_DLL (hMsls31);
  743     FREE_DLL (hntmartadll);
  744     FREE_DLL (hwinscarddll);
  745     FREE_DLL (hmsvcrtdll);
  746 
  747     exit (1);
  748 }
  749 
  750 void AbortProcess (char *stringId)
  751 {
  752     // Note that this function also causes localcleanup() to be called (see atexit())
  753     AbortProcessDirect (GetString (stringId));
  754 }
  755 
  756 void AbortProcessSilent (void)
  757 {
  758     FREE_DLL (hRichEditDll);
  759     FREE_DLL (hComctl32Dll);
  760     FREE_DLL (hSetupDll);
  761     FREE_DLL (hShlwapiDll);
  762     FREE_DLL (hProfApiDll);
  763     FREE_DLL (hUsp10Dll);
  764     FREE_DLL (hCryptSpDll);
  765     FREE_DLL (hUXThemeDll);
  766     FREE_DLL (hUserenvDll);
  767     FREE_DLL (hRsaenhDll);
  768     FREE_DLL (himm32dll);
  769     FREE_DLL (hMSCTFdll);
  770     FREE_DLL (hfltlibdll);
  771     FREE_DLL (hframedyndll);
  772     FREE_DLL (hpsapidll);
  773     FREE_DLL (hsecur32dll);
  774     FREE_DLL (hnetapi32dll);
  775     FREE_DLL (hauthzdll);
  776     FREE_DLL (hxmllitedll);
  777     FREE_DLL (hmprdll);
  778     FREE_DLL (hsppdll);
  779     FREE_DLL (vssapidll);
  780     FREE_DLL (hvsstracedll);
  781     FREE_DLL (hCryptSpDll);
  782     FREE_DLL (hcfgmgr32dll);
  783     FREE_DLL (hdevobjdll);
  784     FREE_DLL (hpowrprofdll);
  785     FREE_DLL (hsspiclidll);
  786     FREE_DLL (hcryptbasedll);
  787     FREE_DLL (hdwmapidll);
  788     FREE_DLL (hmsasn1dll);
  789     FREE_DLL (hcrypt32dll);
  790     FREE_DLL (hbcryptdll);
  791     FREE_DLL (hbcryptprimitivesdll);
  792     FREE_DLL (hMsls31);
  793     FREE_DLL (hntmartadll);
  794     FREE_DLL (hwinscarddll);
  795     FREE_DLL (hmsvcrtdll);
  796 
  797     // Note that this function also causes localcleanup() to be called (see atexit())
  798     exit (1);
  799 }
  800 
  801 
  802 #pragma warning(push)
  803 #pragma warning(disable:4702)
  804 
  805 void *err_malloc (size_t size)
  806 {
  807     void *z = (void *) TCalloc (size);
  808     if (z)
  809         return z;
  810     AbortProcess ("OUTOFMEMORY");
  811     return 0;
  812 }
  813 
  814 #pragma warning(pop)
  815 
  816 
  817 char *err_strdup (char *lpszText)
  818 {
  819     size_t j = (strlen (lpszText) + 1) * sizeof (char);
  820     char *z = (char *) err_malloc (j);
  821     memmove (z, lpszText, j);
  822     return z;
  823 }
  824 
  825 
  826 BOOL IsDiskReadError (DWORD error)
  827 {
  828     return (error == ERROR_CRC
  829         || error == ERROR_IO_DEVICE
  830         || error == ERROR_BAD_CLUSTERS
  831         || error == ERROR_SECTOR_NOT_FOUND
  832         || error == ERROR_READ_FAULT
  833         || error == ERROR_INVALID_FUNCTION // I/O error may be reported as ERROR_INVALID_FUNCTION by buggy chipset drivers
  834         || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT
  835 }
  836 
  837 
  838 BOOL IsDiskWriteError (DWORD error)
  839 {
  840     return (error == ERROR_IO_DEVICE
  841         || error == ERROR_BAD_CLUSTERS
  842         || error == ERROR_SECTOR_NOT_FOUND
  843         || error == ERROR_WRITE_FAULT
  844         || error == ERROR_INVALID_FUNCTION // I/O error may be reported as ERROR_INVALID_FUNCTION by buggy chipset drivers
  845         || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT
  846 }
  847 
  848 
  849 BOOL IsDiskError (DWORD error)
  850 {
  851     return IsDiskReadError (error) || IsDiskWriteError (error);
  852 }
  853 
  854 
  855 DWORD handleWin32Error (HWND hwndDlg, const char* srcPos)
  856 {
  857     PWSTR lpMsgBuf;
  858     DWORD dwError = GetLastError ();    
  859     wchar_t szErrorValue[32];
  860     wchar_t* pszDesc;
  861 
  862     if (Silent || dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE)
  863         return dwError;
  864 
  865     // Access denied
  866     if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ())
  867     {
  868         ErrorDirect ( AppendSrcPos (GetString ("ERR_ACCESS_DENIED"), srcPos).c_str (), hwndDlg);
  869         SetLastError (dwError);     // Preserve the original error code
  870         return dwError;
  871     }
  872 
  873     FormatMessageW (
  874         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  875                   NULL,
  876                   dwError,
  877                   MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),   /* Default language */
  878                   (PWSTR) &lpMsgBuf,
  879                   0,
  880                   NULL
  881         );
  882 
  883     if (lpMsgBuf)
  884         pszDesc = (wchar_t*) lpMsgBuf;
  885     else
  886     {
  887         StringCchPrintfW (szErrorValue, ARRAYSIZE (szErrorValue), L"Error 0x%.8X", dwError);
  888         pszDesc = szErrorValue;
  889     }
  890 
  891     MessageBoxW (hwndDlg, AppendSrcPos (pszDesc, srcPos).c_str (), lpszTitle, ICON_HAND);
  892     if (lpMsgBuf) LocalFree (lpMsgBuf);
  893 
  894     // User-friendly hardware error explanation
  895     if (IsDiskError (dwError))
  896         Error ("ERR_HARDWARE_ERROR", hwndDlg);
  897 
  898     // Device not ready
  899     if (dwError == ERROR_NOT_READY)
  900         HandleDriveNotReadyError(hwndDlg);
  901 
  902     SetLastError (dwError);     // Preserve the original error code
  903 
  904     return dwError;
  905 }
  906 
  907 BOOL translateWin32Error (wchar_t *lpszMsgBuf, int nWSizeOfBuf)
  908 {
  909     DWORD dwError = GetLastError ();
  910 
  911     if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError,
  912                MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),  /* Default language */
  913                lpszMsgBuf, nWSizeOfBuf, NULL))
  914     {
  915         SetLastError (dwError);     // Preserve the original error code
  916         return TRUE;
  917     }
  918 
  919     SetLastError (dwError);         // Preserve the original error code
  920     return FALSE;
  921 }
  922 
  923 // If the user has a non-default screen DPI, all absolute font sizes must be
  924 // converted using this function.
  925 int CompensateDPIFont (int val)
  926 {
  927     if (ScreenDPI == USER_DEFAULT_SCREEN_DPI)
  928         return val;
  929     else
  930     {
  931         double tmpVal = (double) val * DPIScaleFactorY * DlgAspectRatio * 0.999;
  932 
  933         if (tmpVal > 0)
  934             return (int) floor(tmpVal);
  935         else
  936             return (int) ceil(tmpVal);
  937     }
  938 }
  939 
  940 
  941 // If the user has a non-default screen DPI, some screen coordinates and sizes must
  942 // be converted using this function
  943 int CompensateXDPI (int val)
  944 {
  945     if (ScreenDPI == USER_DEFAULT_SCREEN_DPI)
  946         return val;
  947     else
  948     {
  949         double tmpVal = (double) val * DPIScaleFactorX;
  950 
  951         if (tmpVal > 0)
  952             return (int) floor(tmpVal);
  953         else
  954             return (int) ceil(tmpVal);
  955     }
  956 }
  957 
  958 
  959 // If the user has a non-default screen DPI, some screen coordinates and sizes must
  960 // be converted using this function
  961 int CompensateYDPI (int val)
  962 {
  963     if (ScreenDPI == USER_DEFAULT_SCREEN_DPI)
  964         return val;
  965     else
  966     {
  967         double tmpVal = (double) val * DPIScaleFactorY;
  968 
  969         if (tmpVal > 0)
  970             return (int) floor(tmpVal);
  971         else
  972             return (int) ceil(tmpVal);
  973     }
  974 }
  975 
  976 
  977 int GetTextGfxWidth (HWND hwndDlgItem, const wchar_t *text, HFONT hFont)
  978 {
  979     SIZE sizes;
  980     TEXTMETRIC textMetrics;
  981     HDC hdc = GetDC (hwndDlgItem); 
  982 
  983     SelectObject(hdc, (HGDIOBJ) hFont);
  984 
  985     GetTextExtentPoint32W (hdc, text, (int) wcslen (text), &sizes);
  986 
  987     GetTextMetrics(hdc, &textMetrics);  // Necessary for non-TrueType raster fonts (tmOverhang)
  988 
  989     ReleaseDC (hwndDlgItem, hdc); 
  990 
  991     return ((int) sizes.cx - (int) textMetrics.tmOverhang);
  992 }
  993 
  994 
  995 int GetTextGfxHeight (HWND hwndDlgItem, const wchar_t *text, HFONT hFont)
  996 {
  997     SIZE sizes;
  998     HDC hdc = GetDC (hwndDlgItem); 
  999 
 1000     SelectObject(hdc, (HGDIOBJ) hFont);
 1001 
 1002     GetTextExtentPoint32W (hdc, text, (int) wcslen (text), &sizes);
 1003 
 1004     ReleaseDC (hwndDlgItem, hdc); 
 1005 
 1006     return ((int) sizes.cy);
 1007 }
 1008 
 1009 
 1010 std::wstring FitPathInGfxWidth (HWND hwnd, HFONT hFont, LONG width, const std::wstring &path)
 1011 {
 1012     wstring newPath;
 1013 
 1014     RECT rect;
 1015     rect.left = 0;
 1016     rect.top = 0;
 1017     rect.right = width;
 1018     rect.bottom = LONG_MAX;
 1019 
 1020     HDC hdc = GetDC (hwnd); 
 1021     SelectObject (hdc, (HGDIOBJ) hFont);
 1022 
 1023     wchar_t pathBuf[TC_MAX_PATH];
 1024     StringCchCopyW (pathBuf, ARRAYSIZE (pathBuf), path.c_str());
 1025 
 1026     if (DrawText (hdc, pathBuf, (int) path.size(), &rect, DT_CALCRECT | DT_MODIFYSTRING | DT_PATH_ELLIPSIS | DT_SINGLELINE) != 0)
 1027         newPath = pathBuf;
 1028 
 1029     ReleaseDC (hwnd, hdc); 
 1030     return newPath;
 1031 }
 1032 
 1033 
 1034 static LRESULT CALLBACK HyperlinkProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 1035 {
 1036     WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA);
 1037 
 1038     switch (message)
 1039     {
 1040     case WM_SETCURSOR:
 1041         if (!bHyperLinkBeingTracked)
 1042         {
 1043             TRACKMOUSEEVENT trackMouseEvent;
 1044 
 1045             trackMouseEvent.cbSize = sizeof(trackMouseEvent);
 1046             trackMouseEvent.dwFlags = TME_LEAVE;
 1047             trackMouseEvent.hwndTrack = hwnd;
 1048 
 1049             bHyperLinkBeingTracked = TrackMouseEvent(&trackMouseEvent);
 1050 
 1051             HandCursor();
 1052         }
 1053         return 0;
 1054 
 1055     case WM_MOUSELEAVE:
 1056         bHyperLinkBeingTracked = FALSE;
 1057         NormalCursor();
 1058         return 0;
 1059     }
 1060 
 1061     return CallWindowProcW (wp, hwnd, message, wParam, lParam);
 1062 }
 1063 
 1064 
 1065 BOOL ToHyperlink (HWND hwndDlg, UINT ctrlId)
 1066 {
 1067     return ToCustHyperlink (hwndDlg, ctrlId, hUserUnderlineFont);
 1068 }
 1069 
 1070 
 1071 BOOL ToCustHyperlink (HWND hwndDlg, UINT ctrlId, HFONT hFont)
 1072 {
 1073     HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId);
 1074 
 1075     SendMessageW (hwndCtrl, WM_SETFONT, (WPARAM) hFont, 0);
 1076 
 1077     SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC));
 1078     SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) HyperlinkProc);
 1079 
 1080     // Resize the field according to its actual size in pixels and move it if centered or right-aligned.
 1081     // This should be done again if the link text changes.
 1082     AccommodateTextField (hwndDlg, ctrlId, TRUE, hFont);
 1083 
 1084     return TRUE;
 1085 }
 1086 
 1087 
 1088 // Resizes a text field according to its actual width and height in pixels (font size is taken into account) and moves
 1089 // it accordingly if the field is centered or right-aligned. Should be used on all hyperlinks upon dialog init
 1090 // after localization (bFirstUpdate should be TRUE) and later whenever a hyperlink text changes (bFirstUpdate
 1091 // must be FALSE).
 1092 void AccommodateTextField (HWND hwndDlg, UINT ctrlId, BOOL bFirstUpdate, HFONT hFont)
 1093 {
 1094     RECT rec, wrec, trec;
 1095     HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId);
 1096     int width, origWidth, height, origHeight;
 1097     int horizSubOffset, vertSubOffset, vertOffset, alignPosDiff = 0;
 1098     wchar_t text [MAX_URL_LENGTH];
 1099     WINDOWINFO windowInfo;
 1100     BOOL bBorderlessWindow = !(GetWindowLongPtrW (hwndDlg, GWL_STYLE) & (WS_BORDER | WS_DLGFRAME));
 1101 
 1102     // Resize the field according to its length and font size and move if centered or right-aligned
 1103 
 1104     GetWindowTextW (hwndCtrl, text, sizeof (text) / sizeof (wchar_t));
 1105 
 1106     width = GetTextGfxWidth (hwndCtrl, text, hFont);
 1107     height = GetTextGfxHeight (hwndCtrl, text, hFont);
 1108 
 1109     GetClientRect (hwndCtrl, &rec);     
 1110     origWidth = rec.right;
 1111     origHeight = rec.bottom;
 1112 
 1113     if (width >= 0
 1114         && (!bFirstUpdate || origWidth > width))    // The original width of the field is the maximum allowed size 
 1115     {
 1116         horizSubOffset = origWidth - width;
 1117         vertSubOffset = origHeight - height;
 1118 
 1119         // Window coords
 1120         GetWindowRect(hwndDlg, &wrec);
 1121         GetClientRect(hwndDlg, &trec);
 1122 
 1123         // Vertical "title bar" offset
 1124         vertOffset = wrec.bottom - wrec.top - trec.bottom - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CYFIXEDFRAME));
 1125 
 1126         // Text field coords
 1127         GetWindowRect(hwndCtrl, &rec);
 1128 
 1129         // Alignment offset
 1130         windowInfo.cbSize = sizeof(windowInfo);
 1131         GetWindowInfo (hwndCtrl, &windowInfo);
 1132 
 1133         if (windowInfo.dwStyle & SS_CENTER)
 1134             alignPosDiff = horizSubOffset / 2;
 1135         else if (windowInfo.dwStyle & SS_RIGHT)
 1136             alignPosDiff = horizSubOffset;
 1137         
 1138         // Resize/move
 1139         if (alignPosDiff > 0)
 1140         {
 1141             // Resize and move the text field
 1142             MoveWindow (hwndCtrl,
 1143                 rec.left - wrec.left - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CXFIXEDFRAME)) + alignPosDiff,
 1144                 rec.top - wrec.top - vertOffset,
 1145                 origWidth - horizSubOffset,
 1146                 origHeight - vertSubOffset,
 1147                 TRUE);
 1148         }
 1149         else
 1150         {
 1151             // Resize the text field
 1152             SetWindowPos (hwndCtrl, 0, 0, 0,
 1153                 origWidth - horizSubOffset,
 1154                 origHeight - vertSubOffset,
 1155                 SWP_NOMOVE | SWP_NOZORDER);
 1156         }
 1157 
 1158         SetWindowPos (hwndCtrl, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 1159 
 1160         InvalidateRect (hwndCtrl, NULL, TRUE);
 1161     }
 1162 }
 1163 
 1164 // 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.
 1165 void DisableCloseButton (HWND hwndDlg)
 1166 {
 1167     EnableMenuItem (GetSystemMenu (hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
 1168 }
 1169 
 1170 
 1171 void EnableCloseButton (HWND hwndDlg)
 1172 {
 1173     EnableMenuItem (GetSystemMenu (hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
 1174 }
 1175 
 1176 // Protects an input field from having its content updated by a Paste action (call ToBootPwdField() to use this).
 1177 static LRESULT CALLBACK BootPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 1178 {
 1179     WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA);
 1180 
 1181     switch (message)
 1182     {
 1183     case WM_PASTE:
 1184         return 1;
 1185     }
 1186 
 1187     return CallWindowProcW (wp, hwnd, message, wParam, lParam);
 1188 }
 1189 
 1190 
 1191 // Protects an input field from having its content updated by a Paste action. Used for pre-boot password
 1192 // input fields (only the US keyboard layout is supported in pre-boot environment so we must prevent the 
 1193 // user from pasting a password typed using a non-US keyboard layout).
 1194 void ToBootPwdField (HWND hwndDlg, UINT ctrlId)
 1195 {
 1196     HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId);
 1197     WNDPROC originalwp = (WNDPROC) GetWindowLongPtrW (hwndCtrl, GWLP_USERDATA);
 1198     // if ToNormalPwdField has been called before, GWLP_USERDATA already contains original WNDPROC
 1199     if (!originalwp)
 1200     {       
 1201         SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC));
 1202     }
 1203     SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) BootPwdFieldProc);
 1204 }
 1205 
 1206 // Ensures that a warning is displayed when user is pasting a password longer than the maximum
 1207 // length which is set to 64 characters
 1208 static LRESULT CALLBACK NormalPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 1209 {
 1210     WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA);
 1211 
 1212     switch (message)
 1213     {
 1214     case WM_PASTE:
 1215         {
 1216             bool bBlock = false;
 1217             if (OpenClipboard (NULL))
 1218             {
 1219                 HANDLE h = GetClipboardData (CF_UNICODETEXT);
 1220                 if (h)
 1221                 {
 1222                     wchar_t *pchData = (wchar_t*)GlobalLock(h);
 1223                     int txtlen = 0;
 1224                     while (*pchData)
 1225                     {
 1226                         if (*pchData == '\r' || *pchData == '\n')
 1227                             break;
 1228                         else
 1229                         {
 1230                             txtlen++;
 1231                             pchData++;
 1232                         }
 1233                     }
 1234 
 1235                     if (txtlen)
 1236                     {
 1237                         int curLen = GetWindowTextLength (hwnd);
 1238                         if (curLen == MAX_PASSWORD)
 1239                         {
 1240                             EDITBALLOONTIP ebt;
 1241 
 1242                             ebt.cbStruct = sizeof( EDITBALLOONTIP );
 1243                             ebt.pszText = GetString ("PASSWORD_MAXLENGTH_REACHED");
 1244                             ebt.pszTitle = lpszTitle;
 1245                             ebt.ttiIcon = TTI_ERROR_LARGE;    // tooltip warning icon
 1246 
 1247                             SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt);
 1248 
 1249                             MessageBeep (0xFFFFFFFF);
 1250 
 1251                             bBlock = true;
 1252                         }
 1253                         else if ((txtlen + curLen) > MAX_PASSWORD)
 1254                         {
 1255                             EDITBALLOONTIP ebt;
 1256 
 1257                             ebt.cbStruct = sizeof( EDITBALLOONTIP );
 1258                             ebt.pszText = GetString ("PASSWORD_PASTED_TRUNCATED");
 1259                             ebt.pszTitle = lpszTitle;
 1260                             ebt.ttiIcon = TTI_WARNING_LARGE;    // tooltip warning icon
 1261 
 1262                             SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt);
 1263 
 1264                             MessageBeep (0xFFFFFFFF);
 1265                         }
 1266                         else
 1267                              SendMessage(hwnd, EM_HIDEBALLOONTIP, 0, 0);
 1268                     }
 1269                     GlobalUnlock(h);
 1270                 }
 1271                 CloseClipboard ();
 1272             }
 1273 
 1274             if (bBlock)
 1275                 return FALSE;
 1276         }
 1277         break;
 1278     case WM_CHAR:
 1279         {
 1280             DWORD dwStartPos = 0, dwEndPos = 0;
 1281             short vk = VkKeyScanW ((WCHAR) wParam);
 1282             BYTE vkCode = LOBYTE (vk);
 1283             BYTE vkState = HIBYTE (vk);
 1284             bool ctrlPressed = (vkState & 2) && !(vkState & 4);
 1285 
 1286             // check if there is a selected text
 1287             SendMessage (hwnd,  EM_GETSEL, (WPARAM) &dwStartPos, (LPARAM) &dwEndPos);
 1288 
 1289             if ((dwStartPos == dwEndPos) 
 1290                 && (vkCode != VK_DELETE) && (vkCode != VK_BACK) 
 1291                 && !ctrlPressed 
 1292                 && (GetWindowTextLength (hwnd) == MAX_PASSWORD))
 1293             {
 1294                 EDITBALLOONTIP ebt;
 1295 
 1296                 ebt.cbStruct = sizeof( EDITBALLOONTIP );
 1297                 ebt.pszText = GetString ("PASSWORD_MAXLENGTH_REACHED");
 1298                 ebt.pszTitle = lpszTitle;
 1299                 ebt.ttiIcon = TTI_ERROR_LARGE;    // tooltip warning icon
 1300 
 1301                 SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt);
 1302 
 1303                 MessageBeep (0xFFFFFFFF);
 1304             }
 1305             else
 1306                  SendMessage(hwnd, EM_HIDEBALLOONTIP, 0, 0);
 1307         }
 1308         break;
 1309     }
 1310 
 1311     return CallWindowProcW (wp, hwnd, message, wParam, lParam);
 1312 }
 1313 
 1314 void ToNormalPwdField (HWND hwndDlg, UINT ctrlId)
 1315 {
 1316     HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId);
 1317     WNDPROC originalwp = (WNDPROC) GetWindowLongPtrW (hwndCtrl, GWLP_USERDATA);
 1318 
 1319     SendMessage (hwndCtrl, EM_LIMITTEXT, MAX_PASSWORD, 0);
 1320     // only change WNDPROC if not changed already
 1321     if (!originalwp)
 1322     {
 1323         SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC));
 1324         SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) NormalPwdFieldProc);
 1325     }
 1326 }
 1327 
 1328 
 1329 // This function currently serves the following purposes:
 1330 // - Determines scaling factors for current screen DPI and GUI aspect ratio.
 1331 // - Determines how Windows skews the GUI aspect ratio (which happens when the user has a non-default DPI).
 1332 // The determined values must be used when performing some GUI operations and calculations.
 1333 BOOL CALLBACK AuxiliaryDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 1334 {
 1335     switch (msg)
 1336     {
 1337     case WM_INITDIALOG:
 1338         {
 1339             HDC hDC = GetDC (hwndDlg);
 1340 
 1341             if (hDC)
 1342             {
 1343                 ScreenDPI = GetDeviceCaps (hDC, LOGPIXELSY);
 1344                 ReleaseDC (hwndDlg, hDC); 
 1345             }
 1346 
 1347             DPIScaleFactorX = 1;
 1348             DPIScaleFactorY = 1;
 1349             DlgAspectRatio = 1;
 1350 
 1351             if (ScreenDPI != USER_DEFAULT_SCREEN_DPI)
 1352             {
 1353                 // Windows skews the GUI aspect ratio if the user has a non-default DPI. Hence, working with 
 1354                 // actual screen DPI is redundant and leads to incorrect results. What really matters here is
 1355                 // how Windows actually renders our GUI. This is determined by comparing the expected and current
 1356                 // sizes of a hidden calibration text field.
 1357 
 1358                 RECT trec;
 1359 
 1360                 trec.right = 0;
 1361                 trec.bottom = 0;
 1362 
 1363                 GetClientRect (GetDlgItem (hwndDlg, IDC_ASPECT_RATIO_CALIBRATION_BOX), &trec);
 1364 
 1365                 if (trec.right != 0 && trec.bottom != 0)
 1366                 {
 1367                     // The size of the 282x282 IDC_ASPECT_RATIO_CALIBRATION_BOX rendered at the default DPI (96) is 423x458
 1368                     DPIScaleFactorX = (double) trec.right / 423;
 1369                     DPIScaleFactorY = (double) trec.bottom / 458;
 1370                     DlgAspectRatio = DPIScaleFactorX / DPIScaleFactorY;
 1371                 }
 1372             }
 1373 
 1374             EndDialog (hwndDlg, 0);
 1375             return 1;
 1376         }
 1377 
 1378     case WM_CLOSE:
 1379         EndDialog (hwndDlg, 0);
 1380         return 1;
 1381     }
 1382 
 1383     return 0;
 1384 }
 1385 
 1386 
 1387 /* Except in response to the WM_INITDIALOG message, the dialog box procedure
 1388    should return nonzero if it processes the message, and zero if it does
 1389    not. - see DialogProc */
 1390 BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 1391 {
 1392     WORD lw = LOWORD (wParam);
 1393     static HBITMAP hbmTextualLogoBitmapRescaled = NULL;
 1394 
 1395     switch (msg)
 1396     {
 1397     case WM_INITDIALOG:
 1398         {
 1399             wchar_t szTmp[100];
 1400             RECT rec;
 1401 
 1402             LocalizeDialog (hwndDlg, "IDD_ABOUT_DLG");
 1403 
 1404             // Hyperlink
 1405             SetWindowText (GetDlgItem (hwndDlg, IDC_HOMEPAGE), L"www.idrix.fr");
 1406             ToHyperlink (hwndDlg, IDC_HOMEPAGE);
 1407 
 1408             // Logo area background (must not keep aspect ratio; must retain Windows-imposed distortion)
 1409             GetClientRect (GetDlgItem (hwndDlg, IDC_ABOUT_LOGO_AREA), &rec);
 1410             SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, rec.right, rec.bottom, SWP_NOMOVE);
 1411 
 1412             // Resize the logo bitmap if the user has a non-default DPI 
 1413             if (ScreenDPI != USER_DEFAULT_SCREEN_DPI)
 1414             {
 1415                 // Logo (must recreate and keep the original aspect ratio as Windows distorts it)
 1416                 hbmTextualLogoBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_TEXTUAL_LOGO_288DPI),
 1417                     GetDlgItem (hwndDlg, IDC_TEXTUAL_LOGO_IMG),
 1418                     0, 0, 0, 0, FALSE, TRUE);
 1419 
 1420                 SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 1421             }
 1422 
 1423             // Version
 1424             SendMessage (GetDlgItem (hwndDlg, IDT_ABOUT_VERSION), WM_SETFONT, (WPARAM) hUserBoldFont, 0);
 1425             StringCbPrintfW (szTmp, sizeof(szTmp), L"VeraCrypt %s", _T(VERSION_STRING));
 1426 #ifdef _WIN64
 1427             StringCbCatW (szTmp, sizeof(szTmp), L"  (64-bit)");
 1428 #else
 1429             StringCbCatW (szTmp, sizeof(szTmp), L"  (32-bit)");
 1430 #endif
 1431 #if (defined(_DEBUG) || defined(DEBUG))
 1432             StringCbCatW (szTmp, sizeof(szTmp), L"  (debug)");
 1433 #endif
 1434             SetDlgItemText (hwndDlg, IDT_ABOUT_VERSION, szTmp);
 1435             SetDlgItemText (hwndDlg, IDT_ABOUT_RELEASE, TC_STR_RELEASED_BY);
 1436 
 1437             // Credits
 1438             SendMessage (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS), WM_SETFONT, (WPARAM) hUserFont, (LPARAM) 0);
 1439             SendMessage (hwndDlg, WM_APP, 0, 0);
 1440             return 1;
 1441         }
 1442 
 1443     case WM_APP:
 1444         SetWindowText (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS),
 1445             L"Based on TrueCrypt 7.1a, freely available at http://www.truecrypt.org/ .\r\n\r\n"
 1446 
 1447             L"Portions of this software:\r\n"
 1448             L"Copyright \xA9 2013-2018 IDRIX. All rights reserved.\r\n"
 1449             L"Copyright \xA9 2003-2012 TrueCrypt Developers Association. All Rights Reserved.\r\n"
 1450             L"Copyright \xA9 1998-2000 Paul Le Roux. All Rights Reserved.\r\n"
 1451             L"Copyright \xA9 1998-2008 Brian Gladman. All Rights Reserved.\r\n"
 1452             L"Copyright \xA9 1995-2017 Jean-loup Gailly and Mark Adler.\r\n"
 1453             L"Copyright \xA9 2016 Disk Cryptography Services for EFI (DCS), Alex Kolotnikov.\r\n"
 1454             L"Copyright \xA9 1999-2017 Dieter Baron and Thomas Klausner.\r\n"
 1455             L"Copyright \xA9 2013, Alexey Degtyarev. All rights reserved.\r\n"
 1456             L"Copyright \xA9 1999-2016 Jack Lloyd. All rights reserved.\r\n\r\n"
 1457 
 1458             L"This software as a whole:\r\n"
 1459             L"Copyright \xA9 2013-2018 IDRIX. All rights reserved.\r\n\r\n"
 1460 
 1461             L"An IDRIX Release");
 1462 
 1463         return 1;
 1464 
 1465     case WM_COMMAND:
 1466         if (lw == IDOK || lw == IDCANCEL)
 1467         {
 1468             PostMessage (hwndDlg, WM_CLOSE, 0, 0);
 1469             return 1;
 1470         }
 1471 
 1472         if (lw == IDC_HOMEPAGE)
 1473         {
 1474             Applink ("main");
 1475             return 1;
 1476         }
 1477 
 1478         // Disallow modification of credits
 1479         if (HIWORD (wParam) == EN_UPDATE)
 1480         {
 1481             SendMessage (hwndDlg, WM_APP, 0, 0);
 1482             return 1;
 1483         }
 1484 
 1485         return 0;
 1486 
 1487     case WM_CLOSE:
 1488         /* Delete buffered bitmaps (if any) */
 1489         if (hbmTextualLogoBitmapRescaled != NULL)
 1490         {
 1491             DeleteObject ((HGDIOBJ) hbmTextualLogoBitmapRescaled);
 1492             hbmTextualLogoBitmapRescaled = NULL;
 1493         }
 1494 
 1495         EndDialog (hwndDlg, 0);
 1496         return 1;
 1497     }
 1498 
 1499     return 0;
 1500 }
 1501 
 1502 
 1503 static HWND StaticModelessWaitDlgHandle = NULL;
 1504 
 1505 // Call DisplayStaticModelessWaitDlg() to open this dialog and CloseStaticModelessWaitDlg() to close it.
 1506 static BOOL CALLBACK StaticModelessWaitDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 1507 {
 1508     WORD lw = LOWORD (wParam);
 1509 
 1510     switch (msg)
 1511     {
 1512     case WM_INITDIALOG:
 1513         {
 1514             LocalizeDialog (hwndDlg, NULL);
 1515 
 1516             return 0;
 1517         }
 1518 
 1519     case WM_COMMAND:
 1520 
 1521         if (lw == IDOK || lw == IDCANCEL)
 1522             return 1;
 1523 
 1524         return 0;
 1525 
 1526 
 1527     case WM_CLOSE:
 1528         StaticModelessWaitDlgHandle = NULL;
 1529         EndDialog (hwndDlg, 0);
 1530         return 1;
 1531     }
 1532 
 1533     return 0;
 1534 }
 1535 
 1536 
 1537 // Opens a dialog window saying "Please wait..." which is not modal and does not need any GUI refresh after initialization.
 1538 void DisplayStaticModelessWaitDlg (HWND parent)
 1539 {
 1540     if (StaticModelessWaitDlgHandle != NULL)
 1541         return; // Already shown
 1542 
 1543     StaticModelessWaitDlgHandle = CreateDialogParamW (hInst, MAKEINTRESOURCEW (IDD_STATIC_MODELESS_WAIT_DLG), parent, (DLGPROC) StaticModelessWaitDlgProc, (LPARAM) 0);
 1544 
 1545     ShowWindow (StaticModelessWaitDlgHandle, SW_SHOWNORMAL);
 1546 
 1547     // Allow synchronous use with the GUI being instantly and fully rendered
 1548     ProcessPaintMessages (StaticModelessWaitDlgHandle, 500);
 1549 }
 1550 
 1551 
 1552 void CloseStaticModelessWaitDlg (void)
 1553 {
 1554     if (StaticModelessWaitDlgHandle == NULL)
 1555         return; // Not shown
 1556 
 1557     DestroyWindow (StaticModelessWaitDlgHandle);
 1558 }
 1559 
 1560 
 1561 BOOL IsButtonChecked (HWND hButton)
 1562 {
 1563     if (SendMessage (hButton, BM_GETCHECK, 0, 0) == BST_CHECKED)
 1564         return TRUE;
 1565     else
 1566         return FALSE;
 1567 }
 1568 
 1569 
 1570 void CheckButton (HWND hButton)
 1571 {
 1572     SendMessage (hButton, BM_SETCHECK, BST_CHECKED, 0);
 1573 }
 1574 
 1575 
 1576 void LeftPadString (wchar_t *szTmp, int len, int targetLen, wchar_t filler)
 1577 {
 1578     int i;
 1579 
 1580     if (targetLen <= len)
 1581         return;
 1582 
 1583     for (i = targetLen-1; i >= (targetLen-len); i--)
 1584         szTmp [i] = szTmp [i-(targetLen-len)];
 1585 
 1586     wmemset (szTmp, filler, targetLen-len);
 1587     szTmp [targetLen] = 0;
 1588 }
 1589 
 1590 /* InitDialog - initialize the applications main dialog, this function should
 1591    be called only once in the dialogs WM_INITDIALOG message handler */
 1592 void InitDialog (HWND hwndDlg)
 1593 {
 1594     NONCLIENTMETRICSW metric;
 1595     static BOOL aboutMenuAppended = FALSE;
 1596 
 1597     int nHeight;
 1598     LOGFONTW lf;
 1599     HMENU hMenu;
 1600     Font *font;
 1601 
 1602     /* Fonts */
 1603 
 1604     memset (&lf, 0, sizeof(lf));
 1605 
 1606     // Normal
 1607     font = GetFont ("font_normal");
 1608 
 1609     metric.cbSize = sizeof (metric);
 1610     SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(metric), &metric, 0);
 1611 
 1612     WindowTitleBarFont = CreateFontIndirectW (&metric.lfCaptionFont);
 1613 
 1614     metric.lfMessageFont.lfHeight = CompensateDPIFont (!font ? -11 : -font->Size);
 1615     metric.lfMessageFont.lfWidth = 0;
 1616 
 1617     if (font && wcscmp (font->FaceName, L"default") != 0)
 1618     {
 1619         StringCbCopyW ((WCHAR *)metric.lfMessageFont.lfFaceName, sizeof (metric.lfMessageFont.lfFaceName), font->FaceName);
 1620     }
 1621     else if (IsOSAtLeast (WIN_VISTA))
 1622     {
 1623         // Vista's new default font (size and spacing) breaks compatibility with Windows 2k/XP applications.
 1624         // Force use of Tahoma (as Microsoft does in many dialogs) until a native Vista look is implemented.
 1625         StringCbCopyW ((WCHAR *)metric.lfMessageFont.lfFaceName, sizeof (metric.lfMessageFont.lfFaceName), L"Tahoma");
 1626     }
 1627 
 1628     hUserFont = CreateFontIndirectW (&metric.lfMessageFont);
 1629 
 1630     metric.lfMessageFont.lfUnderline = TRUE;
 1631     hUserUnderlineFont = CreateFontIndirectW (&metric.lfMessageFont);
 1632 
 1633     metric.lfMessageFont.lfUnderline = FALSE;
 1634     metric.lfMessageFont.lfWeight = FW_BOLD;
 1635     hUserBoldFont = CreateFontIndirectW (&metric.lfMessageFont);
 1636 
 1637     metric.lfMessageFont.lfUnderline = TRUE;
 1638     metric.lfMessageFont.lfWeight = FW_BOLD;
 1639     hUserUnderlineBoldFont = CreateFontIndirectW (&metric.lfMessageFont);
 1640 
 1641     // Fixed-size (hexadecimal digits)
 1642     nHeight = CompensateDPIFont (-12);
 1643     lf.lfHeight = nHeight;
 1644     lf.lfWidth = 0;
 1645     lf.lfEscapement = 0;
 1646     lf.lfOrientation = 0;
 1647     lf.lfWeight = FW_NORMAL;
 1648     lf.lfItalic = FALSE;
 1649     lf.lfUnderline = FALSE;
 1650     lf.lfStrikeOut = FALSE;
 1651     lf.lfCharSet = DEFAULT_CHARSET;
 1652     lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
 1653     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
 1654     lf.lfQuality = PROOF_QUALITY;
 1655     lf.lfPitchAndFamily = FF_DONTCARE;
 1656     StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName), L"Courier New");
 1657     hFixedDigitFont = CreateFontIndirectW (&lf);
 1658     if (hFixedDigitFont == NULL)
 1659     {
 1660         handleWin32Error (hwndDlg, SRC_POS);
 1661         AbortProcess ("NOFONT");
 1662     }
 1663 
 1664     // Bold
 1665     font = GetFont ("font_bold");
 1666 
 1667     nHeight = CompensateDPIFont (!font ? -13 : -font->Size);
 1668     lf.lfHeight = nHeight;
 1669     lf.lfWeight = FW_BLACK;
 1670     StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName), !font ? L"Arial" : font->FaceName);
 1671     hBoldFont = CreateFontIndirectW (&lf);
 1672     if (hBoldFont == NULL)
 1673     {
 1674         handleWin32Error (hwndDlg, SRC_POS);
 1675         AbortProcess ("NOFONT");
 1676     }
 1677 
 1678     // Title
 1679     font = GetFont ("font_title");
 1680 
 1681     nHeight = CompensateDPIFont (!font ? -21 : -font->Size);
 1682     lf.lfHeight = nHeight;
 1683     lf.lfWeight = FW_REGULAR;
 1684     StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName),!font ? L"Times New Roman" : font->FaceName);
 1685     hTitleFont = CreateFontIndirectW (&lf);
 1686     if (hTitleFont == NULL)
 1687     {
 1688         handleWin32Error (hwndDlg, SRC_POS);
 1689         AbortProcess ("NOFONT");
 1690     }
 1691 
 1692     // Fixed-size
 1693     font = GetFont ("font_fixed");
 1694 
 1695     nHeight = CompensateDPIFont (!font ? -12 : -font->Size);
 1696     lf.lfHeight = nHeight;
 1697     lf.lfWidth = 0;
 1698     lf.lfEscapement = 0;
 1699     lf.lfOrientation = 0;
 1700     lf.lfWeight = FW_NORMAL;
 1701     lf.lfItalic = FALSE;
 1702     lf.lfUnderline = FALSE;
 1703     lf.lfStrikeOut = FALSE;
 1704     lf.lfCharSet = DEFAULT_CHARSET;
 1705     lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
 1706     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
 1707     lf.lfQuality = PROOF_QUALITY;
 1708     lf.lfPitchAndFamily = FF_DONTCARE;
 1709     StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName),!font ? L"Lucida Console" : font->FaceName);
 1710     hFixedFont = CreateFontIndirectW (&lf);
 1711     if (hFixedFont == NULL)
 1712     {
 1713         handleWin32Error (hwndDlg, SRC_POS);
 1714         AbortProcess ("NOFONT");
 1715     }
 1716 
 1717     if (!aboutMenuAppended)
 1718     {
 1719         hMenu = GetSystemMenu (hwndDlg, FALSE);
 1720         AppendMenu (hMenu, MF_SEPARATOR, 0, L"");
 1721         AppendMenuW (hMenu, MF_ENABLED | MF_STRING, IDC_ABOUT, GetString ("ABOUTBOX"));
 1722 
 1723         aboutMenuAppended = TRUE;
 1724     }
 1725 }
 1726 
 1727 
 1728 // The parameter maxMessagesToProcess prevents endless processing of paint messages
 1729 void ProcessPaintMessages (HWND hwnd, int maxMessagesToProcess)
 1730 {
 1731     MSG paintMsg;
 1732     int msgCounter = maxMessagesToProcess;  
 1733 
 1734     while (PeekMessageW (&paintMsg, hwnd, 0, 0, PM_REMOVE | PM_QS_PAINT) != 0 && msgCounter-- > 0)
 1735     {
 1736         DispatchMessageW (&paintMsg);
 1737     }
 1738 }
 1739 
 1740 
 1741 HDC CreateMemBitmap (HINSTANCE hInstance, HWND hwnd, wchar_t *resource)
 1742 {
 1743     HBITMAP picture = LoadBitmap (hInstance, resource);
 1744     HDC viewDC = GetDC (hwnd), dcMem;
 1745 
 1746     dcMem = CreateCompatibleDC (viewDC);
 1747 
 1748     SetMapMode (dcMem, MM_TEXT);
 1749 
 1750     SelectObject (dcMem, picture);
 1751 
 1752     DeleteObject (picture);
 1753 
 1754     ReleaseDC (hwnd, viewDC);
 1755 
 1756     return dcMem;
 1757 }
 1758 
 1759 
 1760 /* Renders the specified bitmap at the specified location and stretches it to fit (anti-aliasing is applied). 
 1761 If bDirectRender is FALSE and both nWidth and nHeight are zero, the width and height of hwndDest are
 1762 retrieved and adjusted according to screen DPI (the width and height of the resultant image are adjusted the
 1763 same way); furthermore, if bKeepAspectRatio is TRUE, the smaller DPI factor of the two (i.e. horiz. or vert.)
 1764 is used both for horiz. and vert. scaling (note that the overall GUI aspect ratio changes irregularly in
 1765 both directions depending on the DPI). If bDirectRender is TRUE, bKeepAspectRatio is ignored. 
 1766 This function returns a handle to the scaled bitmap. When the bitmap is no longer needed, it should be
 1767 deleted by calling DeleteObject() with the handle passed as the parameter. 
 1768 Known Windows issues: 
 1769 - For some reason, anti-aliasing is not applied if the source bitmap contains less than 16K pixels. 
 1770 - Windows 2000 may produce slightly inaccurate colors even when source, buffer, and target are 24-bit true color. */
 1771 HBITMAP RenderBitmap (wchar_t *resource, HWND hwndDest, int x, int y, int nWidth, int nHeight, BOOL bDirectRender, BOOL bKeepAspectRatio)
 1772 {
 1773     LRESULT lResult = 0;
 1774 
 1775     HDC hdcSrc = CreateMemBitmap (hInst, hwndDest, resource);
 1776     if (!hdcSrc)
 1777         return NULL;
 1778 
 1779     HGDIOBJ picture = GetCurrentObject (hdcSrc, OBJ_BITMAP);
 1780 
 1781     HBITMAP hbmpRescaled = NULL;
 1782     BITMAP bitmap;
 1783 
 1784     HDC hdcRescaled;
 1785 
 1786     if (!bDirectRender && nWidth == 0 && nHeight == 0)
 1787     {
 1788         RECT rec;
 1789 
 1790         GetClientRect (hwndDest, &rec);
 1791 
 1792         if (bKeepAspectRatio)
 1793         {
 1794             if (DlgAspectRatio > 1)
 1795             {
 1796                 // Do not fix this, it's correct. We use the Y scale factor intentionally for both
 1797                 // directions to maintain aspect ratio (see above for more info).
 1798                 nWidth = CompensateYDPI (rec.right);
 1799                 nHeight = CompensateYDPI (rec.bottom);
 1800             }
 1801             else
 1802             {
 1803                 // Do not fix this, it's correct. We use the X scale factor intentionally for both
 1804                 // directions to maintain aspect ratio (see above for more info).
 1805                 nWidth = CompensateXDPI (rec.right);
 1806                 nHeight = CompensateXDPI (rec.bottom);
 1807             }
 1808         }
 1809         else
 1810         {
 1811             nWidth = CompensateXDPI (rec.right);
 1812             nHeight = CompensateYDPI (rec.bottom);
 1813         }
 1814     }
 1815 
 1816     GetObject (picture, sizeof (BITMAP), &bitmap);
 1817 
 1818     hdcRescaled = CreateCompatibleDC (hdcSrc); 
 1819 
 1820     if (hdcRescaled)
 1821     {
 1822         hbmpRescaled = CreateCompatibleBitmap (hdcSrc, nWidth, nHeight); 
 1823 
 1824         SelectObject (hdcRescaled, hbmpRescaled);
 1825 
 1826         /* Anti-aliasing mode (HALFTONE is the only anti-aliasing algorithm natively supported by Windows 2000.
 1827         TODO: GDI+ offers higher quality -- InterpolationModeHighQualityBicubic) */
 1828         SetStretchBltMode (hdcRescaled, HALFTONE);
 1829 
 1830         StretchBlt (hdcRescaled,
 1831             0,
 1832             0,
 1833             nWidth,
 1834             nHeight,
 1835             hdcSrc,
 1836             0,
 1837             0,
 1838             bitmap.bmWidth, 
 1839             bitmap.bmHeight,
 1840             SRCCOPY);
 1841 
 1842         DeleteDC (hdcSrc);
 1843 
 1844         if (bDirectRender)
 1845         {
 1846             HDC hdcDest = GetDC (hwndDest);
 1847             if (hdcDest)
 1848             {
 1849                 BitBlt (hdcDest, x, y, nWidth, nHeight, hdcRescaled, 0, 0, SRCCOPY);
 1850                 ReleaseDC (hwndDest, hdcDest);
 1851             }
 1852         }
 1853         else
 1854         {
 1855             lResult = SendMessage (hwndDest, (UINT) STM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) (HANDLE) hbmpRescaled);
 1856         }
 1857 
 1858         if ((HGDIOBJ) lResult != NULL && (HGDIOBJ) lResult != (HGDIOBJ) hbmpRescaled)
 1859             DeleteObject ((HGDIOBJ) lResult);
 1860 
 1861         DeleteDC (hdcRescaled);
 1862     }
 1863 
 1864     return hbmpRescaled;
 1865 }
 1866 
 1867 
 1868 LRESULT CALLBACK
 1869 RedTick (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 1870 {
 1871     if (uMsg == WM_CREATE)
 1872     {
 1873     }
 1874     else if (uMsg == WM_DESTROY)
 1875     {
 1876     }
 1877     else if (uMsg == WM_TIMER)
 1878     {
 1879     }
 1880     else if (uMsg == WM_PAINT)
 1881     {
 1882         PAINTSTRUCT tmp;
 1883         HPEN hPen;
 1884         HDC hDC;
 1885         BOOL bEndPaint;
 1886         RECT Rect;
 1887 
 1888         if (GetUpdateRect (hwnd, NULL, FALSE))
 1889         {
 1890             hDC = BeginPaint (hwnd, &tmp);
 1891             bEndPaint = TRUE;
 1892             if (hDC == NULL)
 1893                 return DefWindowProcW (hwnd, uMsg, wParam, lParam);
 1894         }
 1895         else
 1896         {
 1897             hDC = GetDC (hwnd);
 1898             bEndPaint = FALSE;
 1899         }
 1900 
 1901         GetClientRect (hwnd, &Rect);
 1902 
 1903         hPen = CreatePen (PS_SOLID, 2, RGB (0, 255, 0));
 1904         if (hPen != NULL)
 1905         {
 1906             HGDIOBJ hObj = SelectObject (hDC, hPen);
 1907             WORD bx = LOWORD (GetDialogBaseUnits ());
 1908             WORD by = HIWORD (GetDialogBaseUnits ());
 1909 
 1910             MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL);
 1911             LineTo (hDC, Rect.right, Rect.top);
 1912             MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL);
 1913 
 1914             LineTo (hDC, (3 * bx) / 4, (2 * by) / 8);
 1915 
 1916             SelectObject (hDC, hObj);
 1917             DeleteObject (hPen);
 1918         }
 1919 
 1920         if (bEndPaint)
 1921             EndPaint (hwnd, &tmp);
 1922         else
 1923             ReleaseDC (hwnd, hDC);
 1924 
 1925         return TRUE;
 1926     }
 1927 
 1928     return DefWindowProcW (hwnd, uMsg, wParam, lParam);
 1929 }
 1930 
 1931 BOOL
 1932 RegisterRedTick (HINSTANCE hInstance)
 1933 {
 1934   WNDCLASSW wc;
 1935   ULONG rc;
 1936 
 1937   memset(&wc, 0 , sizeof wc);
 1938 
 1939   wc.style = CS_HREDRAW | CS_VREDRAW;
 1940   wc.cbClsExtra = 0;
 1941   wc.cbWndExtra = 4;
 1942   wc.hInstance = hInstance;
 1943   wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
 1944   wc.hCursor = NULL;
 1945   wc.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH);
 1946   wc.lpszClassName = L"VCREDTICK";
 1947   wc.lpfnWndProc = &RedTick; 
 1948   
 1949   rc = (ULONG) RegisterClassW (&wc);
 1950 
 1951   return rc == 0 ? FALSE : TRUE;
 1952 }
 1953 
 1954 BOOL
 1955 UnregisterRedTick (HINSTANCE hInstance)
 1956 {
 1957   return UnregisterClassW (L"VCREDTICK", hInstance);
 1958 }
 1959 
 1960 LRESULT CALLBACK
 1961 SplashDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 1962 {
 1963     return DefDlgProcW (hwnd, uMsg, wParam, lParam);
 1964 }
 1965 
 1966 static int g_waitCursorCounter = 0;
 1967 
 1968 void
 1969 WaitCursor ()
 1970 {
 1971     static HCURSOR hcWait = NULL;
 1972     if (hcWait == NULL)
 1973         hcWait = LoadCursor (NULL, IDC_WAIT);
 1974 
 1975     if ((g_waitCursorCounter == 0) || (hCursor != hcWait))
 1976     {
 1977         if (!Silent) SetCursor (hcWait);
 1978         hCursor = hcWait;
 1979     }
 1980     g_waitCursorCounter++;
 1981 }
 1982 
 1983 void
 1984 NormalCursor ()
 1985 {
 1986     static HCURSOR hcArrow = NULL;
 1987     if (hcArrow == NULL)
 1988         hcArrow = LoadCursor (NULL, IDC_ARROW);
 1989     if (g_waitCursorCounter > 0)
 1990         g_waitCursorCounter--;
 1991     if (g_waitCursorCounter == 0)
 1992     {
 1993         if (!Silent) SetCursor (hcArrow);
 1994         hCursor = NULL;
 1995     }
 1996 }
 1997 
 1998 void
 1999 ArrowWaitCursor ()
 2000 {
 2001     static HCURSOR hcArrowWait = NULL;
 2002     if (hcArrowWait == NULL)
 2003         hcArrowWait = LoadCursor (NULL, IDC_APPSTARTING);
 2004     if ((g_waitCursorCounter == 0) || (hCursor != hcArrowWait))
 2005     {
 2006         if (!Silent) SetCursor (hcArrowWait);
 2007         hCursor = hcArrowWait;
 2008     }
 2009     g_waitCursorCounter++;
 2010 }
 2011 
 2012 void HandCursor ()
 2013 {
 2014     static HCURSOR hcHand = NULL;
 2015     if (hcHand == NULL)
 2016         hcHand = LoadCursor (NULL, IDC_HAND);
 2017     SetCursor (hcHand);
 2018     hCursor = hcHand;
 2019 }
 2020 
 2021 void
 2022 AddComboPair (HWND hComboBox, const wchar_t *lpszItem, int value)
 2023 {
 2024     LPARAM nIndex;
 2025 
 2026     nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) lpszItem);
 2027     nIndex = SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) value);
 2028 }
 2029 
 2030 void
 2031 SelectAlgo (HWND hComboBox, int *algo_id)
 2032 {
 2033     LPARAM nCount = SendMessage (hComboBox, CB_GETCOUNT, 0, 0);
 2034     LPARAM x, i;
 2035 
 2036     for (i = 0; i < nCount; i++)
 2037     {
 2038         x = SendMessage (hComboBox, CB_GETITEMDATA, i, 0);
 2039         if (x == (LPARAM) *algo_id)
 2040         {
 2041             SendMessage (hComboBox, CB_SETCURSEL, i, 0);
 2042             return;
 2043         }
 2044     }
 2045 
 2046     /* Something went wrong ; couldn't find the requested algo id so we drop
 2047        back to a default */
 2048 
 2049     *algo_id = (int) SendMessage (hComboBox, CB_GETITEMDATA, 0, 0);
 2050 
 2051     SendMessage (hComboBox, CB_SETCURSEL, 0, 0);
 2052 
 2053 }
 2054 
 2055 void PopulateWipeModeCombo (HWND hComboBox, BOOL bNA, BOOL bInPlaceEncryption, BOOL bHeaderWipe)
 2056 {
 2057     if (bNA)
 2058     {
 2059         AddComboPair (hComboBox, GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"), TC_WIPE_NONE);
 2060     }
 2061     else
 2062     {
 2063         if (!bHeaderWipe)
 2064         {
 2065             AddComboPair (hComboBox, GetString ("WIPE_MODE_NONE"), TC_WIPE_NONE);               
 2066         }
 2067 
 2068         AddComboPair (hComboBox, GetString ("WIPE_MODE_1_RAND"), TC_WIPE_1_RAND);
 2069         AddComboPair (hComboBox, GetString ("WIPE_MODE_3_DOD_5220"), TC_WIPE_3_DOD_5220);
 2070         AddComboPair (hComboBox, GetString ("WIPE_MODE_7_DOD_5220"), TC_WIPE_7_DOD_5220);
 2071         AddComboPair (hComboBox, GetString ("WIPE_MODE_35_GUTMANN"), TC_WIPE_35_GUTMANN);
 2072 
 2073         if (bHeaderWipe)
 2074             AddComboPair (hComboBox, GetString ("WIPE_MODE_256"), TC_WIPE_256); // paranoid wipe for volume header
 2075     }
 2076 }
 2077 
 2078 wchar_t *GetWipeModeName (WipeAlgorithmId modeId)
 2079 {
 2080     switch (modeId)
 2081     {
 2082     case TC_WIPE_NONE:
 2083         return GetString ("WIPE_MODE_NONE");
 2084 
 2085     case TC_WIPE_1_RAND:
 2086         return GetString ("WIPE_MODE_1_RAND");
 2087 
 2088     case TC_WIPE_3_DOD_5220:
 2089         return GetString ("WIPE_MODE_3_DOD_5220");
 2090 
 2091     case TC_WIPE_7_DOD_5220:
 2092         return GetString ("WIPE_MODE_7_DOD_5220");
 2093 
 2094     case TC_WIPE_35_GUTMANN:
 2095         return GetString ("WIPE_MODE_35_GUTMANN");
 2096 
 2097     case TC_WIPE_256:
 2098         return GetString ("WIPE_MODE_256");
 2099 
 2100     default:
 2101         return GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE");
 2102     }
 2103 }
 2104 
 2105 wchar_t *GetPathType (const wchar_t *path, BOOL bUpperCase, BOOL *bIsPartition)
 2106 {
 2107     if (wcsstr (path, L"Partition")
 2108         && wcsstr (path, L"Partition0") == NULL)
 2109     {
 2110         *bIsPartition = TRUE;
 2111         return GetString (bUpperCase ? "PARTITION_UPPER_CASE" : "PARTITION_LOWER_CASE");
 2112     }
 2113     else if (wcsstr (path, L"HarddiskVolume"))
 2114     {
 2115         *bIsPartition = TRUE;
 2116         return GetString (bUpperCase ? "VOLUME_UPPER_CASE" : "VOLUME_LOWER_CASE");
 2117     }
 2118 
 2119     *bIsPartition = FALSE;
 2120     return GetString (bUpperCase ? "DEVICE_UPPER_CASE" : "DEVICE_LOWER_CASE");
 2121 }
 2122 
 2123 LRESULT CALLBACK CustomDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 2124 {
 2125     if (uMsg == WM_SETCURSOR && hCursor != NULL)
 2126     {
 2127         SetCursor (hCursor);
 2128         return TRUE;
 2129     }
 2130 
 2131     return DefDlgProcW (hwnd, uMsg, wParam, lParam);
 2132 }
 2133 
 2134 /*
 2135 static BOOL IsReturnAddress (DWORD64 address)
 2136 {
 2137     static size_t codeEnd = 0;
 2138     byte *sp = (byte *) address;
 2139 
 2140     if (codeEnd == 0)
 2141     {
 2142         MEMORY_BASIC_INFORMATION mi;
 2143         if (VirtualQuery ((LPCVOID) 0x401000, &mi, sizeof (mi)) >= sizeof (mi))
 2144             codeEnd = (size_t) mi.BaseAddress + mi.RegionSize;
 2145     }
 2146 
 2147     if (address < 0x401000 + 8 || address > codeEnd)
 2148         return FALSE;
 2149 
 2150     return sp[-5] == 0xe8                                   // call ADDR
 2151         || (sp[-6] == 0xff && sp[-5] == 0x15)               // call [ADDR]
 2152         || (sp[-2] == 0xff && (sp[-1] & 0xf0) == 0xd0);     // call REG
 2153 }
 2154 */
 2155 
 2156 typedef struct
 2157 {
 2158     EXCEPTION_POINTERS *ExceptionPointers;
 2159     HANDLE ExceptionThread;
 2160 
 2161 } ExceptionHandlerThreadArgs;
 2162 
 2163 
 2164 void ExceptionHandlerThread (void *threadArg)
 2165 {
 2166     ExceptionHandlerThreadArgs *args = (ExceptionHandlerThreadArgs *) threadArg;
 2167 
 2168     EXCEPTION_POINTERS *ep = args->ExceptionPointers;
 2169     //DWORD addr;
 2170     DWORD exCode = ep->ExceptionRecord->ExceptionCode;
 2171     // SYSTEM_INFO si;
 2172     // wchar_t msg[8192];
 2173     // char modPath[MAX_PATH];
 2174     // int crc = 0;
 2175     // char url[MAX_URL_LENGTH];
 2176     // char lpack[128];
 2177     // stringstream callStack;
 2178     // addr = (DWORD) ep->ExceptionRecord->ExceptionAddress;
 2179     // PDWORD sp = (PDWORD) ep->ContextRecord->Esp;
 2180     // int frameNumber = 0;
 2181 
 2182     switch (exCode)
 2183     {
 2184     case STATUS_IN_PAGE_ERROR:
 2185     case 0xeedfade:
 2186         // Exception not caused by VeraCrypt
 2187         MessageBoxW (0, GetString ("EXCEPTION_REPORT_EXT"),
 2188             GetString ("EXCEPTION_REPORT_TITLE"),
 2189             MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
 2190         return;
 2191     }
 2192 
 2193     // Call stack
 2194 /*  HMODULE dbgDll = LoadLibrary ("dbghelp.dll");
 2195     if (dbgDll)
 2196     {
 2197         typedef DWORD (__stdcall *SymGetOptions_t) ();
 2198         typedef DWORD (__stdcall *SymSetOptions_t) (DWORD SymOptions);
 2199         typedef BOOL (__stdcall *SymInitialize_t) (HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess);
 2200         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);
 2201         typedef BOOL (__stdcall * SymFromAddr_t) (HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol);
 2202 
 2203         SymGetOptions_t DbgHelpSymGetOptions = (SymGetOptions_t) GetProcAddress (dbgDll, "SymGetOptions");
 2204         SymSetOptions_t DbgHelpSymSetOptions = (SymSetOptions_t) GetProcAddress (dbgDll, "SymSetOptions");
 2205         SymInitialize_t DbgHelpSymInitialize = (SymInitialize_t) GetProcAddress (dbgDll, "SymInitialize");
 2206         PFUNCTION_TABLE_ACCESS_ROUTINE64 DbgHelpSymFunctionTableAccess64 = (PFUNCTION_TABLE_ACCESS_ROUTINE64) GetProcAddress (dbgDll, "SymFunctionTableAccess64");
 2207         PGET_MODULE_BASE_ROUTINE64 DbgHelpSymGetModuleBase64 = (PGET_MODULE_BASE_ROUTINE64) GetProcAddress (dbgDll, "SymGetModuleBase64");
 2208         StackWalk64_t DbgHelpStackWalk64 = (StackWalk64_t) GetProcAddress (dbgDll, "StackWalk64");
 2209         SymFromAddr_t DbgHelpSymFromAddr = (SymFromAddr_t) GetProcAddress (dbgDll, "SymFromAddr");
 2210 
 2211         if (DbgHelpSymGetOptions && DbgHelpSymSetOptions && DbgHelpSymInitialize && DbgHelpSymFunctionTableAccess64 && DbgHelpSymGetModuleBase64 && DbgHelpStackWalk64 && DbgHelpSymFromAddr)
 2212         {
 2213             DbgHelpSymSetOptions (DbgHelpSymGetOptions() | SYMOPT_DEFERRED_LOADS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_NO_CPP);
 2214 
 2215             if (DbgHelpSymInitialize (GetCurrentProcess(), NULL, TRUE))
 2216             {
 2217                 STACKFRAME64 frame;
 2218                 memset (&frame, 0, sizeof (frame));
 2219 
 2220                 frame.AddrPC.Offset = ep->ContextRecord->Eip;
 2221                 frame.AddrPC.Mode = AddrModeFlat;
 2222                 frame.AddrStack.Offset = ep->ContextRecord->Esp;
 2223                 frame.AddrStack.Mode = AddrModeFlat;
 2224                 frame.AddrFrame.Offset = ep->ContextRecord->Ebp;
 2225                 frame.AddrFrame.Mode = AddrModeFlat;
 2226 
 2227                 string lastSymbol;
 2228 
 2229                 while (frameNumber < 32 && DbgHelpStackWalk64 (IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), args->ExceptionThread, &frame, ep->ContextRecord, NULL, DbgHelpSymFunctionTableAccess64, DbgHelpSymGetModuleBase64, NULL))
 2230                 {
 2231                     if (!frame.AddrPC.Offset)
 2232                         continue;
 2233 
 2234                     ULONG64 symbolBuffer[(sizeof (SYMBOL_INFO) + MAX_SYM_NAME * sizeof (TCHAR) + sizeof (ULONG64) - 1) / sizeof (ULONG64)];
 2235                     memset (symbolBuffer, 0, sizeof (symbolBuffer));
 2236 
 2237                     PSYMBOL_INFO symbol = (PSYMBOL_INFO) symbolBuffer;
 2238                     symbol->SizeOfStruct = sizeof (SYMBOL_INFO);
 2239                     symbol->MaxNameLen = MAX_SYM_NAME;
 2240 
 2241                     if (DbgHelpSymFromAddr (GetCurrentProcess(), frame.AddrPC.Offset, NULL, symbol) && symbol->NameLen > 0)
 2242                     {
 2243                         for (size_t i = 0; i < symbol->NameLen; ++i)
 2244                         {
 2245                             if (!isalnum (symbol->Name[i]))
 2246                                 symbol->Name[i] = '_';
 2247                         }
 2248 
 2249                         if (symbol->Name != lastSymbol)
 2250                             callStack << "&st" << frameNumber++ << "=" << symbol->Name;
 2251 
 2252                         lastSymbol = symbol->Name;
 2253                     }
 2254                     else if (frameNumber == 0 || IsReturnAddress (frame.AddrPC.Offset))
 2255                     {
 2256                         callStack << "&st" << frameNumber++ << "=0x" << hex << frame.AddrPC.Offset << dec;
 2257                     }
 2258                 }
 2259             }
 2260         }
 2261     }
 2262 
 2263     // StackWalk64() may fail due to missing frame pointers
 2264     list <DWORD> retAddrs;
 2265     if (frameNumber == 0)
 2266         retAddrs.push_back (ep->ContextRecord->Eip);
 2267 
 2268     retAddrs.push_back (0);
 2269 
 2270     MEMORY_BASIC_INFORMATION mi;
 2271     VirtualQuery (sp, &mi, sizeof (mi));
 2272     PDWORD stackTop = (PDWORD)((byte *) mi.BaseAddress + mi.RegionSize);
 2273     int i = 0;
 2274 
 2275     while (retAddrs.size() < 16 && &sp[i] < stackTop)
 2276     {
 2277         if (IsReturnAddress (sp[i]))
 2278         {
 2279             bool duplicate = false;
 2280             foreach (DWORD prevAddr, retAddrs)
 2281             {
 2282                 if (sp[i] == prevAddr)
 2283                 {
 2284                     duplicate = true;
 2285                     break;
 2286                 }
 2287             }
 2288 
 2289             if (!duplicate)
 2290                 retAddrs.push_back (sp[i]);
 2291         }
 2292         i++;
 2293     }
 2294 
 2295     if (retAddrs.size() > 1)
 2296     {
 2297         foreach (DWORD addr, retAddrs)
 2298         {
 2299             callStack << "&st" << frameNumber++ << "=0x" << hex << addr << dec;
 2300         }
 2301     }
 2302 
 2303     // Checksum of the module
 2304     if (GetModuleFileName (NULL, modPath, sizeof (modPath)))
 2305     {
 2306         HANDLE h = CreateFile (modPath, FILE_READ_DATA | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
 2307         if (h != INVALID_HANDLE_VALUE)
 2308         {
 2309             BY_HANDLE_FILE_INFORMATION fi;
 2310             if (GetFileInformationByHandle (h, &fi))
 2311             {
 2312                 char *buf = (char *) malloc (fi.nFileSizeLow);
 2313                 if (buf)
 2314                 {
 2315                     DWORD bytesRead;
 2316                     if (ReadFile (h, buf, fi.nFileSizeLow, &bytesRead, NULL) && bytesRead == fi.nFileSizeLow)
 2317                         crc = GetCrc32 ((unsigned char *) buf, fi.nFileSizeLow);
 2318                     free (buf);
 2319                 }
 2320             }
 2321             CloseHandle (h);
 2322         }
 2323     }
 2324 
 2325     GetSystemInfo (&si);
 2326 
 2327     if (LocalizationActive)
 2328         sprintf_s (lpack, sizeof (lpack), "&langpack=%s_%s", GetPreferredLangId (), GetActiveLangPackVersion ());
 2329     else
 2330         lpack[0] = 0;
 2331 
 2332     
 2333     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"
 2334         , lpack
 2335         , GetWindowsEdition().c_str()
 2336         , CurrentOSMajor
 2337         , CurrentOSMinor
 2338         , CurrentOSServicePack
 2339         , Is64BitOs () ? "x64" : "x86"
 2340         , si.dwNumberOfProcessors
 2341 #ifdef TCMOUNT
 2342         ,"main"
 2343 #endif
 2344 #ifdef VOLFORMAT
 2345         ,"format"
 2346 #endif
 2347 #ifdef SETUP
 2348         ,"setup"
 2349 #endif
 2350         , crc
 2351         , LastDialogId ? LastDialogId : "-"
 2352         , exCode
 2353         , addr);
 2354 
 2355     string urlStr = url + callStack.str();
 2356 
 2357     _snwprintf (msg, array_capacity (msg), GetString ("EXCEPTION_REPORT"), urlStr.c_str());
 2358 
 2359     if (IDYES == MessageBoxW (0, msg, GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1))
 2360         ShellExecute (NULL, "open", urlStr.c_str(), NULL, NULL, SW_SHOWNORMAL);
 2361     else */
 2362         UnhandledExceptionFilter (ep);
 2363 }
 2364 
 2365 
 2366 LONG __stdcall ExceptionHandler (EXCEPTION_POINTERS *ep)
 2367 {
 2368     SetUnhandledExceptionFilter (NULL);
 2369 
 2370     if (SystemFileSelectorCallPending && SystemFileSelectorCallerThreadId == GetCurrentThreadId())
 2371     {
 2372         MessageBoxW (NULL, GetString ("EXCEPTION_REPORT_EXT_FILESEL"), GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
 2373 
 2374         UnhandledExceptionFilter (ep);
 2375         return EXCEPTION_EXECUTE_HANDLER;
 2376     }
 2377 
 2378     ExceptionHandlerThreadArgs args;
 2379     args.ExceptionPointers = ep;
 2380     args.ExceptionThread = GetCurrentThread();
 2381 
 2382     WaitForSingleObject ((HANDLE) _beginthread (ExceptionHandlerThread, 0, &args), INFINITE);
 2383 
 2384     return EXCEPTION_EXECUTE_HANDLER;
 2385 }
 2386 
 2387 
 2388 void InvalidParameterHandler (const wchar_t *expression, const wchar_t *function, const wchar_t *file, unsigned int line, uintptr_t reserved)
 2389 {
 2390     TC_THROW_FATAL_EXCEPTION;
 2391 }
 2392 
 2393 
 2394 static LRESULT CALLBACK NonInstallUacWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 2395 {
 2396     return DefWindowProcW (hWnd, message, wParam, lParam);
 2397 }
 2398 
 2399 BOOL LaunchElevatedProcess (HWND hwndDlg, const wchar_t* szModPath, const wchar_t* args)
 2400 {
 2401     wchar_t newCmdLine[4096];
 2402     WNDCLASSEXW wcex;
 2403     HWND hWnd;
 2404 
 2405     memset (&wcex, 0, sizeof (wcex));
 2406     wcex.cbSize = sizeof(WNDCLASSEX); 
 2407     wcex.lpfnWndProc = (WNDPROC) NonInstallUacWndProc;
 2408     wcex.hInstance = hInst;
 2409     wcex.lpszClassName = L"VeraCrypt";
 2410     RegisterClassExW (&wcex);
 2411 
 2412     // A small transparent window is necessary to bring the new instance to foreground
 2413     hWnd = CreateWindowExW (WS_EX_TOOLWINDOW | WS_EX_LAYERED,
 2414         L"VeraCrypt", L"VeraCrypt", 0,
 2415         GetSystemMetrics (SM_CXSCREEN)/2,
 2416         GetSystemMetrics (SM_CYSCREEN)/2,
 2417         1, 1, NULL, NULL, hInst, NULL);
 2418 
 2419     SetLayeredWindowAttributes (hWnd, 0, 0, LWA_ALPHA);
 2420     ShowWindow (hWnd, SW_SHOWNORMAL);
 2421 
 2422     StringCbCopyW (newCmdLine, sizeof(newCmdLine), L"/q UAC ");
 2423     StringCbCatW (newCmdLine, sizeof (newCmdLine), args);
 2424 
 2425     if ((int)ShellExecuteW (hWnd, L"runas", szModPath, newCmdLine, NULL, SW_SHOWNORMAL) <= 32)
 2426     {
 2427         if (hwndDlg)
 2428             handleWin32Error (hwndDlg, SRC_POS);
 2429         return FALSE;
 2430     }
 2431     else
 2432     {
 2433         Sleep (2000);
 2434         return TRUE;
 2435     }
 2436 }
 2437 
 2438 
 2439 // Mutex handling to prevent multiple instances of the wizard or main app from dealing with system encryption.
 2440 // Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). 
 2441 BOOL CreateSysEncMutex (void)
 2442 {
 2443     return TCCreateMutex (&hSysEncMutex, TC_MUTEX_NAME_SYSENC);
 2444 }
 2445 
 2446 
 2447 BOOL InstanceHasSysEncMutex (void)
 2448 {
 2449     return (hSysEncMutex != NULL);
 2450 }
 2451 
 2452 
 2453 // Mutex handling to prevent multiple instances of the wizard from dealing with system encryption
 2454 void CloseSysEncMutex (void)
 2455 {
 2456     TCCloseMutex (&hSysEncMutex);
 2457 }
 2458 
 2459 
 2460 // Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). 
 2461 BOOL CreateNonSysInplaceEncMutex (void)
 2462 {
 2463     return TCCreateMutex (&hNonSysInplaceEncMutex, TC_MUTEX_NAME_NONSYS_INPLACE_ENC);
 2464 }
 2465 
 2466 
 2467 BOOL InstanceHasNonSysInplaceEncMutex (void)
 2468 {
 2469     return (hNonSysInplaceEncMutex != NULL);
 2470 }
 2471 
 2472 
 2473 void CloseNonSysInplaceEncMutex (void)
 2474 {
 2475     TCCloseMutex (&hNonSysInplaceEncMutex);
 2476 }
 2477 
 2478 
 2479 // Returns TRUE if another instance of the wizard is preparing, resuming or performing non-system in-place encryption
 2480 BOOL NonSysInplaceEncInProgressElsewhere (void)
 2481 {
 2482     return (!InstanceHasNonSysInplaceEncMutex () 
 2483         && MutexExistsOnSystem (TC_MUTEX_NAME_NONSYS_INPLACE_ENC));
 2484 }
 2485 
 2486 
 2487 // Mutex handling to prevent multiple instances of the wizard or main app from trying to install
 2488 // or register the driver or from trying to launch it in portable mode at the same time.
 2489 // Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). 
 2490 BOOL CreateDriverSetupMutex (void)
 2491 {
 2492     return TCCreateMutex (&hDriverSetupMutex, TC_MUTEX_NAME_DRIVER_SETUP);
 2493 }
 2494 
 2495 
 2496 void CloseDriverSetupMutex (void)
 2497 {
 2498     TCCloseMutex (&hDriverSetupMutex);
 2499 }
 2500 
 2501 
 2502 BOOL CreateAppSetupMutex (void)
 2503 {
 2504     return TCCreateMutex (&hAppSetupMutex, TC_MUTEX_NAME_APP_SETUP);
 2505 }
 2506 
 2507 
 2508 void CloseAppSetupMutex (void)
 2509 {
 2510     TCCloseMutex (&hAppSetupMutex);
 2511 }
 2512 
 2513 
 2514 BOOL IsTrueCryptInstallerRunning (void)
 2515 {
 2516     return (MutexExistsOnSystem (TC_MUTEX_NAME_APP_SETUP));
 2517 }
 2518 
 2519 
 2520 // Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). 
 2521 BOOL TCCreateMutex (volatile HANDLE *hMutex, wchar_t *name)
 2522 {
 2523     if (*hMutex != NULL)
 2524         return TRUE;    // This instance already has the mutex
 2525 
 2526     *hMutex = CreateMutex (NULL, TRUE, name);
 2527     if (*hMutex == NULL)
 2528     {
 2529         // In multi-user configurations, the OS returns "Access is denied" here when a user attempts
 2530         // to acquire the mutex if another user already has. However, on Vista, "Access is denied" is
 2531         // returned also if the mutex is owned by a process with admin rights while we have none.
 2532 
 2533         return FALSE;
 2534     }
 2535 
 2536     if (GetLastError () == ERROR_ALREADY_EXISTS)
 2537     {
 2538         ReleaseMutex (*hMutex);
 2539         CloseHandle (*hMutex);
 2540 
 2541         *hMutex = NULL;
 2542         return FALSE;
 2543     }
 2544 
 2545     return TRUE;
 2546 }
 2547 
 2548 
 2549 void TCCloseMutex (volatile HANDLE *hMutex)
 2550 {
 2551     if (*hMutex != NULL)
 2552     {
 2553         if (ReleaseMutex (*hMutex)
 2554             && CloseHandle (*hMutex))
 2555             *hMutex = NULL;
 2556     }
 2557 }
 2558 
 2559 
 2560 // Returns TRUE if a process running on the system has the specified mutex (otherwise FALSE). 
 2561 BOOL MutexExistsOnSystem (wchar_t *name)
 2562 {
 2563     if (name[0] == 0)
 2564         return FALSE;
 2565 
 2566     HANDLE hMutex = OpenMutex (MUTEX_ALL_ACCESS, FALSE, name);
 2567 
 2568     if (hMutex == NULL)
 2569     {
 2570         if (GetLastError () == ERROR_FILE_NOT_FOUND)
 2571             return FALSE;
 2572 
 2573         if (GetLastError () == ERROR_ACCESS_DENIED) // On Vista, this is returned if the owner of the mutex is elevated while we are not
 2574             return TRUE;        
 2575 
 2576         // The call failed and it is not certain whether the mutex exists or not
 2577         return FALSE;
 2578     }
 2579 
 2580     CloseHandle (hMutex);
 2581     return TRUE;
 2582 }
 2583 
 2584 
 2585 uint32 ReadDriverConfigurationFlags ()
 2586 {
 2587     DWORD configMap;
 2588 
 2589     if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", TC_DRIVER_CONFIG_REG_VALUE_NAME, &configMap))
 2590         configMap = 0;
 2591 
 2592     return configMap;
 2593 }
 2594 
 2595 
 2596 uint32 ReadEncryptionThreadPoolFreeCpuCountLimit ()
 2597 {
 2598     DWORD count;
 2599 
 2600     if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", TC_ENCRYPTION_FREE_CPU_COUNT_REG_VALUE_NAME, &count))
 2601         count = 0;
 2602 
 2603     return count;
 2604 }
 2605 
 2606 
 2607 BOOL LoadSysEncSettings ()
 2608 {
 2609     BOOL status = TRUE;
 2610     DWORD size = 0;
 2611     char *sysEncCfgFileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION), &size);
 2612     char *xml = sysEncCfgFileBuf;
 2613     char paramName[100], paramVal[MAX_PATH];
 2614 
 2615     // Defaults
 2616     int newSystemEncryptionStatus = SYSENC_STATUS_NONE;
 2617     WipeAlgorithmId newnWipeMode = TC_WIPE_NONE;
 2618 
 2619     if (!FileExists (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION)))
 2620     {
 2621         SystemEncryptionStatus = newSystemEncryptionStatus;
 2622         nWipeMode = newnWipeMode;
 2623     }
 2624 
 2625     if (xml == NULL)
 2626     {
 2627         return FALSE;
 2628     }
 2629 
 2630     while (xml = XmlFindElement (xml, "config"))
 2631     {
 2632         XmlGetAttributeText (xml, "key", paramName, sizeof (paramName));
 2633         XmlGetNodeText (xml, paramVal, sizeof (paramVal));
 2634 
 2635         if (strcmp (paramName, "SystemEncryptionStatus") == 0)
 2636         {
 2637             newSystemEncryptionStatus = atoi (paramVal);
 2638         }
 2639         else if (strcmp (paramName, "WipeMode") == 0)
 2640         {
 2641             newnWipeMode = (WipeAlgorithmId) atoi (paramVal);
 2642         }
 2643 
 2644         xml++;
 2645     }
 2646 
 2647     SystemEncryptionStatus = newSystemEncryptionStatus;
 2648     nWipeMode = newnWipeMode;
 2649 
 2650     free (sysEncCfgFileBuf);
 2651     return status;
 2652 }
 2653 
 2654 
 2655 // Returns the number of partitions where non-system in-place encryption is progress or had been in progress
 2656 // but was interrupted. In addition, via the passed pointer, returns the last selected wipe algorithm ID.
 2657 int LoadNonSysInPlaceEncSettings (WipeAlgorithmId *wipeAlgorithm)
 2658 {
 2659     char *fileBuf = NULL;
 2660     char *fileBuf2 = NULL;
 2661     DWORD size, size2;
 2662     int count;
 2663 
 2664     *wipeAlgorithm = TC_WIPE_NONE;
 2665 
 2666     if (!FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC)))
 2667         return 0;
 2668 
 2669     if ((fileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), &size)) == NULL)
 2670         return 0;
 2671 
 2672     if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE)))
 2673     {
 2674         if ((fileBuf2 = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE), &size2)) != NULL)
 2675             *wipeAlgorithm = (WipeAlgorithmId) atoi (fileBuf2);
 2676     }
 2677 
 2678     count = atoi (fileBuf);
 2679 
 2680     if (fileBuf != NULL)
 2681         TCfree (fileBuf);
 2682 
 2683     if (fileBuf2 != NULL)
 2684         TCfree (fileBuf2);
 2685 
 2686     return (count);
 2687 }
 2688 
 2689 
 2690 void RemoveNonSysInPlaceEncNotifications (void)
 2691 {
 2692     if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC)))
 2693         _wremove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC));
 2694 
 2695     if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE)))
 2696         _wremove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE));
 2697 
 2698     if (!IsNonInstallMode () && SystemEncryptionStatus == SYSENC_STATUS_NONE)
 2699         ManageStartupSeqWiz (TRUE, L"");
 2700 }
 2701 
 2702 
 2703 void SavePostInstallTasksSettings (int command)
 2704 {
 2705     FILE *f = NULL;
 2706 
 2707     if (IsNonInstallMode() && command != TC_POST_INSTALL_CFG_REMOVE_ALL)
 2708         return;
 2709 
 2710     switch (command)
 2711     {
 2712     case TC_POST_INSTALL_CFG_REMOVE_ALL:
 2713         _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL));
 2714         _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES));
 2715         _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK));
 2716         break;
 2717 
 2718     case TC_POST_INSTALL_CFG_TUTORIAL:
 2719         f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL), L"w");
 2720         break;
 2721 
 2722     case TC_POST_INSTALL_CFG_RELEASE_NOTES:
 2723         f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES), L"w");
 2724         break;
 2725 
 2726     case TC_POST_INSTALL_CFG_RESCUE_DISK:
 2727         f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK), L"w");
 2728         break;
 2729 
 2730     default:
 2731         return;
 2732     }
 2733 
 2734     if (f == NULL)
 2735         return;
 2736 
 2737     if (fputws (L"1", f) < 0)
 2738     {
 2739         // Error
 2740         fclose (f);
 2741         return;
 2742     }
 2743 
 2744     TCFlushFile (f);
 2745 
 2746     fclose (f);
 2747 }
 2748 
 2749 
 2750 void DoPostInstallTasks (HWND hwndDlg)
 2751 {
 2752     BOOL bDone = FALSE;
 2753 
 2754     if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL)))
 2755     {
 2756         if (AskYesNo ("AFTER_INSTALL_TUTORIAL", hwndDlg) == IDYES)
 2757             Applink ("beginnerstutorial");
 2758 
 2759         bDone = TRUE;
 2760     }
 2761 
 2762     if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES)))
 2763     {
 2764         if (AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES", hwndDlg) == IDYES)
 2765             Applink ("releasenotes");
 2766 
 2767         bDone = TRUE;
 2768     }
 2769 
 2770     if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK)))
 2771     {
 2772         if (AskYesNo ("AFTER_UPGRADE_RESCUE_DISK", hwndDlg) == IDYES)
 2773             PostMessage (hwndDlg, VC_APPMSG_CREATE_RESCUE_DISK, 0, 0);
 2774 
 2775         bDone = TRUE;
 2776     }
 2777 
 2778     if (bDone)
 2779         SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_REMOVE_ALL);
 2780 }
 2781 
 2782 /*
 2783  * Use RtlGetVersion to get Windows version because GetVersionEx is affected by application manifestation.
 2784  */
 2785 typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
 2786 
 2787 static BOOL GetWindowsVersion(LPOSVERSIONINFOW lpVersionInformation)
 2788 {
 2789     BOOL bRet = FALSE;
 2790     RtlGetVersionPtr RtlGetVersionFn = (RtlGetVersionPtr) GetProcAddress(GetModuleHandle (L"ntdll.dll"), "RtlGetVersion");
 2791     if (RtlGetVersionFn != NULL)
 2792     {
 2793         if (ERROR_SUCCESS == RtlGetVersionFn (lpVersionInformation))
 2794             bRet = TRUE;
 2795     }
 2796 
 2797     if (!bRet)
 2798         bRet = GetVersionExW (lpVersionInformation);
 2799 
 2800     return bRet;
 2801 }
 2802 
 2803 
 2804 void InitOSVersionInfo ()
 2805 {
 2806     OSVERSIONINFOEXW os;
 2807     os.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
 2808 
 2809     if (GetWindowsVersion ((LPOSVERSIONINFOW) &os) == FALSE)
 2810         AbortProcess ("NO_OS_VER");
 2811 
 2812     CurrentOSMajor = os.dwMajorVersion;
 2813     CurrentOSMinor = os.dwMinorVersion;
 2814     CurrentOSServicePack = os.wServicePackMajor;
 2815     CurrentOSBuildNumber = os.dwBuildNumber;
 2816 
 2817     if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 0)
 2818         nCurrentOS = WIN_2000;
 2819     else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 1)
 2820         nCurrentOS = WIN_XP;
 2821     else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 2)
 2822     {
 2823         if (os.wProductType == VER_NT_SERVER || os.wProductType == VER_NT_DOMAIN_CONTROLLER)
 2824             nCurrentOS = WIN_SERVER_2003;
 2825         else
 2826             nCurrentOS = WIN_XP64;
 2827     }
 2828     else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 0)
 2829     {
 2830         if (os.wProductType !=  VER_NT_WORKSTATION)
 2831             nCurrentOS = WIN_SERVER_2008;
 2832         else
 2833             nCurrentOS = WIN_VISTA;
 2834     }
 2835     else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 1)
 2836         nCurrentOS = ((os.wProductType !=  VER_NT_WORKSTATION) ? WIN_SERVER_2008_R2 : WIN_7);
 2837     else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 2)
 2838         nCurrentOS = ((os.wProductType !=  VER_NT_WORKSTATION) ? WIN_SERVER_2012 : WIN_8);
 2839     else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 3)
 2840         nCurrentOS = ((os.wProductType !=  VER_NT_WORKSTATION) ? WIN_SERVER_2012_R2 : WIN_8_1);
 2841     else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 10 && CurrentOSMinor == 0)
 2842         nCurrentOS = ((os.wProductType !=  VER_NT_WORKSTATION) ? WIN_SERVER_2016 : WIN_10);
 2843     else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 4)
 2844         nCurrentOS = WIN_NT4;
 2845     else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 0)
 2846         nCurrentOS = WIN_95;
 2847     else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 10)
 2848         nCurrentOS = WIN_98;
 2849     else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 90)
 2850         nCurrentOS = WIN_ME;
 2851     else if (os.dwPlatformId == VER_PLATFORM_WIN32s)
 2852         nCurrentOS = WIN_31;
 2853     else
 2854         nCurrentOS = WIN_UNKNOWN;
 2855 }
 2856 
 2857 static void LoadSystemDll (LPCTSTR szModuleName, HMODULE *pHandle, BOOL bIgnoreError, const char* srcPos)
 2858 {
 2859     wchar_t dllPath[MAX_PATH];
 2860 
 2861     /* Load dll explictely from System32 to avoid Dll hijacking attacks*/
 2862     if (!GetSystemDirectory(dllPath, MAX_PATH))
 2863         StringCbCopyW(dllPath, sizeof(dllPath), L"C:\\Windows\\System32");
 2864 
 2865     StringCbCatW(dllPath, sizeof(dllPath), L"\\");
 2866     StringCbCatW(dllPath, sizeof(dllPath), szModuleName);
 2867 
 2868     if (((*pHandle = LoadLibrary(dllPath)) == NULL) && !bIgnoreError)
 2869     {
 2870         // This error is fatal
 2871         handleWin32Error (NULL, srcPos);
 2872         AbortProcess ("INIT_DLL");
 2873     }
 2874 }
 2875 
 2876 /* InitApp - initialize the application, this function is called once in the
 2877    applications WinMain function, but before the main dialog has been created */
 2878 void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine)
 2879 {
 2880     WNDCLASSW wc;
 2881     char langId[6]; 
 2882     InitCommonControlsPtr InitCommonControlsFn = NULL;  
 2883     wchar_t modPath[MAX_PATH];
 2884 
 2885     GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath));
 2886 
 2887    /* remove current directory from dll search path */
 2888    SetDllDirectoryFn = (SetDllDirectoryPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDllDirectoryW");
 2889    SetSearchPathModeFn = (SetSearchPathModePtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetSearchPathMode");
 2890    SetDefaultDllDirectoriesFn = (SetDefaultDllDirectoriesPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDefaultDllDirectories");
 2891 
 2892    if (SetDllDirectoryFn)
 2893       SetDllDirectoryFn (L"");
 2894    if (SetSearchPathModeFn)
 2895       SetSearchPathModeFn (BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT);
 2896    if (SetDefaultDllDirectoriesFn)
 2897       SetDefaultDllDirectoriesFn (LOAD_LIBRARY_SEARCH_SYSTEM32);
 2898 
 2899    InitOSVersionInfo();
 2900 
 2901     VirtualLock (&CmdTokenPin, sizeof (CmdTokenPin));
 2902 
 2903     InitGlobalLocks ();
 2904 
 2905     LoadSystemDll (L"msvcrt.dll", &hmsvcrtdll, TRUE, SRC_POS);
 2906     LoadSystemDll (L"ntmarta.dll", &hntmartadll, TRUE, SRC_POS);
 2907     LoadSystemDll (L"MPR.DLL", &hmprdll, TRUE, SRC_POS);
 2908 #ifdef SETUP
 2909     if (IsOSAtLeast (WIN_7))
 2910     {
 2911         LoadSystemDll (L"ProfApi.DLL", &hProfApiDll, TRUE, SRC_POS);
 2912         LoadSystemDll (L"cryptbase.dll", &hcryptbasedll, TRUE, SRC_POS);
 2913         LoadSystemDll (L"sspicli.dll", &hsspiclidll, TRUE, SRC_POS);
 2914     }
 2915 #endif
 2916     LoadSystemDll (L"psapi.dll", &hpsapidll, TRUE, SRC_POS);
 2917     LoadSystemDll (L"secur32.dll", &hsecur32dll, TRUE, SRC_POS);
 2918     LoadSystemDll (L"msasn1.dll", &hmsasn1dll, TRUE, SRC_POS);
 2919     LoadSystemDll (L"Usp10.DLL", &hUsp10Dll, TRUE, SRC_POS);
 2920     if (IsOSAtLeast (WIN_7))
 2921         LoadSystemDll (L"dwmapi.dll", &hdwmapidll, TRUE, SRC_POS);
 2922     LoadSystemDll (L"UXTheme.dll", &hUXThemeDll, TRUE, SRC_POS);   
 2923 
 2924     LoadSystemDll (L"msls31.dll", &hMsls31, TRUE, SRC_POS); 
 2925     LoadSystemDll (L"SETUPAPI.DLL", &hSetupDll, FALSE, SRC_POS);
 2926     LoadSystemDll (L"SHLWAPI.DLL", &hShlwapiDll, FALSE, SRC_POS);   
 2927 
 2928     LoadSystemDll (L"userenv.dll", &hUserenvDll, TRUE, SRC_POS);
 2929     LoadSystemDll (L"rsaenh.dll", &hRsaenhDll, TRUE, SRC_POS);
 2930 
 2931 #ifdef SETUP
 2932     if (nCurrentOS < WIN_7)
 2933     {
 2934         if (nCurrentOS == WIN_XP)
 2935         {
 2936             LoadSystemDll (L"imm32.dll", &himm32dll, TRUE, SRC_POS);
 2937             LoadSystemDll (L"MSCTF.dll", &hMSCTFdll, TRUE, SRC_POS);
 2938             LoadSystemDll (L"fltlib.dll", &hfltlibdll, TRUE, SRC_POS);
 2939             LoadSystemDll (L"wbem\\framedyn.dll", &hframedyndll, TRUE, SRC_POS);
 2940         }
 2941 
 2942         if (IsOSAtLeast (WIN_VISTA))
 2943         {                   
 2944             LoadSystemDll (L"netapi32.dll", &hnetapi32dll, TRUE, SRC_POS);
 2945             LoadSystemDll (L"authz.dll", &hauthzdll, TRUE, SRC_POS);
 2946             LoadSystemDll (L"xmllite.dll", &hxmllitedll, TRUE, SRC_POS);
 2947         }
 2948     }
 2949 
 2950     if (IsOSAtLeast (WIN_VISTA))
 2951     {                   
 2952         LoadSystemDll (L"atl.dll", &hsppdll, TRUE, SRC_POS);
 2953         LoadSystemDll (L"vsstrace.dll", &hvsstracedll, TRUE, SRC_POS);
 2954         LoadSystemDll (L"vssapi.dll", &vssapidll, TRUE, SRC_POS);
 2955         LoadSystemDll (L"spp.dll", &hsppdll, TRUE, SRC_POS);
 2956     }
 2957 #endif
 2958 
 2959     LoadSystemDll (L"crypt32.dll", &hcrypt32dll, TRUE, SRC_POS);
 2960     
 2961     if (IsOSAtLeast (WIN_7))
 2962     {
 2963         LoadSystemDll (L"CryptSP.dll", &hCryptSpDll, TRUE, SRC_POS);
 2964 
 2965         LoadSystemDll (L"cfgmgr32.dll", &hcfgmgr32dll, TRUE, SRC_POS);
 2966         LoadSystemDll (L"devobj.dll", &hdevobjdll, TRUE, SRC_POS);
 2967         LoadSystemDll (L"powrprof.dll", &hpowrprofdll, TRUE, SRC_POS);
 2968 
 2969         LoadSystemDll (L"bcrypt.dll", &hbcryptdll, TRUE, SRC_POS);
 2970         LoadSystemDll (L"bcryptprimitives.dll", &hbcryptprimitivesdll, TRUE, SRC_POS);                              
 2971     }   
 2972 
 2973 #ifndef SETUP
 2974     LoadSystemDll (L"WINSCARD.DLL", &hwinscarddll, TRUE, SRC_POS);
 2975 #endif
 2976 
 2977     LoadSystemDll (L"COMCTL32.DLL", &hComctl32Dll, FALSE, SRC_POS);
 2978     
 2979     // call InitCommonControls function
 2980     InitCommonControlsFn = (InitCommonControlsPtr) GetProcAddress (hComctl32Dll, "InitCommonControls");
 2981     ImageList_AddFn = (ImageList_AddPtr) GetProcAddress (hComctl32Dll, "ImageList_Add");
 2982     ImageList_CreateFn = (ImageList_CreatePtr) GetProcAddress (hComctl32Dll, "ImageList_Create");
 2983 
 2984     if (InitCommonControlsFn && ImageList_AddFn && ImageList_CreateFn)
 2985     {
 2986         InitCommonControlsFn();
 2987     }
 2988     else
 2989         AbortProcess ("INIT_DLL");
 2990 
 2991     LoadSystemDll (L"Riched20.dll", &hRichEditDll, FALSE, SRC_POS);
 2992 
 2993 #if !defined(SETUP)
 2994     if (!VerifyModuleSignature (modPath))
 2995         AbortProcess ("DIST_PACKAGE_CORRUPTED");
 2996 #endif
 2997     // Get SetupAPI functions pointers
 2998     SetupCloseInfFileFn = (SetupCloseInfFilePtr) GetProcAddress (hSetupDll, "SetupCloseInfFile");
 2999     SetupDiOpenClassRegKeyFn = (SetupDiOpenClassRegKeyPtr) GetProcAddress (hSetupDll, "SetupDiOpenClassRegKey");
 3000     SetupInstallFromInfSectionWFn = (SetupInstallFromInfSectionWPtr) GetProcAddress (hSetupDll, "SetupInstallFromInfSectionW");
 3001     SetupOpenInfFileWFn = (SetupOpenInfFileWPtr) GetProcAddress (hSetupDll, "SetupOpenInfFileW");
 3002 
 3003     if (!SetupCloseInfFileFn || !SetupDiOpenClassRegKeyFn || !SetupInstallFromInfSectionWFn || !SetupOpenInfFileWFn)
 3004         AbortProcess ("INIT_DLL");
 3005 
 3006     // Get SHDeleteKeyW function pointer
 3007     SHDeleteKeyWFn = (SHDeleteKeyWPtr) GetProcAddress (hShlwapiDll, "SHDeleteKeyW");
 3008     SHStrDupWFn = (SHStrDupWPtr) GetProcAddress (hShlwapiDll, "SHStrDupW");
 3009     if (!SHDeleteKeyWFn || !SHStrDupWFn)
 3010         AbortProcess ("INIT_DLL");
 3011 
 3012     if (IsOSAtLeast (WIN_VISTA))
 3013     {
 3014         /* Get ChangeWindowMessageFilter used to enable some messages bypasss UIPI (User Interface Privilege Isolation) */
 3015         ChangeWindowMessageFilterFn = (ChangeWindowMessageFilterPtr) GetProcAddress (GetModuleHandle (L"user32.dll"), "ChangeWindowMessageFilter");
 3016 
 3017 #ifndef SETUP
 3018         /* enable drag-n-drop when we are running elevated */
 3019         AllowMessageInUIPI (WM_DROPFILES);
 3020         AllowMessageInUIPI (WM_COPYDATA);
 3021         AllowMessageInUIPI (WM_COPYGLOBALDATA);
 3022 #endif
 3023     }
 3024 
 3025     /* Save the instance handle for later */
 3026     hInst = hInstance;
 3027 
 3028     SetErrorMode (SetErrorMode (0) | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
 3029     CoInitialize (NULL);
 3030 
 3031 #ifndef SETUP
 3032     // Application ID
 3033     typedef HRESULT (WINAPI *SetAppId_t) (PCWSTR appID);
 3034     SetAppId_t setAppId = (SetAppId_t) GetProcAddress (GetModuleHandle (L"shell32.dll"), "SetCurrentProcessExplicitAppUserModelID");
 3035 
 3036     if (setAppId)
 3037         setAppId (TC_APPLICATION_ID);
 3038 #endif
 3039 
 3040     // Language
 3041     langId[0] = 0;
 3042     SetPreferredLangId (ConfigReadString ("Language", "", langId, sizeof (langId)));
 3043 
 3044 #ifndef SETUP
 3045     if (langId[0] == 0)
 3046     {
 3047         // check if user selected a language during installation
 3048         WCHAR uiLang[6];
 3049         ReadRegistryString (L"Software\\VeraCrypt", L"SetupUILanguage", L"", uiLang, sizeof (uiLang));
 3050         if (0 < WideCharToMultiByte (CP_ACP, 0, uiLang, -1, langId, sizeof (langId), NULL, NULL))
 3051         {
 3052             SetPreferredLangId (langId);
 3053             bLanguageSetInSetup = TRUE;
 3054         }
 3055     }
 3056 
 3057 #ifndef VCEXPANDER
 3058     // delete the registry key created by the installer (if any)
 3059     DeleteRegistryKey (HKEY_CURRENT_USER, L"Software\\VeraCrypt");
 3060 #endif
 3061 
 3062 #endif
 3063     
 3064     if (langId[0] == 0)
 3065     {
 3066         if (IsNonInstallMode ())
 3067         {
 3068             // only support automatic use of a language file in portable mode
 3069             // this is achieved by placing a unique language XML file in the same
 3070             // place as portable VeraCrypt binaries.
 3071             DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_LANGUAGE), NULL,
 3072                 (DLGPROC) LanguageDlgProc, (LPARAM) 1);
 3073         }
 3074         else
 3075         {
 3076             // when installed, force using English as default language
 3077             SetPreferredLangId ("en");
 3078         }
 3079     }
 3080 
 3081     LoadLanguageFile ();
 3082 
 3083 #ifndef SETUP
 3084     // UAC elevation moniker cannot be used in portable mode.
 3085     // A new instance of the application must be created with elevated privileges.
 3086     if (IsNonInstallMode () && !IsAdmin () && IsUacSupported ())
 3087     {
 3088 
 3089         if (wcsstr (lpszCommandLine, L"/q UAC ") == lpszCommandLine)
 3090         {
 3091             Error ("UAC_INIT_ERROR", NULL);
 3092             exit (1);
 3093         }
 3094 
 3095 
 3096         if (LaunchElevatedProcess (NULL, modPath, lpszCommandLine))
 3097             exit (0);
 3098         else
 3099             exit (1);
 3100     }
 3101 #endif
 3102 
 3103     SetUnhandledExceptionFilter (ExceptionHandler);
 3104     _set_invalid_parameter_handler (InvalidParameterHandler);
 3105 
 3106     RemoteSession = GetSystemMetrics (SM_REMOTESESSION) != 0;
 3107 
 3108     // OS version check
 3109     if (CurrentOSMajor < 5)
 3110     {
 3111         MessageBoxW (NULL, GetString ("UNSUPPORTED_OS"), lpszTitle, MB_ICONSTOP);
 3112         exit (1);
 3113     }
 3114     else
 3115     {
 3116         // Service pack check & warnings about critical MS issues
 3117         switch (nCurrentOS)
 3118         {
 3119         case WIN_2000:
 3120             if (CurrentOSServicePack < 3)
 3121                 Warning ("LARGE_IDE_WARNING_2K", NULL);
 3122             else
 3123             {
 3124                 DWORD val = 0, size = sizeof(val);
 3125                 HKEY hkey;
 3126 
 3127                 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Atapi\\Parameters", 0, KEY_READ, &hkey) == ERROR_SUCCESS)
 3128                 {
 3129                     if (RegQueryValueExW (hkey, L"EnableBigLba", 0, 0, (LPBYTE) &val, &size) != ERROR_SUCCESS
 3130                             || val != 1)
 3131                     {
 3132                         Warning ("LARGE_IDE_WARNING_2K_REGISTRY", NULL);
 3133                     }
 3134                     RegCloseKey (hkey);
 3135                 }
 3136             }
 3137             break;
 3138 
 3139         case WIN_XP:
 3140             if (CurrentOSServicePack < 1)
 3141             {
 3142                 HKEY k;
 3143                 // PE environment does not report version of SP
 3144                 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\minint", 0, KEY_READ, &k) != ERROR_SUCCESS)
 3145                     Warning ("LARGE_IDE_WARNING_XP", NULL);
 3146                 else
 3147                     RegCloseKey (k);
 3148             }
 3149             break;
 3150         }
 3151     }
 3152     
 3153     /* Get the attributes for the standard dialog class */
 3154     if ((GetClassInfoW (hInst, WINDOWS_DIALOG_CLASS, &wc)) == 0)
 3155     {
 3156         handleWin32Error (NULL, SRC_POS);
 3157         AbortProcess ("INIT_REGISTER");
 3158     }
 3159 
 3160 #ifndef SETUP
 3161     wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_TRUECRYPT_ICON));
 3162 #else
 3163 #include "../setup/resource.h"
 3164     wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_SETUP));
 3165 #endif
 3166     wc.lpszClassName = TC_DLG_CLASS;
 3167     wc.lpfnWndProc = &CustomDlgProc;
 3168     wc.hCursor = LoadCursor (NULL, IDC_ARROW);
 3169     wc.cbWndExtra = DLGWINDOWEXTRA;
 3170 
 3171     hDlgClass = RegisterClassW (&wc);
 3172     if (hDlgClass == 0)
 3173     {
 3174         handleWin32Error (NULL, SRC_POS);
 3175         AbortProcess ("INIT_REGISTER");
 3176     }
 3177 
 3178     wc.lpszClassName = TC_SPLASH_CLASS;
 3179     wc.lpfnWndProc = &SplashDlgProc;
 3180     wc.hCursor = LoadCursor (NULL, IDC_ARROW);
 3181     wc.cbWndExtra = DLGWINDOWEXTRA;
 3182 
 3183     hSplashClass = RegisterClassW (&wc);
 3184     if (hSplashClass == 0)
 3185     {
 3186         handleWin32Error (NULL, SRC_POS);
 3187         AbortProcess ("INIT_REGISTER");
 3188     }
 3189 
 3190     // DPI and GUI aspect ratio
 3191     DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_AUXILIARY_DLG), NULL,
 3192         (DLGPROC) AuxiliaryDlgProc, (LPARAM) 1);
 3193 
 3194     InitHelpFileName ();
 3195 
 3196 #ifndef SETUP
 3197     if (!EncryptionThreadPoolStart (ReadEncryptionThreadPoolFreeCpuCountLimit()))
 3198     {
 3199         handleWin32Error (NULL, SRC_POS);
 3200         FREE_DLL (hRichEditDll);
 3201         FREE_DLL (hComctl32Dll);
 3202         FREE_DLL (hSetupDll);
 3203         FREE_DLL (hShlwapiDll);
 3204         FREE_DLL (hProfApiDll);
 3205         FREE_DLL (hUsp10Dll);
 3206         FREE_DLL (hCryptSpDll);
 3207         FREE_DLL (hUXThemeDll);
 3208         FREE_DLL (hUserenvDll);
 3209         FREE_DLL (hRsaenhDll);
 3210         FREE_DLL (himm32dll);
 3211         FREE_DLL (hMSCTFdll);
 3212         FREE_DLL (hfltlibdll);
 3213         FREE_DLL (hframedyndll);
 3214         FREE_DLL (hpsapidll);
 3215         FREE_DLL (hsecur32dll);
 3216         FREE_DLL (hnetapi32dll);
 3217         FREE_DLL (hauthzdll);
 3218         FREE_DLL (hxmllitedll);
 3219         FREE_DLL (hmprdll);
 3220         FREE_DLL (hsppdll);
 3221         FREE_DLL (vssapidll);
 3222         FREE_DLL (hvsstracedll);
 3223         FREE_DLL (hCryptSpDll);
 3224         FREE_DLL (hcfgmgr32dll);
 3225         FREE_DLL (hdevobjdll);
 3226         FREE_DLL (hpowrprofdll);
 3227         FREE_DLL (hsspiclidll);
 3228         FREE_DLL (hcryptbasedll);
 3229         FREE_DLL (hdwmapidll);
 3230         FREE_DLL (hmsasn1dll);
 3231         FREE_DLL (hcrypt32dll);
 3232         FREE_DLL (hbcryptdll);
 3233         FREE_DLL (hbcryptprimitivesdll);
 3234         FREE_DLL (hMsls31);
 3235         FREE_DLL (hntmartadll);
 3236         FREE_DLL (hwinscarddll);
 3237         FREE_DLL (hmsvcrtdll);
 3238         exit (1);
 3239     }
 3240 #endif
 3241 }
 3242 
 3243 void FinalizeApp (void)
 3244 {
 3245     FREE_DLL (hRichEditDll);
 3246     FREE_DLL (hComctl32Dll);
 3247     FREE_DLL (hSetupDll);
 3248     FREE_DLL (hShlwapiDll);
 3249     FREE_DLL (hProfApiDll);
 3250     FREE_DLL (hUsp10Dll);
 3251     FREE_DLL (hCryptSpDll);
 3252     FREE_DLL (hUXThemeDll);
 3253     FREE_DLL (hUserenvDll);
 3254     FREE_DLL (hRsaenhDll);
 3255     FREE_DLL (himm32dll);
 3256     FREE_DLL (hMSCTFdll);
 3257     FREE_DLL (hfltlibdll);
 3258     FREE_DLL (hframedyndll);
 3259     FREE_DLL (hpsapidll);
 3260     FREE_DLL (hsecur32dll);
 3261     FREE_DLL (hnetapi32dll);
 3262     FREE_DLL (hauthzdll);
 3263     FREE_DLL (hxmllitedll);
 3264     FREE_DLL (hmprdll);
 3265     FREE_DLL (hsppdll);
 3266     FREE_DLL (vssapidll);
 3267     FREE_DLL (hvsstracedll);
 3268     FREE_DLL (hCryptSpDll);
 3269     FREE_DLL (hcfgmgr32dll);
 3270     FREE_DLL (hdevobjdll);
 3271     FREE_DLL (hpowrprofdll);
 3272     FREE_DLL (hsspiclidll);
 3273     FREE_DLL (hcryptbasedll);
 3274     FREE_DLL (hdwmapidll);
 3275     FREE_DLL (hmsasn1dll);
 3276     FREE_DLL (hcrypt32dll);
 3277     FREE_DLL (hbcryptdll);
 3278     FREE_DLL (hbcryptprimitivesdll);
 3279     FREE_DLL (hMsls31);
 3280     FREE_DLL (hntmartadll);
 3281     FREE_DLL (hwinscarddll);
 3282     FREE_DLL (hmsvcrtdll);
 3283 }
 3284 
 3285 void InitHelpFileName (void)
 3286 {
 3287     wchar_t *lpszTmp;
 3288 
 3289     GetModuleFileNameW (NULL, szHelpFile, ARRAYSIZE (szHelpFile));
 3290     lpszTmp = wcsrchr (szHelpFile, L'\\');
 3291     if (lpszTmp)
 3292     {
 3293         wchar_t szTemp[TC_MAX_PATH];
 3294 
 3295         ++lpszTmp;
 3296         *lpszTmp = 0; // add null terminating character to prepare for append operations
 3297 
 3298         // Primary file name
 3299         if (strcmp (GetPreferredLangId(), "en") == 0
 3300             || strlen(GetPreferredLangId()) == 0)
 3301         {
 3302             StringCbCatW (szHelpFile, sizeof(szHelpFile), L"docs\\VeraCrypt User Guide.chm");
 3303         }
 3304         else
 3305         {
 3306             StringCbPrintfW (szTemp, sizeof(szTemp), L"docs\\VeraCrypt User Guide.%S.chm", GetPreferredLangId());
 3307             StringCbCatW (szHelpFile, sizeof(szHelpFile), szTemp);
 3308         }
 3309 
 3310         // Secondary file name (used when localized documentation is not found).
 3311         GetModuleFileNameW (NULL, szHelpFile2, ARRAYSIZE (szHelpFile2));
 3312         lpszTmp = wcsrchr (szHelpFile2, L'\\');
 3313         if (lpszTmp)
 3314         {
 3315             ++lpszTmp;
 3316             *lpszTmp = 0;
 3317             StringCbCatW (szHelpFile2, sizeof(szHelpFile2), L"docs\\VeraCrypt User Guide.chm");
 3318         }
 3319     }
 3320 }
 3321 
 3322 #ifndef SETUP
 3323 BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem, BOOL computeVolumeIDs)
 3324 {
 3325     DWORD dwResult;
 3326     BOOL bResult;
 3327     wchar_t wszFileName[TC_MAX_PATH];
 3328 
 3329     StringCbCopyW (wszFileName, sizeof(wszFileName), lpszPath);
 3330 
 3331     memset (driver, 0, sizeof (OPEN_TEST_STRUCT));
 3332     memcpy (driver->wszFileName, wszFileName, sizeof (wszFileName));
 3333 
 3334     driver->bDetectTCBootLoader = FALSE;
 3335     driver->DetectFilesystem = detectFilesystem;
 3336     driver->bComputeVolumeIDs = computeVolumeIDs;
 3337 
 3338     bResult = DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST,
 3339                    driver, sizeof (OPEN_TEST_STRUCT),
 3340                    driver, sizeof (OPEN_TEST_STRUCT),
 3341                    &dwResult, NULL);
 3342 
 3343     // check variable driver
 3344     if (    bResult 
 3345         && ( (driver->bDetectTCBootLoader != TRUE && driver->bDetectTCBootLoader != FALSE) ||
 3346               (driver->TCBootLoaderDetected != TRUE && driver->TCBootLoaderDetected != FALSE) ||
 3347               (driver->DetectFilesystem != TRUE && driver->DetectFilesystem != FALSE) ||
 3348               (driver->FilesystemDetected != TRUE && driver->FilesystemDetected != FALSE) ||
 3349               (wcscmp (wszFileName, driver->wszFileName))
 3350             )
 3351         )
 3352     {
 3353         return FALSE;
 3354     }
 3355 
 3356     if (bResult == FALSE)
 3357     {
 3358         dwResult = GetLastError ();
 3359 
 3360         if (dwResult == ERROR_SHARING_VIOLATION || dwResult == ERROR_NOT_READY)
 3361         {
 3362             driver->TCBootLoaderDetected = FALSE;
 3363             driver->FilesystemDetected = FALSE;
 3364             memset (driver->VolumeIDComputed, 0, sizeof (driver->VolumeIDComputed));
 3365             return TRUE;
 3366         }
 3367         else
 3368             return FALSE;
 3369     }
 3370         
 3371     return TRUE;
 3372 }
 3373 
 3374 #endif
 3375 
 3376 // Tells the driver that it's running in portable mode
 3377 void NotifyDriverOfPortableMode (void)
 3378 {
 3379     if (hDriver != INVALID_HANDLE_VALUE)
 3380     {
 3381         DWORD dwResult;
 3382 
 3383         DeviceIoControl (hDriver, TC_IOCTL_SET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dwResult, NULL);
 3384     }
 3385 }
 3386 
 3387 
 3388 BOOL GetDriveLabel (int driveNo, wchar_t *label, int labelSize)
 3389 {
 3390     DWORD fileSystemFlags;
 3391     wchar_t root[] = { L'A' + (wchar_t) driveNo, L':', L'\\', 0 };
 3392 
 3393     return GetVolumeInformationW (root, label, labelSize / 2, NULL, NULL, &fileSystemFlags, NULL, 0);
 3394 }
 3395 
 3396 #ifndef SETUP
 3397 
 3398 /* Stores the device path of the system partition in SysPartitionDevicePath and the device path of the system drive
 3399 in SysDriveDevicePath.
 3400 IMPORTANT: As this may take a very long time if called for the first time, it should be called only before performing 
 3401            a dangerous operation (such as header backup restore or formatting a supposedly non-system device) never 
 3402            at WM_INITDIALOG or any other GUI events -- instead call IsSystemDevicePath (path, hwndDlg, FALSE) for 
 3403            very fast preliminary GUI checks; also note that right after the "Select Device" dialog exits with an OK 
 3404            return code, you can use the global flags bSysPartitionSelected and bSysDriveSelected to see if the user
 3405            selected the system partition/device.
 3406 After this function completes successfully, the results are cached for the rest of the session and repeated
 3407 executions complete very fast. Returns TRUE if successful (otherwise FALSE). */
 3408 BOOL GetSysDevicePaths (HWND hwndDlg)
 3409 {
 3410     if (!bCachedSysDevicePathsValid
 3411         || wcslen (SysPartitionDevicePath) <= 1 
 3412         || wcslen (SysDriveDevicePath) <= 1)
 3413     {
 3414         foreach (const HostDevice &device, GetAvailableHostDevices (false, true))
 3415         {
 3416             if (device.ContainsSystem)
 3417                 StringCchCopyW (device.IsPartition ? SysPartitionDevicePath : SysDriveDevicePath, TC_MAX_PATH, device.Path.c_str()); 
 3418         }
 3419 
 3420         if (IsOSAtLeast (WIN_7))
 3421         {
 3422             // Find extra boot partition
 3423             foreach (const HostDevice &drive, GetAvailableHostDevices (false, false))
 3424             {
 3425                 if (drive.ContainsSystem)
 3426                 {
 3427                     foreach (const HostDevice &sysDrivePartition, drive.Partitions)
 3428                     {
 3429                         if (sysDrivePartition.Bootable)
 3430                         {
 3431                             if (sysDrivePartition.Size <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE)
 3432                                 ExtraBootPartitionDevicePath = sysDrivePartition.Path;
 3433                             break;
 3434                         }
 3435                     }
 3436                     break;
 3437                 }
 3438             }
 3439         }
 3440 
 3441         bCachedSysDevicePathsValid = 1;
 3442     }
 3443 
 3444     return (bCachedSysDevicePathsValid 
 3445         && wcslen (SysPartitionDevicePath) > 1 
 3446         && wcslen (SysDriveDevicePath) > 1);
 3447 }
 3448 
 3449 /* Determines whether the device path is the path of the system partition or of the system drive (or neither). 
 3450 If bReliableRequired is TRUE, very fast execution is guaranteed, but the results cannot be relied upon. 
 3451 If it's FALSE and the function is called for the first time, execution may take up to one minute but the
 3452 results are reliable.
 3453 IMPORTANT: As the execution may take a very long time if called for the first time with bReliableRequired set
 3454            to TRUE, it should be called with bReliableRequired set to TRUE only before performing a dangerous
 3455            operation (such as header backup restore or formatting a supposedly non-system device) never at 
 3456            WM_INITDIALOG or any other GUI events (use IsSystemDevicePath(path, hwndDlg, FALSE) for fast 
 3457            preliminary GUI checks; also note that right after the "Select Device" dialog exits with an OK 
 3458            return code, you can use the global flags bSysPartitionSelected and bSysDriveSelected to see if the
 3459            user selected the system partition/device).
 3460 After this function completes successfully, the results are cached for the rest of the session, bReliableRequired
 3461 is ignored (TRUE implied), repeated executions complete very fast, and the results are always reliable. 
 3462 Return codes:
 3463 1  - it is the system partition path (e.g. \Device\Harddisk0\Partition1)
 3464 2  - it is the system drive path (e.g. \Device\Harddisk0\Partition0)
 3465 3  - it is the extra boot partition path
 3466 0  - it's not the system partition/drive path
 3467 -1 - the result can't be determined, isn't reliable, or there was an error. */
 3468 int IsSystemDevicePath (const wchar_t *path, HWND hwndDlg, BOOL bReliableRequired)
 3469 {
 3470     if (!bCachedSysDevicePathsValid
 3471         && bReliableRequired)
 3472     {
 3473         if (!GetSysDevicePaths (hwndDlg))
 3474             return -1;
 3475     }
 3476 
 3477     if (wcslen (SysPartitionDevicePath) <= 1 || wcslen (SysDriveDevicePath) <= 1)
 3478         return -1;
 3479 
 3480     if (!path)
 3481         return -1;
 3482 
 3483     if (wcsncmp (path, SysPartitionDevicePath, max (wcslen(path), wcslen(SysPartitionDevicePath))) == 0)
 3484         return 1;
 3485     else if (wcsncmp (path, SysDriveDevicePath, max (wcslen(path), wcslen(SysDriveDevicePath))) == 0)
 3486         return 2;
 3487     else if (ExtraBootPartitionDevicePath == path)
 3488         return 3;
 3489 
 3490     return 0;
 3491 }
 3492 
 3493 
 3494 /* Determines whether the path points to a non-system partition on the system drive.
 3495 IMPORTANT: As this may take a very long time if called for the first time, it should be called
 3496            only before performing a dangerous operation, never at WM_INITDIALOG or any other GUI events. 
 3497 Return codes:
 3498 0  - it isn't a non-system partition on the system drive 
 3499 1  - it's a non-system partition on the system drive 
 3500 -1 - the result can't be determined, isn't reliable, or there was an error. */
 3501 int IsNonSysPartitionOnSysDrive (const wchar_t *path)
 3502 {
 3503     wchar_t tmpPath [TC_MAX_PATH + 1];
 3504     int pos;
 3505 
 3506     if (!GetSysDevicePaths (MainDlg))
 3507         return -1;
 3508 
 3509     if (wcslen (SysPartitionDevicePath) <= 1 || wcslen (SysDriveDevicePath) <= 1)
 3510         return -1;
 3511 
 3512     if (wcsncmp (path, SysPartitionDevicePath, max (wcslen(path), wcslen(SysPartitionDevicePath))) == 0
 3513         || wcsncmp (path, SysDriveDevicePath, max (wcslen(path), wcslen(SysDriveDevicePath))) == 0)
 3514     {
 3515         // It is the system partition/drive path (it isn't a non-system partition)
 3516         return 0;
 3517     }
 3518 
 3519     memset (tmpPath, 0, sizeof (tmpPath));
 3520     wcsncpy (tmpPath, path, ARRAYSIZE (tmpPath) - 1);
 3521 
 3522 
 3523     pos = (int) FindString ((const char*) tmpPath, (const char*) L"Partition", (int) wcslen (tmpPath) * 2, (int) wcslen (L"Partition") * 2, 0);
 3524 
 3525     if (pos < 0)
 3526         return -1;
 3527 
 3528     pos /= 2;
 3529     pos += (int) strlen ("Partition");
 3530 
 3531     if (pos + 1 > ARRAYSIZE (tmpPath) - 1)
 3532         return -1;
 3533 
 3534     tmpPath [pos] = L'0';
 3535     tmpPath [pos + 1] = 0;
 3536 
 3537     if (wcsncmp (tmpPath, SysDriveDevicePath, max (wcslen(tmpPath), wcslen(SysDriveDevicePath))) == 0)
 3538     {
 3539         // It is a non-system partition on the system drive 
 3540         return 1;
 3541     }
 3542     else 
 3543     {
 3544         // The partition is not on the system drive 
 3545         return 0;
 3546     }
 3547 }
 3548 
 3549 #endif //!SETUP
 3550 
 3551 wstring GetSysEncryptionPretestInfo2String (void)
 3552 {
 3553     // This huge string is divided into smaller portions to make it easier for translators to
 3554     // re-translate it when a minor modification is made to it (the whole huge string will not be
 3555     // reverted to English, so they will have to translate only a small portion of it).
 3556     return (wstring (L"\n")
 3557         + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_1")
 3558         + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_2")
 3559         + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_3")
 3560         + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_4"));
 3561 }
 3562 
 3563 
 3564 wstring GetRescueDiskHelpString (void)
 3565 {
 3566     // This huge string is divided into smaller portions to make it easier for translators to
 3567     // re-translate it when a minor modification is made to it (the whole huge string will not be
 3568     // reverted to English, so they will have to translate only a small portion of it).
 3569     return (wstring (
 3570         GetString ("RESCUE_DISK_HELP_PORTION_1"))
 3571         + GetString ("RESCUE_DISK_HELP_PORTION_2")
 3572         + GetString ("RESCUE_DISK_HELP_PORTION_3")
 3573         + GetString ("RESCUE_DISK_HELP_PORTION_4")
 3574         + GetString ("RESCUE_DISK_HELP_PORTION_5")
 3575         + GetString ("RESCUE_DISK_HELP_PORTION_6")
 3576         + GetString ("RESCUE_DISK_HELP_PORTION_7")
 3577         + GetString ("RESCUE_DISK_HELP_PORTION_8")
 3578         + GetString ("RESCUE_DISK_HELP_PORTION_9"));
 3579 }
 3580 
 3581 
 3582 wstring GetDecoyOsInstructionsString (void)
 3583 {
 3584     // This huge string is divided into smaller portions to make it easier for translators to
 3585     // re-translate it when a minor modification is made to it (the whole huge string will not be
 3586     // reverted to English, so they will have to translate only a small portion of it).
 3587     return (wstring (
 3588         GetString ("DECOY_OS_INSTRUCTIONS_PORTION_1"))
 3589         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_2")
 3590         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_3")
 3591         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_4")
 3592         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_5")
 3593         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_6")
 3594         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_7")
 3595         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_8")
 3596         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_9")
 3597         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_10")
 3598         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_11")
 3599         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_12")
 3600         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_13")
 3601         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_14")
 3602         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_15")
 3603         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_16")
 3604         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_17")
 3605         + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_18"));
 3606 }
 3607 
 3608 struct _TEXT_EDIT_DIALOG_PARAM {
 3609     BOOL ReadOnly;
 3610     std::string&  Text;
 3611     const WCHAR*  Title;
 3612 
 3613     _TEXT_EDIT_DIALOG_PARAM(BOOL _readOnly, const WCHAR* title, std::string&  _text) : Title(title), Text(_text), ReadOnly(_readOnly) {}
 3614     _TEXT_EDIT_DIALOG_PARAM& operator=( const _TEXT_EDIT_DIALOG_PARAM& other) { 
 3615         ReadOnly = other.ReadOnly;
 3616         Text = other.Text;
 3617         Title = other.Title;
 3618         return *this; 
 3619 }
 3620 };
 3621 typedef struct _TEXT_EDIT_DIALOG_PARAM TEXT_INFO_DIALOG_PARAM,*TEXT_INFO_DIALOG_PARAM_PTR;
 3622 
 3623 INT_PTR TextEditDialogBox (BOOL readOnly, HWND parent, const WCHAR* Title, std::string& text)
 3624 {
 3625     TEXT_INFO_DIALOG_PARAM pm(readOnly, Title, text);
 3626     return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_EDIT_DLG), parent, (DLGPROC) TextEditDlgProc, (LPARAM) &pm);
 3627 }
 3628 
 3629 BOOL CALLBACK TextEditDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 3630 {
 3631     WORD lw = LOWORD (wParam);
 3632     static int nID = 0;
 3633     static TEXT_INFO_DIALOG_PARAM_PTR prm;
 3634     switch (msg)
 3635     {
 3636     case WM_INITDIALOG:
 3637         {
 3638             prm = (TEXT_INFO_DIALOG_PARAM_PTR)lParam;
 3639             // increase size limit of rich edit control
 3640             SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_EXLIMITTEXT, 0, -1);
 3641 
 3642             SetWindowTextW (hwndDlg, prm->Title);
 3643             // Left margin for rich edit text field
 3644             SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4));
 3645 
 3646             if (prm->ReadOnly)
 3647             {
 3648                 // switch rich edit control to ReadOnly
 3649                 SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), ES_READONLY, TRUE, 0);
 3650                 // hide cancel button
 3651                 ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_HIDE);
 3652             }
 3653 
 3654             SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0);
 3655         }
 3656         return 0;
 3657 
 3658     case WM_COMMAND:
 3659         if (lw == IDOK )
 3660         {
 3661             if (!prm->ReadOnly)
 3662             {
 3663                 prm->Text.resize(GetWindowTextLengthA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT)) + 1);
 3664                 GetWindowTextA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), &(prm->Text)[0], (int) prm->Text.size());
 3665             }
 3666             NormalCursor ();
 3667             EndDialog (hwndDlg, IDOK);
 3668             return 1;
 3669         }
 3670 
 3671         if (lw == IDCANCEL )
 3672         {
 3673             NormalCursor ();
 3674             EndDialog (hwndDlg, IDCANCEL);
 3675             return 1;
 3676         }
 3677         return 0;
 3678 
 3679     case TC_APPMSG_LOAD_TEXT_BOX_CONTENT:
 3680         {
 3681             SetWindowTextA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), prm->Text.c_str());
 3682         }
 3683         return 0;
 3684 
 3685     case WM_CLOSE:
 3686         NormalCursor ();
 3687         EndDialog (hwndDlg, 0);
 3688         return 1;
 3689     }
 3690 
 3691     return 0;
 3692 }
 3693 
 3694 INT_PTR TextInfoDialogBox (int nID)
 3695 {
 3696     return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_INFO_DIALOG_BOX_DLG), MainDlg, (DLGPROC) TextInfoDialogBoxDlgProc, (LPARAM) nID);
 3697 }
 3698 
 3699 BOOL CALLBACK TextInfoDialogBoxDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 3700 {
 3701     WORD lw = LOWORD (wParam);
 3702     static int nID = 0;
 3703 
 3704     switch (msg)
 3705     {
 3706     case WM_INITDIALOG:
 3707         {
 3708             nID = (int) lParam;
 3709 
 3710             // increase size limit of rich edit control
 3711             SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_EXLIMITTEXT, 0, -1);
 3712 
 3713             // Left margin for rich edit text field
 3714             SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4));
 3715 
 3716             ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_HIDE);
 3717 
 3718             switch (nID)
 3719             {
 3720             case TC_TBXID_LEGAL_NOTICES:
 3721                 LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE");
 3722                 break;
 3723 
 3724             case TC_TBXID_SYS_ENCRYPTION_PRETEST:
 3725                 LocalizeDialog (hwndDlg, NULL);
 3726                 ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW);
 3727                 break;
 3728 
 3729             case TC_TBXID_SYS_ENC_RESCUE_DISK:
 3730                 LocalizeDialog (hwndDlg, NULL);
 3731                 ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW);
 3732                 break;
 3733 
 3734             case TC_TBXID_DECOY_OS_INSTRUCTIONS:
 3735                 LocalizeDialog (hwndDlg, NULL);
 3736                 ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW);
 3737                 break;
 3738 
 3739             case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS:
 3740                 LocalizeDialog (hwndDlg, NULL);
 3741                 ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW);
 3742                 break;
 3743             }
 3744 
 3745             SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0);
 3746         }
 3747         return 0;
 3748 
 3749     case WM_COMMAND:
 3750         if (lw == IDOK || lw == IDCANCEL)
 3751         {
 3752             NormalCursor ();
 3753             EndDialog (hwndDlg, 0);
 3754             return 1;
 3755         }
 3756 
 3757         if (lw == IDC_PRINT)
 3758         {
 3759             switch (nID)
 3760             {
 3761             case TC_TBXID_SYS_ENCRYPTION_PRETEST:
 3762                 PrintHardCopyTextUTF16 ((wchar_t *) GetSysEncryptionPretestInfo2String ().c_str(), L"Pre-Boot Troubleshooting", GetSysEncryptionPretestInfo2String ().length () * 2);
 3763                 break;
 3764 
 3765             case TC_TBXID_SYS_ENC_RESCUE_DISK:
 3766                 PrintHardCopyTextUTF16 ((wchar_t *) GetRescueDiskHelpString ().c_str(), L"VeraCrypt Rescue Disk Help", GetRescueDiskHelpString ().length () * 2);
 3767                 break;
 3768 
 3769             case TC_TBXID_DECOY_OS_INSTRUCTIONS:
 3770                 PrintHardCopyTextUTF16 ((wchar_t *) GetDecoyOsInstructionsString ().c_str(), L"How to Create Decoy OS", GetDecoyOsInstructionsString ().length () * 2);
 3771                 break;
 3772 
 3773             case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS:
 3774                 PrintHardCopyTextUTF16 (GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS"), L"How to Remove Extra Boot Partition", wcslen (GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS")) * 2);
 3775                 break;
 3776             }
 3777             return 1;
 3778         }
 3779 
 3780         return 0;
 3781 
 3782     case TC_APPMSG_LOAD_TEXT_BOX_CONTENT:
 3783         {
 3784             char *r = NULL;
 3785 
 3786             switch (nID)
 3787             {
 3788             case TC_TBXID_LEGAL_NOTICES:
 3789                 LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE");
 3790                 r = GetLegalNotices ();
 3791                 if (r != NULL)
 3792                 {
 3793                     SETTEXTEX TextInfo = {0};
 3794 
 3795                     TextInfo.flags = ST_SELECTION;
 3796                     TextInfo.codepage = CP_ACP;
 3797 
 3798                     SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETTEXTEX, (WPARAM)&TextInfo, (LPARAM)r);
 3799                     free (r);
 3800                 }
 3801                 break;
 3802 
 3803             case TC_TBXID_SYS_ENCRYPTION_PRETEST:
 3804                 LocalizeDialog (hwndDlg, NULL);
 3805                 SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetSysEncryptionPretestInfo2String ().c_str());
 3806                 break;
 3807 
 3808             case TC_TBXID_SYS_ENC_RESCUE_DISK:
 3809                 LocalizeDialog (hwndDlg, NULL);
 3810                 SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetRescueDiskHelpString ().c_str());
 3811                 break;
 3812 
 3813             case TC_TBXID_DECOY_OS_INSTRUCTIONS:
 3814                 LocalizeDialog (hwndDlg, NULL);
 3815                 SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetDecoyOsInstructionsString ().c_str());
 3816                 break;
 3817 
 3818             case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS:
 3819                 LocalizeDialog (hwndDlg, NULL);
 3820                 SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS"));
 3821                 break;
 3822             }
 3823         }
 3824         return 1;
 3825 
 3826     case WM_CLOSE:
 3827         NormalCursor ();
 3828         EndDialog (hwndDlg, 0);
 3829         return 1;
 3830     }
 3831 
 3832     return 0;
 3833 }
 3834 
 3835 
 3836 char * GetLegalNotices ()
 3837 {
 3838     static char *resource;
 3839     static DWORD size;
 3840     char *buf = NULL;
 3841 
 3842     if (resource == NULL)
 3843         resource = (char *) MapResource (L"Text", IDR_LICENSE, &size);
 3844 
 3845     if (resource != NULL)
 3846     {
 3847         buf = (char *) malloc (size + 1);
 3848         if (buf != NULL)
 3849         {
 3850             memcpy (buf, resource, size);
 3851             buf[size] = 0;
 3852         }
 3853     }
 3854 
 3855     return buf;
 3856 }
 3857 
 3858 #ifndef SETUP
 3859 
 3860 BOOL CALLBACK RawDevicesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 3861 {
 3862     static wchar_t *lpszFileName;       // This is actually a pointer to a GLOBAL array
 3863     static vector <HostDevice> devices;
 3864     static map <int, HostDevice> itemToDeviceMap;
 3865 
 3866     WORD lw = LOWORD (wParam);
 3867 
 3868     switch (msg)
 3869     {
 3870     case WM_INITDIALOG:
 3871         {
 3872             LVCOLUMNW LvCol;
 3873             HWND hList = GetDlgItem (hwndDlg, IDC_DEVICELIST);
 3874             RawDevicesDlgParam* pDlgParam = (RawDevicesDlgParam *) lParam;
 3875 
 3876             LocalizeDialog (hwndDlg, "IDD_RAWDEVICES_DLG");
 3877 
 3878             SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
 3879                 LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP 
 3880                 ); 
 3881 
 3882             memset (&LvCol,0,sizeof(LvCol));               
 3883             LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT;  
 3884             LvCol.pszText = GetString ("DEVICE");
 3885             LvCol.cx = CompensateXDPI (186);
 3886             LvCol.fmt = LVCFMT_LEFT;
 3887             SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol);
 3888 
 3889             LvCol.pszText = GetString ("DRIVE");  
 3890             LvCol.cx = CompensateXDPI (38);
 3891             LvCol.fmt = LVCFMT_LEFT;
 3892             SendMessage (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol);
 3893 
 3894             LvCol.pszText = GetString ("SIZE");
 3895             LvCol.cx = CompensateXDPI (64);
 3896             LvCol.fmt = LVCFMT_RIGHT;
 3897             SendMessage (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol);
 3898 
 3899             LvCol.pszText = GetString ("LABEL");
 3900             LvCol.cx = CompensateXDPI (128);
 3901             LvCol.fmt = LVCFMT_LEFT;
 3902             SendMessage (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol);
 3903 
 3904             devices.clear();
 3905             itemToDeviceMap.clear();
 3906 
 3907             if (pDlgParam->devices.empty())
 3908             {
 3909                 WaitCursor();
 3910                 devices = GetAvailableHostDevices (false, true, false);
 3911                 NormalCursor();
 3912             }
 3913             else
 3914                 devices = pDlgParam->devices;
 3915 
 3916             if (devices.empty())
 3917             {
 3918                 MessageBoxW (hwndDlg, GetString ("RAWDEVICES"), lpszTitle, ICON_HAND);
 3919                 EndDialog (hwndDlg, IDCANCEL);
 3920                 return 1;
 3921             }
 3922 
 3923             int line = 1;
 3924             LVITEM item;
 3925             memset (&item, 0, sizeof (item));
 3926             item.mask = LVIF_TEXT;
 3927 
 3928             foreach (const HostDevice &device, devices)
 3929             {
 3930                 item.iSubItem = 1;
 3931 
 3932                 if (device.ContainsSystem)
 3933                 {
 3934                     if (device.IsPartition)
 3935                         StringCbCopyW (SysPartitionDevicePath, sizeof (SysPartitionDevicePath), device.Path.c_str());
 3936                     else
 3937                         StringCbCopyW (SysDriveDevicePath, sizeof (SysDriveDevicePath), device.Path.c_str());
 3938                 }
 3939 
 3940                 // Path
 3941                 if (!device.IsPartition || device.DynamicVolume)
 3942                 {
 3943                     if (!device.Floppy && (device.Size == 0) 
 3944                         && (device.IsPartition || device.Partitions.empty() || device.Partitions[0].Size == 0)
 3945                         )
 3946                         continue;
 3947 
 3948                     if (line > 1)
 3949                     {
 3950                         ListItemAdd (hList, item.iItem, L"");
 3951                         item.iItem = line++;   
 3952                     }
 3953 
 3954                     if (device.Floppy || device.DynamicVolume)
 3955                     {
 3956                         ListItemAdd (hList, item.iItem, (wchar_t *) device.Path.c_str());
 3957                     }
 3958                     else
 3959                     {
 3960                         wchar_t s[1024];
 3961                         if (device.Removable)
 3962                             StringCbPrintfW (s, sizeof(s), L"%s %d", GetString ("REMOVABLE_DISK"), device.SystemNumber);
 3963                         else
 3964                             StringCbPrintfW (s, sizeof(s), L"%s %d", GetString ("HARDDISK"), device.SystemNumber);
 3965 
 3966                         if (!device.Partitions.empty())
 3967                             StringCbCatW (s, sizeof(s), L":");
 3968 
 3969                         ListItemAdd (hList, item.iItem, s);
 3970                     }
 3971                 }
 3972                 else
 3973                 {
 3974                     ListItemAdd (hList, item.iItem, (wchar_t *) device.Path.c_str());
 3975                 }
 3976 
 3977                 itemToDeviceMap[item.iItem] = device;
 3978 
 3979                 // Size
 3980                 if (device.Size != 0)
 3981                 {
 3982                     wchar_t size[100] = { 0 };
 3983                     GetSizeString (device.Size, size, sizeof(size));
 3984                     ListSubItemSet (hList, item.iItem, 2, size);
 3985                 }
 3986 
 3987                 // Mount point
 3988                 if (!device.MountPoint.empty())
 3989                     ListSubItemSet (hList, item.iItem, 1, (wchar_t *) device.MountPoint.c_str());
 3990 
 3991                 // Label
 3992                 if (!device.Name.empty())
 3993                     ListSubItemSet (hList, item.iItem, 3, (wchar_t *) device.Name.c_str());
 3994 #ifdef TCMOUNT
 3995                 else
 3996                 {
 3997                     bool useInExplorer = false;
 3998                     wstring favoriteLabel = GetFavoriteVolumeLabel (device.Path, useInExplorer);
 3999                     if (!favoriteLabel.empty())
 4000                         ListSubItemSet (hList, item.iItem, 3, (wchar_t *) favoriteLabel.c_str());
 4001                 }
 4002 #endif
 4003 
 4004                 item.iItem = line++;   
 4005             }
 4006 
 4007             SendMessageW(hList, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0));
 4008             SendMessageW(hList, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0));
 4009             SendMessageW(hList, LVM_SETCOLUMNWIDTH, 2, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0));
 4010             SendMessageW(hList, LVM_SETCOLUMNWIDTH, 3, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0));
 4011 
 4012             lpszFileName = pDlgParam->pszFileName;
 4013 
 4014 #ifdef VOLFORMAT
 4015             EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE);
 4016 #endif
 4017             return 1;
 4018         }
 4019 
 4020     case WM_COMMAND:
 4021     case WM_NOTIFY:
 4022         // catch non-device line selected
 4023         if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED ))
 4024         {
 4025             BOOL bEnableOkButton = FALSE;
 4026             LVITEM LvItem;
 4027             memset(&LvItem,0,sizeof(LvItem));           
 4028             LvItem.mask = LVIF_TEXT | LVIF_PARAM;   
 4029             LvItem.iItem = ((LPNMLISTVIEW) lParam)->iItem;
 4030             LvItem.pszText = lpszFileName;
 4031             LvItem.cchTextMax = TC_MAX_PATH;
 4032 
 4033             lpszFileName[0] = 0;
 4034             SendMessage (GetDlgItem (hwndDlg, IDC_DEVICELIST), LVM_GETITEM, LvItem.iItem, (LPARAM) &LvItem);
 4035             if (lpszFileName[0] != 0 && lpszFileName[0] != ' ')
 4036             {
 4037                 bEnableOkButton = TRUE;
 4038 #ifdef VOLFORMAT
 4039                 if (    bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE)
 4040                     &&  LvItem.iItem != -1 && itemToDeviceMap.find (LvItem.iItem) != itemToDeviceMap.end()
 4041                     )
 4042                 {
 4043                     const HostDevice selectedDevice = itemToDeviceMap[LvItem.iItem];
 4044                     if (selectedDevice.ContainsSystem)
 4045                     {
 4046                         bEnableOkButton = FALSE;
 4047                     }
 4048                 }
 4049 #endif
 4050             }
 4051             EnableWindow (GetDlgItem ((HWND) hwndDlg, IDOK), bEnableOkButton);
 4052 
 4053             return 1;
 4054         }
 4055 
 4056         if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE)
 4057         {
 4058             int selectedItem = ListView_GetSelectionMark (GetDlgItem (hwndDlg, IDC_DEVICELIST));
 4059 
 4060             if (selectedItem == -1 || itemToDeviceMap.find (selectedItem) == itemToDeviceMap.end())
 4061                 return 1; // non-device line selected   
 4062 
 4063             const HostDevice selectedDevice = itemToDeviceMap[selectedItem];
 4064             StringCchCopyW (lpszFileName, TC_MAX_PATH, selectedDevice.Path.c_str());
 4065 
 4066 #ifdef VOLFORMAT
 4067             if (selectedDevice.ContainsSystem && selectedDevice.IsPartition)
 4068             {
 4069                 if (WizardMode != WIZARD_MODE_SYS_DEVICE)
 4070                 {
 4071                     if (bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE))
 4072                     {
 4073                         // disable selection
 4074                         return 1;
 4075                     }
 4076 
 4077                     if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE", hwndDlg) == IDNO)
 4078                     {
 4079                         EndDialog (hwndDlg, IDCANCEL);
 4080                         return 1;
 4081                     }
 4082 
 4083                     bSysPartitionSelected = TRUE;
 4084                     bSysDriveSelected = FALSE;
 4085                     lpszFileName[0] = 0;
 4086                     SwitchWizardToSysEncMode ();
 4087 
 4088                     NormalCursor ();
 4089                     EndDialog (hwndDlg, IDOK);
 4090                     return 1;
 4091                 }
 4092                 else
 4093                 {
 4094                     // This should never be the case because the Select Device dialog is not available in this wizard mode
 4095                     bSysPartitionSelected = TRUE;
 4096                     bSysDriveSelected = FALSE;
 4097                     lpszFileName[0] = 0;
 4098                     SwitchWizardToSysEncMode ();
 4099                     NormalCursor ();
 4100                     EndDialog (hwndDlg, IDCANCEL);
 4101                     return 1;
 4102                 }
 4103             }
 4104 
 4105             if (!(selectedDevice.ContainsSystem && !selectedDevice.IsPartition))
 4106             {
 4107                 if (bWarnDeviceFormatAdvanced
 4108                     && !bHiddenVolDirect
 4109                     && AskWarnNoYes("FORMAT_DEVICE_FOR_ADVANCED_ONLY", hwndDlg) == IDNO)
 4110                 {
 4111                     if (AskNoYes("CONFIRM_CHANGE_WIZARD_MODE_TO_FILE_CONTAINER", hwndDlg) == IDYES)
 4112                     {
 4113                         SwitchWizardToFileContainerMode ();
 4114                     }
 4115                     EndDialog (hwndDlg, IDCANCEL);
 4116                     return 1;
 4117                 }
 4118 
 4119                 if (!bHiddenVolDirect)
 4120                     bWarnDeviceFormatAdvanced = FALSE;
 4121             }
 4122 
 4123 #else   // #ifdef VOLFORMAT
 4124 
 4125             bSysPartitionSelected = (selectedDevice.ContainsSystem && selectedDevice.IsPartition);
 4126             bSysDriveSelected = FALSE;
 4127 
 4128 #endif  // #ifdef VOLFORMAT
 4129 
 4130             if (!selectedDevice.IsPartition && !selectedDevice.Floppy)
 4131             {
 4132                 // Whole device selected
 4133 
 4134 #ifdef VOLFORMAT
 4135                 if (selectedDevice.ContainsSystem && !selectedDevice.IsPartition)
 4136                 {
 4137                     if (WizardMode != WIZARD_MODE_SYS_DEVICE)
 4138                     {
 4139                         if (bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE))
 4140                         {
 4141                             // disable selection
 4142                             return 1;
 4143                         }
 4144 
 4145                         if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE", hwndDlg) == IDNO)
 4146                         {
 4147                             NormalCursor ();
 4148                             EndDialog (hwndDlg, IDCANCEL);
 4149                             return 1;
 4150                         }
 4151 
 4152                         bSysDriveSelected = TRUE;
 4153                         bSysPartitionSelected = FALSE;
 4154                         lpszFileName[0] = 0;
 4155                         SwitchWizardToSysEncMode ();
 4156 
 4157                         NormalCursor ();
 4158                         EndDialog (hwndDlg, IDOK);
 4159                         return 1;
 4160                     }
 4161                     else
 4162                     {
 4163                         // This should never be the case because the Select Device dialog is not available in this wizard mode
 4164                         bSysDriveSelected = TRUE;
 4165                         bSysPartitionSelected = FALSE;
 4166                         lpszFileName[0] = 0;
 4167                         SwitchWizardToSysEncMode ();
 4168                         NormalCursor ();
 4169                         EndDialog (hwndDlg, IDCANCEL);
 4170                         return 1;
 4171                     }
 4172                 }
 4173 
 4174                 // Disallow format if the device contains partitions, but not if the partition is virtual or system 
 4175                 if (!selectedDevice.IsVirtualPartition
 4176                     && !bHiddenVolDirect)
 4177                 {
 4178                     if (!selectedDevice.Partitions.empty())
 4179                     {
 4180                         EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE);
 4181                         Error ("DEVICE_PARTITIONS_ERR_W_INPLACE_ENC_NOTE", hwndDlg);
 4182                         return 1;
 4183                     }
 4184 
 4185                     if (AskWarnNoYes ("WHOLE_NONSYS_DEVICE_ENC_CONFIRM", hwndDlg) == IDNO)
 4186                         return 1;
 4187                 }
 4188 #else   // #ifdef VOLFORMAT
 4189 
 4190                 bSysDriveSelected = (selectedDevice.ContainsSystem && !selectedDevice.IsPartition);
 4191                 bSysPartitionSelected = FALSE;
 4192 
 4193 #endif  // #ifdef VOLFORMAT
 4194             }
 4195             else 
 4196                 bSysDriveSelected = FALSE;
 4197 
 4198 #ifdef VOLFORMAT
 4199             bRemovableHostDevice = selectedDevice.Removable;
 4200 #endif
 4201             NormalCursor ();
 4202             EndDialog (hwndDlg, IDOK);
 4203             return 1;
 4204         }
 4205 
 4206         if ((msg == WM_COMMAND) && (lw == IDCANCEL))
 4207         {
 4208             NormalCursor ();
 4209             EndDialog (hwndDlg, IDCANCEL);
 4210             return 1;
 4211         }
 4212         return 0;
 4213     }
 4214     return 0;
 4215 }
 4216 
 4217 #endif //!SETUP
 4218 
 4219 BOOL DoDriverInstall (HWND hwndDlg)
 4220 {
 4221 #ifdef SETUP
 4222     if (SystemEncryptionUpdate)
 4223         return TRUE;
 4224 #endif
 4225 
 4226     SC_HANDLE hManager, hService = NULL;
 4227     BOOL bOK = FALSE, bRet;
 4228 
 4229     hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
 4230     if (hManager == NULL)
 4231         goto error;
 4232 
 4233 #ifdef SETUP
 4234     StatusMessage (hwndDlg, "INSTALLING_DRIVER");
 4235 #endif
 4236 
 4237     hService = CreateService (hManager, L"veracrypt", L"veracrypt",
 4238         SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_SYSTEM_START, SERVICE_ERROR_NORMAL,
 4239         L"System32\\drivers\\veracrypt.sys",
 4240         NULL, NULL, NULL, NULL, NULL);
 4241 
 4242     if (hService == NULL)
 4243         goto error;
 4244     else
 4245         CloseServiceHandle (hService);
 4246 
 4247     hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS);
 4248     if (hService == NULL)
 4249         goto error;
 4250 
 4251 #ifdef SETUP
 4252     StatusMessage (hwndDlg, "STARTING_DRIVER");
 4253 #endif
 4254 
 4255     bRet = StartService (hService, 0, NULL);
 4256     if (bRet == FALSE)
 4257         goto error;
 4258 
 4259     bOK = TRUE;
 4260 
 4261 error:
 4262     if (bOK == FALSE && GetLastError () != ERROR_SERVICE_ALREADY_RUNNING)
 4263     {
 4264         handleWin32Error (hwndDlg, SRC_POS);
 4265         MessageBoxW (hwndDlg, GetString ("DRIVER_INSTALL_FAILED"), lpszTitle, MB_ICONHAND);
 4266     }
 4267     else
 4268         bOK = TRUE;
 4269 
 4270     if (hService != NULL)
 4271         CloseServiceHandle (hService);
 4272 
 4273     if (hManager != NULL)
 4274         CloseServiceHandle (hManager);
 4275 
 4276     return bOK;
 4277 }
 4278 
 4279 
 4280 // Install and start driver service and mark it for removal (non-install mode)
 4281 static int DriverLoad ()
 4282 {
 4283     HANDLE file;
 4284     WIN32_FIND_DATA find;
 4285     SC_HANDLE hManager, hService = NULL;
 4286     wchar_t driverPath[TC_MAX_PATH*2];
 4287     BOOL res;
 4288     wchar_t *tmp;
 4289     DWORD startType;
 4290 
 4291     if (ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", L"Start", &startType) && startType == SERVICE_BOOT_START)
 4292         return ERR_PARAMETER_INCORRECT;
 4293 
 4294     GetModuleFileName (NULL, driverPath, ARRAYSIZE (driverPath));
 4295     tmp = wcsrchr (driverPath, L'\\');
 4296     if (!tmp)
 4297     {
 4298         driverPath[0] = L'.';
 4299         driverPath[1] = 0;
 4300     }
 4301     else
 4302         *tmp = 0;
 4303 
 4304     StringCbCatW (driverPath, sizeof(driverPath), !Is64BitOs () ? L"\\veracrypt.sys" : L"\\veracrypt-x64.sys");
 4305 
 4306     file = FindFirstFile (driverPath, &find);
 4307 
 4308     if (file == INVALID_HANDLE_VALUE)
 4309     {
 4310         MessageBoxW (0, GetString ("DRIVER_NOT_FOUND"), lpszTitle, ICON_HAND);
 4311         return ERR_DONT_REPORT;
 4312     }
 4313 
 4314     FindClose (file);
 4315 
 4316     hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
 4317     if (hManager == NULL)
 4318     {
 4319         if (GetLastError () == ERROR_ACCESS_DENIED)
 4320         {
 4321             MessageBoxW (0, GetString ("ADMIN_PRIVILEGES_DRIVER"), lpszTitle, ICON_HAND);
 4322             return ERR_DONT_REPORT;
 4323         }
 4324 
 4325         return ERR_OS_ERROR;
 4326     }
 4327 
 4328     hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS);
 4329     if (hService != NULL)
 4330     {
 4331         // Remove stale service (driver is not loaded but service exists)
 4332         DeleteService (hService);
 4333         CloseServiceHandle (hService);
 4334         Sleep (500);
 4335     }
 4336 
 4337     hService = CreateService (hManager, L"veracrypt", L"veracrypt",
 4338         SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
 4339         driverPath, NULL, NULL, NULL, NULL, NULL);
 4340 
 4341     if (hService == NULL)
 4342     {
 4343         CloseServiceHandle (hManager);
 4344         return ERR_OS_ERROR;
 4345     }
 4346 
 4347     res = StartService (hService, 0, NULL);
 4348     DeleteService (hService);
 4349 
 4350     CloseServiceHandle (hManager);
 4351     CloseServiceHandle (hService);
 4352 
 4353     return !res ? ERR_OS_ERROR : ERROR_SUCCESS;
 4354 }
 4355 
 4356 
 4357 BOOL DriverUnload ()
 4358 {
 4359     MOUNT_LIST_STRUCT driver;
 4360     int refCount;
 4361     int volumesMounted;
 4362     DWORD dwResult;
 4363     BOOL bResult;
 4364 
 4365     SC_HANDLE hManager, hService = NULL;
 4366     BOOL bRet;
 4367     SERVICE_STATUS status;
 4368     int x;
 4369     BOOL driverUnloaded = FALSE;
 4370 
 4371     if (hDriver == INVALID_HANDLE_VALUE)
 4372         return TRUE;
 4373     
 4374     try
 4375     {
 4376         if (BootEncryption (NULL).GetStatus().DeviceFilterActive)
 4377             return FALSE;
 4378     }
 4379     catch (...) { }
 4380 
 4381     // Test for mounted volumes
 4382     bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL);
 4383 
 4384     if (!bResult)
 4385     {
 4386         bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL);
 4387         if (bResult)
 4388             volumesMounted = driver.ulMountedDrives;
 4389     }
 4390 
 4391     if (bResult)
 4392     {
 4393         if (volumesMounted != 0)
 4394             return FALSE;
 4395     }
 4396     else
 4397         return TRUE;
 4398 
 4399     // Test for any applications attached to driver
 4400     refCount = GetDriverRefCount ();
 4401 
 4402     if (refCount > 1)
 4403         return FALSE;
 4404 
 4405     CloseHandle (hDriver);
 4406     hDriver = INVALID_HANDLE_VALUE;
 4407 
 4408     // Stop driver service
 4409 
 4410     hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
 4411     if (hManager == NULL)
 4412         goto error;
 4413 
 4414     hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS);
 4415     if (hService == NULL)
 4416         goto error;
 4417 
 4418     bRet = QueryServiceStatus (hService, &status);
 4419     if (bRet != TRUE)
 4420         goto error;
 4421 
 4422     if (status.dwCurrentState != SERVICE_STOPPED)
 4423     {
 4424         ControlService (hService, SERVICE_CONTROL_STOP, &status);
 4425 
 4426         for (x = 0; x < 10; x++)
 4427         {
 4428             bRet = QueryServiceStatus (hService, &status);
 4429             if (bRet != TRUE)
 4430                 goto error;
 4431 
 4432             if (status.dwCurrentState == SERVICE_STOPPED)
 4433             {
 4434                 driverUnloaded = TRUE;
 4435                 break;
 4436             }
 4437 
 4438             Sleep (200);
 4439         }
 4440     }
 4441     else
 4442         driverUnloaded = TRUE;
 4443 
 4444 error:
 4445     if (hService != NULL)
 4446         CloseServiceHandle (hService);
 4447 
 4448     if (hManager != NULL)
 4449         CloseServiceHandle (hManager);
 4450 
 4451     if (driverUnloaded)
 4452     {
 4453         hDriver = INVALID_HANDLE_VALUE;
 4454         return TRUE;
 4455     }
 4456 
 4457     return FALSE;
 4458 }
 4459 
 4460 
 4461 int DriverAttach (void)
 4462 {
 4463     /* Try to open a handle to the device driver. It will be closed later. */
 4464 
 4465 #ifndef SETUP
 4466 
 4467     int nLoadRetryCount = 0;
 4468 start:
 4469 
 4470 #endif
 4471 
 4472     hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
 4473 
 4474     if (hDriver == INVALID_HANDLE_VALUE)
 4475     {
 4476 #ifndef SETUP
 4477 
 4478         LoadSysEncSettings ();
 4479 
 4480         if (!CreateDriverSetupMutex ())
 4481         {
 4482             // Another instance is already attempting to install, register or start the driver
 4483 
 4484             while (!CreateDriverSetupMutex ())
 4485             {
 4486                 Sleep (100);    // Wait until the other instance finishes
 4487             }
 4488 
 4489             // Try to open a handle to the driver again (keep the mutex in case the other instance failed)
 4490             goto start;     
 4491         }
 4492         else
 4493         {
 4494             // No other instance is currently attempting to install, register or start the driver
 4495 
 4496             if (SystemEncryptionStatus != SYSENC_STATUS_NONE)
 4497             {
 4498                 // This is an inconsistent state. The config file indicates system encryption should be
 4499                 // active, but the driver is not running. This may happen e.g. when the pretest fails and 
 4500                 // the user selects "Last Known Good Configuration" from the Windows boot menu.
 4501                 // To fix this, we're going to reinstall the driver, start it, and register it for boot.
 4502 
 4503                 if (DoDriverInstall (NULL))
 4504                 {
 4505                     Sleep (1000);
 4506                     hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
 4507 
 4508                     try
 4509                     {
 4510                         BootEncryption bootEnc (NULL);
 4511                         bootEnc.RegisterBootDriver (bootEnc.GetHiddenOSCreationPhase() != TC_HIDDEN_OS_CREATION_PHASE_NONE ? true : false);
 4512                     }
 4513                     catch (Exception &e)
 4514                     {
 4515                         e.Show (NULL);
 4516                     }
 4517                 }
 4518 
 4519                 CloseDriverSetupMutex ();
 4520             }
 4521             else
 4522             {
 4523                 // Attempt to load the driver (non-install/portable mode)
 4524 load:
 4525                 BOOL res = DriverLoad ();
 4526 
 4527                 CloseDriverSetupMutex ();
 4528 
 4529                 if (res != ERROR_SUCCESS)
 4530                     return res;
 4531 
 4532                 bPortableModeConfirmed = TRUE;
 4533             
 4534                 if (hDriver != INVALID_HANDLE_VALUE)
 4535                     CloseHandle (hDriver);
 4536                 hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
 4537             }
 4538 
 4539             if (bPortableModeConfirmed)
 4540                 NotifyDriverOfPortableMode ();
 4541         }
 4542 
 4543 #endif  // #ifndef SETUP
 4544 
 4545         if (hDriver == INVALID_HANDLE_VALUE)
 4546             return ERR_OS_ERROR;
 4547     }
 4548 
 4549     CloseDriverSetupMutex ();
 4550 
 4551     if (hDriver != INVALID_HANDLE_VALUE)
 4552     {
 4553         DWORD dwResult;
 4554 
 4555         BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL);
 4556 
 4557         if (!bResult)
 4558             bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL);
 4559 
 4560 #ifndef SETUP // Don't check version during setup to allow removal of another version
 4561         if (bResult == FALSE)
 4562         {
 4563             return ERR_OS_ERROR;
 4564         }
 4565         else if (DriverVersion != VERSION_NUM)
 4566         {
 4567             // Unload an incompatbile version of the driver loaded in non-install mode and load the required version
 4568             if (IsNonInstallMode () && CreateDriverSetupMutex () && DriverUnload () && nLoadRetryCount++ < 3)
 4569                 goto load;
 4570 
 4571             CloseDriverSetupMutex ();
 4572             CloseHandle (hDriver);
 4573             hDriver = INVALID_HANDLE_VALUE;
 4574             return ERR_DRIVER_VERSION;
 4575         }
 4576 #else
 4577         if (!bResult)
 4578             DriverVersion = 0;
 4579 #endif
 4580     }
 4581 
 4582     return 0;
 4583 }
 4584 
 4585 
 4586 void ResetCurrentDirectory ()
 4587 {
 4588     wchar_t p[MAX_PATH];
 4589     if (!IsNonInstallMode () && SHGetFolderPath (NULL, CSIDL_PROFILE, NULL, 0, p) == ERROR_SUCCESS)
 4590     {
 4591         SetCurrentDirectory (p);
 4592     }
 4593     else
 4594     {
 4595         GetModPath (p, ARRAYSIZE (p));
 4596         SetCurrentDirectory (p);
 4597     }
 4598 }
 4599 
 4600 
 4601 BOOL BrowseFiles (HWND hwndDlg, char *stringId, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter)
 4602 {
 4603     return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, browseFilter);
 4604 }
 4605 
 4606 
 4607 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)
 4608 {
 4609     OPENFILENAMEW ofn;
 4610     wchar_t file[TC_MAX_PATH] = { 0 };
 4611     wchar_t filter[1024];
 4612     BOOL status = FALSE;
 4613 
 4614     CoInitialize (NULL);
 4615 
 4616     ZeroMemory (&ofn, sizeof (ofn));
 4617     *lpszFileName = 0;
 4618 
 4619     if (initialDir)
 4620     {
 4621         ofn.lpstrInitialDir         = initialDir;
 4622     }
 4623 
 4624     if (initialFileName)
 4625         StringCchCopyW (file, array_capacity (file), initialFileName);
 4626 
 4627     ofn.lStructSize             = sizeof (ofn);
 4628     ofn.hwndOwner               = hwndDlg;
 4629 
 4630     StringCbPrintfW (filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c",
 4631         GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0);
 4632     ofn.lpstrFilter             = browseFilter ? browseFilter : filter;
 4633     ofn.nFilterIndex            = 1;
 4634     ofn.lpstrFile               = file;
 4635     ofn.nMaxFile                = sizeof (file) / sizeof (file[0]);
 4636     ofn.lpstrTitle              = GetString (stringId);
 4637     ofn.lpstrDefExt             = defaultExtension;
 4638     ofn.Flags                   = OFN_HIDEREADONLY
 4639         | OFN_PATHMUSTEXIST
 4640         | (keepHistory ? 0 : OFN_DONTADDTORECENT)
 4641         | (saveMode ? OFN_OVERWRITEPROMPT : 0);
 4642 
 4643     if (!keepHistory)
 4644         CleanLastVisitedMRU ();
 4645 
 4646     SystemFileSelectorCallerThreadId = GetCurrentThreadId();
 4647     SystemFileSelectorCallPending = TRUE;
 4648 
 4649     if (!saveMode)
 4650     {
 4651         if (!GetOpenFileNameW (&ofn))
 4652             goto ret;
 4653     }
 4654     else
 4655     {
 4656         if (!GetSaveFileNameW (&ofn))
 4657             goto ret;
 4658     }
 4659 
 4660     SystemFileSelectorCallPending = FALSE;
 4661 
 4662     StringCchCopyW (lpszFileName, MAX_PATH, file);
 4663 
 4664     if (!keepHistory)
 4665         CleanLastVisitedMRU ();
 4666 
 4667     status = TRUE;
 4668 
 4669 ret:
 4670     SystemFileSelectorCallPending = FALSE;
 4671     ResetCurrentDirectory();
 4672     CoUninitialize();
 4673 
 4674     return status;
 4675 }
 4676 
 4677 
 4678 static wchar_t SelectMultipleFilesPath[131072];
 4679 static int SelectMultipleFilesOffset;
 4680 
 4681 BOOL SelectMultipleFiles (HWND hwndDlg, const char *stringId, wchar_t *lpszFileName, size_t cbFileName,BOOL keepHistory)
 4682 {
 4683     OPENFILENAMEW ofn;
 4684     wchar_t filter[1024];
 4685     BOOL status = FALSE;
 4686 
 4687     CoInitialize (NULL);
 4688 
 4689     ZeroMemory (&ofn, sizeof (ofn));
 4690 
 4691     SelectMultipleFilesPath[0] = 0;
 4692     *lpszFileName = 0;
 4693     ofn.lStructSize             = sizeof (ofn);
 4694     ofn.hwndOwner               = hwndDlg;
 4695     StringCbPrintfW (filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c",
 4696         GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0);
 4697     ofn.lpstrFilter             = filter;
 4698     ofn.nFilterIndex            = 1;
 4699     ofn.lpstrFile               = SelectMultipleFilesPath;
 4700     ofn.nMaxFile                = 0xffff * 2; // The size must not exceed 0xffff*2 due to a bug in Windows 2000 and XP SP1
 4701     ofn.lpstrTitle              = GetString (stringId);
 4702     ofn.Flags                   = OFN_HIDEREADONLY
 4703         | OFN_EXPLORER
 4704         | OFN_PATHMUSTEXIST
 4705         | OFN_ALLOWMULTISELECT
 4706         | (keepHistory ? 0 : OFN_DONTADDTORECENT);
 4707     
 4708     if (!keepHistory)
 4709         CleanLastVisitedMRU ();
 4710 
 4711     SystemFileSelectorCallerThreadId = GetCurrentThreadId();
 4712     SystemFileSelectorCallPending = TRUE;
 4713 
 4714     if (!GetOpenFileNameW (&ofn))
 4715         goto ret;
 4716 
 4717     SystemFileSelectorCallPending = FALSE;
 4718 
 4719     if (SelectMultipleFilesPath[ofn.nFileOffset - 1] != 0)
 4720     {
 4721         // Single file selected
 4722         StringCbCopyW (lpszFileName, cbFileName, SelectMultipleFilesPath);
 4723         SelectMultipleFilesOffset = 0;
 4724         SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath));
 4725     }
 4726     else
 4727     {
 4728         // Multiple files selected
 4729         SelectMultipleFilesOffset = ofn.nFileOffset;
 4730         SelectMultipleFilesNext (lpszFileName, cbFileName);
 4731     }
 4732 
 4733     if (!keepHistory)
 4734         CleanLastVisitedMRU ();
 4735 
 4736     status = TRUE;
 4737     
 4738 ret:
 4739     SystemFileSelectorCallPending = FALSE;
 4740     ResetCurrentDirectory();
 4741     CoUninitialize();
 4742 
 4743     return status;
 4744 }
 4745 
 4746 
 4747 BOOL SelectMultipleFilesNext (wchar_t *lpszFileName, size_t cbFileName)
 4748 {
 4749     if (SelectMultipleFilesOffset == 0)
 4750         return FALSE;
 4751 
 4752     StringCbCopyW (lpszFileName, cbFileName,SelectMultipleFilesPath);
 4753     lpszFileName[TC_MAX_PATH - 1] = 0;
 4754 
 4755     if (lpszFileName[wcslen (lpszFileName) - 1] != L'\\')
 4756         StringCbCatW (lpszFileName, cbFileName,L"\\");
 4757 
 4758     StringCbCatW (lpszFileName, cbFileName,SelectMultipleFilesPath + SelectMultipleFilesOffset);
 4759 
 4760     SelectMultipleFilesOffset += (int) wcslen (SelectMultipleFilesPath + SelectMultipleFilesOffset) + 1;
 4761     if (SelectMultipleFilesPath[SelectMultipleFilesOffset] == 0)
 4762     {
 4763         SelectMultipleFilesOffset = 0;
 4764         SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath));
 4765     }
 4766 
 4767     return TRUE;
 4768 }
 4769 
 4770 
 4771 static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) 
 4772 {
 4773     switch(uMsg) {
 4774     case BFFM_INITIALIZED: 
 4775     {
 4776       /* WParam is TRUE since we are passing a path.
 4777        It would be FALSE if we were passing a pidl. */
 4778        SendMessageW (hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)pData);
 4779        break;
 4780     }
 4781 
 4782     case BFFM_SELCHANGED: 
 4783     {
 4784         wchar_t szDir[TC_MAX_PATH];
 4785 
 4786        /* Set the status window to the currently selected path. */
 4787        if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir)) 
 4788        {
 4789           SendMessage (hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);
 4790        }
 4791        break;
 4792     }
 4793 
 4794     default:
 4795        break;
 4796     }
 4797 
 4798     return 0;
 4799 }
 4800 
 4801 
 4802 BOOL BrowseDirectories (HWND hwndDlg, char *lpszTitle, wchar_t *dirName)
 4803 {
 4804     BROWSEINFOW bi;
 4805     LPITEMIDLIST pidl;
 4806     LPMALLOC pMalloc;
 4807     BOOL bOK  = FALSE;
 4808 
 4809     CoInitialize (NULL);
 4810 
 4811     if (SUCCEEDED (SHGetMalloc (&pMalloc))) 
 4812     {
 4813         ZeroMemory (&bi, sizeof(bi));
 4814         bi.hwndOwner = hwndDlg;
 4815         bi.pszDisplayName = 0;
 4816         bi.lpszTitle = GetString (lpszTitle);
 4817         bi.pidlRoot = 0;
 4818         bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
 4819         bi.lpfn = BrowseCallbackProc;
 4820         bi.lParam = (LPARAM)dirName;
 4821 
 4822         pidl = SHBrowseForFolderW (&bi);
 4823         if (pidl != NULL) 
 4824         {
 4825             if (SHGetPathFromIDList(pidl, dirName)) 
 4826             {
 4827                 bOK = TRUE;
 4828             }
 4829 
 4830             pMalloc->Free (pidl);
 4831             pMalloc->Release();
 4832         }
 4833     }
 4834 
 4835     CoUninitialize();
 4836 
 4837     return bOK;
 4838 }
 4839 
 4840 
 4841 std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg)
 4842 {
 4843     WCHAR szTmp[8192];
 4844 
 4845     StringCbPrintfW (szTmp, sizeof(szTmp), GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_WRONG" : "PASSWORD_WRONG"));
 4846     if (CheckCapsLock (hwndDlg, TRUE))
 4847         StringCbCatW (szTmp, sizeof(szTmp), GetString ("PASSWORD_WRONG_CAPSLOCK_ON"));
 4848 
 4849 #ifdef TCMOUNT
 4850     wchar_t szDevicePath [TC_MAX_PATH+1] = {0};
 4851     GetWindowText (GetDlgItem (MainDlg, IDC_VOLUME), szDevicePath, ARRAYSIZE (szDevicePath));
 4852 
 4853     if (TCBootLoaderOnInactiveSysEncDrive (szDevicePath))
 4854     {
 4855         StringCbPrintfW (szTmp, sizeof(szTmp), GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_OR_MODE_WRONG" : "PASSWORD_OR_MODE_WRONG"));
 4856 
 4857         if (CheckCapsLock (hwndDlg, TRUE))
 4858             StringCbCatW (szTmp, sizeof(szTmp), GetString ("PASSWORD_WRONG_CAPSLOCK_ON"));
 4859 
 4860         StringCbCatW (szTmp, sizeof(szTmp), GetString ("SYSENC_MOUNT_WITHOUT_PBA_NOTE"));
 4861     }
 4862 #endif
 4863 
 4864     wstring msg = szTmp;
 4865 
 4866 #ifdef TCMOUNT
 4867     if (KeyFilesEnable && HiddenFilesPresentInKeyfilePath)
 4868     {
 4869         msg += GetString ("HIDDEN_FILES_PRESENT_IN_KEYFILE_PATH");
 4870         HiddenFilesPresentInKeyfilePath = FALSE;
 4871     }
 4872 #endif
 4873 
 4874     return msg;
 4875 }
 4876 
 4877 
 4878 void handleError (HWND hwndDlg, int code, const char* srcPos)
 4879 {
 4880     WCHAR szTmp[4096];
 4881 
 4882     if (Silent) return;
 4883 
 4884     switch (code & 0x0000FFFF)
 4885     {
 4886     case ERR_OS_ERROR:
 4887         handleWin32Error (hwndDlg, srcPos);
 4888         break;
 4889     case ERR_OUTOFMEMORY:
 4890         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OUTOFMEMORY"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4891         break;
 4892 
 4893     case ERR_PASSWORD_WRONG:
 4894         MessageBoxW (hwndDlg, AppendSrcPos (GetWrongPasswordErrorMessage (hwndDlg).c_str(), srcPos).c_str(), lpszTitle, MB_ICONWARNING);
 4895         break;
 4896 
 4897     case ERR_DRIVE_NOT_FOUND:
 4898         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NOT_FOUND"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4899         break;
 4900     case ERR_FILES_OPEN:
 4901         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OPENFILES_DRIVER"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4902         break;
 4903     case ERR_FILES_OPEN_LOCK:
 4904         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OPENFILES_LOCK"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4905         break;
 4906     case ERR_VOL_SIZE_WRONG:
 4907         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_SIZE_WRONG"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4908         break;
 4909     case ERR_COMPRESSION_NOT_SUPPORTED:
 4910         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("COMPRESSION_NOT_SUPPORTED"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4911         break;
 4912     case ERR_PASSWORD_CHANGE_VOL_TYPE:
 4913         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("WRONG_VOL_TYPE"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4914         break;
 4915     case ERR_VOL_SEEKING:
 4916         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_SEEKING"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4917         break;
 4918     case ERR_CIPHER_INIT_FAILURE:
 4919         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_CIPHER_INIT_FAILURE"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4920         break;
 4921     case ERR_CIPHER_INIT_WEAK_KEY:
 4922         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_CIPHER_INIT_WEAK_KEY"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4923         break;
 4924     case ERR_VOL_ALREADY_MOUNTED:
 4925         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_ALREADY_MOUNTED"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4926         break;
 4927     case ERR_FILE_OPEN_FAILED:
 4928         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("FILE_OPEN_FAILED"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4929         break;
 4930     case ERR_VOL_MOUNT_FAILED:
 4931         MessageBoxW (hwndDlg, AppendSrcPos (GetString  ("VOL_MOUNT_FAILED"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4932         break;
 4933     case ERR_NO_FREE_DRIVES:
 4934         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NO_FREE_DRIVES"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4935         break;
 4936     case ERR_ACCESS_DENIED:
 4937         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ACCESS_DENIED"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4938         break;
 4939 
 4940     case ERR_DRIVER_VERSION:
 4941         Error ("DRIVER_VERSION", hwndDlg);
 4942         break;
 4943 
 4944     case ERR_NEW_VERSION_REQUIRED:
 4945         MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NEW_VERSION_REQUIRED"), srcPos).c_str(), lpszTitle, ICON_HAND);
 4946         break;
 4947 
 4948     case ERR_SELF_TESTS_FAILED:
 4949         Error ("ERR_SELF_TESTS_FAILED", hwndDlg);
 4950         break;
 4951 
 4952     case ERR_VOL_FORMAT_BAD:
 4953         Error ("ERR_VOL_FORMAT_BAD", hwndDlg);
 4954         break;
 4955 
 4956     case ERR_ENCRYPTION_NOT_COMPLETED:
 4957         Error ("ERR_ENCRYPTION_NOT_COMPLETED", hwndDlg);
 4958         break;
 4959 
 4960     case ERR_NONSYS_INPLACE_ENC_INCOMPLETE:
 4961         Error ("ERR_NONSYS_INPLACE_ENC_INCOMPLETE", hwndDlg);
 4962         break;
 4963 
 4964     case ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG:
 4965         Error ("ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG", hwndDlg);
 4966         break;
 4967 
 4968     case ERR_PARAMETER_INCORRECT:
 4969         Error ("ERR_PARAMETER_INCORRECT", hwndDlg);
 4970         break;
 4971 
 4972     case ERR_USER_ABORT:
 4973     case ERR_DONT_REPORT:
 4974         // A non-error
 4975         break;
 4976 
 4977     case ERR_UNSUPPORTED_TRUECRYPT_FORMAT:
 4978         StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("UNSUPPORTED_TRUECRYPT_FORMAT"), (code >> 24), (code >> 16) & 0x000000FF);
 4979         MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, ICON_HAND);
 4980         break;
 4981 
 4982 #ifndef SETUP
 4983     case ERR_RAND_INIT_FAILED:
 4984         StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("INIT_RAND"), SRC_POS, GetLastError ());
 4985         MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, MB_ICONERROR);
 4986         break;
 4987 
 4988     case ERR_CAPI_INIT_FAILED:
 4989         StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("CAPI_RAND"), SRC_POS, CryptoAPILastError);
 4990         MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, MB_ICONERROR);
 4991         break;
 4992 #endif
 4993 
 4994     default:
 4995         StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("ERR_UNKNOWN"), code);
 4996         MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, ICON_HAND);
 4997     }
 4998 }
 4999 
 5000 
 5001 BOOL CheckFileStreamWriteErrors (HWND hwndDlg, FILE *file, const wchar_t *fileName)
 5002 {
 5003     if (ferror (file))
 5004     {
 5005         wchar_t s[TC_MAX_PATH];
 5006         StringCbPrintfW (s, sizeof (s), GetString ("CANNOT_WRITE_FILE_X"), fileName);
 5007         ErrorDirect (s, hwndDlg);
 5008 
 5009         return FALSE;
 5010     }
 5011 
 5012     return TRUE;
 5013 }
 5014 
 5015 
 5016 static BOOL CALLBACK LocalizeDialogEnum( HWND hwnd, LPARAM font)
 5017 {
 5018     // Localization of controls
 5019 
 5020     if (LocalizationActive)
 5021     {
 5022         int ctrlId = GetDlgCtrlID (hwnd);
 5023         if (ctrlId != 0)
 5024         {
 5025             WCHAR name[10] = { 0 };
 5026             GetClassNameW (hwnd, name, array_capacity (name));
 5027 
 5028             if (_wcsicmp (name, L"Button") == 0 || _wcsicmp (name, L"Static") == 0)
 5029             {
 5030                 wchar_t *str = (wchar_t *) GetDictionaryValueByInt (ctrlId);
 5031                 if (str != NULL)
 5032                     SetWindowTextW (hwnd, str);
 5033             }
 5034         }
 5035     }
 5036 
 5037     // Font
 5038     SendMessageW (hwnd, WM_SETFONT, (WPARAM) font, 0);
 5039     
 5040     return TRUE;
 5041 }
 5042 
 5043 void LocalizeDialog (HWND hwnd, char *stringId)
 5044 {
 5045     LastDialogId = stringId;
 5046     SetWindowLongPtrW (hwnd, GWLP_USERDATA, (LONG_PTR) 'VERA');
 5047     SendMessageW (hwnd, WM_SETFONT, (WPARAM) hUserFont, 0);
 5048 
 5049     if (stringId == NULL)
 5050         SetWindowTextW (hwnd, L"VeraCrypt");
 5051     else
 5052         SetWindowTextW (hwnd, GetString (stringId));
 5053     
 5054     if (hUserFont != 0)
 5055         EnumChildWindows (hwnd, LocalizeDialogEnum, (LPARAM) hUserFont);
 5056 }
 5057 
 5058 void OpenVolumeExplorerWindow (int driveNo)
 5059 {
 5060     wchar_t dosName[5];
 5061     SHFILEINFO fInfo;
 5062 
 5063     StringCbPrintfW (dosName, sizeof(dosName), L"%c:\\", (wchar_t) driveNo + L'A');
 5064 
 5065     // Force explorer to discover the drive
 5066     SHGetFileInfo (dosName, 0, &fInfo, sizeof (fInfo), 0);
 5067 
 5068     ShellExecute (NULL, L"open", dosName, NULL, NULL, SW_SHOWNORMAL);
 5069 }
 5070 
 5071 static BOOL explorerCloseSent;
 5072 static HWND explorerTopLevelWindow;
 5073 
 5074 static BOOL CALLBACK CloseVolumeExplorerWindowsChildEnum (HWND hwnd, LPARAM driveStr)
 5075 {
 5076     WCHAR s[MAX_PATH];
 5077     SendMessageW (hwnd, WM_GETTEXT, array_capacity (s), (LPARAM) s);
 5078 
 5079     if (wcsstr (s, (WCHAR *) driveStr) != NULL)
 5080     {
 5081         PostMessageW (explorerTopLevelWindow, WM_CLOSE, 0, 0);
 5082         explorerCloseSent = TRUE;
 5083         return FALSE;
 5084     }
 5085 
 5086     return TRUE;
 5087 }
 5088 
 5089 static BOOL CALLBACK CloseVolumeExplorerWindowsEnum (HWND hwnd, LPARAM driveNo)
 5090 {
 5091     WCHAR driveStr[10];
 5092     WCHAR s[MAX_PATH];
 5093 
 5094     StringCbPrintfW (driveStr, sizeof(driveStr), L"%c:\\", driveNo + L'A');
 5095 
 5096     GetClassNameW (hwnd, s, array_capacity (s));
 5097     if (wcscmp (s, L"CabinetWClass") == 0)
 5098     {
 5099         GetWindowTextW (hwnd, s, array_capacity (s));
 5100         if (wcsstr (s, driveStr) != NULL)
 5101         {
 5102             PostMessageW (hwnd, WM_CLOSE, 0, 0);
 5103             explorerCloseSent = TRUE;
 5104             return TRUE;
 5105         }
 5106 
 5107         explorerTopLevelWindow = hwnd;
 5108         EnumChildWindows (hwnd, CloseVolumeExplorerWindowsChildEnum, (LPARAM) driveStr);
 5109     }
 5110 
 5111     return TRUE;
 5112 }
 5113 
 5114 BOOL CloseVolumeExplorerWindows (HWND hwnd, int driveNo)
 5115 {
 5116     if (driveNo >= 0)
 5117     {
 5118         explorerCloseSent = FALSE;
 5119         EnumWindows (CloseVolumeExplorerWindowsEnum, (LPARAM) driveNo);
 5120     }
 5121 
 5122     return explorerCloseSent;
 5123 }
 5124 
 5125 BOOL UpdateDriveCustomLabel (int driveNo, wchar_t* effectiveLabel, BOOL bSetValue)
 5126 {
 5127     wchar_t wszRegPath[MAX_PATH];
 5128     wchar_t driveStr[] = {L'A' + (wchar_t) driveNo, 0};
 5129     HKEY hKey;
 5130     LSTATUS lStatus;
 5131     DWORD cbLabelLen = (DWORD) ((wcslen (effectiveLabel) + 1) * sizeof (wchar_t));
 5132     BOOL bToBeDeleted = FALSE;
 5133 
 5134     StringCbPrintfW (wszRegPath, sizeof (wszRegPath), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%s\\DefaultLabel", driveStr);   
 5135     
 5136     if (bSetValue)
 5137         lStatus = RegCreateKeyExW (HKEY_CURRENT_USER, wszRegPath, NULL, NULL, 0, 
 5138             KEY_READ | KEY_WRITE | KEY_SET_VALUE, NULL, &hKey, NULL);
 5139     else
 5140         lStatus = RegOpenKeyExW (HKEY_CURRENT_USER, wszRegPath, 0, KEY_READ | KEY_WRITE | KEY_SET_VALUE, &hKey);
 5141     if (ERROR_SUCCESS == lStatus)
 5142     {
 5143         if (bSetValue)
 5144             lStatus = RegSetValueExW (hKey, NULL, NULL, REG_SZ, (LPCBYTE) effectiveLabel, cbLabelLen);
 5145         else
 5146         {
 5147             wchar_t storedLabel[34] = {0};
 5148             DWORD cbStoredLen = sizeof (storedLabel) - 1, dwType;
 5149             lStatus = RegQueryValueExW (hKey, NULL, NULL, &dwType, (LPBYTE) storedLabel, &cbStoredLen);
 5150             if ((ERROR_SUCCESS == lStatus) && (REG_SZ == dwType) && (0 == wcscmp(storedLabel, effectiveLabel)))
 5151             {
 5152                 // same label stored. mark key for deletion
 5153                 bToBeDeleted = TRUE;
 5154             }
 5155         }
 5156         RegCloseKey (hKey);
 5157     }
 5158 
 5159     if (bToBeDeleted)
 5160     {
 5161         StringCbPrintfW (wszRegPath, sizeof (wszRegPath), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%s", driveStr); 
 5162         lStatus = RegOpenKeyExW (HKEY_CURRENT_USER, wszRegPath, 0, KEY_READ | KEY_WRITE | KEY_SET_VALUE, &hKey);
 5163         if (ERROR_SUCCESS == lStatus)
 5164         {
 5165             lStatus = RegDeleteKeyW (hKey, L"DefaultLabel");
 5166             RegCloseKey (hKey);
 5167         }
 5168 
 5169         // delete drive letter of nothing else is present under it
 5170         RegDeleteKeyW (HKEY_CURRENT_USER, wszRegPath);
 5171 
 5172     }
 5173 
 5174     return (ERROR_SUCCESS == lStatus)? TRUE : FALSE;
 5175 }
 5176 
 5177 wstring GetUserFriendlyVersionString (int version)
 5178 {
 5179     wchar_t szTmp [64];
 5180     StringCbPrintfW (szTmp, sizeof(szTmp), L"%x", version);
 5181 
 5182     wstring versionString (szTmp);
 5183 
 5184     versionString.insert (version > 0xfff ? 2 : 1,L".");
 5185 
 5186     return (versionString);
 5187 }
 5188 
 5189 wstring IntToWideString (int val)
 5190 {
 5191     wchar_t szTmp [64];
 5192     StringCbPrintfW (szTmp, sizeof(szTmp), L"%d", val);
 5193 
 5194     return szTmp;
 5195 }
 5196 
 5197 wstring ArrayToHexWideString (const unsigned char* pbData, int cbData)
 5198 {
 5199     static wchar_t* hexChar = L"0123456789ABCDEF";
 5200     wstring result;
 5201     if (pbData)
 5202     {
 5203         for (int i = 0; i < cbData; i++)
 5204         {
 5205             result += hexChar[pbData[i] >> 4];
 5206             result += hexChar[pbData[i] & 0x0F];
 5207         }
 5208     }
 5209 
 5210     return result;
 5211 }
 5212 
 5213 bool HexToByte (wchar_t c, byte& b)
 5214 {
 5215     bool bRet = true;
 5216     if (c >= L'0' && c <= L'9')
 5217         b = (byte) (c - L'0');
 5218     else if (c >= L'a' && c <= L'z')
 5219         b = (byte) (c - L'a' + 10);
 5220     else if (c >= L'A' && c <= L'Z')
 5221         b = (byte) (c - L'A' + 10);
 5222     else
 5223         bRet = false;
 5224 
 5225     return bRet;
 5226 }
 5227 
 5228 bool HexWideStringToArray (const wchar_t* hexStr, std::vector<byte>& arr)
 5229 {
 5230     byte b1, b2;
 5231     size_t i, len = wcslen (hexStr);
 5232 
 5233     arr.clear();
 5234     if (len %2)
 5235         return false;
 5236     
 5237     for (i = 0; i < len/2; i++)
 5238     {
 5239         if (!HexToByte (*hexStr++, b1) || !HexToByte (*hexStr++, b2))
 5240             return false;
 5241         arr.push_back (b1 << 4 | b2);
 5242     }
 5243     return true;
 5244 }
 5245 
 5246 wstring GetTempPathString ()
 5247 {
 5248     wchar_t tempPath[MAX_PATH];
 5249     DWORD tempLen = ::GetTempPath (ARRAYSIZE (tempPath), tempPath);
 5250     if (tempLen == 0 || tempLen > ARRAYSIZE (tempPath))
 5251         throw ParameterIncorrect (SRC_POS);
 5252 
 5253     return wstring (tempPath);
 5254 }
 5255 
 5256 void GetSizeString (unsigned __int64 size, wchar_t *str, size_t cbStr)
 5257 {
 5258     static wchar_t *b, *kb, *mb, *gb, *tb, *pb;
 5259     static int serNo;
 5260 
 5261     if (b == NULL || serNo != LocalizationSerialNo)
 5262     {
 5263         serNo = LocalizationSerialNo;
 5264         kb = GetString ("KB");
 5265         mb = GetString ("MB");
 5266         gb = GetString ("GB");
 5267         tb = GetString ("TB");
 5268         pb = GetString ("PB");
 5269         b = GetString ("BYTE");
 5270     }
 5271 
 5272     if (size > 1024I64*1024*1024*1024*1024*99)
 5273         StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024/1024/1024/1024/1024, pb);
 5274     else if (size > 1024I64*1024*1024*1024*1024)
 5275         StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024/1024/1024), pb);
 5276     else if (size > 1024I64*1024*1024*1024*99)
 5277         StringCbPrintfW (str, cbStr, L"%I64d %s",size/1024/1024/1024/1024, tb);
 5278     else if (size > 1024I64*1024*1024*1024)
 5279         StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024/1024), tb);
 5280     else if (size > 1024I64*1024*1024*99)
 5281         StringCbPrintfW (str, cbStr, L"%I64d %s",size/1024/1024/1024, gb);
 5282     else if (size > 1024I64*1024*1024)
 5283         StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024), gb);
 5284     else if (size > 1024I64*1024*99)
 5285         StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024/1024, mb);
 5286     else if (size > 1024I64*1024)
 5287         StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024), mb);
 5288     else if (size >= 1024I64)
 5289         StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024, kb);
 5290     else
 5291         StringCbPrintfW (str, cbStr, L"%I64d %s", size, b);
 5292 }
 5293 
 5294 #ifndef SETUP
 5295 void GetSpeedString (unsigned __int64 speed, wchar_t *str, size_t cbStr)
 5296 {
 5297     static wchar_t *b, *kb, *mb, *gb, *tb, *pb;
 5298     static int serNo;
 5299     
 5300     if (b == NULL || serNo != LocalizationSerialNo)
 5301     {
 5302         serNo = LocalizationSerialNo;
 5303         kb = GetString ("KB_PER_SEC");
 5304         mb = GetString ("MB_PER_SEC");
 5305         gb = GetString ("GB_PER_SEC");
 5306         tb = GetString ("TB_PER_SEC");
 5307         pb = GetString ("PB_PER_SEC");
 5308         b = GetString ("B_PER_SEC");
 5309     }
 5310 
 5311     if (speed > 1024I64*1024*1024*1024*1024*99)
 5312         StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024/1024/1024/1024/1024, pb);
 5313     else if (speed > 1024I64*1024*1024*1024*1024)
 5314         StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024/1024), pb);
 5315     else if (speed > 1024I64*1024*1024*1024*99)
 5316         StringCbPrintfW (str, cbStr, L"%I64d %s",speed/1024/1024/1024/1024, tb);
 5317     else if (speed > 1024I64*1024*1024*1024)
 5318         StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024), tb);
 5319     else if (speed > 1024I64*1024*1024*99)
 5320         StringCbPrintfW (str, cbStr, L"%I64d %s",speed/1024/1024/1024, gb);
 5321     else if (speed > 1024I64*1024*1024)
 5322         StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024), gb);
 5323     else if (speed > 1024I64*1024*99)
 5324         StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024/1024, mb);
 5325     else if (speed > 1024I64*1024)
 5326         StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024), mb);
 5327     else if (speed > 1024I64)
 5328         StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024, kb);
 5329     else
 5330         StringCbPrintfW (str, cbStr, L"%I64d %s", speed, b);
 5331 }
 5332 
 5333 static void ResetBenchmarkList (HWND hwndDlg)
 5334 {
 5335     LVCOLUMNW LvCol;
 5336 
 5337     HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS);
 5338 
 5339     /* Render the results */
 5340     // delete data
 5341     SendMessage (hList, LVM_DELETEALLITEMS, 0, 0);
 5342     // Delete headers
 5343     SendMessageW (hList, LVM_DELETECOLUMN, 1, 0);
 5344     SendMessageW (hList, LVM_DELETECOLUMN, 1, 0);
 5345     SendMessageW (hList, LVM_DELETECOLUMN, 1, 0);
 5346 
 5347     memset (&LvCol,0,sizeof(LvCol));               
 5348     LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT;  
 5349     switch(benchmarkType) {
 5350     case BENCHMARK_TYPE_ENCRYPTION:
 5351         // Create headers
 5352         LvCol.pszText = GetString ("ENCRYPTION");
 5353         LvCol.cx = CompensateXDPI (80);
 5354         LvCol.fmt = LVCFMT_RIGHT;
 5355         SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol);
 5356 
 5357         LvCol.pszText = GetString ("DECRYPTION");
 5358         LvCol.cx = CompensateXDPI (80);
 5359         LvCol.fmt = LVCFMT_RIGHT;
 5360         SendMessageW (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol);
 5361 
 5362         LvCol.pszText = GetString ("MEAN");
 5363         LvCol.cx = CompensateXDPI (80);
 5364         LvCol.fmt = LVCFMT_RIGHT;
 5365         SendMessageW (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol);
 5366         break;
 5367     case BENCHMARK_TYPE_HASH:
 5368         LvCol.pszText = GetString ("MEAN");
 5369         LvCol.cx = CompensateXDPI (80);
 5370         LvCol.fmt = LVCFMT_RIGHT;
 5371         SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol);
 5372         break;
 5373     case BENCHMARK_TYPE_PRF:
 5374         LvCol.pszText = GetString ("TIME");
 5375         LvCol.cx = CompensateXDPI (80);
 5376         LvCol.fmt = LVCFMT_RIGHT;
 5377         SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol);
 5378 
 5379         LvCol.pszText = GetString ("ITERATIONS");
 5380         LvCol.cx = CompensateXDPI (80);
 5381         LvCol.fmt = LVCFMT_RIGHT;
 5382         SendMessageW (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol);
 5383         break;
 5384     }
 5385 }
 5386 
 5387 static void DisplayBenchmarkResults (HWND hwndDlg)
 5388 {
 5389     wchar_t item1[100]={0};
 5390     LVITEMW LvItem;
 5391     HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS);
 5392     int ea, i;
 5393     BOOL unsorted = TRUE;
 5394     BENCHMARK_REC tmp_line;
 5395 
 5396     ResetBenchmarkList (hwndDlg);
 5397 
 5398     /* Sort the list */
 5399 
 5400     switch (benchmarkSortMethod)
 5401     {
 5402     case BENCHMARK_SORT_BY_SPEED:
 5403 
 5404         while (unsorted)
 5405         {
 5406             unsorted = FALSE;
 5407             for (i = 0; i < benchmarkTotalItems - 1; i++)
 5408             {
 5409 
 5410                 if (((benchmarkType == BENCHMARK_TYPE_PRF) && (benchmarkTable[i].meanBytesPerSec > benchmarkTable[i+1].meanBytesPerSec)) ||
 5411                      ((benchmarkType != BENCHMARK_TYPE_PRF) && (benchmarkTable[i].meanBytesPerSec < benchmarkTable[i+1].meanBytesPerSec))
 5412                     )
 5413                 {
 5414                     unsorted = TRUE;
 5415                     memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC));
 5416                     memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC));
 5417                     memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC));
 5418                 }
 5419             }
 5420         }
 5421         break;
 5422 
 5423     case BENCHMARK_SORT_BY_NAME:
 5424 
 5425         while (unsorted)
 5426         {
 5427             unsorted = FALSE;
 5428             for (i = 0; i < benchmarkTotalItems - 1; i++)
 5429             {
 5430                 if (benchmarkTable[i].id > benchmarkTable