VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common')
-rw-r--r--src/Common/BaseCom.cpp4
-rw-r--r--src/Common/BootEncryption.cpp837
-rw-r--r--src/Common/BootEncryption.h28
-rw-r--r--src/Common/Cmdline.c4
-rw-r--r--src/Common/Common.rc49
-rw-r--r--src/Common/Crypto.c13
-rw-r--r--src/Common/Crypto.h2
-rw-r--r--src/Common/Dlgcode.c654
-rw-r--r--src/Common/Dlgcode.h43
-rw-r--r--src/Common/EncryptionThreadPool.c132
-rw-r--r--src/Common/EncryptionThreadPool.h4
-rw-r--r--src/Common/Fat.c41
-rw-r--r--src/Common/Format.c285
-rw-r--r--src/Common/Format.h2
-rw-r--r--src/Common/Keyfiles.c59
-rw-r--r--src/Common/Language.c1
-rw-r--r--src/Common/Language.xml95
-rw-r--r--src/Common/Password.c20
-rw-r--r--src/Common/Random.c27
-rw-r--r--src/Common/Random.h1
-rw-r--r--src/Common/SecurityToken.cpp20
-rw-r--r--src/Common/SecurityToken.h8
-rw-r--r--src/Common/Tcdefs.h36
-rw-r--r--src/Common/Zip.vcxproj1
-rw-r--r--src/Common/Zip.vcxproj.filters3
-rw-r--r--src/Common/libzip/NEWS.md8
-rw-r--r--src/Common/libzip/compat.h19
-rw-r--r--src/Common/libzip/config.h2
-rw-r--r--src/Common/libzip/zip.h78
-rw-r--r--src/Common/libzip/zip_add.c2
-rw-r--r--src/Common/libzip/zip_add_dir.c2
-rw-r--r--src/Common/libzip/zip_add_entry.c2
-rw-r--r--src/Common/libzip/zip_algorithm_deflate.c3
-rw-r--r--src/Common/libzip/zip_buffer.c2
-rw-r--r--src/Common/libzip/zip_close.c60
-rw-r--r--src/Common/libzip/zip_delete.c2
-rw-r--r--src/Common/libzip/zip_dir_add.c2
-rw-r--r--src/Common/libzip/zip_dirent.c28
-rw-r--r--src/Common/libzip/zip_discard.c2
-rw-r--r--src/Common/libzip/zip_entry.c2
-rw-r--r--src/Common/libzip/zip_err_str.c72
-rw-r--r--src/Common/libzip/zip_error.c2
-rw-r--r--src/Common/libzip/zip_error_clear.c2
-rw-r--r--src/Common/libzip/zip_error_get.c2
-rw-r--r--src/Common/libzip/zip_error_get_sys_type.c2
-rw-r--r--src/Common/libzip/zip_error_strerror.c2
-rw-r--r--src/Common/libzip/zip_error_to_str.c2
-rw-r--r--src/Common/libzip/zip_extra_field.c2
-rw-r--r--src/Common/libzip/zip_extra_field_api.c2
-rw-r--r--src/Common/libzip/zip_fclose.c2
-rw-r--r--src/Common/libzip/zip_fdopen.c4
-rw-r--r--src/Common/libzip/zip_file_add.c2
-rw-r--r--src/Common/libzip/zip_file_error_clear.c2
-rw-r--r--src/Common/libzip/zip_file_error_get.c2
-rw-r--r--src/Common/libzip/zip_file_get_comment.c2
-rw-r--r--src/Common/libzip/zip_file_get_external_attributes.c2
-rw-r--r--src/Common/libzip/zip_file_get_offset.c2
-rw-r--r--src/Common/libzip/zip_file_rename.c2
-rw-r--r--src/Common/libzip/zip_file_replace.c2
-rw-r--r--src/Common/libzip/zip_file_set_comment.c2
-rw-r--r--src/Common/libzip/zip_file_set_external_attributes.c2
-rw-r--r--src/Common/libzip/zip_file_set_mtime.c36
-rw-r--r--src/Common/libzip/zip_file_strerror.c2
-rw-r--r--src/Common/libzip/zip_filerange_crc.c14
-rw-r--r--src/Common/libzip/zip_fopen.c2
-rw-r--r--src/Common/libzip/zip_fopen_encrypted.c2
-rw-r--r--src/Common/libzip/zip_fopen_index.c2
-rw-r--r--src/Common/libzip/zip_fopen_index_encrypted.c2
-rw-r--r--src/Common/libzip/zip_fread.c2
-rw-r--r--src/Common/libzip/zip_get_archive_comment.c2
-rw-r--r--src/Common/libzip/zip_get_archive_flag.c2
-rw-r--r--src/Common/libzip/zip_get_encryption_implementation.c2
-rw-r--r--src/Common/libzip/zip_get_file_comment.c2
-rw-r--r--src/Common/libzip/zip_get_name.c2
-rw-r--r--src/Common/libzip/zip_get_num_entries.c2
-rw-r--r--src/Common/libzip/zip_get_num_files.c2
-rw-r--r--src/Common/libzip/zip_hash.c2
-rw-r--r--src/Common/libzip/zip_io_util.c2
-rw-r--r--src/Common/libzip/zip_memdup.c2
-rw-r--r--src/Common/libzip/zip_name_locate.c2
-rw-r--r--src/Common/libzip/zip_new.c2
-rw-r--r--src/Common/libzip/zip_open.c34
-rw-r--r--src/Common/libzip/zip_progress.c172
-rw-r--r--src/Common/libzip/zip_rename.c2
-rw-r--r--src/Common/libzip/zip_replace.c2
-rw-r--r--src/Common/libzip/zip_set_archive_comment.c2
-rw-r--r--src/Common/libzip/zip_set_archive_flag.c2
-rw-r--r--src/Common/libzip/zip_set_default_password.c2
-rw-r--r--src/Common/libzip/zip_set_file_comment.c2
-rw-r--r--src/Common/libzip/zip_set_file_compression.c2
-rw-r--r--src/Common/libzip/zip_set_name.c2
-rw-r--r--src/Common/libzip/zip_source_accept_empty.c52
-rw-r--r--src/Common/libzip/zip_source_begin_write.c2
-rw-r--r--src/Common/libzip/zip_source_begin_write_cloning.c2
-rw-r--r--src/Common/libzip/zip_source_buffer.c18
-rw-r--r--src/Common/libzip/zip_source_call.c2
-rw-r--r--src/Common/libzip/zip_source_close.c2
-rw-r--r--src/Common/libzip/zip_source_commit_write.c2
-rw-r--r--src/Common/libzip/zip_source_compress.c12
-rw-r--r--src/Common/libzip/zip_source_crc.c3
-rw-r--r--src/Common/libzip/zip_source_error.c2
-rw-r--r--src/Common/libzip/zip_source_file.c2
-rw-r--r--src/Common/libzip/zip_source_filep.c114
-rw-r--r--src/Common/libzip/zip_source_free.c2
-rw-r--r--src/Common/libzip/zip_source_function.c2
-rw-r--r--src/Common/libzip/zip_source_get_compression_flags.c2
-rw-r--r--src/Common/libzip/zip_source_is_deleted.c2
-rw-r--r--src/Common/libzip/zip_source_layered.c2
-rw-r--r--src/Common/libzip/zip_source_open.c2
-rw-r--r--src/Common/libzip/zip_source_pkware.c2
-rw-r--r--src/Common/libzip/zip_source_read.c4
-rw-r--r--src/Common/libzip/zip_source_remove.c2
-rw-r--r--src/Common/libzip/zip_source_rollback_write.c2
-rw-r--r--src/Common/libzip/zip_source_seek.c9
-rw-r--r--src/Common/libzip/zip_source_seek_write.c2
-rw-r--r--src/Common/libzip/zip_source_stat.c2
-rw-r--r--src/Common/libzip/zip_source_supports.c2
-rw-r--r--src/Common/libzip/zip_source_tell.c2
-rw-r--r--src/Common/libzip/zip_source_tell_write.c2
-rw-r--r--src/Common/libzip/zip_source_win32a.c12
-rw-r--r--src/Common/libzip/zip_source_win32handle.c9
-rw-r--r--src/Common/libzip/zip_source_win32utf8.c2
-rw-r--r--src/Common/libzip/zip_source_win32w.c12
-rw-r--r--src/Common/libzip/zip_source_window.c17
-rw-r--r--src/Common/libzip/zip_source_write.c2
-rw-r--r--src/Common/libzip/zip_source_zip.c2
-rw-r--r--src/Common/libzip/zip_source_zip_new.c2
-rw-r--r--src/Common/libzip/zip_stat.c2
-rw-r--r--src/Common/libzip/zip_stat_index.c11
-rw-r--r--src/Common/libzip/zip_stat_init.c2
-rw-r--r--src/Common/libzip/zip_strerror.c2
-rw-r--r--src/Common/libzip/zip_string.c2
-rw-r--r--src/Common/libzip/zip_unchange.c2
-rw-r--r--src/Common/libzip/zip_unchange_all.c2
-rw-r--r--src/Common/libzip/zip_unchange_archive.c2
-rw-r--r--src/Common/libzip/zip_unchange_data.c2
-rw-r--r--src/Common/libzip/zip_utf-8.c4
-rw-r--r--src/Common/libzip/zipint.h41
-rw-r--r--src/Common/libzip/zipwin32.h2
139 files changed, 2533 insertions, 858 deletions
diff --git a/src/Common/BaseCom.cpp b/src/Common/BaseCom.cpp
index 7a74e29..32859b1 100644
--- a/src/Common/BaseCom.cpp
+++ b/src/Common/BaseCom.cpp
@@ -130,7 +130,7 @@ DWORD BaseCom::ReadWriteFile (BOOL write, BOOL device, BSTR filePath, BSTR *buff
{
try
{
- auto_ptr <File> file (device ? new Device (filePath, !write) : new File (filePath, !write));
+ unique_ptr <File> file (device ? new Device (filePath, !write) : new File (filePath, !write));
file->CheckOpened (SRC_POS);
file->SeekAt (offset);
@@ -194,7 +194,7 @@ DWORD BaseCom::DeviceIoControl (BOOL readOnly, BOOL device, BSTR filePath, DWORD
{
try
{
- auto_ptr <File> file (device ? new Device (filePath, readOnly == TRUE) : new File (filePath, readOnly == TRUE));
+ unique_ptr <File> file (device ? new Device (filePath, readOnly == TRUE) : new File (filePath, readOnly == TRUE));
file->CheckOpened (SRC_POS);
if (!file->IoCtl (dwIoControlCode, (BYTE *) input, !(BYTE *) input ? 0 : ((DWORD *) ((BYTE *) input))[-1],
(BYTE *) *output, !(BYTE *) *output ? 0 : ((DWORD *) ((BYTE *) *output))[-1]))
diff --git a/src/Common/BootEncryption.cpp b/src/Common/BootEncryption.cpp
index 4061bde..502b4e0 100644
--- a/src/Common/BootEncryption.cpp
+++ b/src/Common/BootEncryption.cpp
@@ -275,6 +275,27 @@ bool ZipAdd (zip_t *z, const char* name, const unsigned char* pbData, DWORD cbDa
return true;
}
+static BOOL IsWindowsMBR (const byte *buffer, size_t bufferSize)
+{
+ BOOL bRet = FALSE;
+ byte g_pbMsSignature[4] = {0x33, 0xc0, 0x8e, 0xd0};
+ const char* g_szStr1 = "Invalid partition table";
+ const char* g_szStr2 = "Error loading operating system";
+ const char* g_szStr3 = "Missing operating system";
+
+ if ((0 == memcmp (buffer, g_pbMsSignature, 4)) &&
+ (BufferContainsString (buffer, bufferSize, g_szStr1)
+ || BufferContainsString (buffer, bufferSize, g_szStr2)
+ || BufferContainsString (buffer, bufferSize, g_szStr3)
+ )
+ )
+ {
+ bRet = TRUE;
+ }
+
+ return bRet;
+}
+
namespace VeraCrypt
{
#if !defined (SETUP)
@@ -1030,7 +1051,7 @@ namespace VeraCrypt
static EfiBoot EfiBootInst;
- BootEncryption::BootEncryption (HWND parent, bool postOOBE)
+ BootEncryption::BootEncryption (HWND parent, bool postOOBE, bool setBootEntry, bool forceFirstBootEntry, bool setBootNext)
: DriveConfigValid (false),
ParentWindow (parent),
RealSystemDriveSizeValid (false),
@@ -1041,7 +1062,10 @@ namespace VeraCrypt
SelectedEncryptionAlgorithmId (0),
SelectedPrfAlgorithmId (0),
VolumeHeaderValid (false),
- PostOOBEMode (postOOBE)
+ PostOOBEMode (postOOBE),
+ SetBootNext (setBootNext),
+ SetBootEntry (setBootEntry),
+ ForceFirstBootEntry (forceFirstBootEntry)
{
HiddenOSCandidatePartition.IsGPT = FALSE;
HiddenOSCandidatePartition.Number = (size_t) -1;
@@ -2364,6 +2388,35 @@ namespace VeraCrypt
WriteConfigInteger (configFile, configContent, "AuthorizeRetry", authorizeRetry);
WriteConfigInteger (configFile, configContent, "DcsBmlLockFlags", bmlLockFlags);
WriteConfigInteger (configFile, configContent, "DcsBmlDriver", bmlDriverEnabled);
+
+ string fieldValue;
+ if (IsPostExecFileField(actionSuccessValue, fieldValue) && (0 == _stricmp(fieldValue.c_str(), "\\EFI\\Microsoft\\Boot\\bootmgfw.efi")))
+ {
+ // fix wrong configuration file since bootmgfw.efi is now a copy of VeraCrypt and if we don't fix the DcsProp
+ // file, veraCrypt bootloader will call itself
+ // We first check if bootmgfw.efi is original Microsoft one. If yes, we don't do anything, otherwise we set the field to bootmgfw_ms.vc
+ unsigned __int64 loaderSize = 0;
+ bool bModifiedMsBoot = true;
+ EfiBootInst.GetFileSize(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", loaderSize);
+
+ if (loaderSize > 32768)
+ {
+ std::vector<byte> bootLoaderBuf ((size_t) loaderSize);
+
+ EfiBootInst.ReadFile(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", &bootLoaderBuf[0], (DWORD) loaderSize);
+
+ // look for bootmgfw.efi identifiant string
+ const char* g_szMsBootString = "bootmgfw.pdb";
+ if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, g_szMsBootString, strlen (g_szMsBootString)))
+ {
+ bModifiedMsBoot = false;
+ }
+ }
+
+ if (bModifiedMsBoot)
+ actionSuccessValue = "postexec file(EFI\\Microsoft\\Boot\\bootmgfw_ms.vc)";
+ }
+
WriteConfigString (configFile, configContent, "ActionSuccess", actionSuccessValue.c_str());
// Write unmodified values
@@ -2396,12 +2449,62 @@ namespace VeraCrypt
return bRet;
}
+ BOOL EfiBootConf::IsPostExecFileField (const string& fieldValue, string& filePath)
+ {
+ BOOL bRet = FALSE;
+ filePath = "";
+
+ if (!fieldValue.empty() && strlen (fieldValue.c_str()))
+ {
+ string copieValue = fieldValue;
+ std::transform(copieValue.begin(), copieValue.end(), copieValue.begin(), ::tolower);
+
+ if (strstr (copieValue.c_str(), "postexec") && strstr (copieValue.c_str(), "file("))
+ {
+ char c;
+ const char* ptr = strstr (copieValue.c_str(), "file(");
+
+ filePath = "\\";
+ ptr += 5;
+ while ((c = *ptr))
+ {
+ if (c == ')')
+ break;
+ if (c == '/')
+ c = '\\';
+ filePath += c;
+ ptr++;
+ }
+
+ if (c == ')')
+ bRet = TRUE;
+ else
+ filePath = "";
+ }
+ }
+
+ return bRet;
+ }
+
+ BOOL EfiBootConf::IsPostExecFileField (const string& fieldValue, wstring& filePath)
+ {
+ string aPath;
+ BOOL bRet = IsPostExecFileField (fieldValue, aPath);
+ if (bRet)
+ filePath = wstring(aPath.begin(), aPath.end());
+ else
+ filePath = L"";
+
+ return bRet;
+ }
+
static const wchar_t* EfiVarGuid = L"{8BE4DF61-93CA-11D2-AA0D-00E098032B8C}";
void
- GetVolumeESP(wstring& path)
+ GetVolumeESP(wstring& path, wstring& bootVolumePath)
{
static wstring g_EspPath;
+ static wstring g_BootVolumePath;
static bool g_EspPathInitialized = false;
if (!g_EspPathInitialized)
@@ -2422,17 +2525,29 @@ namespace VeraCrypt
res = NtQuerySystemInformationPtr((SYSTEM_INFORMATION_CLASS)SYSPARTITIONINFORMATION, tempBuf, sizeof(tempBuf), &len);
if (res != S_OK)
{
+ /* try to convert the returned NTSTATUS to a WIN32 system error using RtlNtStatusToDosError */
+ RtlNtStatusToDosErrorFn RtlNtStatusToDosErrorPtr = (RtlNtStatusToDosErrorFn) GetProcAddress (GetModuleHandle (L"ntdll.dll"), "RtlNtStatusToDosError");
+ if (RtlNtStatusToDosErrorPtr)
+ {
+ ULONG win32err = RtlNtStatusToDosErrorPtr (res);
+ if (win32err != ERROR_MR_MID_NOT_FOUND)
+ res = (NTSTATUS) win32err;
+ }
+
SetLastError (res);
throw SystemException (SRC_POS);
}
PUNICODE_STRING pStr = (PUNICODE_STRING) tempBuf;
+
+ g_BootVolumePath = pStr->Buffer;
g_EspPath = L"\\\\?";
g_EspPath += &pStr->Buffer[7];
g_EspPathInitialized = true;
}
path = g_EspPath;
+ bootVolumePath = g_BootVolumePath;
}
std::string ReadESPFile (LPCWSTR szFilePath, bool bSkipUTF8BOM)
@@ -2442,9 +2557,9 @@ namespace VeraCrypt
ByteArray fileContent;
DWORD dwSize = 0, dwOffset = 0;
- std::wstring pathESP;
+ std::wstring pathESP, bootVolumePath;
- GetVolumeESP(pathESP);
+ GetVolumeESP(pathESP, bootVolumePath);
if (szFilePath[0] != L'\\')
pathESP += L"\\";
File f(pathESP + szFilePath, true);
@@ -2473,7 +2588,7 @@ namespace VeraCrypt
ByteArray fileContent;
DWORD dwSize = dwDataLen, dwOffset = 0;
- std::wstring pathESP;
+ std::wstring pathESP, bootVolumePath;
if (bAddUTF8BOM)
{
@@ -2481,7 +2596,7 @@ namespace VeraCrypt
dwOffset = 3;
}
- GetVolumeESP(pathESP);
+ GetVolumeESP(pathESP, bootVolumePath);
if (szFilePath[0] != L'\\')
pathESP += L"\\";
@@ -2500,42 +2615,13 @@ namespace VeraCrypt
ZeroMemory (&sdn, sizeof (sdn));
ZeroMemory (&partInfo, sizeof (partInfo));
m_bMounted = false;
- bBootVolumePathSelected = false;
+ bDeviceInfoValid = false;
}
- void EfiBoot::SelectBootVolumeESP() {
- NTSTATUS res;
- ULONG len;
- memset(tempBuf, 0, sizeof(tempBuf));
-
- // Load NtQuerySystemInformation function point
- if (!NtQuerySystemInformationPtr)
- {
- NtQuerySystemInformationPtr = (NtQuerySystemInformationFn) GetProcAddress (GetModuleHandle (L"ntdll.dll"), "NtQuerySystemInformation");
- if (!NtQuerySystemInformationPtr)
- throw SystemException (SRC_POS);
- }
-
- res = NtQuerySystemInformationPtr((SYSTEM_INFORMATION_CLASS)SYSPARTITIONINFORMATION, tempBuf, sizeof(tempBuf), &len);
- if (res != S_OK)
- {
- SetLastError (res);
- throw SystemException (SRC_POS);
- }
-
- PUNICODE_STRING pStr = (PUNICODE_STRING) tempBuf;
- BootVolumePath = pStr->Buffer;
-
- EfiBootPartPath = L"\\\\?";
- EfiBootPartPath += &pStr->Buffer[7];
-
- bBootVolumePathSelected = true;
- }
+ void EfiBoot::PrepareBootPartition(bool bDisableException) {
+
+ GetVolumeESP (EfiBootPartPath, BootVolumePath);
- void EfiBoot::PrepareBootPartition() {
- if (!bBootVolumePathSelected) {
- SelectBootVolumeESP();
- }
std::wstring devicePath = L"\\\\?\\GLOBALROOT";
devicePath += BootVolumePath;
Device dev(devicePath.c_str(), TRUE);
@@ -2546,18 +2632,22 @@ namespace VeraCrypt
}
catch (...)
{
- throw;
+ if (!bDisableException)
+ throw;
}
- bool bSuccess = dev.IoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn))
- && dev.IoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &partInfo, sizeof(partInfo));
- DWORD dwLastError = GetLastError ();
- dev.Close();
- if (!bSuccess)
+ if (dev.IsOpened())
{
- SetLastError (dwLastError);
- throw SystemException(SRC_POS);
- }
+ bDeviceInfoValid = dev.IoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn))
+ && dev.IoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &partInfo, sizeof(partInfo));
+ DWORD dwLastError = GetLastError ();
+ dev.Close();
+ if (!bDeviceInfoValid && !bDisableException)
+ {
+ SetLastError (dwLastError);
+ throw SystemException(SRC_POS);
+ }
+ }
}
bool EfiBoot::IsEfiBoot() {
@@ -2615,98 +2705,107 @@ namespace VeraCrypt
}
}
- void EfiBoot::SetStartExec(wstring description, wstring execPath, uint16 statrtOrderNum , wchar_t* type, uint32 attr) {
+ void EfiBoot::SetStartExec(wstring description, wstring execPath, bool setBootEntry, bool forceFirstBootEntry, bool setBootNext, uint16 statrtOrderNum , wchar_t* type, uint32 attr) {
SetPrivilege(SE_SYSTEM_ENVIRONMENT_NAME, TRUE);
// Check EFI
if (!IsEfiBoot()) {
throw ErrorException(L"can not detect EFI environment", SRC_POS);
}
- uint32 varSize = 56;
- varSize += ((uint32) description.length()) * 2 + 2;
- varSize += ((uint32) execPath.length()) * 2 + 2;
- byte *startVar = new byte[varSize];
- byte *pVar = startVar;
-
- // Attributes (1b Active, 1000b - Hidden)
- *(uint32 *)pVar = attr;
- pVar += sizeof(uint32);
-
- // Size Of device path + file path
- *(uint16 *)pVar = (uint16)(50 + execPath.length() * 2 + 2);
- pVar += sizeof(uint16);
-
- // description
- for (uint32 i = 0; i < description.length(); i++) {
- *(uint16 *)pVar = description[i];
+ if (bDeviceInfoValid)
+ {
+ uint32 varSize = 56;
+ varSize += ((uint32) description.length()) * 2 + 2;
+ varSize += ((uint32) execPath.length()) * 2 + 2;
+ byte *startVar = new byte[varSize];
+ byte *pVar = startVar;
+
+ // Attributes (1b Active, 1000b - Hidden)
+ *(uint32 *)pVar = attr;
+ pVar += sizeof(uint32);
+
+ // Size Of device path + file path
+ *(uint16 *)pVar = (uint16)(50 + execPath.length() * 2 + 2);
+ pVar += sizeof(uint16);
+
+ // description
+ for (uint32 i = 0; i < description.length(); i++) {
+ *(uint16 *)pVar = description[i];
+ pVar += sizeof(uint16);
+ }
+ *(uint16 *)pVar = 0;
pVar += sizeof(uint16);
- }
- *(uint16 *)pVar = 0;
- pVar += sizeof(uint16);
- /* EFI_DEVICE_PATH_PROTOCOL (HARDDRIVE_DEVICE_PATH \ FILE_PATH \ END) */
+ /* EFI_DEVICE_PATH_PROTOCOL (HARDDRIVE_DEVICE_PATH \ FILE_PATH \ END) */
- // Type
- *(byte *)pVar = 0x04;
- pVar += sizeof(byte);
+ // Type
+ *(byte *)pVar = 0x04;
+ pVar += sizeof(byte);
- // SubType
- *(byte *)pVar = 0x01;
- pVar += sizeof(byte);
+ // SubType
+ *(byte *)pVar = 0x01;
+ pVar += sizeof(byte);
- // HDD dev path length
- *(uint16 *)pVar = 0x2A; // 42
- pVar += sizeof(uint16);
+ // HDD dev path length
+ *(uint16 *)pVar = 0x2A; // 42
+ pVar += sizeof(uint16);
- // PartitionNumber
- *(uint32 *)pVar = (uint32)partInfo.PartitionNumber;
- pVar += sizeof(uint32);
+ // PartitionNumber
+ *(uint32 *)pVar = (uint32)partInfo.PartitionNumber;
+ pVar += sizeof(uint32);
- // PartitionStart
- *(uint64 *)pVar = partInfo.StartingOffset.QuadPart >> 9;
- pVar += sizeof(uint64);
+ // PartitionStart
+ *(uint64 *)pVar = partInfo.StartingOffset.QuadPart >> 9;
+ pVar += sizeof(uint64);
- // PartitiontSize
- *(uint64 *)pVar = partInfo.PartitionLength.QuadPart >> 9;
- pVar += sizeof(uint64);
+ // PartitiontSize
+ *(uint64 *)pVar = partInfo.PartitionLength.QuadPart >> 9;
+ pVar += sizeof(uint64);
- // GptGuid
- memcpy(pVar, &partInfo.Gpt.PartitionId, 16);
- pVar += 16;
+ // GptGuid
+ memcpy(pVar, &partInfo.Gpt.PartitionId, 16);
+ pVar += 16;
- // MbrType
- *(byte *)pVar = 0x02;
- pVar += sizeof(byte);
+ // MbrType
+ *(byte *)pVar = 0x02;
+ pVar += sizeof(byte);
- // SigType
- *(byte *)pVar = 0x02;
- pVar += sizeof(byte);
+ // SigType
+ *(byte *)pVar = 0x02;
+ pVar += sizeof(byte);
- // Type and sub type 04 04 (file path)
- *(uint16 *)pVar = 0x0404;
- pVar += sizeof(uint16);
+ // Type and sub type 04 04 (file path)
+ *(uint16 *)pVar = 0x0404;
+ pVar += sizeof(uint16);
- // SizeOfFilePath ((CHAR16)FullPath.length + sizeof(EndOfrecord marker) )
- *(uint16 *)pVar = (uint16)(execPath.length() * 2 + 2 + sizeof(uint32));
- pVar += sizeof(uint16);
+ // SizeOfFilePath ((CHAR16)FullPath.length + sizeof(EndOfrecord marker) )
+ *(uint16 *)pVar = (uint16)(execPath.length() * 2 + 2 + sizeof(uint32));
+ pVar += sizeof(uint16);
- // FilePath
- for (uint32 i = 0; i < execPath.length(); i++) {
- *(uint16 *)pVar = execPath[i];
+ // FilePath
+ for (uint32 i = 0; i < execPath.length(); i++) {
+ *(uint16 *)pVar = execPath[i];
+ pVar += sizeof(uint16);
+ }
+ *(uint16 *)pVar = 0;
pVar += sizeof(uint16);
- }
- *(uint16 *)pVar = 0;
- pVar += sizeof(uint16);
- // EndOfrecord
- *(uint32 *)pVar = 0x04ff7f;
- pVar += sizeof(uint32);
+ // EndOfrecord
+ *(uint32 *)pVar = 0x04ff7f;
+ pVar += sizeof(uint32);
- // Set variable
- wchar_t varName[256];
- StringCchPrintfW(varName, ARRAYSIZE (varName), L"%s%04X", type == NULL ? L"Boot" : type, statrtOrderNum);
- SetFirmwareEnvironmentVariable(varName, EfiVarGuid, startVar, varSize);
- delete [] startVar;
+ // Set variable
+ wchar_t varName[256];
+ StringCchPrintfW(varName, ARRAYSIZE (varName), L"%s%04X", type == NULL ? L"Boot" : type, statrtOrderNum);
+
+ // only set value if it doesn't already exist
+ byte* existingVar = new byte[varSize];
+ DWORD existingVarLen = GetFirmwareEnvironmentVariableW (varName, EfiVarGuid, existingVar, varSize);
+ if ((existingVarLen != varSize) || (0 != memcmp (existingVar, startVar, varSize)))
+ SetFirmwareEnvironmentVariable(varName, EfiVarGuid, startVar, varSize);
+ delete [] startVar;
+ delete [] existingVar;
+ }
// Update order
wstring order = L"Order";
@@ -2723,42 +2822,183 @@ namespace VeraCrypt
}
}
- // Create new entry if absent
- if (startOrderNumPos == UINT_MAX) {
- for (uint32 i = startOrderLen / 2; i > 0; --i) {
- startOrder[i] = startOrder[i - 1];
+ if (setBootEntry)
+ {
+ // check if first entry in BootOrder is Windows one
+ bool bFirstEntryIsWindows = false;
+ if (startOrderNumPos != 0)
+ {
+ wchar_t varName[256];
+ StringCchPrintfW(varName, ARRAYSIZE (varName), L"%s%04X", type == NULL ? L"Boot" : type, startOrder[0]);
+
+ byte* existingVar = new byte[512];
+ DWORD existingVarLen = GetFirmwareEnvironmentVariableW (varName, EfiVarGuid, existingVar, 512);
+ if (existingVarLen > 0)
+ {
+ if (BufferContainsWideString (existingVar, existingVarLen, L"EFI\\Microsoft\\Boot\\bootmgfw.efi"))
+ bFirstEntryIsWindows = true;
+ }
+
+ delete [] existingVar;
}
- startOrder[0] = statrtOrderNum;
- startOrderLen += 2;
- startOrderUpdate = true;
- } else if (startOrderNumPos > 0) {
- for (uint32 i = startOrderNumPos; i > 0; --i) {
- startOrder[i] = startOrder[i - 1];
+
+
+ // Create new entry if absent
+ if (startOrderNumPos == UINT_MAX) {
+ if (bDeviceInfoValid)
+ {
+ if (forceFirstBootEntry && bFirstEntryIsWindows)
+ {
+ for (uint32 i = startOrderLen / 2; i > 0; --i) {
+ startOrder[i] = startOrder[i - 1];
+ }
+ startOrder[0] = statrtOrderNum;
+ }
+ else
+ {
+ startOrder[startOrderLen/2] = statrtOrderNum;
+ }
+ startOrderLen += 2;
+ startOrderUpdate = true;
+ }
+ } else if ((startOrderNumPos > 0) && forceFirstBootEntry && bFirstEntryIsWindows) {
+ for (uint32 i = startOrderNumPos; i > 0; --i) {
+ startOrder[i] = startOrder[i - 1];
+ }
+ startOrder[0] = statrtOrderNum;
+ startOrderUpdate = true;
+ }
+
+ if (startOrderUpdate) {
+ SetFirmwareEnvironmentVariable(order.c_str(), EfiVarGuid, startOrder, startOrderLen);
}
- startOrder[0] = statrtOrderNum;
- startOrderUpdate = true;
}
- if (startOrderUpdate) {
- SetFirmwareEnvironmentVariable(order.c_str(), EfiVarGuid, startOrder, startOrderLen);
+ if (setBootNext)
+ {
+ // set BootNext value
+ wstring next = L"Next";
+ next.insert(0, type == NULL ? L"Boot" : type);
+
+ SetFirmwareEnvironmentVariable(next.c_str(), EfiVarGuid, &statrtOrderNum, 2);
+
}
+ }
+
+ bool EfiBoot::CompareFiles (const wchar_t* fileName1, const wchar_t* fileName2)
+ {
+ bool bRet = false;
+ File f1 (fileName1, true);
+ File f2 (fileName2, true);
+
+ if (f1.IsOpened() && f2.IsOpened())
+ {
+ try
+ {
+ DWORD size1, size2;
+ f1.GetFileSize (size1);
+ f2.GetFileSize (size2);
- // set BootNext value
- wstring next = L"Next";
- next.insert(0, type == NULL ? L"Boot" : type);
+ if (size1 == size2)
+ {
+ // same size, so now we compare content
+ std::vector<byte> file1Buf (8096);
+ std::vector<byte> file2Buf (8096);
+ DWORD remainingBytes = size1, dataToRead;
+
+ while (remainingBytes)
+ {
+ dataToRead = VC_MIN (remainingBytes, (DWORD) file1Buf.size());
+ DWORD f1Bytes = f1.Read (file1Buf.data(), dataToRead);
+ DWORD f2Bytes = f2.Read (file2Buf.data(), dataToRead);
+
+ if ((f1Bytes != f2Bytes) || memcmp (file1Buf.data(), file2Buf.data(), (size_t) f1Bytes))
+ {
+ break;
+ }
+ else
+ {
+ remainingBytes -= f1Bytes;
+ }
+ }
+
+ if (0 == remainingBytes)
+ {
+ // content is the same
+ bRet = true;
+ }
+ }
+ }
+ catch (...) {}
+ }
- SetFirmwareEnvironmentVariable(next.c_str(), EfiVarGuid, &statrtOrderNum, 2);
+ f1.Close();
+ f2.Close();
+ return bRet;
+ }
+
+ bool EfiBoot::CompareFileData (const wchar_t* fileName, const byte* data, DWORD size)
+ {
+ bool bRet = false;
+
+ File f(fileName, true);
+ if (f.IsOpened ())
+ {
+ try
+ {
+ // check if the file has the same content
+ // if yes, don't perform any write operation to avoid changing its timestamp
+ DWORD existingSize = 0;
+
+ f.GetFileSize(existingSize);
+
+ if (existingSize == size)
+ {
+ std::vector<byte> fileBuf (8096);
+ DWORD remainingBytes = size, dataOffset = 0, dataToRead;
+
+ while (remainingBytes)
+ {
+ dataToRead = VC_MIN (remainingBytes, (DWORD) fileBuf.size());
+ dataToRead = f.Read (fileBuf.data(), dataToRead);
+
+ if (memcmp (data + dataOffset, fileBuf.data(), (size_t) dataToRead))
+ {
+ break;
+ }
+ else
+ {
+ dataOffset += dataToRead;
+ remainingBytes -= dataToRead;
+ }
+ }
+
+ if (0 == remainingBytes)
+ {
+ // content is the same
+ bRet = true;
+ }
+ }
+ }
+ catch (...){}
+ }
+
+ f.Close();
+
+ return bRet;
}
void EfiBoot::SaveFile(const wchar_t* name, byte* data, DWORD size) {
wstring path = EfiBootPartPath;
path += name;
- File f(path, false, true);
- f.Write(data, size);
- f.Close();
-
+ if (!CompareFileData (path.c_str(), data, size))
+ {
+ File f(path, false, true);
+ f.Write(data, size);
+ f.Close();
+ }
}
bool EfiBoot::FileExists(const wchar_t* name) {
@@ -2797,7 +3037,10 @@ namespace VeraCrypt
}
else
targetPath = targetName;
- throw_sys_if (!::CopyFileW (path.c_str(), targetPath.c_str(), FALSE));
+
+ // if both files are the same, we don't perform copy operation
+ if (!CompareFiles (path.c_str(), targetPath.c_str()))
+ throw_sys_if (!::CopyFileW (path.c_str(), targetPath.c_str(), FALSE));
}
BOOL EfiBoot::RenameFile(const wchar_t* name, const wchar_t* nameNew, BOOL bForce) {
@@ -2805,7 +3048,16 @@ namespace VeraCrypt
path += name;
wstring pathNew = EfiBootPartPath;
pathNew += nameNew;
- return MoveFileExW(path.c_str(), pathNew.c_str(), bForce? MOVEFILE_REPLACE_EXISTING : 0);
+
+ BOOL bRet;
+ if (CompareFiles (path.c_str(), pathNew.c_str()))
+ {
+ // files identical. Delete source file only
+ bRet = DeleteFile (path.c_str());
+ }
+ else
+ bRet = MoveFileExW(path.c_str(), pathNew.c_str(), bForce? MOVEFILE_REPLACE_EXISTING : 0);
+ return bRet;
}
BOOL EfiBoot::DelFile(const wchar_t* name) {
@@ -2955,20 +3207,69 @@ namespace VeraCrypt
if (bForInstall)
{
+ /* Before updating files, we check first if they already have the expected content. If yes, then we don't perform
+ * any write operation to avoid modifying file timestamps Unnecessarily.
+ */
+ bool bSkipWrite = false;
+ wchar_t wszBuffer [2 * TC_MAX_PATH] = {0};
wstring szPathParam = L"\"";
szPathParam += szInstallPath;
szPathParam += L"\"";
- WritePrivateProfileStringW (L"SetupConfig", L"ReflectDrivers", szPathParam.c_str(), szSetupconfigLocation);
+ if ( (0 < GetPrivateProfileStringW (L"SetupConfig", L"ReflectDrivers", L"", wszBuffer, ARRAYSIZE (wszBuffer), szSetupconfigLocation))
+ && (_wcsicmp (wszBuffer, szInstallPath) == 0)
+ )
+ {
+ bSkipWrite = true;
+ }
+
+ if (!bSkipWrite)
+ WritePrivateProfileStringW (L"SetupConfig", L"ReflectDrivers", szPathParam.c_str(), szSetupconfigLocation);
+
+ bSkipWrite = false;
szPathParam = GetProgramConfigPath (L"SetupComplete.cmd");
- FILE* scriptFile = _wfopen (szPathParam.c_str(), L"w");
+
+ wstring wszExpectedValue = L"\"";
+ wszExpectedValue += szInstallPath;
+ wszExpectedValue += L"\\VeraCrypt.exe\" /PostOOBE";
+
+ FILE* scriptFile = _wfopen (szPathParam.c_str(), L"r");
if (scriptFile)
{
- fwprintf (scriptFile, L"\"%s\\VeraCrypt.exe\" /PostOOBE\n", szInstallPath);
+ long fileSize = _filelength (_fileno (scriptFile));
+ if (fileSize < (2 * TC_MAX_PATH))
+ {
+ fgetws (wszBuffer, ARRAYSIZE (wszBuffer), scriptFile);
+
+ if (wszBuffer[wcslen (wszBuffer) - 1] == L'\n')
+ wszBuffer[wcslen (wszBuffer) - 1] = 0;
+
+ bSkipWrite = (0 == _wcsicmp (wszBuffer, wszExpectedValue.c_str()));
+ }
fclose (scriptFile);
+ }
- WritePrivateProfileStringW (L"SetupConfig", L"PostOOBE", szPathParam.c_str(), szSetupconfigLocation);
+ if (!bSkipWrite)
+ {
+ scriptFile = _wfopen (szPathParam.c_str(), L"w");
+ if (scriptFile)
+ {
+ fwprintf (scriptFile, L"%s\n", wszExpectedValue.c_str());
+ fclose (scriptFile);
+ }
}
+
+ bSkipWrite = false;
+
+ if ( (0 < GetPrivateProfileStringW (L"SetupConfig", L"PostOOBE", L"", wszBuffer, ARRAYSIZE (wszBuffer), szSetupconfigLocation))
+ && (_wcsicmp (wszBuffer, szPathParam.c_str()) == 0)
+ )
+ {
+ bSkipWrite = true;
+ }
+
+ if (!bSkipWrite)
+ WritePrivateProfileStringW (L"SetupConfig", L"PostOOBE", szPathParam.c_str(), szSetupconfigLocation);
}
else
{
@@ -3063,7 +3364,7 @@ namespace VeraCrypt
if (!DcsInfoImg)
throw ErrorException(L"Out of resource DcsInfo", SRC_POS);
- EfiBootInst.PrepareBootPartition();
+ EfiBootInst.PrepareBootPartition(PostOOBEMode);
try
{
@@ -3076,8 +3377,15 @@ namespace VeraCrypt
if (preserveUserConfig)
{
- bool bModifiedMsBoot = true;
- EfiBootInst.GetFileSize(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", loaderSize);
+ bool bModifiedMsBoot = true, bMissingMsBoot = false;;
+ if (EfiBootInst.FileExists (L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi"))
+ EfiBootInst.GetFileSize(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", loaderSize);
+ else
+ bMissingMsBoot = true;
+
+ // restore boot menu entry in case of PostOOBE
+ if (PostOOBEMode)
+ EfiBootInst.SetStartExec(L"VeraCrypt BootLoader (DcsBoot)", L"\\EFI\\VeraCrypt\\DcsBoot.efi", SetBootEntry, ForceFirstBootEntry, SetBootNext);
if (EfiBootInst.FileExists (L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc"))
{
@@ -3120,37 +3428,40 @@ namespace VeraCrypt
EfiBootConf conf;
if (EfiBootInst.ReadConfig (L"\\EFI\\VeraCrypt\\DcsProp", conf) && strlen (conf.actionSuccessValue.c_str()))
{
- string actionValue = conf.actionSuccessValue;
- std::transform(actionValue.begin(), actionValue.end(), actionValue.begin(), ::tolower);
-
- if (strstr (actionValue.c_str(), "postexec") && strstr (actionValue.c_str(), "file("))
+ wstring loaderPath;
+ if (EfiBootConf::IsPostExecFileField (conf.actionSuccessValue, loaderPath))
{
- char c;
- const char* ptr = strstr (actionValue.c_str(), "file(");
- ptr += 5;
- wstring loaderPath = L"\\";
- while ((c = *ptr))
+ // check that it is not bootmgfw.efi
+ if ( (0 != _wcsicmp (loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi"))
+ && (EfiBootInst.FileExists (loaderPath.c_str()))
+ )
{
- if (c == ')' || c == ' ')
- break;
- loaderPath += (wchar_t) c;
- ptr++;
+ // look for bootmgfw.efi identifiant string
+ EfiBootInst.GetFileSize(loaderPath.c_str(), loaderSize);
+ std::vector<byte> bootLoaderBuf ((size_t) loaderSize);
+
+ EfiBootInst.ReadFile(loaderPath.c_str(), &bootLoaderBuf[0], (DWORD) loaderSize);
+
+ // look for bootmgfw.efi identifiant string
+ if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, g_szMsBootString, strlen (g_szMsBootString)))
+ {
+ bFound = true;
+ EfiBootInst.RenameFile(loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc", TRUE);
+ }
}
- bFound = true;
- EfiBootInst.RenameFile(loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc", TRUE);
}
}
- if (!bFound)
+ if (!bFound && !PostOOBEMode)
throw ErrorException ("WINDOWS_EFI_BOOT_LOADER_MISSING", SRC_POS);
}
}
- if (PostOOBEMode)
- {
+ if (PostOOBEMode && EfiBootInst.FileExists (L"\\EFI\\VeraCrypt\\DcsBoot.efi"))
+ {
// check if bootmgfw.efi has been set again to Microsoft version
// if yes, replace it with our bootloader after it was copied to bootmgfw_ms.vc
- if (!bModifiedMsBoot)
+ if (!bModifiedMsBoot || bMissingMsBoot)
EfiBootInst.CopyFile (L"\\EFI\\VeraCrypt\\DcsBoot.efi", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
if (EfiBootInst.FileExists (szStdEfiBootloader))
@@ -3244,50 +3555,67 @@ namespace VeraCrypt
}
else
{
- byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE] = {0};
- CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation);
+ try
+ {
+ byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE] = {0};
+ CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation);
- // Write MBR
- byte mbr[TC_SECTOR_SIZE_BIOS];
+ // Write MBR
+ byte mbr[TC_SECTOR_SIZE_BIOS];
- device.SeekAt (0);
- device.Read (mbr, sizeof (mbr));
+ device.SeekAt (0);
+ device.Read (mbr, sizeof (mbr));
- if (preserveUserConfig && BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME))
- {
- uint16 version = BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET));
- if (version != 0)
+ if (preserveUserConfig && BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME))
{
- bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET];
- memcpy (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH);
-
- if (bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] & TC_BOOT_USER_CFG_FLAG_DISABLE_PIM)
+ uint16 version = BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET));
+ if (version != 0)
{
- if (pim >= 0)
+ bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET];
+ memcpy (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH);
+
+ if (bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] & TC_BOOT_USER_CFG_FLAG_DISABLE_PIM)
{
- memcpy (bootLoaderBuf + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &pim, TC_BOOT_SECTOR_PIM_VALUE_SIZE);
+ if (pim >= 0)
+ {
+ memcpy (bootLoaderBuf + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &pim, TC_BOOT_SECTOR_PIM_VALUE_SIZE);
+ }
+ else
+ memcpy (bootLoaderBuf + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, mbr + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, TC_BOOT_SECTOR_PIM_VALUE_SIZE);
}
- else
- memcpy (bootLoaderBuf + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, mbr + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, TC_BOOT_SECTOR_PIM_VALUE_SIZE);
}
}
- }
- memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE);
+ // perform actual write only if content is different and either we are not in PostOOBE mode or the MBR contains VeraCrypt/Windows signature.
+ // this last check is done to avoid interfering with multi-boot configuration where MBR belongs to a boot manager like Grub
+ if (memcmp (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE)
+ && (!PostOOBEMode || BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME) || IsWindowsMBR (mbr, sizeof (mbr))))
+ {
+ memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE);
- device.SeekAt (0);
- device.Write (mbr, sizeof (mbr));
+ device.SeekAt (0);
+ device.Write (mbr, sizeof (mbr));
- byte mbrVerificationBuf[TC_SECTOR_SIZE_BIOS];
- device.SeekAt (0);
- device.Read (mbrVerificationBuf, sizeof (mbr));
+ byte mbrVerificationBuf[TC_SECTOR_SIZE_BIOS];
+ device.SeekAt (0);
+ device.Read (mbrVerificationBuf, sizeof (mbr));
- if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
- throw ErrorException ("ERROR_MBR_PROTECTED", SRC_POS);
+ if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
+ throw ErrorException ("ERROR_MBR_PROTECTED", SRC_POS);
+ }
- // Write boot loader
- device.SeekAt (TC_SECTOR_SIZE_BIOS);
- device.Write (bootLoaderBuf + TC_SECTOR_SIZE_BIOS, sizeof (bootLoaderBuf) - TC_SECTOR_SIZE_BIOS);
+ if (!PostOOBEMode)
+ {
+ // Write boot loader
+ device.SeekAt (TC_SECTOR_SIZE_BIOS);
+ device.Write (bootLoaderBuf + TC_SECTOR_SIZE_BIOS, sizeof (bootLoaderBuf) - TC_SECTOR_SIZE_BIOS);
+ }
+ }
+ catch (...)
+ {
+ if (!PostOOBEMode)
+ throw;
+ }
}
if (!IsAdmin() && IsUacSupported())
@@ -3441,16 +3769,23 @@ namespace VeraCrypt
if (!DcsInfoImg)
throw ParameterIncorrect (SRC_POS);
- char szTmpPath[MAX_PATH + 1], szTmpFilePath[MAX_PATH + 1];
- if (!GetTempPathA (MAX_PATH, szTmpPath))
+ WCHAR szTmpPath[MAX_PATH + 1], szTmpFilePath[MAX_PATH + 1];
+ if (!GetTempPathW (MAX_PATH, szTmpPath))
throw SystemException (SRC_POS);
- if (!GetTempFileNameA (szTmpPath, "_vrd", 0, szTmpFilePath))
+ if (!GetTempFileNameW (szTmpPath, L"_vrd", 0, szTmpFilePath))
throw SystemException (SRC_POS);
- finally_do_arg (char*, szTmpFilePath, { DeleteFileA (finally_arg);});
+ finally_do_arg (WCHAR*, szTmpFilePath, { DeleteFileW (finally_arg);});
int ierr;
- zip_t* z = zip_open (szTmpFilePath, ZIP_CREATE | ZIP_TRUNCATE | ZIP_CHECKCONS, &ierr);
+
+ // convert szTmpFilePath to UTF-8 since this is what zip_open expected
+ char szUtf8Path[2*MAX_PATH + 1];
+ int utf8Len = WideCharToMultiByte (CP_UTF8, 0, szTmpFilePath, -1, szUtf8Path, sizeof (szUtf8Path), NULL, NULL);
+ if (utf8Len <= 0)
+ throw SystemException (SRC_POS);
+
+ zip_t* z = zip_open (szUtf8Path, ZIP_CREATE | ZIP_TRUNCATE | ZIP_CHECKCONS, &ierr);
if (!z)
throw ParameterIncorrect (SRC_POS);
@@ -3542,7 +3877,7 @@ namespace VeraCrypt
z = NULL;
// read the zip data from the temporary file
- FILE* ftmpFile = fopen (szTmpFilePath, "rb");
+ FILE* ftmpFile = _wfopen (szTmpFilePath, L"rb");
if (!ftmpFile)
throw ParameterIncorrect (SRC_POS);
@@ -4230,24 +4565,27 @@ namespace VeraCrypt
EfiBootConf conf;
if (EfiBootInst.ReadConfig (L"\\EFI\\VeraCrypt\\DcsProp", conf) && strlen (conf.actionSuccessValue.c_str()))
{
- string actionValue = conf.actionSuccessValue;
- std::transform(actionValue.begin(), actionValue.end(), actionValue.begin(), ::tolower);
-
- if (strstr (actionValue.c_str(), "postexec") && strstr (actionValue.c_str(), "file("))
+ wstring loaderPath;
+ if (EfiBootConf::IsPostExecFileField (conf.actionSuccessValue, loaderPath))
{
- char c;
- const char* ptr = strstr (actionValue.c_str(), "file(");
- ptr += 5;
- wstring loaderPath = L"\\";
- while ((c = *ptr))
+ // check that it is not bootmgfw_ms.vc or bootmgfw.efi
+ if ( (0 != _wcsicmp (loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc"))
+ && (0 != _wcsicmp (loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi"))
+ )
{
- if (c == ')' || c == ' ')
- break;
- loaderPath += (wchar_t) c;
- ptr++;
- }
+ const char* g_szMsBootString = "bootmgfw.pdb";
+ unsigned __int64 loaderSize = 0;
+ EfiBootInst.GetFileSize(loaderPath.c_str(), loaderSize);
+ std::vector<byte> bootLoaderBuf ((size_t) loaderSize);
+
+ EfiBootInst.ReadFile(loaderPath.c_str(), &bootLoaderBuf[0], (DWORD) loaderSize);
- EfiBootInst.RenameFile(loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", TRUE);
+ // look for bootmgfw.efi identifiant string
+ if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, g_szMsBootString, strlen (g_szMsBootString)))
+ {
+ EfiBootInst.RenameFile(loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", TRUE);
+ }
+ }
}
}
}
@@ -4567,6 +4905,16 @@ namespace VeraCrypt
if (registerService)
{
+ // check if service already exists.
+ // If yes then start it immediatly after reinstalling it
+ bool bAlreadyExists = false;
+ SC_HANDLE service = OpenService (scm, TC_SYSTEM_FAVORITES_SERVICE_NAME, GENERIC_READ);
+ if (service)
+ {
+ bAlreadyExists = true;
+ CloseServiceHandle (service);
+ }
+
try
{
RegisterSystemFavoritesService (FALSE, noFileHandling);
@@ -4577,11 +4925,19 @@ namespace VeraCrypt
{
wchar_t appPath[TC_MAX_PATH];
throw_sys_if (!GetModuleFileName (NULL, appPath, ARRAYSIZE (appPath)));
-
+ /* explicitely specify VeraCrypt.exe as the file to copy and don't rely
+ * on the fact we will be always called by VeraCrypt.exe because it's not
+ * always true.
+ */
+ wchar_t* ptr = wcsrchr (appPath, L'\\');
+ if (ptr)
+ ptr[1] = 0;
+ StringCchCatW (appPath, ARRAYSIZE (appPath), _T(TC_APP_NAME) L".exe");
+
throw_sys_if (!CopyFile (appPath, servicePath.c_str(), FALSE));
}
- SC_HANDLE service = CreateService (scm,
+ service = CreateService (scm,
TC_SYSTEM_FAVORITES_SERVICE_NAME,
_T(TC_APP_NAME) L" System Favorites",
SERVICE_ALL_ACCESS,
@@ -4601,6 +4957,10 @@ namespace VeraCrypt
description.lpDescription = L"Mounts VeraCrypt system favorite volumes.";
ChangeServiceConfig2 (service, SERVICE_CONFIG_DESCRIPTION, &description);
+ // start the service immediatly if it already existed before
+ if (bAlreadyExists)
+ StartService (service, 0, NULL);
+
CloseServiceHandle (service);
try
@@ -4642,6 +5002,30 @@ namespace VeraCrypt
}
}
+ bool BootEncryption::IsSystemFavoritesServiceRunning ()
+ {
+ bool bRet = false;
+ SC_HANDLE scm = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT);
+ if (scm)
+ {
+ SC_HANDLE service = OpenService(scm, TC_SYSTEM_FAVORITES_SERVICE_NAME, GENERIC_READ);
+ if (service)
+ {
+ SERVICE_STATUS status;
+ if (QueryServiceStatus(service, &status))
+ {
+ bRet = (status.dwCurrentState == SERVICE_RUNNING);
+ }
+
+ CloseServiceHandle(service);
+ }
+
+ CloseServiceHandle (scm);
+ }
+
+ return bRet;
+ }
+
void BootEncryption::UpdateSystemFavoritesService ()
{
SC_HANDLE scm = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
@@ -4785,16 +5169,19 @@ namespace VeraCrypt
#endif
#ifndef SETUP
void BootEncryption::CheckRequirements ()
- {
- if (nCurrentOS == WIN_2000)
- throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS", SRC_POS);
-
+ {
if (CurrentOSMajor == 6 && CurrentOSMinor == 0 && CurrentOSServicePack < 1)
throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_VISTA_SP0", SRC_POS);
if (IsNonInstallMode())
throw ErrorException ("FEATURE_REQUIRES_INSTALLATION", SRC_POS);
+ /* check if the system drive is already encrypted by BitLocker */
+ wchar_t windowsDrive = (wchar_t) towupper (GetWindowsDirectory()[0]);
+ BitLockerEncryptionStatus bitLockerStatus = GetBitLockerEncryptionStatus (windowsDrive);
+ if (bitLockerStatus == BL_Status_Protected)
+ throw ErrorException ("SYSENC_BITLOCKER_CONFLICT", SRC_POS);
+
SystemDriveConfiguration config = GetSystemDriveConfiguration ();
if (SystemDriveIsDynamic())
diff --git a/src/Common/BootEncryption.h b/src/Common/BootEncryption.h
index 0b5fe4f..decacb8 100644
--- a/src/Common/BootEncryption.h
+++ b/src/Common/BootEncryption.h
@@ -29,6 +29,10 @@ typedef NTSTATUS (WINAPI *NtQuerySystemInformationFn)(
PULONG ReturnLength
);
+typedef ULONG (WINAPI *RtlNtStatusToDosErrorFn)(
+ NTSTATUS Status
+);
+
using namespace std;
namespace VeraCrypt
@@ -189,9 +193,11 @@ namespace VeraCrypt
BOOL Load (const wchar_t* fileName);
void Load (char* configContent);
BOOL Save (const wchar_t* fileName, HWND hwnd);
+ static BOOL IsPostExecFileField (const string& szFieldValue, string& filePath);
+ static BOOL IsPostExecFileField (const string& szFieldValue, wstring& filePath);
};
- void GetVolumeESP(wstring& path);
+ void GetVolumeESP(wstring& path, wstring& bootVolumePath);
std::string ReadESPFile (LPCWSTR szFilePath, bool bSkipUTF8BOM);
void WriteESPFile (LPCWSTR szFilePath, LPBYTE pbData, DWORD dwDataLen, bool bAddUTF8BOM);
@@ -199,16 +205,18 @@ namespace VeraCrypt
public:
EfiBoot();
- void PrepareBootPartition();
+ void PrepareBootPartition(bool bDisableException = false);
bool IsEfiBoot();
void DeleteStartExec(uint16 statrtOrderNum = 0xDC5B, wchar_t* type = NULL);
- void SetStartExec(wstring description, wstring execPath, uint16 statrtOrderNum = 0xDC5B, wchar_t* type = NULL, uint32 attr = 1);
+ void SetStartExec(wstring description, wstring execPath, bool setBootEntry = true, bool forceFirstBootEntry = true, bool setBootNext = true, uint16 statrtOrderNum = 0xDC5B, wchar_t* type = NULL, uint32 attr = 1);
void SaveFile(const wchar_t* name, byte* data, DWORD size);
void GetFileSize(const wchar_t* name, unsigned __int64& size);
void ReadFile(const wchar_t* name, byte* data, DWORD size);
void CopyFile(const wchar_t* name, const wchar_t* targetName);
bool FileExists(const wchar_t* name);
+ static bool CompareFiles (const wchar_t* fileName1, const wchar_t* fileName2);
+ static bool CompareFileData (const wchar_t* fileName, const byte* data, DWORD size);
BOOL RenameFile(const wchar_t* name, const wchar_t* nameNew, BOOL bForce);
BOOL DelFile(const wchar_t* name);
@@ -217,23 +225,22 @@ namespace VeraCrypt
BOOL UpdateConfig (const wchar_t* name, int pim, int hashAlgo, HWND hwndDlg);
BOOL WriteConfig (const wchar_t* name, bool preserveUserConfig, int pim, int hashAlgo, const char* passPromptMsg, HWND hwndDlg);
BOOL DelDir(const wchar_t* name);
- void SelectBootVolumeESP();
- PSTORAGE_DEVICE_NUMBER GetStorageDeviceNumber () { return &sdn;}
+ PSTORAGE_DEVICE_NUMBER GetStorageDeviceNumber () { if (bDeviceInfoValid) return &sdn; else { SetLastError (ERROR_INVALID_DRIVE); throw SystemException(SRC_POS);}}
protected:
bool m_bMounted;
std::wstring EfiBootPartPath;
STORAGE_DEVICE_NUMBER sdn;
PARTITION_INFORMATION_EX partInfo;
+ bool bDeviceInfoValid;
WCHAR tempBuf[1024];
- bool bBootVolumePathSelected;
std::wstring BootVolumePath;
};
class BootEncryption
{
public:
- BootEncryption (HWND parent, bool postOOBE = false);
+ BootEncryption (HWND parent, bool postOOBE = false, bool setBootEntry = true, bool forceFirstBootEntry = true, bool setBootNext = false);
~BootEncryption ();
enum FilterType
@@ -285,6 +292,7 @@ namespace VeraCrypt
void RegisterFilterDriver (bool registerDriver, FilterType filterType);
void RegisterSystemFavoritesService (BOOL registerService);
void RegisterSystemFavoritesService (BOOL registerService, BOOL noFileHandling);
+ bool IsSystemFavoritesServiceRunning ();
void UpdateSystemFavoritesService ();
void RenameDeprecatedSystemLoaderBackup ();
bool RestartComputer (BOOL bShutdown = FALSE);
@@ -344,6 +352,9 @@ namespace VeraCrypt
bool RescueVolumeHeaderValid;
bool VolumeHeaderValid;
bool PostOOBEMode;
+ bool SetBootNext;
+ bool SetBootEntry;
+ bool ForceFirstBootEntry;
};
}
@@ -361,6 +372,9 @@ namespace VeraCrypt
#define VC_SYSTEM_FAVORITES_SERVICE_ARG_SKIP_MOUNT L"/SkipMount"
#define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_UPDATE_LOADER 0x1
+#define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_FORCE_SET_BOOTNEXT 0x2
+#define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_SET_BOOTENTRY 0x4
+#define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_FORCE_FIRST_BOOTENTRY 0x8
#define VC_WINDOWS_UPGRADE_POSTOOBE_CMDLINE_OPTION L"/PostOOBE"
diff --git a/src/Common/Cmdline.c b/src/Common/Cmdline.c
index d205673..f0dcf7c 100644
--- a/src/Common/Cmdline.c
+++ b/src/Common/Cmdline.c
@@ -70,9 +70,9 @@ BOOL CALLBACK CommandHelpDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM
StringCchCatW(tmp, 8192, tmp2);
}
}
-
+#if defined(TCMOUNT) && !defined(VCEXPANDER)
StringCchCatW (tmp, 8192, L"\nExamples:\n\nMount a volume as X:\tveracrypt.exe /q /v volume.hc /l X\nDismount a volume X:\tveracrypt.exe /q /d X");
-
+#endif
SetWindowTextW (GetDlgItem (hwndDlg, IDC_COMMANDHELP_TEXT), tmp);
TCfree(tmp);
diff --git a/src/Common/Common.rc b/src/Common/Common.rc
index 60ea0a5..d55e31b 100644
--- a/src/Common/Common.rc
+++ b/src/Common/Common.rc
@@ -65,39 +65,39 @@ BEGIN
PUSHBUTTON "Cancel",IDCANCEL,248,190,50,14
END
-IDD_MOUNT_OPTIONS DIALOGEX 0, 0, 277, 244
+IDD_MOUNT_OPTIONS DIALOGEX 0, 0, 310, 244
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "VeraCrypt - Mount Options"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
- CONTROL "Mount volume as read-&only",IDC_MOUNT_READONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,11,194,10
+ CONTROL "Mount volume as read-&only",IDC_MOUNT_READONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,11,231,10
CONTROL "Mount volume as removable &medium",IDC_MOUNT_REMOVABLE,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,25,195,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,25,231,10
CONTROL "Use backup header embedded in &volume if available",IDC_USE_EMBEDDED_HEADER_BAK,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,39,257,11
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,39,295,11
CONTROL "Mount partition &using system encryption without pre-boot authentication",IDC_MOUNT_SYSENC_PART_WITHOUT_PBA,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,53,259,11
- EDITTEXT IDC_VOLUME_LABEL,112,82,150,14,ES_AUTOHSCROLL
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,53,295,11
+ EDITTEXT IDC_VOLUME_LABEL,134,82,167,14,ES_AUTOHSCROLL
CONTROL "&Protect hidden volume against damage caused by writing to outer volume",IDC_PROTECT_HIDDEN_VOL,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,115,252,10
- EDITTEXT IDC_PASSWORD_PROT_HIDVOL,112,133,151,14,ES_PASSWORD | ES_AUTOHSCROLL
- COMBOBOX IDC_PKCS5_PRF_ID,112,154,91,90,CBS_DROPDOWNLIST | WS_TABSTOP
- EDITTEXT IDC_PIM,112,174,42,14,ES_RIGHT | ES_PASSWORD | ES_AUTOHSCROLL | ES_NUMBER | NOT WS_VISIBLE
- CONTROL "Use P&IM",IDC_PIM_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,112,179,97,10
- LTEXT "(Empty or 0 for default iterations)",IDC_PIM_HELP,158,177,112,8,NOT WS_VISIBLE
- CONTROL "&Display password",IDC_SHOW_PASSWORD_MO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,112,192,90,10
- CONTROL "U&se keyfiles",IDC_KEYFILES_ENABLE_HIDVOL_PROT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,112,205,90,10
- PUSHBUTTON "&Keyfiles...",IDC_KEYFILES_HIDVOL_PROT,204,201,60,14
- DEFPUSHBUTTON "OK",IDOK,211,7,60,14
- PUSHBUTTON "Cancel",IDCANCEL,211,24,60,14
- LTEXT "What is hidden volume protection?",IDC_LINK_HIDVOL_PROTECTION_INFO,16,220,247,10,SS_NOTIFY
- RTEXT "P&assword to hidden volume:\n(if empty, cache is used)",IDT_HIDDEN_PROT_PASSWD,15,132,91,17,0,WS_EX_RIGHT
- GROUPBOX "Hidden Volume Protection",IDT_HIDDEN_VOL_PROTECTION,6,101,265,136
- RTEXT "PKCS-5 PRF:",IDT_PKCS5_PRF,15,155,91,17
- RTEXT "Volume PIM:",IDT_PIM,15,177,91,17,NOT WS_VISIBLE
- LTEXT "Volume Label in Windows:",IDT_VOLUME_LABEL,12,85,95,8
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,115,283,10
+ EDITTEXT IDC_PASSWORD_PROT_HIDVOL,134,133,167,14,ES_PASSWORD | ES_AUTOHSCROLL
+ COMBOBOX IDC_PKCS5_PRF_ID,134,154,91,90,CBS_DROPDOWNLIST | WS_TABSTOP
+ EDITTEXT IDC_PIM,134,174,42,14,ES_RIGHT | ES_PASSWORD | ES_AUTOHSCROLL | ES_NUMBER | NOT WS_VISIBLE
+ CONTROL "Use P&IM",IDC_PIM_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,134,179,97,10
+ LTEXT "(Empty or 0 for default iterations)",IDC_PIM_HELP,181,177,121,8,NOT WS_VISIBLE
+ CONTROL "&Display password",IDC_SHOW_PASSWORD_MO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,134,192,90,10
+ CONTROL "U&se keyfiles",IDC_KEYFILES_ENABLE_HIDVOL_PROT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,134,205,90,10
+ PUSHBUTTON "&Keyfiles...",IDC_KEYFILES_HIDVOL_PROT,239,201,60,14
+ DEFPUSHBUTTON "OK",IDOK,246,7,60,14
+ PUSHBUTTON "Cancel",IDCANCEL,246,24,60,14
+ LTEXT "What is hidden volume protection?",IDC_LINK_HIDVOL_PROTECTION_INFO,16,220,279,10,SS_NOTIFY
+ RTEXT "P&assword to hidden volume:\n(if empty, cache is used)",IDT_HIDDEN_PROT_PASSWD,15,132,115,17,0,WS_EX_RIGHT
+ GROUPBOX "Hidden Volume Protection",IDT_HIDDEN_VOL_PROTECTION,6,101,299,136
+ RTEXT "PKCS-5 PRF:",IDT_PKCS5_PRF,15,155,115,17
+ RTEXT "Volume PIM:",IDT_PIM,15,177,115,17,NOT WS_VISIBLE
+ LTEXT "Volume Label in Windows:",IDT_VOLUME_LABEL,12,85,115,8
CONTROL "Only create virtual device without mounting on selected drive letter",IDC_DISABLE_MOUNT_MANAGER,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,67,231,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,67,297,10
END
IDD_KEYFILES DIALOGEX 0, 0, 363, 251
@@ -375,6 +375,7 @@ BEGIN
IDD_MOUNT_OPTIONS, DIALOG
BEGIN
LEFTMARGIN, 7
+ RIGHTMARGIN, 309
TOPMARGIN, 7
BOTTOMMARGIN, 238
END
diff --git a/src/Common/Crypto.c b/src/Common/Crypto.c
index 501cd16..550de2b 100644
--- a/src/Common/Crypto.c
+++ b/src/Common/Crypto.c
@@ -252,7 +252,7 @@ void EncipherBlocks (int cipher, void *dataPtr, void *ks, size_t blockCount)
#endif
}
#endif
-#if CRYPTOPP_BOOL_X64
+#if CRYPTOPP_BOOL_X64 && !defined(CRYPTOPP_DISABLE_ASM)
else if (cipher == TWOFISH) {
twofish_encrypt_blocks(ks, data, data, (uint32) blockCount);
}
@@ -369,7 +369,7 @@ void DecipherBlocks (int cipher, void *dataPtr, void *ks, size_t blockCount)
#endif
}
#endif
-#if CRYPTOPP_BOOL_X64
+#if CRYPTOPP_BOOL_X64 && !defined(CRYPTOPP_DISABLE_ASM)
else if (cipher == TWOFISH) {
twofish_decrypt_blocks(ks, data, data, (uint32) blockCount);
}
@@ -464,7 +464,7 @@ BOOL CipherSupportsIntraDataUnitParallelization (int cipher)
|| (cipher == SERPENT && HasSSE2())
|| (cipher == KUZNYECHIK && HasSSE2())
#endif
-#if CRYPTOPP_BOOL_X64
+#if CRYPTOPP_BOOL_X64 && !defined(CRYPTOPP_DISABLE_ASM)
|| (cipher == TWOFISH)
|| (cipher == CAMELLIA)
#endif
@@ -1217,7 +1217,7 @@ BOOL IsHwEncryptionEnabled ()
#endif // !TC_WINDOWS_BOOT
-#ifndef TC_WINDOWS_BOOT
+#if !defined (TC_WINDOWS_BOOT) && !defined (_UEFI)
static BOOL CpuRngDisabled = TRUE;
static BOOL RamEncryptionEnabled = FALSE;
@@ -1243,7 +1243,10 @@ BOOL IsCpuRngEnabled ()
BOOL IsRamEncryptionSupported ()
{
#ifdef _WIN64
- return TRUE;
+ if (t1ha_selfcheck__t1ha2() == 0)
+ return TRUE;
+ else
+ return FALSE;
#else
return FALSE;
#endif
diff --git a/src/Common/Crypto.h b/src/Common/Crypto.h
index 600fee9..a31152f 100644
--- a/src/Common/Crypto.h
+++ b/src/Common/Crypto.h
@@ -208,10 +208,12 @@ typedef struct
# include "GostCipher.h"
# include "kuznyechik.h"
# include "Camellia.h"
+#if !defined (_UEFI)
# include "chachaRng.h"
# ifdef _WIN64
# include "t1ha.h"
# endif
+#endif
#else
# include "CamelliaSmall.h"
#endif
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c
index 64c1147..bd1f6f8 100644
--- a/src/Common/Dlgcode.c
+++ b/src/Common/Dlgcode.c
@@ -179,7 +179,7 @@ BOOL bInPlaceEncNonSysPending = FALSE; // TRUE if the non-system in-place encry
BOOL PimEnable = FALSE;
BOOL KeyFilesEnable = FALSE;
KeyFile *FirstKeyFile = NULL;
-KeyFilesDlgParam defaultKeyFilesParam;
+KeyFilesDlgParam defaultKeyFilesParam = {0};
BOOL IgnoreWmDeviceChange = FALSE;
BOOL DeviceChangeBroadcastDisabled = FALSE;
@@ -188,6 +188,10 @@ BOOL MountVolumesAsSystemFavorite = FALSE;
BOOL FavoriteMountOnArrivalInProgress = FALSE;
BOOL MultipleMountOperationInProgress = FALSE;
+volatile BOOL NeedPeriodicDeviceListUpdate = FALSE;
+BOOL DisablePeriodicDeviceListUpdate = FALSE;
+BOOL EnableMemoryProtection = FALSE;
+
BOOL WaitDialogDisplaying = FALSE;
/* Handle to the device driver */
@@ -221,6 +225,9 @@ 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 */
+BOOL bSecureDesktopOngoing = FALSE;
+
HINSTANCE hInst = NULL;
HCURSOR hCursor = NULL;
@@ -294,6 +301,7 @@ HMODULE hntmartadll = NULL;
HMODULE hwinscarddll = NULL;
HMODULE hmsvcrtdll = NULL;
HMODULE hWinTrustLib = NULL;
+HMODULE hAdvapi32Dll = NULL;
#define FREE_DLL(h) if (h) { FreeLibrary (h); h = NULL;}
@@ -330,6 +338,18 @@ typedef HRESULT (STDAPICALLTYPE *SHStrDupWPtr)(LPCWSTR psz, LPWSTR *ppwsz);
// ChangeWindowMessageFilter
typedef BOOL (WINAPI *ChangeWindowMessageFilterPtr) (UINT, DWORD);
+typedef BOOL (WINAPI *CreateProcessWithTokenWFn)(
+ __in HANDLE hToken,
+ __in DWORD dwLogonFlags,
+ __in_opt LPCWSTR lpApplicationName,
+ __inout_opt LPWSTR lpCommandLine,
+ __in DWORD dwCreationFlags,
+ __in_opt LPVOID lpEnvironment,
+ __in_opt LPCWSTR lpCurrentDirectory,
+ __in LPSTARTUPINFOW lpStartupInfo,
+ __out LPPROCESS_INFORMATION lpProcessInformation
+ );
+
SetDllDirectoryPtr SetDllDirectoryFn = NULL;
SetSearchPathModePtr SetSearchPathModeFn = NULL;
SetDefaultDllDirectoriesPtr SetDefaultDllDirectoriesFn = NULL;
@@ -344,6 +364,7 @@ SetupOpenInfFileWPtr SetupOpenInfFileWFn = NULL;
SHDeleteKeyWPtr SHDeleteKeyWFn = NULL;
SHStrDupWPtr SHStrDupWFn = NULL;
ChangeWindowMessageFilterPtr ChangeWindowMessageFilterFn = NULL;
+CreateProcessWithTokenWFn CreateProcessWithTokenWPtr = NULL;
typedef LONG (WINAPI *WINVERIFYTRUST)(HWND hwnd, GUID *pgActionID, LPVOID pWVTData);
typedef CRYPT_PROVIDER_DATA* (WINAPI *WTHELPERPROVDATAFROMSTATEDATA)(HANDLE hStateData);
@@ -360,12 +381,12 @@ static WTHELPERGETPROVSIGNERFROMCHAIN WTHelperGetProvSignerFromChainFn = NULL;
static WTHELPERGETPROVCERTFROMCHAIN WTHelperGetProvCertFromChainFn = NULL;
static unsigned char gpbSha1CodeSignCertFingerprint[64] = {
- 0xCD, 0xF3, 0x05, 0xAD, 0xAE, 0xD3, 0x91, 0xF2, 0x0D, 0x95, 0x95, 0xAC,
- 0x76, 0x09, 0x35, 0x53, 0x11, 0x00, 0x4D, 0xDD, 0x56, 0x02, 0xBD, 0x09,
- 0x76, 0x57, 0xE1, 0xFA, 0xFA, 0xF4, 0x86, 0x09, 0x28, 0xA4, 0x0D, 0x1C,
- 0x68, 0xE7, 0x68, 0x31, 0xD3, 0xB6, 0x62, 0x9C, 0x75, 0x91, 0xAB, 0xB5,
- 0x6F, 0x1A, 0x75, 0xE7, 0x13, 0x2F, 0xF1, 0xB1, 0x14, 0xBF, 0x5F, 0x00,
- 0x40, 0xCE, 0x17, 0x6C
+ 0x97, 0xE3, 0x36, 0xE0, 0x45, 0x21, 0xE9, 0x8A, 0xA7, 0xEA, 0xE8, 0x68,
+ 0x4A, 0x56, 0x02, 0xB2, 0xE7, 0x63, 0x59, 0x3A, 0x37, 0x03, 0x64, 0xC3,
+ 0x7D, 0xBF, 0xF8, 0x19, 0xDB, 0x39, 0x57, 0x41, 0x55, 0x00, 0x9C, 0xBE,
+ 0xFE, 0xA3, 0xBC, 0x0F, 0xE3, 0xD8, 0x34, 0x2D, 0x2F, 0xB4, 0x80, 0xBE,
+ 0xDD, 0xEA, 0xA7, 0xDB, 0xAD, 0x53, 0x07, 0x71, 0x1A, 0x12, 0x42, 0xB4,
+ 0xE9, 0x65, 0xA5, 0x61
};
typedef HRESULT (WINAPI *SHGETKNOWNFOLDERPATH) (
@@ -466,6 +487,10 @@ void FinalizeGlobalLocks ()
void cleanup ()
{
burn (&CmdTokenPin, sizeof (CmdTokenPin));
+#ifndef SETUP
+ KeyFileRemoveAll (&FirstKeyFile);
+ KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile);
+#endif
/* Cleanup the GDI fonts */
if (hFixedFont != NULL)
@@ -752,6 +777,7 @@ void AbortProcessDirect (wchar_t *abortMsg)
FREE_DLL (hntmartadll);
FREE_DLL (hwinscarddll);
FREE_DLL (hmsvcrtdll);
+ FREE_DLL (hAdvapi32Dll);
exit (1);
}
@@ -802,6 +828,7 @@ void AbortProcessSilent (void)
FREE_DLL (hntmartadll);
FREE_DLL (hwinscarddll);
FREE_DLL (hmsvcrtdll);
+ FREE_DLL (hAdvapi32Dll);
// Note that this function also causes localcleanup() to be called (see atexit())
exit (1);
@@ -1460,7 +1487,7 @@ BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam
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-2019 IDRIX. All rights reserved.\r\n"
+ L"Copyright \xA9 2013-2020 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"
@@ -1469,10 +1496,10 @@ BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam
L"Copyright \xA9 1999-2017 Dieter Baron and Thomas Klausner.\r\n"
L"Copyright \xA9 2013, Alexey Degtyarev. All rights reserved.\r\n"
L"Copyright \xA9 1999-2016 Jack Lloyd. All rights reserved.\r\n"
- L"Copyright \xA9 2013-2018 Stephan Mueller <smueller@chronox.de>\r\n\r\n"
+ L"Copyright \xA9 2013-2019 Stephan Mueller <smueller@chronox.de>\r\n\r\n"
L"This software as a whole:\r\n"
- L"Copyright \xA9 2013-2019 IDRIX. All rights reserved.\r\n\r\n"
+ L"Copyright \xA9 2013-2020 IDRIX. All rights reserved.\r\n\r\n"
L"An IDRIX Release");
@@ -2897,9 +2924,6 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine)
char langId[6];
InitCommonControlsPtr InitCommonControlsFn = NULL;
wchar_t modPath[MAX_PATH];
-
- /* Protect this process memory from being accessed by non-admin users */
- EnableProcessProtection ();
GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath));
@@ -3008,6 +3032,7 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine)
AbortProcess ("INIT_DLL");
LoadSystemDll (L"Riched20.dll", &hRichEditDll, FALSE, SRC_POS);
+ LoadSystemDll (L"Advapi32.dll", &hAdvapi32Dll, FALSE, SRC_POS);
#if !defined(SETUP)
if (!VerifyModuleSignature (modPath))
@@ -3041,6 +3066,9 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine)
#endif
}
+ // Get CreateProcessWithTokenW function pointer
+ CreateProcessWithTokenWPtr = (CreateProcessWithTokenWFn) GetProcAddress(hAdvapi32Dll, "CreateProcessWithTokenW");
+
/* Save the instance handle for later */
hInst = hInstance;
@@ -3265,6 +3293,7 @@ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine)
FREE_DLL (hntmartadll);
FREE_DLL (hwinscarddll);
FREE_DLL (hmsvcrtdll);
+ FREE_DLL (hAdvapi32Dll);
exit (1);
}
#endif
@@ -3310,6 +3339,7 @@ void FinalizeApp (void)
FREE_DLL (hntmartadll);
FREE_DLL (hwinscarddll);
FREE_DLL (hmsvcrtdll);
+ FREE_DLL (hAdvapi32Dll);
}
void InitHelpFileName (void)
@@ -3640,11 +3670,15 @@ struct _TEXT_EDIT_DIALOG_PARAM {
std::string& Text;
const WCHAR* Title;
- _TEXT_EDIT_DIALOG_PARAM(BOOL _readOnly, const WCHAR* title, std::string& _text) : Title(title), Text(_text), ReadOnly(_readOnly) {}
+ _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) {
- ReadOnly = other.ReadOnly;
- Text = other.Text;
- Title = other.Title;
+ if (this != &other)
+ {
+ ReadOnly = other.ReadOnly;
+ Text = other.Text;
+ Title = other.Title;
+ }
return *this;
}
};
@@ -5095,7 +5129,7 @@ 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;
@@ -5503,11 +5537,11 @@ static void DisplayBenchmarkResults (HWND hwndDlg)
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);
@@ -5544,13 +5578,11 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
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 ();
@@ -5757,6 +5789,10 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
if (EAInitMode (ci, ci->k2))
{
int i;
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ VcProtectKeys (ci, VcGetEncryptionID (ci));
+#endif
for (i = 0; i < 10; i++)
{
@@ -5778,6 +5814,11 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
if (!EAInitMode (ci, ci->k2))
goto counter_error;
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ VcProtectKeys (ci, VcGetEncryptionID (ci));
+#endif
+
if (QueryPerformanceCounter (&performanceCountStart) == 0)
goto counter_error;
@@ -5969,7 +6010,7 @@ BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP
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());
@@ -5980,13 +6021,12 @@ 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"));
}
@@ -6003,8 +6043,8 @@ BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP
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);
}
@@ -7364,6 +7404,15 @@ BOOL CheckFileExtension (wchar_t *fileName)
return FALSE;
}
+BOOL IsTrueCryptFileExtension (wchar_t *fileName)
+{
+ wchar_t *ext = wcsrchr (fileName, L'.');
+ if (ext && !_wcsicmp (ext, L".tc"))
+ return TRUE;
+ else
+ return FALSE;
+}
+
void CorrectFileName (wchar_t* fileName)
{
/* replace '/' by '\' */
@@ -7495,7 +7544,10 @@ int GetLastAvailableDrive ()
BOOL IsDriveAvailable (int driveNo)
{
- return (GetUsedLogicalDrives() & (1 << driveNo)) == 0;
+ if (driveNo >= 0 && driveNo < 26)
+ return (GetUsedLogicalDrives() & (1 << driveNo)) == 0;
+ else
+ return FALSE;
}
@@ -10014,12 +10066,6 @@ 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));
@@ -10493,25 +10539,37 @@ 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 ())
{
- // Try the secondary help file
- r = (int)ShellExecuteW (NULL, L"open", szHelpFile2, NULL, NULL, SW_SHOWNORMAL);
+ if (FileExists (szHelpFile))
+ SafeOpenURL (szHelpFile);
+ else if (FileExists (szHelpFile2))
+ SafeOpenURL (szHelpFile2);
+ else
+ Applink ("help");
+ }
+ else
+ {
+ int r = (int)ShellExecuteW (NULL, L"open", szHelpFile, 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;
+ // Try the secondary help file
+ r = (int)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 ();
+ }
}
}
@@ -11015,14 +11073,30 @@ void Applink (const char *dest)
CorrectURL (url);
}
- r = (int) ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL);
-
- if (((r == ERROR_FILE_NOT_FOUND) || (r == ERROR_PATH_NOT_FOUND)) && buildUrl)
+ if (IsAdmin ())
{
- // fallbacl to online resources
- StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page);
- ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL);
- }
+ if (buildUrl && !FileExists (url))
+ {
+ // fallbacl to online resources
+ StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page);
+ SafeOpenURL (url);
+ }
+ else
+ {
+ SafeOpenURL (url);
+ }
+ }
+ else
+ {
+ r = (int) ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL);
+
+ if (((r == ERROR_FILE_NOT_FOUND) || (r == ERROR_PATH_NOT_FOUND)) && buildUrl)
+ {
+ // fallbacl to online resources
+ StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page);
+ ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL);
+ }
+ }
Sleep (200);
NormalCursor ();
@@ -11136,7 +11210,7 @@ void InconsistencyResolved (char *techInfo)
}
-void ReportUnexpectedState (char *techInfo)
+void ReportUnexpectedState (const char *techInfo)
{
wchar_t finalMsg[8024];
@@ -11182,10 +11256,8 @@ 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)
{
@@ -11207,6 +11279,13 @@ 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
@@ -12029,7 +12108,7 @@ 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)
{
@@ -12556,6 +12635,8 @@ wstring FindDeviceByVolumeID (const BYTE volumeID [VOLUME_ID_SIZE], BOOL bFromSe
static std::vector<HostDevice> volumeIdCandidates;
EnterCriticalSection (&csMountableDevices);
+ if (!NeedPeriodicDeviceListUpdate)
+ UpdateMountableHostDeviceList ();
std::vector<HostDevice> newDevices = mountableDevices;
LeaveCriticalSection (&csMountableDevices);
@@ -12677,19 +12758,16 @@ 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 byte *buffer, size_t bufferSize, const byte *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;
}
@@ -12697,6 +12775,17 @@ BOOL BufferContainsString (const byte *buffer, size_t bufferSize, const char *st
}
+BOOL BufferContainsString (const byte *buffer, size_t bufferSize, const char *str)
+{
+ return BufferContainsPattern (buffer, bufferSize, (const byte*) str, strlen (str));
+}
+
+BOOL BufferContainsWideString (const byte *buffer, size_t bufferSize, const wchar_t *str)
+{
+ return BufferContainsPattern (buffer, bufferSize, (const byte*) str, 2 * wcslen (str));
+}
+
+
#ifndef SETUP
int AskNonSysInPlaceEncryptionResume (HWND hwndDlg, BOOL *pbDecrypt)
@@ -12979,7 +13068,7 @@ BOOL IsApplicationInstalled (const wchar_t *appName, BOOL b32bitApp)
}
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)
{
@@ -13096,7 +13185,7 @@ BOOL GetPassword (HWND hwndDlg, UINT ctrlID, char* passValue, int bufSize, BOOL
{
SetFocus (GetDlgItem(hwndDlg, ctrlID));
if (GetLastError () == ERROR_INSUFFICIENT_BUFFER)
- Error ("PASSWORD_UTF8_TOO_LONG", hwndDlg);
+ Error ((bufSize == (MAX_LEGACY_PASSWORD + 1))? "LEGACY_PASSWORD_UTF8_TOO_LONG": "PASSWORD_UTF8_TOO_LONG", hwndDlg);
else
Error ("PASSWORD_UTF8_INVALID", hwndDlg);
}
@@ -13384,7 +13473,8 @@ BOOL DeleteDirectory (const wchar_t* szDirName)
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);
}
@@ -13408,6 +13498,19 @@ static BOOL GenerateRandomString (HWND hwndDlg, LPTSTR szName, DWORD maxCharsCou
}
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;
@@ -13575,75 +13678,79 @@ INT_PTR SecureDesktopDialogBoxParam(
INT_PTR retValue = 0;
BOOL bEffectiveUseSecureDesktop = bCmdUseSecureDesktopValid? bCmdUseSecureDesktop : bUseSecureDesktop;
- if (bEffectiveUseSecureDesktop && GenerateRandomString (hWndParent, szDesktopName, 64))
+ if (bEffectiveUseSecureDesktop)
{
- map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList;
- DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS;
- HDESK hSecureDesk;
+ EnterCriticalSection (&csSecureDesktop);
+ bSecureDesktopOngoing = TRUE;
+ finally_do ({ bSecureDesktopOngoing = FALSE; LeaveCriticalSection (&csSecureDesktop); });
- HDESK hInputDesk = NULL;
+ if (GenerateRandomString (hWndParent, szDesktopName, 64))
+ {
+ map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList;
+ DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS;
+ HDESK hSecureDesk;
- EnterCriticalSection (&csSecureDesktop);
- finally_do ({ LeaveCriticalSection (&csSecureDesktop); });
+ HDESK hInputDesk = NULL;
- // wait for the input desktop to be available before switching to
- // secure desktop. Under Windows 10, the user session can be started
- // in the background even before the user has authenticated and in this
- // case, we wait for the user to be really authenticated before starting
- // secure desktop mechanism
+ // wait for the input desktop to be available before switching to
+ // secure desktop. Under Windows 10, the user session can be started
+ // in the background even before the user has authenticated and in this
+ // case, we wait for the user to be really authenticated before starting
+ // secure desktop mechanism
- while (!(hInputDesk = OpenInputDesktop (0, TRUE, GENERIC_READ)))
- {
- Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
- }
+ while (!(hInputDesk = OpenInputDesktop (0, TRUE, GENERIC_READ)))
+ {
+ Sleep (SECUREDESKTOP_MONOTIR_PERIOD);
+ }
- CloseDesktop (hInputDesk);
+ CloseDesktop (hInputDesk);
- // get the initial list of ctfmon.exe processes before creating new desktop
- GetCtfMonProcessIdList (ctfmonBeforeList);
-
- hSecureDesk = CreateDesktop (szDesktopName, NULL, NULL, 0, desktopAccess, NULL);
- if (hSecureDesk)
- {
- SecureDesktopThreadParam param;
-
- param.hDesk = hSecureDesk;
- param.szDesktopName = szDesktopName;
- param.hInstance = hInstance;
- param.lpTemplateName = lpTemplateName;
- param.lpDialogFunc = lpDialogFunc;
- param.dwInitParam = dwInitParam;
- param.retValue = 0;
+ // get the initial list of ctfmon.exe processes before creating new desktop
+ GetCtfMonProcessIdList (ctfmonBeforeList);
- HANDLE hThread = ::CreateThread (NULL, 0, SecureDesktopThread, (LPVOID) &param, 0, NULL);
- if (hThread)
+ hSecureDesk = CreateDesktop (szDesktopName, NULL, NULL, 0, desktopAccess, NULL);
+ if (hSecureDesk)
{
- WaitForSingleObject (hThread, INFINITE);
- CloseHandle (hThread);
+ SecureDesktopThreadParam param;
+
+ param.hDesk = hSecureDesk;
+ param.szDesktopName = szDesktopName;
+ param.hInstance = hInstance;
+ param.lpTemplateName = lpTemplateName;
+ param.lpDialogFunc = lpDialogFunc;
+ param.dwInitParam = dwInitParam;
+ param.retValue = 0;
+
+ HANDLE hThread = ::CreateThread (NULL, 0, SecureDesktopThread, (LPVOID) &param, 0, NULL);
+ if (hThread)
+ {
+ WaitForSingleObject (hThread, INFINITE);
+ CloseHandle (hThread);
- retValue = param.retValue;
- bSuccess = TRUE;
- }
+ retValue = param.retValue;
+ bSuccess = TRUE;
+ }
- CloseDesktop (hSecureDesk);
+ CloseDesktop (hSecureDesk);
- // get the new list of ctfmon.exe processes in order to find the ID of the
- // ctfmon.exe instance that corresponds to the desktop we create so that
- // we can kill it, otherwise it would remain running
- GetCtfMonProcessIdList (ctfmonAfterList);
+ // get the new list of ctfmon.exe processes in order to find the ID of the
+ // ctfmon.exe instance that corresponds to the desktop we create so that
+ // we can kill it, otherwise it would remain running
+ GetCtfMonProcessIdList (ctfmonAfterList);
- for (map<DWORD, BOOL>::iterator It = ctfmonAfterList.begin();
- It != ctfmonAfterList.end(); It++)
- {
- if (ctfmonBeforeList[It->first] != TRUE)
+ for (map<DWORD, BOOL>::iterator It = ctfmonAfterList.begin();
+ It != ctfmonAfterList.end(); It++)
{
- // Kill process
- KillProcess (It->first);
+ if (ctfmonBeforeList[It->first] != TRUE)
+ {
+ // Kill process
+ KillProcess (It->first);
+ }
}
}
- }
- burn (szDesktopName, sizeof (szDesktopName));
+ burn (szDesktopName, sizeof (szDesktopName));
+ }
}
if (!bSuccess)
@@ -13933,6 +14040,17 @@ BOOL EnableProcessProtection()
PACL pACL = NULL;
DWORD cbACL = 0;
+ // Acces mask
+ DWORD dwAccessMask = SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE; // same as protected process
+
+ 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;
@@ -13971,7 +14089,7 @@ BOOL EnableProcessProtection()
if (!AddAccessAllowedAce(
pACL,
ACL_REVISION,
- SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process
+ dwAccessMask,
pTokenUser->User.Sid // pointer to the trustee's SID
)) {
goto Cleanup;
@@ -14002,6 +14120,190 @@ Cleanup:
return bSuccess;
}
+// Based on sample code from:
+// https://blogs.msdn.microsoft.com/aaron_margosis/2009/06/06/faq-how-do-i-start-a-program-as-the-desktop-user-from-an-elevated-app/
+// start a program non-elevated as the desktop user from an elevated app
+
+static bool RunAsDesktopUser(
+ __in const wchar_t * szApp,
+ __in wchar_t * szCmdLine)
+{
+ HANDLE hThreadToken = NULL, hShellProcess = NULL, hShellProcessToken = NULL, hPrimaryToken = NULL;
+ HWND hwnd = NULL;
+ DWORD dwPID = 0;
+ BOOL ret;
+ DWORD dwLastErr;
+ STARTUPINFOW si;
+ PROCESS_INFORMATION pi;
+ bool retval = false;
+ SecureZeroMemory(&si, sizeof(si));
+ SecureZeroMemory(&pi, sizeof(pi));
+ si.cb = sizeof(si);
+
+ // locate CreateProcessWithTokenW in Advapi32.dll
+ if (!CreateProcessWithTokenWPtr)
+ {
+ return false;
+ }
+
+ if (!ImpersonateSelf (SecurityImpersonation))
+ {
+ return false;
+ }
+
+ if (!OpenThreadToken (GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, TRUE, &hThreadToken))
+ {
+ return false;
+ }
+ else
+ {
+ TOKEN_PRIVILEGES tkp;
+ tkp.PrivilegeCount = 1;
+ LookupPrivilegeValueW(NULL, SE_INCREASE_QUOTA_NAME, &tkp.Privileges[0].Luid);
+ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ SetThreadToken (NULL, NULL);
+
+ 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 = CreateProcessWithTokenWPtr(
+ 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);
+ RevertToSelf ();
+ 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;
+}
+
+// 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
+void SafeOpenURL (LPCWSTR szUrl)
+{
+ if (IsOSAtLeast (WIN_VISTA) && IsAdmin () && IsElevated())
+ {
+ 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);
+
+ RunAsDesktopUser (NULL, szCommandLine);
+
+ delete [] szCommandLine;
+ }
+ else
+ {
+ ShellExecuteW (NULL, L"open", szUrl, NULL, NULL, SW_SHOWNORMAL);
+ }
+}
+
#if !defined(SETUP) && defined(_WIN64)
#define RtlGenRandom SystemFunction036
@@ -14070,3 +14372,105 @@ void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed)
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 hShell32 = NULL;
+
+ CoInitialize(NULL);
+
+ if (GetSystemDirectory(szDllPath, MAX_PATH))
+ StringCchCatW(szDllPath, MAX_PATH, L"\\Shell32.dll");
+ else
+ StringCchCopyW(szDllPath, MAX_PATH, L"C:\\Windows\\System32\\Shell32.dll");
+
+ hShell32 = LoadLibrary(szDllPath);
+ if (hShell32)
+ {
+ SHCreateItemFromParsingNameFn SHCreateItemFromParsingNamePtr = (SHCreateItemFromParsingNameFn)GetProcAddress(hShell32, "SHCreateItemFromParsingName");
+ if (SHCreateItemFromParsingNamePtr)
+ {
+ HMODULE hPropsys = NULL;
+
+ if (GetSystemDirectory(szDllPath, MAX_PATH))
+ StringCchCatW(szDllPath, MAX_PATH, L"\\Propsys.dll");
+ else
+ StringCchCopyW(szDllPath, MAX_PATH, L"C:\\Windows\\System32\\Propsys.dll");
+
+ hPropsys = LoadLibrary(szDllPath);
+ if (hPropsys)
+ {
+ PSGetPropertyKeyFromNameFn PSGetPropertyKeyFromNamePtr = (PSGetPropertyKeyFromNameFn)GetProcAddress(hPropsys, "PSGetPropertyKeyFromName");
+ if (PSGetPropertyKeyFromNamePtr)
+ {
+ WCHAR parsingName[3] = {driveLetter, L':', 0};
+ IShellItem2* drive = NULL;
+ hr = SHCreateItemFromParsingNamePtr(parsingName, NULL, IID_PPV_ARGS(&drive));
+ 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);
+ }
+ }
+ else
+ {
+ blStatus = BL_Status_Unprotected; // before Vista, there was no Bitlocker
+ }
+
+ FreeLibrary(hShell32);
+ }
+
+ CoUninitialize();
+ return blStatus;
+}
diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h
index 54475cb..9e77c0a 100644
--- a/src/Common/Dlgcode.h
+++ b/src/Common/Dlgcode.h
@@ -124,6 +124,7 @@ extern BOOL bHideWaitingDialog;
extern BOOL bCmdHideWaitingDialog;
extern BOOL bCmdHideWaitingDialogValid;
extern BOOL bUseSecureDesktop;
+extern BOOL bSecureDesktopOngoing;
extern BOOL bUseLegacyMaxPasswordLength;
extern BOOL bCmdUseSecureDesktop;
extern BOOL bCmdUseSecureDesktopValid;
@@ -164,6 +165,10 @@ extern BOOL MountVolumesAsSystemFavorite;
extern BOOL FavoriteMountOnArrivalInProgress;
extern BOOL MultipleMountOperationInProgress;
+extern volatile BOOL NeedPeriodicDeviceListUpdate;
+extern BOOL DisablePeriodicDeviceListUpdate;
+extern BOOL EnableMemoryProtection;
+
#ifndef SETUP
extern BOOL bLanguageSetInSetup;
#endif
@@ -237,6 +242,13 @@ typedef struct
} OpenVolumeContext;
+typedef enum BitLockerEncryptionStatus
+{
+ BL_Status_Unknown = 0,
+ BL_Status_Unprotected,
+ BL_Status_Protected
+} BitLockerEncryptionStatus;
+
#define DEFAULT_VOL_CREATION_WIZARD_MODE WIZARD_MODE_FILE_CONTAINER
@@ -347,6 +359,7 @@ BOOL CloseVolumeExplorerWindows (HWND hwnd, int driveNo);
BOOL UpdateDriveCustomLabel (int driveNo, wchar_t* effectiveLabel, BOOL bSetValue);
BOOL CheckCapsLock (HWND hwnd, BOOL quiet);
BOOL CheckFileExtension (wchar_t *fileName);
+BOOL IsTrueCryptFileExtension (wchar_t *fileName);
void CorrectFileName (wchar_t* fileName);
void CorrectURL (wchar_t* fileName);
void IncreaseWrongPwdRetryCount (int count);
@@ -469,7 +482,7 @@ BOOL CALLBACK CloseTCWindowsEnum( HWND hwnd, LPARAM lParam);
BOOL CALLBACK FindTCWindowEnum (HWND hwnd, LPARAM lParam);
BYTE *MapResource (wchar_t *resourceType, int resourceId, PDWORD size);
void InconsistencyResolved (char *msg);
-void ReportUnexpectedState (char *techInfo);
+void ReportUnexpectedState (const char *techInfo);
BOOL SelectMultipleFiles (HWND hwndDlg, const char *stringId, wchar_t *lpszFileName, size_t cbFileName, BOOL keepHistory);
BOOL SelectMultipleFilesNext (wchar_t *lpszFileName, size_t cbFileName);
void OpenOnlineHelp ();
@@ -505,7 +518,9 @@ BOOL InitSecurityTokenLibrary (HWND hwndDlg);
BOOL FileHasReadOnlyAttribute (const wchar_t *path);
BOOL IsFileOnReadOnlyFilesystem (const wchar_t *path);
void CheckFilesystem (HWND hwndDlg, int driveNo, BOOL fixErrors);
+BOOL BufferContainsPattern (const byte *buffer, size_t bufferSize, const byte *pattern, size_t patternSize);
BOOL BufferContainsString (const byte *buffer, size_t bufferSize, const char *str);
+BOOL BufferContainsWideString (const byte *buffer, size_t bufferSize, const wchar_t *str);
int AskNonSysInPlaceEncryptionResume (HWND hwndDlg, BOOL* pbDecrypt);
BOOL RemoveDeviceWriteProtection (HWND hwndDlg, wchar_t *devicePath);
void EnableElevatedCursorChange (HWND parent);
@@ -539,6 +554,8 @@ void GetInstallationPath (HWND hwndDlg, wchar_t* szInstallPath, DWORD cchSize, B
BOOL GetSetupconfigLocation (wchar_t* path, DWORD cchSize);
BOOL BufferHasPattern (const unsigned char* buffer, size_t bufferLen, const void* pattern, size_t patternLen);
BOOL EnableProcessProtection();
+void SafeOpenURL (LPCWSTR szUrl);
+BitLockerEncryptionStatus GetBitLockerEncryptionStatus(WCHAR driveLetter);
#ifdef _WIN64
void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed);
#endif
@@ -592,6 +609,30 @@ struct HostDevice
~HostDevice () {}
+ HostDevice& operator= (const HostDevice& device)
+ {
+ if (this != &device)
+ {
+ Bootable = device.Bootable;
+ ContainsSystem = device.ContainsSystem;
+ DynamicVolume = device.DynamicVolume;
+ Floppy = device.Floppy;
+ IsPartition = device.IsPartition;
+ IsVirtualPartition = device.IsVirtualPartition;
+ HasUnencryptedFilesystem = device.HasUnencryptedFilesystem;
+ MountPoint = device.MountPoint;
+ Name = device.Name;
+ Path = device.Path;
+ Removable = device.Removable;
+ Size = device.Size;
+ SystemNumber = device.SystemNumber;
+ HasVolumeIDs = device.HasVolumeIDs;
+ Partitions = device.Partitions;
+ memcpy (VolumeIDs, device.VolumeIDs, sizeof (VolumeIDs));
+ }
+ return *this;
+ }
+
bool Bootable;
bool ContainsSystem;
bool DynamicVolume;
diff --git a/src/Common/EncryptionThreadPool.c b/src/Common/EncryptionThreadPool.c
index 461f284..1005279 100644
--- a/src/Common/EncryptionThreadPool.c
+++ b/src/Common/EncryptionThreadPool.c
@@ -16,9 +16,16 @@
#include "Driver/Ntdriver.h"
#endif
-#define TC_ENC_THREAD_POOL_MAX_THREAD_COUNT 64
+//Increasing the maximum number of threads
+#define TC_ENC_THREAD_POOL_MAX_THREAD_COUNT 256 //64
#define TC_ENC_THREAD_POOL_QUEUE_SIZE (TC_ENC_THREAD_POOL_MAX_THREAD_COUNT * 2)
+#define TC_ENC_THREAD_POOL_LEGACY_MAX_THREAD_COUNT 64
+#define TC_ENC_THREAD_POOL_LEGACY_QUEUE_SIZE (TC_ENC_THREAD_POOL_LEGACY_MAX_THREAD_COUNT * 2)
+
+static volatile size_t ThreadPoolCount = TC_ENC_THREAD_POOL_LEGACY_MAX_THREAD_COUNT;
+static volatile int ThreadQueueSize = TC_ENC_THREAD_POOL_LEGACY_QUEUE_SIZE;
+
#ifdef DEVICE_DRIVER
#define TC_THREAD_HANDLE PKTHREAD
@@ -43,6 +50,18 @@
#define TC_ACQUIRE_MUTEX(MUTEX) WaitForSingleObject (*(MUTEX), INFINITE)
#define TC_RELEASE_MUTEX(MUTEX) ReleaseMutex (*(MUTEX))
+typedef BOOL (WINAPI *SetThreadGroupAffinityFn)(
+ HANDLE hThread,
+ const GROUP_AFFINITY *GroupAffinity,
+ PGROUP_AFFINITY PreviousGroupAffinity
+);
+
+typedef WORD (WINAPI* GetActiveProcessorGroupCountFn)();
+
+typedef DWORD (WINAPI *GetActiveProcessorCountFn)(
+ WORD GroupNumber
+);
+
#endif // !DEVICE_DRIVER
@@ -99,6 +118,7 @@ static volatile BOOL StopPending = FALSE;
static uint32 ThreadCount;
static TC_THREAD_HANDLE ThreadHandles[TC_ENC_THREAD_POOL_MAX_THREAD_COUNT];
+static WORD ThreadProcessorGroups[TC_ENC_THREAD_POOL_MAX_THREAD_COUNT];
static EncryptionThreadPoolWorkItem WorkItemQueue[TC_ENC_THREAD_POOL_QUEUE_SIZE];
@@ -164,6 +184,23 @@ static void SetWorkItemState (EncryptionThreadPoolWorkItem *workItem, WorkItemSt
static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
{
EncryptionThreadPoolWorkItem *workItem;
+ if (threadArg)
+ {
+#ifdef DEVICE_DRIVER
+ SetThreadCpuGroupAffinity ((USHORT) *(WORD*)(threadArg));
+#else
+ SetThreadGroupAffinityFn SetThreadGroupAffinityPtr = (SetThreadGroupAffinityFn) GetProcAddress (GetModuleHandle (L"kernel32.dll"), "SetThreadGroupAffinity");
+ if (SetThreadGroupAffinityPtr && threadArg)
+ {
+ GROUP_AFFINITY groupAffinity = {0};
+ groupAffinity.Mask = ~0ULL;
+ groupAffinity.Group = *(WORD*)(threadArg);
+ SetThreadGroupAffinityPtr(GetCurrentThread(), &groupAffinity, NULL);
+ }
+
+#endif
+ }
+
while (!StopPending)
{
@@ -171,7 +208,7 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
workItem = &WorkItemQueue[DequeuePosition++];
- if (DequeuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE)
+ if (DequeuePosition >= ThreadQueueSize)
DequeuePosition = 0;
while (!StopPending && GetWorkItemState (workItem) != WorkItemReady)
@@ -260,23 +297,55 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
#endif
}
+#ifndef DEVICE_DRIVER
+
+size_t GetCpuCount (WORD* pGroupCount)
+{
+ size_t cpuCount = 0;
+ SYSTEM_INFO sysInfo;
+ GetActiveProcessorGroupCountFn GetActiveProcessorGroupCountPtr = (GetActiveProcessorGroupCountFn) GetProcAddress (GetModuleHandle (L"Kernel32.dll"), "GetActiveProcessorGroupCount");
+ GetActiveProcessorCountFn GetActiveProcessorCountPtr = (GetActiveProcessorCountFn) GetProcAddress (GetModuleHandle (L"Kernel32.dll"), "GetActiveProcessorCount");
+ if (GetActiveProcessorGroupCountPtr && GetActiveProcessorCountPtr)
+ {
+ WORD j, groupCount = GetActiveProcessorGroupCountPtr();
+ size_t totalProcessors = 0;
+ for (j = 0; j < groupCount; ++j)
+ {
+ totalProcessors += (size_t) GetActiveProcessorCountPtr(j);
+ }
+ cpuCount = totalProcessors;
+ if (pGroupCount)
+ *pGroupCount = groupCount;
+ }
+ else
+ {
+ GetSystemInfo(&sysInfo);
+ cpuCount = (size_t) sysInfo.dwNumberOfProcessors;
+ if (pGroupCount)
+ *pGroupCount = 1;
+ }
+
+ return cpuCount;
+}
+
+#endif
+
BOOL EncryptionThreadPoolStart (size_t encryptionFreeCpuCount)
{
- size_t cpuCount, i;
+ size_t cpuCount = 0, i = 0;
+ WORD groupCount = 1;
+
+ cpuCount = GetCpuCount(&groupCount);
if (ThreadPoolRunning)
return TRUE;
-#ifdef DEVICE_DRIVER
- cpuCount = GetCpuCount();
-#else
+ if (groupCount > 1)
{
- SYSTEM_INFO sysInfo;
- GetSystemInfo (&sysInfo);
- cpuCount = sysInfo.dwNumberOfProcessors;
+ ThreadPoolCount = TC_ENC_THREAD_POOL_MAX_THREAD_COUNT;
+ ThreadQueueSize = TC_ENC_THREAD_POOL_QUEUE_SIZE;
}
-#endif
if (cpuCount > encryptionFreeCpuCount)
cpuCount -= encryptionFreeCpuCount;
@@ -284,8 +353,8 @@ BOOL EncryptionThreadPoolStart (size_t encryptionFreeCpuCount)
if (cpuCount < 2)
return TRUE;
- if (cpuCount > TC_ENC_THREAD_POOL_MAX_THREAD_COUNT)
- cpuCount = TC_ENC_THREAD_POOL_MAX_THREAD_COUNT;
+ if (cpuCount > ThreadPoolCount)
+ cpuCount = ThreadPoolCount;
StopPending = FALSE;
DequeuePosition = 0;
@@ -337,11 +406,40 @@ BOOL EncryptionThreadPoolStart (size_t encryptionFreeCpuCount)
for (ThreadCount = 0; ThreadCount < cpuCount; ++ThreadCount)
{
+ WORD* pThreadArg = NULL;
+ if (groupCount > 1)
+ {
+#ifdef DEVICE_DRIVER
+ ThreadProcessorGroups[ThreadCount] = GetCpuGroup ((size_t) ThreadCount);
+#else
+ GetActiveProcessorCountFn GetActiveProcessorCountPtr = (GetActiveProcessorCountFn) GetProcAddress (GetModuleHandle (L"Kernel32.dll"), "GetActiveProcessorCount");
+ // Determine which processor group to bind the thread to.
+ if (GetActiveProcessorCountPtr)
+ {
+ WORD j;
+ uint32 totalProcessors = 0U;
+ for (j = 0U; j < groupCount; j++)
+ {
+ totalProcessors += (uint32) GetActiveProcessorCountPtr(j);
+ if (totalProcessors >= ThreadCount)
+ {
+ ThreadProcessorGroups[ThreadCount] = j;
+ break;
+ }
+ }
+ }
+ else
+ ThreadProcessorGroups[ThreadCount] = 0;
+#endif
+ pThreadArg = &ThreadProcessorGroups[ThreadCount];
+ }
+
#ifdef DEVICE_DRIVER
- if (!NT_SUCCESS (TCStartThread (EncryptionThreadProc, NULL, &ThreadHandles[ThreadCount])))
+ if (!NT_SUCCESS(TCStartThread(EncryptionThreadProc, (void*) pThreadArg, &ThreadHandles[ThreadCount])))
#else
- if (!(ThreadHandles[ThreadCount] = (HANDLE) _beginthreadex (NULL, 0, EncryptionThreadProc, NULL, 0, NULL)))
+ if (!(ThreadHandles[ThreadCount] = (HANDLE)_beginthreadex(NULL, 0, EncryptionThreadProc, (void*) pThreadArg, 0, NULL)))
#endif
+
{
EncryptionThreadPoolStop();
return FALSE;
@@ -402,7 +500,7 @@ void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT
TC_ACQUIRE_MUTEX (&EnqueueMutex);
workItem = &WorkItemQueue[EnqueuePosition++];
- if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE)
+ if (EnqueuePosition >= ThreadQueueSize)
EnqueuePosition = 0;
while (GetWorkItemState (workItem) != WorkItemFree)
@@ -501,7 +599,7 @@ void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data,
while (fragmentCount-- > 0)
{
workItem = &WorkItemQueue[EnqueuePosition++];
- if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE)
+ if (EnqueuePosition >= ThreadQueueSize)
EnqueuePosition = 0;
while (GetWorkItemState (workItem) != WorkItemFree)
@@ -543,7 +641,7 @@ size_t GetEncryptionThreadCount ()
size_t GetMaxEncryptionThreadCount ()
{
- return TC_ENC_THREAD_POOL_MAX_THREAD_COUNT;
+ return ThreadPoolCount;
}
diff --git a/src/Common/EncryptionThreadPool.h b/src/Common/EncryptionThreadPool.h
index 6a28062..161fb7c 100644
--- a/src/Common/EncryptionThreadPool.h
+++ b/src/Common/EncryptionThreadPool.h
@@ -27,6 +27,10 @@ typedef enum
DeriveKeyWork
} EncryptionThreadPoolWorkType;
+#ifndef DEVICE_DRIVER
+size_t GetCpuCount (WORD* pGroupCount);
+#endif
+
void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, char *password, int passwordLength, char *salt, int iterationCount, char *derivedKey);
void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data, const UINT64_STRUCT *startUnitNo, uint32 unitCount, PCRYPTO_INFO cryptoInfo);
BOOL EncryptionThreadPoolStart (size_t encryptionFreeCpuCount);
diff --git a/src/Common/Fat.c b/src/Common/Fat.c
index b47e531..cd2c124 100644
--- a/src/Common/Fat.c
+++ b/src/Common/Fat.c
@@ -394,6 +394,8 @@ FormatFat (void* hwndDlgPtr, unsigned __int64 startSector, fatparams * ft, void
if(!quickFormat)
{
+ CRYPTO_INFO tmpCI;
+
if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
goto fail;
@@ -402,26 +404,49 @@ FormatFat (void* hwndDlgPtr, unsigned __int64 startSector, fatparams * ft, void
deniability of hidden volumes (and also reduces the amount of predictable plaintext
within the volume). */
+ VirtualLock (&tmpCI, sizeof (tmpCI));
+ memcpy (&tmpCI, cryptoInfo, sizeof (CRYPTO_INFO));
+ cryptoInfo = &tmpCI;
+
// Temporary master key
if (!RandgetBytes (hwndDlg, temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
+ {
+ burn (&tmpCI, sizeof (tmpCI));
+ VirtualUnlock (&tmpCI, sizeof (tmpCI));
goto fail;
+ }
// Temporary secondary key (XTS mode)
if (!RandgetBytes (hwndDlg, cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE))
+ {
+ burn (&tmpCI, sizeof (tmpCI));
+ VirtualUnlock (&tmpCI, sizeof (tmpCI));
goto fail;
+ }
retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
if (retVal != ERR_SUCCESS)
{
+ TCfree (write_buf);
burn (temporaryKey, sizeof(temporaryKey));
+ burn (&tmpCI, sizeof (tmpCI));
+ VirtualUnlock (&tmpCI, sizeof (tmpCI));
return retVal;
}
if (!EAInitMode (cryptoInfo, cryptoInfo->k2))
{
+ TCfree (write_buf);
burn (temporaryKey, sizeof(temporaryKey));
+ burn (&tmpCI, sizeof (tmpCI));
+ VirtualUnlock (&tmpCI, sizeof (tmpCI));
return ERR_MODE_INIT_FAILED;
}
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ VcProtectKeys (cryptoInfo, VcGetEncryptionID (cryptoInfo));
+#endif
+
x = ft->num_sectors - ft->reserved - ft->size_root_dir / ft->sector_size - ft->fat_length * 2;
while (x--)
{
@@ -430,12 +455,24 @@ FormatFat (void* hwndDlgPtr, unsigned __int64 startSector, fatparams * ft, void
goto fail;
}
UpdateProgressBar (nSecNo * ft->sector_size);
+
+ if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
+ {
+ burn (&tmpCI, sizeof (tmpCI));
+ VirtualUnlock (&tmpCI, sizeof (tmpCI));
+ goto fail;
+ }
+
+ burn (&tmpCI, sizeof (tmpCI));
+ VirtualUnlock (&tmpCI, sizeof (tmpCI));
}
else
+ {
UpdateProgressBar ((uint64) ft->num_sectors * ft->sector_size);
- if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
- goto fail;
+ if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
+ goto fail;
+ }
TCfree (write_buf);
burn (temporaryKey, sizeof(temporaryKey));
diff --git a/src/Common/Format.c b/src/Common/Format.c
index bd33f75..f691c78 100644
--- a/src/Common/Format.c
+++ b/src/Common/Format.c
@@ -100,6 +100,10 @@ int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams)
LARGE_INTEGER offset;
BOOL bFailedRequiredDASD = FALSE;
HWND hwndDlg = volParams->hwndDlg;
+#ifdef _WIN64
+ CRYPTO_INFO tmpCI;
+ PCRYPTO_INFO cryptoInfoBackup = NULL;
+#endif
FormatSectorSize = volParams->sectorSize;
@@ -350,14 +354,32 @@ begin_format:
nStatus = ERR_OS_ERROR;
goto error;
}
+ else if (volParams->hiddenVol && bPreserveTimestamp)
+ {
+ // ensure that Last Access and Last Write timestamps are not modified
+ ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
+ ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
+
+ SetFileTime (dev, NULL, &ftLastAccessTime, NULL);
+
+ if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
+ bTimeStampValid = FALSE;
+ else
+ bTimeStampValid = TRUE;
+ }
DisableFileCompression (dev);
if (!volParams->hiddenVol && !bInstantRetryOtherFilesys)
{
LARGE_INTEGER volumeSize;
+ BOOL speedupFileCreation = FALSE;
volumeSize.QuadPart = dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
+ // speedup for file creation only makes sens when using quick format
+ if (volParams->quickFormat && volParams->fastCreateFile)
+ speedupFileCreation = TRUE;
+
if (volParams->sparseFileSwitch && volParams->quickFormat)
{
// Create as sparse file container
@@ -371,21 +393,29 @@ begin_format:
// Preallocate the file
if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
- || !SetEndOfFile (dev)
- || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
+ || !SetEndOfFile (dev))
{
nStatus = ERR_OS_ERROR;
goto error;
}
- }
- }
- if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp)
- {
- if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
- bTimeStampValid = FALSE;
- else
- bTimeStampValid = TRUE;
+ if (speedupFileCreation)
+ {
+ // accelerate file creation by telling Windows not to fill all file content with zeros
+ // this has security issues since it will put existing disk content into file container
+ // We use this mechanism only when switch /fastCreateFile specific and when quick format
+ // also specified and which is documented to have security issues.
+ // we don't check returned status because failure is not issue for us
+ SetFileValidData (dev, volumeSize.QuadPart);
+ }
+
+ if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
+ {
+ nStatus = ERR_OS_ERROR;
+ goto error;
+ }
+
+ }
}
if (volParams->hwndDlg && volParams->bGuiMode) KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW);
@@ -548,6 +578,17 @@ begin_format:
goto error;
}
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ {
+ VirtualLock (&tmpCI, sizeof (tmpCI));
+ memcpy (&tmpCI, cryptoInfo, sizeof (CRYPTO_INFO));
+ VcUnprotectKeys (&tmpCI, VcGetEncryptionID (cryptoInfo));
+ cryptoInfoBackup = cryptoInfo;
+ cryptoInfo = &tmpCI;
+ }
+#endif
+
nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
header,
volParams->ea,
@@ -566,6 +607,15 @@ begin_format:
FormatSectorSize,
FALSE);
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ {
+ cryptoInfo = cryptoInfoBackup;
+ burn (&tmpCI, sizeof (CRYPTO_INFO));
+ VirtualUnlock (&tmpCI, sizeof (tmpCI));
+ }
+#endif
+
if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, header))
{
nStatus = ERR_OS_ERROR;
@@ -577,8 +627,28 @@ begin_format:
{
BOOL bUpdateBackup = FALSE;
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ {
+ VirtualLock (&tmpCI, sizeof (tmpCI));
+ memcpy (&tmpCI, cryptoInfo, sizeof (CRYPTO_INFO));
+ VcUnprotectKeys (&tmpCI, VcGetEncryptionID (cryptoInfo));
+ cryptoInfoBackup = cryptoInfo;
+ cryptoInfo = &tmpCI;
+ }
+#endif
+
nStatus = WriteRandomDataToReservedHeaderAreas (hwndDlg, dev, cryptoInfo, dataAreaSize, FALSE, FALSE);
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ {
+ cryptoInfo = cryptoInfoBackup;
+ burn (&tmpCI, sizeof (CRYPTO_INFO));
+ VirtualUnlock (&tmpCI, sizeof (tmpCI));
+ }
+#endif
+
if (nStatus != ERR_SUCCESS)
goto error;
@@ -692,13 +762,13 @@ error:
}
mountOptions.ReadOnly = FALSE;
- mountOptions.Removable = FALSE;
+ mountOptions.Removable = TRUE; /* mount as removal media to allow formatting without admin rights */
mountOptions.ProtectHiddenVolume = FALSE;
mountOptions.PreserveTimestamp = bPreserveTimestamp;
mountOptions.PartitionInInactiveSysEncScope = FALSE;
mountOptions.UseBackupHeader = FALSE;
- if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, volParams->pkcs5, volParams->pim, FALSE, FALSE, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
+ if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, volParams->pkcs5, volParams->pim, FALSE, FALSE, FALSE, TRUE, &mountOptions, Silent, TRUE) < 1)
{
if (!Silent)
{
@@ -709,10 +779,15 @@ error:
goto fv_end;
}
- if (!Silent && !IsAdmin () && IsUacSupported ())
- retCode = UacFormatFs (volParams->hwndDlg, driveNo, volParams->clusterSize, fsType);
- else
- retCode = FormatFs (driveNo, volParams->clusterSize, fsType);
+ retCode = ExternalFormatFs (driveNo, volParams->clusterSize, fsType);
+ if (retCode != TRUE)
+ {
+ /* fallback to using FormatEx function from fmifs.dll */
+ if (!Silent && !IsAdmin () && IsUacSupported ())
+ retCode = UacFormatFs (volParams->hwndDlg, driveNo, volParams->clusterSize, fsType);
+ else
+ retCode = FormatFs (driveNo, volParams->clusterSize, fsType);
+ }
if (retCode != TRUE)
{
@@ -768,6 +843,10 @@ int FormatNoFs (HWND hwndDlg, unsigned __int64 startSector, __int64 num_sectors,
LARGE_INTEGER startOffset;
LARGE_INTEGER newOffset;
+#ifdef _WIN64
+ CRYPTO_INFO tmpCI;
+#endif
+
// Seek to start sector
startOffset.QuadPart = startSector * FormatSectorSize;
if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
@@ -785,6 +864,16 @@ int FormatNoFs (HWND hwndDlg, unsigned __int64 startSector, __int64 num_sectors,
memset (sector, 0, sizeof (sector));
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ {
+ VirtualLock (&tmpCI, sizeof (tmpCI));
+ memcpy (&tmpCI, cryptoInfo, sizeof (CRYPTO_INFO));
+ VcUnprotectKeys (&tmpCI, VcGetEncryptionID (cryptoInfo));
+ cryptoInfo = &tmpCI;
+ }
+#endif
+
// Remember the original secondary key (XTS mode) before generating a temporary one
memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2));
@@ -814,6 +903,11 @@ int FormatNoFs (HWND hwndDlg, unsigned __int64 startSector, __int64 num_sectors,
goto fail;
}
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ VcProtectKeys (cryptoInfo, VcGetEncryptionID (cryptoInfo));
+#endif
+
while (num_sectors--)
{
if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
@@ -847,6 +941,13 @@ int FormatNoFs (HWND hwndDlg, unsigned __int64 startSector, __int64 num_sectors,
VirtualUnlock (temporaryKey, sizeof (temporaryKey));
VirtualUnlock (originalK2, sizeof (originalK2));
TCfree (write_buf);
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ {
+ burn (&tmpCI, sizeof (CRYPTO_INFO));
+ VirtualUnlock (&tmpCI, sizeof (tmpCI));
+ }
+#endif
return 0;
@@ -858,6 +959,13 @@ fail:
VirtualUnlock (temporaryKey, sizeof (temporaryKey));
VirtualUnlock (originalK2, sizeof (originalK2));
TCfree (write_buf);
+#ifdef _WIN64
+ if (IsRamEncryptionEnabled ())
+ {
+ burn (&tmpCI, sizeof (CRYPTO_INFO));
+ VirtualUnlock (&tmpCI, sizeof (tmpCI));
+ }
+#endif
SetLastError (err);
return (retVal ? retVal : ERR_OS_ERROR);
@@ -991,6 +1099,151 @@ BOOL FormatNtfs (int driveNo, int clusterSize)
return FormatFs (driveNo, clusterSize, FILESYS_NTFS);
}
+/* call Windows format.com program to perform formatting */
+BOOL ExternalFormatFs (int driveNo, int clusterSize, int fsType)
+{
+ wchar_t exePath[MAX_PATH] = {0};
+ HANDLE hChildStd_IN_Rd = NULL;
+ HANDLE hChildStd_IN_Wr = NULL;
+ HANDLE hChildStd_OUT_Rd = NULL;
+ HANDLE hChildStd_OUT_Wr = NULL;
+ WCHAR szFsFormat[16];
+ TCHAR szCmdline[2 * MAX_PATH];
+ STARTUPINFO siStartInfo;
+ PROCESS_INFORMATION piProcInfo;
+ BOOL bSuccess = FALSE;
+ SECURITY_ATTRIBUTES saAttr;
+
+ switch (fsType)
+ {
+ case FILESYS_NTFS:
+ StringCchCopyW (szFsFormat, ARRAYSIZE (szFsFormat),L"NTFS");
+ break;
+ case FILESYS_EXFAT:
+ StringCchCopyW (szFsFormat, ARRAYSIZE (szFsFormat),L"exFAT");
+ break;
+ case FILESYS_REFS:
+ StringCchCopyW (szFsFormat, ARRAYSIZE (szFsFormat),L"ReFS");
+ break;
+ default:
+ return FALSE;
+ }
+
+ /* Set the bInheritHandle flag so pipe handles are inherited. */
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = NULL;
+
+ /* Create a pipe for the child process's STDOUT. */
+ if ( !CreatePipe(&hChildStd_OUT_Rd, &hChildStd_OUT_Wr, &saAttr, 0) )
+ return FALSE;
+
+ /* Ensure the read handle to the pipe for STDOUT is not inherited. */
+ /* Create a pipe for the child process's STDIN. */
+ if ( !SetHandleInformation(hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)
+ || !CreatePipe(&hChildStd_IN_Rd, &hChildStd_IN_Wr, &saAttr, 0))
+ {
+ CloseHandle (hChildStd_OUT_Rd);
+ CloseHandle (hChildStd_OUT_Wr);
+ return FALSE;
+ }
+
+ /* Ensure the write handle to the pipe for STDIN is not inherited. */
+ if ( !SetHandleInformation(hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
+ {
+ CloseHandle (hChildStd_OUT_Rd);
+ CloseHandle (hChildStd_OUT_Wr);
+ CloseHandle (hChildStd_IN_Rd);
+ CloseHandle (hChildStd_IN_Wr);
+ return FALSE;
+ }
+
+ if (GetSystemDirectory (exePath, MAX_PATH))
+ {
+ StringCchCatW(exePath, ARRAYSIZE(exePath), L"\\format.com");
+ }
+ else
+ StringCchCopyW(exePath, ARRAYSIZE(exePath), L"C:\\Windows\\System32\\format.com");
+
+ StringCbPrintf (szCmdline, sizeof(szCmdline), L"%s %c: /FS:%s /Q /X /V:\"\"", exePath, (WCHAR) driveNo + L'A', szFsFormat);
+
+ if (clusterSize)
+ {
+ WCHAR szSize[8];
+ uint32 unitSize = (uint32) clusterSize * FormatSectorSize;
+ if (unitSize <= 8192)
+ StringCbPrintf (szSize, sizeof (szSize), L"%d", unitSize);
+ else if (unitSize < BYTES_PER_MB)
+ {
+ StringCbPrintf (szSize, sizeof (szSize), L"%dK", unitSize / BYTES_PER_KB);
+ }
+ else
+ StringCbPrintf (szSize, sizeof (szSize), L"%dM", unitSize / BYTES_PER_MB);
+
+ StringCbCat (szCmdline, sizeof (szCmdline), L" /A:");
+ StringCbCat (szCmdline, sizeof (szCmdline), szSize);
+ }
+
+
+ ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
+
+ /* Set up members of the STARTUPINFO structure.
+ This structure specifies the STDIN and STDOUT handles for redirection.
+ */
+ ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.hStdError = hChildStd_OUT_Wr;
+ siStartInfo.hStdOutput = hChildStd_OUT_Wr;
+ siStartInfo.hStdInput = hChildStd_IN_Rd;
+ siStartInfo.wShowWindow = SW_HIDE;
+ siStartInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+
+ /* Create the child process. */
+ bSuccess = CreateProcess(NULL,
+ szCmdline, // command line
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ 0, // creation flags
+ NULL, // use parent's environment
+ NULL, // use parent's current directory
+ &siStartInfo, // STARTUPINFO pointer
+ &piProcInfo); // receives PROCESS_INFORMATION
+
+ if (bSuccess)
+ {
+ /* Unblock the format process by simulating hit on ENTER key */
+ DWORD dwExitCode, dwWritten;
+ LPCSTR newLine = "\n";
+
+ WriteFile(hChildStd_IN_Wr, (LPCVOID) newLine, 1, &dwWritten, NULL);
+
+ /* wait for the format process to finish */
+ WaitForSingleObject (piProcInfo.hProcess, INFINITE);
+
+ /* check if it was successfull */
+ if (GetExitCodeProcess (piProcInfo.hProcess, &dwExitCode))
+ {
+ if (dwExitCode == 0)
+ bSuccess = TRUE;
+ else
+ bSuccess = FALSE;
+ }
+ else
+ bSuccess = FALSE;
+
+ CloseHandle (piProcInfo.hThread);
+ CloseHandle (piProcInfo.hProcess);
+ }
+
+ CloseHandle(hChildStd_OUT_Wr);
+ CloseHandle(hChildStd_OUT_Rd);
+ CloseHandle(hChildStd_IN_Rd);
+ CloseHandle(hChildStd_IN_Wr);
+
+ return bSuccess;
+}
+
BOOL WriteSector (void *dev, char *sector,
char *write_buf, int *write_buf_cnt,
__int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
diff --git a/src/Common/Format.h b/src/Common/Format.h
index 961ece7..139607e 100644
--- a/src/Common/Format.h
+++ b/src/Common/Format.h
@@ -38,6 +38,7 @@ typedef struct
unsigned int clusterSize;
BOOL sparseFileSwitch;
BOOL quickFormat;
+ BOOL fastCreateFile;
DWORD sectorSize;
int *realClusterSize;
Password *password;
@@ -75,6 +76,7 @@ extern int FormatWriteBufferSize;
int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams);
BOOL FormatNtfs (int driveNo, int clusterSize);
BOOL FormatFs (int driveNo, int clusterSize, int fsType);
+BOOL ExternalFormatFs (int driveNo, int clusterSize, int fsType);
uint64 GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize);
int FormatNoFs (HWND hwndDlg, unsigned __int64 startSector, __int64 num_sectors, void *dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat);
BOOL WriteSector ( void *dev , char *sector , char *write_buf , int *write_buf_cnt , __int64 *nSecNo , PCRYPTO_INFO cryptoInfo );
diff --git a/src/Common/Keyfiles.c b/src/Common/Keyfiles.c
index 686f3ca..174aed9 100644
--- a/src/Common/Keyfiles.c
+++ b/src/Common/Keyfiles.c
@@ -149,50 +149,41 @@ void KeyFileCloneAll (KeyFile *firstKeyFile, KeyFile **outputKeyFile)
static BOOL KeyFileProcess (unsigned __int8 *keyPool, unsigned __int32 keyPoolSize, KeyFile *keyFile)
{
- FILE *f;
unsigned __int8 buffer[64 * 1024];
unsigned __int32 crc = 0xffffffff;
unsigned __int32 writePos = 0;
- size_t bytesRead, totalRead = 0;
+ DWORD bytesRead, totalRead = 0;
int status = TRUE;
-
HANDLE src;
- FILETIME ftCreationTime;
- FILETIME ftLastWriteTime;
- FILETIME ftLastAccessTime;
-
- BOOL bTimeStampValid = FALSE;
+ BOOL bReadStatus = FALSE;
- /* Remember the last access time of the keyfile. It will be preserved in order to prevent
- an adversary from determining which file may have been used as keyfile. */
src = CreateFile (keyFile->FileName,
- GENERIC_READ | GENERIC_WRITE,
+ GENERIC_READ | FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (src != INVALID_HANDLE_VALUE)
{
- if (GetFileTime ((HANDLE) src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime))
- bTimeStampValid = TRUE;
- }
+ /* We tell Windows not to update the Last Access timestamp in order to prevent
+ an adversary from determining which file may have been used as keyfile. */
+ FILETIME ftLastAccessTime;
+ ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
+ ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
- finally_do_arg (HANDLE, src,
+ SetFileTime (src, NULL, &ftLastAccessTime, NULL);
+ }
+ else
{
- if (finally_arg != INVALID_HANDLE_VALUE)
- CloseHandle (finally_arg);
- });
-
- f = _wfopen (keyFile->FileName, L"rb");
- if (f == NULL) return FALSE;
+ /* try to open without FILE_WRITE_ATTRIBUTES in case we are in a ReadOnly filesystem (e.g. CD) */
+ src = CreateFile (keyFile->FileName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ if (src == INVALID_HANDLE_VALUE)
+ return FALSE;
+ }
- while ((bytesRead = fread (buffer, 1, sizeof (buffer), f)) > 0)
+ while ((bReadStatus = ReadFile (src, buffer, sizeof (buffer), &bytesRead, NULL)) && (bytesRead > 0))
{
- size_t i;
-
- if (ferror (f))
- {
- status = FALSE;
- goto close;
- }
+ DWORD i;
for (i = 0; i < bytesRead; i++)
{
@@ -211,7 +202,7 @@ static BOOL KeyFileProcess (unsigned __int8 *keyPool, unsigned __int32 keyPoolSi
}
}
- if (ferror (f))
+ if (!bReadStatus)
{
status = FALSE;
}
@@ -223,13 +214,9 @@ static BOOL KeyFileProcess (unsigned __int8 *keyPool, unsigned __int32 keyPoolSi
close:
DWORD err = GetLastError();
- fclose (f);
- if (bTimeStampValid && !IsFileOnReadOnlyFilesystem (keyFile->FileName))
- {
- // Restore the keyfile timestamp
- SetFileTime (src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);
- }
+ CloseHandle (src);
+ burn (buffer, sizeof (buffer));
SetLastError (err);
return status;
diff --git a/src/Common/Language.c b/src/Common/Language.c
index 6dbd8b6..ffccd44 100644
--- a/src/Common/Language.c
+++ b/src/Common/Language.c
@@ -209,6 +209,7 @@ static BOOL LoadLanguageData (int resourceid, BOOL bForceSetPreferredLanguage, B
LocalizationActive = FALSE;
ActiveLangPackVersion[0] = 0;
ClearDictionaryPool ();
+ LanguageResource = NULL;
if ((resourceid == 0) && (PreferredLangId[0] != 0))
StringCbCopyA (langId, sizeof(langId), PreferredLangId);
diff --git a/src/Common/Language.xml b/src/Common/Language.xml
index fd5ee63..d071cec 100644
--- a/src/Common/Language.xml
+++ b/src/Common/Language.xml
@@ -33,14 +33,14 @@
<entry lang="en" key="IDC_DISPLAY_POOL_CONTENTS">Display pool content</entry>
<entry lang="en" key="IDC_DOWNLOAD_CD_BURN_SOFTWARE">Download CD/DVD recording software</entry>
<entry lang="en" key="IDC_FILE_CONTAINER">Create an encrypted file container</entry>
- <entry lang="en" key="IDC_GB">&amp;GB</entry>
- <entry lang="en" key="IDC_TB">&amp;TB</entry>
+ <entry lang="en" key="IDC_GB">&amp;GiB</entry>
+ <entry lang="en" key="IDC_TB">&amp;TiB</entry>
<entry lang="en" key="IDC_HIDDEN_SYSENC_INFO_LINK">More information</entry>
<entry lang="en" key="IDC_HIDDEN_VOL">Hi&amp;dden VeraCrypt volume </entry>
<entry lang="en" key="IDC_HIDDEN_VOL_HELP">More information about hidden volumes</entry>
<entry lang="en" key="IDC_HIDVOL_WIZ_MODE_DIRECT">Direct mode</entry>
<entry lang="en" key="IDC_HIDVOL_WIZ_MODE_FULL">Normal mode</entry>
- <entry lang="en" key="IDC_KB">&amp;KB</entry>
+ <entry lang="en" key="IDC_KB">&amp;KiB</entry>
<entry lang="en" key="IDC_KEYFILES_ENABLE">U&amp;se keyfiles</entry>
<entry lang="en" key="IDC_KEYFILES_TRY_EMPTY_PASSWORD">Try first to mount with an empty password</entry>
<entry lang="en" key="IDC_KEYFILES_RANDOM_SIZE">Random size ( 64 &lt;-&gt; 1048576 )</entry>
@@ -48,7 +48,7 @@
<entry lang="en" key="IDC_LINK_HASH_INFO">Information on hash algorithms</entry>
<entry lang="en" key="IDC_LINK_MORE_INFO_ABOUT_CIPHER">More information</entry>
<entry lang="en" key="IDC_LINK_PIM_INFO">Information on PIM</entry>
- <entry lang="en" key="IDC_MB">&amp;MB</entry>
+ <entry lang="en" key="IDC_MB">&amp;MiB</entry>
<entry lang="en" key="IDC_MORE_INFO_ON_CONTAINERS">More information</entry>
<entry lang="en" key="IDC_MORE_INFO_ON_SYS_ENCRYPTION">More information about system encryption</entry>
<entry lang="en" key="IDC_MORE_INFO_SYS_ENCRYPTION">More information</entry>
@@ -414,11 +414,11 @@
<entry lang="en" key="COMPRESSION_NOT_SUPPORTED">Error: The container has been compressed at the filesystem level. VeraCrypt does not support compressed containers (note that compression of encrypted data is ineffective and redundant).\n\nPlease disable compression for the container by following these steps:\n1) Right-click the container in Windows Explorer (not in VeraCrypt).\n2) Select 'Properties'.\n3) In the 'Properties' dialog box, click 'Advanced'.\n4) In the 'Advanced Attributes' dialog box, disable the option 'Compress contents to save disk space' and click 'OK'.\n5) In the 'Properties' dialog box, click 'OK'.</entry>
<entry lang="en" key="CREATE_FAILED">Failed to create volume %s</entry>
<entry lang="en" key="DEVICE_FREE_BYTES">Size of %s is %.2f bytes</entry>
- <entry lang="en" key="DEVICE_FREE_KB">Size of %s is %.2f KB</entry>
- <entry lang="en" key="DEVICE_FREE_MB">Size of %s is %.2f MB</entry>
- <entry lang="en" key="DEVICE_FREE_GB">Size of %s is %.2f GB</entry>
- <entry lang="en" key="DEVICE_FREE_TB">Size of %s is %.2f TB</entry>
- <entry lang="en" key="DEVICE_FREE_PB">Size of %s is %.2f PB</entry>
+ <entry lang="en" key="DEVICE_FREE_KB">Size of %s is %.2f KiB</entry>
+ <entry lang="en" key="DEVICE_FREE_MB">Size of %s is %.2f MiB</entry>
+ <entry lang="en" key="DEVICE_FREE_GB">Size of %s is %.2f GiB</entry>
+ <entry lang="en" key="DEVICE_FREE_TB">Size of %s is %.2f TiB</entry>
+ <entry lang="en" key="DEVICE_FREE_PB">Size of %s is %.2f PiB</entry>
<entry lang="en" key="DEVICE_IN_USE_FORMAT">WARNING: The device/partition is in use by the operating system or applications. Formatting the device/partition might cause data corruption and system instability.\n\nContinue?</entry>
<entry lang="en" key="DEVICE_IN_USE_INPLACE_ENC">Warning: The partition is in use by the operating system or applications. You should close any applications that might be using the partition (including antivirus software).\n\nContinue?</entry>
<entry lang="en" key="FORMAT_CANT_DISMOUNT_FILESYS">Error: The device/partition contains a file system that could not be dismounted. The file system may be in use by the operating system. Formatting the device/partition would very likely cause data corruption and system instability.\n\nTo solve this issue, we recommend that you first delete the partition and then recreate it without formatting. To do so, follow these steps:\n1) Right-click the 'Computer' (or 'My Computer') icon in the 'Start Menu' and select 'Manage'. The 'Computer Management' window should appear.\n2) In the 'Computer Management' window, select 'Storage' > 'Disk Management'.\n3) Right-click the partition you want to encrypt and select either 'Delete Partition', or 'Delete Volume', or 'Delete Logical Drive'.\n4) Click 'Yes'. If Windows asks you to restart the computer, do so. Then repeat the steps 1 and 2 and continue from the step 5.\n5) Right-click the unallocated/free space area and select either 'New Partition', or 'New Simple Volume', or 'New Logical Drive'.\n6) The 'New Partition Wizard' or 'New Simple Volume Wizard' window should appear now; follow its instructions. On the wizard page entitled 'Format Partition', select either 'Do not format this partition' or 'Do not format this volume'. In the same wizard, click 'Next' and then 'Finish'.\n7) Note that the device path you have selected in VeraCrypt may be wrong now. Therefore, exit the VeraCrypt Volume Creation Wizard (if it is still running) and then start it again.\n8) Try encrypting the device/partition again.\n\nIf VeraCrypt repeatedly fails to encrypt the device/partition, you may want to consider creating a file container instead.</entry>
@@ -436,13 +436,13 @@
<entry lang="en" key="RAW_DEV_NOT_SUPPORTED_FOR_INPLACE_ENC">VeraCrypt can in-place encrypt only a partition, a dynamic volume, or an entire system drive.\n\nIf you want to create an encrypted VeraCrypt volume within the selected non-system device, choose the option "Create encrypted volume and format it" (instead of the option "Encrypt partition in place").</entry>
<entry lang="en" key="INPLACE_ENC_INVALID_PATH">Error: VeraCrypt can in-place encrypt only a partition, a dynamic volume, or an entire system drive. Please make sure the specified path is valid.</entry>
<entry lang="en" key="CANNOT_RESIZE_FILESYS">Error: Cannot shrink the filesystem (the filesystem needs to be shrunk to make space for the volume header and backup header).\n\nPossible causes and solutions:\n\n- Not enough free space on the volume. Please make sure no other application is writing to the filesystem.\n\n- Corrupted file system. Try to check it and fix any errors (right-click the corresponding drive letter in the 'Computer' list, then select Properties > Tools > 'Check Now', make sure the option 'Automatically fix file system errors' is enabled and click Start).\n\nIf the above steps do not help, please follow the below steps.</entry>
- <entry lang="en" key="NOT_ENOUGH_FREE_FILESYS_SPACE_FOR_SHRINK">Error: There is not enough free space on the volume and so the filesystem cannot be shrunk (the filesystem needs to be shrunk to make space for the volume header and backup header).\n\nPlease delete any redundant files and empty the Recycle Bin so as to free at least 256 KB of space and then try again. Note that due to a Windows issue, the amount of free space reported by the Windows Explorer may be incorrect until the operating system is restarted. If restarting the system does not help, the file system may be corrupted. Try to check it and fix any errors (right-click the corresponding drive letter in the 'Computer' list, then select Properties > Tools > 'Check Now', make sure the option 'Automatically fix file system errors' is enabled and click Start).\n\nIf the above steps do not help, please follow the below steps.</entry>
+ <entry lang="en" key="NOT_ENOUGH_FREE_FILESYS_SPACE_FOR_SHRINK">Error: There is not enough free space on the volume and so the filesystem cannot be shrunk (the filesystem needs to be shrunk to make space for the volume header and backup header).\n\nPlease delete any redundant files and empty the Recycle Bin so as to free at least 256 KiB of space and then try again. Note that due to a Windows issue, the amount of free space reported by the Windows Explorer may be incorrect until the operating system is restarted. If restarting the system does not help, the file system may be corrupted. Try to check it and fix any errors (right-click the corresponding drive letter in the 'Computer' list, then select Properties > Tools > 'Check Now', make sure the option 'Automatically fix file system errors' is enabled and click Start).\n\nIf the above steps do not help, please follow the below steps.</entry>
<entry lang="en" key="DISK_FREE_BYTES">Free space on drive %s is %.2f bytes.</entry>
- <entry lang="en" key="DISK_FREE_KB">Free space on drive %s is %.2f KB</entry>
- <entry lang="en" key="DISK_FREE_MB">Free space on drive %s is %.2f MB</entry>
- <entry lang="en" key="DISK_FREE_GB">Free space on drive %s is %.2f GB</entry>
- <entry lang="en" key="DISK_FREE_TB">Free space on drive %s is %.2f TB</entry>
- <entry lang="en" key="DISK_FREE_PB">Free space on drive %s is %.2f PB</entry>
+ <entry lang="en" key="DISK_FREE_KB">Free space on drive %s is %.2f KiB</entry>
+ <entry lang="en" key="DISK_FREE_MB">Free space on drive %s is %.2f MiB</entry>
+ <entry lang="en" key="DISK_FREE_GB">Free space on drive %s is %.2f GiB</entry>
+ <entry lang="en" key="DISK_FREE_TB">Free space on drive %s is %.2f TiB</entry>
+ <entry lang="en" key="DISK_FREE_PB">Free space on drive %s is %.2f PiB</entry>
<entry lang="en" key="DRIVELETTERS">Could not get available drive letters.</entry>
<entry lang="en" key="DRIVER_NOT_FOUND">Error: VeraCrypt driver not found.\n\nPlease copy the files 'veracrypt.sys' and 'veracrypt-x64.sys' to the directory where the main VeraCrypt application (VeraCrypt.exe) is located.</entry>
<entry lang="en" key="DRIVER_VERSION">Error: An incompatible version of the VeraCrypt driver is currently running.\n\nIf you are trying to run VeraCrypt in portable mode (i.e. without installing it) and a different version of VeraCrypt is already installed, you must uninstall it first (or upgrade it using the VeraCrypt installer). To uninstall it, follow these steps: On Windows Vista or later, select 'Start Menu' > Computer > 'Uninstall or change a program' > VeraCrypt > Uninstall; on Windows XP, select 'Start Menu' > Settings > 'Control Panel' > 'Add Or Remove Programs' > VeraCrypt > Remove.\n\nSimilarly, if you are trying to run VeraCrypt in portable mode (i.e. without installing it) and a different version of VeraCrypt is already running in portable mode, you must restart the system first and then run only this new version.</entry>
@@ -456,7 +456,7 @@
<entry lang="en" key="ASK_KEEP_DETECTING_SYSTEM_CRASH">Do you want VeraCrypt to continue detecting system crashes?</entry>
<entry lang="en" key="NO_MINIDUMP_FOUND">VeraCrypt found no system crash minidump file.</entry>
<entry lang="en" key="ASK_DELETE_KERNEL_CRASH_DUMP">Do you want to delete the Windows crash dump file to free up disk space?</entry>
- <entry lang="en" key="ASK_DEBUGGER_INSTALL">In order to analyze the system crash, VeraCrypt needs to install Microsoft Debugging Tools for Windows first.\n\nAfter you click OK, the Windows installer will download the Microsoft Debugging Tools installation package (16 MB) from a Microsoft server and install it (the Windows installer will be forwarded to the Microsoft server URL from the veracrypt.org server, which ensures that this feature works even if Microsoft changes the location of the installation package).</entry>
+ <entry lang="en" key="ASK_DEBUGGER_INSTALL">In order to analyze the system crash, VeraCrypt needs to install Microsoft Debugging Tools for Windows first.\n\nAfter you click OK, the Windows installer will download the Microsoft Debugging Tools installation package (16 MiB) from a Microsoft server and install it (the Windows installer will be forwarded to the Microsoft server URL from the veracrypt.org server, which ensures that this feature works even if Microsoft changes the location of the installation package).</entry>
<entry lang="en" key="SYSTEM_CRASH_ANALYSIS_INFO">After you click OK, VeraCrypt will analyze the system crash. This may take up to several minutes.</entry>
<entry lang="en" key="DEBUGGER_NOT_FOUND">Please make sure the environment variable 'PATH' includes the path to 'kd.exe' (Kernel Debugger).</entry>
<entry lang="en" key="SYSTEM_CRASH_NO_VERACRYPT">It appears that VeraCrypt most likely did not cause the system crash. There are many potential reasons why the system could have crashed (for example, a failing hardware component, a bug in a device driver, etc.)</entry>
@@ -479,9 +479,9 @@
<entry lang="en" key="FILE_OPEN_FAILED">The file could not be opened.</entry>
<entry lang="en" key="FILE_TITLE">Volume Location</entry>
<entry lang="en" key="FILESYS_PAGE_TITLE">Large Files</entry>
- <entry lang="en" key="FILESYS_PAGE_HELP_QUESTION">Do you intend to store files larger than 4 GB in this VeraCrypt volume?</entry>
+ <entry lang="en" key="FILESYS_PAGE_HELP_QUESTION">Do you intend to store files larger than 4 GiB in this VeraCrypt volume?</entry>
<entry lang="en" key="FILESYS_PAGE_HELP_EXPLANATION">Depending on your choice above, VeraCrypt will choose a suitable default file system for the VeraCrypt volume (you will be able to select a file system in the next step).</entry>
- <entry lang="en" key="FILESYS_PAGE_HELP_EXPLANATION_HIDVOL">As you are creating an outer volume, you should consider choosing 'No'. If you choose 'Yes', the default filesystem will be NTFS, which is not as suitable for outer volumes as FAT/exFAT (for example, the maximum possible size of the hidden volume will be significantly greater if the outer volume is formatted as FAT/exFAT). Normally, FAT is the default for both hidden and normal volumes (so FAT volumes are not suspicious). However, if the user indicates intent to store files larger than 4 GB (which the FAT file system does not allow), then FAT is not the default.</entry>
+ <entry lang="en" key="FILESYS_PAGE_HELP_EXPLANATION_HIDVOL">As you are creating an outer volume, you should consider choosing 'No'. If you choose 'Yes', the default filesystem will be NTFS, which is not as suitable for outer volumes as FAT/exFAT (for example, the maximum possible size of the hidden volume will be significantly greater if the outer volume is formatted as FAT/exFAT). Normally, FAT is the default for both hidden and normal volumes (so FAT volumes are not suspicious). However, if the user indicates intent to store files larger than 4 GiB (which the FAT file system does not allow), then FAT is not the default.</entry>
<entry lang="en" key="FILESYS_PAGE_HELP_EXPLANATION_HIDVOL_CONFIRM">Are you sure you want to choose 'Yes'?</entry>
<entry lang="en" key="DEVICE_TRANSFORM_MODE_PAGE_TITLE">Volume Creation Mode</entry>
<entry lang="en" key="DEVICE_TRANSFORM_MODE_PAGE_FORMAT_HELP">This is the fastest way to create a partition-hosted or device-hosted VeraCrypt volume (in-place encryption, which is the other option, is slower because content of each sector has to be first read, encrypted, and then written). Any data currently stored on the selected partition/device will be lost (the data will NOT be encrypted; it will be overwritten with random data). If you want to encrypt existing data on a partition, choose the other option.</entry>
@@ -536,7 +536,7 @@
<entry lang="en" key="HIDVOL_PROT_WARN_AFTER_MOUNT">The hidden volume is now protected against damage until the outer volume is dismounted.\n\nWARNING: If any data is attempted to be saved to the hidden volume area, VeraCrypt will start write-protecting the entire volume (both the outer and the hidden part) until it is dismounted. This may cause filesystem corruption on the outer volume, which (if repeated) might adversely affect plausible deniability of the hidden volume. Therefore, you should make every effort to avoid writing to the hidden volume area. Any data being saved to the hidden volume area will not be saved and will be lost. Windows may report this as a write error ("Delayed Write Failed" or "The parameter is incorrect").</entry>
<entry lang="en" key="HIDVOL_PROT_WARN_AFTER_MOUNT_PLURAL">Each of the hidden volumes within the newly mounted volumes is now protected against damage until dismounted.\n\nWARNING: If any data is attempted to be saved to protected hidden volume area of any of these volumes, VeraCrypt will start write-protecting the entire volume (both the outer and the hidden part) until it is dismounted. This may cause filesystem corruption on the outer volume, which (if repeated) might adversely affect plausible deniability of the hidden volume. Therefore, you should make every effort to avoid writing to the hidden volume area. Any data being saved to protected hidden volume areas will not be saved and will be lost. Windows may report this as a write error ("Delayed Write Failed" or "The parameter is incorrect").</entry>
<entry lang="en" key="DAMAGE_TO_HIDDEN_VOLUME_PREVENTED">WARNING: Data were attempted to be saved to the hidden volume area of the volume mounted as %c:! VeraCrypt prevented these data from being saved in order to protect the hidden volume. This may have caused filesystem corruption on the outer volume and Windows may have reported a write error ("Delayed Write Failed" or "The parameter is incorrect"). The entire volume (both the outer and the hidden part) will be write-protected until it is dismounted. If this is not the first time VeraCrypt has prevented data from being saved to the hidden volume area of this volume, plausible deniability of this hidden volume might be adversely affected (due to possible unusual correlated inconsistencies within the outer volume file system). Therefore, you should consider creating a new VeraCrypt volume (with Quick Format disabled) and moving files from this volume to the new volume; this volume should be securely erased (both the outer and the hidden part). We strongly recommend that you restart the operating system now.</entry>
- <entry lang="en" key="CANNOT_SATISFY_OVER_4G_FILE_SIZE_REQ">You have indicated intent to store files larger than 4 GB on the volume. This requires the volume to be formatted as NTFS/exFAT/ReFS, which, however, will not be possible.</entry>
+ <entry lang="en" key="CANNOT_SATISFY_OVER_4G_FILE_SIZE_REQ">You have indicated intent to store files larger than 4 GiB on the volume. This requires the volume to be formatted as NTFS/exFAT/ReFS, which, however, will not be possible.</entry>
<entry lang="en" key="CANNOT_CREATE_NON_HIDDEN_NTFS_VOLUMES_UNDER_HIDDEN_OS">Please note that when a hidden operating system is running, non-hidden VeraCrypt volumes cannot be formatted as NTFS/exFAT/ReFS. The reason is that the volume would need to be temporarily mounted without write protection in order to allow the operating system to format it as NTFS (whereas formatting as FAT is performed by VeraCrypt, not by the operating system, and without mounting the volume). For further technical details, see below. You can create a non-hidden NTFS/exFAT/ReFS volume from within the decoy operating system.</entry>
<entry lang="en" key="HIDDEN_VOL_CREATION_UNDER_HIDDEN_OS_HOWTO">For security reasons, when a hidden operating system is running, hidden volumes can be created only in the 'direct' mode (because outer volumes must always be mounted as read-only). To create a hidden volume securely, follow these steps:\n\n1) Boot the decoy system.\n\n2) Create a normal VeraCrypt volume and, to this volume, copy some sensitive-looking files that you actually do NOT want to hide (the volume will become the outer volume).\n\n3) Boot the hidden system and start the VeraCrypt Volume Creation Wizard. If the volume is file-hosted, move it to the system partition or to another hidden volume (otherwise, the newly created hidden volume would be mounted as read-only and could not be formatted). Follow the instructions in the wizard so as to select the 'direct' hidden volume creation mode.\n\n4) In the wizard, select the volume you created in step 2 and then follow the instructions to create a hidden volume within it.</entry>
<entry lang="en" key="HIDDEN_OS_WRITE_PROTECTION_BRIEF_INFO">For security reasons, when a hidden operating system is running, local unencrypted filesystems and non-hidden VeraCrypt volumes are mounted as read-only (no data can be written to such filesystems or VeraCrypt volumes).\n\nData is allowed to be written to any filesystem that resides within a hidden VeraCrypt volume (provided that the hidden volume is not located in a container stored on an unencrypted filesystem or on any other read-only filesystem).</entry>
@@ -560,10 +560,10 @@
<entry lang="en" key="INIT_RICHEDIT">Error: Failed to load the Rich Edit system library.</entry>
<entry lang="en" key="INTRO_TITLE">VeraCrypt Volume Creation Wizard</entry>
<entry lang="en" key="MAX_HIDVOL_SIZE_BYTES">Maximum possible hidden volume size for this volume is %.2f bytes.</entry>
- <entry lang="en" key="MAX_HIDVOL_SIZE_KB">Maximum possible hidden volume size for this volume is %.2f KB.</entry>
- <entry lang="en" key="MAX_HIDVOL_SIZE_MB">Maximum possible hidden volume size for this volume is %.2f MB.</entry>
- <entry lang="en" key="MAX_HIDVOL_SIZE_GB">Maximum possible hidden volume size for this volume is %.2f GB.</entry>
- <entry lang="en" key="MAX_HIDVOL_SIZE_TB">Maximum possible hidden volume size for this volume is %.2f TB.</entry>
+ <entry lang="en" key="MAX_HIDVOL_SIZE_KB">Maximum possible hidden volume size for this volume is %.2f KiB.</entry>
+ <entry lang="en" key="MAX_HIDVOL_SIZE_MB">Maximum possible hidden volume size for this volume is %.2f MiB.</entry>
+ <entry lang="en" key="MAX_HIDVOL_SIZE_GB">Maximum possible hidden volume size for this volume is %.2f GiB.</entry>
+ <entry lang="en" key="MAX_HIDVOL_SIZE_TB">Maximum possible hidden volume size for this volume is %.2f TiB.</entry>
<entry lang="en" key="MOUNTED_NOPWCHANGE">Volume password/keyfiles cannot be changed while the volume is mounted. Please dismount the volume first.</entry>
<entry lang="en" key="MOUNTED_NO_PKCS5_PRF_CHANGE">The header key derivation algorithm cannot be changed while the volume is mounted. Please dismount the volume first.</entry>
<entry lang="en" key="MOUNT_BUTTON">&amp;Mount</entry>
@@ -666,14 +666,14 @@
<entry lang="en" key="SELECT_KEYFILE_GENERATION_DIRECTORY">Select a directory where to store the keyfiles.</entry>
<entry lang="en" key="SELECTED_KEYFILE_IS_CONTAINER_FILE">The current container file was selected as a keyfile. It will be skipped.</entry>
<entry lang="en" key="SERPENT_HELP">Designed by Ross Anderson, Eli Biham, and Lars Knudsen. Published in 1998. 256-bit key, 128-bit block. Mode of operation is XTS. Serpent was one of the AES finalists.</entry>
- <entry lang="en" key="SIZE_HELP">Please specify the size of the container you want to create.\n\nIf you create a dynamic (sparse-file) container, this parameter will specify its maximum possible size.\n\nNote that the minimum possible size of a FAT volume is 292 KB. The minimum possible size of an exFAT volume is 424 KB. The minimum possible size of an NTFS volume is 3792 KB. The minimum possible size of an ReFS volume is 642 MB.</entry>
- <entry lang="en" key="SIZE_HELP_HIDDEN_HOST_VOL">Please specify the size of the outer volume to be created (you will first create the outer volume and then a hidden volume within it). The minimum possible size of a volume within which a hidden volume is intended to be created is 340 KB.</entry>
- <entry lang="en" key="SIZE_HELP_HIDDEN_VOL">Please specify the size of the hidden volume to create. The minimum possible size of a hidden volume is 40 KB (or 3664 KB if it is formatted as NTFS). The maximum possible size you can specify for the hidden volume is displayed above.</entry>
+ <entry lang="en" key="SIZE_HELP">Please specify the size of the container you want to create.\n\nIf you create a dynamic (sparse-file) container, this parameter will specify its maximum possible size.\n\nNote that the minimum possible size of a FAT volume is 292 KiB. The minimum possible size of an exFAT volume is 424 KiB. The minimum possible size of an NTFS volume is 3792 KiB. The minimum possible size of an ReFS volume is 642 MiB.</entry>
+ <entry lang="en" key="SIZE_HELP_HIDDEN_HOST_VOL">Please specify the size of the outer volume to be created (you will first create the outer volume and then a hidden volume within it). The minimum possible size of a volume within which a hidden volume is intended to be created is 340 KiB.</entry>
+ <entry lang="en" key="SIZE_HELP_HIDDEN_VOL">Please specify the size of the hidden volume to create. The minimum possible size of a hidden volume is 40 KiB (or 3664 KiB if it is formatted as NTFS). The maximum possible size you can specify for the hidden volume is displayed above.</entry>
<entry lang="en" key="SIZE_HIDVOL_HOST_TITLE">Outer Volume Size</entry>
<entry lang="en" key="SIZE_HIDVOL_TITLE">Hidden Volume Size</entry>
<entry lang="en" key="SIZE_PARTITION_HELP">Please verify that the size of the selected device/partition shown above is correct and click Next.</entry>
<entry lang="en" key="SIZE_PARTITION_HIDDEN_SYSENC_HELP">The outer volume and the hidden volume (containing the hidden operating system) will reside within the above partition. It should be the first partition behind the system partition.\n\nPlease verify that the size of the partition and its number shown above are correct, and if they are, click Next.</entry>
- <entry lang="en" key="SIZE_PARTITION_HIDDEN_VOL_HELP">\n\nNote that the minimum possible size of a volume within which a hidden volume is intended to be created is 340 KB.</entry>
+ <entry lang="en" key="SIZE_PARTITION_HIDDEN_VOL_HELP">\n\nNote that the minimum possible size of a volume within which a hidden volume is intended to be created is 340 KiB.</entry>
<entry lang="en" key="SIZE_TITLE">Volume Size</entry>
<entry lang="en" key="SPARSE_FILE">Dynamic</entry>
<entry lang="en" key="TESTS_FAILED">CAUTION: SELF-TEST FAILED!</entry>
@@ -748,7 +748,7 @@
<entry lang="en" key="HIDDEN_VOL_HOST_NTFS">Note: The FAT/exFAT file system is more suitable for outer volumes than the NTFS file system (for example, the maximum possible size of the hidden volume would very likely have been significantly greater if the outer volume had been formatted as FAT/exFAT).</entry>
<entry lang="en" key="HIDDEN_VOL_HOST_NTFS_ASK">Note that the FAT/exFAT file system is more suitable for outer volumes than the NTFS file system. For example, the maximum possible size of the hidden volume will very likely be significantly greater if the outer volume is formatted as FAT/exFAT (the reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume can reside only in the second half of the outer volume).\n\nAre you sure you want to format the outer volume as NTFS?</entry>
<entry lang="en" key="OFFER_FAT_FORMAT_ALTERNATIVE">Do you want to format the volume as FAT instead?</entry>
- <entry lang="en" key="FAT_NOT_AVAILABLE_FOR_SO_LARGE_VOLUME">Note: This volume cannot be formatted as FAT, because it exceeds the maximum volume size supported by the FAT32 filesystem for the applicable sector size (2 TB for 512-byte sectors and 16 TB for 4096-byte sectors).</entry>
+ <entry lang="en" key="FAT_NOT_AVAILABLE_FOR_SO_LARGE_VOLUME">Note: This volume cannot be formatted as FAT, because it exceeds the maximum volume size supported by the FAT32 filesystem for the applicable sector size (2 TiB for 512-byte sectors and 16 TiB for 4096-byte sectors).</entry>
<entry lang="en" key="PARTITION_TOO_SMALL_FOR_HIDDEN_OS">Error: The partition for the hidden operating system (i.e. the first partition behind the system partition) must be at least 5% larger than the system partition (the system partition is the one where the currently running operating system is installed).</entry>
<entry lang="en" key="PARTITION_TOO_SMALL_FOR_HIDDEN_OS_NTFS">Error: The partition for the hidden operating system (i.e. the first partition behind the system partition) must be at least 110% (2.1 times) larger than the system partition (the system partition is the one where the currently running operating system is installed). The reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume (which is to contain a clone of the system partition) can reside only in the second half of the partition.</entry>
<entry lang="en" key="OUTER_VOLUME_TOO_SMALL_FOR_HIDDEN_OS_NTFS">Error: If the outer volume is formatted as NTFS, it must be at least 110% (2.1 times) larger than the system partition. The reason is that the NTFS file system always stores internal data exactly in the middle of the volume and, therefore, the hidden volume (which is to contain a clone of the system partition) can reside only in the second half of the outer volume.\n\nNote: The outer volume needs to reside within the same partition as the hidden operating system (i.e. within the first partition behind the system partition).</entry>
@@ -756,7 +756,7 @@
<entry lang="en" key="TWO_SYSTEMS_IN_ONE_PARTITION_REMARK">Remark: It is not practical (and therefore is not supported) to install operating systems in two VeraCrypt volumes that are embedded within a single partition, because using the outer operating system would often require data to be written to the area of the hidden operating system (and if such write operations were prevented using the hidden volume protection feature, it would inherently cause system crashes, i.e. 'Blue Screen' errors).</entry>
<entry lang="en" key="FOR_MORE_INFO_ON_PARTITIONS">For information on how to create and manage partitions, please refer to the documentation supplied with your operating system or contact your computer vendor's technical support team for assistance.</entry>
<entry lang="en" key="SYSTEM_PARTITION_NOT_ACTIVE">Error: The currently running operating system is not installed on the boot partition (first Active partition). This is not supported.</entry>
- <entry lang="en" key="CONFIRM_FAT_FOR_FILES_OVER_4GB">You indicated that you intend to store files larger than 4 GB in this VeraCrypt volume. However, you chose the FAT file system, on which files larger than 4 GB cannot be stored.\n\nAre you sure you want to format the volume as FAT?</entry>
+ <entry lang="en" key="CONFIRM_FAT_FOR_FILES_OVER_4GB">You indicated that you intend to store files larger than 4 GiB in this VeraCrypt volume. However, you chose the FAT file system, on which files larger than 4 GiB cannot be stored.\n\nAre you sure you want to format the volume as FAT?</entry>
<entry lang="en" key="NONSYS_INPLACE_DECRYPTION_BAD_VOL_FORMAT">Error: VeraCrypt does not support in-place decryption of legacy non-system volumes created by VeraCrypt 1.0b or earlier.\n\nNote: You can still decrypt files stored on the volume by copying/moving them to any unencrypted volume.</entry>
<entry lang="en" key="NONSYS_INPLACE_DECRYPTION_CANT_DECRYPT_HID_VOL">Error: VeraCrypt cannot in-place decrypt a hidden VeraCrypt volume.\n\nNote: You can still decrypt files stored on the volume by copying/moving them to any unencrypted volume.</entry>
<entry lang="en" key="CONFIRM_VOL_CONTAINS_NO_HIDDEN_VOL">Warning: Note that VeraCrypt cannot in-place decrypt a volume that contains a hidden VeraCrypt volume (the hidden volume would be overwritten with pseudorandom data).\n\nPlease confirm that the volume you are about to decrypt contains no hidden volume.\n\nNote: If the volume contains a hidden volume but you do not mind losing the hidden volume, you can select Proceed (the outer volume will be safely decrypted).</entry>
@@ -997,11 +997,11 @@
<entry lang="en" key="EXE_FILE_EXTENSION_CONFIRM">WARNING: We strongly recommend that you avoid file extensions that are used for executable files (such as .exe, .sys, or .dll) and other similarly problematic file extensions. Using such file extensions causes Windows and antivirus software to interfere with the container, which adversely affects the performance of the volume and may also cause other serious problems.\n\nWe strongly recommend that you remove the file extension or change it (e.g., to '.hc').\n\nAre you sure you want to use the problematic file extension?</entry>
<entry lang="en" key="EXE_FILE_EXTENSION_MOUNT_WARNING">WARNING: This container has a file extension that is used for executable files (such as .exe, .sys, or .dll) or some other file extension that is similarly problematic. It will very likely cause Windows and antivirus software to interfere with the container, which will adversely affect the performance of the volume and may also cause other serious problems.\n\nWe strongly recommend that you remove the file extension of the container or change it (e.g., to '.hc') after you dismount the volume.</entry>
<entry lang="en" key="HOMEPAGE">Homepage</entry>
- <entry lang="en" key="LARGE_IDE_WARNING_XP">WARNING: It appears that you have not applied any Service Pack to your Windows installation. You should not write to IDE disks larger than 128 GB under Windows XP to which you did not apply Service Pack 1 or later! If you do, data on the disk (no matter if it is a VeraCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a bug in VeraCrypt.</entry>
- <entry lang="en" key="LARGE_IDE_WARNING_2K">WARNING: It appears that you have not applied Service Pack 3 or later to your Windows installation. You should not write to IDE disks larger than 128 GB under Windows 2000 to which you did not apply Service Pack 3 or later! If you do, data on the disk (no matter if it is a VeraCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a bug in VeraCrypt.\n\nNote: You may also need to enable the 48-bit LBA support in the registry; for more information, see http://support.microsoft.com/kb/305098/EN-US</entry>
- <entry lang="en" key="LARGE_IDE_WARNING_2K_REGISTRY">WARNING: 48-bit LBA ATAPI support is disabled on your system. Therefore, you should not write to IDE disks larger than 128 GB! If you do, data on the disk (no matter if it is a VeraCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a limitation of VeraCrypt.\n\nTo enable the 48-bit LBA support, add the 'EnableBigLba' registry value in the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\atapi\\Parameters and set it to 1.\n\nFor more information, see http://support.microsoft.com/kb/305098</entry>
- <entry lang="en" key="VOLUME_TOO_LARGE_FOR_FAT32">Error: Files larger than 4 GB cannot be stored on a FAT32 file system. Therefore, file-hosted VeraCrypt volumes (containers) stored on a FAT32 file system cannot be larger than 4 GB.\n\nIf you need a larger volume, create it on an NTFS file system (or, if you use Windows Vista SP1 or later, on an exFAT file system) or, instead of creating a file-hosted volume, encrypt an entire partition or device.</entry>
- <entry lang="en" key="VOLUME_TOO_LARGE_FOR_WINXP">Warning: Windows XP does not support files larger than 2048 GB (it will report that "Not enough storage is available"). Therefore, you cannot create a file-hosted VeraCrypt volume (container) larger than 2048 GB under Windows XP.\n\nNote that it is still possible to encrypt the entire drive or create a partition-hosted VeraCrypt volume larger than 2048 GB under Windows XP.</entry>
+ <entry lang="en" key="LARGE_IDE_WARNING_XP">WARNING: It appears that you have not applied any Service Pack to your Windows installation. You should not write to IDE disks larger than 128 GiB under Windows XP to which you did not apply Service Pack 1 or later! If you do, data on the disk (no matter if it is a VeraCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a bug in VeraCrypt.</entry>
+ <entry lang="en" key="LARGE_IDE_WARNING_2K">WARNING: It appears that you have not applied Service Pack 3 or later to your Windows installation. You should not write to IDE disks larger than 128 GiB under Windows 2000 to which you did not apply Service Pack 3 or later! If you do, data on the disk (no matter if it is a VeraCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a bug in VeraCrypt.\n\nNote: You may also need to enable the 48-bit LBA support in the registry; for more information, see http://support.microsoft.com/kb/305098/EN-US</entry>
+ <entry lang="en" key="LARGE_IDE_WARNING_2K_REGISTRY">WARNING: 48-bit LBA ATAPI support is disabled on your system. Therefore, you should not write to IDE disks larger than 128 GiB! If you do, data on the disk (no matter if it is a VeraCrypt volume or not) may get corrupted. Note that this is a limitation of Windows, not a limitation of VeraCrypt.\n\nTo enable the 48-bit LBA support, add the 'EnableBigLba' registry value in the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\atapi\\Parameters and set it to 1.\n\nFor more information, see http://support.microsoft.com/kb/305098</entry>
+ <entry lang="en" key="VOLUME_TOO_LARGE_FOR_FAT32">Error: Files larger than 4 GiB cannot be stored on a FAT32 file system. Therefore, file-hosted VeraCrypt volumes (containers) stored on a FAT32 file system cannot be larger than 4 GiB.\n\nIf you need a larger volume, create it on an NTFS file system (or, if you use Windows Vista SP1 or later, on an exFAT file system) or, instead of creating a file-hosted volume, encrypt an entire partition or device.</entry>
+ <entry lang="en" key="VOLUME_TOO_LARGE_FOR_WINXP">Warning: Windows XP does not support files larger than 2048 GiB (it will report that "Not enough storage is available"). Therefore, you cannot create a file-hosted VeraCrypt volume (container) larger than 2048 GiB under Windows XP.\n\nNote that it is still possible to encrypt the entire drive or create a partition-hosted VeraCrypt volume larger than 2048 GiB under Windows XP.</entry>
<entry lang="en" key="FREE_SPACE_FOR_WRITING_TO_OUTER_VOLUME">WARNING: If you want to be able to add more data/files to the outer volume in future, you should consider choosing a smaller size for the hidden volume.\n\nAre you sure you want to continue with the size you specified?</entry>
<entry lang="en" key="NO_VOLUME_SELECTED">No volume selected.\n\nClick 'Select Device' or 'Select File' to select a VeraCrypt volume.</entry>
<entry lang="en" key="NO_SYSENC_PARTITION_SELECTED">No partition selected.\n\nClick 'Select Device' to select a dismounted partition that normally requires pre-boot authentication (for example, a partition located on the encrypted system drive of another operating system, which is not running, or the encrypted system partition of another operating system).\n\nNote: The selected partition will be mounted as a regular VeraCrypt volume without pre-boot authentication. This is useful e.g. for backup or repair operations.</entry>
@@ -1066,7 +1066,7 @@
<entry lang="en" key="ERR_ACCESS_DENIED">Access was denied by the operating system.\n\nPossible cause: The operating system requires that you have read/write permission (or administrator privileges) for certain folders, files, and devices, in order for you to be allowed to read and write data to/from them. Normally, a user without administrator privileges is allowed to create, read and modify files in his or her Documents folder.</entry>
<entry lang="en" key="SECTOR_SIZE_UNSUPPORTED">Error: The drive uses an unsupported sector size.\n\nIt is currently not possible to create partition/device-hosted volumes on drives that use sectors larger than 4096 bytes. However, note that you can create file-hosted volumes (containers) on such drives.</entry>
<entry lang="en" key="SYSENC_UNSUPPORTED_SECTOR_SIZE_BIOS">It is currently not possible to encrypt a system installed on a disk that uses a sector size other than 512 bytes.</entry>
- <entry lang="en" key="NO_SPACE_FOR_BOOT_LOADER">The VeraCrypt Boot Loader requires at least 32 KBytes of free space at the beginning of the system drive (the VeraCrypt Boot Loader needs to be stored in that area). Unfortunately, your drive does not meet this condition.\n\nPlease do NOT report this as a bug/problem in VeraCrypt. To solve this problem, you will need to repartition your disk and leave the first 32 KBytes of the disk free (in most cases, you will need to delete and recreate the first partition). We recommend that you use the Microsoft partition manager that is available e.g. when you are installing Windows.</entry>
+ <entry lang="en" key="NO_SPACE_FOR_BOOT_LOADER">The VeraCrypt Boot Loader requires at least 32 KibiBytes of free space at the beginning of the system drive (the VeraCrypt Boot Loader needs to be stored in that area). Unfortunately, your drive does not meet this condition.\n\nPlease do NOT report this as a bug/problem in VeraCrypt. To solve this problem, you will need to repartition your disk and leave the first 32 KibiBytes of the disk free (in most cases, you will need to delete and recreate the first partition). We recommend that you use the Microsoft partition manager that is available e.g. when you are installing Windows.</entry>
<entry lang="en" key="FEATURE_UNSUPPORTED_ON_CURRENT_OS">The feature is not supported on the version of the operating system you are currently using.</entry>
<entry lang="en" key="SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS">VeraCrypt does not support encryption of a system partition/drive on the version of the operating system you are currently using.</entry>
<entry lang="en" key="SYS_ENCRYPTION_UNSUPPORTED_ON_VISTA_SP0">Before you can encrypt the system partition/drive on Windows Vista, you need to install Service Pack 1 or higher for Windows Vista (no such Service Pack has been installed on this system yet).\n\nNote: Service Pack 1 for Windows Vista resolved an issue causing a shortage of free base memory during system boot.</entry>
@@ -1363,17 +1363,17 @@
<entry lang="en" key="VK_ALT">Alt</entry>
<entry lang="en" key="VK_WIN">Win</entry>
<entry lang="en" key="BYTE">B</entry>
- <entry lang="en" key="KB">KB</entry>
- <entry lang="en" key="MB">MB</entry>
- <entry lang="en" key="GB">GB</entry>
- <entry lang="en" key="TB">TB</entry>
- <entry lang="en" key="PB">PB</entry>
+ <entry lang="en" key="KB">KiB</entry>
+ <entry lang="en" key="MB">MiB</entry>
+ <entry lang="en" key="GB">GiB</entry>
+ <entry lang="en" key="TB">TiB</entry>
+ <entry lang="en" key="PB">PiB</entry>
<entry lang="en" key="B_PER_SEC">B/s</entry>
- <entry lang="en" key="KB_PER_SEC">KB/s</entry>
- <entry lang="en" key="MB_PER_SEC">MB/s</entry>
- <entry lang="en" key="GB_PER_SEC">GB/s</entry>
- <entry lang="en" key="TB_PER_SEC">TB/s</entry>
- <entry lang="en" key="PB_PER_SEC">PB/s</entry>
+ <entry lang="en" key="KB_PER_SEC">KiB/s</entry>
+ <entry lang="en" key="MB_PER_SEC">MiB/s</entry>
+ <entry lang="en" key="GB_PER_SEC">GiB/s</entry>
+ <entry lang="en" key="TB_PER_SEC">TiB/s</entry>
+ <entry lang="en" key="PB_PER_SEC">PiB/s</entry>
<entry lang="en" key="TRIPLE_DOT_GLYPH_ELLIPSIS">…</entry>
<entry lang="en" key="IDC_BOOT_LOADER_CACHE_PIM">Include &amp;PIM when caching pre-boot authentication password</entry>
<entry lang="en" key="IDC_PREF_CACHE_PIM">Include PIM when caching a password</entry>
@@ -1435,6 +1435,11 @@
<entry lang="en" key="IDC_ENABLE_CPU_RNG">Use CPU hardware random generator as an additional source of entropy</entry>
<entry lang="en" key="IDC_USE_LEGACY_MAX_PASSWORD_LENGTH">Use legacy maximum password length (64 characters)</entry>
<entry lang="en" key="IDC_ENABLE_RAM_ENCRYPTION">Activate encryption of keys and passwords stored in RAM</entry>
+ <entry lang="en" key="IDT_BENCHMARK">Benchmark:</entry>
+ <entry lang="en" key="IDC_DISABLE_MOUNT_MANAGER">Only create virtual device without mounting on selected drive letter</entry>
+ <entry lang="en" key="LEGACY_PASSWORD_UTF8_TOO_LONG">The entered password is too long: its UTF-8 representation exceeds 64 bytes.</entry>
+ <entry lang="en" key="HIDDEN_CREDS_SAME_AS_OUTER">The Hidden volume can't have the same password, PIM and keyfiles as the Outer volume</entry>
+ <entry lang="en" key="SYSENC_BITLOCKER_CONFLICT">VeraCrypt does not support encrypting a system drive that is already encrypted by BitLocker.</entry>
</localization>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="VeraCrypt">
diff --git a/src/Common/Password.c b/src/Common/Password.c
index ca0dd46..f2413b6 100644
--- a/src/Common/Password.c
+++ b/src/Common/Password.c
@@ -224,6 +224,19 @@ int ChangePwd (const wchar_t *lpszVolume, Password *oldPassword, int old_pkcs5,
if (dev == INVALID_HANDLE_VALUE)
goto error;
+ else if (!bDevice && bPreserveTimestamp)
+ {
+ // ensure that Last Access and Last Write timestamps are not modified
+ ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
+ ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
+
+ SetFileTime (dev, NULL, &ftLastAccessTime, NULL);
+
+ if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
+ bTimeStampValid = FALSE;
+ else
+ bTimeStampValid = TRUE;
+ }
if (bDevice)
{
@@ -313,13 +326,6 @@ int ChangePwd (const wchar_t *lpszVolume, Password *oldPassword, int old_pkcs5,
SetRandomPoolEnrichedByUserStatus (FALSE); /* force the display of the random enriching dialog */
- if (!bDevice && bPreserveTimestamp)
- {
- if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
- bTimeStampValid = FALSE;
- else
- bTimeStampValid = TRUE;
- }
for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++)
{
diff --git a/src/Common/Random.c b/src/Common/Random.c
index 1c6b953..09c55bf 100644
--- a/src/Common/Random.c
+++ b/src/Common/Random.c
@@ -94,14 +94,21 @@ HCRYPTPROV hCryptProv;
/* Init the random number generator, setup the hooks, and start the thread */
-int Randinit ()
+int RandinitWithCheck ( int* pAlreadyInitialized)
{
DWORD dwLastError = ERROR_SUCCESS;
if (GetMaxPkcs5OutSize() > RNG_POOL_SIZE)
TC_THROW_FATAL_EXCEPTION;
if(bRandDidInit)
+ {
+ if (pAlreadyInitialized)
+ *pAlreadyInitialized = 1;
return 0;
+ }
+
+ if (pAlreadyInitialized)
+ *pAlreadyInitialized = 0;
InitializeCriticalSection (&critRandProt);
@@ -153,6 +160,11 @@ error:
return 1;
}
+int Randinit ()
+{
+ return RandinitWithCheck (NULL);
+}
+
/* Close everything down, including the thread which is closed down by
setting a flag which eventually causes the thread function to exit */
void RandStop (BOOL freePool)
@@ -922,19 +934,6 @@ BOOL FastPoll (void)
return FALSE;
}
- /* 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*) buffer, sizeof (buffer));
- if (rndLen > 0)
- RandaddBuf (buffer, (int) rndLen);
- jent_entropy_collector_free (ec);
- }
- }
-
// use RDSEED or RDRAND from CPU as source of entropy if enabled
if ( IsCpuRngEnabled() &&
( (HasRDSEED() && RDSEED_getBytes (buffer, sizeof (buffer)))
diff --git a/src/Common/Random.h b/src/Common/Random.h
index 46fe59a..88dd041 100644
--- a/src/Common/Random.h
+++ b/src/Common/Random.h
@@ -35,6 +35,7 @@ extern "C" {
void RandAddInt ( unsigned __int32 x );
int Randinit ( void );
+int RandinitWithCheck ( int* pAlreadyInitialized);
void RandStop (BOOL freePool);
BOOL IsRandomNumberGeneratorStarted ();
void RandSetHashFunction ( int hash_algo_id );
diff --git a/src/Common/SecurityToken.cpp b/src/Common/SecurityToken.cpp
index 841ca72..8401a0e 100644
--- a/src/Common/SecurityToken.cpp
+++ b/src/Common/SecurityToken.cpp
@@ -26,12 +26,12 @@
# include <dlfcn.h>
#endif
-#include "SecurityToken.h"
-
-#ifndef burn
-# define burn Memory::Erase
+#ifdef TC_WINDOWS
+#define move_ptr std::move
#endif
+#include "SecurityToken.h"
+
using namespace std;
namespace VeraCrypt
@@ -513,9 +513,9 @@ namespace VeraCrypt
}
#ifdef TC_WINDOWS
- void SecurityToken::InitLibrary (const wstring &pkcs11LibraryPath, auto_ptr <GetPinFunctor> pinCallback, auto_ptr <SendExceptionFunctor> warningCallback)
+ void SecurityToken::InitLibrary (const wstring &pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> warningCallback)
#else
- void SecurityToken::InitLibrary (const string &pkcs11LibraryPath, auto_ptr <GetPinFunctor> pinCallback, auto_ptr <SendExceptionFunctor> warningCallback)
+ void SecurityToken::InitLibrary (const string &pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> warningCallback)
#endif
{
if (Initialized)
@@ -548,8 +548,8 @@ namespace VeraCrypt
if (status != CKR_OK)
throw Pkcs11Exception (status);
- PinCallback = pinCallback;
- WarningCallback = warningCallback;
+ PinCallback = move_ptr(pinCallback);
+ WarningCallback = move_ptr(warningCallback);
Initialized = true;
}
@@ -728,8 +728,8 @@ namespace VeraCrypt
}
#endif // TC_HEADER_Common_Exception
- auto_ptr <GetPinFunctor> SecurityToken::PinCallback;
- auto_ptr <SendExceptionFunctor> SecurityToken::WarningCallback;
+ unique_ptr <GetPinFunctor> SecurityToken::PinCallback;
+ unique_ptr <SendExceptionFunctor> SecurityToken::WarningCallback;
bool SecurityToken::Initialized;
CK_FUNCTION_LIST_PTR SecurityToken::Pkcs11Functions;
diff --git a/src/Common/SecurityToken.h b/src/Common/SecurityToken.h
index 1112f11..6b22889 100644
--- a/src/Common/SecurityToken.h
+++ b/src/Common/SecurityToken.h
@@ -191,9 +191,9 @@ namespace VeraCrypt
static list <SecurityTokenInfo> GetAvailableTokens ();
static SecurityTokenInfo GetTokenInfo (CK_SLOT_ID slotId);
#ifdef TC_WINDOWS
- static void InitLibrary (const wstring &pkcs11LibraryPath, auto_ptr <GetPinFunctor> pinCallback, auto_ptr <SendExceptionFunctor> warningCallback);
+ static void InitLibrary (const wstring &pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> warningCallback);
#else
- static void InitLibrary (const string &pkcs11LibraryPath, auto_ptr <GetPinFunctor> pinCallback, auto_ptr <SendExceptionFunctor> warningCallback);
+ static void InitLibrary (const string &pkcs11LibraryPath, unique_ptr <GetPinFunctor> pinCallback, unique_ptr <SendExceptionFunctor> warningCallback);
#endif
static bool IsInitialized () { return Initialized; }
static bool IsKeyfilePathValid (const wstring &securityTokenKeyfilePath);
@@ -211,7 +211,7 @@ namespace VeraCrypt
static void CheckLibraryStatus ();
static bool Initialized;
- static auto_ptr <GetPinFunctor> PinCallback;
+ static unique_ptr <GetPinFunctor> PinCallback;
static CK_FUNCTION_LIST_PTR Pkcs11Functions;
#ifdef TC_WINDOWS
static HMODULE Pkcs11LibraryHandle;
@@ -219,7 +219,7 @@ namespace VeraCrypt
static void *Pkcs11LibraryHandle;
#endif
static map <CK_SLOT_ID, Pkcs11Session> Sessions;
- static auto_ptr <SendExceptionFunctor> WarningCallback;
+ static unique_ptr <SendExceptionFunctor> WarningCallback;
};
}
diff --git a/src/Common/Tcdefs.h b/src/Common/Tcdefs.h
index 6ee154e..b84e29c 100644
--- a/src/Common/Tcdefs.h
+++ b/src/Common/Tcdefs.h
@@ -54,22 +54,22 @@ extern unsigned short _rotl16(unsigned short value, unsigned char shift);
#define TC_APP_NAME "VeraCrypt"
+// Version displayed to user
+#define VERSION_STRING "1.24-Update7"
+
#ifdef VC_EFI_CUSTOM_MODE
#define VERSION_STRING_SUFFIX "-CustomEFI"
#else
#define VERSION_STRING_SUFFIX ""
#endif
-// Version displayed to user
-#define VERSION_STRING "1.24-Beta5"
-
// Version number to compare against driver
#define VERSION_NUM 0x0124
// Release date
-#define TC_STR_RELEASE_DATE L"March 8, 2019"
-#define TC_RELEASE_DATE_YEAR 2019
-#define TC_RELEASE_DATE_MONTH 3
+#define TC_STR_RELEASE_DATE L"July 2, 2020"
+#define TC_RELEASE_DATE_YEAR 2020
+#define TC_RELEASE_DATE_MONTH 7
#define BYTES_PER_KB 1024LL
#define BYTES_PER_MB 1048576LL
@@ -263,6 +263,14 @@ extern ULONG AllocTag;
typedef int BOOL;
#endif
+#ifndef WORD
+typedef USHORT WORD;
+#endif
+
+#ifndef BOOLEAN
+typedef unsigned char BOOLEAN;
+#endif
+
#ifndef TRUE
#define TRUE 1
#endif
@@ -289,6 +297,19 @@ typedef NTSTATUS (NTAPI *ExGetFirmwareEnvironmentVariableFn) (
PULONG Attributes
);
+typedef BOOLEAN (NTAPI *KeAreAllApcsDisabledFn) ();
+
+typedef void (NTAPI *KeSetSystemGroupAffinityThreadFn)(
+ PGROUP_AFFINITY Affinity,
+ PGROUP_AFFINITY PreviousAffinity
+);
+
+typedef USHORT (NTAPI *KeQueryActiveGroupCountFn)();
+
+typedef ULONG (NTAPI *KeQueryActiveProcessorCountExFn)(
+ USHORT GroupNumber
+);
+
extern NTSTATUS NTAPI KeSaveExtendedProcessorState (
__in ULONG64 Mask,
PXSTATE_SAVE XStateSave
@@ -299,6 +320,9 @@ extern VOID NTAPI KeRestoreExtendedProcessorState (
PXSTATE_SAVE XStateSave
);
+extern BOOLEAN VC_KeAreAllApcsDisabled (VOID);
+
+
#else /* !TC_WINDOWS_DRIVER */
#if !defined(_UEFI)
#define TCalloc malloc
diff --git a/src/Common/Zip.vcxproj b/src/Common/Zip.vcxproj
index 746f771..086657b 100644
--- a/src/Common/Zip.vcxproj
+++ b/src/Common/Zip.vcxproj
@@ -81,6 +81,7 @@
<ClCompile Include="libzip\zip_set_file_comment.c" />
<ClCompile Include="libzip\zip_set_file_compression.c" />
<ClCompile Include="libzip\zip_set_name.c" />
+ <ClCompile Include="libzip\zip_source_accept_empty.c" />
<ClCompile Include="libzip\zip_source_begin_write.c" />
<ClCompile Include="libzip\zip_source_begin_write_cloning.c" />
<ClCompile Include="libzip\zip_source_buffer.c" />
diff --git a/src/Common/Zip.vcxproj.filters b/src/Common/Zip.vcxproj.filters
index fa83631..f274e80 100644
--- a/src/Common/Zip.vcxproj.filters
+++ b/src/Common/Zip.vcxproj.filters
@@ -360,6 +360,9 @@
<ClCompile Include="libzip\zip_source_get_compression_flags.c">
<Filter>libzip</Filter>
</ClCompile>
+ <ClCompile Include="libzip\zip_source_accept_empty.c">
+ <Filter>libzip</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="libzip\compat.h">
diff --git a/src/Common/libzip/NEWS.md b/src/Common/libzip/NEWS.md
index ab2be0a..9d8d2a3 100644
--- a/src/Common/libzip/NEWS.md
+++ b/src/Common/libzip/NEWS.md
@@ -1,3 +1,11 @@
+1.5.2 [2019-03-12]
+==================
+* Fix bug in AES encryption affecting certain file sizes
+* Keep file permissions when modifying zip archives
+* Support systems with small stack size.
+* Support mbed TLS as crypto backend.
+* Add nullability annotations.
+
1.5.1 [2018-04-11]
==================
diff --git a/src/Common/libzip/compat.h b/src/Common/libzip/compat.h
index 7604d96..e0a27be 100644
--- a/src/Common/libzip/compat.h
+++ b/src/Common/libzip/compat.h
@@ -3,7 +3,7 @@
/*
compat.h -- compatibility defines.
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -81,6 +81,11 @@ typedef char bool;
#define EOVERFLOW EFBIG
#endif
+/* not supported on at least Windows */
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
#ifdef _WIN32
#if defined(HAVE__CHMOD)
#define chmod _chmod
@@ -120,9 +125,6 @@ typedef char bool;
#if !defined(HAVE_STRTOULL) && defined(HAVE__STRTOUI64)
#define strtoull _strtoui64
#endif
-#if defined(HAVE__UMASK)
-#define umask _umask
-#endif
#if defined(HAVE__UNLINK)
#define unlink _unlink
#endif
@@ -136,11 +138,6 @@ typedef char bool;
#define ftello(s) ((long)ftell((s)))
#endif
-#ifndef HAVE_MKSTEMP
-int _zip_mkstemp(char *);
-#define mkstemp _zip_mkstemp
-#endif
-
#if !defined(HAVE_STRCASECMP)
#if defined(HAVE__STRICMP)
#define strcasecmp _stricmp
@@ -203,4 +200,8 @@ int _zip_mkstemp(char *);
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
#endif
+#ifndef S_ISREG
+#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
+#endif
+
#endif /* compat.h */
diff --git a/src/Common/libzip/config.h b/src/Common/libzip/config.h
index d6134b4..4de10df 100644
--- a/src/Common/libzip/config.h
+++ b/src/Common/libzip/config.h
@@ -76,7 +76,7 @@
#define HAVE_SHARED
/* END DEFINES */
#define PACKAGE "libzip"
-#define VERSION "1.5.0a"
+#define VERSION "1.5.2"
#ifndef HAVE_SSIZE_T_LIBZIP
# if SIZE_T_LIBZIP == INT_LIBZIP
diff --git a/src/Common/libzip/zip.h b/src/Common/libzip/zip.h
index 2d83a99..34b544e 100644
--- a/src/Common/libzip/zip.h
+++ b/src/Common/libzip/zip.h
@@ -3,7 +3,7 @@
/*
zip.h -- exported declarations.
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -134,6 +134,7 @@ extern "C" {
#define ZIP_ER_INUSE 29 /* N Resource still in use */
#define ZIP_ER_TELL 30 /* S Tell error */
#define ZIP_ER_COMPRESSED_DATA 31 /* N Compressed data invalid */
+#define ZIP_ER_CANCELLED 32 /* N Operation cancelled */
/* type of system error value */
@@ -162,6 +163,7 @@ extern "C" {
/* 15-17 - Reserved by PKWARE */
#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */
#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */
+#define ZIP_CM_LZMA2 33
#define ZIP_CM_XZ 95 /* XZ compressed data */
#define ZIP_CM_JPEG 96 /* Compressed Jpeg data */
#define ZIP_CM_WAVPACK 97 /* WavPack compressed data */
@@ -229,7 +231,8 @@ enum zip_source_cmd {
ZIP_SOURCE_SUPPORTS, /* check whether source supports command */
ZIP_SOURCE_REMOVE, /* remove file */
ZIP_SOURCE_GET_COMPRESSION_FLAGS, /* get compression flags, internal only */
- ZIP_SOURCE_BEGIN_WRITE_CLONING /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */
+ ZIP_SOURCE_BEGIN_WRITE_CLONING, /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */
+ ZIP_SOURCE_ACCEPT_EMPTY /* whether empty files are valid archives */
};
typedef enum zip_source_cmd zip_source_cmd_t;
@@ -290,7 +293,7 @@ struct zip_error {
struct zip_stat {
zip_uint64_t valid; /* which fields have valid values */
- const char *name; /* name of the file */
+ const char * name; /* name of the file */
zip_uint64_t index; /* index within archive */
zip_uint64_t size; /* size of file (uncompressed) */
zip_uint64_t comp_size; /* size of file (compressed) */
@@ -302,7 +305,7 @@ struct zip_stat {
};
struct zip_buffer_fragment {
- zip_uint8_t *data;
+ zip_uint8_t * data;
zip_uint64_t length;
};
@@ -321,6 +324,7 @@ typedef zip_uint32_t zip_flags_t;
typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, zip_source_cmd_t);
typedef void (*zip_progress_callback)(zip_t *, double, void *);
+typedef int (*zip_cancel_callback)(zip_t *, void *);
#ifndef ZIP_DISABLE_DEPRECATED
typedef void (*zip_progress_callback_t)(double);
@@ -328,7 +332,7 @@ ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t)
ZIP_EXTERN zip_int64_t zip_add(zip_t *, const char *, zip_source_t *); /* use zip_file_add */
ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *, const char *); /* use zip_dir_add */
-ZIP_EXTERN const char *zip_get_file_comment(zip_t *, zip_uint64_t, int *, int); /* use zip_file_get_comment */
+ZIP_EXTERN const char * zip_get_file_comment(zip_t *, zip_uint64_t, int *, int); /* use zip_file_get_comment */
ZIP_EXTERN int zip_get_num_files(zip_t *); /* use zip_get_num_entries instead */
ZIP_EXTERN int zip_rename(zip_t *, zip_uint64_t, const char *); /* use zip_file_rename */
ZIP_EXTERN int zip_replace(zip_t *, zip_uint64_t, zip_source_t *); /* use zip_file_replace */
@@ -344,7 +348,7 @@ ZIP_EXTERN int zip_delete(zip_t *, zip_uint64_t);
ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *, const char *, zip_flags_t);
ZIP_EXTERN void zip_discard(zip_t *);
-ZIP_EXTERN zip_error_t *zip_get_error(zip_t *);
+ZIP_EXTERN zip_error_t * zip_get_error(zip_t *);
ZIP_EXTERN void zip_error_clear(zip_t *);
ZIP_EXTERN int zip_error_code_zip(const zip_error_t *);
ZIP_EXTERN int zip_error_code_system(const zip_error_t *);
@@ -352,12 +356,12 @@ ZIP_EXTERN void zip_error_fini(zip_error_t *);
ZIP_EXTERN void zip_error_init(zip_error_t *);
ZIP_EXTERN void zip_error_init_with_code(zip_error_t *, int);
ZIP_EXTERN void zip_error_set(zip_error_t *, int, int);
-ZIP_EXTERN const char *zip_error_strerror(zip_error_t *);
+ZIP_EXTERN const char * zip_error_strerror(zip_error_t *);
ZIP_EXTERN int zip_error_system_type(const zip_error_t *);
ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *, void *, zip_uint64_t);
ZIP_EXTERN int zip_fclose(zip_file_t *);
-ZIP_EXTERN zip_t *zip_fdopen(int, int, int *);
+ZIP_EXTERN zip_t * zip_fdopen(int, int, int *);
ZIP_EXTERN zip_int64_t zip_file_add(zip_t *, const char *, zip_source_t *, zip_flags_t);
ZIP_EXTERN void zip_file_error_clear(zip_file_t *);
ZIP_EXTERN int zip_file_extra_field_delete(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t);
@@ -365,54 +369,56 @@ ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *, zip_uint64_t, zip_uint
ZIP_EXTERN int zip_file_extra_field_set(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t);
ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *, zip_uint64_t, zip_flags_t);
ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t);
-ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t);
-ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t);
-ZIP_EXTERN const char *zip_file_get_comment(zip_t *, zip_uint64_t, zip_uint32_t *, zip_flags_t);
-ZIP_EXTERN zip_error_t *zip_file_get_error(zip_file_t *);
+ZIP_EXTERN const zip_uint8_t * zip_file_extra_field_get(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t);
+ZIP_EXTERN const zip_uint8_t * zip_file_extra_field_get_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t);
+ZIP_EXTERN const char * zip_file_get_comment(zip_t *, zip_uint64_t, zip_uint32_t *, zip_flags_t);
+ZIP_EXTERN zip_error_t * zip_file_get_error(zip_file_t *);
ZIP_EXTERN int zip_file_get_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t *, zip_uint32_t *);
ZIP_EXTERN int zip_file_rename(zip_t *, zip_uint64_t, const char *, zip_flags_t);
ZIP_EXTERN int zip_file_replace(zip_t *, zip_uint64_t, zip_source_t *, zip_flags_t);
ZIP_EXTERN int zip_file_set_comment(zip_t *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t);
+ZIP_EXTERN int zip_file_set_dostime(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
ZIP_EXTERN int zip_file_set_encryption(zip_t *, zip_uint64_t, zip_uint16_t, const char *);
ZIP_EXTERN int zip_file_set_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t);
ZIP_EXTERN int zip_file_set_mtime(zip_t *, zip_uint64_t, time_t, zip_flags_t);
-ZIP_EXTERN const char *zip_file_strerror(zip_file_t *);
-ZIP_EXTERN zip_file_t *zip_fopen(zip_t *, const char *, zip_flags_t);
-ZIP_EXTERN zip_file_t *zip_fopen_encrypted(zip_t *, const char *, zip_flags_t, const char *);
-ZIP_EXTERN zip_file_t *zip_fopen_index(zip_t *, zip_uint64_t, zip_flags_t);
-ZIP_EXTERN zip_file_t *zip_fopen_index_encrypted(zip_t *, zip_uint64_t, zip_flags_t, const char *);
+ZIP_EXTERN const char * zip_file_strerror(zip_file_t *);
+ZIP_EXTERN zip_file_t * zip_fopen(zip_t *, const char *, zip_flags_t);
+ZIP_EXTERN zip_file_t * zip_fopen_encrypted(zip_t *, const char *, zip_flags_t, const char *);
+ZIP_EXTERN zip_file_t * zip_fopen_index(zip_t *, zip_uint64_t, zip_flags_t);
+ZIP_EXTERN zip_file_t * zip_fopen_index_encrypted(zip_t *, zip_uint64_t, zip_flags_t, const char *);
ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *, void *, zip_uint64_t);
ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *, zip_int64_t, int);
ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *);
-ZIP_EXTERN const char *zip_get_archive_comment(zip_t *, int *, zip_flags_t);
+ZIP_EXTERN const char * zip_get_archive_comment(zip_t *, int *, zip_flags_t);
ZIP_EXTERN int zip_get_archive_flag(zip_t *, zip_flags_t, zip_flags_t);
-ZIP_EXTERN const char *zip_get_name(zip_t *, zip_uint64_t, zip_flags_t);
+ZIP_EXTERN const char * zip_get_name(zip_t *, zip_uint64_t, zip_flags_t);
ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *, zip_flags_t);
-ZIP_EXTERN const char *zip_libzip_version(void);
+ZIP_EXTERN const char * zip_libzip_version(void);
ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *, const char *, zip_flags_t);
-ZIP_EXTERN zip_t *zip_open(const char *, int, int *);
-ZIP_EXTERN zip_t *zip_open_from_source(zip_source_t *, int, zip_error_t *);
+ZIP_EXTERN zip_t * zip_open(const char *, int, int *);
+ZIP_EXTERN zip_t * zip_open_from_source(zip_source_t *, int, zip_error_t *);
ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *, double, zip_progress_callback, void (*)(void *), void *);
+ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *, zip_cancel_callback, void (*)(void *), void *);
ZIP_EXTERN int zip_set_archive_comment(zip_t *, const char *, zip_uint16_t);
ZIP_EXTERN int zip_set_archive_flag(zip_t *, zip_flags_t, int);
ZIP_EXTERN int zip_set_default_password(zip_t *, const char *);
ZIP_EXTERN int zip_set_file_compression(zip_t *, zip_uint64_t, zip_int32_t, zip_uint32_t);
ZIP_EXTERN int zip_source_begin_write(zip_source_t *);
ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *, zip_uint64_t);
-ZIP_EXTERN zip_source_t *zip_source_buffer(zip_t *, const void *, zip_uint64_t, int);
-ZIP_EXTERN zip_source_t *zip_source_buffer_create(const void *, zip_uint64_t, int, zip_error_t *);
-ZIP_EXTERN zip_source_t *zip_source_buffer_fragment(zip_t *, const zip_buffer_fragment_t *, zip_uint64_t, int);
-ZIP_EXTERN zip_source_t *zip_source_buffer_fragment_create(const zip_buffer_fragment_t *, zip_uint64_t, int, zip_error_t *);
+ZIP_EXTERN zip_source_t * zip_source_buffer(zip_t *, const void *, zip_uint64_t, int);
+ZIP_EXTERN zip_source_t * zip_source_buffer_create(const void *, zip_uint64_t, int, zip_error_t *);
+ZIP_EXTERN zip_source_t * zip_source_buffer_fragment(zip_t *, const zip_buffer_fragment_t *, zip_uint64_t, int);
+ZIP_EXTERN zip_source_t * zip_source_buffer_fragment_create(const zip_buffer_fragment_t *, zip_uint64_t, int, zip_error_t *);
ZIP_EXTERN int zip_source_close(zip_source_t *);
ZIP_EXTERN int zip_source_commit_write(zip_source_t *);
-ZIP_EXTERN zip_error_t *zip_source_error(zip_source_t *);
-ZIP_EXTERN zip_source_t *zip_source_file(zip_t *, const char *, zip_uint64_t, zip_int64_t);
-ZIP_EXTERN zip_source_t *zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *);
-ZIP_EXTERN zip_source_t *zip_source_filep(zip_t *, FILE *, zip_uint64_t, zip_int64_t);
-ZIP_EXTERN zip_source_t *zip_source_filep_create(FILE *, zip_uint64_t, zip_int64_t, zip_error_t *);
+ZIP_EXTERN zip_error_t * zip_source_error(zip_source_t *);
+ZIP_EXTERN zip_source_t * zip_source_file(zip_t *, const char *, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN zip_source_t * zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *);
+ZIP_EXTERN zip_source_t * zip_source_filep(zip_t *, FILE *, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN zip_source_t * zip_source_filep_create(FILE *, zip_uint64_t, zip_int64_t, zip_error_t *);
ZIP_EXTERN void zip_source_free(zip_source_t *);
-ZIP_EXTERN zip_source_t *zip_source_function(zip_t *, zip_source_callback, void *);
-ZIP_EXTERN zip_source_t *zip_source_function_create(zip_source_callback, void *, zip_error_t *);
+ZIP_EXTERN zip_source_t * zip_source_function(zip_t *, zip_source_callback , void *);
+ZIP_EXTERN zip_source_t * zip_source_function_create(zip_source_callback , void *, zip_error_t *);
ZIP_EXTERN int zip_source_is_deleted(zip_source_t *);
ZIP_EXTERN void zip_source_keep(zip_source_t *);
ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...);
@@ -434,11 +440,11 @@ ZIP_EXTERN zip_source_t *zip_source_win32w(zip_t *, const wchar_t *, zip_uint64_
ZIP_EXTERN zip_source_t *zip_source_win32w_create(const wchar_t *, zip_uint64_t, zip_int64_t, zip_error_t *);
#endif
ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *, const void *, zip_uint64_t);
-ZIP_EXTERN zip_source_t *zip_source_zip(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN zip_source_t * zip_source_zip(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
ZIP_EXTERN int zip_stat(zip_t *, const char *, zip_flags_t, zip_stat_t *);
ZIP_EXTERN int zip_stat_index(zip_t *, zip_uint64_t, zip_flags_t, zip_stat_t *);
-ZIP_EXTERN void zip_stat_init(zip_stat_t *);
-ZIP_EXTERN const char *zip_strerror(zip_t *);
+ZIP_EXTERN void zip_stat_init( zip_stat_t *);
+ZIP_EXTERN const char * zip_strerror(zip_t *);
ZIP_EXTERN int zip_unchange(zip_t *, zip_uint64_t);
ZIP_EXTERN int zip_unchange_all(zip_t *);
ZIP_EXTERN int zip_unchange_archive(zip_t *);
diff --git a/src/Common/libzip/zip_add.c b/src/Common/libzip/zip_add.c
index 69966d3..1954235 100644
--- a/src/Common/libzip/zip_add.c
+++ b/src/Common/libzip/zip_add.c
@@ -1,6 +1,6 @@
/*
zip_add.c -- add file via callback function
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_add_dir.c b/src/Common/libzip/zip_add_dir.c
index a0026a7..88fcf53 100644
--- a/src/Common/libzip/zip_add_dir.c
+++ b/src/Common/libzip/zip_add_dir.c
@@ -1,6 +1,6 @@
/*
zip_add_dir.c -- add directory
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_add_entry.c b/src/Common/libzip/zip_add_entry.c
index f1de445..f52e0b5 100644
--- a/src/Common/libzip/zip_add_entry.c
+++ b/src/Common/libzip/zip_add_entry.c
@@ -1,6 +1,6 @@
/*
zip_add_entry.c -- create and init struct zip_entry
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_algorithm_deflate.c b/src/Common/libzip/zip_algorithm_deflate.c
index 2a1c904..30e072a 100644
--- a/src/Common/libzip/zip_algorithm_deflate.c
+++ b/src/Common/libzip/zip_algorithm_deflate.c
@@ -1,6 +1,6 @@
/*
zip_algorithm_deflate.c -- deflate (de)compression routines
- Copyright (C) 2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -51,6 +51,7 @@ allocate(bool compress, int compression_flags, zip_error_t *error) {
struct ctx *ctx;
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
+ zip_error_set(error, ZIP_ET_SYS, errno);
return NULL;
}
diff --git a/src/Common/libzip/zip_buffer.c b/src/Common/libzip/zip_buffer.c
index 96010b2..8c24b27 100644
--- a/src/Common/libzip/zip_buffer.c
+++ b/src/Common/libzip/zip_buffer.c
@@ -1,6 +1,6 @@
/*
zip_buffer.c -- bounds checked access to memory buffer
- Copyright (C) 2014-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_close.c b/src/Common/libzip/zip_close.c
index c46e1b3..2a9fed2 100644
--- a/src/Common/libzip/zip_close.c
+++ b/src/Common/libzip/zip_close.c
@@ -1,6 +1,6 @@
/*
zip_close.c -- close zip archive and update changes
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -73,8 +73,10 @@ zip_close(zip_t *za) {
if (survivors == 0) {
if ((za->open_flags & ZIP_TRUNCATE) || changed) {
if (zip_source_remove(za->src) < 0) {
- _zip_error_set_from_source(&za->error, za->src);
- return -1;
+ if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) {
+ _zip_error_set_from_source(&za->error, za->src);
+ return -1;
+ }
}
}
zip_discard(za);
@@ -158,14 +160,23 @@ zip_close(zip_t *za) {
}
}
- _zip_progress_start(za->progress);
+ if (_zip_progress_start(za->progress) != 0) {
+ zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
+ zip_source_rollback_write(za->src);
+ free(filelist);
+ return -1;
+ }
error = 0;
for (j = 0; j < survivors; j++) {
int new_data;
zip_entry_t *entry;
zip_dirent_t *de;
- _zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors);
+ if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) {
+ zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
+ error = 1;
+ break;
+ }
i = filelist[j].idx;
entry = za->entry + i;
@@ -256,10 +267,9 @@ zip_close(zip_t *za) {
_zip_error_set_from_source(&za->error, za->src);
error = 1;
}
+ _zip_progress_end(za->progress);
}
- _zip_progress_end(za->progress);
-
if (error) {
zip_source_rollback_write(za->src);
return -1;
@@ -520,32 +530,43 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
static int
copy_data(zip_t *za, zip_uint64_t len) {
- zip_uint8_t buf[BUFSIZE];
+ DEFINE_BYTE_ARRAY(buf, BUFSIZE);
size_t n;
double total = (double)len;
+ if (!byte_array_init(buf, BUFSIZE)) {
+ zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ return -1;
+ }
+
while (len > 0) {
- n = len > sizeof(buf) ? sizeof(buf) : len;
+ n = len > BUFSIZE ? BUFSIZE : len;
if (_zip_read(za->src, buf, n, &za->error) < 0) {
+ byte_array_fini(buf);
return -1;
}
if (_zip_write(za, buf, n) < 0) {
+ byte_array_fini(buf);
return -1;
}
len -= n;
- _zip_progress_update(za->progress, (total - (double)len) / total);
+ if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) {
+ zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
+ return -1;
+ }
}
+ byte_array_fini(buf);
return 0;
}
static int
copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
- zip_uint8_t buf[BUFSIZE];
+ DEFINE_BYTE_ARRAY(buf, BUFSIZE);
zip_int64_t n, current;
int ret;
@@ -554,16 +575,25 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
return -1;
}
+ if (!byte_array_init(buf, BUFSIZE)) {
+ zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ return -1;
+ }
+
ret = 0;
current = 0;
- while ((n = zip_source_read(src, buf, sizeof(buf))) > 0) {
+ while ((n = zip_source_read(src, buf, BUFSIZE)) > 0) {
if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
ret = -1;
break;
}
- if (n == sizeof(buf) && za->progress && data_length > 0) {
+ if (n == BUFSIZE && za->progress && data_length > 0) {
current += n;
- _zip_progress_update(za->progress, (double)current / (double)data_length);
+ if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) {
+ zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
+ ret = -1;
+ break;
+ }
}
}
@@ -572,6 +602,8 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
ret = -1;
}
+ byte_array_fini(buf);
+
zip_source_close(src);
return ret;
diff --git a/src/Common/libzip/zip_delete.c b/src/Common/libzip/zip_delete.c
index ae8f5a6..97701a0 100644
--- a/src/Common/libzip/zip_delete.c
+++ b/src/Common/libzip/zip_delete.c
@@ -1,6 +1,6 @@
/*
zip_delete.c -- delete file from zip archive
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_dir_add.c b/src/Common/libzip/zip_dir_add.c
index 236b439..c40b1cb 100644
--- a/src/Common/libzip/zip_dir_add.c
+++ b/src/Common/libzip/zip_dir_add.c
@@ -1,6 +1,6 @@
/*
zip_dir_add.c -- add directory
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_dirent.c b/src/Common/libzip/zip_dirent.c
index a6dbfac..2bbb63d 100644
--- a/src/Common/libzip/zip_dirent.c
+++ b/src/Common/libzip/zip_dirent.c
@@ -1,6 +1,6 @@
/*
zip_dirent.c -- read directory entry (local or central), clean dirent
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -41,7 +41,6 @@
#include "zipint.h"
-static time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t);
static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str);
static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t, zip_string_t *, zip_error_t *);
static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error);
@@ -978,7 +977,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
}
-static time_t
+time_t
_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate) {
struct tm tm;
@@ -1066,15 +1065,26 @@ _zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *err
void
_zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) {
- struct tm *tm;
+ struct tm *tpm;
- tm = localtime(&intime);
- if (tm->tm_year < 80) {
- tm->tm_year = 80;
+#ifdef HAVE_LOCALTIME_R
+ struct tm tm;
+ tpm = localtime_r(&intime, &tm);
+#else
+ tpm = localtime(&intime);
+#endif
+ if (tpm == NULL) {
+ /* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */
+ *ddate = (1 << 5) + 1;
+ *dtime = 0;
+ return;
+ }
+ if (tpm->tm_year < 80) {
+ tpm->tm_year = 80;
}
- *ddate = (zip_uint16_t)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
- *dtime = (zip_uint16_t)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
+ *ddate = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
+ *dtime = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1));
return;
}
diff --git a/src/Common/libzip/zip_discard.c b/src/Common/libzip/zip_discard.c
index 5bbf8d6..12f0636 100644
--- a/src/Common/libzip/zip_discard.c
+++ b/src/Common/libzip/zip_discard.c
@@ -1,6 +1,6 @@
/*
zip_discard.c -- discard and free struct zip
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_entry.c b/src/Common/libzip/zip_entry.c
index f083412..52ecaef 100644
--- a/src/Common/libzip/zip_entry.c
+++ b/src/Common/libzip/zip_entry.c
@@ -1,6 +1,6 @@
/*
zip_entry.c -- struct zip_entry helper functions
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_err_str.c b/src/Common/libzip/zip_err_str.c
index 3d9ee54..e0a04a9 100644
--- a/src/Common/libzip/zip_err_str.c
+++ b/src/Common/libzip/zip_err_str.c
@@ -5,16 +5,80 @@
#include "zipint.h"
-const char *const _zip_err_str[] = {
- "No error", "Multi-disk zip archives not supported", "Renaming temporary file failed", "Closing zip archive failed", "Seek error", "Read error", "Write error", "CRC error", "Containing zip archive was closed", "No such file", "File already exists", "Can't open file", "Failure to create temporary file", "Zlib error", "Malloc failure", "Entry has been changed", "Compression method not supported", "Premature end of file", "Invalid argument", "Not a zip archive", "Internal error", "Zip archive inconsistent", "Can't remove file", "Entry has been deleted", "Encryption method not supported", "Read-only archive", "No password provided", "Wrong password provided", "Operation not supported", "Resource still in use", "Tell error", "Compressed data invalid",
+const char * const _zip_err_str[] = {
+ "No error",
+ "Multi-disk zip archives not supported",
+ "Renaming temporary file failed",
+ "Closing zip archive failed",
+ "Seek error",
+ "Read error",
+ "Write error",
+ "CRC error",
+ "Containing zip archive was closed",
+ "No such file",
+ "File already exists",
+ "Can't open file",
+ "Failure to create temporary file",
+ "Zlib error",
+ "Malloc failure",
+ "Entry has been changed",
+ "Compression method not supported",
+ "Premature end of file",
+ "Invalid argument",
+ "Not a zip archive",
+ "Internal error",
+ "Zip archive inconsistent",
+ "Can't remove file",
+ "Entry has been deleted",
+ "Encryption method not supported",
+ "Read-only archive",
+ "No password provided",
+ "Wrong password provided",
+ "Operation not supported",
+ "Resource still in use",
+ "Tell error",
+ "Compressed data invalid",
+ "Operation cancelled",
};
-const int _zip_nerr_str = sizeof(_zip_err_str) / sizeof(_zip_err_str[0]);
+const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]);
#define N ZIP_ET_NONE
#define S ZIP_ET_SYS
#define Z ZIP_ET_ZLIB
const int _zip_err_type[] = {
- N, N, S, S, S, S, S, N, N, N, N, S, S, Z, N, N, N, N, N, N, N, N, S, N, N, N, N, N, N, N, S, N,
+ N,
+ N,
+ S,
+ S,
+ S,
+ S,
+ S,
+ N,
+ N,
+ N,
+ N,
+ S,
+ S,
+ Z,
+ N,
+ N,
+ N,
+ N,
+ N,
+ N,
+ N,
+ N,
+ S,
+ N,
+ N,
+ N,
+ N,
+ N,
+ N,
+ N,
+ S,
+ N,
+ N,
};
diff --git a/src/Common/libzip/zip_error.c b/src/Common/libzip/zip_error.c
index 9ccaf91..a0f74f0 100644
--- a/src/Common/libzip/zip_error.c
+++ b/src/Common/libzip/zip_error.c
@@ -1,6 +1,6 @@
/*
zip_error.c -- zip_error_t helper functions
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_error_clear.c b/src/Common/libzip/zip_error_clear.c
index 2cce450..eec1568 100644
--- a/src/Common/libzip/zip_error_clear.c
+++ b/src/Common/libzip/zip_error_clear.c
@@ -1,6 +1,6 @@
/*
zip_error_clear.c -- clear zip error
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_error_get.c b/src/Common/libzip/zip_error_get.c
index 1f02ed3..9588b4c 100644
--- a/src/Common/libzip/zip_error_get.c
+++ b/src/Common/libzip/zip_error_get.c
@@ -1,6 +1,6 @@
/*
zip_error_get.c -- get zip error
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_error_get_sys_type.c b/src/Common/libzip/zip_error_get_sys_type.c
index d7a594e..3dfe5c2 100644
--- a/src/Common/libzip/zip_error_get_sys_type.c
+++ b/src/Common/libzip/zip_error_get_sys_type.c
@@ -1,6 +1,6 @@
/*
zip_error_get_sys_type.c -- return type of system error code
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_error_strerror.c b/src/Common/libzip/zip_error_strerror.c
index 6baf900..6358577 100644
--- a/src/Common/libzip/zip_error_strerror.c
+++ b/src/Common/libzip/zip_error_strerror.c
@@ -1,6 +1,6 @@
/*
zip_error_sterror.c -- get string representation of struct zip_error
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_error_to_str.c b/src/Common/libzip/zip_error_to_str.c
index 518c0e5..13faf96 100644
--- a/src/Common/libzip/zip_error_to_str.c
+++ b/src/Common/libzip/zip_error_to_str.c
@@ -1,6 +1,6 @@
/*
zip_error_to_str.c -- get string representation of zip error code
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_extra_field.c b/src/Common/libzip/zip_extra_field.c
index 42f97d0..7114a25 100644
--- a/src/Common/libzip/zip_extra_field.c
+++ b/src/Common/libzip/zip_extra_field.c
@@ -1,6 +1,6 @@
/*
zip_extra_field.c -- manipulate extra fields
- Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_extra_field_api.c b/src/Common/libzip/zip_extra_field_api.c
index 469abd2..605f95d 100644
--- a/src/Common/libzip/zip_extra_field_api.c
+++ b/src/Common/libzip/zip_extra_field_api.c
@@ -1,6 +1,6 @@
/*
zip_extra_field_api.c -- public extra fields API functions
- Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_fclose.c b/src/Common/libzip/zip_fclose.c
index be98cc0..6eb9dc9 100644
--- a/src/Common/libzip/zip_fclose.c
+++ b/src/Common/libzip/zip_fclose.c
@@ -1,6 +1,6 @@
/*
zip_fclose.c -- close file in zip archive
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_fdopen.c b/src/Common/libzip/zip_fdopen.c
index b1fc22b..5a732cd 100644
--- a/src/Common/libzip/zip_fdopen.c
+++ b/src/Common/libzip/zip_fdopen.c
@@ -1,6 +1,6 @@
/*
zip_fdopen.c -- open read-only archive from file descriptor
- Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -67,12 +67,14 @@ zip_fdopen(int fd_orig, int _flags, int *zep) {
zip_error_init(&error);
if ((src = zip_source_filep_create(fp, 0, -1, &error)) == NULL) {
+ fclose(fp);
_zip_set_open_error(zep, &error, 0);
zip_error_fini(&error);
return NULL;
}
if ((za = zip_open_from_source(src, _flags, &error)) == NULL) {
+ zip_source_free(src);
_zip_set_open_error(zep, &error, 0);
zip_error_fini(&error);
return NULL;
diff --git a/src/Common/libzip/zip_file_add.c b/src/Common/libzip/zip_file_add.c
index ec8ef06..c019d8d 100644
--- a/src/Common/libzip/zip_file_add.c
+++ b/src/Common/libzip/zip_file_add.c
@@ -1,6 +1,6 @@
/*
zip_file_add.c -- add file via callback function
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_file_error_clear.c b/src/Common/libzip/zip_file_error_clear.c
index 666beca..47e5da6 100644
--- a/src/Common/libzip/zip_file_error_clear.c
+++ b/src/Common/libzip/zip_file_error_clear.c
@@ -1,6 +1,6 @@
/*
zip_file_error_clear.c -- clear zip file error
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_file_error_get.c b/src/Common/libzip/zip_file_error_get.c
index d7e0191..1ed68df 100644
--- a/src/Common/libzip/zip_file_error_get.c
+++ b/src/Common/libzip/zip_file_error_get.c
@@ -1,6 +1,6 @@
/*
zip_file_error_get.c -- get zip file error
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_file_get_comment.c b/src/Common/libzip/zip_file_get_comment.c
index 478f3d7..8f68141 100644
--- a/src/Common/libzip/zip_file_get_comment.c
+++ b/src/Common/libzip/zip_file_get_comment.c
@@ -1,6 +1,6 @@
/*
zip_file_get_comment.c -- get file comment
- Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_file_get_external_attributes.c b/src/Common/libzip/zip_file_get_external_attributes.c
index e3ede74..ebc2058 100644
--- a/src/Common/libzip/zip_file_get_external_attributes.c
+++ b/src/Common/libzip/zip_file_get_external_attributes.c
@@ -1,6 +1,6 @@
/*
zip_file_get_external_attributes.c -- get opsys/external attributes
- Copyright (C) 2013-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2013-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_file_get_offset.c b/src/Common/libzip/zip_file_get_offset.c
index 877c179..9ea8909 100644
--- a/src/Common/libzip/zip_file_get_offset.c
+++ b/src/Common/libzip/zip_file_get_offset.c
@@ -1,6 +1,6 @@
/*
zip_file_get_offset.c -- get offset of file data in archive.
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_file_rename.c b/src/Common/libzip/zip_file_rename.c
index 1eb7fac..7ca428c 100644
--- a/src/Common/libzip/zip_file_rename.c
+++ b/src/Common/libzip/zip_file_rename.c
@@ -1,6 +1,6 @@
/*
zip_file_rename.c -- rename file in zip archive
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_file_replace.c b/src/Common/libzip/zip_file_replace.c
index e42f5cd..87401f4 100644
--- a/src/Common/libzip/zip_file_replace.c
+++ b/src/Common/libzip/zip_file_replace.c
@@ -1,6 +1,6 @@
/*
zip_file_replace.c -- replace file via callback function
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_file_set_comment.c b/src/Common/libzip/zip_file_set_comment.c
index 964486b..c309db8 100644
--- a/src/Common/libzip/zip_file_set_comment.c
+++ b/src/Common/libzip/zip_file_set_comment.c
@@ -1,6 +1,6 @@
/*
zip_file_set_comment.c -- set comment for file in archive
- Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_file_set_external_attributes.c b/src/Common/libzip/zip_file_set_external_attributes.c
index cd46e88..bb2ea61 100644
--- a/src/Common/libzip/zip_file_set_external_attributes.c
+++ b/src/Common/libzip/zip_file_set_external_attributes.c
@@ -1,6 +1,6 @@
/*
zip_file_set_external_attributes.c -- set external attributes for entry
- Copyright (C) 2013-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2013-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_file_set_mtime.c b/src/Common/libzip/zip_file_set_mtime.c
index 15316d3..838548e 100644
--- a/src/Common/libzip/zip_file_set_mtime.c
+++ b/src/Common/libzip/zip_file_set_mtime.c
@@ -1,6 +1,6 @@
/*
zip_file_set_mtime.c -- set modification time of entry.
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2020 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -34,9 +34,15 @@
#include "zipint.h"
ZIP_EXTERN int
+zip_file_set_dostime(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16_t ddate, zip_flags_t flags) {
+ time_t mtime;
+ mtime = _zip_d2u_time(dtime, ddate);
+ return zip_file_set_mtime(za, idx, mtime, flags);
+}
+
+ZIP_EXTERN int
zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) {
zip_entry_t *e;
- int changed;
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
@@ -48,27 +54,15 @@ zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags)
e = za->entry + idx;
- changed = e->orig == NULL || mtime != e->orig->last_mod;
-
- if (changed) {
- if (e->changes == NULL) {
- if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- return -1;
- }
- }
- e->changes->last_mod = mtime;
- e->changes->changed |= ZIP_DIRENT_LAST_MOD;
- }
- else {
- if (e->changes) {
- e->changes->changed &= ~ZIP_DIRENT_LAST_MOD;
- if (e->changes->changed == 0) {
- _zip_dirent_free(e->changes);
- e->changes = NULL;
- }
+ if (e->changes == NULL) {
+ if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
+ zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ return -1;
}
}
+ e->changes->last_mod = mtime;
+ e->changes->changed |= ZIP_DIRENT_LAST_MOD;
+
return 0;
}
diff --git a/src/Common/libzip/zip_file_strerror.c b/src/Common/libzip/zip_file_strerror.c
index fd4008a..1fa7fff 100644
--- a/src/Common/libzip/zip_file_strerror.c
+++ b/src/Common/libzip/zip_file_strerror.c
@@ -1,6 +1,6 @@
/*
zip_file_sterror.c -- get string representation of zip file error
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_filerange_crc.c b/src/Common/libzip/zip_filerange_crc.c
index 6c4be27..b887363 100644
--- a/src/Common/libzip/zip_filerange_crc.c
+++ b/src/Common/libzip/zip_filerange_crc.c
@@ -1,6 +1,6 @@
/*
zip_filerange_crc.c -- compute CRC32 for a range of a file
- Copyright (C) 2008-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -39,7 +39,8 @@
int
_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error) {
- Bytef buf[BUFSIZE];
+ DEFINE_BYTE_ARRAY(buf, BUFSIZE);
+
zip_int64_t n;
*crcp = crc32(0L, Z_NULL, 0);
@@ -54,14 +55,21 @@ _zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLon
return -1;
}
+ if (!byte_array_init(buf, BUFSIZE)) {
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return -1;
+ }
+
while (len > 0) {
n = (zip_int64_t)(len > BUFSIZE ? BUFSIZE : len);
if ((n = zip_source_read(src, buf, (zip_uint64_t)n)) < 0) {
_zip_error_set_from_source(error, src);
+ byte_array_fini(buf);
return -1;
}
if (n == 0) {
zip_error_set(error, ZIP_ER_EOF, 0);
+ byte_array_fini(buf);
return -1;
}
@@ -70,5 +78,7 @@ _zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLon
len -= (zip_uint64_t)n;
}
+ byte_array_fini(buf);
+
return 0;
}
diff --git a/src/Common/libzip/zip_fopen.c b/src/Common/libzip/zip_fopen.c
index cb45cc2..4f1a051 100644
--- a/src/Common/libzip/zip_fopen.c
+++ b/src/Common/libzip/zip_fopen.c
@@ -1,6 +1,6 @@
/*
zip_fopen.c -- open file in zip archive for reading
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_fopen_encrypted.c b/src/Common/libzip/zip_fopen_encrypted.c
index abcf6ac..9e9b13e 100644
--- a/src/Common/libzip/zip_fopen_encrypted.c
+++ b/src/Common/libzip/zip_fopen_encrypted.c
@@ -1,6 +1,6 @@
/*
zip_fopen_encrypted.c -- open file for reading with password
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_fopen_index.c b/src/Common/libzip/zip_fopen_index.c
index 7dcf1f7..ffca281 100644
--- a/src/Common/libzip/zip_fopen_index.c
+++ b/src/Common/libzip/zip_fopen_index.c
@@ -1,6 +1,6 @@
/*
zip_fopen_index.c -- open file in zip archive for reading by index
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_fopen_index_encrypted.c b/src/Common/libzip/zip_fopen_index_encrypted.c
index 6b32008..6712c32 100644
--- a/src/Common/libzip/zip_fopen_index_encrypted.c
+++ b/src/Common/libzip/zip_fopen_index_encrypted.c
@@ -1,6 +1,6 @@
/*
zip_fopen_index_encrypted.c -- open file for reading by index w/ password
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_fread.c b/src/Common/libzip/zip_fread.c
index be46cf0..646d712 100644
--- a/src/Common/libzip/zip_fread.c
+++ b/src/Common/libzip/zip_fread.c
@@ -1,6 +1,6 @@
/*
zip_fread.c -- read from file
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_get_archive_comment.c b/src/Common/libzip/zip_get_archive_comment.c
index a3d5a19..953c6f4 100644
--- a/src/Common/libzip/zip_get_archive_comment.c
+++ b/src/Common/libzip/zip_get_archive_comment.c
@@ -1,6 +1,6 @@
/*
zip_get_archive_comment.c -- get archive comment
- Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_get_archive_flag.c b/src/Common/libzip/zip_get_archive_flag.c
index 67fe4f8..fa4dd50 100644
--- a/src/Common/libzip/zip_get_archive_flag.c
+++ b/src/Common/libzip/zip_get_archive_flag.c
@@ -1,6 +1,6 @@
/*
zip_get_archive_flag.c -- get archive global flag
- Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_get_encryption_implementation.c b/src/Common/libzip/zip_get_encryption_implementation.c
index ba459d4..c9d52ad 100644
--- a/src/Common/libzip/zip_get_encryption_implementation.c
+++ b/src/Common/libzip/zip_get_encryption_implementation.c
@@ -1,6 +1,6 @@
/*
zip_get_encryption_implementation.c -- get encryption implementation
- Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_get_file_comment.c b/src/Common/libzip/zip_get_file_comment.c
index 44e5917..f800686 100644
--- a/src/Common/libzip/zip_get_file_comment.c
+++ b/src/Common/libzip/zip_get_file_comment.c
@@ -1,6 +1,6 @@
/*
zip_get_file_comment.c -- get file comment
- Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_get_name.c b/src/Common/libzip/zip_get_name.c
index d42f14a..4344209 100644
--- a/src/Common/libzip/zip_get_name.c
+++ b/src/Common/libzip/zip_get_name.c
@@ -1,6 +1,6 @@
/*
zip_get_name.c -- get filename for a file in zip file
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_get_num_entries.c b/src/Common/libzip/zip_get_num_entries.c
index 78f30dc..410d26e 100644
--- a/src/Common/libzip/zip_get_num_entries.c
+++ b/src/Common/libzip/zip_get_num_entries.c
@@ -1,6 +1,6 @@
/*
zip_get_num_entries.c -- get number of entries in archive
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_get_num_files.c b/src/Common/libzip/zip_get_num_files.c
index 3ccf400..4895eaa 100644
--- a/src/Common/libzip/zip_get_num_files.c
+++ b/src/Common/libzip/zip_get_num_files.c
@@ -1,6 +1,6 @@
/*
zip_get_num_files.c -- get number of files in archive
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_hash.c b/src/Common/libzip/zip_hash.c
index 0d9e996..3206dbf 100644
--- a/src/Common/libzip/zip_hash.c
+++ b/src/Common/libzip/zip_hash.c
@@ -1,6 +1,6 @@
/*
zip_hash.c -- hash table string -> uint64
- Copyright (C) 2015-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_io_util.c b/src/Common/libzip/zip_io_util.c
index 77be8f0..dd07cbb 100644
--- a/src/Common/libzip/zip_io_util.c
+++ b/src/Common/libzip/zip_io_util.c
@@ -1,6 +1,6 @@
/*
zip_io_util.c -- I/O helper functions
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_memdup.c b/src/Common/libzip/zip_memdup.c
index 9d7949d..05fcb7b 100644
--- a/src/Common/libzip/zip_memdup.c
+++ b/src/Common/libzip/zip_memdup.c
@@ -1,6 +1,6 @@
/*
zip_memdup.c -- internal zip function, "strdup" with len
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_name_locate.c b/src/Common/libzip/zip_name_locate.c
index 6713cab..f7318ec 100644
--- a/src/Common/libzip/zip_name_locate.c
+++ b/src/Common/libzip/zip_name_locate.c
@@ -1,6 +1,6 @@
/*
zip_name_locate.c -- get index by name
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_new.c b/src/Common/libzip/zip_new.c
index 19155f4..4f58ecc 100644
--- a/src/Common/libzip/zip_new.c
+++ b/src/Common/libzip/zip_new.c
@@ -1,6 +1,6 @@
/*
zip_new.c -- create and init struct zip
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_open.c b/src/Common/libzip/zip_open.c
index 1886c9d..4e29c5b 100644
--- a/src/Common/libzip/zip_open.c
+++ b/src/Common/libzip/zip_open.c
@@ -1,6 +1,6 @@
/*
zip_open.c -- open zip archive by name
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -43,8 +43,7 @@
typedef enum {
EXISTS_ERROR = -1,
EXISTS_NOT = 0,
- EXISTS_EMPTY,
- EXISTS_NONEMPTY,
+ EXISTS_OK
} exists_t;
static zip_t *_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error);
static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error);
@@ -174,20 +173,16 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
}
len = st.size;
- /* treat empty files as empty archives */
- if (len == 0) {
- if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
- zip_source_free(src);
- return NULL;
- }
-
- return za;
- }
if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
return NULL;
}
+ /* treat empty files as empty archives */
+ if (len == 0 && zip_source_accept_empty(src)) {
+ return za;
+ }
+
if ((cdir = _zip_find_central_dir(za, len)) == NULL) {
_zip_error_copy(error, &za->error);
/* keep src so discard does not get rid of it */
@@ -541,7 +536,7 @@ _zip_file_exists(zip_source_t *src, zip_error_t *error) {
return EXISTS_ERROR;
}
- return (st.valid & ZIP_STAT_SIZE) && st.size == 0 ? EXISTS_EMPTY : EXISTS_NONEMPTY;
+ return EXISTS_OK;
}
@@ -726,16 +721,19 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
eocd_disk = _zip_buffer_get_16(buffer);
eocd_offset = _zip_buffer_get_64(buffer);
- if (eocd_offset > ZIP_INT64_MAX || eocd_offset + EOCD64LEN < eocd_offset) {
+ /* valid seek value for start of EOCD */
+ if (eocd_offset > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return NULL;
}
+ /* does EOCD fit before EOCD locator? */
if (eocd_offset + EOCD64LEN > eocdloc_offset + buf_offset) {
zip_error_set(error, ZIP_ER_INCONS, 0);
return NULL;
}
+ /* make sure current position of buffer is beginning of EOCD */
if (eocd_offset >= buf_offset && eocd_offset + EOCD64LEN <= buf_offset + _zip_buffer_size(buffer)) {
_zip_buffer_set_offset(buffer, eocd_offset - buf_offset);
free_buffer = false;
@@ -759,8 +757,10 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
return NULL;
}
+ /* size of EOCD */
size = _zip_buffer_get_64(buffer);
+ /* is there a hole between EOCD and EOCD locator, or do they overlap? */
if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) {
zip_error_set(error, ZIP_ER_INCONS, 0);
if (free_buffer) {
@@ -812,6 +812,7 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
size = _zip_buffer_get_64(buffer);
offset = _zip_buffer_get_64(buffer);
+ /* did we read past the end of the buffer? */
if (!_zip_buffer_ok(buffer)) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
if (free_buffer) {
@@ -838,6 +839,11 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
return NULL;
}
+ if (nentry > size / CDENTRYSIZE) {
+ zip_error_set(error, ZIP_ER_INCONS, 0);
+ return NULL;
+ }
+
if ((cd = _zip_cdir_new(nentry, error)) == NULL)
return NULL;
diff --git a/src/Common/libzip/zip_progress.c b/src/Common/libzip/zip_progress.c
index 46c8bb8..d48ae56 100644
--- a/src/Common/libzip/zip_progress.c
+++ b/src/Common/libzip/zip_progress.c
@@ -1,6 +1,6 @@
/*
zip_progress.c -- progress reporting
- Copyright (C) 2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2017-2020 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -40,10 +40,14 @@
struct zip_progress {
zip_t *za;
- zip_progress_callback callback;
- void (*ud_free)(void *);
- void *ud;
+ zip_progress_callback callback_progress;
+ void (*ud_progress_free)(void *);
+ void *ud_progress;
+
+ zip_cancel_callback callback_cancel;
+ void (*ud_cancel_free)(void *);
+ void *ud_cancel;
double precision;
@@ -54,6 +58,11 @@ struct zip_progress {
double end; /* end of sub-progress section */
};
+static void _zip_progress_free_cancel_callback(zip_progress_t *progress);
+static void _zip_progress_free_progress_callback(zip_progress_t *progress);
+static zip_progress_t *_zip_progress_new(zip_t *za);
+static void _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback callback, void (*ud_free)(void *), void *ud);
+static void _zip_progress_set_progress_callback(zip_progress_t *progress, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud);
void
_zip_progress_end(zip_progress_t *progress) {
@@ -67,16 +76,15 @@ _zip_progress_free(zip_progress_t *progress) {
return;
}
- if (progress->ud_free) {
- progress->ud_free(progress->ud);
- }
+ _zip_progress_free_progress_callback(progress);
+ _zip_progress_free_cancel_callback(progress);
free(progress);
}
-zip_progress_t *
-_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
+static zip_progress_t *
+_zip_progress_new(zip_t *za) {
zip_progress_t *progress = (zip_progress_t *)malloc(sizeof(*progress));
if (progress == NULL) {
@@ -85,52 +93,117 @@ _zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, v
}
progress->za = za;
- progress->callback = callback;
- progress->ud_free = ud_free;
- progress->ud = ud;
- progress->precision = precision;
+
+ progress->callback_progress = NULL;
+ progress->ud_progress_free = NULL;
+ progress->ud_progress = NULL;
+ progress->precision = 0.0;
+
+ progress->callback_cancel = NULL;
+ progress->ud_cancel_free = NULL;
+ progress->ud_cancel = NULL;
return progress;
}
+static void
+_zip_progress_free_progress_callback(zip_progress_t *progress) {
+ if (progress->ud_progress_free) {
+ progress->ud_progress_free(progress->ud_progress);
+ }
+
+ progress->callback_progress = NULL;
+ progress->ud_progress = NULL;
+ progress->ud_progress_free = NULL;
+}
+
+static void
+_zip_progress_free_cancel_callback(zip_progress_t *progress) {
+ if (progress->ud_cancel_free) {
+ progress->ud_cancel_free(progress->ud_cancel);
+ }
+
+ progress->callback_cancel = NULL;
+ progress->ud_cancel = NULL;
+ progress->ud_cancel_free = NULL;
+}
+
+static void
+_zip_progress_set_progress_callback(zip_progress_t *progress, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
+ _zip_progress_free_progress_callback(progress);
+
+ progress->callback_progress = callback;
+ progress->ud_progress_free = ud_free;
+ progress->ud_progress = ud;
+ progress->precision = precision;
+}
void
+_zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) {
+ _zip_progress_free_cancel_callback(progress);
+
+ progress->callback_cancel = callback;
+ progress->ud_cancel_free = ud_free;
+ progress->ud_cancel = ud;
+}
+
+int
_zip_progress_start(zip_progress_t *progress) {
if (progress == NULL) {
- return;
+ return 0;
+ }
+
+ if (progress->callback_progress != NULL) {
+ progress->last_update = 0.0;
+ progress->callback_progress(progress->za, 0.0, progress->ud_progress);
+ }
+
+ if (progress->callback_cancel != NULL) {
+ if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
+ return -1;
+ }
}
- progress->last_update = 0.0;
- progress->callback(progress->za, 0.0, progress->ud);
+ return 0;
}
-void
+int
_zip_progress_subrange(zip_progress_t *progress, double start, double end) {
if (progress == NULL) {
- return;
+ return 0;
}
progress->start = start;
progress->end = end;
- _zip_progress_update(progress, 0.0);
+ return _zip_progress_update(progress, 0.0);
}
-void
+int
_zip_progress_update(zip_progress_t *progress, double sub_current) {
double current;
if (progress == NULL) {
- return;
+ return 0;
}
- current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
+ if (progress->callback_progress != NULL) {
+ current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
- if (current - progress->last_update > progress->precision) {
- progress->callback(progress->za, current, progress->ud);
- progress->last_update = current;
+ if (current - progress->last_update > progress->precision) {
+ progress->callback_progress(progress->za, current, progress->ud_progress);
+ progress->last_update = current;
+ }
}
+
+ if (progress->callback_cancel != NULL) {
+ if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
+ return -1;
+ }
+ }
+
+ return 0;
}
@@ -139,13 +212,54 @@ zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progr
zip_progress_t *progress = NULL;
if (callback != NULL) {
- if ((progress = _zip_progress_new(za, precision, callback, ud_free, ud)) == NULL) {
- return -1;
+ if (za->progress == NULL) {
+ if ((za->progress = _zip_progress_new(za)) == NULL) {
+ return -1;
+ }
}
+
+ _zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud);
}
+ else {
+ if (za->progress != NULL) {
+ if (za->progress->callback_cancel == NULL) {
+ _zip_progress_free(za->progress);
+ za->progress = NULL;
+ }
+ else {
+ _zip_progress_free_progress_callback(za->progress);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+ZIP_EXTERN int
+zip_register_cancel_callback_with_state(zip_t *za, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) {
+ zip_progress_t *progress = NULL;
+
+ if (callback != NULL) {
+ if (za->progress == NULL) {
+ if ((za->progress = _zip_progress_new(za)) == NULL) {
+ return -1;
+ }
+ }
- _zip_progress_free(za->progress);
- za->progress = progress;
+ _zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud);
+ }
+ else {
+ if (za->progress != NULL) {
+ if (za->progress->callback_progress == NULL) {
+ _zip_progress_free(za->progress);
+ za->progress = NULL;
+ }
+ else {
+ _zip_progress_free_cancel_callback(za->progress);
+ }
+ }
+ }
return 0;
}
diff --git a/src/Common/libzip/zip_rename.c b/src/Common/libzip/zip_rename.c
index 0cc81ed..e5f1682 100644
--- a/src/Common/libzip/zip_rename.c
+++ b/src/Common/libzip/zip_rename.c
@@ -1,6 +1,6 @@
/*
zip_rename.c -- rename file in zip archive
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_replace.c b/src/Common/libzip/zip_replace.c
index 34b922e..30a2eb1 100644
--- a/src/Common/libzip/zip_replace.c
+++ b/src/Common/libzip/zip_replace.c
@@ -1,6 +1,6 @@
/*
zip_replace.c -- replace file via callback function
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_set_archive_comment.c b/src/Common/libzip/zip_set_archive_comment.c
index 221fde5..3f050b3 100644
--- a/src/Common/libzip/zip_set_archive_comment.c
+++ b/src/Common/libzip/zip_set_archive_comment.c
@@ -1,6 +1,6 @@
/*
zip_set_archive_comment.c -- set archive comment
- Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_set_archive_flag.c b/src/Common/libzip/zip_set_archive_flag.c
index 6fb1131..e0d5502 100644
--- a/src/Common/libzip/zip_set_archive_flag.c
+++ b/src/Common/libzip/zip_set_archive_flag.c
@@ -1,6 +1,6 @@
/*
zip_get_archive_flag.c -- set archive global flag
- Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_set_default_password.c b/src/Common/libzip/zip_set_default_password.c
index 33c1754..41c7c51 100644
--- a/src/Common/libzip/zip_set_default_password.c
+++ b/src/Common/libzip/zip_set_default_password.c
@@ -1,6 +1,6 @@
/*
zip_set_default_password.c -- set default password for decryption
- Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_set_file_comment.c b/src/Common/libzip/zip_set_file_comment.c
index 93594f0..1fa01ae 100644
--- a/src/Common/libzip/zip_set_file_comment.c
+++ b/src/Common/libzip/zip_set_file_comment.c
@@ -1,6 +1,6 @@
/*
zip_set_file_comment.c -- set comment for file in archive
- Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_set_file_compression.c b/src/Common/libzip/zip_set_file_compression.c
index 6de2d40..927fbb7 100644
--- a/src/Common/libzip/zip_set_file_compression.c
+++ b/src/Common/libzip/zip_set_file_compression.c
@@ -1,6 +1,6 @@
/*
zip_set_file_compression.c -- set compression for file in archive
- Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_set_name.c b/src/Common/libzip/zip_set_name.c
index 33fb4bc..43c772e 100644
--- a/src/Common/libzip/zip_set_name.c
+++ b/src/Common/libzip/zip_set_name.c
@@ -1,6 +1,6 @@
/*
zip_set_name.c -- rename helper function
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_accept_empty.c b/src/Common/libzip/zip_source_accept_empty.c
new file mode 100644
index 0000000..e6d5151
--- /dev/null
+++ b/src/Common/libzip/zip_source_accept_empty.c
@@ -0,0 +1,52 @@
+/*
+ zip_source_accept_empty.c -- if empty source is a valid archive
+ Copyright (C) 2019 Dieter Baron and Thomas Klausner
+
+ This file is part of libzip, a library to manipulate ZIP archives.
+ The authors can be contacted at <libzip@nih.at>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "zipint.h"
+
+
+bool
+zip_source_accept_empty(zip_source_t *src) {
+ int ret;
+
+ if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY)) == 0) {
+ if (ZIP_SOURCE_IS_LAYERED(src)) {
+ return zip_source_accept_empty(src->src);
+ }
+ return true;
+ }
+
+ ret = (int)_zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY);
+
+ return ret != 0;
+}
diff --git a/src/Common/libzip/zip_source_begin_write.c b/src/Common/libzip/zip_source_begin_write.c
index 0b010df..432c2c1 100644
--- a/src/Common/libzip/zip_source_begin_write.c
+++ b/src/Common/libzip/zip_source_begin_write.c
@@ -1,6 +1,6 @@
/*
zip_source_begin_write.c -- start a new file for writing
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_begin_write_cloning.c b/src/Common/libzip/zip_source_begin_write_cloning.c
index 8c4cf71..41b4c73 100644
--- a/src/Common/libzip/zip_source_begin_write_cloning.c
+++ b/src/Common/libzip/zip_source_begin_write_cloning.c
@@ -1,6 +1,6 @@
/*
zip_source_begin_write_cloning.c -- clone part of file for writing
- Copyright (C) 2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_buffer.c b/src/Common/libzip/zip_source_buffer.c
index d2bc8ad..0685fb3 100644
--- a/src/Common/libzip/zip_source_buffer.c
+++ b/src/Common/libzip/zip_source_buffer.c
@@ -1,6 +1,6 @@
/*
zip_source_buffer.c -- create zip data source from buffer
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -93,9 +93,13 @@ ZIP_EXTERN zip_source_t *
zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) {
zip_buffer_fragment_t fragment;
- if (data == NULL && len > 0) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
+ if (data == NULL) {
+ if (len > 0) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return NULL;
+ }
+
+ return zip_source_buffer_fragment_create(NULL, 0, freep, error);
}
fragment.data = (zip_uint8_t *)data;
@@ -389,8 +393,8 @@ buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *erro
}
if ((fragments = realloc(buffer->fragments, sizeof(buffer->fragments[0]) * capacity)) == NULL) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return false;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return false;
}
buffer->fragments = fragments;
if ((offsets = realloc(buffer->fragment_offsets, sizeof(buffer->fragment_offsets[0]) * (capacity + 1))) == NULL) {
@@ -457,7 +461,7 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int
}
buffer->nfragments = j;
buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments;
- buffer->fragment_offsets[nfragments] = offset;
+ buffer->fragment_offsets[buffer->nfragments] = offset;
buffer->size = offset;
}
diff --git a/src/Common/libzip/zip_source_call.c b/src/Common/libzip/zip_source_call.c
index ec54b92..e7c2954 100644
--- a/src/Common/libzip/zip_source_call.c
+++ b/src/Common/libzip/zip_source_call.c
@@ -1,6 +1,6 @@
/*
zip_source_call.c -- invoke callback command on zip_source
- Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_close.c b/src/Common/libzip/zip_source_close.c
index cbc3bea..ab7898c 100644
--- a/src/Common/libzip/zip_source_close.c
+++ b/src/Common/libzip/zip_source_close.c
@@ -1,6 +1,6 @@
/*
zip_source_close.c -- close zip_source (stop reading)
- Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_commit_write.c b/src/Common/libzip/zip_source_commit_write.c
index 26c3dd7..d1254bf 100644
--- a/src/Common/libzip/zip_source_commit_write.c
+++ b/src/Common/libzip/zip_source_commit_write.c
@@ -1,6 +1,6 @@
/*
zip_source_commit_write.c -- commit changes to file
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_compress.c b/src/Common/libzip/zip_source_compress.c
index a1ac3e0..59b1212 100644
--- a/src/Common/libzip/zip_source_compress.c
+++ b/src/Common/libzip/zip_source_compress.c
@@ -1,6 +1,6 @@
/*
zip_source_compress.c -- (de)compression routines
- Copyright (C) 2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -67,6 +67,16 @@ static struct implementation implementations[] = {
#if defined(HAVE_LIBBZ2)
{ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress},
#endif
+#if defined(HAVE_LIBLZMA)
+/* Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2
+ archives made this way - and vice versa.
+
+ {ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
+ {ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
+*/
+ {ZIP_CM_XZ, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
+#endif
+
};
static size_t implementations_size = sizeof(implementations) / sizeof(implementations[0]);
diff --git a/src/Common/libzip/zip_source_crc.c b/src/Common/libzip/zip_source_crc.c
index 8797dfe..56572c0 100644
--- a/src/Common/libzip/zip_source_crc.c
+++ b/src/Common/libzip/zip_source_crc.c
@@ -1,6 +1,6 @@
/*
zip_source_crc.c -- pass-through source that calculates CRC32 and size
- Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -148,7 +148,6 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
st->comp_method = ZIP_CM_STORE;
st->encryption_method = ZIP_EM_NONE;
st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
- ;
}
return 0;
}
diff --git a/src/Common/libzip/zip_source_error.c b/src/Common/libzip/zip_source_error.c
index 5145169..2257f71 100644
--- a/src/Common/libzip/zip_source_error.c
+++ b/src/Common/libzip/zip_source_error.c
@@ -1,6 +1,6 @@
/*
zip_source_error.c -- get last error from zip_source
- Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_file.c b/src/Common/libzip/zip_source_file.c
index 77376f4..3fff4e3 100644
--- a/src/Common/libzip/zip_source_file.c
+++ b/src/Common/libzip/zip_source_file.c
@@ -1,6 +1,6 @@
/*
zip_source_file.c -- create data source from file
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_filep.c b/src/Common/libzip/zip_source_filep.c
index 9fc9a01..30e5991 100644
--- a/src/Common/libzip/zip_source_filep.c
+++ b/src/Common/libzip/zip_source_filep.c
@@ -1,6 +1,6 @@
/*
zip_source_filep.c -- create data source from FILE *
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -31,9 +31,11 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include <sys/stat.h>
#include "zipint.h"
@@ -53,28 +55,6 @@
#define CAN_CLONE
#endif
-#ifdef _WIN32
-/* WIN32 needs <fcntl.h> for _O_BINARY */
-#include <fcntl.h>
-#endif
-
-/* Windows sys/types.h does not provide these */
-#ifndef S_ISREG
-#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
-#endif
-#if defined(S_IXUSR) && defined(S_IRWXG) && defined(S_IRWXO)
-#define _SAFE_MASK (S_IXUSR | S_IRWXG | S_IRWXO)
-#elif defined(_S_IWRITE)
-#define _SAFE_MASK (_S_IWRITE)
-#else
-#error do not know safe values for umask, please report this
-#endif
-
-#ifdef _MSC_VER
-/* MSVC doesn't have mode_t */
-typedef int mode_t;
-#endif
-
struct read_file {
zip_error_t error; /* last error information */
zip_int64_t supports;
@@ -98,6 +78,7 @@ static int create_temp_output(struct read_file *ctx);
#ifdef CAN_CLONE
static zip_int64_t create_temp_output_cloning(struct read_file *ctx, zip_uint64_t offset);
#endif
+static FILE *_zip_fopen(const char *name, bool writeable);
static int _zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error);
static int _zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error);
@@ -224,6 +205,7 @@ _zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int
}
}
+ ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY);
#ifdef CAN_CLONE
if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) {
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING);
@@ -244,23 +226,29 @@ static int
create_temp_output(struct read_file *ctx) {
char *temp;
int tfd;
- mode_t mask;
+ int mode;
FILE *tfp;
+ struct stat st;
if ((temp = (char *)malloc(strlen(ctx->fname) + 8)) == NULL) {
zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
return -1;
}
+
+ if (stat(ctx->fname, &st) == 0) {
+ mode = st.st_mode;
+ }
+ else {
+ mode = -1;
+ }
+
sprintf(temp, "%s.XXXXXX", ctx->fname);
- mask = umask(_SAFE_MASK);
- if ((tfd = mkstemp(temp)) == -1) {
+ if ((tfd = _zip_mkstempm(temp, mode)) == -1) {
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
- umask(mask);
free(temp);
return -1;
}
- umask(mask);
if ((tfp = fdopen(tfd, "r+b")) == NULL) {
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
@@ -270,14 +258,6 @@ create_temp_output(struct read_file *ctx) {
return -1;
}
-#ifdef _WIN32
- /*
- According to Pierre Joye, Windows in some environments per
- default creates text files, so force binary mode.
- */
- _setmode(_fileno(tfp), _O_BINARY);
-#endif
-
ctx->fout = tfp;
ctx->tmpname = temp;
@@ -315,7 +295,7 @@ zip_int64_t static create_temp_output_cloning(struct read_file *ctx, zip_uint64_
free(temp);
return -1;
}
- if ((tfp = fopen(temp, "r+b")) == NULL) {
+ if ((tfp = _zip_fopen(temp, true)) == NULL) {
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
(void)remove(temp);
free(temp);
@@ -395,12 +375,19 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
buf = (char *)data;
switch (cmd) {
+ case ZIP_SOURCE_ACCEPT_EMPTY:
+ return 0;
+
case ZIP_SOURCE_BEGIN_WRITE:
+#ifdef _WIN32
+ return -1;
+#else
if (ctx->fname == NULL) {
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
return create_temp_output(ctx);
+#endif
#ifdef CAN_CLONE
case ZIP_SOURCE_BEGIN_WRITE_CLONING:
@@ -411,9 +398,14 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
return create_temp_output_cloning(ctx, len);
#endif
- case ZIP_SOURCE_COMMIT_WRITE: {
- mode_t mask;
+ case ZIP_SOURCE_CLOSE:
+ if (ctx->fname) {
+ fclose(ctx->f);
+ ctx->f = NULL;
+ }
+ return 0;
+ case ZIP_SOURCE_COMMIT_WRITE: {
if (fclose(ctx->fout) < 0) {
ctx->fout = NULL;
zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
@@ -423,22 +415,11 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
zip_error_set(&ctx->error, ZIP_ER_RENAME, errno);
return -1;
}
- mask = umask(022);
- umask(mask);
- /* not much we can do if chmod fails except make the whole commit fail */
- (void)chmod(ctx->fname, 0666 & ~mask);
free(ctx->tmpname);
ctx->tmpname = NULL;
return 0;
}
- case ZIP_SOURCE_CLOSE:
- if (ctx->fname) {
- fclose(ctx->f);
- ctx->f = NULL;
- }
- return 0;
-
case ZIP_SOURCE_ERROR:
return zip_error_to_data(&ctx->error, data, len);
@@ -452,7 +433,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
case ZIP_SOURCE_OPEN:
if (ctx->fname) {
- if ((ctx->f = fopen(ctx->fname, "rb")) == NULL) {
+ if ((ctx->f = _zip_fopen(ctx->fname, false)) == NULL) {
zip_error_set(&ctx->error, ZIP_ER_OPEN, errno);
return -1;
}
@@ -649,3 +630,34 @@ _zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error) {
}
return 0;
}
+
+
+/*
+ * fopen replacement that sets the close-on-exec flag
+ * some implementations support an fopen 'e' flag for that,
+ * but e.g. macOS doesn't.
+ */
+static FILE *
+_zip_fopen(const char *name, bool writeable)
+{
+ int fd;
+ int flags;
+ FILE *fp;
+
+ flags = O_CLOEXEC;
+ if (writeable) {
+ flags |= O_RDWR;
+ }
+ else {
+ flags |= O_RDONLY;
+ }
+
+ /* mode argument needed on Windows */
+ if ((fd = open(name, flags, 0666)) < 0) {
+ return NULL;
+ }
+ if ((fp = fdopen(fd, writeable ? "r+b" : "rb")) == NULL) {
+ return NULL;
+ }
+ return fp;
+}
diff --git a/src/Common/libzip/zip_source_free.c b/src/Common/libzip/zip_source_free.c
index 7cb3525..2f10ef8 100644
--- a/src/Common/libzip/zip_source_free.c
+++ b/src/Common/libzip/zip_source_free.c
@@ -1,6 +1,6 @@
/*
zip_source_free.c -- free zip data source
- Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_function.c b/src/Common/libzip/zip_source_function.c
index 56eb1c5..d5c1b5b 100644
--- a/src/Common/libzip/zip_source_function.c
+++ b/src/Common/libzip/zip_source_function.c
@@ -1,6 +1,6 @@
/*
zip_source_function.c -- create zip data source from callback function
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_get_compression_flags.c b/src/Common/libzip/zip_source_get_compression_flags.c
index e33e43b..7e04bed 100644
--- a/src/Common/libzip/zip_source_get_compression_flags.c
+++ b/src/Common/libzip/zip_source_get_compression_flags.c
@@ -1,6 +1,6 @@
/*
zip_source_get_compression_flags.c -- get compression flags for entry
- Copyright (C) 2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_is_deleted.c b/src/Common/libzip/zip_source_is_deleted.c
index 1e5d343..edd10ca 100644
--- a/src/Common/libzip/zip_source_is_deleted.c
+++ b/src/Common/libzip/zip_source_is_deleted.c
@@ -1,6 +1,6 @@
/*
zip_source_is_deleted.c -- was archive was removed?
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_layered.c b/src/Common/libzip/zip_source_layered.c
index 5e95bc1..d02bc85 100644
--- a/src/Common/libzip/zip_source_layered.c
+++ b/src/Common/libzip/zip_source_layered.c
@@ -1,6 +1,6 @@
/*
zip_source_layered.c -- create layered source
- Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_open.c b/src/Common/libzip/zip_source_open.c
index 187001c..414c677 100644
--- a/src/Common/libzip/zip_source_open.c
+++ b/src/Common/libzip/zip_source_open.c
@@ -1,6 +1,6 @@
/*
zip_source_open.c -- open zip_source (prepare for reading)
- Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_pkware.c b/src/Common/libzip/zip_source_pkware.c
index b466da4..1b59d7a 100644
--- a/src/Common/libzip/zip_source_pkware.c
+++ b/src/Common/libzip/zip_source_pkware.c
@@ -1,6 +1,6 @@
/*
zip_source_pkware.c -- Traditional PKWARE de/encryption routines
- Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_read.c b/src/Common/libzip/zip_source_read.c
index 83514c6..33088cb 100644
--- a/src/Common/libzip/zip_source_read.c
+++ b/src/Common/libzip/zip_source_read.c
@@ -1,6 +1,6 @@
/*
zip_source_read.c -- read data from zip_source
- Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -57,7 +57,7 @@ zip_source_read(zip_source_t *src, void *data, zip_uint64_t len) {
}
if (len == 0) {
- return 0;
+ return 0;
}
bytes_read = 0;
diff --git a/src/Common/libzip/zip_source_remove.c b/src/Common/libzip/zip_source_remove.c
index 8e01e24..14eddb8 100644
--- a/src/Common/libzip/zip_source_remove.c
+++ b/src/Common/libzip/zip_source_remove.c
@@ -1,6 +1,6 @@
/*
zip_source_remove.c -- remove empty archive
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_rollback_write.c b/src/Common/libzip/zip_source_rollback_write.c
index bbccaf8..e8259bf 100644
--- a/src/Common/libzip/zip_source_rollback_write.c
+++ b/src/Common/libzip/zip_source_rollback_write.c
@@ -1,6 +1,6 @@
/*
zip_source_rollback_write.c -- discard changes
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_seek.c b/src/Common/libzip/zip_source_seek.c
index aed53b8..163daf1 100644
--- a/src/Common/libzip/zip_source_seek.c
+++ b/src/Common/libzip/zip_source_seek.c
@@ -1,6 +1,6 @@
/*
zip_source_seek.c -- seek to offset
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -50,7 +50,12 @@ zip_source_seek(zip_source_t *src, zip_int64_t offset, int whence) {
args.offset = offset;
args.whence = whence;
- return (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK) < 0 ? -1 : 0);
+ if (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK) < 0) {
+ return -1;
+ }
+
+ src->eof = 0;
+ return 0;
}
diff --git a/src/Common/libzip/zip_source_seek_write.c b/src/Common/libzip/zip_source_seek_write.c
index 4ecbee1..6b0aa78 100644
--- a/src/Common/libzip/zip_source_seek_write.c
+++ b/src/Common/libzip/zip_source_seek_write.c
@@ -1,6 +1,6 @@
/*
zip_source_seek_write.c -- seek to offset for writing
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_stat.c b/src/Common/libzip/zip_source_stat.c
index 987c862..3421d2c 100644
--- a/src/Common/libzip/zip_source_stat.c
+++ b/src/Common/libzip/zip_source_stat.c
@@ -1,6 +1,6 @@
/*
zip_source_stat.c -- get meta information from zip_source
- Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_supports.c b/src/Common/libzip/zip_source_supports.c
index a47f293..8471559 100644
--- a/src/Common/libzip/zip_source_supports.c
+++ b/src/Common/libzip/zip_source_supports.c
@@ -1,6 +1,6 @@
/*
zip_source_supports.c -- check for supported functions
- Copyright (C) 2014-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_tell.c b/src/Common/libzip/zip_source_tell.c
index ab418fa..772e252 100644
--- a/src/Common/libzip/zip_source_tell.c
+++ b/src/Common/libzip/zip_source_tell.c
@@ -1,6 +1,6 @@
/*
zip_source_tell.c -- report current offset
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_tell_write.c b/src/Common/libzip/zip_source_tell_write.c
index f7a8a3f..96ad7e2 100644
--- a/src/Common/libzip/zip_source_tell_write.c
+++ b/src/Common/libzip/zip_source_tell_write.c
@@ -1,6 +1,6 @@
/*
zip_source_tell_write.c -- report current offset for writing
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_win32a.c b/src/Common/libzip/zip_source_win32a.c
index 0780fa5..257fc6a 100644
--- a/src/Common/libzip/zip_source_win32a.c
+++ b/src/Common/libzip/zip_source_win32a.c
@@ -1,6 +1,6 @@
/*
zip_source_win32a.c -- create data source from Windows file (ANSI)
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -112,8 +112,18 @@ _win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32
static int
_win32_rename_temp_a(_zip_source_win32_read_file_t *ctx) {
+ DWORD attributes = GetFileAttributesA(ctx->tmpname);
+ if (INVALID_FILE_ATTRIBUTES == attributes)
+ return -1;
+
+ if (FILE_ATTRIBUTE_TEMPORARY & attributes) {
+ if (!SetFileAttributesA(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY))
+ return -1;
+ }
+
if (!MoveFileExA(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING))
return -1;
+
return 0;
}
diff --git a/src/Common/libzip/zip_source_win32handle.c b/src/Common/libzip/zip_source_win32handle.c
index 8cef919..8746cdd 100644
--- a/src/Common/libzip/zip_source_win32handle.c
+++ b/src/Common/libzip/zip_source_win32handle.c
@@ -1,6 +1,6 @@
/*
zip_source_win32file.c -- create data source from HANDLE (Win32)
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -127,6 +127,8 @@ _zip_source_win32_handle_or_name(const void *fname, HANDLE h, zip_uint64_t start
ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
}
+ ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY);
+
if ((zs = zip_source_function_create(_win32_read_file, ctx, error)) == NULL) {
free(ctx->fname);
free(ctx);
@@ -148,6 +150,9 @@ _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd
buf = (char *)data;
switch (cmd) {
+ case ZIP_SOURCE_ACCEPT_EMPTY:
+ return 0;
+
case ZIP_SOURCE_BEGIN_WRITE:
if (ctx->fname == NULL) {
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
@@ -261,7 +266,7 @@ _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd
switch (args->whence) {
case SEEK_SET:
- new_current = args->offset;
+ new_current = args->offset + ctx->start;
break;
case SEEK_END:
diff --git a/src/Common/libzip/zip_source_win32utf8.c b/src/Common/libzip/zip_source_win32utf8.c
index 1e279b0..083f5bc 100644
--- a/src/Common/libzip/zip_source_win32utf8.c
+++ b/src/Common/libzip/zip_source_win32utf8.c
@@ -1,6 +1,6 @@
/*
zip_source_win32utf8.c -- create data source from Windows file (UTF-8)
- Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_win32w.c b/src/Common/libzip/zip_source_win32w.c
index 5583bdf..cb8d64e 100644
--- a/src/Common/libzip/zip_source_win32w.c
+++ b/src/Common/libzip/zip_source_win32w.c
@@ -1,6 +1,6 @@
/*
zip_source_win32w.c -- create data source from Windows file (UTF-16)
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -136,8 +136,18 @@ _win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32
static int
_win32_rename_temp_w(_zip_source_win32_read_file_t *ctx) {
+ DWORD attributes = GetFileAttributesW(ctx->tmpname);
+ if (INVALID_FILE_ATTRIBUTES == attributes)
+ return -1;
+
+ if (FILE_ATTRIBUTE_TEMPORARY & attributes) {
+ if (!SetFileAttributesW(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY))
+ return -1;
+ }
+
if (!MoveFileExW(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING))
return -1;
+
return 0;
}
diff --git a/src/Common/libzip/zip_source_window.c b/src/Common/libzip/zip_source_window.c
index f4701a0..1276485 100644
--- a/src/Common/libzip/zip_source_window.c
+++ b/src/Common/libzip/zip_source_window.c
@@ -1,6 +1,6 @@
/*
zip_source_window.c -- return part of lower source
- Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -121,7 +121,6 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
struct window *ctx;
zip_int64_t ret;
zip_uint64_t n, i;
- char b[8192];
ctx = (struct window *)_ctx;
@@ -154,18 +153,30 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
}
if (!ctx->needs_seek) {
+ DEFINE_BYTE_ARRAY(b, BUFSIZE);
+
+ if (!byte_array_init(b, BUFSIZE)) {
+ zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
+ return -1;
+ }
+
for (n = 0; n < ctx->start; n += (zip_uint64_t)ret) {
- i = (ctx->start - n > sizeof(b) ? sizeof(b) : ctx->start - n);
+ i = (ctx->start - n > BUFSIZE ? BUFSIZE : ctx->start - n);
if ((ret = zip_source_read(src, b, i)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
+ byte_array_fini(b);
return -1;
}
if (ret == 0) {
zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
+ byte_array_fini(b);
return -1;
}
}
+
+ byte_array_fini(b);
}
+
ctx->offset = ctx->start;
return 0;
diff --git a/src/Common/libzip/zip_source_write.c b/src/Common/libzip/zip_source_write.c
index 1646e33..73fc3a3 100644
--- a/src/Common/libzip/zip_source_write.c
+++ b/src/Common/libzip/zip_source_write.c
@@ -1,6 +1,6 @@
/*
zip_source_write.c -- start a new file for writing
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_zip.c b/src/Common/libzip/zip_source_zip.c
index b3f1805..1f77aaa 100644
--- a/src/Common/libzip/zip_source_zip.c
+++ b/src/Common/libzip/zip_source_zip.c
@@ -1,6 +1,6 @@
/*
zip_source_zip.c -- create data source from zip file
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_source_zip_new.c b/src/Common/libzip/zip_source_zip_new.c
index a5cfee3..f36609b 100644
--- a/src/Common/libzip/zip_source_zip_new.c
+++ b/src/Common/libzip/zip_source_zip_new.c
@@ -1,6 +1,6 @@
/*
zip_source_zip_new.c -- prepare data structures for zip_fopen/zip_source_zip
- Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_stat.c b/src/Common/libzip/zip_stat.c
index 02cca37..341c6f7 100644
--- a/src/Common/libzip/zip_stat.c
+++ b/src/Common/libzip/zip_stat.c
@@ -1,6 +1,6 @@
/*
zip_stat.c -- get information about file by name
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_stat_index.c b/src/Common/libzip/zip_stat_index.c
index 109c118..71f8049 100644
--- a/src/Common/libzip/zip_stat_index.c
+++ b/src/Common/libzip/zip_stat_index.c
@@ -1,6 +1,6 @@
/*
zip_stat_index.c -- get information about file by index
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -48,10 +48,17 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st)
if ((flags & ZIP_FL_UNCHANGED) == 0 && ZIP_ENTRY_DATA_CHANGED(za->entry + index)) {
- if (zip_source_stat(za->entry[index].source, st) < 0) {
+ zip_entry_t *entry = za->entry+index;
+
+ if (zip_source_stat(entry->source, st) < 0) {
zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
return -1;
}
+
+ if (entry->changes->changed & ZIP_DIRENT_LAST_MOD) {
+ st->mtime = de->last_mod;
+ st->valid |= ZIP_STAT_MTIME;
+ }
}
else {
zip_stat_init(st);
diff --git a/src/Common/libzip/zip_stat_init.c b/src/Common/libzip/zip_stat_init.c
index 0be5138..6d0903d 100644
--- a/src/Common/libzip/zip_stat_init.c
+++ b/src/Common/libzip/zip_stat_init.c
@@ -1,6 +1,6 @@
/*
zip_stat_init.c -- initialize struct zip_stat.
- Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_strerror.c b/src/Common/libzip/zip_strerror.c
index 9e6e86c..906c7f7 100644
--- a/src/Common/libzip/zip_strerror.c
+++ b/src/Common/libzip/zip_strerror.c
@@ -1,6 +1,6 @@
/*
zip_sterror.c -- get string representation of zip error
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_string.c b/src/Common/libzip/zip_string.c
index 293766c..a6edbc5 100644
--- a/src/Common/libzip/zip_string.c
+++ b/src/Common/libzip/zip_string.c
@@ -1,6 +1,6 @@
/*
zip_string.c -- string handling (with encoding)
- Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_unchange.c b/src/Common/libzip/zip_unchange.c
index b0bd078..1a78e2c 100644
--- a/src/Common/libzip/zip_unchange.c
+++ b/src/Common/libzip/zip_unchange.c
@@ -1,6 +1,6 @@
/*
zip_unchange.c -- undo changes to file in zip archive
- Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_unchange_all.c b/src/Common/libzip/zip_unchange_all.c
index 165064b..5e7df80 100644
--- a/src/Common/libzip/zip_unchange_all.c
+++ b/src/Common/libzip/zip_unchange_all.c
@@ -1,6 +1,6 @@
/*
zip_unchange.c -- undo changes to all files in zip archive
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_unchange_archive.c b/src/Common/libzip/zip_unchange_archive.c
index f70dba9..bd223ef 100644
--- a/src/Common/libzip/zip_unchange_archive.c
+++ b/src/Common/libzip/zip_unchange_archive.c
@@ -1,6 +1,6 @@
/*
zip_unchange_archive.c -- undo global changes to ZIP archive
- Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_unchange_data.c b/src/Common/libzip/zip_unchange_data.c
index 1addaa8..74a429c 100644
--- a/src/Common/libzip/zip_unchange_data.c
+++ b/src/Common/libzip/zip_unchange_data.c
@@ -1,6 +1,6 @@
/*
zip_unchange_data.c -- undo helper function
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
diff --git a/src/Common/libzip/zip_utf-8.c b/src/Common/libzip/zip_utf-8.c
index 8f02f88..099db9b 100644
--- a/src/Common/libzip/zip_utf-8.c
+++ b/src/Common/libzip/zip_utf-8.c
@@ -1,6 +1,6 @@
/*
zip_utf-8.c -- UTF-8 support functions for libzip
- Copyright (C) 2011-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2011-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -39,7 +39,7 @@
static const zip_uint16_t _cp437_to_unicode[256] = {
/* 0x00 - 0x0F */
- 0x2007, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
+ 0x0000, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
/* 0x10 - 0x1F */
0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8, 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
diff --git a/src/Common/libzip/zipint.h b/src/Common/libzip/zipint.h
index 3c60ece..721d36e 100644
--- a/src/Common/libzip/zipint.h
+++ b/src/Common/libzip/zipint.h
@@ -3,7 +3,7 @@
/*
zipint.h -- internal declarations.
- Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -40,6 +40,10 @@
#include "compat.h"
+#ifdef ZIP_ALLOCATE_BUFFER
+#include <stdlib.h>
+#endif
+
#include <zlib.h>
#ifndef _ZIP_COMPILING_DEPRECATED
@@ -146,6 +150,9 @@ extern zip_compression_algorithm_t zip_algorithm_bzip2_compress;
extern zip_compression_algorithm_t zip_algorithm_bzip2_decompress;
extern zip_compression_algorithm_t zip_algorithm_deflate_compress;
extern zip_compression_algorithm_t zip_algorithm_deflate_decompress;
+extern zip_compression_algorithm_t zip_algorithm_xz_compress;
+extern zip_compression_algorithm_t zip_algorithm_xz_decompress;
+
bool zip_compression_method_supported(zip_int32_t method, bool compress);
@@ -367,6 +374,23 @@ struct zip_string {
};
+/* byte array */
+
+/* For performance, we usually keep 8k byte arrays on the stack.
+ However, there are (embedded) systems with a stack size of 12k;
+ for those, use malloc()/free() */
+
+#ifdef ZIP_ALLOCATE_BUFFER
+#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t *buf
+#define byte_array_init(buf, size) (((buf) = (zip_uint8_t *)malloc(size)) != NULL)
+#define byte_array_fini(buf) (free(buf))
+#else
+#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t buf[size]
+#define byte_array_init(buf, size) (1)
+#define byte_array_fini(buf) ((void)0)
+#endif
+
+
/* bounds checked access to memory buffer */
struct zip_buffer {
@@ -447,6 +471,7 @@ void _zip_cdir_free(zip_cdir_t *);
bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error);
zip_cdir_t *_zip_cdir_new(zip_uint64_t, zip_error_t *);
zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors);
+time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t);
void _zip_deregister_source(zip_t *za, zip_source_t *src);
zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *);
@@ -502,16 +527,19 @@ zip_hash_t *_zip_hash_new(zip_error_t *error);
bool _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error);
bool _zip_hash_revert(zip_hash_t *hash, zip_error_t *error);
+int _zip_mkstempm(char *path, int mode);
+
zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *);
void _zip_progress_end(zip_progress_t *progress);
void _zip_progress_free(zip_progress_t *progress);
-zip_progress_t *_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud);
-void _zip_progress_start(zip_progress_t *progress);
-void _zip_progress_subrange(zip_progress_t *progress, double start, double end);
-void _zip_progress_update(zip_progress_t *progress, double value);
+int _zip_progress_start(zip_progress_t *progress);
+int _zip_progress_subrange(zip_progress_t *progress, double start, double end);
+int _zip_progress_update(zip_progress_t *progress, double value);
-ZIP_EXTERN bool zip_random(zip_uint8_t *buffer, zip_uint16_t length);
+/* this symbol is extern so it can be overridden for regression testing */
+ZIP_EXTERN bool zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length);
+zip_uint32_t zip_random_uint32(void);
int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_error_t *error);
int _zip_read_at_offset(zip_source_t *src, zip_uint64_t offset, unsigned char *b, size_t length, zip_error_t *error);
@@ -522,6 +550,7 @@ int _zip_register_source(zip_t *za, zip_source_t *src);
void _zip_set_open_error(int *zep, const zip_error_t *err, int ze);
+bool zip_source_accept_empty(zip_source_t *src);
zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command);
bool _zip_source_eof(zip_source_t *);
zip_source_t *_zip_source_file_or_p(const char *, FILE *, zip_uint64_t, zip_int64_t, const zip_stat_t *, zip_error_t *error);
diff --git a/src/Common/libzip/zipwin32.h b/src/Common/libzip/zipwin32.h
index d2c5d82..870f1d5 100644
--- a/src/Common/libzip/zipwin32.h
+++ b/src/Common/libzip/zipwin32.h
@@ -3,7 +3,7 @@
/*
zipwin32.h -- internal declarations for Windows.
- Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>