VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/Dlgcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/Dlgcode.c')
-rw-r--r--src/Common/Dlgcode.c7278
1 files changed, 5430 insertions, 1848 deletions
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c
index c15da303..681761bf 100644
--- a/src/Common/Dlgcode.c
+++ b/src/Common/Dlgcode.c
@@ -5,33 +5,39 @@
governed by the TrueCrypt License 3.0, also from the source code of
Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
and which is governed by the 'License Agreement for Encryption for the Masses'
Modifications and additions to the original source code (contained in this file)
- and all other portions of this file are Copyright (c) 2013-2016 IDRIX
+ and all other portions of this file are Copyright (c) 2013-2017 IDRIX
and are governed by the Apache License 2.0 the full text of which is
contained in the file License.txt included in VeraCrypt binary and source
code distribution packages. */
#include "Tcdefs.h"
#include <windowsx.h>
+#include <versionhelpers.h>
#include <dbghelp.h>
#include <dbt.h>
#include <Setupapi.h>
+#include <aclapi.h>
+#include <Netlistmgr.h>
#include <fcntl.h>
#include <io.h>
#include <math.h>
#include <shlobj.h>
+#include <shlwapi.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
#include <tchar.h>
#include <Richedit.h>
-#ifdef TCMOUNT
-#include <Shlwapi.h>
+#if defined (TCMOUNT) || defined (VOLFORMAT)
#include <process.h>
#include <Tlhelp32.h>
#endif
+#if _WIN32_WINNT >= 0x0602
+#include "processthreadsapi.h"
+#endif
#include "Resource.h"
#include "Platform/Finally.h"
@@ -58,8 +64,11 @@
#include "Xml.h"
#include "Xts.h"
#include "Boot/Windows/BootCommon.h"
#include "Progress.h"
+#include "zip.h"
+#include "rdrand.h"
+#include "jitterentropy.h"
#ifdef TCMOUNT
#include "Mount/Mount.h"
#include "Mount/resource.h"
@@ -72,10 +81,55 @@
#ifdef SETUP
#include "Setup/Setup.h"
#endif
+#include <Setupapi.h>
+#include <Softpub.h>
+#include <WinTrust.h>
#include <strsafe.h>
+#define _WIN32_DCOM
+#include <comdef.h>
+#include <Wbemidl.h>
+
+#pragma comment(lib, "wbemuuid.lib")
+#pragma comment(lib, "Shlwapi.lib")
+#pragma comment(lib, "setupapi.lib" )
+#pragma comment(lib, "Wintrust.lib" )
+#pragma comment(lib, "Comctl32.lib" )
+
+#ifndef TTI_INFO_LARGE
+#define TTI_INFO_LARGE 4
+#endif
+
+#ifndef TTI_WARNING_LARGE
+#define TTI_WARNING_LARGE 5
+#endif
+
+#ifndef TTI_ERROR_LARGE
+#define TTI_ERROR_LARGE 6
+#endif
+
+/* GPT Partition Type GUIDs */
+#define LOCAL_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID name = {l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8}
+LOCAL_DEFINE_GUID(PARTITION_ENTRY_UNUSED_GUID, 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); // Entry unused
+LOCAL_DEFINE_GUID(PARTITION_SYSTEM_GUID, 0xC12A7328L, 0xF81F, 0x11D2, 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B); // EFI system partition
+LOCAL_DEFINE_GUID(PARTITION_MSFT_RESERVED_GUID, 0xE3C9E316L, 0x0B5C, 0x4DB8, 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE); // Microsoft reserved space
+LOCAL_DEFINE_GUID(PARTITION_BASIC_DATA_GUID, 0xEBD0A0A2L, 0xB9E5, 0x4433, 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7); // Basic data partition
+LOCAL_DEFINE_GUID(PARTITION_LDM_METADATA_GUID, 0x5808C8AAL, 0x7E8F, 0x42E0, 0x85, 0xD2, 0xE1, 0xE9, 0x04, 0x34, 0xCF, 0xB3); // Logical Disk Manager metadata partition
+LOCAL_DEFINE_GUID(PARTITION_LDM_DATA_GUID, 0xAF9B60A0L, 0x1431, 0x4F62, 0xBC, 0x68, 0x33, 0x11, 0x71, 0x4A, 0x69, 0xAD); // Logical Disk Manager data partition
+LOCAL_DEFINE_GUID(PARTITION_MSFT_RECOVERY_GUID, 0xDE94BBA4L, 0x06D1, 0x4D40, 0xA1, 0x6A, 0xBF, 0xD5, 0x01, 0x79, 0xD6, 0xAC); // Microsoft recovery partition
+LOCAL_DEFINE_GUID(PARTITION_CLUSTER_GUID, 0xdb97dba9L, 0x0840, 0x4bae, 0x97, 0xf0, 0xff, 0xb9, 0xa3, 0x27, 0xc7, 0xe1); // Cluster metadata partition
+
+#ifndef PROCESSOR_ARCHITECTURE_ARM64
+#define PROCESSOR_ARCHITECTURE_ARM64 12
+#endif
+
+#ifndef IMAGE_FILE_MACHINE_ARM64
+#define IMAGE_FILE_MACHINE_ARM64 0xAA64
+#endif
+
+
using namespace VeraCrypt;
LONG DriverVersion;
@@ -113,24 +167,36 @@ BOOL bShowDisconnectedNetworkDrives = FALSE;
BOOL bHideWaitingDialog = FALSE;
BOOL bCmdHideWaitingDialog = FALSE;
BOOL bCmdHideWaitingDialogValid = FALSE;
BOOL bUseSecureDesktop = FALSE;
+BOOL bUseLegacyMaxPasswordLength = FALSE;
BOOL bCmdUseSecureDesktop = FALSE;
BOOL bCmdUseSecureDesktopValid = FALSE;
BOOL bStartOnLogon = FALSE;
BOOL bMountDevicesOnLogon = FALSE;
BOOL bMountFavoritesOnLogon = FALSE;
BOOL bHistory = FALSE;
+#ifndef SETUP
+BOOL bLanguageSetInSetup = FALSE;
+#else
+extern BOOL bMakePackage;
+#endif
+
+#ifdef TCMOUNT
+extern BOOL ServiceMode;
+#endif
+
// Status of detection of hidden sectors (whole-system-drive encryption).
// 0 - Unknown/undetermined/completed, 1: Detection is or was in progress (but did not complete e.g. due to system crash).
int HiddenSectorDetectionStatus = 0;
OSVersionEnum nCurrentOS = WIN_UNKNOWN;
int CurrentOSMajor = 0;
int CurrentOSMinor = 0;
int CurrentOSServicePack = 0;
+int CurrentOSBuildNumber = 0;
BOOL RemoteSession = FALSE;
BOOL UacElevated = FALSE;
BOOL bPortableModeConfirmed = FALSE; // TRUE if it is certain that the instance is running in portable mode
@@ -140,16 +206,23 @@ BOOL bInPlaceEncNonSysPending = FALSE; // TRUE if the non-system in-place encry
/* Globals used by Mount and Format (separately per instance) */
BOOL PimEnable = FALSE;
BOOL KeyFilesEnable = FALSE;
KeyFile *FirstKeyFile = NULL;
-KeyFilesDlgParam defaultKeyFilesParam;
+KeyFilesDlgParam defaultKeyFilesParam = {0};
BOOL IgnoreWmDeviceChange = FALSE;
BOOL DeviceChangeBroadcastDisabled = FALSE;
BOOL LastMountedVolumeDirty;
BOOL MountVolumesAsSystemFavorite = FALSE;
BOOL FavoriteMountOnArrivalInProgress = FALSE;
BOOL MultipleMountOperationInProgress = FALSE;
+BOOL EMVSupportEnabled = FALSE;
+
+volatile BOOL NeedPeriodicDeviceListUpdate = FALSE;
+BOOL DisablePeriodicDeviceListUpdate = FALSE;
+BOOL EnableMemoryProtection = FALSE;
+
+BOOL MemoryProtectionActivated = FALSE;
BOOL WaitDialogDisplaying = FALSE;
/* Handle to the device driver */
@@ -172,8 +245,22 @@ volatile HANDLE hAppSetupMutex = NULL;
/* Critical section used to protect access to global variables used in WNetGetConnection calls */
CRITICAL_SECTION csWNetCalls;
+/* Critical section used to protect access to global list of physical drives */
+CRITICAL_SECTION csMountableDevices;
+CRITICAL_SECTION csVolumeIdCandidates;
+
+static std::vector<HostDevice> mountableDevices;
+static std::vector<HostDevice> rawHostDeviceList;
+
+/* Critical section used to ensure that only one thread at a time can create a secure desktop */
+CRITICAL_SECTION csSecureDesktop;
+
+/* Boolean that indicates if our Secure Desktop is active and being used or not */
+volatile BOOL bSecureDesktopOngoing = FALSE;
+TCHAR SecureDesktopName[65];
+
HINSTANCE hInst = NULL;
HCURSOR hCursor = NULL;
ATOM hDlgClass, hSplashClass;
@@ -207,94 +294,31 @@ DWORD SystemFileSelectorCallerThreadId;
#define RANDPOOL_DISPLAY_REFRESH_INTERVAL 30
#define RANDPOOL_DISPLAY_ROWS 16
#define RANDPOOL_DISPLAY_COLUMNS 20
-HMODULE hRichEditDll = NULL;
-HMODULE hComctl32Dll = NULL;
-HMODULE hSetupDll = NULL;
-HMODULE hShlwapiDll = NULL;
-HMODULE hProfApiDll = NULL;
-HMODULE hUsp10Dll = NULL;
-HMODULE hCryptSpDll = NULL;
-HMODULE hUXThemeDll = NULL;
-HMODULE hUserenvDll = NULL;
-HMODULE hRsaenhDll = NULL;
-HMODULE himm32dll = NULL;
-HMODULE hMSCTFdll = NULL;
-HMODULE hfltlibdll = NULL;
-HMODULE hframedyndll = NULL;
-HMODULE hpsapidll = NULL;
-HMODULE hsecur32dll = NULL;
-HMODULE hnetapi32dll = NULL;
-HMODULE hauthzdll = NULL;
-HMODULE hxmllitedll = NULL;
-HMODULE hmprdll = NULL;
-HMODULE hsppdll = NULL;
-HMODULE vssapidll = NULL;
-HMODULE hvsstracedll = NULL;
-HMODULE hcfgmgr32dll = NULL;
-HMODULE hdevobjdll = NULL;
-HMODULE hpowrprofdll = NULL;
-HMODULE hsspiclidll = NULL;
-HMODULE hcryptbasedll = NULL;
-HMODULE hdwmapidll = NULL;
-HMODULE hmsasn1dll = NULL;
-HMODULE hcrypt32dll = NULL;
-HMODULE hbcryptdll = NULL;
-HMODULE hbcryptprimitivesdll = NULL;
-HMODULE hMsls31 = NULL;
-HMODULE hntmartadll = NULL;
-HMODULE hwinscarddll = NULL;
-
-#define FREE_DLL(h) if (h) { FreeLibrary (h); h = NULL;}
-
-#ifndef BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE
-#define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE 0x00000001
-#endif
-
-#ifndef BASE_SEARCH_PATH_PERMANENT
-#define BASE_SEARCH_PATH_PERMANENT 0x00008000
-#endif
#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
#endif
-
-typedef BOOL (WINAPI *SetDllDirectoryPtr)(LPCWSTR lpPathName);
-typedef BOOL (WINAPI *SetSearchPathModePtr)(DWORD Flags);
typedef BOOL (WINAPI *SetDefaultDllDirectoriesPtr)(DWORD DirectoryFlags);
+static unsigned char gpbSha512CodeSignCertFingerprint[64] = {
+ 0x9C, 0xA0, 0x21, 0xD3, 0x7C, 0x90, 0x61, 0x88, 0xEF, 0x5F, 0x99, 0x3D,
+ 0x54, 0x9F, 0xB8, 0xCE, 0x72, 0x32, 0x4F, 0x57, 0x4F, 0x19, 0xD2, 0xA4,
+ 0xDC, 0x84, 0xFF, 0xE2, 0x84, 0x2B, 0xD4, 0x30, 0xAB, 0xA7, 0xE4, 0x63,
+ 0x18, 0xD1, 0xD8, 0x32, 0x0E, 0xA4, 0x81, 0x3C, 0x19, 0xBF, 0x13, 0x11,
+ 0xA4, 0x37, 0xD6, 0xDB, 0x26, 0xBA, 0xDC, 0x8F, 0x86, 0x96, 0x55, 0x96,
+ 0xDB, 0x6F, 0xC0, 0x62
+};
-typedef void (WINAPI *InitCommonControlsPtr)(void);
-typedef HIMAGELIST (WINAPI *ImageList_CreatePtr)(int cx, int cy, UINT flags, int cInitial, int cGrow);
-typedef int (WINAPI *ImageList_AddPtr)(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask);
-
-typedef VOID (WINAPI *SetupCloseInfFilePtr)(HINF InfHandle);
-typedef HKEY (WINAPI *SetupDiOpenClassRegKeyPtr)(CONST GUID *ClassGuid,REGSAM samDesired);
-typedef BOOL (WINAPI *SetupInstallFromInfSectionWPtr)(HWND,HINF,PCWSTR,UINT,HKEY,PCWSTR,UINT,PSP_FILE_CALLBACK_W,PVOID,HDEVINFO,PSP_DEVINFO_DATA);
-typedef HINF (WINAPI *SetupOpenInfFileWPtr)(PCWSTR FileName,PCWSTR InfClass,DWORD InfStyle,PUINT ErrorLine);
-
-typedef LSTATUS (STDAPICALLTYPE *SHDeleteKeyWPtr)(HKEY hkey, LPCWSTR pszSubKey);
-
-typedef HRESULT (STDAPICALLTYPE *SHStrDupWPtr)(LPCWSTR psz, LPWSTR *ppwsz);
-
-// ChangeWindowMessageFilter
-typedef BOOL (WINAPI *ChangeWindowMessageFilterPtr) (UINT, DWORD);
-
-SetDllDirectoryPtr SetDllDirectoryFn = NULL;
-SetSearchPathModePtr SetSearchPathModeFn = NULL;
-SetDefaultDllDirectoriesPtr SetDefaultDllDirectoriesFn = NULL;
-
-ImageList_CreatePtr ImageList_CreateFn = NULL;
-ImageList_AddPtr ImageList_AddFn = NULL;
-
-SetupCloseInfFilePtr SetupCloseInfFileFn = NULL;
-SetupDiOpenClassRegKeyPtr SetupDiOpenClassRegKeyFn = NULL;
-SetupInstallFromInfSectionWPtr SetupInstallFromInfSectionWFn = NULL;
-SetupOpenInfFileWPtr SetupOpenInfFileWFn = NULL;
-SHDeleteKeyWPtr SHDeleteKeyWFn = NULL;
-SHStrDupWPtr SHStrDupWFn = NULL;
-ChangeWindowMessageFilterPtr ChangeWindowMessageFilterFn = NULL;
+static unsigned char gpbSha512MSCodeSignCertFingerprint[64] = {
+ 0xEB, 0x76, 0x2E, 0xD3, 0x5B, 0x4A, 0xB1, 0x0E, 0xF5, 0x3B, 0x99, 0x4E,
+ 0xC1, 0xF7, 0x48, 0x88, 0xF6, 0xA0, 0xE9, 0xAC, 0x32, 0x69, 0xCF, 0x20,
+ 0xE1, 0x60, 0xC4, 0x0C, 0xEF, 0x01, 0x1F, 0xCB, 0x41, 0x95, 0x72, 0xB9,
+ 0xED, 0x63, 0x0C, 0x6B, 0xB9, 0xE9, 0xA2, 0x72, 0xA6, 0x78, 0x96, 0x4C,
+ 0x69, 0x9F, 0x90, 0x3F, 0xB1, 0x3C, 0x64, 0xF2, 0xAB, 0xCF, 0x14, 0x1D,
+ 0xEC, 0x7C, 0xB0, 0xC7
+};
/* Windows dialog class */
#define WINDOWS_DIALOG_CLASS L"#32770"
@@ -367,11 +391,874 @@ typedef struct
} MULTI_CHOICE_DLGPROC_PARAMS;
+
+
+// Loads a 32-bit integer from the file at the specified file offset. The saved value is assumed to have been
+// processed by mputLong(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE).
+BOOL LoadInt32 (const wchar_t *filePath, unsigned __int32 *result, __int64 fileOffset)
+{
+ DWORD bufSize = sizeof(__int32);
+ unsigned char *buffer = (unsigned char *) malloc (bufSize);
+ unsigned char *bufferPtr = buffer;
+ HANDLE src = NULL;
+ DWORD bytesRead;
+ LARGE_INTEGER seekOffset, seekOffsetNew;
+ BOOL retVal = FALSE;
+
+ if (buffer == NULL)
+ return -1;
+
+ src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (src == INVALID_HANDLE_VALUE)
+ {
+ free (buffer);
+ return FALSE;
+ }
+
+ seekOffset.QuadPart = fileOffset;
+
+ if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0)
+ goto fsif_end;
+
+ if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0
+ || bytesRead != bufSize)
+ goto fsif_end;
+
+
+ retVal = TRUE;
+
+ *result = mgetLong(bufferPtr);
+
+fsif_end:
+ CloseHandle (src);
+ free (buffer);
+
+ return retVal;
+}
+
+// Loads a 16-bit integer from the file at the specified file offset. The saved value is assumed to have been
+// processed by mputWord(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE).
+BOOL LoadInt16 (const wchar_t *filePath, int *result, __int64 fileOffset)
+{
+ DWORD bufSize = sizeof(__int16);
+ unsigned char *buffer = (unsigned char *) malloc (bufSize);
+ unsigned char *bufferPtr = buffer;
+ HANDLE src = NULL;
+ DWORD bytesRead;
+ LARGE_INTEGER seekOffset, seekOffsetNew;
+ BOOL retVal = FALSE;
+
+ if (buffer == NULL)
+ return -1;
+
+ src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (src == INVALID_HANDLE_VALUE)
+ {
+ free (buffer);
+ return FALSE;
+ }
+
+ seekOffset.QuadPart = fileOffset;
+
+ if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0)
+ goto fsif_end;
+
+ if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0
+ || bytesRead != bufSize)
+ goto fsif_end;
+
+
+ retVal = TRUE;
+
+ *result = mgetWord(bufferPtr);
+
+fsif_end:
+ CloseHandle (src);
+ free (buffer);
+
+ return retVal;
+}
+
+// Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated.
+char *LoadFile (const wchar_t *fileName, DWORD *size)
+{
+ char *buf;
+ DWORD fileSize = INVALID_FILE_SIZE;
+ HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ *size = 0;
+ if (h == INVALID_HANDLE_VALUE)
+ return NULL;
+
+ if ((fileSize = GetFileSize (h, NULL)) == INVALID_FILE_SIZE)
+ {
+ CloseHandle (h);
+ return NULL;
+ }
+
+ buf = (char *) calloc (fileSize + 1, 1);
+
+ if (buf == NULL)
+ {
+ CloseHandle (h);
+ return NULL;
+ }
+
+ if (!ReadFile (h, buf, fileSize, size, NULL))
+ {
+ free (buf);
+ buf = NULL;
+ }
+ else
+ {
+ buf[*size] = 0; //make coverity happy eventhough buf is guaranteed to be null terminated because of fileSize+1 in calloc call
+ }
+
+ CloseHandle (h);
+ return buf;
+}
+
+
+// Returns NULL if there's any error.
+char *LoadFileBlock (const wchar_t *fileName, __int64 fileOffset, DWORD count)
+{
+ char *buf;
+ DWORD bytesRead = 0;
+ LARGE_INTEGER seekOffset, seekOffsetNew;
+ BOOL bStatus;
+
+ HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return NULL;
+
+ seekOffset.QuadPart = fileOffset;
+
+ if (SetFilePointerEx (h, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0)
+ {
+ CloseHandle (h);
+ return NULL;
+ }
+
+ buf = (char *) calloc (count, 1);
+
+ if (buf == NULL)
+ {
+ CloseHandle (h);
+ return NULL;
+ }
+
+ bStatus = ReadFile (h, buf, count, &bytesRead, NULL);
+
+ CloseHandle (h);
+
+ if (!bStatus || (bytesRead != count))
+ {
+ free (buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
+
+// Returns -1 if there is an error, or the size of the file.
+__int64 GetFileSize64 (const wchar_t *path)
+{
+ HANDLE h = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ LARGE_INTEGER size;
+ __int64 retSize = -1;
+
+ if (h)
+ {
+ if (GetFileSizeEx (h, &size))
+ {
+ retSize = size.QuadPart;
+ }
+
+ CloseHandle (h);
+ }
+
+ return retSize;
+}
+
+// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file
+// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE).
+BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed)
+{
+ HANDLE dst;
+ DWORD bytesWritten;
+ BOOL res = TRUE;
+ DWORD dwLastError = 0;
+#if defined(SETUP) && !defined (PORTABLE)
+ BOOL securityModified = FALSE;
+ SECURITY_INFO_BACKUP secBackup = { 0 };
+ const wchar_t* existingFile = destinationFile;
+#endif
+
+ dst = CreateFile (destinationFile,
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
+
+ dwLastError = GetLastError();
+ if (!bAppend && bRenameIfFailed && (dst == INVALID_HANDLE_VALUE) && (GetLastError () == ERROR_SHARING_VIOLATION || GetLastError() == ERROR_ACCESS_DENIED))
+ {
+ wchar_t renamedPath[TC_MAX_PATH + 1];
+ StringCbCopyW (renamedPath, sizeof(renamedPath), destinationFile);
+ StringCbCatW (renamedPath, sizeof(renamedPath), VC_FILENAME_RENAMED_SUFFIX);
+
+#if defined(SETUP) && !defined (PORTABLE)
+ // Take ownership of the file
+ securityModified = ModifyFileSecurityPermissions(destinationFile, &secBackup);
+#endif
+ /* rename the locked file in order to be able to create a new one */
+ if (MoveFileEx (destinationFile, renamedPath, MOVEFILE_REPLACE_EXISTING))
+ {
+ dst = CreateFile (destinationFile,
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
+ dwLastError = GetLastError();
+ if (dst == INVALID_HANDLE_VALUE)
+ {
+ /* restore the original file name */
+ MoveFileEx (renamedPath, destinationFile, MOVEFILE_REPLACE_EXISTING);
+ }
+ else
+ {
+#if defined(SETUP) && !defined (PORTABLE)
+ existingFile = renamedPath;
+#endif
+ /* delete the renamed file when the machine reboots */
+ MoveFileEx (renamedPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+ }
+ }
+#if defined(SETUP) && !defined (PORTABLE)
+ if (securityModified)
+ {
+ RestoreSecurityInfo(existingFile, &secBackup);
+ FreeSecurityBackup(&secBackup);
+ }
+#endif
+ }
+
+ if (dst == INVALID_HANDLE_VALUE)
+ {
+ SetLastError (dwLastError);
+ handleWin32Error (MainDlg, SRC_POS);
+ return FALSE;
+ }
+
+ if (bAppend)
+ SetFilePointer (dst, 0, NULL, FILE_END);
+
+ if (!WriteFile (dst, inputBuffer, inputLength, &bytesWritten, NULL)
+ || inputLength != bytesWritten)
+ {
+ res = FALSE;
+ }
+
+ if (!res)
+ {
+ // If CREATE_ALWAYS is used, ERROR_ALREADY_EXISTS is returned after successful overwrite
+ // of an existing file (it's not an error)
+ if (! (GetLastError() == ERROR_ALREADY_EXISTS && !bAppend) )
+ handleWin32Error (MainDlg, SRC_POS);
+ }
+
+ CloseHandle (dst);
+
+ if (!res && !bAppend)
+ _wremove (destinationFile);
+
+ return res;
+}
+
+
+// Returns -1 if the specified string is not found in the buffer. Otherwise, returns the
+// offset of the first occurrence of the string. The string and the buffer may contain zeroes,
+// which do NOT terminate them.
+int64 FindString (const char *buf, const char *str, int64 bufLen, int64 strLen, int64 startOffset)
+{
+ if (buf == NULL
+ || str == NULL
+ || strLen > bufLen
+ || bufLen < 1
+ || strLen < 1
+ || startOffset > bufLen - strLen)
+ {
+ return -1;
+ }
+
+ for (int64 i = startOffset; i <= bufLen - strLen; i++)
+ {
+ if (memcmp (buf + i, str, (size_t) strLen) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+// Returns TRUE if the file or directory exists (both may be enclosed in quotation marks).
+BOOL FileExists (const wchar_t *filePathPtr)
+{
+ wchar_t filePath [TC_MAX_PATH * 2 + 1];
+
+ // Strip quotation marks (if any)
+ if (filePathPtr [0] == L'"')
+ {
+ StringCbCopyW (filePath, sizeof(filePath), filePathPtr + 1);
+ }
+ else
+ {
+ StringCbCopyW (filePath, sizeof(filePath), filePathPtr);
+ }
+
+ // Strip quotation marks (if any)
+ if (filePath [wcslen (filePath) - 1] == L'"')
+ filePath [wcslen (filePath) - 1] = 0;
+
+ return (_waccess (filePath, 0) != -1);
+}
+
+
+// Searches the file from its end for the LAST occurrence of the string str.
+// The string may contain zeroes, which do NOT terminate the string.
+// If the string is found, its offset from the start of the file is returned.
+// If the string isn't found or if any error occurs, -1 is returned.
+__int64 FindStringInFile (const wchar_t *filePath, const char* str, int strLen)
+{
+ int bufSize = 64 * BYTES_PER_KB;
+ char *buffer = (char *) err_malloc (bufSize);
+ HANDLE src = NULL;
+ DWORD bytesRead;
+ BOOL readRetVal;
+ __int64 filePos = GetFileSize64 (filePath);
+ int bufPos = 0;
+ LARGE_INTEGER seekOffset, seekOffsetNew;
+ BOOL bExit = FALSE;
+ int filePosStep;
+ __int64 retVal = -1;
+
+ if (filePos <= 0
+ || buffer == NULL
+ || strLen > bufSize
+ || strLen < 1)
+ {
+ if (buffer)
+ free (buffer);
+ return -1;
+ }
+
+ src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (src == INVALID_HANDLE_VALUE)
+ {
+ free (buffer);
+ return -1;
+ }
+
+ filePosStep = bufSize - strLen + 1;
+
+ do
+ {
+ filePos -= filePosStep;
+
+ if (filePos < 0)
+ {
+ filePos = 0;
+ bExit = TRUE;
+ }
+
+ seekOffset.QuadPart = filePos;
+
+ if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0)
+ goto fsif_end;
+
+ if ((readRetVal = ReadFile (src, buffer, bufSize, &bytesRead, NULL)) == 0
+ || bytesRead == 0)
+ goto fsif_end;
+
+ bufPos = bytesRead - strLen;
+
+ while (bufPos > 0)
+ {
+ if (memcmp (buffer + bufPos, str, strLen) == 0)
+ {
+ // String found
+ retVal = filePos + bufPos;
+ goto fsif_end;
+ }
+ bufPos--;
+ }
+
+ } while (!bExit);
+
+fsif_end:
+ CloseHandle (src);
+ free (buffer);
+
+ return retVal;
+}
+
+// System CopyFile() copies source file attributes (like FILE_ATTRIBUTE_ENCRYPTED)
+// so we need to use our own copy function
+BOOL TCCopyFileBase (HANDLE src, HANDLE dst)
+{
+ __int8 *buffer;
+ FILETIME fileTime;
+ DWORD bytesRead, bytesWritten;
+ BOOL res;
+
+ buffer = (char *) malloc (64 * 1024);
+ if (!buffer)
+ {
+ CloseHandle (src);
+ CloseHandle (dst);
+ return FALSE;
+ }
+
+ while (res = ReadFile (src, buffer, 64 * 1024, &bytesRead, NULL))
+ {
+ if (bytesRead == 0)
+ {
+ res = 1;
+ break;
+ }
+
+ if (!WriteFile (dst, buffer, bytesRead, &bytesWritten, NULL)
+ || bytesRead != bytesWritten)
+ {
+ res = 0;
+ break;
+ }
+ }
+
+ if (GetFileTime (src, NULL, NULL, &fileTime))
+ SetFileTime (dst, NULL, NULL, &fileTime);
+
+ CloseHandle (src);
+ CloseHandle (dst);
+
+ free (buffer);
+ return res != 0;
+}
+
+BOOL TCCopyFile (wchar_t *sourceFileName, wchar_t *destinationFile)
+{
+ HANDLE src, dst;
+
+ src = CreateFileW (sourceFileName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (src == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ dst = CreateFileW (destinationFile,
+ GENERIC_WRITE,
+ 0, NULL, CREATE_ALWAYS, 0, NULL);
+
+ if (dst == INVALID_HANDLE_VALUE)
+ {
+ CloseHandle (src);
+ return FALSE;
+ }
+
+ return TCCopyFileBase (src, dst);
+}
+
+
+BOOL VerifyModuleSignature (const wchar_t* path)
+{
+#if defined(NDEBUG) && !defined (VC_SKIP_OS_DRIVER_REQ_CHECK)
+ BOOL bResult = FALSE;
+ HRESULT hResult;
+ GUID gActionID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
+ WINTRUST_FILE_INFO fileInfo = {0};
+ WINTRUST_DATA WVTData = {0};
+ wchar_t filePath [TC_MAX_PATH + 1024];
+
+ // Strip quotation marks (if any)
+ if (path [0] == L'"')
+ {
+ StringCbCopyW (filePath, sizeof(filePath), path + 1);
+ }
+ else
+ {
+ StringCbCopyW (filePath, sizeof(filePath), path);
+ }
+
+ // Strip quotation marks (if any)
+ if (filePath [wcslen (filePath) - 1] == L'"')
+ filePath [wcslen (filePath) - 1] = 0;
+
+ fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
+ fileInfo.pcwszFilePath = filePath;
+ fileInfo.hFile = NULL;
+
+ WVTData.cbStruct = sizeof(WINTRUST_DATA);
+ WVTData.dwUIChoice = WTD_UI_NONE;
+ WVTData.fdwRevocationChecks = WTD_REVOKE_NONE;
+ WVTData.dwUnionChoice = WTD_CHOICE_FILE;
+ WVTData.pFile = &fileInfo;
+ WVTData.dwStateAction = WTD_STATEACTION_VERIFY;
+ WVTData.dwProvFlags = WTD_REVOCATION_CHECK_NONE | WTD_CACHE_ONLY_URL_RETRIEVAL;
+
+ hResult = WinVerifyTrust(0, &gActionID, &WVTData);
+ if (0 == hResult)
+ {
+ PCRYPT_PROVIDER_DATA pProviderData = WTHelperProvDataFromStateData (WVTData.hWVTStateData);
+ if (pProviderData)
+ {
+ PCRYPT_PROVIDER_SGNR pProviderSigner = WTHelperGetProvSignerFromChain (pProviderData, 0, FALSE, 0);
+ if (pProviderSigner)
+ {
+ PCRYPT_PROVIDER_CERT pProviderCert = WTHelperGetProvCertFromChain (pProviderSigner, 0);
+ if (pProviderCert && (pProviderCert->pCert))
+ {
+ BYTE hashVal[64];
+ sha512 (hashVal, pProviderCert->pCert->pbCertEncoded, pProviderCert->pCert->cbCertEncoded);
+
+ if ( (0 == memcmp (hashVal, gpbSha512CodeSignCertFingerprint, 64))
+ || (0 == memcmp (hashVal, gpbSha512MSCodeSignCertFingerprint, 64))
+ )
+ {
+ bResult = TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ WVTData.dwUIChoice = WTD_UI_NONE;
+ WVTData.dwStateAction = WTD_STATEACTION_CLOSE;
+ WinVerifyTrust(0, &gActionID, &WVTData);
+
+ return bResult;
+#else
+ return TRUE;
+#endif
+}
+
+DWORD handleWin32Error (HWND hwndDlg, const char* srcPos)
+{
+#ifndef VC_COMREG
+ PWSTR lpMsgBuf;
+ DWORD dwError = GetLastError ();
+ wchar_t szErrorValue[32];
+ wchar_t* pszDesc;
+
+ if (Silent || dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE)
+ return dwError;
+
+ // Access denied
+ if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ())
+ {
+ ErrorDirect ( AppendSrcPos (GetString ("ERR_ACCESS_DENIED"), srcPos).c_str (), hwndDlg);
+ SetLastError (dwError); // Preserve the original error code
+ return dwError;
+ }
+
+ FormatMessageW (
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ dwError,
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+ (PWSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+
+ if (lpMsgBuf)
+ pszDesc = (wchar_t*) lpMsgBuf;
+ else
+ {
+ StringCchPrintfW (szErrorValue, ARRAYSIZE (szErrorValue), L"Error 0x%.8X", dwError);
+ pszDesc = szErrorValue;
+ }
+
+ MessageBoxW (hwndDlg, AppendSrcPos (pszDesc, srcPos).c_str (), lpszTitle, ICON_HAND);
+ if (lpMsgBuf) LocalFree (lpMsgBuf);
+
+ // User-friendly hardware error explanation
+ if (IsDiskError (dwError))
+ Error ("ERR_HARDWARE_ERROR", hwndDlg);
+
+ // Device not ready
+ if (dwError == ERROR_NOT_READY)
+ HandleDriveNotReadyError(hwndDlg);
+
+ SetLastError (dwError); // Preserve the original error code
+
+ return dwError;
+#else
+ return GetLastError();
+#endif
+}
+
+int Error (char *stringId, HWND hwnd)
+{
+#ifndef VC_COMREG
+ if (Silent) return 0;
+ return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR);
+#else
+ return 0;
+#endif
+}
+
+BOOL IsOSAtLeast (OSVersionEnum reqMinOS)
+{
+ return IsOSVersionAtLeast (reqMinOS, 0);
+}
+
+
+// Returns TRUE if the operating system is at least reqMinOS and service pack at least reqMinServicePack.
+// Example 1: IsOSVersionAtLeast (WIN_VISTA, 1) called under Windows 2008, returns TRUE.
+// Example 2: IsOSVersionAtLeast (WIN_XP, 3) called under Windows XP SP1, returns FALSE.
+// Example 3: IsOSVersionAtLeast (WIN_XP, 3) called under Windows Vista SP1, returns TRUE.
+BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack)
+{
+ /* When updating this function, update IsOSAtLeast() in Ntdriver.c too. */
+
+ if (CurrentOSMajor <= 0)
+ TC_THROW_FATAL_EXCEPTION;
+
+ int major = 0, minor = 0;
+
+ switch (reqMinOS)
+ {
+ case WIN_2000: major = 5; minor = 0; break;
+ case WIN_XP: major = 5; minor = 1; break;
+ case WIN_SERVER_2003: major = 5; minor = 2; break;
+ case WIN_VISTA: major = 6; minor = 0; break;
+ case WIN_7: major = 6; minor = 1; break;
+ case WIN_8: major = 6; minor = 2; break;
+ case WIN_8_1: major = 6; minor = 3; break;
+ case WIN_10: major = 10; minor = 0; break;
+
+ default:
+ TC_THROW_FATAL_EXCEPTION;
+ break;
+ }
+
+ return ((CurrentOSMajor << 16 | CurrentOSMinor << 8 | CurrentOSServicePack)
+ >= (major << 16 | minor << 8 | reqMinServicePack));
+}
+
+BOOL IsWin10BuildAtLeast(DWORD minBuild)
+{
+ // Must first be recognized as Windows 10 or higher
+ if (nCurrentOS < WIN_10)
+ return FALSE;
+
+ // If we’re on Windows 10, check build number
+ if (nCurrentOS == WIN_10 && CurrentOSBuildNumber < minBuild)
+ return FALSE;
+
+ // If we are on a higher version of Windows, we are good to go
+ return TRUE;
+}
+
+#ifdef SETUP_DLL
+static BOOL GetWindowVersionFromFile(DWORD* pdwMajor, DWORD* pdwMinor, DWORD* pdwBuildNumber)
+{
+ wchar_t dllPath[MAX_PATH];
+ BOOL bRet = FALSE;
+ LPBYTE versionInfo = NULL;
+ UINT size;
+ VS_FIXEDFILEINFO *vinfo;
+
+ /* Load dll explictely from System32 to avoid Dll hijacking attacks*/
+ if (!GetSystemDirectory(dllPath, MAX_PATH))
+ StringCbCopyW(dllPath, sizeof(dllPath), L"C:\\Windows\\System32");
+
+ StringCbCatW(dllPath, sizeof(dllPath), L"\\");
+ StringCbCatW(dllPath, sizeof(dllPath), L"Kernel32.dll");
+
+ size = GetFileVersionInfoSizeW(dllPath, NULL);
+ if (size)
+ {
+ versionInfo = (LPBYTE) TCalloc(size);
+ if (GetFileVersionInfo(dllPath, 0, size, versionInfo))
+ {
+
+ if (VerQueryValueW(versionInfo, L"\\", (LPVOID *)&vinfo, &size) && (size >=sizeof(VS_FIXEDFILEINFO)))
+ {
+ *pdwMajor = HIWORD(vinfo->dwProductVersionMS);
+ *pdwMinor = LOWORD(vinfo->dwProductVersionMS);
+ *pdwBuildNumber = HIWORD(vinfo->dwProductVersionLS);
+ bRet = TRUE;
+ }
+ }
+ }
+
+ if (versionInfo)
+ TCfree(versionInfo);
+ return bRet;
+}
+#endif
+
+/*
+ * Use RtlGetVersion to get Windows version because GetVersionEx is affected by application manifestation.
+ */
+typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
+
+static BOOL GetWindowsVersion(LPOSVERSIONINFOW lpVersionInformation)
+{
+ BOOL bRet = FALSE;
+#ifdef SETUP_DLL
+ DWORD dwMajor, dwMinor, dwBuildNumber;
+#endif
+ RtlGetVersionPtr RtlGetVersionFn = (RtlGetVersionPtr) GetProcAddress(GetModuleHandle (L"ntdll.dll"), "RtlGetVersion");
+ if (RtlGetVersionFn != NULL)
+ {
+ if (ERROR_SUCCESS == RtlGetVersionFn (lpVersionInformation))
+ bRet = TRUE;
+ }
+
+#ifdef SETUP_DLL
+ // we get real version from Kernel32.dll version since MSI always sets current version to 6.0
+ // https://stackoverflow.com/questions/49335885/windows-10-not-detecting-on-installshield/49343826#49343826
+ if (GetWindowVersionFromFile(&dwMajor, &dwMinor, &dwBuildNumber))
+ {
+ lpVersionInformation->dwMajorVersion = dwMajor;
+ lpVersionInformation->dwMinorVersion = dwMinor;
+ lpVersionInformation->dwBuildNumber = dwBuildNumber;
+ }
+#endif
+
+ return bRet;
+}
+
+
+void InitOSVersionInfo ()
+{
+ OSVERSIONINFOEXW os;
+ os.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
+
+ if (GetWindowsVersion ((LPOSVERSIONINFOW) &os) == FALSE)
+ AbortProcess ("NO_OS_VER");
+
+ CurrentOSMajor = os.dwMajorVersion;
+ CurrentOSMinor = os.dwMinorVersion;
+ CurrentOSServicePack = os.wServicePackMajor;
+ CurrentOSBuildNumber = os.dwBuildNumber;
+
+ if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 0)
+ nCurrentOS = WIN_2000;
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 1)
+ nCurrentOS = WIN_XP;
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 2)
+ {
+ if (os.wProductType == VER_NT_SERVER || os.wProductType == VER_NT_DOMAIN_CONTROLLER)
+ nCurrentOS = WIN_SERVER_2003;
+ else
+ nCurrentOS = WIN_XP64;
+ }
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 0)
+ {
+ if (os.wProductType != VER_NT_WORKSTATION)
+ nCurrentOS = WIN_SERVER_2008;
+ else
+ nCurrentOS = WIN_VISTA;
+ }
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 1)
+ nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2008_R2 : WIN_7);
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 2)
+ nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012 : WIN_8);
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 3)
+ nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012_R2 : WIN_8_1);
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 10 && CurrentOSMinor == 0)
+ nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2016 : WIN_10);
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 4)
+ nCurrentOS = WIN_NT4;
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 0)
+ nCurrentOS = WIN_95;
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 10)
+ nCurrentOS = WIN_98;
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 90)
+ nCurrentOS = WIN_ME;
+ else if (os.dwPlatformId == VER_PLATFORM_WIN32s)
+ nCurrentOS = WIN_31;
+ else
+ nCurrentOS = WIN_UNKNOWN;
+}
+
+#pragma warning(push)
+#pragma warning(disable:4702)
+
+void *err_malloc (size_t size)
+{
+ void *z = (void *) TCalloc (size);
+ if (z)
+ return z;
+ AbortProcess ("OUTOFMEMORY");
+ return 0;
+}
+
+#pragma warning(pop)
+
+
+char *err_strdup (char *lpszText)
+{
+ size_t j = (strlen (lpszText) + 1) * sizeof (char);
+ char *z = (char *) err_malloc (j);
+ memmove (z, lpszText, j);
+ return z;
+}
+
+void AbortProcessDirect (wchar_t *abortMsg)
+{
+ // Note that this function also causes localcleanup() to be called (see atexit())
+ MessageBeep (MB_ICONEXCLAMATION);
+ MessageBoxW (NULL, abortMsg, lpszTitle, ICON_HAND);
+ exit (1);
+}
+
+void AbortProcess (char *stringId)
+{
+ // Note that this function also causes localcleanup() to be called (see atexit())
+#ifndef VC_COMREG
+ AbortProcessDirect (GetString (stringId));
+#else
+ static wchar_t g_wszUnknown[1024];
+ StringCbPrintfW (g_wszUnknown, sizeof(g_wszUnknown), UNKNOWN_STRING_ID L"%hs" UNKNOWN_STRING_ID, stringId);
+ AbortProcessDirect (g_wszUnknown);
+#endif
+}
+
+#ifndef VC_COMREG
+void AbortProcessSilent (void)
+{
+ // Note that this function also causes localcleanup() to be called (see atexit())
+ exit (1);
+}
+
+void InitGlobalLocks ()
+{
+ InitializeCriticalSection (&csWNetCalls);
+ InitializeCriticalSection (&csMountableDevices);
+ InitializeCriticalSection (&csVolumeIdCandidates);
+ InitializeCriticalSection (&csSecureDesktop);
+}
+
+void FinalizeGlobalLocks ()
+{
+ DeleteCriticalSection (&csWNetCalls);
+ DeleteCriticalSection (&csMountableDevices);
+ DeleteCriticalSection (&csVolumeIdCandidates);
+ DeleteCriticalSection (&csSecureDesktop);
+}
+
void cleanup ()
{
burn (&CmdTokenPin, sizeof (CmdTokenPin));
+#ifndef SETUP
+ KeyFileRemoveAll (&FirstKeyFile);
+ KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile);
+#endif
/* Cleanup the GDI fonts */
if (hFixedFont != NULL)
DeleteObject (hFixedFont);
@@ -445,9 +1332,9 @@ void cleanup ()
EncryptionThreadPoolStop();
#endif
- DeleteCriticalSection (&csWNetCalls);
+ FinalizeGlobalLocks ();
}
void LowerCaseCopy (wchar_t *lpszDest, const wchar_t *lpszSource)
@@ -463,13 +1350,13 @@ void LowerCaseCopy (wchar_t *lpszDest, const wchar_t *lpszSource)
}
void UpperCaseCopy (wchar_t *lpszDest, size_t cbDest, const wchar_t *lpszSource)
{
- if (lpszDest && cbDest)
+ if (lpszDest && (cbDest >= 2))
{
size_t i = wcslen (lpszSource);
- if (i >= cbDest)
- i = cbDest - 1;
+ if (i >= (cbDest/2))
+ i = (cbDest/2) - 1;
lpszDest[i] = 0;
i++;
while (--i > 0)
@@ -522,8 +1409,22 @@ size_t TrimWhiteSpace(wchar_t *str)
return out_size;
}
+BOOL IsNullTerminateString (const wchar_t* str, size_t cbSize)
+{
+ if (str && cbSize)
+ {
+ for (size_t i = 0; i < cbSize; i++)
+ {
+ if (str[i] == 0)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
// check the validity of a file name
BOOL IsValidFileName(const wchar_t* str)
{
static wchar_t invalidChars[9] = {L'<', L'>', L':', L'"', L'/', L'\\', L'|', L'?', L'*'};
@@ -599,129 +1500,8 @@ int RemoveFakeDosName (wchar_t *lpszDiskFile, wchar_t *lpszDosDevice)
return 0;
}
-void AbortProcessDirect (wchar_t *abortMsg)
-{
- // Note that this function also causes localcleanup() to be called (see atexit())
- MessageBeep (MB_ICONEXCLAMATION);
- MessageBoxW (NULL, abortMsg, lpszTitle, ICON_HAND);
- FREE_DLL (hRichEditDll);
- FREE_DLL (hComctl32Dll);
- FREE_DLL (hSetupDll);
- FREE_DLL (hShlwapiDll);
- FREE_DLL (hProfApiDll);
- FREE_DLL (hUsp10Dll);
- FREE_DLL (hCryptSpDll);
- FREE_DLL (hUXThemeDll);
- FREE_DLL (hUserenvDll);
- FREE_DLL (hRsaenhDll);
- FREE_DLL (himm32dll);
- FREE_DLL (hMSCTFdll);
- FREE_DLL (hfltlibdll);
- FREE_DLL (hframedyndll);
- FREE_DLL (hpsapidll);
- FREE_DLL (hsecur32dll);
- FREE_DLL (hnetapi32dll);
- FREE_DLL (hauthzdll);
- FREE_DLL (hxmllitedll);
- FREE_DLL (hmprdll);
- FREE_DLL (hsppdll);
- FREE_DLL (vssapidll);
- FREE_DLL (hvsstracedll);
- FREE_DLL (hCryptSpDll);
- FREE_DLL (hcfgmgr32dll);
- FREE_DLL (hdevobjdll);
- FREE_DLL (hpowrprofdll);
- FREE_DLL (hsspiclidll);
- FREE_DLL (hcryptbasedll);
- FREE_DLL (hdwmapidll);
- FREE_DLL (hmsasn1dll);
- FREE_DLL (hcrypt32dll);
- FREE_DLL (hbcryptdll);
- FREE_DLL (hbcryptprimitivesdll);
- FREE_DLL (hMsls31);
- FREE_DLL (hntmartadll);
- FREE_DLL (hwinscarddll);
-
- exit (1);
-}
-
-void AbortProcess (char *stringId)
-{
- // Note that this function also causes localcleanup() to be called (see atexit())
- AbortProcessDirect (GetString (stringId));
-}
-
-void AbortProcessSilent (void)
-{
- FREE_DLL (hRichEditDll);
- FREE_DLL (hComctl32Dll);
- FREE_DLL (hSetupDll);
- FREE_DLL (hShlwapiDll);
- FREE_DLL (hProfApiDll);
- FREE_DLL (hUsp10Dll);
- FREE_DLL (hCryptSpDll);
- FREE_DLL (hUXThemeDll);
- FREE_DLL (hUserenvDll);
- FREE_DLL (hRsaenhDll);
- FREE_DLL (himm32dll);
- FREE_DLL (hMSCTFdll);
- FREE_DLL (hfltlibdll);
- FREE_DLL (hframedyndll);
- FREE_DLL (hpsapidll);
- FREE_DLL (hsecur32dll);
- FREE_DLL (hnetapi32dll);
- FREE_DLL (hauthzdll);
- FREE_DLL (hxmllitedll);
- FREE_DLL (hmprdll);
- FREE_DLL (hsppdll);
- FREE_DLL (vssapidll);
- FREE_DLL (hvsstracedll);
- FREE_DLL (hCryptSpDll);
- FREE_DLL (hcfgmgr32dll);
- FREE_DLL (hdevobjdll);
- FREE_DLL (hpowrprofdll);
- FREE_DLL (hsspiclidll);
- FREE_DLL (hcryptbasedll);
- FREE_DLL (hdwmapidll);
- FREE_DLL (hmsasn1dll);
- FREE_DLL (hcrypt32dll);
- FREE_DLL (hbcryptdll);
- FREE_DLL (hbcryptprimitivesdll);
- FREE_DLL (hMsls31);
- FREE_DLL (hntmartadll);
- FREE_DLL (hwinscarddll);
-
- // Note that this function also causes localcleanup() to be called (see atexit())
- exit (1);
-}
-
-
-#pragma warning(push)
-#pragma warning(disable:4702)
-
-void *err_malloc (size_t size)
-{
- void *z = (void *) TCalloc (size);
- if (z)
- return z;
- AbortProcess ("OUTOFMEMORY");
- return 0;
-}
-
-#pragma warning(pop)
-
-
-char *err_strdup (char *lpszText)
-{
- size_t j = (strlen (lpszText) + 1) * sizeof (char);
- char *z = (char *) err_malloc (j);
- memmove (z, lpszText, j);
- return z;
-}
-
-
BOOL IsDiskReadError (DWORD error)
{
return (error == ERROR_CRC
|| error == ERROR_IO_DEVICE
@@ -748,61 +1528,8 @@ BOOL IsDiskError (DWORD error)
{
return IsDiskReadError (error) || IsDiskWriteError (error);
}
-
-DWORD handleWin32Error (HWND hwndDlg, const char* srcPos)
-{
- PWSTR lpMsgBuf;
- DWORD dwError = GetLastError ();
- wchar_t szErrorValue[32];
- wchar_t* pszDesc;
-
- if (Silent || dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE)
- return dwError;
-
- // Access denied
- if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ())
- {
- ErrorDirect ( AppendSrcPos (GetString ("ERR_ACCESS_DENIED"), srcPos).c_str (), hwndDlg);
- SetLastError (dwError); // Preserve the original error code
- return dwError;
- }
-
- FormatMessageW (
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- dwError,
- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
- (PWSTR) &lpMsgBuf,
- 0,
- NULL
- );
-
- if (lpMsgBuf)
- pszDesc = (wchar_t*) lpMsgBuf;
- else
- {
- StringCchPrintfW (szErrorValue, ARRAYSIZE (szErrorValue), L"Error 0x%.8X", dwError);
- pszDesc = szErrorValue;
- }
-
- MessageBoxW (hwndDlg, AppendSrcPos (pszDesc, srcPos).c_str (), lpszTitle, ICON_HAND);
- if (lpMsgBuf) LocalFree (lpMsgBuf);
-
- // User-friendly hardware error explanation
- if (IsDiskError (dwError))
- Error ("ERR_HARDWARE_ERROR", hwndDlg);
-
- // Device not ready
- if (dwError == ERROR_NOT_READY)
- HandleDriveNotReadyError(hwndDlg);
-
- SetLastError (dwError); // Preserve the original error code
-
- return dwError;
-}
-
BOOL translateWin32Error (wchar_t *lpszMsgBuf, int nWSizeOfBuf)
{
DWORD dwError = GetLastError ();
@@ -1058,8 +1785,90 @@ void AccommodateTextField (HWND hwndDlg, UINT ctrlId, BOOL bFirstUpdate, HFONT h
InvalidateRect (hwndCtrl, NULL, TRUE);
}
}
+// Resizes width of a checkbox according to actual width in pixels of its label text (font size is taken into account)
+void AccommodateCheckBoxTextWidth (HWND hwndDlg, UINT ctrlId)
+{
+ RECT rec;
+ HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId);
+ int width, origWidth, origHeight;
+ int horizSubOffset;
+ wchar_t text [MAX_URL_LENGTH];
+ HFONT hFont = (HFONT) SendDlgItemMessage (hwndDlg, ctrlId, WM_GETFONT, 0, 0);
+
+ // Resize the field according to its length and font size and move if centered or right-aligned
+
+ GetWindowTextW (hwndCtrl, text, sizeof (text) / sizeof (wchar_t));
+
+ width = GetTextGfxWidth (hwndCtrl, text, hFont);
+
+ // add to width variable value the width of the checkbox square. We use SM_CXMENUCHECK which is a little larger than actual width
+ width += GetSystemMetrics(SM_CXMENUCHECK);
+
+
+ GetClientRect (hwndCtrl, &rec);
+ origWidth = rec.right;
+ origHeight = rec.bottom;
+
+ if (width >= 0
+ && (origWidth > width)) // The original width of the field is the maximum allowed size
+ {
+ horizSubOffset = origWidth - width;
+
+ // Resize the text field
+ SetWindowPos (hwndCtrl, 0, 0, 0,
+ origWidth - horizSubOffset,
+ origHeight,
+ SWP_NOMOVE | SWP_NOZORDER);
+
+ InvalidateRect (hwndCtrl, NULL, TRUE);
+ }
+}
+
+// makes controls contiguous by moving the second control right next to the first one horizontally
+void MakeControlsContiguous(HWND hwndDlg, UINT ctrl1ID, UINT ctrl2ID) {
+ HWND hwndCtrl1 = GetDlgItem(hwndDlg, ctrl1ID);
+ HWND hwndCtrl2 = GetDlgItem(hwndDlg, ctrl2ID);
+ RECT rect1, rect2;
+ POINT pt1, pt2;
+ int newLeftPosition;
+
+ // Exit silently if one or both controls are missing
+ if (!hwndCtrl1 || !hwndCtrl2) {
+ return;
+ }
+
+
+ GetWindowRect(hwndCtrl1, &rect1);
+ GetWindowRect(hwndCtrl2, &rect2);
+
+ // Convert the top-right point of the first control from screen to client coordinates
+ pt1.x = rect1.right;
+ pt1.y = rect1.top;
+ if (!ScreenToClient(hwndDlg, &pt1)) {
+ return; // Exit if the conversion fails
+ }
+
+ // Convert the top-left point of the second control from screen to client coordinates
+ pt2.x = rect2.left;
+ pt2.y = rect2.top;
+ if (!ScreenToClient(hwndDlg, &pt2)) {
+ return; // Exit if the conversion fails
+ }
+
+ // Ensure the second control is always placed to the right of the first one
+ newLeftPosition = pt1.x + 1;
+
+ if (pt2.x < pt1.x) { // if the second control is to the left of the first one
+ newLeftPosition += (pt1.x - pt2.x);
+ }
+
+ // Move the second control to its new position
+ SetWindowPos(hwndCtrl2, NULL, newLeftPosition, pt2.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+}
+
+
// Note that the user can still close the window by right-clicking its taskbar icon and selecting 'Close window', or by pressing Alt-F4, or using the Task Manager.
void DisableCloseButton (HWND hwndDlg)
{
EnableMenuItem (GetSystemMenu (hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
@@ -1070,8 +1879,46 @@ void EnableCloseButton (HWND hwndDlg)
{
EnableMenuItem (GetSystemMenu (hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
}
+void HandlePasswordEditWmChar (HWND hwnd, WPARAM wParam)
+{
+ DWORD dwStartPos = 0, dwEndPos = 0;
+ short vk = VkKeyScanW ((WCHAR) wParam);
+ BYTE vkCode = LOBYTE (vk);
+ BYTE vkState = HIBYTE (vk);
+ bool ctrlPressed = (vkState & 2) && !(vkState & 4);
+ int dwMaxPassLen = (int) SendMessage (hwnd, EM_GETLIMITTEXT, 0, 0);
+
+ // check if there is a selected text
+ SendMessage (hwnd, EM_GETSEL, (WPARAM) &dwStartPos, (LPARAM) &dwEndPos);
+
+ if ((dwStartPos == dwEndPos)
+ && (vkCode != VK_DELETE) && (vkCode != VK_BACK)
+ && !ctrlPressed
+ && (GetWindowTextLength (hwnd) == dwMaxPassLen))
+ {
+ EDITBALLOONTIP ebt;
+ DWORD dwTextSize = (DWORD) wcslen (GetString ("PASSWORD_MAXLENGTH_REACHED")) + 16;
+ WCHAR* szErrorText = (WCHAR*) malloc (dwTextSize * sizeof (WCHAR));
+
+ StringCchPrintf (szErrorText, dwTextSize, GetString ("PASSWORD_MAXLENGTH_REACHED"), dwMaxPassLen);
+
+ ebt.cbStruct = sizeof( EDITBALLOONTIP );
+ ebt.pszText = szErrorText;
+ ebt.pszTitle = lpszTitle;
+ ebt.ttiIcon = TTI_ERROR_LARGE; // tooltip warning icon
+
+ SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt);
+
+ MessageBeep (0xFFFFFFFF);
+
+ free (szErrorText);
+ }
+ else
+ SendMessage(hwnd, EM_HIDEBALLOONTIP, 0, 0);
+}
+
// Protects an input field from having its content updated by a Paste action (call ToBootPwdField() to use this).
static LRESULT CALLBACK BootPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA);
@@ -1079,8 +1926,11 @@ static LRESULT CALLBACK BootPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam
switch (message)
{
case WM_PASTE:
return 1;
+ case WM_CHAR:
+ HandlePasswordEditWmChar (hwnd, wParam);
+ break;
}
return CallWindowProcW (wp, hwnd, message, wParam, lParam);
}
@@ -1091,13 +1941,127 @@ static LRESULT CALLBACK BootPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam
// user from pasting a password typed using a non-US keyboard layout).
void ToBootPwdField (HWND hwndDlg, UINT ctrlId)
{
HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId);
+ WNDPROC originalwp = (WNDPROC) GetWindowLongPtrW (hwndCtrl, GWLP_USERDATA);
- SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC));
+ SendMessage (hwndCtrl, EM_LIMITTEXT, MAX_LEGACY_PASSWORD, 0);
+
+ // if ToNormalPwdField has been called before, GWLP_USERDATA already contains original WNDPROC
+ if (!originalwp)
+ {
+ SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC));
+ }
SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) BootPwdFieldProc);
}
+// Ensures that a warning is displayed when user is pasting a password longer than the maximum
+// length which is set to 64 characters
+static LRESULT CALLBACK NormalPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA);
+
+ switch (message)
+ {
+ case WM_PASTE:
+ {
+ bool bBlock = false;
+ if (OpenClipboard (NULL))
+ {
+ HANDLE h = GetClipboardData (CF_UNICODETEXT);
+ if (h)
+ {
+ wchar_t *pchData = (wchar_t*)GlobalLock(h);
+ int txtlen = 0;
+ int dwMaxPassLen = bUseLegacyMaxPasswordLength? MAX_LEGACY_PASSWORD : MAX_PASSWORD;
+ while (*pchData)
+ {
+ if (*pchData == '\r' || *pchData == '\n')
+ break;
+ else
+ {
+ txtlen++;
+ pchData++;
+ }
+ }
+
+ if (txtlen)
+ {
+ int curLen = GetWindowTextLength (hwnd);
+ if (curLen == dwMaxPassLen)
+ {
+ EDITBALLOONTIP ebt;
+ DWORD dwTextSize = (DWORD) wcslen (GetString ("PASSWORD_MAXLENGTH_REACHED")) + 16;
+ WCHAR* szErrorText = (WCHAR*) malloc (dwTextSize * sizeof (WCHAR));
+
+ StringCchPrintf (szErrorText, dwTextSize, GetString ("PASSWORD_MAXLENGTH_REACHED"), dwMaxPassLen);
+
+ ebt.cbStruct = sizeof( EDITBALLOONTIP );
+ ebt.pszText = szErrorText;
+ ebt.pszTitle = lpszTitle;
+ ebt.ttiIcon = TTI_ERROR_LARGE; // tooltip warning icon
+
+ SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt);
+
+ MessageBeep (0xFFFFFFFF);
+
+ free (szErrorText);
+
+ bBlock = true;
+ }
+ else if ((txtlen + curLen) > dwMaxPassLen)
+ {
+ EDITBALLOONTIP ebt;
+ DWORD dwTextSize = (DWORD) wcslen (GetString ("PASSWORD_PASTED_TRUNCATED")) + 16;
+ WCHAR* szErrorText = (WCHAR*) malloc (dwTextSize * sizeof (WCHAR));
+
+ StringCchPrintf (szErrorText, dwTextSize, GetString ("PASSWORD_PASTED_TRUNCATED"), dwMaxPassLen);
+
+ ebt.cbStruct = sizeof( EDITBALLOONTIP );
+ ebt.pszText = szErrorText;
+ ebt.pszTitle = lpszTitle;
+ ebt.ttiIcon = TTI_WARNING_LARGE; // tooltip warning icon
+
+ SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt);
+
+ MessageBeep (0xFFFFFFFF);
+
+ free (szErrorText);
+ }
+ else
+ SendMessage(hwnd, EM_HIDEBALLOONTIP, 0, 0);
+ }
+ GlobalUnlock(h);
+ }
+ CloseClipboard ();
+ }
+
+ if (bBlock)
+ return FALSE;
+ }
+ break;
+ case WM_CHAR:
+ HandlePasswordEditWmChar (hwnd, wParam);
+ break;
+ }
+
+ return CallWindowProcW (wp, hwnd, message, wParam, lParam);
+}
+
+void ToNormalPwdField (HWND hwndDlg, UINT ctrlId)
+{
+ HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId);
+ WNDPROC originalwp = (WNDPROC) GetWindowLongPtrW (hwndCtrl, GWLP_USERDATA);
+ DWORD dwMaxPassLen = bUseLegacyMaxPasswordLength? MAX_LEGACY_PASSWORD : MAX_PASSWORD;
+
+ SendMessage (hwndCtrl, EM_LIMITTEXT, dwMaxPassLen, 0);
+ // only change WNDPROC if not changed already
+ if (!originalwp)
+ {
+ SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC));
+ SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) NormalPwdFieldProc);
+ }
+}
// This function currently serves the following purposes:
// - Determines scaling factors for current screen DPI and GUI aspect ratio.
@@ -1194,14 +2158,10 @@ BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam
}
// Version
SendMessage (GetDlgItem (hwndDlg, IDT_ABOUT_VERSION), WM_SETFONT, (WPARAM) hUserBoldFont, 0);
- StringCbPrintfW (szTmp, sizeof(szTmp), L"VeraCrypt %s", _T(VERSION_STRING));
-#ifdef _WIN64
- StringCbCatW (szTmp, sizeof(szTmp), L" (64-bit)");
-#else
- StringCbCatW (szTmp, sizeof(szTmp), L" (32-bit)");
-#endif
+ StringCbPrintfW (szTmp, sizeof(szTmp), L"VeraCrypt %s", _T(VERSION_STRING) _T(VERSION_STRING_SUFFIX) L" (64-bit)");
+
#if (defined(_DEBUG) || defined(DEBUG))
StringCbCatW (szTmp, sizeof(szTmp), L" (debug)");
#endif
SetDlgItemText (hwndDlg, IDT_ABOUT_VERSION, szTmp);
@@ -1217,20 +2177,22 @@ BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam
SetWindowText (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS),
L"Based on TrueCrypt 7.1a, freely available at http://www.truecrypt.org/ .\r\n\r\n"
L"Portions of this software:\r\n"
- L"Copyright \xA9 2013-2016 IDRIX. All rights reserved.\r\n"
+ L"Copyright \xA9 2013-2024 IDRIX. All rights reserved.\r\n"
L"Copyright \xA9 2003-2012 TrueCrypt Developers Association. All Rights Reserved.\r\n"
L"Copyright \xA9 1998-2000 Paul Le Roux. All Rights Reserved.\r\n"
L"Copyright \xA9 1998-2008 Brian Gladman. All Rights Reserved.\r\n"
- L"Copyright \xA9 1995-2013 Jean-loup Gailly and Mark Adler.\r\n"
+ L"Copyright \xA9 1995-2023 Jean-loup Gailly and Mark Adler.\r\n"
L"Copyright \xA9 2016 Disk Cryptography Services for EFI (DCS), Alex Kolotnikov.\r\n"
- L"Copyright \xA9 Dieter Baron and Thomas Klausner.\r\n"
+ L"Copyright \xA9 1999-2023 Dieter Baron and Thomas Klausner.\r\n"
L"Copyright \xA9 2013, Alexey Degtyarev. All rights reserved.\r\n"
- L"Copyright \xA9 1999-2013,2014,2015,2016 Jack Lloyd. All rights reserved.\r\n\r\n"
+ L"Copyright \xA9 1999-2016 Jack Lloyd. All rights reserved.\r\n"
+ L"Copyright \xA9 2013-2019 Stephan Mueller <smueller@chronox.de>\r\n"
+ L"Copyright \xA9 1999-2023 Igor Pavlov\r\n\r\n"
L"This software as a whole:\r\n"
- L"Copyright \xA9 2013-2016 IDRIX. All rights reserved.\r\n\r\n"
+ L"Copyright \xA9 2013-2024 IDRIX. All rights reserved.\r\n\r\n"
L"An IDRIX Release");
return 1;
@@ -1243,9 +2205,9 @@ BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam
}
if (lw == IDC_HOMEPAGE)
{
- Applink ("main", TRUE, "");
+ Applink ("main");
return 1;
}
// Disallow modification of credits
@@ -1271,8 +2233,44 @@ BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam
return 0;
}
+HWND CreateToolTip(int toolID, HWND hDlg, const char* strID)
+{
+ if (!toolID || !hDlg)
+ {
+ return FALSE;
+ }
+
+ // Create the tooltip.
+ HWND hwndTip = CreateWindowExW(NULL, TOOLTIPS_CLASS, NULL,
+ WS_POPUP | TTS_ALWAYSTIP | TTS_NOPREFIX | TTS_BALLOON,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ hDlg, NULL,
+ hInst, NULL);
+
+ if (!hwndTip)
+ {
+ return (HWND)NULL;
+ }
+
+ // Associate the tooltip with the tool.
+ TOOLINFOW toolInfo = { 0 };
+ toolInfo.cbSize = sizeof(toolInfo);
+ toolInfo.hwnd = hDlg;
+ toolInfo.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
+ toolInfo.uId = (UINT_PTR) GetDlgItem(hDlg, toolID);
+ toolInfo.lpszText = GetString(strID);
+
+ // set tooltip maximum width
+ SendMessage(hwndTip, TTM_SETMAXTIPWIDTH, 0, (LPARAM) 300);
+
+ SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
+
+ return hwndTip;
+}
+
static HWND StaticModelessWaitDlgHandle = NULL;
// Call DisplayStaticModelessWaitDlg() to open this dialog and CloseStaticModelessWaitDlg() to close it.
@@ -1390,9 +2388,9 @@ void InitDialog (HWND hwndDlg)
if (font && wcscmp (font->FaceName, L"default") != 0)
{
StringCbCopyW ((WCHAR *)metric.lfMessageFont.lfFaceName, sizeof (metric.lfMessageFont.lfFaceName), font->FaceName);
}
- else if (IsOSAtLeast (WIN_VISTA))
+ else
{
// Vista's new default font (size and spacing) breaks compatibility with Windows 2k/XP applications.
// Force use of Tahoma (as Microsoft does in many dialogs) until a native Vista look is implemented.
StringCbCopyW ((WCHAR *)metric.lfMessageFont.lfFaceName, sizeof (metric.lfMessageFont.lfFaceName), L"Tahoma");
@@ -1740,52 +2738,52 @@ static int g_waitCursorCounter = 0;
void
WaitCursor ()
{
- static HCURSOR hcWait;
+ static HCURSOR hcWait = NULL;
if (hcWait == NULL)
hcWait = LoadCursor (NULL, IDC_WAIT);
if ((g_waitCursorCounter == 0) || (hCursor != hcWait))
{
- SetCursor (hcWait);
+ if (!Silent) SetCursor (hcWait);
hCursor = hcWait;
}
g_waitCursorCounter++;
}
void
NormalCursor ()
{
- static HCURSOR hcArrow;
+ static HCURSOR hcArrow = NULL;
if (hcArrow == NULL)
hcArrow = LoadCursor (NULL, IDC_ARROW);
if (g_waitCursorCounter > 0)
g_waitCursorCounter--;
if (g_waitCursorCounter == 0)
{
- SetCursor (hcArrow);
+ if (!Silent) SetCursor (hcArrow);
hCursor = NULL;
}
}
void
ArrowWaitCursor ()
{
- static HCURSOR hcArrowWait;
+ static HCURSOR hcArrowWait = NULL;
if (hcArrowWait == NULL)
hcArrowWait = LoadCursor (NULL, IDC_APPSTARTING);
if ((g_waitCursorCounter == 0) || (hCursor != hcArrowWait))
{
- SetCursor (hcArrowWait);
+ if (!Silent) SetCursor (hcArrowWait);
hCursor = hcArrowWait;
}
g_waitCursorCounter++;
}
void HandCursor ()
{
- static HCURSOR hcHand;
+ static HCURSOR hcHand = NULL;
if (hcHand == NULL)
hcHand = LoadCursor (NULL, IDC_HAND);
SetCursor (hcHand);
hCursor = hcHand;
@@ -1907,9 +2905,9 @@ LRESULT CALLBACK CustomDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lPar
/*
static BOOL IsReturnAddress (DWORD64 address)
{
static size_t codeEnd = 0;
- byte *sp = (byte *) address;
+ uint8 *sp = (uint8 *) address;
if (codeEnd == 0)
{
MEMORY_BASIC_INFORMATION mi;
@@ -2041,9 +3039,9 @@ void ExceptionHandlerThread (void *threadArg)
retAddrs.push_back (0);
MEMORY_BASIC_INFORMATION mi;
VirtualQuery (sp, &mi, sizeof (mi));
- PDWORD stackTop = (PDWORD)((byte *) mi.BaseAddress + mi.RegionSize);
+ PDWORD stackTop = (PDWORD)((uint8 *) mi.BaseAddress + mi.RegionSize);
int i = 0;
while (retAddrs.size() < 16 && &sp[i] < stackTop)
{
@@ -2194,9 +3192,9 @@ BOOL LaunchElevatedProcess (HWND hwndDlg, const wchar_t* szModPath, const wchar_
StringCbCopyW (newCmdLine, sizeof(newCmdLine), L"/q UAC ");
StringCbCatW (newCmdLine, sizeof (newCmdLine), args);
- if ((int)ShellExecuteW (hWnd, L"runas", szModPath, newCmdLine, NULL, SW_SHOWNORMAL) <= 32)
+ if ((INT_PTR)ShellExecuteW (hWnd, L"runas", szModPath, newCmdLine, NULL, SW_SHOWNORMAL) <= 32)
{
if (hwndDlg)
handleWin32Error (hwndDlg, SRC_POS);
return FALSE;
@@ -2364,8 +3362,18 @@ uint32 ReadDriverConfigurationFlags ()
return configMap;
}
+uint32 ReadServiceConfigurationFlags ()
+{
+ DWORD configMap;
+
+ if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\" TC_SYSTEM_FAVORITES_SERVICE_NAME, TC_SYSTEM_FAVORITES_SERVICE_NAME L"Config", &configMap))
+ configMap = 0;
+
+ return configMap;
+}
+
uint32 ReadEncryptionThreadPoolFreeCpuCountLimit ()
{
DWORD count;
@@ -2375,8 +3383,26 @@ uint32 ReadEncryptionThreadPoolFreeCpuCountLimit ()
return count;
}
+BOOL ReadMemoryProtectionConfig ()
+{
+ DWORD config;
+
+ if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", VC_ENABLE_MEMORY_PROTECTION, &config))
+ {
+ // enabled by default
+ config = 1;
+ }
+ return (config)? TRUE: FALSE;
+}
+
+BOOL WriteMemoryProtectionConfig (BOOL bEnable)
+{
+ DWORD config = bEnable? 1: 0;
+
+ return WriteLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", VC_ENABLE_MEMORY_PROTECTION, config);
+}
BOOL LoadSysEncSettings ()
{
BOOL status = TRUE;
@@ -2484,8 +3510,9 @@ void SavePostInstallTasksSettings (int command)
{
case TC_POST_INSTALL_CFG_REMOVE_ALL:
_wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL));
_wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES));
+ _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK));
break;
case TC_POST_INSTALL_CFG_TUTORIAL:
f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL), L"w");
@@ -2494,8 +3521,12 @@ void SavePostInstallTasksSettings (int command)
case TC_POST_INSTALL_CFG_RELEASE_NOTES:
f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES), L"w");
break;
+ case TC_POST_INSTALL_CFG_RESCUE_DISK:
+ f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK), L"w");
+ break;
+
default:
return;
}
@@ -2521,254 +3552,158 @@ void DoPostInstallTasks (HWND hwndDlg)
if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL)))
{
if (AskYesNo ("AFTER_INSTALL_TUTORIAL", hwndDlg) == IDYES)
- Applink ("beginnerstutorial", TRUE, "");
+ Applink ("beginnerstutorial");
bDone = TRUE;
}
if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES)))
{
if (AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES", hwndDlg) == IDYES)
- Applink ("releasenotes", TRUE, "");
+ Applink ("releasenotes");
+
+ bDone = TRUE;
+ }
+
+ if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK)))
+ {
+ if (AskYesNo ("AFTER_UPGRADE_RESCUE_DISK", hwndDlg) == IDYES)
+ PostMessage (hwndDlg, VC_APPMSG_CREATE_RESCUE_DISK, 0, 0);
bDone = TRUE;
}
if (bDone)
SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_REMOVE_ALL);
}
-
-void InitOSVersionInfo ()
-{
- OSVERSIONINFOEXW os;
- os.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
-
- if (GetVersionExW ((LPOSVERSIONINFOW) &os) == FALSE)
- AbortProcess ("NO_OS_VER");
-
- CurrentOSMajor = os.dwMajorVersion;
- CurrentOSMinor = os.dwMinorVersion;
- CurrentOSServicePack = os.wServicePackMajor;
-
- if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 0)
- nCurrentOS = WIN_2000;
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 1)
- nCurrentOS = WIN_XP;
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 2)
+#ifndef SETUP_DLL
+// Use an idea proposed in https://medium.com/@1ndahous3/safe-code-pitfalls-dll-side-loading-winapi-and-c-73baaf48bdf5
+// it allows to set safe DLL search mode for the entire process very early on, before even the CRT is initialized and global constructors are called
+#pragma comment(linker, "/ENTRY:CustomMainCrtStartup")
+extern "C" {
+ int wWinMainCRTStartup();
+ int APIENTRY CustomMainCrtStartup()
{
- if (os.wProductType == VER_NT_SERVER || os.wProductType == VER_NT_DOMAIN_CONTROLLER)
- nCurrentOS = WIN_SERVER_2003;
- else
- nCurrentOS = WIN_XP64;
- }
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 0)
- {
- if (os.wProductType != VER_NT_WORKSTATION)
- nCurrentOS = WIN_SERVER_2008;
- else
- nCurrentOS = WIN_VISTA;
- }
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 1)
- nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2008_R2 : WIN_7);
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 2)
- nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012 : WIN_8);
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 3)
- nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012_R2 : WIN_8_1);
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 10 && CurrentOSMinor == 0)
- nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2016 : WIN_10);
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 4)
- nCurrentOS = WIN_NT4;
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 0)
- nCurrentOS = WIN_95;
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 10)
- nCurrentOS = WIN_98;
- else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 90)
- nCurrentOS = WIN_ME;
- else if (os.dwPlatformId == VER_PLATFORM_WIN32s)
- nCurrentOS = WIN_31;
- else
- nCurrentOS = WIN_UNKNOWN;
-}
-
-static void LoadSystemDll (LPCTSTR szModuleName, HMODULE *pHandle, BOOL bIgnoreError, const char* srcPos)
-{
- wchar_t dllPath[MAX_PATH];
-
- /* Load dll explictely from System32 to avoid Dll hijacking attacks*/
- if (!GetSystemDirectory(dllPath, MAX_PATH))
- StringCbCopyW(dllPath, sizeof(dllPath), L"C:\\Windows\\System32");
+ SetDefaultDllDirectoriesPtr SetDefaultDllDirectoriesFn = NULL;
+ SetDefaultDllDirectoriesFn = (SetDefaultDllDirectoriesPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDefaultDllDirectories");
+ if (SetDefaultDllDirectoriesFn)
+ {
+ /* remove current directory from dll search path */
+ SetDllDirectoryW (L"");
+ // Force loading dlls from system32 directory only
+ SetDefaultDllDirectoriesFn (LOAD_LIBRARY_SEARCH_SYSTEM32);
+ }
- StringCbCatW(dllPath, sizeof(dllPath), L"\\");
- StringCbCatW(dllPath, sizeof(dllPath), szModuleName);
+ // activate process mitigations (currently only ASLR, dynamic code and extensions points)
+ ActivateProcessMitigations();
- if (((*pHandle = LoadLibrary(dllPath)) == NULL) && !bIgnoreError)
- {
- // This error is fatal
- handleWin32Error (NULL, srcPos);
- AbortProcess ("INIT_DLL");
+#ifndef SETUP
+ // call ActivateMemoryProtection if corresponding setting has been enabled (default is enabled)
+ if (ReadMemoryProtectionConfig())
+ {
+ ActivateMemoryProtection();
+ }
+#endif
+ return wWinMainCRTStartup();
}
}
+#endif
/* InitApp - initialize the application, this function is called once in the
applications WinMain function, but before the main dialog has been created */
void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine)
{
WNDCLASSW wc;
char langId[6];
- InitCommonControlsPtr InitCommonControlsFn = NULL;
-
- /* remove current directory from dll search path */
- SetDllDirectoryFn = (SetDllDirectoryPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDllDirectoryW");
- SetSearchPathModeFn = (SetSearchPathModePtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetSearchPathMode");
- SetDefaultDllDirectoriesFn = (SetDefaultDllDirectoriesPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDefaultDllDirectories");
-
- if (SetDllDirectoryFn)
- SetDllDirectoryFn (L"");
- if (SetSearchPathModeFn)
- SetSearchPathModeFn (BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT);
- if (SetDefaultDllDirectoriesFn)
- SetDefaultDllDirectoriesFn (LOAD_LIBRARY_SEARCH_SYSTEM32);
-
- InitOSVersionInfo();
-
- VirtualLock (&CmdTokenPin, sizeof (CmdTokenPin));
+ SetDefaultDllDirectoriesPtr SetDefaultDllDirectoriesFn = NULL;
+#if !defined(SETUP)
+ wchar_t modPath[MAX_PATH];
+#endif
+ INITCOMMONCONTROLSEX InitCtrls;
- InitializeCriticalSection (&csWNetCalls);
+ InitOSVersionInfo();
- LoadSystemDll (L"ntmarta.dll", &hntmartadll, TRUE, SRC_POS);
- LoadSystemDll (L"MPR.DLL", &hmprdll, TRUE, SRC_POS);
-#ifdef SETUP
- if (IsOSAtLeast (WIN_7))
+ if (!IsWin10BuildAtLeast(WIN_10_1809_BUILD))
{
- LoadSystemDll (L"ProfApi.DLL", &hProfApiDll, TRUE, SRC_POS);
- LoadSystemDll (L"cryptbase.dll", &hcryptbasedll, TRUE, SRC_POS);
- LoadSystemDll (L"sspicli.dll", &hsspiclidll, TRUE, SRC_POS);
+ // abort using a message that says that VeraCrypt can run only on Windows 10 version 1809 or later
+ AbortProcessDirect(L"VeraCrypt requires at least Windows 10 version 1809 (October 2018 Update) to run.");
}
-#endif
- LoadSystemDll (L"psapi.dll", &hpsapidll, TRUE, SRC_POS);
- LoadSystemDll (L"secur32.dll", &hsecur32dll, TRUE, SRC_POS);
- LoadSystemDll (L"msasn1.dll", &hmsasn1dll, TRUE, SRC_POS);
- LoadSystemDll (L"Usp10.DLL", &hUsp10Dll, TRUE, SRC_POS);
- if (IsOSAtLeast (WIN_7))
- LoadSystemDll (L"dwmapi.dll", &hdwmapidll, TRUE, SRC_POS);
- LoadSystemDll (L"UXTheme.dll", &hUXThemeDll, TRUE, SRC_POS);
-
- LoadSystemDll (L"msls31.dll", &hMsls31, TRUE, SRC_POS);
- LoadSystemDll (L"SETUPAPI.DLL", &hSetupDll, FALSE, SRC_POS);
- LoadSystemDll (L"SHLWAPI.DLL", &hShlwapiDll, FALSE, SRC_POS);
- LoadSystemDll (L"userenv.dll", &hUserenvDll, TRUE, SRC_POS);
- LoadSystemDll (L"rsaenh.dll", &hRsaenhDll, TRUE, SRC_POS);
-
-#ifdef SETUP
- if (nCurrentOS < WIN_7)
+ if (!Is64BitOs())
{
- if (nCurrentOS == WIN_XP)
- {
- LoadSystemDll (L"imm32.dll", &himm32dll, TRUE, SRC_POS);
- LoadSystemDll (L"MSCTF.dll", &hMSCTFdll, TRUE, SRC_POS);
- LoadSystemDll (L"fltlib.dll", &hfltlibdll, TRUE, SRC_POS);
- LoadSystemDll (L"wbem\\framedyn.dll", &hframedyndll, TRUE, SRC_POS);
- }
-
- if (IsOSAtLeast (WIN_VISTA))
- {
- LoadSystemDll (L"netapi32.dll", &hnetapi32dll, TRUE, SRC_POS);
- LoadSystemDll (L"authz.dll", &hauthzdll, TRUE, SRC_POS);
- LoadSystemDll (L"xmllite.dll", &hxmllitedll, TRUE, SRC_POS);
- }
+ // abort using a message that says that VeraCrypt can run only on 64-bit Windows
+ AbortProcessDirect(L"VeraCrypt requires a 64-bit version of Windows to run.");
}
- if (IsOSAtLeast (WIN_VISTA))
- {
- LoadSystemDll (L"atl.dll", &hsppdll, TRUE, SRC_POS);
- LoadSystemDll (L"vsstrace.dll", &hvsstracedll, TRUE, SRC_POS);
- LoadSystemDll (L"vssapi.dll", &vssapidll, TRUE, SRC_POS);
- LoadSystemDll (L"spp.dll", &hsppdll, TRUE, SRC_POS);
-
- if (IsOSAtLeast (WIN_7))
- {
- LoadSystemDll (L"CryptSP.dll", &hCryptSpDll, TRUE, SRC_POS);
-
- LoadSystemDll (L"cfgmgr32.dll", &hcfgmgr32dll, TRUE, SRC_POS);
- LoadSystemDll (L"devobj.dll", &hdevobjdll, TRUE, SRC_POS);
- LoadSystemDll (L"powrprof.dll", &hpowrprofdll, TRUE, SRC_POS);
-
- LoadSystemDll (L"crypt32.dll", &hcrypt32dll, TRUE, SRC_POS);
-
- LoadSystemDll (L"bcrypt.dll", &hbcryptdll, TRUE, SRC_POS);
- LoadSystemDll (L"bcryptprimitives.dll", &hbcryptprimitivesdll, TRUE, SRC_POS);
- }
- }
-#else
- LoadSystemDll (L"WINSCARD.DLL", &hwinscarddll, TRUE, SRC_POS);
-#endif
-
- LoadSystemDll (L"COMCTL32.DLL", &hComctl32Dll, FALSE, SRC_POS);
-
- // call InitCommonControls function
- InitCommonControlsFn = (InitCommonControlsPtr) GetProcAddress (hComctl32Dll, "InitCommonControls");
- ImageList_AddFn = (ImageList_AddPtr) GetProcAddress (hComctl32Dll, "ImageList_Add");
- ImageList_CreateFn = (ImageList_CreatePtr) GetProcAddress (hComctl32Dll, "ImageList_Create");
-
- if (InitCommonControlsFn && ImageList_AddFn && ImageList_CreateFn)
+ SetDefaultDllDirectoriesFn = (SetDefaultDllDirectoriesPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDefaultDllDirectories");
+ if (!SetDefaultDllDirectoriesFn)
{
- InitCommonControlsFn();
+ // This can happen only if KB2533623 is missing from Windows 7
+ AbortProcessDirect(L"VeraCrypt requires KB2533623 to be installed on Windows 7 and Windows Server 2008 R2 in order to run.");
}
- else
- AbortProcess ("INIT_DLL");
-
- LoadSystemDll (L"Riched20.dll", &hRichEditDll, FALSE, SRC_POS);
- // Get SetupAPI functions pointers
- SetupCloseInfFileFn = (SetupCloseInfFilePtr) GetProcAddress (hSetupDll, "SetupCloseInfFile");
- SetupDiOpenClassRegKeyFn = (SetupDiOpenClassRegKeyPtr) GetProcAddress (hSetupDll, "SetupDiOpenClassRegKey");
- SetupInstallFromInfSectionWFn = (SetupInstallFromInfSectionWPtr) GetProcAddress (hSetupDll, "SetupInstallFromInfSectionW");
- SetupOpenInfFileWFn = (SetupOpenInfFileWPtr) GetProcAddress (hSetupDll, "SetupOpenInfFileW");
-
- if (!SetupCloseInfFileFn || !SetupDiOpenClassRegKeyFn || !SetupInstallFromInfSectionWFn || !SetupOpenInfFileWFn)
- AbortProcess ("INIT_DLL");
-
- // Get SHDeleteKeyW function pointer
- SHDeleteKeyWFn = (SHDeleteKeyWPtr) GetProcAddress (hShlwapiDll, "SHDeleteKeyW");
- SHStrDupWFn = (SHStrDupWPtr) GetProcAddress (hShlwapiDll, "SHStrDupW");
- if (!SHDeleteKeyWFn || !SHStrDupWFn)
- AbortProcess ("INIT_DLL");
+ VirtualLock (&CmdTokenPin, sizeof (CmdTokenPin));
- if (IsOSAtLeast (WIN_VISTA))
- {
- /* Get ChangeWindowMessageFilter used to enable some messages bypasss UIPI (User Interface Privilege Isolation) */
- ChangeWindowMessageFilterFn = (ChangeWindowMessageFilterPtr) GetProcAddress (GetModuleHandle (L"user32.dll"), "ChangeWindowMessageFilter");
+ InitGlobalLocks ();
+
+ // call InitCommonControlsEx function to initialize the common controls
+ InitCtrls.dwSize = sizeof (InitCtrls);
+ InitCtrls.dwICC = ICC_WIN95_CLASSES | ICC_PAGESCROLLER_CLASS | ICC_NATIVEFNTCTL_CLASS | ICC_STANDARD_CLASSES | ICC_LINK_CLASS;
+ InitCommonControlsEx (&InitCtrls);
+
+ // Load RichEdit library in order to be able to use RichEdit20W class
+ LoadLibraryEx (L"Riched20.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+
+#if !defined(SETUP)
+ GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath));
+ if (!VerifyModuleSignature (modPath))
+ AbortProcessDirect (L"This distribution package is damaged. Please try downloading it again (preferably from the official VeraCrypt website at https://www.veracrypt.fr).");
+#endif
#ifndef SETUP
- /* enable drag-n-drop when we are running elevated */
- AllowMessageInUIPI (WM_DROPFILES);
- AllowMessageInUIPI (WM_COPYDATA);
- AllowMessageInUIPI (WM_COPYGLOBALDATA);
+ /* enable drag-n-drop when we are running elevated */
+ AllowMessageInUIPI (WM_DROPFILES);
+ AllowMessageInUIPI (WM_COPYDATA);
+ AllowMessageInUIPI (WM_COPYGLOBALDATA);
#endif
- }
/* Save the instance handle for later */
hInst = hInstance;
SetErrorMode (SetErrorMode (0) | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
- CoInitialize (NULL);
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
#ifndef SETUP
// Application ID
- typedef HRESULT (WINAPI *SetAppId_t) (PCWSTR appID);
- SetAppId_t setAppId = (SetAppId_t) GetProcAddress (GetModuleHandle (L"shell32.dll"), "SetCurrentProcessExplicitAppUserModelID");
-
- if (setAppId)
- setAppId (TC_APPLICATION_ID);
+ SetCurrentProcessExplicitAppUserModelID (TC_APPLICATION_ID);
#endif
// Language
langId[0] = 0;
SetPreferredLangId (ConfigReadString ("Language", "", langId, sizeof (langId)));
+
+#ifndef SETUP
+ if (langId[0] == 0)
+ {
+ // check if user selected a language during installation
+ WCHAR uiLang[6];
+ ReadRegistryString (L"Software\\VeraCrypt", L"SetupUILanguage", L"", uiLang, sizeof (uiLang));
+ if (0 < WideCharToMultiByte (CP_ACP, 0, uiLang, -1, langId, sizeof (langId), NULL, NULL))
+ {
+ SetPreferredLangId (langId);
+ bLanguageSetInSetup = TRUE;
+ }
+ }
+
+#ifndef VCEXPANDER
+ // delete the registry key created by the installer (if any)
+ DeleteRegistryKey (HKEY_CURRENT_USER, L"Software\\VeraCrypt");
+#endif
+
+#endif
if (langId[0] == 0)
{
if (IsNonInstallMode ())
@@ -2792,17 +3727,15 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine)
// UAC elevation moniker cannot be used in portable mode.
// A new instance of the application must be created with elevated privileges.
if (IsNonInstallMode () && !IsAdmin () && IsUacSupported ())
{
- wchar_t modPath[MAX_PATH];
if (wcsstr (lpszCommandLine, L"/q UAC ") == lpszCommandLine)
{
Error ("UAC_INIT_ERROR", NULL);
exit (1);
}
- GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath));
if (LaunchElevatedProcess (NULL, modPath, lpszCommandLine))
exit (0);
else
@@ -2814,52 +3747,37 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine)
_set_invalid_parameter_handler (InvalidParameterHandler);
RemoteSession = GetSystemMetrics (SM_REMOTESESSION) != 0;
- // OS version check
- if (CurrentOSMajor < 5)
+#ifndef VC_SKIP_OS_DRIVER_REQ_CHECK
+ if (!IsSupportedOS())
{
MessageBoxW (NULL, GetString ("UNSUPPORTED_OS"), lpszTitle, MB_ICONSTOP);
exit (1);
}
- else
+#else
+ // in TESTSIGNING mode, we support only Windows 7 and Windows 8/8.1
+ if (
+#ifndef SETUP
+ IsOSVersionAtLeast(WIN_10, 0)
+#else
+ || (IsOSVersionAtLeast(WIN_10, 0) && !bMakePackage)
+#endif
+ )
{
- // Service pack check & warnings about critical MS issues
- switch (nCurrentOS)
- {
- case WIN_2000:
- if (CurrentOSServicePack < 3)
- Warning ("LARGE_IDE_WARNING_2K", NULL);
- else
- {
- DWORD val = 0, size = sizeof(val);
- HKEY hkey;
-
- if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Atapi\\Parameters", 0, KEY_READ, &hkey) == ERROR_SUCCESS)
- {
- if (RegQueryValueExW (hkey, L"EnableBigLba", 0, 0, (LPBYTE) &val, &size) != ERROR_SUCCESS
- || val != 1)
- {
- Warning ("LARGE_IDE_WARNING_2K_REGISTRY", NULL);
- }
- RegCloseKey (hkey);
- }
- }
- break;
-
- case WIN_XP:
- if (CurrentOSServicePack < 1)
- {
- HKEY k;
- // PE environment does not report version of SP
- if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\minint", 0, KEY_READ, &k) != ERROR_SUCCESS)
- Warning ("LARGE_IDE_WARNING_XP", NULL);
- else
- RegCloseKey (k);
- }
- break;
- }
+ MessageBoxW (NULL, L"TESTSIGNING version of VeraCrypt targets only Windows Vista, Windows 7 and Windows 8/8.1.\n\nPlease use the standard version of VeraCrypt instead.", lpszTitle, MB_ICONSTOP);
+ exit (1);
+ }
+ else if ( !IsTestSigningModeEnabled()
+#ifdef SETUP
+ && !bMakePackage
+#endif
+ )
+ {
+ MessageBoxW (NULL, L"Test-Signing Mode, which is required to run VeraCrypt TESTSIGNING binaries, is not enabled in Windows.\n\nExecution aborted!", lpszTitle, MB_ICONSTOP);
+ exit (1);
}
+#endif
/* Get the attributes for the standard dialog class */
if ((GetClassInfoW (hInst, WINDOWS_DIALOG_CLASS, &wc)) == 0)
{
@@ -2903,94 +3821,24 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine)
InitHelpFileName ();
#ifndef SETUP
+
+ EnableRamEncryption ((ReadDriverConfigurationFlags() & VC_DRIVER_CONFIG_ENABLE_RAM_ENCRYPTION) ? TRUE : FALSE);
+ if (IsRamEncryptionEnabled())
+ {
+ if (!InitializeSecurityParameters(GetAppRandomSeed))
+ AbortProcess("OUTOFMEMORY");
+ }
+
if (!EncryptionThreadPoolStart (ReadEncryptionThreadPoolFreeCpuCountLimit()))
{
handleWin32Error (NULL, SRC_POS);
- FREE_DLL (hRichEditDll);
- FREE_DLL (hComctl32Dll);
- FREE_DLL (hSetupDll);
- FREE_DLL (hShlwapiDll);
- FREE_DLL (hProfApiDll);
- FREE_DLL (hUsp10Dll);
- FREE_DLL (hCryptSpDll);
- FREE_DLL (hUXThemeDll);
- FREE_DLL (hUserenvDll);
- FREE_DLL (hRsaenhDll);
- FREE_DLL (himm32dll);
- FREE_DLL (hMSCTFdll);
- FREE_DLL (hfltlibdll);
- FREE_DLL (hframedyndll);
- FREE_DLL (hpsapidll);
- FREE_DLL (hsecur32dll);
- FREE_DLL (hnetapi32dll);
- FREE_DLL (hauthzdll);
- FREE_DLL (hxmllitedll);
- FREE_DLL (hmprdll);
- FREE_DLL (hsppdll);
- FREE_DLL (vssapidll);
- FREE_DLL (hvsstracedll);
- FREE_DLL (hCryptSpDll);
- FREE_DLL (hcfgmgr32dll);
- FREE_DLL (hdevobjdll);
- FREE_DLL (hpowrprofdll);
- FREE_DLL (hsspiclidll);
- FREE_DLL (hcryptbasedll);
- FREE_DLL (hdwmapidll);
- FREE_DLL (hmsasn1dll);
- FREE_DLL (hcrypt32dll);
- FREE_DLL (hbcryptdll);
- FREE_DLL (hbcryptprimitivesdll);
- FREE_DLL (hMsls31);
- FREE_DLL (hntmartadll);
- FREE_DLL (hwinscarddll);
exit (1);
}
#endif
}
-void FinalizeApp (void)
-{
- FREE_DLL (hRichEditDll);
- FREE_DLL (hComctl32Dll);
- FREE_DLL (hSetupDll);
- FREE_DLL (hShlwapiDll);
- FREE_DLL (hProfApiDll);
- FREE_DLL (hUsp10Dll);
- FREE_DLL (hCryptSpDll);
- FREE_DLL (hUXThemeDll);
- FREE_DLL (hUserenvDll);
- FREE_DLL (hRsaenhDll);
- FREE_DLL (himm32dll);
- FREE_DLL (hMSCTFdll);
- FREE_DLL (hfltlibdll);
- FREE_DLL (hframedyndll);
- FREE_DLL (hpsapidll);
- FREE_DLL (hsecur32dll);
- FREE_DLL (hnetapi32dll);
- FREE_DLL (hauthzdll);
- FREE_DLL (hxmllitedll);
- FREE_DLL (hmprdll);
- FREE_DLL (hsppdll);
- FREE_DLL (vssapidll);
- FREE_DLL (hvsstracedll);
- FREE_DLL (hCryptSpDll);
- FREE_DLL (hcfgmgr32dll);
- FREE_DLL (hdevobjdll);
- FREE_DLL (hpowrprofdll);
- FREE_DLL (hsspiclidll);
- FREE_DLL (hcryptbasedll);
- FREE_DLL (hdwmapidll);
- FREE_DLL (hmsasn1dll);
- FREE_DLL (hcrypt32dll);
- FREE_DLL (hbcryptdll);
- FREE_DLL (hbcryptprimitivesdll);
- FREE_DLL (hMsls31);
- FREE_DLL (hntmartadll);
- FREE_DLL (hwinscarddll);
-}
-
void InitHelpFileName (void)
{
wchar_t *lpszTmp;
@@ -3006,13 +3854,13 @@ void InitHelpFileName (void)
// Primary file name
if (strcmp (GetPreferredLangId(), "en") == 0
|| strlen(GetPreferredLangId()) == 0)
{
- StringCbCatW (szHelpFile, sizeof(szHelpFile), L"VeraCrypt User Guide.pdf");
+ StringCbCatW (szHelpFile, sizeof(szHelpFile), L"docs\\VeraCrypt User Guide.chm");
}
else
{
- StringCbPrintfW (szTemp, sizeof(szTemp), L"VeraCrypt User Guide.%S.pdf", GetPreferredLangId());
+ StringCbPrintfW (szTemp, sizeof(szTemp), L"docs\\VeraCrypt User Guide.%S.chm", GetPreferredLangId());
StringCbCatW (szHelpFile, sizeof(szHelpFile), szTemp);
}
// Secondary file name (used when localized documentation is not found).
@@ -3021,14 +3869,15 @@ void InitHelpFileName (void)
if (lpszTmp)
{
++lpszTmp;
*lpszTmp = 0;
- StringCbCatW (szHelpFile2, sizeof(szHelpFile2), L"VeraCrypt User Guide.pdf");
+ StringCbCatW (szHelpFile2, sizeof(szHelpFile2), L"docs\\VeraCrypt User Guide.chm");
}
}
}
-BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem, BOOL matchVolumeID, const BYTE* pbVolumeID)
+#ifndef SETUP
+BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem, BOOL computeVolumeIDs)
{
DWORD dwResult;
BOOL bResult;
wchar_t wszFileName[TC_MAX_PATH];
@@ -3039,11 +3888,9 @@ BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectF
memcpy (driver->wszFileName, wszFileName, sizeof (wszFileName));
driver->bDetectTCBootLoader = FALSE;
driver->DetectFilesystem = detectFilesystem;
- driver->bMatchVolumeID = matchVolumeID;
- if (matchVolumeID && pbVolumeID)
- memcpy (driver->volumeID, pbVolumeID, VOLUME_ID_SIZE);
+ driver->bComputeVolumeIDs = computeVolumeIDs;
bResult = DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST,
driver, sizeof (OPEN_TEST_STRUCT),
driver, sizeof (OPEN_TEST_STRUCT),
@@ -3069,9 +3916,9 @@ BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectF
if (dwResult == ERROR_SHARING_VIOLATION || dwResult == ERROR_NOT_READY)
{
driver->TCBootLoaderDetected = FALSE;
driver->FilesystemDetected = FALSE;
- driver->VolumeIDMatched = FALSE;
+ memset (driver->VolumeIDComputed, 0, sizeof (driver->VolumeIDComputed));
return TRUE;
}
else
return FALSE;
@@ -3079,8 +3926,9 @@ BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectF
return TRUE;
}
+#endif
// Tells the driver that it's running in portable mode
void NotifyDriverOfPortableMode (void)
{
@@ -3095,13 +3943,14 @@ void NotifyDriverOfPortableMode (void)
BOOL GetDriveLabel (int driveNo, wchar_t *label, int labelSize)
{
DWORD fileSystemFlags;
- wchar_t root[] = { L'A' + (wchar_t) driveNo, L':', L'\\', 0 };
+ wchar_t root[] = { (wchar_t) (L'A' + driveNo), L':', L'\\', 0 };
return GetVolumeInformationW (root, label, labelSize / 2, NULL, NULL, &fileSystemFlags, NULL, 0);
}
+#ifndef SETUP
/* Stores the device path of the system partition in SysPartitionDevicePath and the device path of the system drive
in SysDriveDevicePath.
IMPORTANT: As this may take a very long time if called for the first time, it should be called only before performing
@@ -3123,26 +3972,24 @@ BOOL GetSysDevicePaths (HWND hwndDlg)
if (device.ContainsSystem)
StringCchCopyW (device.IsPartition ? SysPartitionDevicePath : SysDriveDevicePath, TC_MAX_PATH, device.Path.c_str());
}
- if (IsOSAtLeast (WIN_7))
+ // Find extra boot partition
+ std::vector <HostDevice> devices = GetAvailableHostDevices(false, false);
+ for (const HostDevice& drive : devices)
{
- // Find extra boot partition
- foreach (const HostDevice &drive, GetAvailableHostDevices (false, false))
+ if (drive.ContainsSystem)
{
- if (drive.ContainsSystem)
+ for (const HostDevice &sysDrivePartition : drive.Partitions)
{
- foreach (const HostDevice &sysDrivePartition, drive.Partitions)
+ if (sysDrivePartition.Bootable)
{
- if (sysDrivePartition.Bootable)
- {
- if (sysDrivePartition.Size <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE)
- ExtraBootPartitionDevicePath = sysDrivePartition.Path;
- break;
- }
+ if (sysDrivePartition.Size <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE)
+ ExtraBootPartitionDevicePath = sysDrivePartition.Path;
+ break;
}
- break;
}
+ break;
}
}
bCachedSysDevicePathsValid = 1;
@@ -3252,8 +4099,9 @@ int IsNonSysPartitionOnSysDrive (const wchar_t *path)
return 0;
}
}
+#endif //!SETUP
wstring GetSysEncryptionPretestInfo2String (void)
{
// This huge string is divided into smaller portions to make it easier for translators to
@@ -3310,8 +4158,137 @@ wstring GetDecoyOsInstructionsString (void)
+ GetString ("DECOY_OS_INSTRUCTIONS_PORTION_17")
+ GetString ("DECOY_OS_INSTRUCTIONS_PORTION_18"));
}
+struct _TEXT_EDIT_DIALOG_PARAM {
+ BOOL ReadOnly;
+ std::string& Text;
+ const WCHAR* Title;
+
+ _TEXT_EDIT_DIALOG_PARAM (const _TEXT_EDIT_DIALOG_PARAM& other) : ReadOnly (other.ReadOnly), Text (other.Text), Title (other.Title) {}
+ _TEXT_EDIT_DIALOG_PARAM(BOOL _readOnly, const WCHAR* title, std::string& _text) : ReadOnly(_readOnly), Text(_text), Title(title) {}
+ _TEXT_EDIT_DIALOG_PARAM& operator=( const _TEXT_EDIT_DIALOG_PARAM& other) {
+ if (this != &other)
+ {
+ ReadOnly = other.ReadOnly;
+ Text = other.Text;
+ Title = other.Title;
+ }
+ return *this;
+}
+};
+typedef struct _TEXT_EDIT_DIALOG_PARAM TEXT_INFO_DIALOG_PARAM,*TEXT_INFO_DIALOG_PARAM_PTR;
+
+INT_PTR TextEditDialogBox (BOOL readOnly, HWND parent, const WCHAR* Title, std::string& text)
+{
+ TEXT_INFO_DIALOG_PARAM pm(readOnly, Title, text);
+ return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_EDIT_DLG), parent, (DLGPROC) TextEditDlgProc, (LPARAM) &pm);
+}
+
+BOOL CALLBACK TextEditDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WORD lw = LOWORD (wParam);
+ static int nID = 0;
+ static TEXT_INFO_DIALOG_PARAM_PTR prm;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ prm = (TEXT_INFO_DIALOG_PARAM_PTR)lParam;
+ LocalizeDialog (hwndDlg, NULL);
+ // increase size limit of rich edit control
+ SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_EXLIMITTEXT, 0, -1);
+
+ SetWindowTextW (hwndDlg, prm->Title);
+ // Left margin for rich edit text field
+ SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4));
+
+ if (prm->ReadOnly)
+ {
+ // switch rich edit control to ReadOnly
+ SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETREADONLY , TRUE, 0);
+ // hide cancel button
+ HWND hwndCancel = GetDlgItem(hwndDlg, IDCANCEL);
+ ShowWindow(hwndCancel, SW_HIDE);
+
+ // Reposition OK button to Cancel button's position
+ HWND hwndOK = GetDlgItem(hwndDlg, IDOK);
+ if (hwndOK && hwndCancel)
+ {
+ // Get Cancel button's position in screen coordinates
+ RECT rectCancel;
+ if (GetWindowRect(hwndCancel, &rectCancel))
+ {
+ // Convert Cancel button's position to dialog's client coordinates
+ POINT ptCancel = { rectCancel.left, rectCancel.top };
+ ScreenToClient(hwndDlg, &ptCancel);
+
+ // Get OK button's current size
+ RECT rectOK;
+ if (GetWindowRect(hwndOK, &rectOK))
+ {
+ int width = rectOK.right - rectOK.left;
+ int height = rectOK.bottom - rectOK.top;
+
+ // Move OK button to Cancel button's position
+ SetWindowPos(
+ hwndOK,
+ NULL,
+ ptCancel.x,
+ ptCancel.y,
+ width,
+ height,
+ SWP_NOZORDER | SWP_NOACTIVATE
+ );
+ }
+ }
+ }
+ }
+
+ SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0);
+ }
+ return 0;
+
+ case WM_COMMAND:
+ if (lw == IDOK )
+ {
+ if (!prm->ReadOnly)
+ {
+ // read content of the text box as UTF16 and then convert it to UTF8
+ HWND hEdit = GetDlgItem(hwndDlg, IDC_INFO_BOX_TEXT);
+ int size = GetWindowTextLengthW(hEdit);
+ std::vector<WCHAR> buffer(size + 1);
+ GetWindowTextW(hEdit, buffer.data(), size + 1);
+ prm->Text = WideToUtf8String(buffer.data());
+ }
+ NormalCursor ();
+ EndDialog (hwndDlg, IDOK);
+ return 1;
+ }
+
+ if (lw == IDCANCEL )
+ {
+ NormalCursor ();
+ EndDialog (hwndDlg, IDCANCEL);
+ return 1;
+ }
+ return 0;
+
+ case TC_APPMSG_LOAD_TEXT_BOX_CONTENT:
+ {
+ // convert prm->Text to UTF16 using Utf8StringToWide
+ SetWindowTextW(GetDlgItem(hwndDlg, IDC_INFO_BOX_TEXT), Utf8StringToWide(prm->Text).c_str());
+ }
+ return 0;
+
+ case WM_CLOSE:
+ NormalCursor ();
+ EndDialog (hwndDlg, 0);
+ return 1;
+ }
+
+ return 0;
+}
INT_PTR TextInfoDialogBox (int nID)
{
return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_INFO_DIALOG_BOX_DLG), MainDlg, (DLGPROC) TextInfoDialogBoxDlgProc, (LPARAM) nID);
@@ -3475,8 +4452,9 @@ char * GetLegalNotices ()
return buf;
}
+#ifndef SETUP
BOOL CALLBACK RawDevicesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static wchar_t *lpszFileName; // This is actually a pointer to a GLOBAL array
@@ -3833,8 +4811,9 @@ BOOL CALLBACK RawDevicesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM l
}
return 0;
}
+#endif //!SETUP
BOOL DoDriverInstall (HWND hwndDlg)
{
#ifdef SETUP
@@ -3919,9 +4898,9 @@ static int DriverLoad ()
}
else
*tmp = 0;
- StringCbCatW (driverPath, sizeof(driverPath), !Is64BitOs () ? L"\\veracrypt.sys" : L"\\veracrypt-x64.sys");
+ StringCbCatW (driverPath, sizeof(driverPath), IsARM()? L"\\veracrypt-arm64.sys" : L"\\veracrypt-x64.sys");
file = FindFirstFile (driverPath, &find);
if (file == INVALID_HANDLE_VALUE)
@@ -3974,9 +4953,8 @@ static int DriverLoad ()
BOOL DriverUnload ()
{
- MOUNT_LIST_STRUCT driver;
int refCount;
int volumesMounted;
DWORD dwResult;
BOOL bResult;
@@ -3999,15 +4977,8 @@ BOOL DriverUnload ()
// Test for mounted volumes
bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL);
- if (!bResult)
- {
- bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL);
- if (bResult)
- volumesMounted = driver.ulMountedDrives;
- }
-
if (bResult)
{
if (volumesMounted != 0)
return FALSE;
@@ -4172,11 +5143,8 @@ load:
DWORD dwResult;
BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL);
- if (!bResult)
- bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL);
-
#ifndef SETUP // Don't check version during setup to allow removal of another version
if (bResult == FALSE)
{
return ERR_OS_ERROR;
@@ -4186,12 +5154,18 @@ load:
// Unload an incompatbile version of the driver loaded in non-install mode and load the required version
if (IsNonInstallMode () && CreateDriverSetupMutex () && DriverUnload () && nLoadRetryCount++ < 3)
goto load;
- CloseDriverSetupMutex ();
- CloseHandle (hDriver);
- hDriver = INVALID_HANDLE_VALUE;
- return ERR_DRIVER_VERSION;
+#ifdef TCMOUNT
+ // don't fail in case of service. This solves issues during upgrade when system encryption is enabled
+ if (!ServiceMode)
+#endif
+ {
+ CloseDriverSetupMutex ();
+ CloseHandle (hDriver);
+ hDriver = INVALID_HANDLE_VALUE;
+ return ERR_DRIVER_VERSION;
+ }
}
#else
if (!bResult)
DriverVersion = 0;
@@ -4216,248 +5190,315 @@ void ResetCurrentDirectory ()
}
}
-BOOL BrowseFiles (HWND hwndDlg, char *stringId, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter)
+BOOL BrowseFiles (HWND hwndDlg, char *stringId, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode)
{
- return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, browseFilter);
+ return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, NULL);
}
-
-BOOL BrowseFilesInDir (HWND hwndDlg, char *stringId, wchar_t *initialDir, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter, const wchar_t *initialFileName, const wchar_t *defaultExtension)
+BOOL BrowseFilesInDir(HWND hwndDlg, char *stringId, wchar_t *initialDir, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter, const wchar_t *initialFileName, const wchar_t *defaultExtension)
{
- OPENFILENAMEW ofn;
- wchar_t file[TC_MAX_PATH] = { 0 };
+ IFileDialog *pfd = NULL;
+ HRESULT hr;
wchar_t filter[1024];
BOOL status = FALSE;
- CoInitialize (NULL);
-
- ZeroMemory (&ofn, sizeof (ofn));
- *lpszFileName = 0;
-
- if (initialDir)
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ if (FAILED(hr))
{
- ofn.lpstrInitialDir = initialDir;
+ return FALSE;
}
- if (initialFileName)
- StringCchCopyW (file, array_capacity (file), initialFileName);
-
- ofn.lStructSize = sizeof (ofn);
- ofn.hwndOwner = hwndDlg;
-
- StringCbPrintfW (filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c",
- GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0);
- ofn.lpstrFilter = browseFilter ? browseFilter : filter;
- ofn.nFilterIndex = 1;
- ofn.lpstrFile = file;
- ofn.nMaxFile = sizeof (file) / sizeof (file[0]);
- ofn.lpstrTitle = GetString (stringId);
- ofn.lpstrDefExt = defaultExtension;
- ofn.Flags = OFN_HIDEREADONLY
- | OFN_PATHMUSTEXIST
- | (keepHistory ? 0 : OFN_DONTADDTORECENT)
- | (saveMode ? OFN_OVERWRITEPROMPT : 0);
-
- if (!keepHistory)
- CleanLastVisitedMRU ();
-
- SystemFileSelectorCallerThreadId = GetCurrentThreadId();
- SystemFileSelectorCallPending = TRUE;
-
- if (!saveMode)
+ // Choose between the File Open or File Save dialog depending on the saveMode.
+ if (saveMode)
{
- if (!GetOpenFileNameW (&ofn))
- goto ret;
+ hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
}
else
{
- if (!GetSaveFileNameW (&ofn))
- goto ret;
+ hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
}
- SystemFileSelectorCallPending = FALSE;
+ if (SUCCEEDED(hr))
+ {
+ // Set the options for the dialog.
+ DWORD dwFlags;
+ hr = pfd->GetOptions(&dwFlags);
+ if (SUCCEEDED(hr))
+ {
+ dwFlags |= FOS_NOCHANGEDIR | FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE;
+ if (!keepHistory)
+ dwFlags |= FOS_DONTADDTORECENT;
+ if (saveMode)
+ dwFlags |= FOS_NOTESTFILECREATE | FOS_OVERWRITEPROMPT | FOS_DEFAULTNOMINIMODE;
+ hr = pfd->SetOptions(dwFlags);
+ }
- StringCchCopyW (lpszFileName, MAX_PATH, file);
+ // Set the initial directory, if provided.
+ if (initialDir)
+ {
+ IShellItem *psi;
+ hr = SHCreateItemFromParsingName(initialDir, NULL, IID_PPV_ARGS(&psi));
+ if (SUCCEEDED(hr))
+ {
+ pfd->SetFolder(psi);
+ psi->Release();
+ }
+ }
- if (!keepHistory)
- CleanLastVisitedMRU ();
+ // Set the initial file name, if provided.
+ if (initialFileName)
+ {
+ pfd->SetFileName(initialFileName);
+ }
- status = TRUE;
+ // Set the title.
+ pfd->SetTitle(GetString(stringId));
-ret:
- SystemFileSelectorCallPending = FALSE;
- ResetCurrentDirectory();
- CoUninitialize();
+ // Set the default extension.
+ if (defaultExtension)
+ {
+ pfd->SetDefaultExtension(defaultExtension);
+ }
- return status;
-}
+ // Prepare the filter
+ COMDLG_FILTERSPEC filterSpec[5];
+ UINT cfilterSpec = 0;
+ if (!browseFilter)
+ {
+ StringCbPrintfW(filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c",
+ GetString("ALL_FILES"), 0, 0, GetString("TC_VOLUMES"), 0, 0, 0);
+ browseFilter = filter;
+ }
-static wchar_t SelectMultipleFilesPath[131072];
-static int SelectMultipleFilesOffset;
+ // Assume browseFilter is a formatted wide string like L"Text Files (*.txt)\0*.txt\0"
+ // loop over all the filters in the string and add them to filterSpec array
+ while (*browseFilter)
+ {
+ filterSpec[cfilterSpec].pszName = browseFilter;
+ browseFilter += wcslen(browseFilter) + 1;
+ filterSpec[cfilterSpec].pszSpec = browseFilter;
+ browseFilter += wcslen(browseFilter) + 1;
+ cfilterSpec++;
-BOOL SelectMultipleFiles (HWND hwndDlg, const char *stringId, wchar_t *lpszFileName, size_t cbFileName,BOOL keepHistory)
-{
- OPENFILENAMEW ofn;
- wchar_t filter[1024];
- BOOL status = FALSE;
+ if (cfilterSpec >= ARRAYSIZE(filterSpec))
+ break;
+ }
- CoInitialize (NULL);
-
- ZeroMemory (&ofn, sizeof (ofn));
-
- SelectMultipleFilesPath[0] = 0;
- *lpszFileName = 0;
- ofn.lStructSize = sizeof (ofn);
- ofn.hwndOwner = hwndDlg;
- StringCbPrintfW (filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c",
- GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0);
- ofn.lpstrFilter = filter;
- ofn.nFilterIndex = 1;
- ofn.lpstrFile = SelectMultipleFilesPath;
- ofn.nMaxFile = 0xffff * 2; // The size must not exceed 0xffff*2 due to a bug in Windows 2000 and XP SP1
- ofn.lpstrTitle = GetString (stringId);
- ofn.Flags = OFN_HIDEREADONLY
- | OFN_EXPLORER
- | OFN_PATHMUSTEXIST
- | OFN_ALLOWMULTISELECT
- | (keepHistory ? 0 : OFN_DONTADDTORECENT);
-
- if (!keepHistory)
- CleanLastVisitedMRU ();
+ // Set the file types filter.
+ hr = pfd->SetFileTypes(cfilterSpec, filterSpec);
+ hr = pfd->SetFileTypeIndex(1);
- SystemFileSelectorCallerThreadId = GetCurrentThreadId();
- SystemFileSelectorCallPending = TRUE;
+ if (!keepHistory)
+ CleanLastVisitedMRU();
- if (!GetOpenFileNameW (&ofn))
- goto ret;
+ SystemFileSelectorCallerThreadId = GetCurrentThreadId();
+ SystemFileSelectorCallPending = TRUE;
- SystemFileSelectorCallPending = FALSE;
+ // Show the dialog.
+ hr = pfd->Show(hwndDlg);
- if (SelectMultipleFilesPath[ofn.nFileOffset - 1] != 0)
- {
- // Single file selected
- StringCbCopyW (lpszFileName, cbFileName, SelectMultipleFilesPath);
- SelectMultipleFilesOffset = 0;
- SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath));
- }
- else
- {
- // Multiple files selected
- SelectMultipleFilesOffset = ofn.nFileOffset;
- SelectMultipleFilesNext (lpszFileName, cbFileName);
- }
+ // Obtain the result if the user clicked the "OK" button.
+ if (SUCCEEDED(hr))
+ {
+ IShellItem *pItem;
+ hr = pfd->GetResult(&pItem);
+ if (SUCCEEDED(hr))
+ {
+ PWSTR pszFilePath;
+ hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
+ if (SUCCEEDED(hr))
+ {
+ StringCchCopyW(lpszFileName, MAX_PATH, pszFilePath);
+ CoTaskMemFree(pszFilePath);
+ status = TRUE;
+ }
+ pItem->Release();
+ }
+ }
- if (!keepHistory)
- CleanLastVisitedMRU ();
+ pfd->Release();
+
+ if (!keepHistory)
+ CleanLastVisitedMRU();
+ }
- status = TRUE;
-
-ret:
SystemFileSelectorCallPending = FALSE;
ResetCurrentDirectory();
CoUninitialize();
return status;
}
-
-BOOL SelectMultipleFilesNext (wchar_t *lpszFileName, size_t cbFileName)
+BOOL SelectMultipleFiles(HWND hwndDlg, const char *stringId, BOOL keepHistory, std::vector<std::wstring> &filesList)
{
- if (SelectMultipleFilesOffset == 0)
+ IFileOpenDialog *pfd = NULL;
+ HRESULT hr;
+ BOOL status = FALSE;
+
+ filesList.clear();
+
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ if (FAILED(hr))
+ {
return FALSE;
+ }
- StringCbCopyW (lpszFileName, cbFileName,SelectMultipleFilesPath);
- lpszFileName[TC_MAX_PATH - 1] = 0;
+ // Create the File Open Dialog object.
+ hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
+ if (SUCCEEDED(hr))
+ {
+ DWORD dwFlags;
+ hr = pfd->GetOptions(&dwFlags);
+ if (SUCCEEDED(hr))
+ {
+ dwFlags |= FOS_ALLOWMULTISELECT | FOS_NOCHANGEDIR | FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE;
+ if (!keepHistory)
+ dwFlags |= FOS_DONTADDTORECENT;
- if (lpszFileName[wcslen (lpszFileName) - 1] != L'\\')
- StringCbCatW (lpszFileName, cbFileName,L"\\");
+ hr = pfd->SetOptions(dwFlags);
+ }
- StringCbCatW (lpszFileName, cbFileName,SelectMultipleFilesPath + SelectMultipleFilesOffset);
+ // Set the title and filter
+ pfd->SetTitle(GetString(stringId));
- SelectMultipleFilesOffset += (int) wcslen (SelectMultipleFilesPath + SelectMultipleFilesOffset) + 1;
- if (SelectMultipleFilesPath[SelectMultipleFilesOffset] == 0)
- {
- SelectMultipleFilesOffset = 0;
- SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath));
- }
+ wchar_t allFilesfilter[512];
+ wchar_t volumesfilter[512];
- return TRUE;
-}
+ StringCbPrintfW(allFilesfilter, sizeof(allFilesfilter), L"%ls (*.*)", GetString("ALL_FILES"));
+ StringCbPrintfW(volumesfilter, sizeof(volumesfilter), L"%ls (*.hc)", GetString("TC_VOLUMES"));
+ COMDLG_FILTERSPEC rgSpec[] =
+ {
+ {allFilesfilter, L"*.*"},
+ {volumesfilter, L"*.hc"}};
+ hr = pfd->SetFileTypes(ARRAYSIZE(rgSpec), rgSpec);
-static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData)
-{
- switch(uMsg) {
- case BFFM_INITIALIZED:
- {
- /* WParam is TRUE since we are passing a path.
- It would be FALSE if we were passing a pidl. */
- SendMessageW (hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)pData);
- break;
- }
+ if (!keepHistory)
+ CleanLastVisitedMRU();
- case BFFM_SELCHANGED:
- {
- wchar_t szDir[TC_MAX_PATH];
+ // Show the dialog
+ hr = pfd->Show(hwndDlg);
+ if (SUCCEEDED(hr))
+ {
+ IShellItemArray *psiaResults;
+ hr = pfd->GetResults(&psiaResults);
+ if (SUCCEEDED(hr))
+ {
+ DWORD count;
+ hr = psiaResults->GetCount(&count);
+ if (SUCCEEDED(hr))
+ {
+ for (DWORD i = 0; i < count; ++i)
+ {
+ IShellItem *psi;
+ hr = psiaResults->GetItemAt(i, &psi);
+ if (SUCCEEDED(hr))
+ {
+ PWSTR pszFilePath;
+ hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
+ if (SUCCEEDED(hr))
+ {
+ filesList.push_back(pszFilePath);
+ CoTaskMemFree(pszFilePath);
+ }
+ psi->Release();
+ }
+ }
- /* Set the status window to the currently selected path. */
- if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir))
- {
- SendMessage (hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);
- }
- break;
- }
+ status = TRUE;
+ }
+ psiaResults->Release();
+ }
+ }
- default:
- break;
+ if (!keepHistory)
+ CleanLastVisitedMRU();
+
+ pfd->Release();
}
- return 0;
+ CoUninitialize();
+ return status;
}
-
-BOOL BrowseDirectories (HWND hwndDlg, char *lpszTitle, wchar_t *dirName)
+BOOL BrowseDirectories(HWND hwndDlg, char *lpszDlgTitle, wchar_t *dirName, const wchar_t *initialDir)
{
- BROWSEINFOW bi;
- LPITEMIDLIST pidl;
- LPMALLOC pMalloc;
- BOOL bOK = FALSE;
+ IFileDialog *pfd = NULL;
+ HRESULT hr;
+ BOOL bOK = FALSE;
- CoInitialize (NULL);
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ if (FAILED(hr))
+ {
+ return FALSE;
+ }
- if (SUCCEEDED (SHGetMalloc (&pMalloc)))
+ hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
+ if (SUCCEEDED(hr))
{
- ZeroMemory (&bi, sizeof(bi));
- bi.hwndOwner = hwndDlg;
- bi.pszDisplayName = 0;
- bi.lpszTitle = GetString (lpszTitle);
- bi.pidlRoot = 0;
- bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
- bi.lpfn = BrowseCallbackProc;
- bi.lParam = (LPARAM)dirName;
+ // Set the options on the dialog.
+ DWORD dwFlags;
+ hr = pfd->GetOptions(&dwFlags);
+ if (SUCCEEDED(hr))
+ {
+ dwFlags |= FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM | FOS_NOCHANGEDIR; // Important to enable folder-picking mode
+ hr = pfd->SetOptions(dwFlags);
+ }
+
+ // Set the title.
+ if (lpszDlgTitle)
+ {
+ pfd->SetTitle(GetString(lpszDlgTitle));
+ }
- pidl = SHBrowseForFolderW (&bi);
- if (pidl != NULL)
+ IShellItem *psi;
+ if (initialDir)
{
- if (SHGetPathFromIDList(pidl, dirName))
+ // Set the initial directory, if provided.
+ hr = SHCreateItemFromParsingName(initialDir, NULL, IID_PPV_ARGS(&psi));
+ }
+ else
+ {
+ // set folder to "This PC" shel item
+ hr = SHCreateItemInKnownFolder(FOLDERID_ComputerFolder, 0, NULL, IID_PPV_ARGS(&psi));
+ }
+ if (SUCCEEDED(hr))
+ {
+ pfd->SetFolder(psi);
+ psi->Release();
+ }
+
+ // Show the dialog.
+ hr = pfd->Show(hwndDlg);
+ if (SUCCEEDED(hr))
+ {
+ // Obtain the result when the user clicks the "OK" button.
+ // The result is an IShellItem object.
+ IShellItem *pItem;
+ hr = pfd->GetResult(&pItem);
+ if (SUCCEEDED(hr))
{
- bOK = TRUE;
+ PWSTR pszFolderPath;
+ hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFolderPath);
+ if (SUCCEEDED(hr))
+ {
+ StringCchCopyW(dirName, MAX_PATH, pszFolderPath);
+ CoTaskMemFree(pszFolderPath);
+ bOK = TRUE;
+ }
+ pItem->Release();
}
-
- pMalloc->Free (pidl);
- pMalloc->Release();
}
+ pfd->Release();
}
CoUninitialize();
-
return bOK;
}
-
std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg)
{
WCHAR szTmp[8192];
@@ -4592,13 +5633,8 @@ void handleError (HWND hwndDlg, int code, const char* srcPos)
case ERR_DONT_REPORT:
// A non-error
break;
- case ERR_UNSUPPORTED_TRUECRYPT_FORMAT:
- StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("UNSUPPORTED_TRUECRYPT_FORMAT"), (code >> 24), (code >> 16) & 0x000000FF);
- MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, ICON_HAND);
- break;
-
#ifndef SETUP
case ERR_RAND_INIT_FAILED:
StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("INIT_RAND"), SRC_POS, GetLastError ());
MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, MB_ICONERROR);
@@ -4609,8 +5645,16 @@ void handleError (HWND hwndDlg, int code, const char* srcPos)
MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, MB_ICONERROR);
break;
#endif
+ case ERR_XTS_MASTERKEY_VULNERABLE:
+ MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_XTS_MASTERKEY_VULNERABLE"), srcPos).c_str(), lpszTitle, ICON_HAND);
+ break;
+
+ case ERR_SYSENC_XTS_MASTERKEY_VULNERABLE:
+ MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_SYSENC_XTS_MASTERKEY_VULNERABLE"), srcPos).c_str(), lpszTitle, ICON_HAND);
+ break;
+
default:
StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("ERR_UNKNOWN"), code);
MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, ICON_HAND);
}
@@ -4683,9 +5727,9 @@ void OpenVolumeExplorerWindow (int driveNo)
// Force explorer to discover the drive
SHGetFileInfo (dosName, 0, &fInfo, sizeof (fInfo), 0);
- ShellExecute (NULL, L"open", dosName, NULL, NULL, SW_SHOWNORMAL);
+ SafeOpenURL (dosName);
}
static BOOL explorerCloseSent;
static HWND explorerTopLevelWindow;
@@ -4743,9 +5787,9 @@ BOOL CloseVolumeExplorerWindows (HWND hwnd, int driveNo)
BOOL UpdateDriveCustomLabel (int driveNo, wchar_t* effectiveLabel, BOOL bSetValue)
{
wchar_t wszRegPath[MAX_PATH];
- wchar_t driveStr[] = {L'A' + (wchar_t) driveNo, 0};
+ wchar_t driveStr[] = { (wchar_t) (L'A' + driveNo), 0};
HKEY hKey;
LSTATUS lStatus;
DWORD cbLabelLen = (DWORD) ((wcslen (effectiveLabel) + 1) * sizeof (wchar_t));
BOOL bToBeDeleted = FALSE;
@@ -4801,11 +5845,8 @@ wstring GetUserFriendlyVersionString (int version)
wstring versionString (szTmp);
versionString.insert (version > 0xfff ? 2 : 1,L".");
- if (versionString[versionString.length()-1] == L'0')
- versionString.erase (versionString.length()-1, 1);
-
return (versionString);
}
wstring IntToWideString (int val)
@@ -4831,26 +5872,26 @@ wstring ArrayToHexWideString (const unsigned char* pbData, int cbData)
return result;
}
-bool HexToByte (wchar_t c, byte& b)
+bool HexToByte (wchar_t c, uint8& b)
{
bool bRet = true;
if (c >= L'0' && c <= L'9')
- b = (byte) (c - L'0');
+ b = (uint8) (c - L'0');
else if (c >= L'a' && c <= L'z')
- b = (byte) (c - L'a' + 10);
+ b = (uint8) (c - L'a' + 10);
else if (c >= L'A' && c <= L'Z')
- b = (byte) (c - L'A' + 10);
+ b = (uint8) (c - L'A' + 10);
else
bRet = false;
return bRet;
}
-bool HexWideStringToArray (const wchar_t* hexStr, std::vector<byte>& arr)
+bool HexWideStringToArray (const wchar_t* hexStr, std::vector<uint8>& arr)
{
- byte b1, b2;
+ uint8 b1, b2;
size_t i, len = wcslen (hexStr);
arr.clear();
if (len %2)
@@ -5094,13 +6135,13 @@ static void DisplayBenchmarkResults (HWND hwndDlg)
LvItem.pszText = item1;
SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem);
break;
case BENCHMARK_TYPE_PRF:
- swprintf_s (item1, sizeof(item1) / sizeof(item1[0]), L"%d ms", benchmarkTable[i].meanBytesPerSec);
+ swprintf_s (item1, sizeof(item1) / sizeof(item1[0]), L"%d ms", (int) benchmarkTable[i].meanBytesPerSec);
LvItem.iSubItem = 1;
LvItem.pszText = item1;
SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem);
- swprintf_s (item1, sizeof(item1) / sizeof(item1[0]), L"%d", benchmarkTable[i].decSpeed);
+ swprintf_s (item1, sizeof(item1) / sizeof(item1[0]), L"%d", (int) benchmarkTable[i].decSpeed);
LvItem.iSubItem = 2;
LvItem.pszText = item1;
SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem);
break;
@@ -5135,15 +6176,13 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
LARGE_INTEGER performanceCountStart, performanceCountEnd;
BYTE *lpTestBuffer = NULL;
PCRYPTO_INFO ci = NULL;
UINT64_STRUCT startDataUnitNo;
- SYSTEM_INFO sysInfo = {0};
-
- GetSystemInfo (&sysInfo);
+ size_t cpuCount = GetCpuCount(NULL);
startDataUnitNo.Value = 0;
/* set priority to critical only when there are 2 or more CPUs on the system */
- if (sysInfo.dwNumberOfProcessors > 1 && (benchmarkType != BENCHMARK_TYPE_ENCRYPTION))
+ if (cpuCount > 1 && (benchmarkType != BENCHMARK_TYPE_ENCRYPTION))
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
ci = crypto_open ();
if (!ci)
@@ -5179,14 +6218,16 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
/* Measures the speed at which each of the hash algorithms processes the message to produce
a single digest.
*/
{
- BYTE *digest [MAX_DIGESTSIZE];
- WHIRLPOOL_CTX wctx;
- RMD160_CTX rctx;
+ BYTE digest [MAX_DIGESTSIZE];
+ #ifndef WOLFCRYPT_BACKEND
+ WHIRLPOOL_CTX wctx;
+ STREEBOG_CTX stctx;
+ blake2s_state bctx;
+ #endif
sha512_ctx s2ctx;
sha256_ctx s256ctx;
- STREEBOG_CTX stctx;
int hid, i;
for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++)
@@ -5209,13 +6250,13 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
sha256_begin (&s256ctx);
sha256_hash (lpTestBuffer, benchmarkBufferSize, &s256ctx);
sha256_end ((unsigned char *) digest, &s256ctx);
break;
-
- case RIPEMD160:
- RMD160Init(&rctx);
- RMD160Update(&rctx, lpTestBuffer, benchmarkBufferSize);
- RMD160Final((unsigned char *) digest, &rctx);
+ #ifndef WOLFCRYPT_BACKEND
+ case BLAKE2S:
+ blake2s_init(&bctx);
+ blake2s_update(&bctx, lpTestBuffer, benchmarkBufferSize);
+ blake2s_final(&bctx, (unsigned char *) digest);
break;
case WHIRLPOOL:
WHIRLPOOL_init (&wctx);
@@ -5229,9 +6270,10 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
STREEBOG_finalize(&stctx, (unsigned char *)digest);
break;
}
- }
+ #endif
+ }
if (QueryPerformanceCounter (&performanceCountEnd) == 0)
goto counter_error;
@@ -5252,9 +6294,9 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
each of the implemented PRF algorithms.
*/
{
int thid, i;
- char dk[MASTER_KEYDATA_SIZE];
+ unsigned char dk[MASTER_KEYDATA_SIZE];
char *tmp_salt = {"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"};
for (thid = FIRST_PRF_ID; thid <= LAST_PRF_ID; thid++)
{
@@ -5270,39 +6312,40 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
{
case SHA512:
/* PKCS-5 test with HMAC-SHA-512 used as the PRF */
- derive_key_sha512 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
+ derive_key_sha512 ((unsigned char*) "passphrase-1234567890", 21, (unsigned char*) tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
break;
case SHA256:
/* PKCS-5 test with HMAC-SHA-256 used as the PRF */
- derive_key_sha256 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
+ derive_key_sha256 ((unsigned char*)"passphrase-1234567890", 21, (unsigned char*) tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
break;
-
- case RIPEMD160:
- /* PKCS-5 test with HMAC-RIPEMD-160 used as the PRF */
- derive_key_ripemd160 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
+ #ifndef WOLFCRYPT_BACKEND
+ case BLAKE2S:
+ /* PKCS-5 test with HMAC-BLAKE2s used as the PRF */
+ derive_key_blake2s ((unsigned char*)"passphrase-1234567890", 21, (unsigned char*) tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
break;
case WHIRLPOOL:
/* PKCS-5 test with HMAC-Whirlpool used as the PRF */
- derive_key_whirlpool ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
+ derive_key_whirlpool ((unsigned char*)"passphrase-1234567890", 21, (unsigned char*) tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
break;
case STREEBOG:
/* PKCS-5 test with HMAC-STREEBOG used as the PRF */
- derive_key_streebog("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
+ derive_key_streebog((unsigned char*)"passphrase-1234567890", 21, (unsigned char*) tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
break;
}
- }
+ #endif
+ }
if (QueryPerformanceCounter (&performanceCountEnd) == 0)
goto counter_error;
benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
benchmarkTable[benchmarkTotalItems].id = thid;
- benchmarkTable[benchmarkTotalItems].decSpeed = get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot);
+ benchmarkTable[benchmarkTotalItems].decSpeed = get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot);
benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (unsigned __int64) (1000 * ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart / 2));
if (benchmarkPreBoot)
{
/* heuristics for boot times */
@@ -5313,21 +6356,13 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
else
{
if (thid == SHA256)
{
-#ifdef _WIN64
benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 26);
-#else
- benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 24);
-#endif
}
else
{
-#ifdef _WIN64
benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 21) / 5;
-#else
- benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 18) / 5;
-#endif
}
}
}
StringCbPrintfW (benchmarkTable[benchmarkTotalItems].name, sizeof(benchmarkTable[benchmarkTotalItems].name),L"%s", get_pkcs5_prf_name (thid));
@@ -5345,11 +6380,13 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
ci->ea = EAGetFirst();
if (!EAInit (ci->ea, ci->master_keydata, ci->ks))
{
ci->mode = FIRST_MODE_OF_OPERATION_ID;
- if (EAInitMode (ci))
+ if (EAInitMode (ci, ci->k2))
{
int i;
+ if (IsRamEncryptionEnabled ())
+ VcProtectKeys (ci, VcGetEncryptionID (ci));
for (i = 0; i < 10; i++)
{
EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci);
@@ -5366,11 +6403,14 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
if (ERR_CIPHER_INIT_FAILURE == EAInit (ci->ea, ci->master_keydata, ci->ks))
goto counter_error;
ci->mode = FIRST_MODE_OF_OPERATION_ID;
- if (!EAInitMode (ci))
+ if (!EAInitMode (ci, ci->k2))
goto counter_error;
+ if (IsRamEncryptionEnabled ())
+ VcProtectKeys (ci, VcGetEncryptionID (ci));
+
if (QueryPerformanceCounter (&performanceCountStart) == 0)
goto counter_error;
EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci);
@@ -5390,9 +6430,9 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
benchmarkTable[benchmarkTotalItems].decSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
benchmarkTable[benchmarkTotalItems].id = ci->ea;
benchmarkTable[benchmarkTotalItems].meanBytesPerSec = ((unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart)) + (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].decSpeed / benchmarkPerformanceFrequency.QuadPart))) / 2;
- EAGetName (benchmarkTable[benchmarkTotalItems].name, ci->ea, 1);
+ EAGetName (benchmarkTable[benchmarkTotalItems].name, 100, ci->ea, 1);
benchmarkTotalItems++;
}
}
@@ -5560,9 +6600,9 @@ BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP
SendMessage (hCboxBufferSize, CB_SETCURSEL, 5, 0); // Default buffer size
uint32 driverConfig = ReadDriverConfigurationFlags();
- int isAesHwSupported = is_aes_hw_cpu_supported();
+ int isAesHwSupported = HasAESNI();
SetDlgItemTextW (hwndDlg, IDC_HW_AES, (wstring (L" ") + (GetString (isAesHwSupported ? ((driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION) ? "UISTR_DISABLED" : "UISTR_YES") : "NOT_APPLICABLE_OR_NOT_AVAILABLE"))).c_str());
ToHyperlink (hwndDlg, IDC_HW_AES_LABEL_LINK);
@@ -5571,15 +6611,14 @@ BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP
{
Warning ("DISABLED_HW_AES_AFFECTS_PERFORMANCE", hwndDlg);
}
- SYSTEM_INFO sysInfo;
- GetSystemInfo (&sysInfo);
+ size_t cpuCount = GetCpuCount (NULL);
size_t nbrThreads = GetEncryptionThreadCount();
wchar_t nbrThreadsStr [300];
- if (sysInfo.dwNumberOfProcessors < 2)
+ if (cpuCount < 2)
{
StringCbCopyW (nbrThreadsStr, sizeof(nbrThreadsStr), GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"));
}
else if (nbrThreads < 2)
@@ -5594,10 +6633,10 @@ BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP
SetDlgItemTextW (hwndDlg, IDC_PARALLELIZATION, (wstring (L" ") + nbrThreadsStr).c_str());
ToHyperlink (hwndDlg, IDC_PARALLELIZATION_LABEL_LINK);
- if (nbrThreads < min (sysInfo.dwNumberOfProcessors, GetMaxEncryptionThreadCount())
- && sysInfo.dwNumberOfProcessors > 1)
+ if (nbrThreads < min (cpuCount, GetMaxEncryptionThreadCount())
+ && cpuCount > 1)
{
Warning ("LIMITED_THREAD_COUNT_AFFECTS_PERFORMANCE", hwndDlg);
}
@@ -5650,9 +6689,9 @@ BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP
case IDC_PERFORM_BENCHMARK:
if (benchmarkType == BENCHMARK_TYPE_PRF)
{
- benchmarkPim = GetPim (hwndDlg, IDC_PIM);
+ benchmarkPim = GetPim (hwndDlg, IDC_PIM, 0);
benchmarkPreBoot = GetCheckBox (hwndDlg, IDC_BENCHMARK_PREBOOT);
}
else
{
@@ -5677,14 +6716,14 @@ BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP
return 1;
case IDC_HW_AES_LABEL_LINK:
- Applink ("hwacceleration", TRUE, "");
+ Applink ("hwacceleration");
return 1;
case IDC_PARALLELIZATION_LABEL_LINK:
- Applink ("parallelization", TRUE, "");
+ Applink ("parallelization");
return 1;
case IDCLOSE:
case IDCANCEL:
@@ -5924,8 +6963,9 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
{
case WM_INITDIALOG:
{
HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID);
+ HWND hSizeUnit = GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE_UNIT);
HCRYPTPROV hRngProv = NULL;
VirtualLock (randPool, sizeof(randPool));
VirtualLock (lastRandPool, sizeof(lastRandPool));
@@ -5953,8 +6993,18 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
AddComboPair (hComboBox, HashGetName(hid), hid);
}
SelectAlgo (hComboBox, &hash_algo);
+ // populate keyfiles size unit combo
+ SendMessage (hSizeUnit, CB_RESETCONTENT, 0, 0);
+ AddComboPair (hSizeUnit, GetString ("BYTES"), 0);
+ AddComboPair (hSizeUnit, GetString ("KB"), 1);
+ AddComboPair (hSizeUnit, GetString ("MB"), 2);
+ AddComboPair (hSizeUnit, GetString ("GB"), 3);
+
+ // set default keyfiles size unit
+ SendMessage (hSizeUnit, CB_SETCURSEL, 0, 0);
+
SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents);
hEntropyBar = GetDlgItem (hwndDlg, IDC_ENTROPY_BAR);
SendMessage (hEntropyBar, PBM_SETRANGE32, 0, maxEntropyLevel);
SendMessage (hEntropyBar, PBM_SETSTEP, 1, 0);
@@ -5976,8 +7026,10 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
SendMessage (GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), EM_SETLIMITTEXT, (WPARAM) 7, 0);
SetWindowText(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), L"64");
// set the maximum length of the keyfile base name to (TC_MAX_PATH - 1)
SendMessage (GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), EM_SETLIMITTEXT, (WPARAM) (TC_MAX_PATH - 1), 0);
+
+ ToHyperlink (hwndDlg, IDC_LINK_KEYFILES_EXTENSIONS_WARNING);
return 1;
}
case WM_TIMER:
@@ -6060,8 +7112,15 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
if (lw == IDC_KEYFILES_RANDOM_SIZE)
{
EnableWindow(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), !GetCheckBox (hwndDlg, IDC_KEYFILES_RANDOM_SIZE));
+ EnableWindow(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE_UNIT), !GetCheckBox (hwndDlg, IDC_KEYFILES_RANDOM_SIZE));
+ }
+
+ if (lw == IDC_LINK_KEYFILES_EXTENSIONS_WARNING)
+ {
+ Applink ("keyfilesextensions");
+ return 1;
}
if (lw == IDC_GENERATE_AND_SAVE_KEYFILE)
{
@@ -6070,9 +7129,12 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
wchar_t szDirName[TC_MAX_PATH];
wchar_t szFileName [2*TC_MAX_PATH + 16];
unsigned char *keyfile = NULL;
int fhKeyfile = -1, status;
- long keyfilesCount = 0, keyfilesSize = 0, i;
+ long keyfilesCount = 0, i;
+ unsigned long long keyfilesSize = 0, remainingBytes = 0;
+ int selectedUnitIndex, selectedUnitFactor, loopIndex, rndBytesLength;
+ DWORD dwLastError = 0;
wchar_t* fileExtensionPtr = 0;
wchar_t szSuffix[32];
BOOL bRandomSize = GetCheckBox (hwndDlg, IDC_KEYFILES_RANDOM_SIZE);
@@ -6092,9 +7154,18 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
if (!GetWindowText(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), szNumber, ARRAYSIZE(szNumber)))
szNumber[0] = 0;
keyfilesSize = wcstoul(szNumber, NULL, 0);
- if (keyfilesSize < 64 || keyfilesSize > 1024*1024)
+ // multiply by the unit factor
+ selectedUnitIndex = ComboBox_GetCurSel (GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE_UNIT));
+ if (selectedUnitIndex != CB_ERR)
+ {
+ selectedUnitFactor = (CK_SLOT_ID) ComboBox_GetItemData (GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE_UNIT), selectedUnitIndex);
+ for (loopIndex = 0; loopIndex < selectedUnitFactor; loopIndex++)
+ keyfilesSize *= 1024ULL;
+ }
+
+ if (keyfilesSize < 64)
{
Warning("KEYFILE_INCORRECT_SIZE", hwndDlg);
SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), TRUE);
return 1;
@@ -6121,17 +7192,17 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
fileExtensionPtr = wcsrchr(szFileBaseName, L'.');
/* Select directory */
- if (!BrowseDirectories (hwndDlg, "SELECT_KEYFILE_GENERATION_DIRECTORY", szDirName))
+ if (!BrowseDirectories (hwndDlg, "SELECT_KEYFILE_GENERATION_DIRECTORY", szDirName, NULL))
return 1;
if (szDirName[wcslen(szDirName) - 1] != L'\\' && szDirName[wcslen(szDirName) - 1] != L'/')
StringCbCat(szDirName, sizeof(szDirName), L"\\");
WaitCursor();
- keyfile = (unsigned char*) TCalloc( bRandomSize? KEYFILE_MAX_READ_LEN : keyfilesSize );
+ keyfile = (unsigned char*) TCalloc(KEYFILE_MAX_READ_LEN);
for (i= 0; i < keyfilesCount; i++)
{
StringCbCopyW(szFileName, sizeof(szFileName), szDirName);
@@ -6192,34 +7263,48 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
NormalCursor();
return 1;
}
- /* since keyfilesSize < 1024 * 1024, we mask with 0x000FFFFF */
- keyfilesSize = (long) (((unsigned long) keyfilesSize) & 0x000FFFFF);
+ /* since random keyfilesSize < 1024 * 1024, we mask with 0x000FFFFF */
+ keyfilesSize = (unsigned long long) (((unsigned long) keyfilesSize) & 0x000FFFFF);
keyfilesSize %= ((KEYFILE_MAX_READ_LEN - 64) + 1);
keyfilesSize += 64;
+
}
- /* Generate the keyfile */
- if (!RandgetBytesFull (hwndDlg, keyfile, keyfilesSize, TRUE, TRUE))
- {
- _close (fhKeyfile);
- DeleteFile (szFileName);
- TCfree(keyfile);
- NormalCursor();
- return 1;
- }
+ remainingBytes = keyfilesSize;
+
+ do {
+ rndBytesLength = (int) min (remainingBytes, (unsigned long long) KEYFILE_MAX_READ_LEN);
+
+ /* Generate the keyfile */
+ if (!RandgetBytesFull (hwndDlg, keyfile, rndBytesLength, TRUE, TRUE))
+ {
+ _close (fhKeyfile);
+ DeleteFile (szFileName);
+ TCfree(keyfile);
+ NormalCursor();
+ return 1;
+ }
+
+ /* Write the keyfile */
+ status = _write (fhKeyfile, keyfile, rndBytesLength);
+ } while (status != -1 && (remainingBytes -= (unsigned long long) rndBytesLength) > 0);
+
+ /* save last error code */
+ if (status == -1)
+ dwLastError = GetLastError();
- /* Write the keyfile */
- status = _write (fhKeyfile, keyfile, keyfilesSize);
- burn (keyfile, keyfilesSize);
+ burn (keyfile, KEYFILE_MAX_READ_LEN);
_close (fhKeyfile);
if (status == -1)
{
TCfree(keyfile);
NormalCursor();
+ /* restore last error code */
+ SetLastError(dwLastError);
handleWin32Error (hwndDlg, SRC_POS);
return 1;
}
}
@@ -6314,9 +7399,9 @@ CipherTestDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_RESETCONTENT, 0, 0);
for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea))
{
if (EAGetCipherCount (ea) == 1 && EAIsFormatEnabled (ea))
- AddComboPair (GetDlgItem (hwndDlg, IDC_CIPHER), EAGetName (buf, ea, 1), EAGetFirstCipher (ea));
+ AddComboPair (GetDlgItem (hwndDlg, IDC_CIPHER), EAGetName (buf, ARRAYSIZE(buf),ea, 1), EAGetFirstCipher (ea));
}
ResetCipherTest(hwndDlg, idTestCipher);
@@ -6552,9 +7637,9 @@ CipherTestDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
return 1;
}
memcpy (&ci->k2, secondaryKey, sizeof (secondaryKey));
- if (!EAInitMode (ci))
+ if (!EAInitMode (ci, ci->k2))
{
crypto_close (ci);
return 1;
}
@@ -6570,9 +7655,9 @@ CipherTestDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
else
{
- CipherInit2(idTestCipher, key, ks_tmp, ks);
+ CipherInit2(idTestCipher, key, ks_tmp);
if (bEncrypt)
{
EncipherBlock(idTestCipher, tmp, ks_tmp);
@@ -6656,11 +7741,8 @@ ResetCipherTest(HWND hwndDlg, int idTestCipher)
SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), L"0000000000000000");
SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), L"0000000000000000");
if (idTestCipher == AES || idTestCipher == SERPENT || idTestCipher == TWOFISH || idTestCipher == CAMELLIA
-#if defined(CIPHER_GOST89)
- || idTestCipher == GOST89
-#endif
|| idTestCipher == KUZNYECHIK
)
{
ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) L"256");
@@ -6966,8 +8048,30 @@ void CorrectFileName (wchar_t* fileName)
fileName [i] = L'\\';
}
}
+void CorrectFileName (std::wstring& fileName)
+{
+ /* replace '/' by '\' */
+ size_t i, len = fileName.length();
+ for (i = 0; i < len; i++)
+ {
+ if (fileName [i] == L'/')
+ fileName [i] = L'\\';
+ }
+}
+
+void CorrectURL (wchar_t* fileName)
+{
+ /* replace '\' by '/' */
+ size_t i, len = wcslen (fileName);
+ for (i = 0; i < len; i++)
+ {
+ if (fileName [i] == L'\\')
+ fileName [i] = L'/';
+ }
+}
+
void IncreaseWrongPwdRetryCount (int count)
{
WrongPwdRetryCounter += count;
}
@@ -6995,10 +8099,10 @@ DWORD GetUsedLogicalDrives (void)
EnterCriticalSection (&csWNetCalls);
finally_do ({ LeaveCriticalSection (&csWNetCalls); });
- /* update values every 2 seconds to reduce CPU consumption */
- if ((time (NULL) - g_lastCallTime) > 2)
+ /* update values every 1 minute to reduce CPU consumption */
+ if ((time (NULL) - g_lastCallTime) > 60)
{
/* detect disconnected mapped network shares and removed
* their associated drives from the list
*/
@@ -7064,9 +8168,12 @@ int GetLastAvailableDrive ()
BOOL IsDriveAvailable (int driveNo)
{
- return (GetUsedLogicalDrives() & (1 << driveNo)) == 0;
+ if (driveNo >= 0 && driveNo < 26)
+ return (GetUsedLogicalDrives() & (1 << driveNo)) == 0;
+ else
+ return FALSE;
}
BOOL IsDeviceMounted (wchar_t *deviceName)
@@ -7158,9 +8265,9 @@ void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap)
if (message == DBT_DEVICEARRIVAL)
eventId = SHCNE_DRIVEADD;
else if (message == DBT_DEVICEREMOVECOMPLETE)
eventId = SHCNE_DRIVEREMOVED;
- else if (IsOSAtLeast (WIN_7) && message == DBT_DEVICEREMOVEPENDING) // Explorer on Windows 7 holds open handles of all drives when 'Computer' is expanded in navigation pane. SHCNE_DRIVEREMOVED must be used as DBT_DEVICEREMOVEPENDING is ignored.
+ else if (message == DBT_DEVICEREMOVEPENDING) // Explorer on Windows 7 holds open handles of all drives when 'Computer' is expanded in navigation pane. SHCNE_DRIVEREMOVED must be used as DBT_DEVICEREMOVEPENDING is ignored.
eventId = SHCNE_DRIVEREMOVED;
if (driveMap == 0)
driveMap = (1 << nDosDriveNo);
@@ -7170,9 +8277,9 @@ void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap)
for (i = 0; i < 26; i++)
{
if (driveMap & (1 << i))
{
- wchar_t root[] = { (wchar_t) i + L'A', L':', L'\\', 0 };
+ wchar_t root[] = { (wchar_t) (i + L'A'), L':', L'\\', 0 };
SHChangeNotify (eventId, SHCNF_PATH, root, NULL);
}
@@ -7200,38 +8307,98 @@ void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap)
IgnoreWmDeviceChange = FALSE;
}
-BOOL GetPhysicalDriveAlignment(UINT nDriveNumber, STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR* pDesc)
+static BOOL GetDeviceStorageProperty (HANDLE hDevice, STORAGE_PROPERTY_ID propertyId, DWORD dwDescSize, void* pDesc)
{
DWORD dwRet = NO_ERROR;
if (!pDesc)
return FALSE;
- // Format physical drive path (may be '\\.\PhysicalDrive0', '\\.\PhysicalDrive1' and so on).
- TCHAR strDrivePath[512];
- StringCbPrintf(strDrivePath, sizeof(strDrivePath), _T("\\\\.\\PhysicalDrive%u"), nDriveNumber);
-
- // Get a handle to physical drive
- HANDLE hDevice = ::CreateFile(strDrivePath, 0, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, 0, NULL);
-
- if(INVALID_HANDLE_VALUE == hDevice)
- return FALSE;
+ ZeroMemory (pDesc, dwDescSize);
// Set the input data structure
STORAGE_PROPERTY_QUERY storagePropertyQuery;
ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY));
- storagePropertyQuery.PropertyId = StorageAccessAlignmentProperty;
+ storagePropertyQuery.PropertyId = propertyId;
storagePropertyQuery.QueryType = PropertyStandardQuery;
// Get the necessary output buffer size
+ STORAGE_DESCRIPTOR_HEADER descHeader = {0};
DWORD dwBytesReturned = 0;
BOOL bRet = ::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
- pDesc, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
+ &descHeader, sizeof(STORAGE_DESCRIPTOR_HEADER),
&dwBytesReturned, NULL);
+ if (bRet)
+ {
+ if (dwBytesReturned == sizeof(STORAGE_DESCRIPTOR_HEADER))
+ {
+ unsigned char* outputBuffer = (unsigned char*) TCalloc (descHeader.Size);
+ bRet = ::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
+ &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
+ outputBuffer, descHeader.Size,
+ &dwBytesReturned, NULL);
+ if (bRet)
+ {
+ if (dwBytesReturned >= dwDescSize)
+ {
+ memcpy (pDesc, outputBuffer, dwDescSize);
+ ((STORAGE_DESCRIPTOR_HEADER*)pDesc)->Version = dwDescSize;
+ ((STORAGE_DESCRIPTOR_HEADER*)pDesc)->Size = dwDescSize;
+ }
+ else
+ {
+ bRet = FALSE;
+ dwRet = ERROR_UNHANDLED_ERROR;
+ }
+ }
+ else
+ dwRet = ::GetLastError();
+ TCfree (outputBuffer);
+ }
+ else
+ {
+ bRet = FALSE;
+ dwRet = ERROR_UNHANDLED_ERROR;
+ }
+ }
+ else
+ dwRet = ::GetLastError();
+
+ if (!bRet)
+ {
+ SetLastError (dwRet);
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+BOOL GetPhysicalDriveStorageInformation(UINT nDriveNumber, STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR* pAlignmentDesc, STORAGE_ADAPTER_DESCRIPTOR* pAdapterDesc)
+{
+ DWORD dwRet = NO_ERROR;
+
+ if (!pAlignmentDesc || pAdapterDesc)
+ {
+ SetLastError (ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ // Format physical drive path (may be '\\.\PhysicalDrive0', '\\.\PhysicalDrive1' and so on).
+ TCHAR strDrivePath[512];
+ StringCbPrintf(strDrivePath, sizeof(strDrivePath), _T("\\\\.\\PhysicalDrive%u"), nDriveNumber);
+
+ // Get a handle to physical drive
+ HANDLE hDevice = ::CreateFile(strDrivePath, 0, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+
+ if(INVALID_HANDLE_VALUE == hDevice)
+ return FALSE;
+
+ BOOL bRet = (GetDeviceStorageProperty (hDevice, StorageAccessAlignmentProperty, sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), pAlignmentDesc)
+ || GetDeviceStorageProperty (hDevice, StorageAdapterProperty, sizeof (STORAGE_ADAPTER_DESCRIPTOR), pAdapterDesc))? TRUE : FALSE;
dwRet = ::GetLastError();
::CloseHandle(hDevice);
if (!bRet)
@@ -7242,8 +8409,10 @@ BOOL GetPhysicalDriveAlignment(UINT nDriveNumber, STORAGE_ACCESS_ALIGNMENT_DESCR
else
return TRUE;
}
+#ifndef SETUP
+
/************************************************************/
// implementation of the generic wait dialog mechanism
@@ -7323,35 +8492,44 @@ BOOL CALLBACK WaitDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
}
}
-void BringToForeground(HWND hWnd)
+// Based on source: https://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo?msg=5285754#xx5285754xx
+void BringToForeground (HWND hWnd)
{
if(!::IsWindow(hWnd)) return;
-
- DWORD lockTimeOut = 0;
HWND hCurrWnd = ::GetForegroundWindow();
DWORD dwThisTID = ::GetCurrentThreadId(),
dwCurrTID = ::GetWindowThreadProcessId(hCurrWnd,0);
-
+ // This structure will be used to create the keyboard
+ // input event.
+ INPUT ip;
+
if (hCurrWnd != hWnd)
{
if(dwThisTID != dwCurrTID)
{
- ::AttachThreadInput(dwThisTID, dwCurrTID, TRUE);
-
- ::SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT,0,&lockTimeOut,0);
- ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,0,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
-
- ::AllowSetForegroundWindow(ASFW_ANY);
+ // Set up a generic keyboard event.
+ ip.type = INPUT_KEYBOARD;
+ ip.ki.wScan = 0; // hardware scan code for key
+ ip.ki.time = 0;
+ ip.ki.dwExtraInfo = 0;
+
+ // Press the "A" key
+ ip.ki.wVk = VK_MENU; // virtual-key code for the "a" key
+ ip.ki.dwFlags = 0; // 0 for key press
+ SendInput(1, &ip, sizeof(INPUT));
+
+ ::Sleep(250); //Sometimes SetForegroundWindow will fail and the window will flash instead of it being show. Sleeping for a bit seems to help.
}
-
+
::SetForegroundWindow(hWnd);
-
+
if(dwThisTID != dwCurrTID)
{
- ::SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,(PVOID)lockTimeOut,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
- ::AttachThreadInput(dwThisTID, dwCurrTID, FALSE);
+ // Release the "A" key
+ ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
+ SendInput(1, &ip, sizeof(INPUT));
}
}
#ifdef TCMOUNT
@@ -7362,11 +8540,16 @@ void BringToForeground(HWND hWnd)
}
#endif
}
+static LRESULT CALLBACK ShowWaitDialogParentWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ return DefWindowProcW (hWnd, message, wParam, lParam);
+}
+
+
void ShowWaitDialog(HWND hwnd, BOOL bUseHwndAsParent, WaitThreadProc callback, void* pArg)
{
- HWND hParent = (hwnd && bUseHwndAsParent)? hwnd : GetDesktopWindow();
BOOL bEffectiveHideWaitingDialog = bCmdHideWaitingDialogValid? bCmdHideWaitingDialog : bHideWaitingDialog;
WaitThreadParam threadParam;
threadParam.callback = callback;
threadParam.pArg = pArg;
@@ -7378,35 +8561,68 @@ void ShowWaitDialog(HWND hwnd, BOOL bUseHwndAsParent, WaitThreadProc callback, v
if (!WaitDialogDisplaying) NormalCursor ();
}
else
{
+ const wchar_t *className = L"VeraCryptShowWaitDialogParent";
BOOL bIsForeground = FALSE;
HWND creatorWnd = hwnd? hwnd : MainDlg;
WaitDialogDisplaying = TRUE;
+ HWND hParent = NULL;
+
if (creatorWnd)
{
if (GetForegroundWindow () == creatorWnd)
bIsForeground = TRUE;
EnableWindow (creatorWnd, FALSE);
}
+ if (hwnd && bUseHwndAsParent)
+ hParent = hwnd;
+ else
+ {
+ /* create invisible window and use it as parent */
+ WNDCLASSEXW winClass;
+
+ memset (&winClass, 0, sizeof (winClass));
+ winClass.cbSize = sizeof (WNDCLASSEX);
+ winClass.lpfnWndProc = (WNDPROC) ShowWaitDialogParentWndProc;
+ winClass.hInstance = hInst;
+ winClass.lpszClassName = className;
+ RegisterClassExW (&winClass);
+
+ hParent = CreateWindowExW (WS_EX_TOOLWINDOW | WS_EX_LAYERED, className, L"VeraCrypt ShowWaitDialog Parent", 0, 0, 0, 1, 1, NULL, NULL, hInst, NULL);
+ if (hParent)
+ {
+ SetLayeredWindowAttributes (hParent, 0, 1, LWA_ALPHA);
+ ShowWindow (hParent, SW_SHOWNORMAL);
+ }
+ }
+
finally_do_arg2 (HWND, creatorWnd, BOOL, bIsForeground, { if (finally_arg) { EnableWindow(finally_arg, TRUE); if (finally_arg2) BringToForeground (finally_arg);}});
DialogBoxParamW (hInst,
MAKEINTRESOURCEW (IDD_STATIC_MODAL_WAIT_DLG), hParent,
(DLGPROC) WaitDlgProc, (LPARAM) &threadParam);
WaitDialogDisplaying = FALSE;
+
+ if (!(hwnd && bUseHwndAsParent))
+ {
+ if (hParent)
+ DestroyWindow (hParent);
+ UnregisterClassW (className, hInst);
+ }
}
}
+#ifndef SETUP
/************************************************************************/
static BOOL PerformMountIoctl (MOUNT_STRUCT* pmount, LPDWORD pdwResult, BOOL useVolumeID, BYTE volumeID[VOLUME_ID_SIZE])
{
if (useVolumeID)
{
- wstring devicePath = FindDeviceByVolumeID (volumeID);
+ wstring devicePath = FindDeviceByVolumeID (volumeID, FALSE);
if (devicePath == L"")
{
if (pdwResult)
*pdwResult = 0;
@@ -7464,9 +8680,8 @@ int MountVolume (HWND hwndDlg,
wchar_t *volumePath,
Password *password,
int pkcs5,
int pim,
- BOOL truecryptMode,
BOOL cachePassword,
BOOL cachePim,
BOOL sharedAccess,
const MountOptions* const mountOptions,
@@ -7504,9 +8719,9 @@ int MountVolume (HWND hwndDlg,
return -1;
}
// If using cached passwords, check cache status first
- if (password == NULL && IsPasswordCacheEmpty ())
+ if (password == NULL && (mountOptions->SkipCachedPasswords || IsPasswordCacheEmpty ()))
return 0;
ZeroMemory (&mount, sizeof (mount));
mount.bExclusiveAccess = sharedAccess ? FALSE : TRUE;
@@ -7539,18 +8754,16 @@ retry:
mount.bMountReadOnly = mountOptions->ReadOnly;
mount.bMountRemovable = mountOptions->Removable;
mount.bPreserveTimestamp = mountOptions->PreserveTimestamp;
-
- mount.bMountManager = TRUE;
+
+ if (mountOptions->DisableMountManager)
+ mount.bMountManager = FALSE;
+ else
+ mount.bMountManager = TRUE;
mount.pkcs5_prf = pkcs5;
- mount.bTrueCryptMode = truecryptMode;
mount.VolumePim = pim;
- // Windows 2000 mount manager causes problems with remounted volumes
- if (CurrentOSMajor == 5 && CurrentOSMinor == 0)
- mount.bMountManager = FALSE;
-
wstring path = volumePath;
if (path.find (L"\\\\?\\") == 0)
{
// Remove \\?\ prefix
@@ -7567,9 +8780,9 @@ retry:
}
if ((path.length () >= 3) && (_wcsnicmp (path.c_str(), L"ID:", 3) == 0))
{
- std::vector<byte> arr;
+ std::vector<uint8> arr;
if ( (path.length() == (3 + 2*VOLUME_ID_SIZE))
&& HexWideStringToArray (path.c_str() + 3, arr)
&& (arr.size() == VOLUME_ID_SIZE)
)
@@ -7591,8 +8804,15 @@ retry:
CreateFullVolumePath (mount.wszVolume, sizeof(mount.wszVolume), volumePath, &bDevice);
if (!bDevice)
{
+ // put default values
+ mount.BytesPerSector = 512;
+ mount.BytesPerPhysicalSector = 512;
+ mount.MaximumTransferLength = 65536;
+ mount.MaximumPhysicalPages = 17;
+ mount.AlignmentMask = 0;
+
// UNC path
if (path.find (L"\\\\") == 0)
{
StringCbCopyW (mount.wszVolume, sizeof (mount.wszVolume), (L"UNC" + path.substr (1)).c_str());
@@ -7606,37 +8826,46 @@ retry:
mount.BytesPerSector = bps;
mount.BytesPerPhysicalSector = bps;
}
- if (IsOSAtLeast (WIN_VISTA))
- {
- if ( (wcslen(root) >= 2)
- && (root[1] == L':')
- && (towupper(root[0]) >= L'A' && towupper(root[0]) <= L'Z')
- )
+ if ( (wcslen(root) >= 2)
+ && (root[1] == L':')
+ && (towupper(root[0]) >= L'A' && towupper(root[0]) <= L'Z')
+ )
+ {
+ wstring drivePath = L"\\\\.\\X:";
+ HANDLE dev = INVALID_HANDLE_VALUE;
+ VOLUME_DISK_EXTENTS extents = {0};
+ DWORD cbReturnedBytes = 0;
+ drivePath[4] = root[0];
+
+ if ((dev = CreateFile (drivePath.c_str(),0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
{
- wstring drivePath = L"\\\\.\\X:";
- HANDLE dev = INVALID_HANDLE_VALUE;
- VOLUME_DISK_EXTENTS extents = {0};
- DWORD dwResult = 0;
- drivePath[4] = root[0];
-
- if ((dev = CreateFile (drivePath.c_str(),0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
+ if (DeviceIoControl (dev, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extents, sizeof(extents), &cbReturnedBytes, NULL))
{
- if (DeviceIoControl (dev, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extents, sizeof(extents), &dwResult, NULL))
+ if (extents.NumberOfDiskExtents > 0)
{
- if (extents.NumberOfDiskExtents > 0)
+ STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR accessDesc;
+ STORAGE_ADAPTER_DESCRIPTOR adapterDesc;
+
+ if (GetPhysicalDriveStorageInformation (extents.Extents[0].DiskNumber, &accessDesc, &adapterDesc))
{
- STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR desc;
- if (GetPhysicalDriveAlignment (extents.Extents[0].DiskNumber, &desc))
+ if (accessDesc.Size >= sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR))
+ {
+ mount.BytesPerSector = accessDesc.BytesPerLogicalSector;
+ mount.BytesPerPhysicalSector = accessDesc.BytesPerPhysicalSector;
+ }
+
+ if (adapterDesc.Size >= sizeof (STORAGE_ADAPTER_DESCRIPTOR))
{
- mount.BytesPerSector = desc.BytesPerLogicalSector;
- mount.BytesPerPhysicalSector = desc.BytesPerPhysicalSector;
+ mount.MaximumTransferLength = adapterDesc.MaximumTransferLength;
+ mount.MaximumPhysicalPages = adapterDesc.MaximumPhysicalPages;
+ mount.AlignmentMask = adapterDesc.AlignmentMask;
}
}
}
- CloseHandle (dev);
}
+ CloseHandle (dev);
}
}
// Read-only host filesystem
@@ -7648,10 +8877,9 @@ retry:
if (mountOptions->PartitionInInactiveSysEncScope)
{
if (mount.wszVolume == NULL || swscanf_s ((const wchar_t *) mount.wszVolume,
WIDE("\\Device\\Harddisk%d\\Partition"),
- &mount.nPartitionInInactiveSysEncScopeDriveNo,
- sizeof(mount.nPartitionInInactiveSysEncScopeDriveNo)) != 1)
+ &mount.nPartitionInInactiveSysEncScopeDriveNo) != 1)
{
if (!quiet)
Warning ("NO_SYSENC_PARTITION_SELECTED", hwndDlg);
return -1;
@@ -7683,9 +8911,8 @@ retry:
burn (&mount.VolumePassword, sizeof (mount.VolumePassword));
burn (&mount.ProtectedHidVolPassword, sizeof (mount.ProtectedHidVolPassword));
burn (&mount.pkcs5_prf, sizeof (mount.pkcs5_prf));
- burn (&mount.bTrueCryptMode, sizeof (mount.bTrueCryptMode));
burn (&mount.ProtectedHidVolPkcs5Prf, sizeof (mount.ProtectedHidVolPkcs5Prf));
SetLastError (dwLastError);
if (bResult == FALSE)
@@ -7749,20 +8976,20 @@ retry:
}
if (bDevice && mount.bProtectHiddenVolume)
{
- int driveNo;
+ int diskNo;
- if (swscanf (volumePath, L"\\Device\\Harddisk%d\\Partition", &driveNo) == 1)
+ if (swscanf (volumePath, L"\\Device\\Harddisk%d\\Partition", &diskNo) == 1)
{
OPEN_TEST_STRUCT openTestStruct;
memset (&openTestStruct, 0, sizeof (openTestStruct));
openTestStruct.bDetectTCBootLoader = TRUE;
- StringCchPrintfW ((wchar_t *) openTestStruct.wszFileName, array_capacity (openTestStruct.wszFileName), L"\\Device\\Harddisk%d\\Partition0", driveNo);
+ StringCchPrintfW ((wchar_t *) openTestStruct.wszFileName, array_capacity (openTestStruct.wszFileName), L"\\Device\\Harddisk%d\\Partition0", diskNo);
- DWORD dwResult;
- if (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, &openTestStruct, sizeof (OPEN_TEST_STRUCT), &openTestStruct, sizeof (OPEN_TEST_STRUCT), &dwResult, NULL) && openTestStruct.TCBootLoaderDetected)
+ DWORD cbBytesReturned;
+ if (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, &openTestStruct, sizeof (OPEN_TEST_STRUCT), &openTestStruct, sizeof (OPEN_TEST_STRUCT), &cbBytesReturned, NULL) && openTestStruct.TCBootLoaderDetected)
WarningDirect ((GetWrongPasswordErrorMessage (hwndDlg) + L"\n\n" + GetString ("HIDDEN_VOL_PROT_PASSWORD_US_KEYB_LAYOUT")).c_str(), hwndDlg);
else
handleError (hwndDlg, mount.nReturnCode, SRC_POS);
}
@@ -7790,12 +9017,18 @@ retry:
}
LastMountedVolumeDirty = mount.FilesystemDirty;
+ if (mount.VolumeMasterKeyVulnerable
+ && !Silent)
+ {
+ Warning ("ERR_XTS_MASTERKEY_VULNERABLE", hwndDlg);
+ }
+
if (mount.FilesystemDirty)
{
wchar_t msg[1024];
- wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 };
+ wchar_t mountPoint[] = { (wchar_t) (L'A' + driveNo), L':', 0 };
StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_VOLUME_DIRTY"), mountPoint);
if (AskWarnYesNoStringTopmost (msg, hwndDlg) == IDYES)
CheckFilesystem (hwndDlg, driveNo, TRUE);
@@ -7807,9 +9040,9 @@ retry:
&& !FileHasReadOnlyAttribute (volumePath)
&& !IsFileOnReadOnlyFilesystem (volumePath))
{
wchar_t msg[1024];
- wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 };
+ wchar_t mountPoint[] = { (wchar_t) (L'A' + driveNo), L':', 0 };
StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_CONTAINER_FORCED_READ_ONLY"), mountPoint);
WarningDirect (msg, hwndDlg);
}
@@ -7818,9 +9051,9 @@ retry:
&& !Silent
&& bDevice)
{
wchar_t msg[1024];
- wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 };
+ wchar_t mountPoint[] = { (wchar_t)(L'A' + driveNo), L':', 0 };
StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_DEVICE_FORCED_READ_ONLY"), mountPoint);
WarningDirect (msg, hwndDlg);
}
@@ -7829,9 +9062,9 @@ retry:
&& !Silent
&& wcsstr (volumePath, L"\\Device\\Harddisk") == volumePath)
{
wchar_t msg[1024];
- wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 };
+ wchar_t mountPoint[] = { (wchar_t) (L'A' + driveNo), L':', 0 };
StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_DEVICE_FORCED_READ_ONLY_WRITE_PROTECTION"), mountPoint);
WarningDirect (msg, hwndDlg);
@@ -7842,8 +9075,19 @@ retry:
RemoveDeviceWriteProtection (hwndDlg, volumePath);
}
}
+ if (mount.VolumeMountedReadOnlyAfterPartialSysEnc
+ && !Silent
+ && bDevice)
+ {
+ wchar_t msg[1024];
+ wchar_t mountPoint[] = { (wchar_t) (L'A' + driveNo), L':', 0 };
+ StringCbPrintfW (msg, sizeof(msg), GetString ("PARTIAL_SYSENC_MOUNT_READONLY"), mountPoint);
+
+ WarningDirect (msg, hwndDlg);
+ }
+
if (mount.wszLabel[0] && !mount.bDriverSetLabel)
{
// try setting the drive label on user-mode using registry
UpdateDriveCustomLabel (driveNo, mount.wszLabel, TRUE);
@@ -7858,8 +9102,10 @@ retry:
return 1;
}
+#endif
+
typedef struct
{
int nDosDriveNo;
BOOL forced;
@@ -7926,14 +9172,11 @@ retry:
forced = TRUE;
goto retry;
}
- if (IsOSAtLeast (WIN_7))
- {
- // Undo SHCNE_DRIVEREMOVED
- wchar_t root[] = { (wchar_t) nDosDriveNo + L'A', L':', L'\\', 0 };
- SHChangeNotify (SHCNE_DRIVEADD, SHCNF_PATH, root, NULL);
- }
+ // Undo SHCNE_DRIVEREMOVED
+ wchar_t root[] = { (wchar_t) (nDosDriveNo + L'A'), L':', L'\\', 0 };
+ SHChangeNotify (SHCNE_DRIVEADD, SHCNF_PATH, root, NULL);
return FALSE;
}
@@ -7956,9 +9199,8 @@ BOOL UnmountVolumeAfterFormatExCall (HWND hwndDlg, int nDosDriveNo)
{
return UnmountVolumeBase (hwndDlg, nDosDriveNo, FALSE, TRUE);
}
-
BOOL IsPasswordCacheEmpty (void)
{
DWORD dw;
return !DeviceIoControl (hDriver, TC_IOCTL_GET_PASSWORD_CACHE_STATUS, 0, 0, 0, 0, &dw, 0);
@@ -7970,15 +9212,25 @@ BOOL IsMountedVolumeID (BYTE volumeID[VOLUME_ID_SIZE])
DWORD dwResult;
int i;
memset (&mlist, 0, sizeof (mlist));
- DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist,
- sizeof (mlist), &mlist, sizeof (mlist), &dwResult,
- NULL);
+ if ( !DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist,
+ sizeof (mlist), &mlist, sizeof (mlist), &dwResult,
+ NULL)
+ || (mlist.ulMountedDrives >= (1 << 26))
+ )
+ {
+ return FALSE;
+ }
- for (i=0 ; i<26; i++)
- if (0 == memcmp (mlist.volumeID[i], volumeID, VOLUME_ID_SIZE))
- return TRUE;
+ if (mlist.ulMountedDrives)
+ {
+ for (i=0 ; i<26; i++)
+ {
+ if ((mlist.ulMountedDrives & (1 << i)) && (0 == memcmp (mlist.volumeID[i], volumeID, VOLUME_ID_SIZE)))
+ return TRUE;
+ }
+ }
return FALSE;
}
@@ -7986,9 +9238,9 @@ BOOL IsMountedVolume (const wchar_t *volname)
{
if ((wcslen (volname) == (3 + 2*VOLUME_ID_SIZE)) && _wcsnicmp (volname, L"ID:", 3) == 0)
{
/* Volume ID specified. Use it for matching mounted volumes. */
- std::vector<byte> arr;
+ std::vector<uint8> arr;
if (HexWideStringToArray (&volname[3], arr) && (arr.size() == VOLUME_ID_SIZE))
{
return IsMountedVolumeID (&arr[0]);
}
@@ -8009,15 +9261,30 @@ BOOL IsMountedVolume (const wchar_t *volname)
if (!resolvedPath.empty())
StringCbCopyW (volume, sizeof (volume), resolvedPath.c_str());
memset (&mlist, 0, sizeof (mlist));
- DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist,
- sizeof (mlist), &mlist, sizeof (mlist), &dwResult,
- NULL);
+ if ( !DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist,
+ sizeof (mlist), &mlist, sizeof (mlist), &dwResult,
+ NULL)
+ || (mlist.ulMountedDrives >= (1 << 26))
+ )
+ {
+ return FALSE;
+ }
- for (i=0 ; i<26; i++)
- if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], volume))
- return TRUE;
+ if (mlist.ulMountedDrives)
+ {
+ for (i=0 ; i<26; i++)
+ {
+ if ((mlist.ulMountedDrives & (1 << i))
+ && IsNullTerminateString (mlist.wszVolume[i], TC_MAX_PATH)
+ && (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], volume))
+ )
+ {
+ return TRUE;
+ }
+ }
+ }
}
return FALSE;
}
@@ -8042,19 +9309,35 @@ int GetMountedVolumeDriveNo (wchar_t *volname)
if (!resolvedPath.empty())
StringCbCopyW (volume, sizeof (volume), resolvedPath.c_str());
memset (&mlist, 0, sizeof (mlist));
- DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist,
- sizeof (mlist), &mlist, sizeof (mlist), &dwResult,
- NULL);
+ if ( !DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist,
+ sizeof (mlist), &mlist, sizeof (mlist), &dwResult,
+ NULL)
+ || (mlist.ulMountedDrives >= (1 << 26))
+ )
+ {
+ return -1;
+ }
- for (i=0 ; i<26; i++)
- if (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], (WCHAR *)volume))
- return i;
+ if (mlist.ulMountedDrives)
+ {
+ for (i=0 ; i<26; i++)
+ {
+ if ((mlist.ulMountedDrives & (1 << i))
+ && IsNullTerminateString (mlist.wszVolume[i], TC_MAX_PATH)
+ && (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], (WCHAR *)volume))
+ )
+ {
+ return i;
+ }
+ }
+ }
return -1;
}
+#endif //!SETUP
BOOL IsAdmin (void)
{
return IsUserAnAdmin ();
@@ -8091,11 +9374,8 @@ BOOL IsUacSupported ()
{
HKEY hkey;
DWORD value = 1, size = sizeof (DWORD);
- if (!IsOSAtLeast (WIN_VISTA))
- return FALSE;
-
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 0, KEY_READ, &hkey) == ERROR_SUCCESS)
{
if (RegQueryValueEx (hkey, L"EnableLUA", 0, 0, (LPBYTE) &value, &size) != ERROR_SUCCESS)
value = 1;
@@ -8152,31 +9432,33 @@ BOOL GetDeviceInfo (const wchar_t *deviceName, DISK_PARTITION_INFO_STRUCT *info)
return DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, info, sizeof (*info), info, sizeof (*info), &dwResult, NULL);
}
-
-BOOL GetDriveGeometry (const wchar_t *deviceName, PDISK_GEOMETRY diskGeometry)
+#ifndef SETUP
+BOOL GetDriveGeometry (const wchar_t *deviceName, PDISK_GEOMETRY_EX diskGeometry)
{
BOOL bResult;
DWORD dwResult;
- DISK_GEOMETRY_STRUCT dg;
+ DISK_GEOMETRY_EX_STRUCT dg;
memset (&dg, 0, sizeof(dg));
StringCbCopyW ((PWSTR) &dg.deviceName, sizeof(dg.deviceName), deviceName);
- bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_GEOMETRY, &dg,
+ bResult = DeviceIoControl (hDriver, VC_IOCTL_GET_DRIVE_GEOMETRY_EX, &dg,
sizeof (dg), &dg, sizeof (dg), &dwResult, NULL);
if (bResult && (dwResult == sizeof (dg)) && dg.diskGeometry.BytesPerSector)
{
- memcpy (diskGeometry, &dg.diskGeometry, sizeof (DISK_GEOMETRY));
+ ZeroMemory (diskGeometry, sizeof (DISK_GEOMETRY_EX));
+ memcpy (&diskGeometry->Geometry, &dg.diskGeometry, sizeof (DISK_GEOMETRY));
+ diskGeometry->DiskSize.QuadPart = dg.DiskSize.QuadPart;
return TRUE;
}
else
return FALSE;
}
-BOOL GetPhysicalDriveGeometry (int driveNumber, PDISK_GEOMETRY diskGeometry)
+BOOL GetPhysicalDriveGeometry (int driveNumber, PDISK_GEOMETRY_EX diskGeometry)
{
HANDLE hDev;
BOOL bResult = FALSE;
TCHAR devicePath[MAX_PATH];
@@ -8186,23 +9468,53 @@ BOOL GetPhysicalDriveGeometry (int driveNumber, PDISK_GEOMETRY diskGeometry)
if ((hDev = CreateFileW (devicePath, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
{
DWORD bytesRead = 0;
- ZeroMemory (diskGeometry, sizeof (DISK_GEOMETRY));
+ ZeroMemory (diskGeometry, sizeof (DISK_GEOMETRY_EX));
+ BYTE dgBuffer[256];
- if ( DeviceIoControl (hDev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, diskGeometry, sizeof (DISK_GEOMETRY), &bytesRead, NULL)
- && (bytesRead == sizeof (DISK_GEOMETRY))
- && diskGeometry->BytesPerSector)
+ if ( DeviceIoControl (hDev, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, dgBuffer, sizeof (dgBuffer), &bytesRead, NULL)
+ && (bytesRead >= (sizeof (DISK_GEOMETRY) + sizeof (LARGE_INTEGER)))
+ && ((PDISK_GEOMETRY_EX) dgBuffer)->Geometry.BytesPerSector)
{
+ memcpy (&diskGeometry->Geometry, &((PDISK_GEOMETRY_EX) dgBuffer)->Geometry, sizeof (DISK_GEOMETRY));
+ diskGeometry->DiskSize.QuadPart = ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart;
bResult = TRUE;
}
+ else
+ {
+ DISK_GEOMETRY geo;
+ if ( DeviceIoControl (hDev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, (LPVOID) &geo, sizeof (geo), &bytesRead, NULL)
+ && (bytesRead >= sizeof (DISK_GEOMETRY))
+ && geo.BytesPerSector)
+ {
+ memcpy (&diskGeometry->Geometry, &geo, sizeof (DISK_GEOMETRY));
+ diskGeometry->DiskSize.QuadPart = geo.Cylinders.QuadPart * geo.SectorsPerTrack * geo.TracksPerCylinder * geo.BytesPerSector;
+ bResult = TRUE;
+
+ if (CurrentOSMajor >= 6)
+ {
+ STORAGE_READ_CAPACITY storage = {0};
+
+ storage.Version = sizeof (STORAGE_READ_CAPACITY);
+ storage.Size = sizeof (STORAGE_READ_CAPACITY);
+ if (DeviceIoControl (hDev, IOCTL_STORAGE_READ_CAPACITY, NULL, 0, (LPVOID) &storage, sizeof (storage), &bytesRead, NULL)
+ && (bytesRead >= sizeof (storage))
+ && (storage.Size == sizeof (STORAGE_READ_CAPACITY))
+ )
+ {
+ diskGeometry->DiskSize.QuadPart = storage.DiskLength.QuadPart;
+ }
+ }
+ }
+ }
CloseHandle (hDev);
}
return bResult;
}
-
+#endif
// Returns drive letter number assigned to device (-1 if none)
int GetDiskDeviceDriveLetter (PWSTR deviceName)
{
@@ -8215,9 +9527,9 @@ int GetDiskDeviceDriveLetter (PWSTR deviceName)
StringCchCopyW (device, MAX_PATH, deviceName);
for (i = 0; i < 26; i++)
{
- WCHAR drive[] = { (WCHAR) i + L'A', L':', 0 };
+ WCHAR drive[] = { (WCHAR) (i + L'A'), L':', 0 };
StringCchCopyW (link, MAX_PATH, L"\\DosDevices\\");
StringCchCatW (link, MAX_PATH, drive);
@@ -8374,273 +9686,65 @@ HANDLE DismountDrive (wchar_t *devName, wchar_t *devicePath)
return (bResult ? hVolume : INVALID_HANDLE_VALUE);
}
-// Returns -1 if the specified string is not found in the buffer. Otherwise, returns the
-// offset of the first occurrence of the string. The string and the buffer may contain zeroes,
-// which do NOT terminate them.
-int64 FindString (const char *buf, const char *str, int64 bufLen, int64 strLen, int64 startOffset)
-{
- if (buf == NULL
- || str == NULL
- || strLen > bufLen
- || bufLen < 1
- || strLen < 1
- || startOffset > bufLen - strLen)
- {
- return -1;
- }
-
- for (int64 i = startOffset; i <= bufLen - strLen; i++)
- {
- if (memcmp (buf + i, str, (size_t) strLen) == 0)
- return i;
- }
-
- return -1;
-}
-
-// Returns TRUE if the file or directory exists (both may be enclosed in quotation marks).
-BOOL FileExists (const wchar_t *filePathPtr)
-{
- wchar_t filePath [TC_MAX_PATH * 2 + 1];
-
- // Strip quotation marks (if any)
- if (filePathPtr [0] == L'"')
- {
- StringCbCopyW (filePath, sizeof(filePath), filePathPtr + 1);
- }
- else
- {
- StringCbCopyW (filePath, sizeof(filePath), filePathPtr);
- }
-
- // Strip quotation marks (if any)
- if (filePath [wcslen (filePath) - 1] == L'"')
- filePath [wcslen (filePath) - 1] = 0;
-
- return (_waccess (filePath, 0) != -1);
-}
-
-// Searches the file from its end for the LAST occurrence of the string str.
-// The string may contain zeroes, which do NOT terminate the string.
-// If the string is found, its offset from the start of the file is returned.
-// If the string isn't found or if any error occurs, -1 is returned.
-__int64 FindStringInFile (const wchar_t *filePath, const char* str, int strLen)
-{
- int bufSize = 64 * BYTES_PER_KB;
- char *buffer = (char *) err_malloc (bufSize);
- HANDLE src = NULL;
- DWORD bytesRead;
- BOOL readRetVal;
- __int64 filePos = GetFileSize64 (filePath);
- int bufPos = 0;
- LARGE_INTEGER seekOffset, seekOffsetNew;
- BOOL bExit = FALSE;
- int filePosStep;
- __int64 retVal = -1;
-
- if (filePos <= 0
- || buffer == NULL
- || strLen > bufSize
- || strLen < 1)
- {
- if (buffer)
- free (buffer);
- return -1;
- }
-
- src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
-
- if (src == INVALID_HANDLE_VALUE)
- {
- free (buffer);
- return -1;
- }
-
- filePosStep = bufSize - strLen + 1;
-
- do
- {
- filePos -= filePosStep;
-
- if (filePos < 0)
- {
- filePos = 0;
- bExit = TRUE;
- }
-
- seekOffset.QuadPart = filePos;
-
- if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0)
- goto fsif_end;
-
- if ((readRetVal = ReadFile (src, buffer, bufSize, &bytesRead, NULL)) == 0
- || bytesRead == 0)
- goto fsif_end;
-
- bufPos = bytesRead - strLen;
-
- while (bufPos > 0)
- {
- if (memcmp (buffer + bufPos, str, strLen) == 0)
- {
- // String found
- retVal = filePos + bufPos;
- goto fsif_end;
- }
- bufPos--;
- }
-
- } while (!bExit);
-
-fsif_end:
- CloseHandle (src);
- free (buffer);
-
- return retVal;
-}
-
-// System CopyFile() copies source file attributes (like FILE_ATTRIBUTE_ENCRYPTED)
-// so we need to use our own copy function
-BOOL TCCopyFileBase (HANDLE src, HANDLE dst)
-{
- __int8 *buffer;
- FILETIME fileTime;
- DWORD bytesRead, bytesWritten;
- BOOL res;
-
- buffer = (char *) malloc (64 * 1024);
- if (!buffer)
- {
- CloseHandle (src);
- CloseHandle (dst);
- return FALSE;
- }
-
- while (res = ReadFile (src, buffer, 64 * 1024, &bytesRead, NULL))
- {
- if (bytesRead == 0)
- {
- res = 1;
- break;
- }
-
- if (!WriteFile (dst, buffer, bytesRead, &bytesWritten, NULL)
- || bytesRead != bytesWritten)
- {
- res = 0;
- break;
- }
- }
-
- if (GetFileTime (src, NULL, NULL, &fileTime))
- SetFileTime (dst, NULL, NULL, &fileTime);
-
- CloseHandle (src);
- CloseHandle (dst);
-
- free (buffer);
- return res != 0;
-}
-
-BOOL TCCopyFile (wchar_t *sourceFileName, wchar_t *destinationFile)
+BOOL DecompressZipToDir (const unsigned char *inputBuffer, DWORD inputLength, const wchar_t *destinationDir, ProgressFn progressFnPtr, HWND hwndDlg)
{
- HANDLE src, dst;
-
- src = CreateFileW (sourceFileName,
- GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
-
- if (src == INVALID_HANDLE_VALUE)
+ BOOL res = TRUE;
+ zip_error_t zerr;
+ zip_int64_t numFiles, i;
+ zip_stat_t sb;
+ zip_source_t* zsrc = zip_source_buffer_create (inputBuffer, inputLength, 0, &zerr);
+ if (!zsrc)
return FALSE;
-
- dst = CreateFileW (destinationFile,
- GENERIC_WRITE,
- 0, NULL, CREATE_ALWAYS, 0, NULL);
-
- if (dst == INVALID_HANDLE_VALUE)
+ zip_t* z = zip_open_from_source (zsrc, ZIP_CHECKCONS | ZIP_RDONLY, &zerr);
+ if (!z)
{
- CloseHandle (src);
+ zip_source_free (zsrc);
return FALSE;
}
- return TCCopyFileBase (src, dst);
-}
-
-// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file
-// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE).
-BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed)
-{
- HANDLE dst;
- DWORD bytesWritten;
- BOOL res = TRUE;
- DWORD dwLastError = 0;
+ finally_do_arg (zip_t*, z, { zip_close (finally_arg); });
- dst = CreateFile (destinationFile,
- GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
+ numFiles = zip_get_num_entries (z, 0);
+ if (numFiles <= 0)
+ return FALSE;
- dwLastError = GetLastError();
- if (!bAppend && bRenameIfFailed && (dst == INVALID_HANDLE_VALUE) && (GetLastError () == ERROR_SHARING_VIOLATION))
+ for (i = 0; (i < numFiles) && res; i++)
{
- wchar_t renamedPath[TC_MAX_PATH + 1];
- StringCbCopyW (renamedPath, sizeof(renamedPath), destinationFile);
- StringCbCatW (renamedPath, sizeof(renamedPath), VC_FILENAME_RENAMED_SUFFIX);
-
- /* rename the locked file in order to be able to create a new one */
- if (MoveFileEx (destinationFile, renamedPath, MOVEFILE_REPLACE_EXISTING))
+ ZeroMemory (&sb, sizeof (sb));
+ if ((0 == zip_stat_index (z, i, 0, &sb)) && (sb.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) && (sb.size > 0))
{
- dst = CreateFile (destinationFile,
- GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
- dwLastError = GetLastError();
- if (dst == INVALID_HANDLE_VALUE)
- {
- /* restore the original file name */
- MoveFileEx (renamedPath, destinationFile, MOVEFILE_REPLACE_EXISTING);
- }
- else
+ std::wstring wname = Utf8StringToWide (sb.name);
+ CorrectFileName (wname);
+
+ std::wstring filePath = destinationDir + wname;
+ size_t pos = filePath.find_last_of (L"/\\");
+ // create the parent directory if it doesn't exist
+ if (pos != std::wstring::npos)
{
- /* delete the renamed file when the machine reboots */
- MoveFileEx (renamedPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+ SHCreateDirectoryEx (NULL, filePath.substr (0, pos).c_str(), NULL);
}
- }
- }
- if (dst == INVALID_HANDLE_VALUE)
- {
- SetLastError (dwLastError);
- handleWin32Error (MainDlg, SRC_POS);
- return FALSE;
- }
+ zip_file_t *f = zip_fopen_index (z, i, 0);
+ if (f)
+ {
+ ByteArray buffer((ByteArray::size_type) sb.size);
- if (bAppend)
- SetFilePointer (dst, 0, NULL, FILE_END);
+ zip_fread (f, buffer.data(), sb.size);
+ zip_fclose (f);
- if (!WriteFile (dst, inputBuffer, inputLength, &bytesWritten, NULL)
- || inputLength != bytesWritten)
- {
- res = FALSE;
- }
+ if (progressFnPtr)
+ progressFnPtr (hwndDlg, filePath.c_str());
- if (!res)
- {
- // If CREATE_ALWAYS is used, ERROR_ALREADY_EXISTS is returned after successful overwrite
- // of an existing file (it's not an error)
- if (! (GetLastError() == ERROR_ALREADY_EXISTS && !bAppend) )
- handleWin32Error (MainDlg, SRC_POS);
+ res = SaveBufferToFile ((char *) buffer.data(), filePath.c_str(), (DWORD) buffer.size(), FALSE, TRUE);
+ }
+ }
}
- CloseHandle (dst);
-
- if (!res && !bAppend)
- _wremove (destinationFile);
-
return res;
}
-
// Proper flush for Windows systems. Returns TRUE if successful.
BOOL TCFlushFile (FILE *f)
{
HANDLE hf = (HANDLE) _get_osfhandle (_fileno (f));
@@ -8719,10 +9823,13 @@ BOOL PrintHardCopyTextUTF16 (wchar_t *text, wchar_t *title, size_t textByteLen)
BOOL IsNonInstallMode ()
{
- HKEY hkey;
+ HKEY hkey, hkeybis;
DWORD dw;
+ WCHAR szBuffer[512];
+ DWORD dwBufferSize = sizeof(szBuffer);
+ std::wstring msiProductGUID;
if (bPortableModeConfirmed)
return TRUE;
@@ -8778,8 +9885,31 @@ BOOL IsNonInstallMode ()
else
CloseHandle (hDriverTmp);
}
+ // The following test checks whether the MSI is installed, which means we're not in portable mode.
+ // The ProductGUID is read from registry.
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\VeraCrypt_MSI", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hkey) == ERROR_SUCCESS ||
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\VeraCrypt_MSI", 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)
+ {
+ if (ERROR_SUCCESS == RegQueryValueExW(hkey, L"ProductGuid", 0, NULL, (LPBYTE)szBuffer, &dwBufferSize))
+ {
+ msiProductGUID = szBuffer;
+
+ std::wstring regKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
+ regKey += msiProductGUID;
+
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, regKey.c_str(), 0, KEY_READ | KEY_WOW64_32KEY, &hkeybis) == ERROR_SUCCESS ||
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE, regKey.c_str(), 0, KEY_READ, &hkeybis) == ERROR_SUCCESS)
+ {
+ RegCloseKey(hkeybis);
+ return FALSE;
+ }
+ }
+
+ RegCloseKey(hkey);
+ }
+
// The following test may be unreliable in some cases (e.g. after the user selects restore "Last Known Good
// Configuration" from the Windows boot menu).
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt", 0, KEY_READ | KEY_WOW64_32KEY, &hkey) == ERROR_SUCCESS)
{
@@ -8910,14 +10040,14 @@ void CleanLastVisitedMRU (void)
GetModuleFileNameW (NULL, exeFilename, sizeof (exeFilename) / sizeof(exeFilename[0]));
strToMatch = wcsrchr (exeFilename, L'\\') + 1;
- StringCbPrintfW (regPath, sizeof(regPath), L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisited%sMRU", IsOSAtLeast (WIN_VISTA) ? L"Pidl" : L"");
+ StringCbCopyW (regPath, sizeof(regPath), L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU");
- for (id = (IsOSAtLeast (WIN_VISTA) ? 0 : L'a'); id <= (IsOSAtLeast (WIN_VISTA) ? 1000 : L'z'); id++)
+ for (id = 0; id <= 1000; id++)
{
*strTmp = 0;
- StringCbPrintfW (key, sizeof(key), (IsOSAtLeast (WIN_VISTA) ? L"%d" : L"%c"), id);
+ StringCbPrintfW (key, sizeof(key), L"%d", id);
if ((len = ReadRegistryBytes (regPath, key, (char *) strTmp, sizeof (strTmp))) > 0)
{
if (_wcsicmp (strTmp, strToMatch) == 0)
@@ -8931,50 +10061,28 @@ void CleanLastVisitedMRU (void)
DeleteRegistryValue (regPath, key);
// Remove ID from MRUList
- if (IsOSAtLeast (WIN_VISTA))
- {
- int *p = (int *)buf;
- int *pout = (int *)bufout;
- int l;
+ int *p = (int *)buf;
+ int *pout = (int *)bufout;
+ int l;
- l = len = ReadRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", buf, sizeof (buf));
- while (l > 0)
- {
- l -= sizeof (int);
-
- if (*p == id)
- {
- p++;
- len -= sizeof (int);
- continue;
- }
- *pout++ = *p++;
- }
-
- WriteRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", bufout, len);
- }
- else
+ l = len = ReadRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", buf, sizeof (buf));
+ while (l > 0)
{
- wchar_t *p = (wchar_t*) buf;
- wchar_t *pout = (wchar_t*) bufout;
+ l -= sizeof (int);
- ReadRegistryString (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", L"MRUList", L"", (wchar_t*) buf, sizeof (buf));
- while (*p)
+ if (*p == id)
{
- if (*p == id)
- {
- p++;
- continue;
- }
- *pout++ = *p++;
+ p++;
+ len -= sizeof (int);
+ continue;
}
- *pout++ = 0;
-
- WriteRegistryString (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", L"MRUList", (wchar_t*) bufout);
+ *pout++ = *p++;
}
+ WriteRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", bufout, len);
+
break;
}
}
}
@@ -9024,13 +10132,21 @@ LRESULT ListSubItemSet (HWND list, int index, int subIndex, const wchar_t *strin
BOOL GetMountList (MOUNT_LIST_STRUCT *list)
{
DWORD dwResult;
+ MOUNT_LIST_STRUCT localList = {0};
- memset (list, 0, sizeof (*list));
- return DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, list,
- sizeof (*list), list, sizeof (*list), &dwResult,
- NULL);
+ if ( list && DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &localList,
+ sizeof (localList), &localList, sizeof (localList), &dwResult,
+ NULL)
+ && (localList.ulMountedDrives < (1 << 26))
+ )
+ {
+ memcpy (list, &localList, sizeof (MOUNT_LIST_STRUCT));
+ return TRUE;
+ }
+ else
+ return FALSE;
}
int GetDriverRefCount ()
@@ -9047,193 +10163,8 @@ int GetDriverRefCount ()
else
return -1;
}
-// Loads a 32-bit integer from the file at the specified file offset. The saved value is assumed to have been
-// processed by mputLong(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE).
-BOOL LoadInt32 (const wchar_t *filePath, unsigned __int32 *result, __int64 fileOffset)
-{
- DWORD bufSize = sizeof(__int32);
- unsigned char *buffer = (unsigned char *) malloc (bufSize);
- unsigned char *bufferPtr = buffer;
- HANDLE src = NULL;
- DWORD bytesRead;
- LARGE_INTEGER seekOffset, seekOffsetNew;
- BOOL retVal = FALSE;
-
- if (buffer == NULL)
- return -1;
-
- src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
-
- if (src == INVALID_HANDLE_VALUE)
- {
- free (buffer);
- return FALSE;
- }
-
- seekOffset.QuadPart = fileOffset;
-
- if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0)
- goto fsif_end;
-
- if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0
- || bytesRead != bufSize)
- goto fsif_end;
-
-
- retVal = TRUE;
-
- *result = mgetLong(bufferPtr);
-
-fsif_end:
- CloseHandle (src);
- free (buffer);
-
- return retVal;
-}
-
-// Loads a 16-bit integer from the file at the specified file offset. The saved value is assumed to have been
-// processed by mputWord(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE).
-BOOL LoadInt16 (const wchar_t *filePath, int *result, __int64 fileOffset)
-{
- DWORD bufSize = sizeof(__int16);
- unsigned char *buffer = (unsigned char *) malloc (bufSize);
- unsigned char *bufferPtr = buffer;
- HANDLE src = NULL;
- DWORD bytesRead;
- LARGE_INTEGER seekOffset, seekOffsetNew;
- BOOL retVal = FALSE;
-
- if (buffer == NULL)
- return -1;
-
- src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
-
- if (src == INVALID_HANDLE_VALUE)
- {
- free (buffer);
- return FALSE;
- }
-
- seekOffset.QuadPart = fileOffset;
-
- if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0)
- goto fsif_end;
-
- if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0
- || bytesRead != bufSize)
- goto fsif_end;
-
-
- retVal = TRUE;
-
- *result = mgetWord(bufferPtr);
-
-fsif_end:
- CloseHandle (src);
- free (buffer);
-
- return retVal;
-}
-
-// Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated.
-char *LoadFile (const wchar_t *fileName, DWORD *size)
-{
- char *buf;
- DWORD fileSize = INVALID_FILE_SIZE;
- HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
- if (h == INVALID_HANDLE_VALUE)
- return NULL;
-
- if ((fileSize = GetFileSize (h, NULL)) == INVALID_FILE_SIZE)
- {
- CloseHandle (h);
- return NULL;
- }
-
- *size = fileSize;
- buf = (char *) calloc (*size + 1, 1);
-
- if (buf == NULL)
- {
- CloseHandle (h);
- return NULL;
- }
-
- if (!ReadFile (h, buf, *size, size, NULL))
- {
- free (buf);
- buf = NULL;
- }
-
- CloseHandle (h);
- return buf;
-}
-
-
-// Returns NULL if there's any error.
-char *LoadFileBlock (const wchar_t *fileName, __int64 fileOffset, DWORD count)
-{
- char *buf;
- DWORD bytesRead = 0;
- LARGE_INTEGER seekOffset, seekOffsetNew;
- BOOL bStatus;
-
- HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
- if (h == INVALID_HANDLE_VALUE)
- return NULL;
-
- seekOffset.QuadPart = fileOffset;
-
- if (SetFilePointerEx (h, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0)
- {
- CloseHandle (h);
- return NULL;
- }
-
- buf = (char *) calloc (count, 1);
-
- if (buf == NULL)
- {
- CloseHandle (h);
- return NULL;
- }
-
- bStatus = ReadFile (h, buf, count, &bytesRead, NULL);
-
- CloseHandle (h);
-
- if (!bStatus || (bytesRead != count))
- {
- free (buf);
- return NULL;
- }
-
- return buf;
-}
-
-
-// Returns -1 if there is an error, or the size of the file.
-__int64 GetFileSize64 (const wchar_t *path)
-{
- HANDLE h = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
- LARGE_INTEGER size;
- __int64 retSize = -1;
-
- if (h)
- {
- if (GetFileSizeEx (h, &size))
- {
- retSize = size.QuadPart;
- }
-
- CloseHandle (h);
- }
-
- return retSize;
-}
-
wchar_t *GetModPath (wchar_t *path, int maxSize)
{
GetModuleFileName (NULL, path, maxSize);
@@ -9289,9 +10220,9 @@ wchar_t *GetProgramConfigPath (wchar_t *fileName)
std::wstring GetServiceConfigPath (const wchar_t *fileName, bool useLegacy)
{
wchar_t sysPath[TC_MAX_PATH];
- if (Is64BitOs() && useLegacy)
+ if (useLegacy)
{
typedef UINT (WINAPI *GetSystemWow64Directory_t) (LPWSTR lpBuffer, UINT uSize);
GetSystemWow64Directory_t getSystemWow64Directory = (GetSystemWow64Directory_t) GetProcAddress (GetModuleHandle (L"kernel32"), "GetSystemWow64DirectoryW");
@@ -9317,14 +10248,8 @@ wchar_t GetSystemDriveLetter (void)
void TaskBarIconDisplayBalloonTooltip (HWND hwnd, wchar_t *headline, wchar_t *text, BOOL warning)
{
- if (nCurrentOS == WIN_2000)
- {
- MessageBoxW (MainDlg, text, headline, warning ? MB_ICONWARNING : MB_ICONINFORMATION);
- return;
- }
-
NOTIFYICONDATAW tnid;
ZeroMemory (&tnid, sizeof (tnid));
@@ -9336,9 +10261,9 @@ void TaskBarIconDisplayBalloonTooltip (HWND hwnd, wchar_t *headline, wchar_t *te
//Shell_NotifyIconW (NIM_SETVERSION, &tnid);
tnid.uFlags = NIF_INFO;
tnid.dwInfoFlags = (warning ? NIIF_WARNING : NIIF_INFO);
- tnid.uTimeout = (IsOSAtLeast (WIN_VISTA) ? 1000 : 5000); // in ms
+ tnid.uTimeout = 1000; // in ms
StringCbCopyW (tnid.szInfoTitle, sizeof(tnid.szInfoTitle), headline);
StringCbCopyW (tnid.szInfo, sizeof(tnid.szInfo),text);
@@ -9440,15 +10365,8 @@ int WarningDirect (const wchar_t *warnMsg, HWND hwnd)
if (Silent) return 0;
return MessageBoxW (hwnd, warnMsg, lpszTitle, MB_ICONWARNING);
}
-
-int Error (char *stringId, HWND hwnd)
-{
- if (Silent) return 0;
- return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR);
-}
-
int ErrorRetryCancel (char *stringId, HWND hwnd)
{
if (Silent) return 0;
return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_RETRYCANCEL);
@@ -9796,33 +10714,46 @@ void ConfigReadCompareString (char *configKey, char *defaultValue, char *str, in
}
void OpenPageHelp (HWND hwndDlg, int nPage)
{
- int r = (int)ShellExecuteW (NULL, L"open", szHelpFile, NULL, NULL, SW_SHOWNORMAL);
-
- if (r == ERROR_FILE_NOT_FOUND)
+ if (IsAdmin ())
+ {
+ if (FileExists (szHelpFile))
+ SafeOpenURL (szHelpFile);
+ else if (FileExists (szHelpFile2))
+ SafeOpenURL (szHelpFile2);
+ else
+ Applink ("help");
+ }
+ else
{
- // Try the secondary help file
- r = (int)ShellExecuteW (NULL, L"open", szHelpFile2, NULL, NULL, SW_SHOWNORMAL);
+ INT_PTR r = (INT_PTR)ShellExecuteW (NULL, L"open", szHelpFile, NULL, NULL, SW_SHOWNORMAL);
if (r == ERROR_FILE_NOT_FOUND)
{
- OpenOnlineHelp ();
- return;
+ // Try the secondary help file
+ r = (INT_PTR)ShellExecuteW (NULL, L"open", szHelpFile2, NULL, NULL, SW_SHOWNORMAL);
+
+ if (r == ERROR_FILE_NOT_FOUND)
+ {
+ // Open local HTML help. It will fallback to online help if not found.
+ Applink ("help");
+ return;
+ }
}
- }
- if (r == SE_ERR_NOASSOC)
- {
- if (AskYesNo ("HELP_READER_ERROR", MainDlg) == IDYES)
- OpenOnlineHelp ();
+ if (r == SE_ERR_NOASSOC)
+ {
+ if (AskYesNo ("HELP_READER_ERROR", MainDlg) == IDYES)
+ OpenOnlineHelp ();
+ }
}
}
void OpenOnlineHelp ()
{
- Applink ("help", TRUE, "");
+ Applink ("onlinehelp");
}
#ifndef SETUP
@@ -9912,84 +10843,127 @@ void DebugMsgBox (char *format, ...)
MessageBoxA (MainDlg, buf, "VeraCrypt debug", 0);
}
-
-BOOL IsOSAtLeast (OSVersionEnum reqMinOS)
-{
- return IsOSVersionAtLeast (reqMinOS, 0);
-}
-
-
-// Returns TRUE if the operating system is at least reqMinOS and service pack at least reqMinServicePack.
-// Example 1: IsOSVersionAtLeast (WIN_VISTA, 1) called under Windows 2008, returns TRUE.
-// Example 2: IsOSVersionAtLeast (WIN_XP, 3) called under Windows XP SP1, returns FALSE.
-// Example 3: IsOSVersionAtLeast (WIN_XP, 3) called under Windows Vista SP1, returns TRUE.
-BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack)
+BOOL IsSupportedOS ()
{
- /* When updating this function, update IsOSAtLeast() in Ntdriver.c too. */
-
- if (CurrentOSMajor <= 0)
- TC_THROW_FATAL_EXCEPTION;
-
- int major = 0, minor = 0;
-
- switch (reqMinOS)
+ BOOL bRet = FALSE;
+#ifdef SETUP
+ static const wchar_t* szWin7KBs[] = {L"KB3033929", L"KB4474419"};
+ static const wchar_t* szWinVistaKBs[] = {L"KB4039648", L"KB4474419"};
+ if (IsOSAtLeast(WIN_8))
+ bRet = TRUE;
+ else if (IsOSAtLeast(WIN_7))
{
- case WIN_2000: major = 5; minor = 0; break;
- case WIN_XP: major = 5; minor = 1; break;
- case WIN_SERVER_2003: major = 5; minor = 2; break;
- case WIN_VISTA: major = 6; minor = 0; break;
- case WIN_7: major = 6; minor = 1; break;
- case WIN_8: major = 6; minor = 2; break;
- case WIN_8_1: major = 6; minor = 3; break;
- case WIN_10: major = 10; minor = 0; break;
-
- default:
- TC_THROW_FATAL_EXCEPTION;
- break;
+ if (OneOfKBsInstalled(szWin7KBs, 2))
+ bRet = TRUE;
+ else
+ MessageBoxW (NULL, L"SHA-2 support missing from Windows.\n\nPlease Install KB3033929 or KB4474419", lpszTitle, MB_ICONWARNING);
}
+#else
+ if (IsOSAtLeast(WIN_7))
+ bRet = TRUE;
+#endif
- return ((CurrentOSMajor << 16 | CurrentOSMinor << 8 | CurrentOSServicePack)
- >= (major << 16 | minor << 8 | reqMinServicePack));
+ return bRet;
}
-
-BOOL Is64BitOs ()
+BOOL Is64BitOs()
{
#ifdef _WIN64
return TRUE;
#else
- static BOOL isWow64 = FALSE;
+ static BOOL isWow64 = FALSE;
static BOOL valid = FALSE;
- typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS ) (HANDLE hProcess,PBOOL Wow64Process);
+ typedef BOOL(__stdcall* LPFN_ISWOW64PROCESS) (HANDLE hProcess, PBOOL Wow64Process);
+ typedef BOOL(__stdcall* LPFN_ISWOW64PROCESS2)(
+ HANDLE hProcess,
+ USHORT* pProcessMachine,
+ USHORT* pNativeMachine
+ );
LPFN_ISWOW64PROCESS fnIsWow64Process;
+ LPFN_ISWOW64PROCESS2 fnIsWow64Process2;
if (valid)
return isWow64;
- fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle(L"kernel32"), "IsWow64Process");
+ fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process");
+ fnIsWow64Process2 = (LPFN_ISWOW64PROCESS2)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process2");
- if (fnIsWow64Process != NULL)
- if (!fnIsWow64Process (GetCurrentProcess(), &isWow64))
+ if (fnIsWow64Process2)
+ {
+ USHORT processMachine, nativeMachine;
+ if (!fnIsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine))
isWow64 = FALSE;
-
+ else
+ {
+ if (IMAGE_FILE_MACHINE_ARM64 == nativeMachine || IMAGE_FILE_MACHINE_AMD64 == nativeMachine || IMAGE_FILE_MACHINE_IA64 == nativeMachine || IMAGE_FILE_MACHINE_ALPHA64 == nativeMachine)
+ isWow64 = TRUE;
+ }
+}
+ else if (fnIsWow64Process != NULL)
+ {
+ if (!fnIsWow64Process(GetCurrentProcess(), &isWow64))
+ isWow64 = FALSE;
+ }
valid = TRUE;
- return isWow64;
+ return isWow64;
#endif
}
+BOOL IsARM()
+{
+#if defined(_M_ARM) || defined(_M_ARM64)
+ return TRUE;
+#else
+ static BOOL isARM = FALSE;
+ static BOOL valid = FALSE;
+ typedef BOOL(__stdcall* LPFN_ISWOW64PROCESS2)(
+ HANDLE hProcess,
+ USHORT* pProcessMachine,
+ USHORT* pNativeMachine
+ );
+ LPFN_ISWOW64PROCESS2 fnIsWow64Process2;
+
+ if (valid)
+ return isARM;
+
+ fnIsWow64Process2 = (LPFN_ISWOW64PROCESS2)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process2");
+ if (fnIsWow64Process2)
+ {
+ USHORT processMachine, nativeMachine;
+ if (fnIsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine))
+ {
+ if (IMAGE_FILE_MACHINE_ARM64 == nativeMachine || IMAGE_FILE_MACHINE_ARM == nativeMachine)
+ isARM = TRUE;
+ else
+ isARM = FALSE;
+ valid = TRUE;
+ }
+ }
+
+ if (!valid)
+ {
+ SYSTEM_INFO systemInfo;
+ GetNativeSystemInfo(&systemInfo);
+ if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM || systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64)
+ isARM = TRUE;
+ else
+ isARM = FALSE;
+ }
+ valid = TRUE;
+ return isARM;
+
+#endif
+}
BOOL IsServerOS ()
{
- OSVERSIONINFOEXW osVer;
- osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
- GetVersionExW ((LPOSVERSIONINFOW) &osVer);
-
- return (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER);
+ return IsWindowsServer()? TRUE : FALSE;
}
+
// Returns TRUE, if the currently running operating system is installed in a hidden volume. If it's not, or if
// there's an error, returns FALSE.
BOOL IsHiddenOSRunning (void)
{
@@ -10062,241 +11036,332 @@ BOOL RestartComputer (BOOL bShutdown)
std::wstring GetWindowsEdition ()
{
wstring osname = L"win";
- OSVERSIONINFOEXW osVer;
+ OSVERSIONINFOEXW osVer = { 0 };
osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
- GetVersionExW ((LPOSVERSIONINFOW) &osVer);
+ if (GetWindowsVersion((LPOSVERSIONINFOW)&osVer))
+ {
- BOOL home = (osVer.wSuiteMask & VER_SUITE_PERSONAL);
- BOOL server = (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER);
+ BOOL home = (osVer.wSuiteMask & VER_SUITE_PERSONAL);
+ BOOL server = (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER);
- HKEY hkey;
- wchar_t productName[300] = {0};
- DWORD productNameSize = sizeof (productName);
- if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)
- {
- if (RegQueryValueEx (hkey, L"ProductName", 0, 0, (LPBYTE) &productName, &productNameSize) != ERROR_SUCCESS || productNameSize < 1)
- productName[0] = 0;
+ HKEY hkey;
+ wchar_t productName[300] = { 0 };
+ DWORD productNameSize = sizeof(productName);
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)
+ {
+ if (RegQueryValueEx(hkey, L"ProductName", 0, 0, (LPBYTE)&productName, &productNameSize) != ERROR_SUCCESS || productNameSize < 1)
+ productName[0] = 0;
- RegCloseKey (hkey);
- }
+ RegCloseKey(hkey);
+ }
- switch (nCurrentOS)
- {
- case WIN_2000:
- osname += L"2000";
- break;
+ switch (nCurrentOS)
+ {
+ case WIN_2000:
+ osname += L"2000";
+ break;
- case WIN_XP:
- case WIN_XP64:
- osname += L"xp";
- osname += home ? L"-home" : L"-pro";
- break;
+ case WIN_XP:
+ case WIN_XP64:
+ osname += L"xp";
+ osname += home ? L"-home" : L"-pro";
+ break;
- case WIN_SERVER_2003:
- osname += L"2003";
- break;
+ case WIN_SERVER_2003:
+ osname += L"2003";
+ break;
- case WIN_VISTA:
- osname += L"vista";
- break;
+ case WIN_VISTA:
+ osname += L"vista";
+ break;
- case WIN_SERVER_2008:
- osname += L"2008";
- break;
+ case WIN_SERVER_2008:
+ osname += L"2008";
+ break;
- case WIN_7:
- osname += L"7";
- break;
+ case WIN_7:
+ osname += L"7";
+ break;
- case WIN_SERVER_2008_R2:
- osname += L"2008r2";
- break;
+ case WIN_SERVER_2008_R2:
+ osname += L"2008r2";
+ break;
- default:
- wstringstream s;
- s << CurrentOSMajor << L"." << CurrentOSMinor;
- osname += s.str();
- break;
- }
+ default:
+ wstringstream s;
+ s << CurrentOSMajor << L"." << CurrentOSMinor;
+ osname += s.str();
+ break;
+ }
- if (server)
- osname += L"-server";
+ if (server)
+ osname += L"-server";
- if (IsOSAtLeast (WIN_VISTA))
- {
- if (home)
- osname += L"-home";
- else if (wcsstr (productName, L"Standard") != 0)
- osname += L"-standard";
- else if (wcsstr (productName, L"Professional") != 0)
- osname += L"-pro";
- else if (wcsstr (productName, L"Business") != 0)
- osname += L"-business";
- else if (wcsstr (productName, L"Enterprise") != 0)
- osname += L"-enterprise";
- else if (wcsstr (productName, L"Datacenter") != 0)
- osname += L"-datacenter";
- else if (wcsstr (productName, L"Ultimate") != 0)
- osname += L"-ultimate";
- }
+ if (IsOSAtLeast(WIN_VISTA))
+ {
+ if (home)
+ osname += L"-home";
+ else if (wcsstr(productName, L"Standard") != 0)
+ osname += L"-standard";
+ else if (wcsstr(productName, L"Professional") != 0)
+ osname += L"-pro";
+ else if (wcsstr(productName, L"Business") != 0)
+ osname += L"-business";
+ else if (wcsstr(productName, L"Enterprise") != 0)
+ osname += L"-enterprise";
+ else if (wcsstr(productName, L"Datacenter") != 0)
+ osname += L"-datacenter";
+ else if (wcsstr(productName, L"Ultimate") != 0)
+ osname += L"-ultimate";
+ }
- if (GetSystemMetrics (SM_STARTER))
- osname += L"-starter";
- else if (wcsstr (productName, L"Basic") != 0)
- osname += L"-basic";
+ if (GetSystemMetrics(SM_STARTER))
+ osname += L"-starter";
+ else if (wcsstr(productName, L"Basic") != 0)
+ osname += L"-basic";
- if (Is64BitOs())
- osname += L"-x64";
+ osname += IsARM() ? L"-arm64" : L"-x64";
- if (CurrentOSServicePack > 0)
+ if (CurrentOSServicePack > 0)
+ {
+ wstringstream s;
+ s << L"-sp" << CurrentOSServicePack;
+ osname += s.str();
+ }
+
+ return osname;
+ }
+ else
{
- wstringstream s;
- s << L"-sp" << CurrentOSServicePack;
- osname += s.str();
+ return L"";
}
-
- return osname;
}
+#ifdef SETUP
+extern wchar_t InstallationPath[TC_MAX_PATH];
+#endif
-void Applink (char *dest, BOOL bSendOS, char *extraOutput)
+void Applink (const char *dest)
{
- char url [MAX_URL_LENGTH];
+ wchar_t url [MAX_URL_LENGTH] = {0};
+ wchar_t page[TC_MAX_PATH] = {0};
+ wchar_t installDir[TC_MAX_PATH] = {0};
+ BOOL buildUrl = TRUE;
+ INT_PTR r;
ArrowWaitCursor ();
+
+#ifdef SETUP
+ StringCbCopyW (installDir, sizeof (installDir), InstallationPath);
+#else
+ GetModPath (installDir, TC_MAX_PATH);
+#endif
- // sprintf_s (url, sizeof (url), TC_APPLINK "%s%s&dest=%s", bSendOS ? ("&os=" + GetWindowsEdition()).c_str() : "", extraOutput, dest);
if (strcmp(dest, "donate") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Donation#VeraCryptDonation");
+ StringCbCopyW (page, sizeof (page),L"Donation.html");
}
else if (strcmp(dest, "main") == 0)
{
- StringCbCopyA (url, sizeof (url),TC_HOMEPAGE);
+ StringCbCopyW (url, sizeof (url), TC_HOMEPAGE);
+ buildUrl = FALSE;
}
else if (strcmp(dest,"localizations") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Language%20Packs");
+ StringCbCopyW (page, sizeof (page),L"Language%20Packs.html");
}
else if (strcmp(dest, "beginnerstutorial") == 0 || strcmp(dest,"tutorial") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Beginner%27s%20Tutorial");
+ StringCbCopyW (page, sizeof (page),L"Beginner%27s%20Tutorial.html");
}
else if (strcmp(dest, "releasenotes") == 0 || strcmp(dest, "history") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Release%20Notes");
+ StringCbCopyW (page, sizeof (page),L"Release%20Notes.html");
}
else if (strcmp(dest, "hwacceleration") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Hardware%20Acceleration");
+ StringCbCopyW (page, sizeof (page),L"Hardware%20Acceleration.html");
}
else if (strcmp(dest, "parallelization") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Parallelization");
+ StringCbCopyW (page, sizeof (page),L"Parallelization.html");
}
else if (strcmp(dest, "help") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/documentation");
+ StringCbCopyW (page, sizeof (page),L"Documentation.html");
+ }
+ else if (strcmp(dest, "onlinehelp") == 0)
+ {
+ StringCbCopyW (url, sizeof (url),L"https://www.veracrypt.fr/en/Documentation.html");
+ buildUrl = FALSE;
}
else if (strcmp(dest, "keyfiles") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Keyfiles");
+ StringCbCopyW (page, sizeof (page),L"Keyfiles.html");
+ }
+ else if (strcmp(dest, "keyfilesextensions") == 0)
+ {
+ StringCbCopyW (page, sizeof (page),L"Avoid%20Third-Party%20File%20Extensions.html");
}
else if (strcmp(dest, "introcontainer") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Creating%20New%20Volumes");
+ StringCbCopyW (page, sizeof (page),L"Creating%20New%20Volumes.html");
}
else if (strcmp(dest, "introsysenc") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=System%20Encryption");
+ StringCbCopyW (page, sizeof (page),L"System%20Encryption.html");
}
else if (strcmp(dest, "hiddensysenc") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=VeraCrypt%20Hidden%20Operating%20System");
+ StringCbCopyW (page, sizeof (page),L"VeraCrypt%20Hidden%20Operating%20System.html");
}
else if (strcmp(dest, "sysencprogressinfo") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=System%20Encryption");
+ StringCbCopyW (page, sizeof (page),L"System%20Encryption.html");
}
else if (strcmp(dest, "hiddenvolume") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Hidden%20Volume");
+ StringCbCopyW (page, sizeof (page),L"Hidden%20Volume.html");
}
else if (strcmp(dest, "aes") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=AES");
+ StringCbCopyW (page, sizeof (page),L"AES.html");
}
else if (strcmp(dest, "serpent") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Serpent");
+ StringCbCopyW (page, sizeof (page),L"Serpent.html");
}
else if (strcmp(dest, "twofish") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Twofish");
- }
- else if (strcmp(dest, "gost89") == 0)
- {
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=GOST89");
+ StringCbCopyW (page, sizeof (page),L"Twofish.html");
}
else if (strcmp(dest, "kuznyechik") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Kuznyechik");
+ StringCbCopyW (page, sizeof (page),L"Kuznyechik.html");
}
else if (strcmp(dest, "camellia") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Camellia");
+ StringCbCopyW (page, sizeof (page),L"Camellia.html");
}
else if (strcmp(dest, "cascades") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Cascades");
+ StringCbCopyW (page, sizeof (page),L"Cascades.html");
}
else if (strcmp(dest, "hashalgorithms") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Hash%20Algorithms");
+ StringCbCopyW (page, sizeof (page),L"Hash%20Algorithms.html");
}
else if (strcmp(dest, "isoburning") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://cdburnerxp.se/en/home");
+ StringCbCopyW (url, sizeof (url),L"https://cdburnerxp.se/en/home");
+ buildUrl = FALSE;
}
else if (strcmp(dest, "sysfavorites") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=System%20Favorite%20Volumes");
+ StringCbCopyW (page, sizeof (page),L"System%20Favorite%20Volumes.html");
}
else if (strcmp(dest, "favorites") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Favorite%20Volumes");
+ StringCbCopyW (page, sizeof (page),L"Favorite%20Volumes.html");
}
else if (strcmp(dest, "hiddenvolprotection") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Protection%20of%20Hidden%20Volumes");
+ StringCbCopyW (page, sizeof (page),L"Protection%20of%20Hidden%20Volumes.html");
}
else if (strcmp(dest, "faq") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=FAQ");
+ StringCbCopyW (page, sizeof (page),L"FAQ.html");
}
else if (strcmp(dest, "downloads") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Downloads");
+ StringCbCopyW (page, sizeof (page),L"Downloads.html");
}
else if (strcmp(dest, "news") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=News");
+ StringCbCopyW (page, sizeof (page),L"News.html");
}
else if (strcmp(dest, "contact") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Contact");
+ StringCbCopyW (page, sizeof (page),L"Contact.html");
}
else if (strcmp(dest, "pim") == 0)
{
- StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Personal%20Iterations%20Multiplier%20%28PIM%29");
+ StringCbCopyW (page, sizeof (page),L"Personal%20Iterations%20Multiplier%20%28PIM%29.html");
+ }
+ else if (strcmp(dest, "memoryprotection") == 0)
+ {
+ StringCbCopyW (page, sizeof (page),L"VeraCrypt%20Memory%20Protection.html");
}
else
{
- StringCbCopyA (url, sizeof (url),TC_APPLINK);
+ StringCbCopyW (url, sizeof (url),TC_APPLINK);
+ buildUrl = FALSE;
+ }
+
+ if (buildUrl)
+ {
+ // in case of setup, open the online documentation if we are connected to Internet because existing documentation may be outdated
+#ifdef SETUP
+ if (IsInternetConnected())
+ {
+ StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page);
+ buildUrl = FALSE;
+ }
+ else
+ {
+ StringCbPrintfW (url, sizeof (url), L"file:///%sdocs/html/en/%s", installDir, page);
+ CorrectURL (url);
+ }
+#else
+ StringCbPrintfW (url, sizeof (url), L"file:///%sdocs/html/en/%s", installDir, page);
+ CorrectURL (url);
+#endif
+ }
+
+ if (IsAdmin ())
+ {
+ int openDone = 0;
+ if (buildUrl)
+ {
+ wchar_t pageFileName [TC_MAX_PATH] = {0};
+ DWORD cchUnescaped = ARRAYSIZE(pageFileName);
+
+ StringCbCopyW (pageFileName, sizeof(pageFileName), page);
+ /* remove escape sequences from the page name before calling FileExists function */
+ if (S_OK == UrlUnescapeW (pageFileName, pageFileName, &cchUnescaped, URL_UNESCAPE_INPLACE))
+ {
+ std::wstring pageFullPath = installDir;
+ pageFullPath += L"docs\\html\\en\\";
+ pageFullPath += pageFileName;
+
+ if (!FileExists (pageFullPath.c_str()))
+ {
+ // fallback to online resources
+ StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page);
+ SafeOpenURL (url);
+ openDone = 1;
+ }
+ }
+ }
+
+ if (!openDone)
+ {
+ SafeOpenURL (url);
+ }
+ }
+ else
+ {
+ r = (INT_PTR) ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL);
+
+ if (((r == ERROR_FILE_NOT_FOUND) || (r == ERROR_PATH_NOT_FOUND)) && buildUrl)
+ {
+ // fallback to online resources
+ StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page);
+ ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL);
+ }
}
- ShellExecuteA (NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
Sleep (200);
NormalCursor ();
}
@@ -10335,10 +11400,8 @@ void HandleDriveNotReadyError (HWND hwnd)
&& value != 0)
{
Warning ("SYS_AUTOMOUNT_DISABLED", hwnd);
}
- else if (nCurrentOS == WIN_VISTA && CurrentOSServicePack < 1)
- Warning ("SYS_ASSIGN_DRIVE_LETTER", hwnd);
else
Warning ("DEVICE_NOT_READY_ERROR", hwnd);
RegCloseKey (hkey);
@@ -10351,9 +11414,10 @@ BOOL CALLBACK CloseTCWindowsEnum (HWND hwnd, LPARAM lParam)
if ((userDataVal == (LONG_PTR) 'VERA') || (userDataVal == (LONG_PTR) 'TRUE')) // Prior to 1.0e, 'TRUE' was used for VeraCrypt dialogs
{
wchar_t name[1024] = { 0 };
GetWindowText (hwnd, name, ARRAYSIZE (name) - 1);
- if (hwnd != MainDlg && wcsstr (name, L"VeraCrypt"))
+ // check if the window is a VeraCrypt window, excluding current process main dialog and VeraCrypt Setup window
+ if (hwnd != MainDlg && wcsstr (name, L"VeraCrypt") && !wcsstr (name, L"VeraCrypt Setup"))
{
PostMessage (hwnd, TC_APPMSG_CLOSE_BKG_TASK, 0, 0);
PostMessage (hwnd, WM_CLOSE, 0, 0);
@@ -10388,14 +11452,23 @@ BOOL CALLBACK FindTCWindowEnum (HWND hwnd, LPARAM lParam)
BYTE *MapResource (wchar_t *resourceType, int resourceId, PDWORD size)
{
HGLOBAL hResL;
HRSRC hRes;
+ HINSTANCE hResInst = NULL;
+
+#ifdef SETUP_DLL
+ // In case we're being called from the SetupDLL project, FindResource()
+ // and LoadResource() with NULL will fail since we're in a DLL. We need
+ // to call them with the HINSTANCE of the DLL instead, which we set in
+ // Setup.c of SetupDLL, DllMain() function.
+ hResInst = hInst;
+#endif
- hRes = FindResource (NULL, MAKEINTRESOURCE(resourceId), resourceType);
- hResL = LoadResource (NULL, hRes);
+ hRes = FindResource (hResInst, MAKEINTRESOURCE(resourceId), resourceType);
+ hResL = LoadResource (hResInst, hRes);
if (size != NULL)
- *size = SizeofResource (NULL, hRes);
+ *size = SizeofResource (hResInst, hRes);
return (BYTE *) LockResource (hResL);
}
@@ -10408,9 +11481,9 @@ void InconsistencyResolved (char *techInfo)
MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST);
}
-void ReportUnexpectedState (char *techInfo)
+void ReportUnexpectedState (const char *techInfo)
{
wchar_t finalMsg[8024];
StringCbPrintfW (finalMsg, sizeof(finalMsg), GetString ("UNEXPECTED_STATE"), techInfo);
@@ -10419,18 +11492,18 @@ void ReportUnexpectedState (char *techInfo)
#ifndef SETUP
-int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password *password, int pkcs5_prf, int pim, BOOL truecryptMode, BOOL write, BOOL preserveTimestamps, BOOL useBackupHeader)
+int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password *password, int pkcs5_prf, int pim, BOOL write, BOOL preserveTimestamps, BOOL useBackupHeader)
{
int status = ERR_PARAMETER_INCORRECT;
int volumeType;
wchar_t szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH];
wchar_t szDosDevice[TC_MAX_PATH];
- char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
+ unsigned char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
LARGE_INTEGER headerOffset;
DWORD dwResult;
- DISK_GEOMETRY deviceGeometry;
+ DISK_GEOMETRY_EX deviceGeometry;
context->VolumeIsOpen = FALSE;
context->CryptoInfo = NULL;
context->HostFileHandle = INVALID_HANDLE_VALUE;
@@ -10454,12 +11527,10 @@ int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password
}
else
StringCbCopyW (szCFDevice, sizeof(szCFDevice), szDiskFile);
- if (preserveTimestamps)
- write = TRUE;
- context->HostFileHandle = CreateFile (szCFDevice, GENERIC_READ | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ context->HostFileHandle = CreateFile (szCFDevice, GENERIC_READ | (write ? GENERIC_WRITE : (!context->IsDevice && preserveTimestamps? FILE_WRITE_ATTRIBUTES : 0)), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (context->HostFileHandle == INVALID_HANDLE_VALUE)
{
status = ERR_OS_ERROR;
@@ -10479,8 +11550,15 @@ int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password
// Remember the container modification/creation date and time
if (!context->IsDevice && preserveTimestamps)
{
+ // ensure that Last Access and Last Write timestamps are not modified
+ FILETIME ftLastAccessTime;
+ ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
+ ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
+
+ SetFileTime (context->HostFileHandle, NULL, &ftLastAccessTime, NULL);
+
if (GetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime) == 0)
context->TimestampsValid = FALSE;
else
context->TimestampsValid = TRUE;
@@ -10496,17 +11574,37 @@ int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password
context->HostSize = diskInfo.PartitionLength.QuadPart;
}
else
{
- DISK_GEOMETRY driveInfo;
+ BYTE dgBuffer[256];
- if (!DeviceIoControl (context->HostFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL))
+ if (!DeviceIoControl (context->HostFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, dgBuffer, sizeof (dgBuffer), &dwResult, NULL))
{
- status = ERR_OS_ERROR;
- goto error;
+ DISK_GEOMETRY geo;
+ if (DeviceIoControl (context->HostFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, (LPVOID) &geo, sizeof (geo), &dwResult, NULL))
+ {
+ ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart = geo.Cylinders.QuadPart * geo.SectorsPerTrack * geo.TracksPerCylinder * geo.BytesPerSector;
+
+ if (CurrentOSMajor >= 6)
+ {
+ STORAGE_READ_CAPACITY storage = {0};
+
+ storage.Version = sizeof (STORAGE_READ_CAPACITY);
+ storage.Size = sizeof (STORAGE_READ_CAPACITY);
+ if (DeviceIoControl (context->HostFileHandle, IOCTL_STORAGE_READ_CAPACITY, NULL, 0, (LPVOID) &storage, sizeof (storage), &dwResult, NULL))
+ {
+ ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart = storage.DiskLength.QuadPart;
+ }
+ }
+ }
+ else
+ {
+ status = ERR_OS_ERROR;
+ goto error;
+ }
}
- context->HostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder;
+ context->HostSize = ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart;
}
if (context->HostSize == 0)
{
@@ -10551,9 +11649,9 @@ int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password
}
// Read volume header
DWORD bytesRead;
- if (!ReadEffectiveVolumeHeader (context->IsDevice, context->HostFileHandle, (byte *) buffer, &bytesRead))
+ if (!ReadEffectiveVolumeHeader (context->IsDevice, context->HostFileHandle, (uint8 *) buffer, &bytesRead))
{
status = ERR_OS_ERROR;
goto error;
}
@@ -10569,9 +11667,9 @@ int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password
memset (buffer, 0, sizeof (buffer));
}
// Decrypt volume header
- status = ReadVolumeHeader (FALSE, buffer, password, pkcs5_prf, pim, truecryptMode, &context->CryptoInfo, NULL);
+ status = ReadVolumeHeader (FALSE, buffer, password, pkcs5_prf, pim, &context->CryptoInfo, NULL);
if (status == ERR_PASSWORD_WRONG)
continue; // Try next volume type
@@ -10614,9 +11712,9 @@ void CloseVolume (OpenVolumeContext *context)
context->VolumeIsOpen = FALSE;
}
-int ReEncryptVolumeHeader (HWND hwndDlg, char *buffer, BOOL bBoot, CRYPTO_INFO *cryptoInfo, Password *password, int pim, BOOL wipeMode)
+int ReEncryptVolumeHeader (HWND hwndDlg, unsigned char *buffer, BOOL bBoot, CRYPTO_INFO *cryptoInfo, Password *password, int pim, BOOL wipeMode)
{
CRYPTO_INFO *newCryptoInfo = NULL;
RandSetHashFunction (cryptoInfo->pkcs5);
@@ -10692,12 +11790,13 @@ BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly)
if (handle == INVALID_HANDLE_VALUE)
continue;
- DISK_GEOMETRY driveInfo;
+ BYTE dgBuffer[256];
DWORD dwResult;
- if (!DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveInfo, sizeof (driveInfo), &dwResult, NULL))
+ if (!DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, dgBuffer, sizeof (dgBuffer), &dwResult, NULL)
+ && !DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, dgBuffer, sizeof (dgBuffer), &dwResult, NULL))
{
CloseHandle (handle);
continue;
}
@@ -10810,8 +11909,19 @@ BOOL CALLBACK SecurityTokenPasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wPara
SendMessage (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), EM_LIMITTEXT, SecurityToken::MaxPasswordLength, 0);
SetForegroundWindow (hwndDlg);
SetFocus (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD));
+
+ if (!bSecureDesktopOngoing)
+ {
+ PasswordEditDropTarget* pTarget = new PasswordEditDropTarget ();
+ if (pTarget->Register (hwndDlg))
+ {
+ SetWindowLongPtr (hwndDlg, DWLP_USER, (LONG_PTR) pTarget);
+ }
+ else
+ delete pTarget;
+ }
}
return 0;
case WM_COMMAND:
@@ -10845,8 +11955,21 @@ BOOL CALLBACK SecurityTokenPasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wPara
EndDialog (hwndDlg, lw);
}
return 1;
+
+ case WM_NCDESTROY:
+ {
+ /* unregister drap-n-drop support */
+ PasswordEditDropTarget* pTarget = (PasswordEditDropTarget*) GetWindowLongPtr (hwndDlg, DWLP_USER);
+ if (pTarget)
+ {
+ SetWindowLongPtr (hwndDlg, DWLP_USER, (LONG_PTR) 0);
+ pTarget->Revoke ();
+ pTarget->Release();
+ }
+ }
+ return 0;
}
return 0;
}
@@ -10873,13 +11996,13 @@ static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPA
WaitCursor();
finally_do ({ NormalCursor(); });
- list <SecurityTokenInfo> tokens;
+ list <shared_ptr<TokenInfo>> tokens;
try
{
- tokens = SecurityToken::GetAvailableTokens();
+ tokens = Token::GetAvailableTokens();
}
catch (Exception &e)
{
e.Show (hwndDlg);
@@ -10891,14 +12014,14 @@ static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPA
EndDialog (hwndDlg, IDCANCEL);
return 1;
}
- foreach (const SecurityTokenInfo &token, tokens)
+ foreach (const shared_ptr<TokenInfo> token, tokens)
{
wstringstream tokenLabel;
- tokenLabel << L"[" << token.SlotId << L"] " << token.Label;
+ tokenLabel << L"[" << token->SlotId << L"] " << token->Label;
- AddComboPair (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), tokenLabel.str().c_str(), token.SlotId);
+ AddComboPair (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), tokenLabel.str().c_str(), token->SlotId);
}
ComboBox_SetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), 0);
@@ -10950,40 +12073,40 @@ static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPA
return 0;
}
-static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector <SecurityTokenKeyfile> &keyfiles)
+static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector <shared_ptr<TokenKeyfile>> &keyfiles)
{
HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST);
LVITEMW lvItem;
int line = 0;
ListView_DeleteAllItems (tokenListControl);
- foreach (const SecurityTokenKeyfile &keyfile, keyfiles)
+ foreach (const shared_ptr<TokenKeyfile> keyfile, keyfiles)
{
memset (&lvItem, 0, sizeof(lvItem));
lvItem.mask = LVIF_TEXT;
lvItem.iItem = line++;
wstringstream s;
- s << keyfile.SlotId;
+ s << keyfile->Token->SlotId;
ListItemAdd (tokenListControl, lvItem.iItem, (wchar_t *) s.str().c_str());
- ListSubItemSet (tokenListControl, lvItem.iItem, 1, (wchar_t *) keyfile.Token.Label.c_str());
- ListSubItemSet (tokenListControl, lvItem.iItem, 2, (wchar_t *) keyfile.Id.c_str());
+ ListSubItemSet (tokenListControl, lvItem.iItem, 1, (wchar_t *) keyfile->Token->Label.c_str());
+ ListSubItemSet (tokenListControl, lvItem.iItem, 2, (wchar_t *) keyfile->Id.c_str());
}
BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1);
EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected);
EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected);
}
-static list <SecurityTokenKeyfile> SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector <SecurityTokenKeyfile> &keyfiles)
+static list <shared_ptr<TokenKeyfile>> SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector <shared_ptr<TokenKeyfile>> &keyfiles)
{
HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST);
- list <SecurityTokenKeyfile> selectedKeyfiles;
+ list <shared_ptr<TokenKeyfile>> selectedKeyfiles;
int itemId = -1;
while ((itemId = ListView_GetNextItem (tokenListControl, itemId, LVIS_SELECTED)) != -1)
{
@@ -10995,18 +12118,18 @@ static list <SecurityTokenKeyfile> SecurityTokenKeyfileDlgGetSelected (HWND hwnd
BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
- static list <SecurityTokenKeyfilePath> *selectedTokenKeyfiles;
- static vector <SecurityTokenKeyfile> keyfiles;
+ static list <TokenKeyfilePath> *selectedTokenKeyfiles;
+ static vector <shared_ptr<TokenKeyfile>> keyfiles;
WORD lw = LOWORD (wParam);
switch (msg)
{
case WM_INITDIALOG:
{
- selectedTokenKeyfiles = (list <SecurityTokenKeyfilePath> *) lParam;
+ selectedTokenKeyfiles = (list <TokenKeyfilePath> *) lParam;
LVCOLUMNW LvCol;
HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST);
@@ -11039,9 +12162,9 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
{
WaitCursor();
finally_do ({ NormalCursor(); });
- keyfiles = SecurityToken::GetAvailableKeyfiles();
+ keyfiles = Token::GetAvailableKeyfiles(EMVSupportEnabled? true : false);
}
catch (UserAbort&)
{
EndDialog (hwndDlg, IDCANCEL);
@@ -11067,11 +12190,11 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE)
{
if (selectedTokenKeyfiles)
{
- foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles))
+ foreach (const shared_ptr<TokenKeyfile> &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles))
{
- selectedTokenKeyfiles->push_back (SecurityTokenKeyfilePath (keyfile));
+ selectedTokenKeyfiles->push_back (TokenKeyfilePath (*keyfile));
}
}
EndDialog (hwndDlg, IDOK);
@@ -11080,10 +12203,21 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED)
{
BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1);
+ BOOL deletable = selected;
+ // Multiple key files can be selected.
+ // Therefore, if one of them is not deletable, it means the delete button must be disabled for all.
+ foreach (const shared_ptr<TokenKeyfile> &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles))
+ {
+ if (!keyfile->Token->isEditable())
+ {
+ deletable = false;
+ break;
+ }
+ }
EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected);
- EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), deletable);
return 1;
}
if (msg == WM_COMMAND)
@@ -11097,12 +12231,12 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
case IDC_IMPORT_KEYFILE:
{
wchar_t keyfilePath[TC_MAX_PATH];
- if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE, NULL))
+ if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE))
{
DWORD keyfileSize;
- byte *keyfileData = (byte *) LoadFile (keyfilePath, &keyfileSize);
+ uint8 *keyfileData = (uint8 *) LoadFile (keyfilePath, &keyfileSize);
if (!keyfileData)
{
handleWin32Error (hwndDlg, SRC_POS);
return 1;
@@ -11118,9 +12252,9 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
newParams.Name = newParams.Name.substr (lastBackSlash + 1);
if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_NEW_TOKEN_KEYFILE), hwndDlg, (DLGPROC) NewSecurityTokenKeyfileDlgProc, (LPARAM) &newParams) == IDOK)
{
- vector <byte> keyfileDataVector (keyfileSize);
+ vector <uint8> keyfileDataVector (keyfileSize);
memcpy (&keyfileDataVector.front(), keyfileData, keyfileSize);
try
{
@@ -11128,9 +12262,9 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
finally_do ({ NormalCursor(); });
SecurityToken::CreateKeyfile (newParams.SlotId, keyfileDataVector, newParams.Name);
- keyfiles = SecurityToken::GetAvailableKeyfiles();
+ keyfiles = Token::GetAvailableKeyfiles(EMVSupportEnabled? true : false);
SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles);
}
catch (Exception &e)
{
@@ -11156,31 +12290,31 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
case IDC_EXPORT:
{
try
{
- foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles))
+ foreach (const shared_ptr<TokenKeyfile> &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles))
{
wchar_t keyfilePath[TC_MAX_PATH];
- if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE, NULL))
+ if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE))
break;
{
WaitCursor();
finally_do ({ NormalCursor(); });
- vector <byte> keyfileData;
+ vector <uint8> keyfileData;
- SecurityToken::GetKeyfileData (keyfile, keyfileData);
+ keyfile->GetKeyfileData (keyfileData);
if (keyfileData.empty())
{
SetLastError (ERROR_HANDLE_EOF);
handleWin32Error (hwndDlg, SRC_POS);
return 1;
}
- finally_do_arg (vector <byte> *, &keyfileData, { burn (&finally_arg->front(), finally_arg->size()); });
+ finally_do_arg (vector <uint8> *, &keyfileData, { burn (&finally_arg->front(), finally_arg->size()); });
if (!SaveBufferToFile ((char *) &keyfileData.front(), keyfilePath, (DWORD) keyfileData.size(), FALSE, FALSE))
throw SystemException (SRC_POS);
}
@@ -11205,14 +12339,14 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
{
WaitCursor();
finally_do ({ NormalCursor(); });
- foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles))
+ foreach (const shared_ptr<TokenKeyfile> keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles))
{
- SecurityToken::DeleteKeyfile (keyfile);
+ SecurityToken::DeleteKeyfile (dynamic_cast<SecurityTokenKeyfile&>(*keyfile.get()));
}
- keyfiles = SecurityToken::GetAvailableKeyfiles();
+ keyfiles = Token::GetAvailableKeyfiles(EMVSupportEnabled? true : false);
SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles);
}
catch (Exception &e)
{
@@ -11227,8 +12361,37 @@ BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam
}
return 0;
}
+extern "C" BOOL IsThreadInSecureDesktop(DWORD dwThreadID)
+{
+ BOOL bRet = FALSE;
+ if (bSecureDesktopOngoing)
+ {
+ HDESK currentDesk = GetThreadDesktop (dwThreadID);
+ if (currentDesk)
+ {
+ LPWSTR szName = NULL;
+ DWORD dwLen = 0;
+ if (!GetUserObjectInformation (currentDesk, UOI_NAME, NULL, 0, &dwLen))
+ {
+ szName = (LPWSTR) malloc (dwLen);
+ if (szName)
+ {
+ if (GetUserObjectInformation (currentDesk, UOI_NAME, szName, dwLen, &dwLen))
+ {
+ if (0 == _wcsicmp (szName, SecureDesktopName))
+ bRet = TRUE;
+ }
+ free (szName);
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+
BOOL InitSecurityTokenLibrary (HWND hwndDlg)
{
if (SecurityTokenLibraryPath[0] == 0)
@@ -11251,9 +12414,11 @@ BOOL InitSecurityTokenLibrary (HWND hwndDlg)
{
HWND hParent = IsWindow (m_hwnd)? m_hwnd : GetActiveWindow();
if (!hParent)
hParent = GetForegroundWindow ();
- if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TOKEN_PASSWORD), hParent, (DLGPROC) SecurityTokenPasswordDlgProc, (LPARAM) &str) == IDCANCEL)
+ if (IsThreadInSecureDesktop(GetCurrentThreadId()) && !IsThreadInSecureDesktop(GetWindowThreadProcessId(hParent, NULL)))
+ hParent = GetActiveWindow ();
+ if (SecureDesktopDialogBoxParam (hInst, MAKEINTRESOURCEW (IDD_TOKEN_PASSWORD), hParent, (DLGPROC) SecurityTokenPasswordDlgProc, (LPARAM) &str) == IDCANCEL)
throw UserAbort (SRC_POS);
}
if (hCursor != NULL)
SetCursor (hCursor);
@@ -11280,9 +12445,9 @@ BOOL InitSecurityTokenLibrary (HWND hwndDlg)
};
try
{
- SecurityToken::InitLibrary (SecurityTokenLibraryPath, auto_ptr <GetPinFunctor> (new PinRequestHandler(MainDlg)), auto_ptr <SendExceptionFunctor> (new WarningHandler(MainDlg)));
+ SecurityToken::InitLibrary (SecurityTokenLibraryPath, unique_ptr <GetPinFunctor> (new PinRequestHandler(MainDlg)), unique_ptr <SendExceptionFunctor> (new WarningHandler(MainDlg)));
}
catch (Exception &e)
{
e.Show (hwndDlg);
@@ -11292,10 +12457,8 @@ BOOL InitSecurityTokenLibrary (HWND hwndDlg)
return TRUE;
}
-#endif // !SETUP
-
std::vector <HostDevice> GetAvailableHostDevices (bool noDeviceProperties, bool singleList, bool noFloppy, bool detectUnencryptedFilesystems)
{
vector <HostDevice> devices;
size_t dev0;
@@ -11303,15 +12466,13 @@ std::vector <HostDevice> GetAvailableHostDevices (bool noDeviceProperties, bool
for (int devNumber = 0; devNumber < MAX_HOST_DRIVE_NUMBER; devNumber++)
{
for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++)
{
- wstringstream strm;
- strm << L"\\Device\\Harddisk" << devNumber << L"\\Partition" << partNumber;
- wstring devPathStr (strm.str());
- const wchar_t *devPath = devPathStr.c_str();
+ WCHAR devPath[32];
+ StringCbPrintfW (devPath, sizeof (devPath), L"\\Device\\Harddisk%d\\Partition%d", devNumber, partNumber);
OPEN_TEST_STRUCT openTest = {0};
- if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems && partNumber != 0, FALSE, NULL))
+ if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems && partNumber != 0, FALSE))
{
if (partNumber == 0)
break;
@@ -11330,26 +12491,25 @@ std::vector <HostDevice> GetAvailableHostDevices (bool noDeviceProperties, bool
device.Size = partInfo.PartitionLength.QuadPart;
}
else
{
- // retrieve size using DISK_GEOMETRY
- DISK_GEOMETRY deviceGeometry = {0};
+ // retrieve size using DISK_GEOMETRY_EX
+ DISK_GEOMETRY_EX deviceGeometry = {0};
if ( GetDriveGeometry (devPath, &deviceGeometry)
|| ((partNumber == 0) && GetPhysicalDriveGeometry (devNumber, &deviceGeometry))
)
{
- device.Size = deviceGeometry.Cylinders.QuadPart * (LONGLONG) deviceGeometry.BytesPerSector
- * (LONGLONG) deviceGeometry.SectorsPerTrack * (LONGLONG) deviceGeometry.TracksPerCylinder;
+ device.Size = (uint64) deviceGeometry.DiskSize.QuadPart;
}
}
device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false;
if (!noDeviceProperties)
{
- DISK_GEOMETRY geometry;
+ DISK_GEOMETRY_EX geometry;
- int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) devPathStr.c_str());
+ int driveNumber = GetDiskDeviceDriveLetter (devPath);
if (driveNumber >= 0)
{
device.MountPoint += (wchar_t) (driveNumber + L'A');
@@ -11363,9 +12523,9 @@ std::vector <HostDevice> GetAvailableHostDevices (bool noDeviceProperties, bool
device.ContainsSystem = true;
}
if (partNumber == 0 && GetDriveGeometry (devPath, &geometry))
- device.Removable = (geometry.MediaType == RemovableMedia);
+ device.Removable = (geometry.Geometry.MediaType == RemovableMedia);
}
if (partNumber == 0)
{
@@ -11408,15 +12568,13 @@ std::vector <HostDevice> GetAvailableHostDevices (bool noDeviceProperties, bool
if (CurrentOSMajor >= 6)
{
for (int devNumber = 0; devNumber < 256; devNumber++)
{
- wstringstream strm;
- strm << L"\\Device\\HarddiskVolume" << devNumber;
- wstring devPathStr (strm.str());
- const wchar_t *devPath = devPathStr.c_str();
+ WCHAR devPath[32];
+ StringCbPrintfW (devPath, sizeof (devPath), L"\\Device\\HarddiskVolume%d", devNumber);
OPEN_TEST_STRUCT openTest = {0};
- if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems, FALSE, NULL))
+ if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems, FALSE))
continue;
DISK_PARTITION_INFO_STRUCT info;
if (GetDeviceInfo (devPath, &info) && info.IsDynamic)
@@ -11430,9 +12588,9 @@ std::vector <HostDevice> GetAvailableHostDevices (bool noDeviceProperties, bool
device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false;
if (!noDeviceProperties)
{
- int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) devPathStr.c_str());
+ int driveNumber = GetDiskDeviceDriveLetter (devPath);
if (driveNumber >= 0)
{
device.MountPoint += (wchar_t) (driveNumber + L'A');
@@ -11454,49 +12612,449 @@ std::vector <HostDevice> GetAvailableHostDevices (bool noDeviceProperties, bool
return devices;
}
-wstring FindDeviceByVolumeID (const BYTE volumeID [VOLUME_ID_SIZE])
+void AddDeviceToList (std::vector<HostDevice>& devices, int devNumber, int partNumber)
+{
+ WCHAR devPath[64];
+ StringCbPrintfW (devPath, sizeof (devPath), L"\\Device\\Harddisk%d\\Partition%d", devNumber, partNumber);
+
+ HostDevice device;
+ device.SystemNumber = devNumber;
+ device.Path = devPath;
+
+ devices.push_back (device);
+}
+
+std::vector <HostDevice> GetHostRawDeviceList ()
+{
+ std::vector <HostDevice> list;
+ HDEVINFO diskClassDevices;
+ GUID diskClassDeviceInterfaceGuid = GUID_DEVINTERFACE_DISK;
+ SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
+ PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData;
+ DWORD requiredSize;
+ DWORD deviceIndex;
+
+ STORAGE_DEVICE_NUMBER diskNumber;
+ DWORD bytesReturned;
+
+ diskClassDevices = SetupDiGetClassDevs( &diskClassDeviceInterfaceGuid,
+ NULL,
+ NULL,
+ DIGCF_PRESENT |
+ DIGCF_DEVICEINTERFACE );
+ if ( INVALID_HANDLE_VALUE != diskClassDevices)
+ {
+ ZeroMemory( &deviceInterfaceData, sizeof( SP_DEVICE_INTERFACE_DATA ) );
+ deviceInterfaceData.cbSize = sizeof( SP_DEVICE_INTERFACE_DATA );
+ deviceIndex = 0;
+
+ while ( SetupDiEnumDeviceInterfaces( diskClassDevices,
+ NULL,
+ &diskClassDeviceInterfaceGuid,
+ deviceIndex,
+ &deviceInterfaceData ) )
+ {
+ ++deviceIndex;
+
+ if (!SetupDiGetDeviceInterfaceDetail( diskClassDevices,
+ &deviceInterfaceData,
+ NULL,
+ 0,
+ &requiredSize,
+ NULL ) && ( ERROR_INSUFFICIENT_BUFFER == GetLastError()))
+ {
+ deviceInterfaceDetailData = ( PSP_DEVICE_INTERFACE_DETAIL_DATA ) malloc( requiredSize );
+ if (deviceInterfaceDetailData)
+ {
+ ZeroMemory( deviceInterfaceDetailData, requiredSize );
+ deviceInterfaceDetailData->cbSize = sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA );
+ if (SetupDiGetDeviceInterfaceDetail( diskClassDevices,
+ &deviceInterfaceData,
+ deviceInterfaceDetailData,
+ requiredSize,
+ NULL,
+ NULL ))
+ {
+ HANDLE disk = CreateFile( deviceInterfaceDetailData->DevicePath,
+ 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+ if ( INVALID_HANDLE_VALUE != disk)
+ {
+ if (DeviceIoControl( disk,
+ IOCTL_STORAGE_GET_DEVICE_NUMBER,
+ NULL,
+ 0,
+ &diskNumber,
+ sizeof( STORAGE_DEVICE_NUMBER ),
+ &bytesReturned,
+ NULL ))
+ {
+ HostDevice device;
+ device.Path = deviceInterfaceDetailData->DevicePath;
+ device.SystemNumber = diskNumber.DeviceNumber;
+ list.push_back (device);
+ }
+
+ CloseHandle( disk );
+ }
+ }
+
+ free (deviceInterfaceDetailData);
+ }
+ }
+ }
+
+ SetupDiDestroyDeviceInfoList( diskClassDevices );
+ }
+
+ return list;
+}
+
+bool CompareDeviceList (const std::vector<HostDevice>& list1, const std::vector<HostDevice>& list2)
+{
+ if (list1.size() != list2.size())
+ return false;
+
+ for (std::vector<HostDevice>::const_iterator It1 = list1.begin(); It1 != list1.end(); It1++)
+ {
+ bool bFound = false;
+ for (std::vector<HostDevice>::const_iterator It2 = list2.begin(); It2 != list2.end(); It2++)
+ {
+ if (It1->Path == It2->Path && It1->SystemNumber == It2->SystemNumber)
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ if (!bFound)
+ return false;
+ }
+
+ return true;
+}
+
+void UpdateMountableHostDeviceList ()
+{
+ ByteArray buffer(4096);
+ DWORD bytesReturned;
+ bool dynamicVolumesPresent = false;
+
+ EnterCriticalSection (&csMountableDevices);
+ finally_do ({ LeaveCriticalSection (&csMountableDevices); });
+
+ std::vector<HostDevice> newList = GetHostRawDeviceList ();
+ std::map<DWORD, bool> existingDevicesMap;
+
+ if (CompareDeviceList (newList, rawHostDeviceList))
+ return; //no change, return
+
+ // remove raw devices that don't exist anymore
+ for (std::vector<HostDevice>::iterator It = rawHostDeviceList.begin();
+ It != rawHostDeviceList.end();)
+ {
+ for (std::vector<HostDevice>::iterator newIt = newList.begin(); newIt != newList.end(); newIt++)
+ {
+ if (newIt->SystemNumber == It->SystemNumber)
+ {
+ existingDevicesMap[It->SystemNumber] = true;
+ break;
+ }
+ }
+
+ if (existingDevicesMap[It->SystemNumber])
+ It++;
+ else
+ {
+ It = rawHostDeviceList.erase (It);
+ }
+ }
+
+ // remove mountable devices that don't exist anymore
+ for (std::vector<HostDevice>::iterator It = mountableDevices.begin();
+ It != mountableDevices.end();)
+ {
+ if (existingDevicesMap[It->SystemNumber])
+ It++;
+ else
+ It = mountableDevices.erase (It);
+ }
+
+ // add new devices
+ for (std::vector<HostDevice>::iterator It = newList.begin(); It != newList.end(); It++)
+ {
+ if (existingDevicesMap[It->SystemNumber])
+ continue;
+
+ HANDLE disk = CreateFile( It->Path.c_str(),
+ 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+ if ( INVALID_HANDLE_VALUE != disk)
+ {
+ bool bIsDynamic = false;
+ bool bHasPartition = false;
+ if (DeviceIoControl(
+ disk,
+ IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
+ NULL,
+ 0,
+ (LPVOID) buffer.data(),
+ (DWORD) buffer.size(),
+ (LPDWORD) &bytesReturned,
+ NULL) && (bytesReturned >= sizeof (DRIVE_LAYOUT_INFORMATION_EX)))
+ {
+ PDRIVE_LAYOUT_INFORMATION_EX layout = (PDRIVE_LAYOUT_INFORMATION_EX) buffer.data();
+ // sanity checks
+ if (layout->PartitionCount <= 256)
+ {
+ for (DWORD i = 0; i < layout->PartitionCount; i++)
+ {
+ if (layout->PartitionEntry[i].PartitionStyle == PARTITION_STYLE_MBR)
+ {
+ if (layout->PartitionEntry[i].Mbr.PartitionType == 0)
+ continue;
+
+ bHasPartition = true;
+
+ /* skip dynamic volume */
+ if (layout->PartitionEntry[i].Mbr.PartitionType == PARTITION_LDM)
+ {
+ bIsDynamic = true;
+ /* remove any partition that may have been added */
+ while (!mountableDevices.empty() && (mountableDevices.back().SystemNumber == It->SystemNumber))
+ mountableDevices.pop_back ();
+ break;
+ }
+ }
+
+ if (layout->PartitionEntry[i].PartitionStyle == PARTITION_STYLE_GPT)
+ {
+ if (IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_ENTRY_UNUSED_GUID))
+ continue;
+
+ bHasPartition = true;
+
+ /* skip dynamic volume */
+ if ( IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_LDM_METADATA_GUID)
+ || IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_LDM_DATA_GUID)
+ )
+ {
+ bIsDynamic = true;
+ /* remove any partition that may have been added */
+ while (!mountableDevices.empty() && (mountableDevices.back().SystemNumber == It->SystemNumber))
+ mountableDevices.pop_back ();
+ break;
+ }
+ }
+
+ WCHAR path[MAX_PATH];
+ StringCbPrintfW (path, sizeof(path), L"\\\\?\\GLOBALROOT\\Device\\Harddisk%d\\Partition%d", It->SystemNumber, layout->PartitionEntry[i].PartitionNumber);
+ HANDLE handle = CreateFile( path,
+ 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+ if ((handle != INVALID_HANDLE_VALUE) || (GetLastError () == ERROR_ACCESS_DENIED))
+ {
+ AddDeviceToList (mountableDevices, It->SystemNumber, layout->PartitionEntry[i].PartitionNumber);
+ if (handle != INVALID_HANDLE_VALUE)
+ CloseHandle (handle);
+ }
+ }
+ }
+ }
+
+ if (bIsDynamic)
+ dynamicVolumesPresent = true;
+
+ if (!bHasPartition)
+ AddDeviceToList (mountableDevices, It->SystemNumber, 0);
+
+ CloseHandle (disk);
+ }
+ }
+
+ rawHostDeviceList = newList;
+
+ // Starting from Vista, Windows does not create partition links for dynamic volumes so it is necessary to scan \\Device\\HarddiskVolumeX devices
+ if (dynamicVolumesPresent && (CurrentOSMajor >= 6))
+ {
+ for (int devNumber = 0; devNumber < 256; devNumber++)
+ {
+ WCHAR devPath[32];
+ StringCbPrintfW (devPath, sizeof (devPath), L"\\Device\\HarddiskVolume%d", devNumber);
+
+ OPEN_TEST_STRUCT openTest = {0};
+ if (!OpenDevice (devPath, &openTest, FALSE, FALSE))
+ continue;
+
+ DISK_PARTITION_INFO_STRUCT info;
+ if (GetDeviceInfo (devPath, &info) && info.IsDynamic)
+ {
+ HostDevice device;
+ device.SystemNumber = devNumber;
+ device.Path = devPath;
+
+ mountableDevices.push_back (device);
+ }
+ }
+ }
+}
+
+wstring FindDeviceByVolumeID (const BYTE volumeID [VOLUME_ID_SIZE], BOOL bFromService)
{
/* if it is already mounted, get the real path name used for mounting */
MOUNT_LIST_STRUCT mlist;
DWORD dwResult;
memset (&mlist, 0, sizeof (mlist));
- DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist,
- sizeof (mlist), &mlist, sizeof (mlist), &dwResult,
- NULL);
+ if ( !DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist,
+ sizeof (mlist), &mlist, sizeof (mlist), &dwResult,
+ NULL)
+ || (mlist.ulMountedDrives >= (1 << 26))
+ )
+ {
+ return L"";
+ }
- for (int i=0 ; i < 26; i++)
+ if (mlist.ulMountedDrives)
{
- if (0 == memcmp (mlist.volumeID[i], volumeID, VOLUME_ID_SIZE))
- return mlist.wszVolume[i];
+ for (int i=0 ; i < 26; i++)
+ {
+ if ((mlist.ulMountedDrives & (1 << i)) && (0 == memcmp (mlist.volumeID[i], volumeID, VOLUME_ID_SIZE)))
+ {
+ if (IsNullTerminateString (mlist.wszVolume[i], TC_MAX_PATH))
+ return mlist.wszVolume[i];
+ else
+ return L"";
+ }
+ }
}
/* not mounted. Look for it in the local drives*/
- for (int devNumber = 0; devNumber < MAX_HOST_DRIVE_NUMBER; devNumber++)
+
+ if (bFromService)
{
- for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++)
+ for (int devNumber = 0; devNumber < MAX_HOST_DRIVE_NUMBER; devNumber++)
{
- wstringstream strm;
- strm << L"\\Device\\Harddisk" << devNumber << L"\\Partition" << partNumber;
- wstring devPathStr (strm.str());
- const wchar_t *devPath = devPathStr.c_str();
+ for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++)
+ {
+ WCHAR devPath[32];
+ StringCbPrintfW (devPath, sizeof (devPath), L"\\Device\\Harddisk%d\\Partition%d", devNumber, partNumber);
- OPEN_TEST_STRUCT openTest = {0};
- if (!OpenDevice (devPath, &openTest, FALSE, TRUE, volumeID))
+ OPEN_TEST_STRUCT openTest = {0};
+ if (OpenDevice (devPath, &openTest, TRUE, TRUE)
+ && (openTest.VolumeIDComputed[TC_VOLUME_TYPE_NORMAL] && openTest.VolumeIDComputed[TC_VOLUME_TYPE_HIDDEN])
+ )
+ {
+ if ( (0 == memcmp (volumeID, openTest.volumeIDs[TC_VOLUME_TYPE_NORMAL], VOLUME_ID_SIZE))
+ || (0 == memcmp (volumeID, openTest.volumeIDs[TC_VOLUME_TYPE_HIDDEN], VOLUME_ID_SIZE))
+ )
+ {
+ return devPath;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ static std::vector<HostDevice> volumeIdCandidates;
+
+ EnterCriticalSection (&csMountableDevices);
+ if (!NeedPeriodicDeviceListUpdate)
+ UpdateMountableHostDeviceList ();
+ std::vector<HostDevice> newDevices = mountableDevices;
+ LeaveCriticalSection (&csMountableDevices);
+
+ EnterCriticalSection (&csVolumeIdCandidates);
+ finally_do ({ LeaveCriticalSection (&csVolumeIdCandidates); });
+
+ /* remove any devices that don't exist anymore */
+ for (std::vector<HostDevice>::iterator It = volumeIdCandidates.begin();
+ It != volumeIdCandidates.end();)
+ {
+ bool bFound = false;
+ for (std::vector<HostDevice>::iterator newIt = newDevices.begin();
+ newIt != newDevices.end(); newIt++)
{
- continue;
+ if (It->Path == newIt->Path)
+ {
+ bFound = true;
+ break;
+ }
}
- if (openTest.VolumeIDMatched)
- return devPath;
+ if (bFound)
+ It++;
+ else
+ It = volumeIdCandidates.erase (It);
+ }
+
+ /* Add newly inserted devices and compute their VolumeID */
+ for (std::vector<HostDevice>::iterator newIt = newDevices.begin();
+ newIt != newDevices.end(); newIt++)
+ {
+ bool bFound = false;
+
+ for (std::vector<HostDevice>::iterator It = volumeIdCandidates.begin();
+ It != volumeIdCandidates.end(); It++)
+ {
+ if (It->Path == newIt->Path)
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ if (!bFound)
+ {
+ /* new device/partition. Compute its Volume IDs */
+ OPEN_TEST_STRUCT openTest = {0};
+ if (OpenDevice (newIt->Path.c_str(), &openTest, TRUE, TRUE)
+ && (openTest.VolumeIDComputed[TC_VOLUME_TYPE_NORMAL] && openTest.VolumeIDComputed[TC_VOLUME_TYPE_HIDDEN])
+ )
+ {
+ memcpy (newIt->VolumeIDs, openTest.volumeIDs, sizeof (newIt->VolumeIDs));
+ newIt->HasVolumeIDs = true;
+ }
+ else
+ newIt->HasVolumeIDs = false;
+ volumeIdCandidates.push_back (*newIt);
+ }
+ }
+
+ for (std::vector<HostDevice>::iterator It = volumeIdCandidates.begin();
+ It != volumeIdCandidates.end(); It++)
+ {
+ if ( It->HasVolumeIDs &&
+ ( (0 == memcmp (volumeID, It->VolumeIDs[TC_VOLUME_TYPE_NORMAL], VOLUME_ID_SIZE))
+ || (0 == memcmp (volumeID, It->VolumeIDs[TC_VOLUME_TYPE_HIDDEN], VOLUME_ID_SIZE))
+ )
+ )
+ {
+ return It->Path;
+ }
}
}
return L"";
}
+#endif // !SETUP
+
BOOL FileHasReadOnlyAttribute (const wchar_t *path)
{
DWORD attributes = GetFileAttributes (path);
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_READONLY) != 0;
@@ -11519,9 +13077,9 @@ BOOL IsFileOnReadOnlyFilesystem (const wchar_t *path)
void CheckFilesystem (HWND hwndDlg, int driveNo, BOOL fixErrors)
{
wchar_t msg[1024], param[1024], cmdPath[MAX_PATH];
- wchar_t driveRoot[] = { L'A' + (wchar_t) driveNo, L':', 0 };
+ wchar_t driveRoot[] = { (wchar_t) (L'A' + driveNo), L':', 0 };
if (fixErrors && AskWarnYesNo ("FILESYS_REPAIR_CONFIRM_BACKUP", hwndDlg) == IDNO)
return;
@@ -11537,28 +13095,36 @@ void CheckFilesystem (HWND hwndDlg, int driveNo, BOOL fixErrors)
ShellExecuteW (NULL, (!IsAdmin() && IsUacSupported()) ? L"runas" : L"open", cmdPath, param, NULL, SW_SHOW);
}
-
-BOOL BufferContainsString (const byte *buffer, size_t bufferSize, const char *str)
+BOOL BufferContainsPattern (const uint8 *buffer, size_t bufferSize, const uint8 *pattern, size_t patternSize)
{
- size_t strLen = strlen (str);
-
- if (bufferSize < strLen)
+ if (bufferSize < patternSize)
return FALSE;
- bufferSize -= strLen;
+ bufferSize -= patternSize;
for (size_t i = 0; i < bufferSize; ++i)
{
- if (memcmp (buffer + i, str, strLen) == 0)
+ if (memcmp (buffer + i, pattern, patternSize) == 0)
return TRUE;
}
return FALSE;
}
+BOOL BufferContainsString (const uint8 *buffer, size_t bufferSize, const char *str)
+{
+ return BufferContainsPattern (buffer, bufferSize, (const uint8*) str, strlen (str));
+}
+
+BOOL BufferContainsWideString (const uint8 *buffer, size_t bufferSize, const wchar_t *str)
+{
+ return BufferContainsPattern (buffer, bufferSize, (const uint8*) str, 2 * wcslen (str));
+}
+
+
#ifndef SETUP
int AskNonSysInPlaceEncryptionResume (HWND hwndDlg, BOOL *pbDecrypt)
{
@@ -11707,18 +13273,18 @@ BOOL DisableFileCompression (HANDLE file)
format = COMPRESSION_FORMAT_NONE;
return DeviceIoControl (file, FSCTL_SET_COMPRESSION, &format, sizeof (format), NULL, 0, &bytesOut, NULL);
}
-
+#ifndef SETUP
BOOL VolumePathExists (const wchar_t *volumePath)
{
OPEN_TEST_STRUCT openTest = {0};
wchar_t upperCasePath[TC_MAX_PATH + 1];
UpperCaseCopy (upperCasePath, sizeof(upperCasePath), volumePath);
if (wcsstr (upperCasePath, L"\\DEVICE\\") == upperCasePath)
- return OpenDevice (volumePath, &openTest, FALSE, FALSE, NULL);
+ return OpenDevice (volumePath, &openTest, FALSE, FALSE);
wstring path = volumePath;
if (path.find (L"\\\\?\\Volume{") == 0 && path.rfind (L"}\\") == path.size() - 2)
{
@@ -11743,13 +13309,8 @@ BOOL VolumePathExists (const wchar_t *volumePath)
BOOL IsWindowsIsoBurnerAvailable ()
{
wchar_t path[MAX_PATH*2] = { 0 };
- if (!IsOSAtLeast (WIN_7))
- {
- return FALSE;
- }
-
if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_SYSTEM, NULL, 0, path)))
{
StringCbCatW (path, MAX_PATH*2, L"\\" ISO_BURNER_TOOL);
@@ -11762,20 +13323,20 @@ BOOL IsWindowsIsoBurnerAvailable ()
BOOL LaunchWindowsIsoBurner (HWND hwnd, const wchar_t *isoPath)
{
wchar_t path[MAX_PATH*2] = { 0 };
- int r;
+ INT_PTR r;
if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_SYSTEM, NULL, 0, path)))
StringCbCatW (path, MAX_PATH*2, L"\\" ISO_BURNER_TOOL);
else
StringCbCopyW (path, MAX_PATH*2, L"C:\\Windows\\System32\\" ISO_BURNER_TOOL);
- r = (int) ShellExecute (hwnd, L"open", path, (wstring (L"\"") + isoPath + L"\"").c_str(), NULL, SW_SHOWNORMAL);
+ r = (INT_PTR) ShellExecute (hwnd, L"open", path, (wstring (L"\"") + isoPath + L"\"").c_str(), NULL, SW_SHOWNORMAL);
if (r <= 32)
{
- SetLastError (r);
+ SetLastError ((DWORD) r);
handleWin32Error (hwnd, SRC_POS);
return FALSE;
}
@@ -11824,8 +13385,9 @@ std::wstring HarddiskVolumePathToPartitionPath (const std::wstring &harddiskVolu
return wstring();
}
+#endif
BOOL IsApplicationInstalled (const wchar_t *appName, BOOL b32bitApp)
{
const wchar_t *uninstallRegName = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
@@ -11838,9 +13400,9 @@ BOOL IsApplicationInstalled (const wchar_t *appName, BOOL b32bitApp)
return FALSE;
}
wchar_t regName[1024];
- DWORD regNameSize = sizeof (regName);
+ DWORD regNameSize = ARRAYSIZE (regName);
DWORD index = 0;
while (RegEnumKeyEx (unistallKey, index++, regName, &regNameSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{
if (wcsstr (regName, L"{") == regName)
@@ -11903,11 +13465,11 @@ std::wstring FindLatestFileOrDirectory (const std::wstring &directory, const wch
return wstring (directory) + L"\\" + name;
}
-int GetPim (HWND hwndDlg, UINT ctrlId)
+int GetPim (HWND hwndDlg, UINT ctrlId, int defaultPim)
{
- int pim = 0;
+ int pim = defaultPim;
HWND hCtrl = GetDlgItem (hwndDlg, ctrlId);
if (IsWindowEnabled (hCtrl) && IsWindowVisible (hCtrl))
{
wchar_t szTmp[MAX_PIM + 1] = {0};
@@ -11915,9 +13477,9 @@ int GetPim (HWND hwndDlg, UINT ctrlId)
{
wchar_t* endPtr = NULL;
pim = wcstol(szTmp, &endPtr, 10);
if (pim < 0 || endPtr == szTmp || !endPtr || *endPtr != L'\0')
- pim = 0;
+ pim = defaultPim;
}
}
return pim;
}
@@ -11933,15 +13495,17 @@ void SetPim (HWND hwndDlg, UINT ctrlId, int pim)
else
SetDlgItemText (hwndDlg, ctrlId, L"");
}
-BOOL GetPassword (HWND hwndDlg, UINT ctrlID, char* passValue, int bufSize, BOOL bShowError)
+BOOL GetPassword (HWND hwndDlg, UINT ctrlID, char* passValue, int bufSize, BOOL bLegacyPassword, BOOL bShowError)
{
wchar_t tmp [MAX_PASSWORD + 1];
int utf8Len;
BOOL bRet = FALSE;
GetWindowText (GetDlgItem (hwndDlg, ctrlID), tmp, ARRAYSIZE (tmp));
+ if ((bLegacyPassword || bUseLegacyMaxPasswordLength) && (lstrlen (tmp) > MAX_LEGACY_PASSWORD))
+ wmemset (&tmp[MAX_LEGACY_PASSWORD], 0, MAX_PASSWORD + 1 - MAX_LEGACY_PASSWORD);
utf8Len = WideCharToMultiByte (CP_UTF8, 0, tmp, -1, passValue, bufSize, NULL, NULL);
burn (tmp, sizeof (tmp));
if (utf8Len > 0)
{
@@ -11951,13 +13515,23 @@ BOOL GetPassword (HWND hwndDlg, UINT ctrlID, char* passValue, int bufSize, BOOL
{
passValue [0] = 0;
if (bShowError)
{
- SetFocus (GetDlgItem(hwndDlg, ctrlID));
if (GetLastError () == ERROR_INSUFFICIENT_BUFFER)
- Error ("PASSWORD_UTF8_TOO_LONG", hwndDlg);
+ {
+ DWORD dwTextSize = (DWORD) wcslen (GetString ("PASSWORD_UTF8_TOO_LONG")) + 16;
+ WCHAR* szErrorText = (WCHAR*) malloc (dwTextSize * sizeof (WCHAR));
+
+ // bufSize is equal to maximum password length plus one
+ StringCchPrintf (szErrorText, dwTextSize, GetString ("PASSWORD_UTF8_TOO_LONG"), (bufSize - 1));
+
+ ErrorDirect (szErrorText, hwndDlg);
+
+ free (szErrorText);
+ }
else
Error ("PASSWORD_UTF8_INVALID", hwndDlg);
+ SetFocus (GetDlgItem(hwndDlg, ctrlID));
}
}
return bRet;
@@ -12005,41 +13579,41 @@ void RegisterDriverInf (bool registerFilter, const string& filter, const string&
+ string (registerFilter ? "Add" : "Del") + "Reg=veracrypt_reg\r\n\r\n"
"[veracrypt_reg]\r\n"
"HKR,,\"" + filterReg + "\",0x0001" + string (registerFilter ? "0008" : "8002") + ",\"" + filter + "\"\r\n";
- infFile.Write ((byte *) infTxt.c_str(), (DWORD) infTxt.size());
+ infFile.Write ((uint8 *) infTxt.c_str(), (DWORD) infTxt.size());
infFile.Close();
- HINF hInf = SetupOpenInfFileWFn (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
+ HINF hInf = SetupOpenInfFileW (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
throw_sys_if (hInf == INVALID_HANDLE_VALUE);
- finally_do_arg (HINF, hInf, { SetupCloseInfFileFn (finally_arg); });
+ finally_do_arg (HINF, hInf, { SetupCloseInfFile (finally_arg); });
- throw_sys_if (!SetupInstallFromInfSectionWFn (ParentWindow, hInf, L"veracrypt", SPINST_REGISTRY, regKey, NULL, 0, NULL, NULL, NULL, NULL));
+ throw_sys_if (!SetupInstallFromInfSectionW (ParentWindow, hInf, L"veracrypt", SPINST_REGISTRY, regKey, NULL, 0, NULL, NULL, NULL, NULL));
}
HKEY OpenDeviceClassRegKey (const GUID *deviceClassGuid)
{
- return SetupDiOpenClassRegKeyFn (deviceClassGuid, KEY_READ | KEY_WRITE);
+ return SetupDiOpenClassRegKey (deviceClassGuid, KEY_READ | KEY_WRITE);
}
LSTATUS DeleteRegistryKey (HKEY hKey, LPCTSTR keyName)
{
- return SHDeleteKeyWFn(hKey, keyName);
+ return SHDeleteKeyW(hKey, keyName);
}
HIMAGELIST CreateImageList(int cx, int cy, UINT flags, int cInitial, int cGrow)
{
- return ImageList_CreateFn(cx, cy, flags, cInitial, cGrow);
+ return ImageList_Create(cx, cy, flags, cInitial, cGrow);
}
int AddBitmapToImageList(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
{
- return ImageList_AddFn(himl, hbmImage, hbmMask);
+ return ImageList_Add(himl, hbmImage, hbmMask);
}
HRESULT VCStrDupW(LPCWSTR psz, LPWSTR *ppwsz)
{
- return SHStrDupWFn (psz, ppwsz);
+ return SHStrDupW (psz, ppwsz);
}
void ProcessEntropyEstimate (HWND hProgress, DWORD* pdwInitialValue, DWORD dwCounter, DWORD dwMaxLevel, DWORD* pdwEntropy)
@@ -12060,18 +13634,15 @@ void ProcessEntropyEstimate (HWND hProgress, DWORD* pdwInitialValue, DWORD dwCou
*pdwEntropy = dwCounter - *pdwInitialValue;
else
*pdwEntropy = dwMaxLevel;
- if (IsOSAtLeast (WIN_VISTA))
- {
- int state = PBST_ERROR;
- if (*pdwEntropy >= (dwMaxLevel/2))
- state = PBST_NORMAL;
- else if (*pdwEntropy >= (dwMaxLevel/4))
- state = PBST_PAUSED;
+ int state = PBST_ERROR;
+ if (*pdwEntropy >= (dwMaxLevel/2))
+ state = PBST_NORMAL;
+ else if (*pdwEntropy >= (dwMaxLevel/4))
+ state = PBST_PAUSED;
- SendMessage (hProgress, PBM_SETSTATE, state, 0);
- }
+ SendMessage (hProgress, PBM_SETSTATE, state, 0);
SendMessage (hProgress, PBM_SETPOS,
(WPARAM) (*pdwEntropy),
0);
@@ -12079,15 +13650,13 @@ void ProcessEntropyEstimate (HWND hProgress, DWORD* pdwInitialValue, DWORD dwCou
}
void AllowMessageInUIPI (UINT msg)
{
- if (ChangeWindowMessageFilterFn)
- {
- ChangeWindowMessageFilterFn (msg, MSGFLT_ADD);
- }
+ /* ChangeWindowMessageFilter is used to enable some messages bypasss UIPI (User Interface Privilege Isolation) */
+ ChangeWindowMessageFilter (msg, MSGFLT_ADD);
}
-BOOL IsRepeatedByteArray (byte value, const byte* buffer, size_t bufferSize)
+BOOL IsRepeatedByteArray (uint8 value, const uint8* buffer, size_t bufferSize)
{
if (buffer && bufferSize)
{
size_t i;
@@ -12101,21 +13670,23 @@ BOOL IsRepeatedByteArray (byte value, const byte* buffer, size_t bufferSize)
else
return FALSE;
}
+#ifndef SETUP
+
BOOL TranslateVolumeID (HWND hwndDlg, wchar_t* pathValue, size_t cchPathValue)
{
BOOL bRet = TRUE;
size_t pathLen = pathValue? wcslen (pathValue) : 0;
if ((pathLen >= 3) && (_wcsnicmp (pathValue, L"ID:", 3) == 0))
{
- std::vector<byte> arr;
+ std::vector<uint8> arr;
if ( (pathLen == (3 + 2*VOLUME_ID_SIZE))
&& HexWideStringToArray (pathValue + 3, arr)
&& (arr.size() == VOLUME_ID_SIZE)
)
{
- std::wstring devicePath = FindDeviceByVolumeID (&arr[0]);
+ std::wstring devicePath = FindDeviceByVolumeID (&arr[0], FALSE);
if (devicePath.length() > 0)
StringCchCopyW (pathValue, cchPathValue, devicePath.c_str());
else
{
@@ -12137,8 +13708,10 @@ BOOL TranslateVolumeID (HWND hwndDlg, wchar_t* pathValue, size_t cchPathValue)
return bRet;
}
+#endif
+
BOOL CopyTextToClipboard (LPCWSTR txtValue)
{
size_t txtLen = wcslen(txtValue);
HGLOBAL hdst;
@@ -12176,9 +13749,9 @@ BOOL GetFreeDriveLetter(WCHAR* pCh) {
}
return FALSE;
}
-BOOL RaisePrivileges(void)
+BOOL SetPrivilege(LPTSTR szPrivilegeName, BOOL bEnable)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
BOOL bRet = FALSE;
@@ -12187,18 +13760,54 @@ BOOL RaisePrivileges(void)
if (OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
{
- if (LookupPrivilegeValue(NULL, SE_SYSTEM_ENVIRONMENT_NAME,
+ if (LookupPrivilegeValue(NULL, szPrivilegeName,
&tkp.Privileges[0].Luid))
{
- DWORD len;
-
tkp.PrivilegeCount = 1;
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ tkp.Privileges[0].Attributes = bEnable? SE_PRIVILEGE_ENABLED : 0;
- bRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, &len);
- if (!bRet)
+ bRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, NULL);
+ dwLastError = GetLastError ();
+ if (bRet && (ERROR_NOT_ALL_ASSIGNED == dwLastError))
+ {
+ bRet = FALSE;
+ }
+ }
+ else
+ dwLastError = GetLastError ();
+
+ CloseHandle(hToken);
+ }
+ else
+ dwLastError = GetLastError ();
+
+ SetLastError (dwLastError);
+
+ return bRet;
+}
+
+BOOL IsPrivilegeEnabled (LPTSTR szPrivilegeName)
+{
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tkp;
+ BOOL bRet = FALSE;
+ DWORD dwLastError = 0;
+
+ if (OpenProcessToken(GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
+ &hToken))
+ {
+ if (LookupPrivilegeValue(NULL, szPrivilegeName,
+ &tkp.Privileges[0].Luid))
+ {
+ DWORD dwSize = sizeof (tkp);
+ if (GetTokenInformation (hToken, TokenPrivileges, &tkp, dwSize, &dwSize))
+ {
+ bRet = (tkp.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED) != 0;
+ }
+ else
dwLastError = GetLastError ();
}
else
dwLastError = GetLastError ();
@@ -12233,15 +13842,16 @@ BOOL DeleteDirectory (const wchar_t* szDirName)
}
return bStatus;
}
-#ifdef TCMOUNT
+#if defined (TCMOUNT) || defined (VOLFORMAT)
/*********************************************************************/
static BOOL GenerateRandomString (HWND hwndDlg, LPTSTR szName, DWORD maxCharsCount)
{
BOOL bRet = FALSE;
- if (Randinit () != ERR_SUCCESS)
+ int alreadyInitialized = 0;
+ if (RandinitWithCheck (&alreadyInitialized) != ERR_SUCCESS)
{
handleError (hwndDlg, (CryptoAPILastError == ERROR_SUCCESS)? ERR_RAND_INIT_FAILED : ERR_CAPI_INIT_FAILED, SRC_POS);
}
else
@@ -12249,9 +13859,9 @@ static BOOL GenerateRandomString (HWND hwndDlg, LPTSTR szName, DWORD maxCharsCou
BYTE* indexes = (BYTE*) malloc (maxCharsCount + 1);
bRet = RandgetBytesFull (hwndDlg, indexes, maxCharsCount + 1, TRUE, TRUE);
if (bRet)
{
- static LPCTSTR chars = _T("0123456789@#$%^&_-*abcdefghijklmnopqrstuvwxyz");
+ static LPCTSTR chars = _T("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_");
DWORD i, charsLen = (DWORD) _tcslen (chars);
DWORD effectiveLen = (indexes[0] % (64 - 16)) + 16; // random length between 16 to 64
effectiveLen = (effectiveLen > maxCharsCount)? maxCharsCount : effectiveLen;
@@ -12263,32 +13873,181 @@ static BOOL GenerateRandomString (HWND hwndDlg, LPTSTR szName, DWORD maxCharsCou
szName[effectiveLen] = 0;
}
burn (indexes, maxCharsCount + 1);
free (indexes);
+
+ /* If RNG was not initialized before us, then stop it in order to
+ * stop the fast poll thread which consumes CPU. Next time a critical operation
+ * that requires RNG is performed, it will be initialized again.
+ *
+ * We do this because since the addition of secure desktop support, every time
+ * secure desktop is displayed, the RNG fast poll thread was started even if the
+ * user will never perform any critical operation that requires random bytes.
+ */
+ if (!alreadyInitialized)
+ {
+ RandStop (FALSE);
+ }
}
return bRet;
}
typedef struct
{
HDESK hDesk;
+ LPCWSTR szDesktopName;
HINSTANCE hInstance;
LPCWSTR lpTemplateName;
DLGPROC lpDialogFunc;
LPARAM dwInitParam;
INT_PTR retValue;
+ BOOL bDlgDisplayed; // set to TRUE if the dialog was displayed on secure desktop
} SecureDesktopThreadParam;
-static DWORD WINAPI SecureDesktopThread(LPVOID lpThreadParameter)
+typedef struct
+{
+ LPCWSTR szVCDesktopName;
+ HDESK hVcDesktop;
+ HANDLE hStopEvent; // event to signal when to stop monitoring
+} SecureDesktopMonitoringThreadParam;
+
+#define SECUREDESKTOP_MONOTIR_PERIOD 500
+
+// This thread checks if VeraCrypt secure desktop is the one that has user input
+// and if it is not then it will call SwitchDesktop to make it the input desktop
+static unsigned int __stdcall SecureDesktopMonitoringThread( LPVOID lpThreadParameter )
+{
+ SecureDesktopMonitoringThreadParam* pMonitorParam = (SecureDesktopMonitoringThreadParam*) lpThreadParameter;
+ if (pMonitorParam)
+ {
+ HANDLE hStopEvent = pMonitorParam->hStopEvent;
+ LPCWSTR szVCDesktopName = pMonitorParam->szVCDesktopName;
+ HDESK hVcDesktop = pMonitorParam->hVcDesktop;
+
+ // loop until the stop event is signaled
+ while (WaitForSingleObject (hStopEvent, SECUREDESKTOP_MONOTIR_PERIOD) == WAIT_TIMEOUT)
+ {
+ // check that our secure desktop is still the input desktop
+ // otherwise, switch to it
+ BOOL bPerformSwitch = FALSE;
+ HDESK currentDesk = OpenInputDesktop (0, FALSE, GENERIC_READ);
+ if (currentDesk)
+ {
+ LPWSTR szName = NULL;
+ DWORD dwLen = 0;
+ if (!GetUserObjectInformation (currentDesk, UOI_NAME, NULL, 0, &dwLen))
+ {
+ szName = (LPWSTR) malloc (dwLen);
+ if (szName)
+ {
+ if (GetUserObjectInformation (currentDesk, UOI_NAME, szName, dwLen, &dwLen))
+ {
+ if (0 == _wcsicmp(szName, L"Default")) // default input desktop for the interactive window station
+ bPerformSwitch = TRUE;
+ else if (0 != _wcsicmp (szName, szVCDesktopName))
+ bPerformSwitch = TRUE;
+ }
+ free (szName);
+ }
+ }
+ CloseDesktop (currentDesk);
+ }
+
+ if (bPerformSwitch)
+ SwitchDesktop (hVcDesktop);
+ }
+ }
+
+ return 0;
+}
+
+static unsigned int __stdcall SecureDesktopThread( LPVOID lpThreadParameter )
{
+ HANDLE hMonitoringThread = NULL;
+ unsigned int monitoringThreadID = 0;
SecureDesktopThreadParam* pParam = (SecureDesktopThreadParam*) lpThreadParameter;
+ SecureDesktopMonitoringThreadParam monitorParam;
+ BOOL bNewDesktopSet = FALSE;
+ HDESK hSecureDesk;
+ DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS;
- SetThreadDesktop (pParam->hDesk);
- SwitchDesktop (pParam->hDesk);
+ hSecureDesk = CreateDesktop (pParam->szDesktopName, NULL, NULL, 0, desktopAccess, NULL);
+ if (!hSecureDesk)
+ {
+ return 0;
+ }
+
+ StringCbCopy(SecureDesktopName, sizeof (SecureDesktopName), pParam->szDesktopName);
+ pParam->hDesk = hSecureDesk;
+
+ bNewDesktopSet = SetThreadDesktop (hSecureDesk);
+
+ if (bNewDesktopSet)
+ {
+ // call ImmDisableIME from imm32.dll to disable IME since it can create issue with secure desktop
+ // cf: https://keepass.info/help/kb/sec_desk.html#ime
+ HMODULE hImmDll = LoadLibraryEx (L"imm32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ if (hImmDll)
+ {
+ typedef BOOL (WINAPI *ImmDisableIME_t)(DWORD);
+ ImmDisableIME_t ImmDisableIME = (ImmDisableIME_t) GetProcAddress (hImmDll, "ImmDisableIME");
+ if (ImmDisableIME)
+ {
+ ImmDisableIME (0);
+ }
+ }
+
+ // wait for SwitchDesktop to succeed before using it for current thread
+ while (true)
+ {
+ if (SwitchDesktop (hSecureDesk))
+ {
+ break;
+ }
+ Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
+ }
+
+ // create the thread that will ensure that VeraCrypt secure desktop has always user input
+ // this is done only if the stop event is created successfully
+ HANDLE hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (hStopEvent)
+ {
+ monitorParam.szVCDesktopName = pParam->szDesktopName;
+ monitorParam.hVcDesktop = hSecureDesk;
+ monitorParam.hStopEvent = hStopEvent;
+ hMonitoringThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopMonitoringThread, (LPVOID) &monitorParam, 0, &monitoringThreadID);
+ }
+
+ pParam->retValue = DialogBoxParamW (pParam->hInstance, pParam->lpTemplateName,
+ NULL, pParam->lpDialogFunc, pParam->dwInitParam);
+
+ if (hMonitoringThread)
+ {
+ // notify the monitoring thread to stop
+ SetEvent(hStopEvent);
+
+ WaitForSingleObject (hMonitoringThread, INFINITE);
+ CloseHandle (hMonitoringThread);
+ }
- pParam->retValue = DialogBoxParamW (pParam->hInstance, pParam->lpTemplateName,
- NULL, pParam->lpDialogFunc, pParam->dwInitParam);
+ if (hStopEvent)
+ {
+ CloseHandle (hStopEvent);
+ }
+
+ pParam->bDlgDisplayed = TRUE;
+
+ // free imm32.dll handle
+ if (hImmDll)
+ {
+ FreeLibrary (hImmDll);
+ }
+ }
+ else
+ {
+ pParam->bDlgDisplayed = FALSE;
+ }
return 0;
}
@@ -12334,44 +14093,91 @@ INT_PTR SecureDesktopDialogBoxParam(
BOOL bSuccess = FALSE;
INT_PTR retValue = 0;
BOOL bEffectiveUseSecureDesktop = bCmdUseSecureDesktopValid? bCmdUseSecureDesktop : bUseSecureDesktop;
- if (bEffectiveUseSecureDesktop && GenerateRandomString (hWndParent, szDesktopName, 64))
+ if (bEffectiveUseSecureDesktop && !IsThreadInSecureDesktop(GetCurrentThreadId()))
{
- map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList;
- DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS;
- HDESK hSecureDesk;
-
- // get the initial list of ctfmon.exe processes before creating new desktop
- GetCtfMonProcessIdList (ctfmonBeforeList);
+ BOOL bRandomNameGenerated = FALSE;
+ HDESK existedDesk = NULL;
+ EnterCriticalSection (&csSecureDesktop);
+ bSecureDesktopOngoing = TRUE;
+ finally_do ({ bSecureDesktopOngoing = FALSE; LeaveCriticalSection (&csSecureDesktop); });
- hSecureDesk = CreateDesktop (szDesktopName, NULL, NULL, 0, desktopAccess, NULL);
- if (hSecureDesk)
+ // ensure that the randomly generated name is not already used
+ do
{
- HDESK hOriginalDesk = GetThreadDesktop (GetCurrentThreadId ());
+ if (existedDesk)
+ {
+ CloseDesktop (existedDesk);
+ existedDesk = NULL;
+ }
+ if (GenerateRandomString (hWndParent, szDesktopName, 64))
+ {
+ existedDesk = OpenDesktop (szDesktopName, 0, FALSE, GENERIC_READ);
+ if (!existedDesk)
+ {
+ bRandomNameGenerated = TRUE;
+ }
+ }
+ } while (existedDesk);
+
+ if (bRandomNameGenerated)
+ {
+ map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList;
+ HDESK hOriginalDesk = NULL;
SecureDesktopThreadParam param;
-
- param.hDesk = hSecureDesk;
+
+
+ // wait for the input desktop to be available before switching to
+ // secure desktop. Under Windows 10, the user session can be started
+ // in the background even before the user has authenticated and in this
+ // case, we wait for the user to be really authenticated before starting
+ // secure desktop mechanism
+
+ while (!(hOriginalDesk = OpenInputDesktop (0, TRUE, GENERIC_ALL)))
+ {
+ Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
+ }
+
+ // get the initial list of ctfmon.exe processes before creating new desktop
+ GetCtfMonProcessIdList (ctfmonBeforeList);
+
+ param.hDesk = NULL;
+ param.szDesktopName = szDesktopName;
param.hInstance = hInstance;
param.lpTemplateName = lpTemplateName;
param.lpDialogFunc = lpDialogFunc;
param.dwInitParam = dwInitParam;
param.retValue = 0;
+ param.bDlgDisplayed = FALSE;
- HANDLE hThread = ::CreateThread (NULL, 0, SecureDesktopThread, (LPVOID) &param, 0, NULL);
+ // use _beginthreadex instead of CreateThread because lpDialogFunc may be using the C runtime library
+ HANDLE hThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopThread, (LPVOID) &param, 0, NULL);
if (hThread)
{
WaitForSingleObject (hThread, INFINITE);
CloseHandle (hThread);
- SwitchDesktop (hOriginalDesk);
- SetThreadDesktop (hOriginalDesk);
+ if (param.bDlgDisplayed)
+ {
+ // dialog box was indeed displayed in Secure Desktop
+ retValue = param.retValue;
+ bSuccess = TRUE;
- retValue = param.retValue;
- bSuccess = TRUE;
- }
+ // switch back to the original desktop
+ while (!SwitchDesktop (hOriginalDesk))
+ {
+ Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
+ }
- CloseDesktop (hSecureDesk);
+ SetThreadDesktop (hOriginalDesk);
+ }
+
+ if (param.hDesk)
+ {
+ CloseDesktop (param.hDesk);
+ }
+ }
// get the new list of ctfmon.exe processes in order to find the ID of the
// ctfmon.exe instance that corresponds to the desktop we create so that
// we can kill it, otherwise it would remain running
@@ -12385,11 +14191,12 @@ INT_PTR SecureDesktopDialogBoxParam(
// Kill process
KillProcess (It->first);
}
}
- }
- burn (szDesktopName, sizeof (szDesktopName));
+ CloseDesktop(hOriginalDesk);
+ burn (szDesktopName, sizeof (szDesktopName));
+ }
}
if (!bSuccess)
{
@@ -12400,4 +14207,1779 @@ INT_PTR SecureDesktopDialogBoxParam(
return retValue;
}
#endif
+
+void GetInstallationPath (HWND hwndDlg, wchar_t* szInstallPath, DWORD cchSize, BOOL* pbInstallPathDetermined)
+{
+ HKEY hkey;
+ BOOL bInstallPathDetermined = FALSE;
+ wchar_t path[MAX_PATH+20];
+ ITEMIDLIST *itemList;
+
+ memset (szInstallPath, 0, cchSize * sizeof (wchar_t));
+
+ // Determine if VeraCrypt is already installed and try to determine its "Program Files" location
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt", 0, KEY_READ | KEY_WOW64_32KEY, &hkey) == ERROR_SUCCESS)
+ {
+ /* Default 'UninstallString' registry strings written by VeraCrypt:
+ ------------------------------------------------------------------------------------
+ 5.0+ "C:\Program Files\VeraCrypt\VeraCrypt Setup.exe" /u
+ */
+
+ wchar_t rv[MAX_PATH*4];
+ DWORD size = sizeof (rv);
+ if (RegQueryValueEx (hkey, L"UninstallString", 0, 0, (LPBYTE) &rv, &size) == ERROR_SUCCESS && wcsrchr (rv, L'/'))
+ {
+ size_t len = 0;
+
+ // Cut and paste the location (path) where VeraCrypt is installed to InstallationPath
+ if (rv[0] == L'"')
+ {
+ len = wcsrchr (rv, L'/') - rv - 2;
+ StringCchCopyNW (szInstallPath, cchSize, rv + 1, len);
+ szInstallPath [len] = 0;
+ bInstallPathDetermined = TRUE;
+
+ if (szInstallPath [wcslen (szInstallPath) - 1] != L'\\')
+ {
+ len = wcsrchr (szInstallPath, L'\\') - szInstallPath;
+ szInstallPath [len] = 0;
+ }
+ }
+
+ }
+ RegCloseKey (hkey);
+ }
+
+ if (!bInstallPathDetermined)
+ {
+ /* VeraCrypt is not installed or it wasn't possible to determine where it is installed. */
+
+ // Default "Program Files" path.
+ SHGetSpecialFolderLocation (hwndDlg, CSIDL_PROGRAM_FILES, &itemList);
+ SHGetPathFromIDList (itemList, path);
+
+ // Use a unified default installation path (registry redirection of %ProgramFiles% does not work if the installation path is user-selectable)
+ wstring s = path;
+ size_t p = s.find (L" (x86)");
+ if (p != wstring::npos)
+ {
+ s = s.substr (0, p);
+ if (_waccess (s.c_str(), 0) != -1)
+ StringCbCopyW (path, sizeof (path), s.c_str());
+ }
+
+ StringCbCatW (path, sizeof(path), L"\\VeraCrypt\\");
+ StringCbCopyW (szInstallPath, cchSize, path);
+ }
+
+ // Make sure the path ends with a backslash
+ if (szInstallPath [wcslen (szInstallPath) - 1] != L'\\')
+ {
+ StringCbCatW (szInstallPath, cchSize, L"\\");
+ }
+
+ if (pbInstallPathDetermined)
+ *pbInstallPathDetermined = bInstallPathDetermined;
+}
+
+BOOL GetSetupconfigLocation (wchar_t* path, DWORD cchSize)
+{
+ BOOL bResult = FALSE;
+
+ path[0] = 0;
+
+ wchar_t* pszUsersPath = NULL;
+ if (S_OK == SHGetKnownFolderPath (FOLDERID_UserProfiles, 0, NULL, &pszUsersPath))
+ {
+ StringCchPrintfW (path, cchSize, L"%s\\Default\\AppData\\Local\\Microsoft\\Windows\\WSUS\\", pszUsersPath);
+ CoTaskMemFree (pszUsersPath);
+ bResult = TRUE;
+ }
+
+ if (!bResult && CurrentOSMajor >= 10)
+ {
+ wchar_t szSys32Path[MAX_PATH];
+ if (!GetSystemDirectory (szSys32Path, ARRAYSIZE (szSys32Path)))
+ {
+ StringCchCopy(szSys32Path, ARRAYSIZE (szSys32Path), L"C:\\Windows\\System32");
+ }
+ StringCchPrintfW (path, cchSize, L"%c:\\Users\\Default\\AppData\\Local\\Microsoft\\Windows\\WSUS\\", szSys32Path[0]);
+ bResult = TRUE;
+ }
+
+ return bResult;
+}
+
+BOOL BufferHasPattern (const unsigned char* buffer, size_t bufferLen, const void* pattern, size_t patternLen)
+{
+ BOOL bRet = FALSE;
+ if (patternLen <= bufferLen)
+ {
+ size_t i;
+ for (i = 0; i <= (bufferLen - patternLen); ++i)
+ {
+ if (memcmp (&buffer[i], pattern, patternLen) == 0)
+ {
+ bRet = TRUE;
+ break;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+/* Implementation borrowed from KeePassXC source code (https://github.com/keepassxreboot/keepassxc/blob/2.7.8/src/core/Bootstrap.cpp#L121)
+ *
+ * Reduce current user acess rights for this process to the minimum in order to forbid non-admin users from reading the process memory.
+ * Restrict access to changing DACL's after the process is started. This prevents the creator of veracrypt process from simply adding
+ * the permission to read memory back to the DACL list.
+ */
+BOOL ActivateMemoryProtection()
+{
+ BOOL bSuccess = FALSE;
+
+ // Process token and user
+ HANDLE hToken = NULL;
+ PTOKEN_USER pTokenUser = NULL;
+ DWORD cbBufferSize = 0;
+ PSID pOwnerRightsSid = NULL;
+ DWORD pOwnerRightsSidSize = SECURITY_MAX_SID_SIZE;
+
+ // Access control list
+ PACL pACL = NULL;
+ DWORD cbACL = 0;
+
+ // Acces mask
+ DWORD dwAccessMask = SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE; // same as protected process
+
+ if (MemoryProtectionActivated)
+ return TRUE;
+
+ if (IsAdmin ())
+ {
+ // if we are running elevated, we allow CreateProcessXXX calls alongside PROCESS_DUP_HANDLE and PROCESS_QUERY_INFORMATION in order to be able
+ // to implement secure way to open URLs (cf RunAsDesktopUser)
+ // we are still protecting against memory access from non-admon processes
+ dwAccessMask |= PROCESS_CREATE_PROCESS | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION;
+ }
+
+ // Open the access token associated with the calling process
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
+ goto Cleanup;
+ }
+
+ // Retrieve the token information in a TOKEN_USER structure
+ GetTokenInformation(hToken, TokenUser, NULL, 0, &cbBufferSize);
+
+ pTokenUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbBufferSize);
+ if (pTokenUser == NULL) {
+ goto Cleanup;
+ }
+
+ if (!GetTokenInformation(hToken, TokenUser, pTokenUser, cbBufferSize, &cbBufferSize)) {
+ goto Cleanup;
+ }
+
+ if (!IsValidSid(pTokenUser->User.Sid)) {
+ goto Cleanup;
+ }
+
+ // Retrieve CreaterOwnerRights SID
+ pOwnerRightsSid = (PSID) HeapAlloc(GetProcessHeap(), 0, pOwnerRightsSidSize);
+ if (pOwnerRightsSid == NULL) {
+ goto Cleanup;
+ }
+
+ if (!CreateWellKnownSid(WinCreatorOwnerRightsSid, NULL, pOwnerRightsSid, &pOwnerRightsSidSize)) {
+ goto Cleanup;
+ }
+
+ // Calculate the amount of memory that must be allocated for the DACL
+ cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid)
+ + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pOwnerRightsSid);
+
+ // Create and initialize an ACL
+ pACL = (PACL) HeapAlloc(GetProcessHeap(), 0, cbACL);
+ if (pACL == NULL) {
+ goto Cleanup;
+ }
+
+ if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) {
+ goto Cleanup;
+ }
+
+ // Add allowed access control entries, everything else is denied
+ if (!AddAccessAllowedAce(
+ pACL,
+ ACL_REVISION,
+ dwAccessMask,
+ pTokenUser->User.Sid // pointer to the trustee's SID
+ )) {
+ goto Cleanup;
+ }
+
+ // Explicitly set "Process Owner" rights to Read Only. The default is Full Control.
+ if (!AddAccessAllowedAce(
+ pACL,
+ ACL_REVISION,
+ READ_CONTROL,
+ pOwnerRightsSid
+ )) {
+ goto Cleanup;
+ }
+
+
+ // Set discretionary access control list
+ bSuccess = (ERROR_SUCCESS == SetSecurityInfo(GetCurrentProcess(), // object handle
+ SE_KERNEL_OBJECT, // type of object
+ DACL_SECURITY_INFORMATION, // change only the objects DACL
+ NULL,
+ NULL, // do not change owner or group
+ pACL, // DACL specified
+ NULL // do not change SACL
+ ))? TRUE: FALSE;
+
+ if (bSuccess)
+ MemoryProtectionActivated = TRUE;
+
+Cleanup:
+
+ if (pACL != NULL) {
+ HeapFree(GetProcessHeap(), 0, pACL);
+ }
+ if (pOwnerRightsSid != NULL) {
+ HeapFree(GetProcessHeap(), 0, pOwnerRightsSid);
+ }
+ if (pTokenUser != NULL) {
+ HeapFree(GetProcessHeap(), 0, pTokenUser);
+ }
+ if (hToken != NULL) {
+ CloseHandle(hToken);
+ }
+
+ return bSuccess;
+}
+
+// define missing structures Windows 8
+#if (_WIN32_WINNT < 0x0602)
+
+typedef struct _PROCESS_MITIGATION_ASLR_POLICY {
+ union {
+ DWORD Flags;
+ struct {
+ DWORD EnableBottomUpRandomization : 1;
+ DWORD EnableForceRelocateImages : 1;
+ DWORD EnableHighEntropy : 1;
+ DWORD DisallowStrippedImages : 1;
+ DWORD ReservedFlags : 28;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+} PROCESS_MITIGATION_ASLR_POLICY, *PPROCESS_MITIGATION_ASLR_POLICY;
+
+typedef struct _PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY {
+ union {
+ DWORD Flags;
+ struct {
+ DWORD DisableExtensionPoints : 1;
+ DWORD ReservedFlags : 31;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+} PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY, *PPROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY;
+
+typedef struct _PROCESS_MITIGATION_DYNAMIC_CODE_POLICY {
+ union {
+ DWORD Flags;
+ struct {
+ DWORD ProhibitDynamicCode : 1;
+ DWORD AllowThreadOptOut : 1;
+ DWORD AllowRemoteDowngrade : 1;
+ DWORD AuditProhibitDynamicCode : 1;
+ DWORD ReservedFlags : 28;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+} PROCESS_MITIGATION_DYNAMIC_CODE_POLICY, *PPROCESS_MITIGATION_DYNAMIC_CODE_POLICY;
+
+typedef enum _PROCESS_MITIGATION_POLICY {
+ ProcessDEPPolicy,
+ ProcessASLRPolicy,
+ ProcessDynamicCodePolicy,
+ ProcessStrictHandleCheckPolicy,
+ ProcessSystemCallDisablePolicy,
+ ProcessMitigationOptionsMask,
+ ProcessExtensionPointDisablePolicy,
+ ProcessControlFlowGuardPolicy,
+ ProcessSignaturePolicy,
+ ProcessFontDisablePolicy,
+ ProcessImageLoadPolicy,
+ ProcessSystemCallFilterPolicy,
+ ProcessPayloadRestrictionPolicy,
+ ProcessChildProcessPolicy,
+ ProcessSideChannelIsolationPolicy,
+ ProcessUserShadowStackPolicy,
+ MaxProcessMitigationPolicy
+} PROCESS_MITIGATION_POLICY, *PPROCESS_MITIGATION_POLICY;
+
+#endif
+
+void ActivateProcessMitigations()
+{
+ // we load the function pointer of SetProcessMitigationPolicy dynamically because we are building with Windows 7 SDK that does not have the definition of this function
+ typedef BOOL (WINAPI *SetProcessMitigationPolicyFunc) (PROCESS_MITIGATION_POLICY MitigationPolicy, PVOID lpBuffer, SIZE_T dwLength);
+ SetProcessMitigationPolicyFunc SetProcessMitigationPolicyPtr = (SetProcessMitigationPolicyFunc) GetProcAddress (GetModuleHandle (L"kernel32.dll"), "SetProcessMitigationPolicy");
+ if (SetProcessMitigationPolicyPtr)
+ {
+ PROCESS_MITIGATION_ASLR_POLICY aslrPolicy = { 0 };
+ PROCESS_MITIGATION_DYNAMIC_CODE_POLICY dynCodePolicy = { 0 };
+ PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY extensionPointDisablePolicy = { 0 };
+
+ aslrPolicy.EnableBottomUpRandomization = TRUE;
+ aslrPolicy.EnableForceRelocateImages = TRUE;
+ aslrPolicy.EnableHighEntropy = TRUE;
+
+ dynCodePolicy.ProhibitDynamicCode = TRUE;
+
+ extensionPointDisablePolicy.DisableExtensionPoints = TRUE;
+
+ SetProcessMitigationPolicyPtr (ProcessASLRPolicy, &aslrPolicy, sizeof (aslrPolicy));
+ SetProcessMitigationPolicyPtr (ProcessDynamicCodePolicy, &dynCodePolicy, sizeof (dynCodePolicy));
+ SetProcessMitigationPolicyPtr (ProcessExtensionPointDisablePolicy, &extensionPointDisablePolicy, sizeof (extensionPointDisablePolicy));
+ }
+}
+
+// Based on sample code from:
+// https://blogs.msdn.microsoft.com/aaron_margosis/2009/06/06/faq-how-do-i-start-a-program-as-the-desktop-user-from-an-elevated-app/
+// start a program non-elevated as the desktop user from an elevated app
+
+static bool RunAsDesktopUser(
+ __in const wchar_t * szApp,
+ __in wchar_t * szCmdLine)
+{
+ HANDLE hThreadToken = NULL, hShellProcess = NULL, hShellProcessToken = NULL, hPrimaryToken = NULL;
+ HWND hwnd = NULL;
+ DWORD dwPID = 0;
+ BOOL ret;
+ DWORD dwLastErr;
+ STARTUPINFOW si;
+ PROCESS_INFORMATION pi;
+ bool retval = false;
+ SecureZeroMemory(&si, sizeof(si));
+ SecureZeroMemory(&pi, sizeof(pi));
+ si.cb = sizeof(si);
+
+ if (!ImpersonateSelf (SecurityImpersonation))
+ {
+ return false;
+ }
+
+ if (!OpenThreadToken (GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, TRUE, &hThreadToken))
+ {
+ return false;
+ }
+ else
+ {
+ TOKEN_PRIVILEGES tkp;
+ tkp.PrivilegeCount = 1;
+ LookupPrivilegeValueW(NULL, SE_INCREASE_QUOTA_NAME, &tkp.Privileges[0].Luid);
+ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (!SetThreadToken(NULL, NULL))
+ {
+ goto cleanup;
+ }
+
+ AdjustTokenPrivileges(hThreadToken, FALSE, &tkp, 0, NULL, NULL);
+ dwLastErr = GetLastError();
+ if (ERROR_SUCCESS != dwLastErr)
+ {
+ goto cleanup;
+ }
+ }
+
+ // From this point down, we have handles to close, so make sure to clean up.
+
+ // Get an HWND representing the desktop shell.
+ // CAVEATS: This will fail if the shell is not running (crashed or terminated), or the default shell has been
+ // replaced with a custom shell. This also won't return what you probably want if Explorer has been terminated and
+ // restarted elevated.
+ hwnd = GetShellWindow();
+ if (NULL == hwnd)
+ {
+ dwLastErr = GetLastError();
+ goto cleanup;
+ }
+
+ // Get the PID of the desktop shell process.
+ GetWindowThreadProcessId(hwnd, &dwPID);
+ if (0 == dwPID)
+ {
+ dwLastErr = GetLastError();
+ goto cleanup;
+ }
+
+ // Open the desktop shell process in order to query it (get the token)
+ hShellProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID);
+ if (!hShellProcess)
+ {
+ dwLastErr = GetLastError();
+ goto cleanup;
+ }
+
+ // Get the process token of the desktop shell.
+ ret = OpenProcessToken(hShellProcess, TOKEN_DUPLICATE, &hShellProcessToken);
+ if (!ret)
+ {
+ dwLastErr = GetLastError();
+ goto cleanup;
+ }
+
+ // Duplicate the shell's process token to get a primary token.
+ // Based on experimentation, this is the minimal set of rights required for CreateProcessWithTokenW (contrary to current documentation).
+ const DWORD dwTokenRights = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID;
+ ret = DuplicateTokenEx(hShellProcessToken, dwTokenRights, NULL, SecurityImpersonation, TokenPrimary, &hPrimaryToken);
+ if (!ret)
+ {
+ dwLastErr = GetLastError();
+ goto cleanup;
+ }
+
+ // Start the target process with the new token.
+ ret = CreateProcessWithTokenW(
+ hPrimaryToken,
+ 0,
+ szApp,
+ szCmdLine,
+ 0,
+ NULL,
+ NULL,
+ &si,
+ &pi);
+ if (!ret)
+ {
+ dwLastErr = GetLastError();
+ goto cleanup;
+ }
+
+ // Make sure to close HANDLEs return in the PROCESS_INFORMATION.
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+
+ retval = true;
+
+cleanup:
+ // Clean up resources
+ if (hShellProcessToken) CloseHandle(hShellProcessToken);
+ if (hPrimaryToken) CloseHandle(hPrimaryToken);
+ if (hShellProcess) CloseHandle(hShellProcess);
+ if (hThreadToken) CloseHandle(hThreadToken);
+
+ if (!RevertToSelf())
+ return false;
+
+ if (!retval)
+ SetLastError (dwLastErr);
+ return retval;
+}
+
+// This function checks if the process is running with elevated privileges or not
+BOOL IsElevated()
+{
+ DWORD dwSize = 0;
+ HANDLE hToken = NULL;
+ TOKEN_ELEVATION tokenInformation;
+ BOOL bReturn = FALSE;
+
+ if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
+ {
+ if(GetTokenInformation(hToken, TokenElevation, &tokenInformation, sizeof(TOKEN_ELEVATION), &dwSize))
+ {
+ if (tokenInformation.TokenIsElevated)
+ bReturn = TRUE;
+ }
+
+ CloseHandle(hToken);
+ }
+ return bReturn;
+}
+
+// Based on code from:
+// https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/winui/shell/appplatform/ExecInExplorer/ExecInExplorer.cpp
+HRESULT GetShellViewForDesktop(REFIID riid, void **ppv)
+{
+ *ppv = NULL;
+
+ IShellWindows *psw;
+ HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&psw));
+ if (SUCCEEDED(hr))
+ {
+ HWND hwnd;
+ IDispatch* pdisp;
+ VARIANT vEmpty = {}; // VT_EMPTY
+ if (S_OK == psw->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, (long*)&hwnd, SWFO_NEEDDISPATCH, &pdisp))
+ {
+ IShellBrowser *psb;
+ hr = IUnknown_QueryService(pdisp, SID_STopLevelBrowser, IID_PPV_ARGS(&psb));
+ if (SUCCEEDED(hr))
+ {
+ IShellView *psv;
+ hr = psb->QueryActiveShellView(&psv);
+ if (SUCCEEDED(hr))
+ {
+ hr = psv->QueryInterface(riid, ppv);
+ psv->Release();
+ }
+ psb->Release();
+ }
+ pdisp->Release();
+ }
+ else
+ {
+ hr = E_FAIL;
+ }
+ psw->Release();
+ }
+ return hr;
+}
+
+HRESULT GetShellDispatchFromView(IShellView *psv, REFIID riid, void **ppv)
+{
+ *ppv = NULL;
+
+ IDispatch *pdispBackground;
+ HRESULT hr = psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&pdispBackground));
+ if (SUCCEEDED(hr))
+ {
+ IShellFolderViewDual *psfvd;
+ hr = pdispBackground->QueryInterface(IID_PPV_ARGS(&psfvd));
+ if (SUCCEEDED(hr))
+ {
+ IDispatch *pdisp;
+ hr = psfvd->get_Application(&pdisp);
+ if (SUCCEEDED(hr))
+ {
+ hr = pdisp->QueryInterface(riid, ppv);
+ pdisp->Release();
+ }
+ psfvd->Release();
+ }
+ pdispBackground->Release();
+ }
+ return hr;
+}
+
+HRESULT ShellExecInExplorerProcess(PCWSTR pszFile)
+{
+ IShellView *psv;
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ HRESULT hr = GetShellViewForDesktop(IID_PPV_ARGS(&psv));
+ if (SUCCEEDED(hr))
+ {
+ IShellDispatch2 *psd;
+ hr = GetShellDispatchFromView(psv, IID_PPV_ARGS(&psd));
+ if (SUCCEEDED(hr))
+ {
+ BSTR bstrFile = SysAllocString(pszFile);
+ hr = bstrFile ? S_OK : E_OUTOFMEMORY;
+ if (SUCCEEDED(hr))
+ {
+ VARIANT vtEmpty = {}; // VT_EMPTY
+ hr = psd->ShellExecuteW(bstrFile, vtEmpty, vtEmpty, vtEmpty, vtEmpty);
+ SysFreeString(bstrFile);
+ }
+ psd->Release();
+ }
+ psv->Release();
+ }
+ CoUninitialize();
+ return hr;
+}
+
+// This function always loads a URL in a non-privileged mode
+// If current process has admin privileges, we execute the command "rundll32 url.dll,FileProtocolHandler URL" as non-elevated
+// Use this security mechanism only starting from Windows Vista and only if we can get the window of the Shell's desktop since
+// we rely on the Shell to be already running in a non-privileges mode. If the Shell is not running or if it has been modified,
+// then we can't protect the user in such non standard environment
+void SafeOpenURL (LPCWSTR szUrl)
+{
+ BOOL bFallback = TRUE;
+ if (IsUacSupported() && IsAdmin () && IsElevated() && GetShellWindow())
+ {
+ WCHAR szRunDllPath[TC_MAX_PATH];
+ WCHAR szUrlDllPath[TC_MAX_PATH];
+ WCHAR szSystemPath[TC_MAX_PATH];
+ LPWSTR szCommandLine = new WCHAR[1024];
+
+ if (!GetSystemDirectory(szSystemPath, MAX_PATH))
+ StringCbCopyW(szSystemPath, sizeof(szSystemPath), L"C:\\Windows\\System32");
+
+ StringCbPrintfW(szRunDllPath, sizeof(szRunDllPath), L"%s\\%s", szSystemPath, L"rundll32.exe");
+ StringCbPrintfW(szUrlDllPath, sizeof(szUrlDllPath), L"%s\\%s", szSystemPath, L"url.dll");
+ StringCchPrintfW(szCommandLine, 1024, L"%s %s,FileProtocolHandler %s", szRunDllPath, szUrlDllPath, szUrl);
+
+ if (RunAsDesktopUser (NULL, szCommandLine))
+ {
+ bFallback = FALSE;
+ }
+ else
+ {
+ // fallback to IShellDispatch2::ShellExecuteW
+ if (SUCCEEDED(ShellExecInExplorerProcess(szUrl)))
+ {
+ bFallback = FALSE;
+ }
+ }
+
+ delete [] szCommandLine;
+ }
+
+ if (bFallback)
+ {
+ ShellExecuteW (NULL, L"open", szUrl, NULL, NULL, SW_SHOWNORMAL);
+ }
+}
+
+#if !defined(SETUP)
+
+#define RtlGenRandom SystemFunction036
+extern "C" BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
+
+void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed)
+{
+ LARGE_INTEGER iSeed;
+ SYSTEMTIME sysTime;
+ uint8 digest[WHIRLPOOL_DIGESTSIZE];
+ WHIRLPOOL_CTX tctx;
+ size_t count;
+
+ while (cbRandSeed)
+ {
+ WHIRLPOOL_init (&tctx);
+ // we hash current content of digest buffer which is uninitialized the first time
+ WHIRLPOOL_add (digest, WHIRLPOOL_DIGESTSIZE, &tctx);
+
+ // we use various time information as source of entropy
+ GetSystemTime (&sysTime);
+ WHIRLPOOL_add ((unsigned char *) &sysTime, sizeof(sysTime), &tctx);
+ if (QueryPerformanceCounter (&iSeed))
+ WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx);
+ if (QueryPerformanceFrequency (&iSeed))
+ WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx);
+
+ /* use Windows random generator as entropy source */
+ if (RtlGenRandom (digest, sizeof (digest)))
+ WHIRLPOOL_add (digest, sizeof(digest), &tctx);
+
+ /* use JitterEntropy library to get good quality random bytes based on CPU timing jitter */
+ if (0 == jent_entropy_init ())
+ {
+ struct rand_data *ec = jent_entropy_collector_alloc (1, 0);
+ if (ec)
+ {
+ ssize_t rndLen = jent_read_entropy (ec, (char*) digest, sizeof (digest));
+ if (rndLen > 0)
+ WHIRLPOOL_add (digest, (unsigned int) rndLen, &tctx);
+ jent_entropy_collector_free (ec);
+ }
+ }
+
+ // use RDSEED or RDRAND from CPU as source of entropy if enabled
+ if ( IsCpuRngEnabled() &&
+ ( (HasRDSEED() && RDSEED_getBytes (digest, sizeof (digest)))
+ || (HasRDRAND() && RDRAND_getBytes (digest, sizeof (digest)))
+ ))
+ {
+ WHIRLPOOL_add (digest, sizeof(digest), &tctx);
+ }
+ WHIRLPOOL_finalize (&tctx, digest);
+
+ count = VC_MIN (cbRandSeed, sizeof (digest));
+
+ // copy digest value to seed buffer
+ memcpy (pbRandSeed, digest, count);
+ cbRandSeed -= count;
+ pbRandSeed += count;
+ }
+
+ FAST_ERASE64 (digest, sizeof (digest));
+ FAST_ERASE64 (&iSeed.QuadPart, 8);
+ burn (&sysTime, sizeof(sysTime));
+ burn (&tctx, sizeof(tctx));
+}
+#endif
+
+/*
+ * GetBitLockerEncryptionStatus: retuns the BitLocker encryption status of a given drive.
+ */
+
+typedef enum BitLockerProtectionState
+{
+ BL_State_FullyDecrypted = 0,
+ BL_State_FullyEncrypted = 1,
+ BL_State_EncryptionInProgress = 2,
+ BL_State_DecryptionInProgress = 3,
+ BL_State_EncryptionSuspended = 4,
+ BL_State_DecryptionSuspended = 5,
+ BL_State_FullyEncryptedWipeInProgress = 6,
+ BL_State_FullyEncryptedWipeSuspended = 7
+} BitLockerProtectionState;
+
+typedef HRESULT (WINAPI *SHCreateItemFromParsingNameFn)(
+ PCWSTR pszPath,
+ IBindCtx* pbc,
+ REFIID riid,
+ void** ppv
+);
+
+typedef HRESULT (WINAPI *PSGetPropertyKeyFromNameFn)(
+ _In_ PCWSTR pszName,
+ _Out_ PROPERTYKEY* ppropkey);
+
+
+/*
+ Code derived from https://stackoverflow.com/questions/23841973/how-to-tell-if-drive-is-bitlocker-encrypted-without-admin-privilege/47192128#47192128
+*/
+BitLockerEncryptionStatus GetBitLockerEncryptionStatus(WCHAR driveLetter)
+{
+ HRESULT hr;
+ BitLockerEncryptionStatus blStatus = BL_Status_Unknown;
+ wchar_t szDllPath[MAX_PATH] = { 0 };
+ HMODULE hPropsys = NULL;
+
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+
+ if (GetSystemDirectory(szDllPath, MAX_PATH))
+ StringCchCatW(szDllPath, MAX_PATH, L"\\Propsys.dll");
+ else
+ StringCchCopyW(szDllPath, MAX_PATH, L"C:\\Windows\\System32\\Propsys.dll");
+
+ hPropsys = LoadLibrary(szDllPath);
+ if (hPropsys)
+ {
+ PSGetPropertyKeyFromNameFn PSGetPropertyKeyFromNamePtr = (PSGetPropertyKeyFromNameFn)GetProcAddress(hPropsys, "PSGetPropertyKeyFromName");
+ if (PSGetPropertyKeyFromNamePtr)
+ {
+ WCHAR parsingName[3] = {driveLetter, L':', 0};
+ IShellItem2* drive = NULL;
+ hr = SHCreateItemFromParsingName(parsingName, NULL, IID_PPV_ARGS(&drive));
+ if (SUCCEEDED(hr)) {
+ PROPERTYKEY pKey;
+ hr = PSGetPropertyKeyFromNamePtr(L"System.Volume.BitLockerProtection", &pKey);
+ if (SUCCEEDED(hr)) {
+ PROPVARIANT prop;
+ PropVariantInit(&prop);
+ hr = drive->GetProperty(pKey, &prop);
+ if (SUCCEEDED(hr)) {
+ int status = prop.intVal;
+ if (status == BL_State_FullyEncrypted || status == BL_State_DecryptionInProgress || status == BL_State_DecryptionSuspended)
+ blStatus = BL_Status_Protected;
+ else
+ blStatus = BL_Status_Unprotected;
+ }
+ }
+ }
+ if (drive)
+ drive->Release();
+ }
+
+ FreeLibrary(hPropsys);
+ }
+
+
+ CoUninitialize();
+ return blStatus;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+static CLIPFORMAT g_supportedFormats[] = { CF_UNICODETEXT, CF_TEXT, CF_OEMTEXT};
+
+//*************************************************************
+// GenericDropTarget
+//*************************************************************
+GenericDropTarget::GenericDropTarget(CLIPFORMAT* pFormats, size_t count)
+ : m_DropTargetWnd(NULL),
+ m_dwRefCount(1),
+ m_KeyState(0L),
+ m_Data(NULL)
+{
+ m_DropPoint.x = 0;
+ m_DropPoint.y = 0;
+
+ if (pFormats && count)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ m_SupportedFormat.push_back (pFormats[i]);
+ }
+ }
+}
+
+GenericDropTarget::~GenericDropTarget()
+{
+}
+
+HRESULT GenericDropTarget::QueryInterface(REFIID iid, void **ppvObject)
+{
+ if(ppvObject == NULL)
+ return E_FAIL;
+
+ if (iid == IID_IUnknown)
+ {
+ AddRef();
+ (*ppvObject) = this;
+ return S_OK;
+ }
+ // compare guids fast and dirty
+ if (IsEqualGUID (iid, IID_IDropTarget))
+ {
+ AddRef();
+ (*ppvObject) = this;
+ return S_OK;
+ }
+
+ return E_FAIL;
+}
+
+ULONG GenericDropTarget::AddRef(void)
+{
+ return (ULONG) InterlockedIncrement (&m_dwRefCount);
+}
+
+ULONG GenericDropTarget::Release(void)
+{
+ if (InterlockedDecrement (&m_dwRefCount) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ else
+ return (ULONG) m_dwRefCount;
+}
+
+//*************************************************************
+// Register
+// Called by whom implements us so we can serve
+//*************************************************************
+BOOL GenericDropTarget::Register(HWND hWnd)
+{
+ if(NULL == hWnd)
+ return FALSE;
+
+ OleInitialize(NULL);
+
+ // required: these MUST be strong locked
+ CoLockObjectExternal(this, TRUE, 0);
+
+ // this is ok, we have it
+ DWORD hRes = ::RegisterDragDrop(hWnd, this);
+ if(SUCCEEDED(hRes))
+ {
+ // keep
+ m_DropTargetWnd = hWnd;
+ return TRUE;
+ }
+
+ // unlock
+ CoLockObjectExternal(this, FALSE, 0);
+
+ // bye bye COM
+ OleUninitialize();
+
+ // wont accept data now
+ return FALSE;
+}
+
+//*************************************************************
+// Revoke
+// Unregister us as a target
+//*************************************************************
+void GenericDropTarget::Revoke()
+{
+ if(NULL == m_DropTargetWnd)
+ return;
+
+ RevokeDragDrop(m_DropTargetWnd);
+
+ m_DropTargetWnd = NULL;
+
+ // unlock
+ CoLockObjectExternal(this, FALSE, 0);
+
+ // bye bye COM
+ OleUninitialize();
+}
+
+//*************************************************************
+// DragEnter
+//*************************************************************
+HRESULT GenericDropTarget::DragEnter(struct IDataObject *pDataObject, unsigned long grfKeyState, struct _POINTL pMouse, unsigned long * pDropEffect)
+{
+ if(pDataObject == NULL)
+ return E_FAIL; // must have data
+
+ // keep point
+ m_DropPoint.x = pMouse.x;
+ m_DropPoint.y = pMouse.y;
+
+ // keep key
+ m_KeyState = grfKeyState;
+
+ // call top
+ *pDropEffect = GotEnter();
+
+ return S_OK;
+}
+
+//*************************************************************
+// DragOver
+// Coming over!
+//*************************************************************
+HRESULT GenericDropTarget::DragOver(unsigned long grfKeyState, struct _POINTL pMouse, unsigned long *pEffect)
+{
+ // keep point
+ m_DropPoint.x = pMouse.x;
+ m_DropPoint.y = pMouse.y;
+
+ // keep key
+ m_KeyState = grfKeyState;
+
+ // call top
+ *pEffect = GotDrag();
+
+ return S_OK;
+}
+
+//*************************************************************
+// DragLeave
+// Free! At last!
+//*************************************************************
+HRESULT GenericDropTarget::DragLeave(void)
+{
+ GotLeave();
+
+ return S_OK;
+}
+
+//*************************************************************
+// Drop
+//*************************************************************
+HRESULT GenericDropTarget::Drop(struct IDataObject *pDataObject, unsigned long grfKeyState, struct _POINTL pMouse, unsigned long *pdwEffect)
+{
+ if(NULL == pDataObject)
+ return E_FAIL;
+
+ // do final effect
+ *pdwEffect = DROPEFFECT_COPY;
+
+ // Check the data
+ FORMATETC iFormat;
+ ZeroMemory(&iFormat, sizeof(FORMATETC));
+
+ STGMEDIUM iMedium;
+ ZeroMemory(&iMedium, sizeof(STGMEDIUM));
+
+ HRESULT hRes;
+ size_t i;
+ bool bFound = false;
+
+ for (i = 0; i < m_SupportedFormat.size(); i++)
+ {
+ // data
+ iFormat.cfFormat = m_SupportedFormat[i];
+ iFormat.dwAspect = DVASPECT_CONTENT;
+ iFormat.lindex = -1; // give me all baby
+ iFormat.tymed = TYMED_HGLOBAL; // want mem
+
+ hRes = pDataObject->GetData(&iFormat, &iMedium);
+ if(SUCCEEDED(hRes))
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ if (!bFound)
+ return hRes;
+
+ // we have the data, get it
+ BYTE *iMem = (BYTE *)::GlobalLock(iMedium.hGlobal);
+
+ // pass over
+ m_Data = iMem;
+
+ // keep point
+ m_DropPoint.x = pMouse.x;
+ m_DropPoint.y = pMouse.y;
+
+ // keep key
+ m_KeyState = grfKeyState;
+
+ // notify parent of drop
+ GotDrop(m_SupportedFormat[i]);
+
+ ::GlobalUnlock(iMedium.hGlobal);
+
+ // free data
+ if(iMedium.pUnkForRelease != NULL)
+ iMedium.pUnkForRelease->Release();
+
+ return S_OK;
+}
+
+//*************************************************************
+// Stub implementation
+// Real stuff would be done in parent
+//*************************************************************
+void GenericDropTarget::GotDrop(CLIPFORMAT format)
+{
+}
+
+DWORD GenericDropTarget::GotDrag(void)
+{
+ return DROPEFFECT_LINK;
+}
+
+void GenericDropTarget::GotLeave(void)
+{
+}
+
+DWORD GenericDropTarget::GotEnter(void)
+{
+ return DROPEFFECT_LINK;
+}
+
+// ************************************************************
+// PasswordEditDropTarget
+// Constructor
+// ************************************************************
+PasswordEditDropTarget::PasswordEditDropTarget() : GenericDropTarget (g_supportedFormats, ARRAYSIZE (g_supportedFormats))
+{
+
+}
+
+// ************************************************************
+// GotDrag
+
+// ************************************************************
+DWORD PasswordEditDropTarget::GotDrag(void)
+{
+ return GotEnter();
+}
+
+// ************************************************************
+// GotLeave
+// ************************************************************
+void PasswordEditDropTarget::GotLeave(void)
+{
+}
+
+// ************************************************************
+// GotEnter
+// ************************************************************
+DWORD PasswordEditDropTarget::GotEnter(void)
+{
+ TCHAR szClassName[64];
+ DWORD_PTR dwStyles;
+ int maxLen;
+ HWND hChild = WindowFromPoint (m_DropPoint);
+ // check that we are on password edit control (we use maximum length to correctly identify password fields since they don't always have ES_PASSWORD style (if the the user checked show password)
+ if (hChild && GetClassName (hChild, szClassName, ARRAYSIZE (szClassName)) && (0 == _tcsicmp (szClassName, _T("EDIT")))
+ && (dwStyles = GetWindowLongPtr (hChild, GWL_STYLE)) && !(dwStyles & ES_NUMBER)
+ && (maxLen = (int) SendMessage (hChild, EM_GETLIMITTEXT, 0, 0)) && (maxLen == MAX_PASSWORD || maxLen == MAX_LEGACY_PASSWORD)
+ )
+ {
+ return DROPEFFECT_COPY;
+ }
+
+ return DROPEFFECT_LINK;
+}
+
+// ************************************************************
+// GotDrop
+// Called if we have a drop text drop here.
+//
+// ************************************************************
+void PasswordEditDropTarget::GotDrop(CLIPFORMAT format)
+{
+ // value contains the material itself
+ if(m_Data)
+ {
+ TCHAR szClassName[64];
+ DWORD_PTR dwStyles;
+ int maxLen;
+ HWND hChild = WindowFromPoint (m_DropPoint);
+ if (hChild && GetClassName (hChild, szClassName, ARRAYSIZE (szClassName)) && (0 == _tcsicmp (szClassName, _T("EDIT")))
+ && (dwStyles = GetWindowLongPtr (hChild, GWL_STYLE)) && !(dwStyles & ES_NUMBER)
+ && (maxLen = (int) SendMessage (hChild, EM_GETLIMITTEXT, 0, 0)) && (maxLen == MAX_PASSWORD || maxLen == MAX_LEGACY_PASSWORD)
+ )
+ {
+ WCHAR* wszText;
+ int wlen;
+ bool bFree = false;
+ // get the text
+ if (format == CF_UNICODETEXT)
+ {
+ wszText = (WCHAR *)m_Data;
+ }
+ else
+ {
+ char *iText = (char *)m_Data;
+ wlen = MultiByteToWideChar ((format == CF_OEMTEXT)? CP_OEMCP : CP_ACP, 0, iText, -1, NULL, 0);
+ wszText = new WCHAR[wlen];
+ if (wszText)
+ {
+ wlen = MultiByteToWideChar (CP_ACP, 0, iText, -1, wszText, wlen);
+ bFree = true;
+ }
+ }
+
+ WCHAR* pchData = wszText;
+ int txtlen = 0;
+ bool bTruncated = false;
+
+ // remove any appended \r or \n
+ while (*pchData)
+ {
+ if (*pchData == '\r' || *pchData == '\n')
+ break;
+ else
+ {
+ txtlen++;
+ pchData++;
+ }
+ }
+
+ if (txtlen)
+ {
+ if (txtlen > maxLen)
+ {
+ bTruncated = true;
+ txtlen = maxLen;
+ }
+
+ SetFocus (hChild);
+
+ wszText[txtlen] = 0;
+ SetWindowText(hChild , wszText);
+
+ if (bTruncated)
+ {
+ EDITBALLOONTIP ebt;
+ DWORD dwTextSize = (DWORD) wcslen (GetString ("PASSWORD_PASTED_TRUNCATED")) + 16;
+ WCHAR* szErrorText = (WCHAR*) malloc (dwTextSize * sizeof (WCHAR));
+
+ StringCchPrintf (szErrorText, dwTextSize, GetString ("PASSWORD_PASTED_TRUNCATED"), maxLen);
+
+ ebt.cbStruct = sizeof( EDITBALLOONTIP );
+ ebt.pszText = szErrorText;
+ ebt.pszTitle = lpszTitle;
+ ebt.ttiIcon = TTI_WARNING_LARGE; // tooltip warning icon
+
+ SendMessage(hChild, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt);
+
+ MessageBeep (0xFFFFFFFF);
+
+ free (szErrorText);
+ }
+ }
+
+ if (bFree)
+ {
+ burn (wszText, wlen * sizeof (WCHAR));
+ delete [] wszText;
+ }
+ }
+ }
+}
+
+
+// check if the PC is connected to the internet using INetworkListManager interface
+BOOL IsInternetConnected()
+{
+ HRESULT hr;
+ BOOL isConnected = FALSE;
+ INetworkListManager* pNetworkListManager = nullptr;
+
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ if (SUCCEEDED(hr))
+ {
+ hr = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pNetworkListManager));
+ if (SUCCEEDED(hr))
+ {
+ VARIANT_BOOL isConnectedVariant;
+ hr = pNetworkListManager->get_IsConnectedToInternet(&isConnectedVariant);
+ if (SUCCEEDED(hr))
+ {
+ isConnected = isConnectedVariant == VARIANT_TRUE;
+ }
+ pNetworkListManager->Release();
+ }
+ CoUninitialize();
+ }
+
+ return isConnected;
+}
+
+/*
+ * Query the status of Hibernate and Fast Startup
+ */
+
+typedef BOOLEAN (WINAPI *GetPwrCapabilitiesFn)(
+ PSYSTEM_POWER_CAPABILITIES lpspc
+);
+
+BOOL GetHibernateStatus (BOOL& bHibernateEnabled, BOOL& bHiberbootEnabled)
+{
+ wchar_t szPowrProfPath[MAX_PATH] = {0};
+ HMODULE hPowrProf = NULL;
+ BOOL bResult = FALSE;
+
+ bHibernateEnabled = bHiberbootEnabled = FALSE;
+
+ if (GetSystemDirectory(szPowrProfPath, MAX_PATH))
+ StringCchCatW (szPowrProfPath, MAX_PATH, L"\\PowrProf.dll");
+ else
+ StringCchCopyW (szPowrProfPath, MAX_PATH, L"C:\\Windows\\System32\\PowrProf.dll");
+
+ hPowrProf = LoadLibrary (szPowrProfPath);
+ if (hPowrProf)
+ {
+ GetPwrCapabilitiesFn GetPwrCapabilitiesPtr = (GetPwrCapabilitiesFn) GetProcAddress (hPowrProf, "GetPwrCapabilities");
+ if ( GetPwrCapabilitiesPtr)
+ {
+ SYSTEM_POWER_CAPABILITIES spc;
+ BOOLEAN bRet = GetPwrCapabilitiesPtr (&spc);
+ if (bRet)
+ {
+ DWORD dwHibernateEnabled = 0;
+ DWORD dwHiberbootEnabled = 0;
+
+ if (spc.SystemS4)
+ {
+ dwHibernateEnabled = 1;
+ if(!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Control\\Power", L"HibernateEnabled", &dwHibernateEnabled))
+ {
+ // starting from Windows 10 1809 (Build 17763), HibernateEnabledDefault is used when HibernateEnabled is absent
+ if (IsOSVersionAtLeast (WIN_10, 0) && CurrentOSBuildNumber >= 17763)
+ ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Control\\Power", L"HibernateEnabledDefault", &dwHibernateEnabled);
+ }
+ }
+
+ // check if Fast Startup / Hybrid Boot is enabled
+#if _MSC_VER >= 1900
+ if (IsOSVersionAtLeast (WIN_8, 0) && spc.Hiberboot)
+#else
+ if (IsOSVersionAtLeast(WIN_8, 0) && spc.spare2[0])
+#endif
+ {
+ dwHiberbootEnabled = 1;
+ ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power", L"HiberbootEnabled", &dwHiberbootEnabled);
+ }
+
+ if (dwHibernateEnabled)
+ bHibernateEnabled = TRUE;
+ else
+ bHibernateEnabled = FALSE;
+
+ if (dwHiberbootEnabled)
+ bHiberbootEnabled = TRUE;
+ else
+ bHiberbootEnabled = FALSE;
+
+ bResult = TRUE;
+ }
+ }
+
+ FreeLibrary (hPowrProf);
+ }
+
+ return bResult;
+}
+
+/* return TRUE if Windows is in Test Signing mode */
+/* ref: https://social.msdn.microsoft.com/Forums/Windowsapps/en-US/e6c1be93-7003-4594-b8e4-18ab4a75d273/detecting-testsigning-onoff-via-api */
+BOOL IsTestSigningModeEnabled ()
+{
+ BOOL bEnabled = FALSE;
+ NtQuerySystemInformationFn NtQuerySystemInformationPtr = (NtQuerySystemInformationFn) GetProcAddress (GetModuleHandle (L"ntdll.dll"), "NtQuerySystemInformation");
+ if(NtQuerySystemInformationPtr)
+ {
+ SYSTEM_CODEINTEGRITY_INFORMATION info = {0};
+ ULONG cbReturnedData = 0;
+ info.Length = sizeof(info);
+ if ( (NtQuerySystemInformationPtr((SYSTEM_INFORMATION_CLASS) SYSTEMCODEINTEGRITYINFORMATION, &info, sizeof(info), &cbReturnedData) >= 0)
+ && (cbReturnedData == sizeof(info))
+ )
+ {
+ if ((info.CodeIntegrityOptions & (CODEINTEGRITY_OPTION_TESTSIGN | CODEINTEGRITY_OPTION_ENABLED)) == (CODEINTEGRITY_OPTION_TESTSIGN | CODEINTEGRITY_OPTION_ENABLED))
+ {
+ bEnabled = TRUE;
+ }
+ }
+ }
+
+ return bEnabled;
+}
+
+// Adapted from https://docs.microsoft.com/en-us/windows/win32/wmisdk/example-creating-a-wmi-application
+bool GetKbList (std::vector<std::wstring>& kbList)
+{
+ HRESULT hres;
+ kbList.clear();
+
+ // Initialize COM.
+ hres = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ if (FAILED(hres))
+ {
+ return false;
+ }
+
+ // Initialize
+ hres = CoInitializeSecurity(
+ NULL,
+ -1, // COM negotiates service
+ NULL, // Authentication services
+ NULL, // Reserved
+ RPC_C_AUTHN_LEVEL_DEFAULT, // authentication
+ RPC_C_IMP_LEVEL_IMPERSONATE, // Impersonation
+ NULL, // Authentication info
+ EOAC_NONE, // Additional capabilities
+ NULL // Reserved
+ );
+
+
+ if (FAILED(hres))
+ {
+ CoUninitialize();
+ return false;
+ }
+
+ // Obtain the initial locator to Windows Management
+ // on a particular host computer.
+ IWbemLocator *pLoc = 0;
+
+ hres = CoCreateInstance(
+ CLSID_WbemLocator,
+ 0,
+ CLSCTX_INPROC_SERVER,
+ IID_IWbemLocator, (LPVOID *) &pLoc);
+
+ if (FAILED(hres))
+ {
+ CoUninitialize();
+ return false;
+ }
+
+ IWbemServices *pSvc = 0;
+
+ // Connect to the root\cimv2 namespace with the
+ // current user and obtain pointer pSvc
+ // to make IWbemServices calls.
+
+ hres = pLoc->ConnectServer(
+
+ _bstr_t(L"ROOT\\CIMV2"), // WMI namespace
+ NULL, // User name
+ NULL, // User password
+ 0, // Locale
+ NULL, // Security flags
+ 0, // Authority
+ 0, // Context object
+ &pSvc // IWbemServices proxy
+ );
+
+ if (FAILED(hres))
+ {
+ pLoc->Release();
+ CoUninitialize();
+ return false;
+ }
+
+ // Set the IWbemServices proxy so that impersonation
+ // of the user (client) occurs.
+ hres = CoSetProxyBlanket(
+
+ pSvc, // the proxy to set
+ RPC_C_AUTHN_WINNT, // authentication service
+ RPC_C_AUTHZ_NONE, // authorization service
+ NULL, // Server principal name
+ RPC_C_AUTHN_LEVEL_CALL, // authentication level
+ RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level
+ NULL, // client identity
+ EOAC_NONE // proxy capabilities
+ );
+
+ if (FAILED(hres))
+ {
+ pSvc->Release();
+ pLoc->Release();
+ CoUninitialize();
+ return false;
+ }
+
+
+ // Use the IWbemServices pointer to make requests of WMI.
+ // Make requests here:
+
+ // query for all installed KBs
+ IEnumWbemClassObject* pEnumerator = NULL;
+ hres = pSvc->ExecQuery(
+ bstr_t("WQL"),
+ bstr_t("SELECT * FROM Win32_QuickFixEngineering"),
+ WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
+ NULL,
+ &pEnumerator);
+
+ if (FAILED(hres))
+ {
+ pSvc->Release();
+ pLoc->Release();
+ CoUninitialize();
+ return false;
+ }
+ else
+ {
+ IWbemClassObject *pclsObj;
+ ULONG uReturn = 0;
+
+ while (pEnumerator)
+ {
+ hres = pEnumerator->Next(WBEM_INFINITE, 1,
+ &pclsObj, &uReturn);
+
+ if(0 == uReturn)
+ {
+ break;
+ }
+
+ VARIANT vtProp;
+
+ // Get the value of the "hotfixid" property
+ hres = pclsObj->Get(L"hotfixid", 0, &vtProp, 0, 0);
+ if (SUCCEEDED(hres) && (V_VT(&vtProp) == VT_BSTR))
+ {
+ kbList.push_back(vtProp.bstrVal);
+ }
+ VariantClear(&vtProp);
+
+ pclsObj->Release();
+ pclsObj = NULL;
+ }
+
+ }
+
+ // Cleanup
+ // ========
+
+ pSvc->Release();
+ pLoc->Release();
+ pEnumerator->Release();
+
+ CoUninitialize();
+
+ return true;
+}
+
+bool OneOfKBsInstalled (const wchar_t* szKBs[], int count)
+{
+ std::vector<std::wstring> kbList;
+ bool bRet = GetKbList(kbList);
+ if (bRet)
+ {
+ // at least one of the given KBs must be present
+ bool bFound = false;
+
+ for (size_t j = 0; j < kbList.size(); j++)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ if (_wcsicmp(szKBs[i], kbList[j].c_str()) == 0)
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ if (bFound)
+ {
+ break;
+ }
+ }
+
+ bRet = bFound;
+ }
+
+ return bRet;
+}
+
+DWORD SendServiceNotification (DWORD dwNotificationCmd)
+{
+ DWORD dwRet = ERROR_INVALID_PARAMETER;
+ // We only support clearing keys on new device insertion
+ if (VC_DRIVER_CONFIG_CLEAR_KEYS_ON_NEW_DEVICE_INSERTION == dwNotificationCmd)
+ {
+ DWORD dwServiceControlCode = VC_SERVICE_CONTROL_BUILD_DEVICE_LIST;
+ // send this control code to VeraCrypt SystemFavorites service
+ SC_HANDLE hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT);
+ if (hSCManager != NULL)
+ {
+ SC_HANDLE hService = OpenService (hSCManager, TC_SYSTEM_FAVORITES_SERVICE_NAME, SERVICE_ALL_ACCESS);
+ if (hService != NULL)
+ {
+ SERVICE_STATUS ss;
+ if (ControlService (hService, dwServiceControlCode, &ss))
+ dwRet = ERROR_SUCCESS;
+ else
+ dwRet = GetLastError ();
+ CloseServiceHandle (hService);
+ }
+ else
+ dwRet = GetLastError ();
+ CloseServiceHandle (hSCManager);
+ }
+ else
+ dwRet = GetLastError ();
+ }
+
+ return dwRet;
+}
+
+DWORD FastResizeFile (const wchar_t* filePath, __int64 fileSize)
+{
+ DWORD dwRet = ERROR_INVALID_PARAMETER;
+ if (filePath && fileSize > 0)
+ {
+ // we set required privileges to speedup file creation before we create the file so that the file handle inherits the privileges
+ BOOL bPrivilegesSet = IsPrivilegeEnabled (SE_MANAGE_VOLUME_NAME);
+ if (!bPrivilegesSet && !SetPrivilege(SE_MANAGE_VOLUME_NAME, TRUE))
+ {
+ dwRet = GetLastError ();
+ }
+ else
+ {
+ HANDLE dev = CreateFile (filePath, GENERIC_WRITE | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (dev != INVALID_HANDLE_VALUE)
+ {
+ LARGE_INTEGER liSize;
+ liSize.QuadPart = fileSize;
+ // Preallocate the file with desired size
+ if (!SetFilePointerEx (dev, liSize, NULL, FILE_BEGIN)
+ || !SetEndOfFile (dev))
+ {
+ dwRet = GetLastError ();
+ }
+ else
+ {
+ if (!SetFileValidData (dev, fileSize))
+ {
+ dwRet = GetLastError ();
+ }
+ else
+ {
+ dwRet = ERROR_SUCCESS;
+ }
+ }
+
+ FlushFileBuffers (dev);
+ CloseHandle (dev);
+ }
+ else
+ dwRet = GetLastError ();
+
+ if (!bPrivilegesSet)
+ SetPrivilege(SE_MANAGE_VOLUME_NAME, FALSE);
+ }
+ }
+
+ return dwRet;
+}
+#endif // VC_COMREG
+
+#if defined(SETUP) && !defined (PORTABLE)
+
+// Helper function to save the current state of the required privileges
+BOOL SaveCurrentPrivilegeState(PPRIVILEGE_STATE state) {
+ if (!state) return FALSE;
+
+ state->takeOwnership = IsPrivilegeEnabled(SE_TAKE_OWNERSHIP_NAME);
+ state->backup = IsPrivilegeEnabled(SE_BACKUP_NAME);
+ state->restore = IsPrivilegeEnabled(SE_RESTORE_NAME);
+
+ return TRUE;
+}
+
+// Helper function to restore the saved state of the required privileges
+BOOL RestorePrivilegeState(const PPRIVILEGE_STATE state) {
+ if (!state) return FALSE;
+
+ BOOL result = TRUE;
+ result &= SetPrivilege(SE_TAKE_OWNERSHIP_NAME, state->takeOwnership);
+ result &= SetPrivilege(SE_BACKUP_NAME, state->backup);
+ result &= SetPrivilege(SE_RESTORE_NAME, state->restore);
+
+ return result;
+}
+
+// Helper function to enable required privileges for file operations
+BOOL EnableRequiredSetupPrivileges(PPRIVILEGE_STATE currentState)
+{
+ BOOL result = TRUE;
+
+ // save the current state of the required privileges
+ ZeroMemory(currentState, sizeof(PRIVILEGE_STATE));
+ SaveCurrentPrivilegeState(currentState);
+
+ // Enable required privileges using the existing SetPrivilege function
+ result &= SetPrivilege(SE_TAKE_OWNERSHIP_NAME, TRUE);
+ result &= SetPrivilege(SE_BACKUP_NAME, TRUE);
+ result &= SetPrivilege(SE_RESTORE_NAME, TRUE);
+
+ return result;
+}
+
+// Helper function to backup security information
+BOOL BackupSecurityInfo(const wchar_t* filePath, PSECURITY_INFO_BACKUP pBackup)
+{
+ BOOL result = FALSE;
+ DWORD dwRes;
+
+ ZeroMemory(pBackup, sizeof(SECURITY_INFO_BACKUP));
+
+ // Get the security descriptor
+ dwRes = GetNamedSecurityInfoW(
+ (LPWSTR)filePath,
+ SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
+ &pBackup->pOrigOwner,
+ &pBackup->pOrigGroup,
+ &pBackup->pOrigDacl,
+ &pBackup->pOrigSacl,
+ &pBackup->pOrigSD);
+
+ if (dwRes == ERROR_SUCCESS)
+ {
+ // The individual pointers (pOrigOwner, etc.) are now valid
+ // and point to the copied data
+ result = TRUE;
+ }
+
+ return result;
+}
+
+// Helper function to restore security information
+BOOL RestoreSecurityInfo(const wchar_t* filePath, PSECURITY_INFO_BACKUP pBackup)
+{
+ DWORD dwRes;
+ SECURITY_INFORMATION secInfo = 0;
+
+ if (pBackup->pOrigOwner)
+ secInfo |= OWNER_SECURITY_INFORMATION;
+ if (pBackup->pOrigGroup)
+ secInfo |= GROUP_SECURITY_INFORMATION;
+ if (pBackup->pOrigDacl)
+ secInfo |= DACL_SECURITY_INFORMATION;
+ if (pBackup->pOrigSacl)
+ secInfo |= SACL_SECURITY_INFORMATION;
+
+ if (secInfo == 0)
+ return TRUE; // Nothing to restore
+
+ dwRes = SetNamedSecurityInfoW(
+ (LPWSTR)filePath,
+ SE_FILE_OBJECT,
+ secInfo,
+ pBackup->pOrigOwner,
+ pBackup->pOrigGroup,
+ pBackup->pOrigDacl,
+ pBackup->pOrigSacl);
+
+ return (dwRes == ERROR_SUCCESS);
+}
+
+// Helper function to free security backup
+void FreeSecurityBackup(PSECURITY_INFO_BACKUP pBackup)
+{
+ if (pBackup->pOrigSD)
+ LocalFree(pBackup->pOrigSD);
+ ZeroMemory(pBackup, sizeof(SECURITY_INFO_BACKUP));
+}
+
+// Helper function to take ownership and modify file permissions
+BOOL ModifyFileSecurityPermissions(const wchar_t* filePath, PSECURITY_INFO_BACKUP pBackup)
+{
+ BOOL result = FALSE;
+ PSID pAdminSID = NULL;
+ PACL pNewDACL = NULL;
+ BOOL bBackupDone = FALSE;
+
+ // Get Administrator SID
+ SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
+ if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &pAdminSID))
+ {
+ goto cleanup;
+ }
+
+ // Backup original security info
+ if (!BackupSecurityInfo(filePath, pBackup))
+ goto cleanup;
+
+ bBackupDone = TRUE;
+
+ // Take ownership
+ DWORD dwRes = SetNamedSecurityInfoW(
+ (LPWSTR)filePath,
+ SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION,
+ pAdminSID,
+ NULL,
+ NULL,
+ NULL);
+
+ if (dwRes != ERROR_SUCCESS)
+ goto cleanup;
+
+ // Modify DACL
+ EXPLICIT_ACCESS ea;
+ ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
+ ea.grfAccessPermissions = GENERIC_ALL;
+ ea.grfAccessMode = SET_ACCESS;
+ ea.grfInheritance = NO_INHERITANCE;
+ ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
+ ea.Trustee.ptstrName = (LPTSTR)pAdminSID;
+
+ dwRes = SetEntriesInAcl(1, &ea, NULL, &pNewDACL);
+ if (dwRes != ERROR_SUCCESS)
+ goto cleanup;
+
+ // Apply new DACL
+ dwRes = SetNamedSecurityInfoW(
+ (LPWSTR)filePath,
+ SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ pNewDACL,
+ NULL);
+
+ result = (dwRes == ERROR_SUCCESS);
+
+cleanup:
+ if (!result && bBackupDone)
+ {
+ FreeSecurityBackup(pBackup);
+ }
+ if (pNewDACL)
+ LocalFree(pNewDACL);
+ if (pAdminSID)
+ FreeSid(pAdminSID);
+
+ return result;
+}
+#endif \ No newline at end of file