VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Format
diff options
context:
space:
mode:
Diffstat (limited to 'src/Format')
-rw-r--r--src/Format/Format.rc19
-rw-r--r--src/Format/InPlace.c578
-rw-r--r--src/Format/InPlace.h5
-rw-r--r--src/Format/Resource.h7
-rw-r--r--src/Format/Tcformat.c488
-rw-r--r--src/Format/Tcformat.h2
6 files changed, 1029 insertions, 70 deletions
diff --git a/src/Format/Format.rc b/src/Format/Format.rc
index 44bcc66b..51564a64 100644
--- a/src/Format/Format.rc
+++ b/src/Format/Format.rc
@@ -223,12 +223,12 @@ STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
EDITTEXT IDC_PASSWORD_DIRECT,50,2,149,14,ES_PASSWORD | ES_AUTOHSCROLL
+ COMBOBOX IDC_PKCS5_PRF_ID,50,17,91,90,CBS_DROPDOWNLIST | WS_TABSTOP
CONTROL "&Display password",IDC_SHOW_PASSWORD_SINGLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,50,31,84,11,WS_EX_TRANSPARENT
CONTROL "U&se keyfiles",IDC_KEYFILES_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,50,42,82,11
PUSHBUTTON "&Keyfiles...",IDC_KEY_FILES,142,39,64,14
LTEXT "",IDC_BOX_HELP,0,57,225,94
RTEXT "Password:",IDT_PASSWORD,0,6,48,8
- COMBOBOX IDC_PKCS5_PRF_ID,50,17,91,90,CBS_DROPDOWNLIST | WS_TABSTOP
RTEXT "PKCS-5 PRF:",IDT_PKCS5_PRF,0,17,48,8
END
@@ -419,6 +419,15 @@ BEGIN
LISTBOX IDC_LIST_BOX,0,3,222,100,LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_VSCROLL
END
+IDD_DRIVE_LETTER_SELECTION_PAGE DIALOGEX 0, 0, 226, 152
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "",IDC_BOX_HELP,0,40,225,95
+ COMBOBOX IDC_DRIVE_LETTER_LIST,94,15,38,69,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ RTEXT "Drive letter:",IDT_DRIVE_LETTER,5,17,86,8
+END
+
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
@@ -662,6 +671,14 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 145
END
+
+ IDD_DRIVE_LETTER_SELECTION_PAGE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 219
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 145
+ END
END
#endif // APSTUDIO_INVOKED
diff --git a/src/Format/InPlace.c b/src/Format/InPlace.c
index 3998c2a5..408f6252 100644
--- a/src/Format/InPlace.c
+++ b/src/Format/InPlace.c
@@ -40,6 +40,18 @@ IMPORTANT: Due to this issue, functions in this file must not directly interact
using namespace std;
using namespace VeraCrypt;
+#if TC_VOLUME_DATA_OFFSET != 131072
+# error TC_VOLUME_DATA_OFFSET != 131072
+#endif
+
+#if TC_VOLUME_HEADER_EFFECTIVE_SIZE != 512
+# error TC_VOLUME_HEADER_EFFECTIVE_SIZE != 512
+#endif
+
+#if TC_TOTAL_VOLUME_HEADERS_SIZE != 262144
+# error TC_TOTAL_VOLUME_HEADERS_SIZE != 262144
+#endif
+
#define TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE (2048 * BYTES_PER_KB)
#define TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE (2 * TC_MAX_VOLUME_SECTOR_SIZE)
#define TC_NTFS_CONCEAL_CONSTANT 0xFF
@@ -312,6 +324,42 @@ BOOL CheckRequirementsForNonSysInPlaceEnc (HWND hwndDlg, const char *devicePath,
return TRUE;
}
+BOOL CheckRequirementsForNonSysInPlaceDec (HWND hwndDlg, const char *devicePath, BOOL silent)
+{
+ int partitionNumber = -1, driveNumber = -1;
+
+ /* ---------- Checks that do not require admin rights ----------- */
+
+ /* Volume type (must be a partition or a dynamic volume) */
+ if ((sscanf (devicePath, "\\Device\\HarddiskVolume%d", &partitionNumber) != 1
+ && sscanf (devicePath, "\\Device\\Harddisk%d\\Partition%d", &driveNumber, &partitionNumber) != 2)
+ || partitionNumber == 0)
+ {
+ if (!silent)
+ Error ("INPLACE_ENC_INVALID_PATH", hwndDlg);
+
+ return FALSE;
+ }
+
+
+ /* Admin rights */
+ if (!IsAdmin())
+ {
+ // We rely on the wizard process to call us only when the whole wizard process has been elevated (so UAC
+ // status can be ignored). In case the IsAdmin() detection somehow fails, we allow the user to continue.
+
+ if (!silent)
+ Warning ("ADMIN_PRIVILEGES_WARN_DEVICES", hwndDlg);
+ }
+
+
+ /* ---------- Checks that may require admin rights ----------- */
+
+ // [Currently none]
+
+ return TRUE;
+}
+
int EncryptPartitionInPlaceBegin (volatile FORMAT_VOL_PARAMETERS *volParams, volatile HANDLE *outHandle, WipeAlgorithmId wipeAlgorithm)
{
@@ -606,7 +654,7 @@ int EncryptPartitionInPlaceBegin (volatile FORMAT_VOL_PARAMETERS *volParams, vol
// In the config file, increase the number of partitions where in-place encryption is in progress
- SaveNonSysInPlaceEncSettings (1, wipeAlgorithm);
+ SaveNonSysInPlaceEncSettings (1, wipeAlgorithm, FALSE);
// Add the wizard to the system startup sequence if appropriate
@@ -1033,7 +1081,7 @@ inplace_enc_read:
// Update the configuration files
- SaveNonSysInPlaceEncSettings (-1, wipeAlgorithm);
+ SaveNonSysInPlaceEncSettings (-1, wipeAlgorithm, FALSE);
@@ -1126,6 +1174,513 @@ closing_seq:
return nStatus;
}
+int DecryptPartitionInPlace (volatile FORMAT_VOL_PARAMETERS *volParams, volatile BOOL *DiscardUnreadableEncryptedSectors)
+{
+ HANDLE dev = INVALID_HANDLE_VALUE;
+ PCRYPTO_INFO masterCryptoInfo = NULL, headerCryptoInfo = NULL;
+ UINT64_STRUCT unitNo;
+ char *buf = NULL;
+ byte *tmpSectorBuf = NULL;
+ char dosDev[TC_MAX_PATH] = {0};
+ char devName[MAX_PATH] = {0};
+ WCHAR deviceName[MAX_PATH];
+ int nStatus = ERR_SUCCESS;
+ __int64 deviceSize;
+ uint64 remainingBytes, workChunkStartByteOffset, lastHeaderUpdateDistance = 0, skippedBadSectorCount = 0;
+ uint32 workChunkSize;
+ DWORD dwError, dwResult;
+ BOOL bPause = FALSE, bEncryptedAreaSizeChanged = FALSE;
+ LARGE_INTEGER offset;
+ int sectorSize;
+ int i;
+ DWORD n;
+ char *devicePath = volParams->volumePath;
+ Password *password = volParams->password;
+ HWND hwndDlg = volParams->hwndDlg;
+ int pkcs5_prf = volParams->pkcs5;
+ DISK_GEOMETRY driveGeometry;
+
+
+ buf = (char *) TCalloc (TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE);
+ if (!buf)
+ {
+ nStatus = ERR_OUTOFMEMORY;
+ goto closing_seq;
+ }
+
+ headerCryptoInfo = crypto_open();
+
+ if (headerCryptoInfo == NULL)
+ {
+ nStatus = ERR_OUTOFMEMORY;
+ goto closing_seq;
+ }
+
+ deviceSize = GetDeviceSize (devicePath);
+ if (deviceSize < 0)
+ {
+ // Cannot determine the size of the partition
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+
+
+ // The wizard should have dismounted the TC volume if it was mounted, but for extra safety we will check this again.
+ if (IsMountedVolume (devicePath))
+ {
+ int driveLetter = GetMountedVolumeDriveNo (devicePath);
+
+ if (driveLetter == -1
+ || !UnmountVolume (hwndDlg, driveLetter, TRUE))
+ {
+ handleWin32Error (hwndDlg);
+ AbortProcess ("CANT_DISMOUNT_VOLUME");
+ }
+ }
+
+
+ StringCbCopyA ((char *)deviceName, sizeof(deviceName), devicePath);
+ ToUNICODE ((char *)deviceName, sizeof(deviceName));
+
+ if (FakeDosNameForDevice (devicePath, dosDev, sizeof(dosDev), devName, sizeof(devName), FALSE) != 0)
+ {
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+
+ dev = OpenPartitionVolume (hwndDlg, devName,
+ TRUE, // Require exclusive access
+ FALSE, // Do not require shared access
+ TRUE, // Ask the user to confirm shared access (if exclusive fails)
+ FALSE, // Do not append alternative instructions how to encrypt the data (to applicable error messages)
+ FALSE); // Non-silent mode
+
+ if (dev == INVALID_HANDLE_VALUE)
+ {
+ nStatus = ERR_DONT_REPORT;
+ goto closing_seq;
+ }
+
+
+
+ // This should never be needed, but is still performed for extra safety (without checking the result)
+ DeviceIoControl (dev,
+ FSCTL_ALLOW_EXTENDED_DASD_IO,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ &dwResult,
+ NULL);
+
+
+ if (!DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveGeometry, sizeof (driveGeometry), &dwResult, NULL))
+ {
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+
+ sectorSize = driveGeometry.BytesPerSector;
+
+
+ tmpSectorBuf = (byte *) TCalloc (sectorSize);
+ if (!tmpSectorBuf)
+ {
+ nStatus = ERR_OUTOFMEMORY;
+ goto closing_seq;
+ }
+
+
+ nStatus = OpenBackupHeader (dev, devicePath, password, pkcs5_prf, &masterCryptoInfo, headerCryptoInfo, deviceSize);
+
+ if (nStatus != ERR_SUCCESS)
+ goto closing_seq;
+
+
+ if (masterCryptoInfo->LegacyVolume)
+ {
+ Error ("NONSYS_INPLACE_DECRYPTION_BAD_VOL_FORMAT", hwndDlg);
+ nStatus = ERR_DONT_REPORT;
+ goto closing_seq;
+ }
+
+ if (masterCryptoInfo->hiddenVolume)
+ {
+ Error ("NONSYS_INPLACE_DECRYPTION_CANT_DECRYPT_HID_VOL", hwndDlg);
+ nStatus = ERR_DONT_REPORT;
+ goto closing_seq;
+ }
+
+ if (!bInPlaceEncNonSysResumed
+ && masterCryptoInfo->VolumeSize.Value == masterCryptoInfo->EncryptedAreaLength.Value)
+ {
+ /* Decryption started (not resumed) */
+
+ if ((masterCryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0)
+ {
+ // The volume has not been encrypted in-place so it may contain a hidden volume.
+ // Ask the user to confirm it does not.
+
+ char *tmpStr[] = {0,
+ "CONFIRM_VOL_CONTAINS_NO_HIDDEN_VOL",
+ "VOL_CONTAINS_NO_HIDDEN_VOL",
+ "VOL_CONTAINS_A_HIDDEN_VOL",
+ 0};
+
+ switch (AskMultiChoice ((void **) tmpStr, FALSE, hwndDlg))
+ {
+ case 1:
+ // NOP
+ break;
+ case 2:
+ default:
+ // Cancel
+ nStatus = ERR_DONT_REPORT;
+ goto closing_seq;
+ }
+ }
+
+ // Update config files and app data
+
+ // In the config file, increase the number of partitions where in-place decryption is in progress
+ SaveNonSysInPlaceEncSettings (1, TC_WIPE_NONE, TRUE);
+
+ // Add the wizard to the system startup sequence if appropriate
+ if (!IsNonInstallMode ())
+ ManageStartupSeqWiz (FALSE, "/prinplace");
+ }
+
+
+
+ bInPlaceEncNonSysResumed = TRUE;
+ bFirstNonSysInPlaceEncResumeDone = TRUE;
+
+
+ remainingBytes = masterCryptoInfo->EncryptedAreaLength.Value;
+
+ lastHeaderUpdateDistance = 0;
+
+
+ ExportProgressStats (masterCryptoInfo->EncryptedAreaLength.Value, masterCryptoInfo->VolumeSize.Value);
+
+ SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_DECRYPTING);
+
+
+
+ /* The in-place decryption core */
+
+ while (remainingBytes > 0)
+ {
+ workChunkSize = (uint32) min (remainingBytes, TC_MAX_NONSYS_INPLACE_ENC_WORK_CHUNK_SIZE);
+
+ if (workChunkSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
+ {
+ nStatus = ERR_PARAMETER_INCORRECT;
+ goto closing_seq;
+ }
+
+ workChunkStartByteOffset = masterCryptoInfo->EncryptedAreaStart.Value;
+
+ unitNo.Value = workChunkStartByteOffset / ENCRYPTION_DATA_UNIT_SIZE;
+
+
+ // Read the ciphertext into RAM
+
+ offset.QuadPart = workChunkStartByteOffset;
+
+ if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0)
+ {
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+
+ if (ReadFile (dev, buf, workChunkSize, &n, NULL) == 0)
+ {
+ // Read error
+
+ DWORD dwTmpErr = GetLastError ();
+
+ if (IsDiskReadError (dwTmpErr) && !bVolTransformThreadCancel)
+ {
+ // Physical defect or data corruption
+
+ if (!*DiscardUnreadableEncryptedSectors)
+ {
+ *DiscardUnreadableEncryptedSectors = (AskWarnYesNo ("DISCARD_UNREADABLE_ENCRYPTED_SECTORS", hwndDlg) == IDYES);
+ }
+
+ if (*DiscardUnreadableEncryptedSectors)
+ {
+ // Read the work chunk again, but this time each sector individually and skiping each bad sector
+
+ LARGE_INTEGER tmpSectorOffset;
+ uint64 tmpSectorCount;
+ uint64 tmpBufOffset = 0;
+ DWORD tmpNbrReadBytes = 0;
+
+ tmpSectorOffset.QuadPart = offset.QuadPart;
+
+ for (tmpSectorCount = workChunkSize / sectorSize; tmpSectorCount > 0; --tmpSectorCount)
+ {
+ if (SetFilePointerEx (dev, tmpSectorOffset, NULL, FILE_BEGIN) == 0)
+ {
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+
+ if (ReadFile (dev, tmpSectorBuf, sectorSize, &tmpNbrReadBytes, NULL) == 0
+ || tmpNbrReadBytes != (DWORD) sectorSize)
+ {
+ // Read error
+
+ // Clear the buffer so the content of each unreadable sector is replaced with decrypted all-zero blocks (producing pseudorandom data)
+ memset (tmpSectorBuf, 0, sectorSize);
+
+ skippedBadSectorCount++;
+ }
+
+ memcpy (buf + tmpBufOffset, tmpSectorBuf, sectorSize);
+
+ tmpSectorOffset.QuadPart += sectorSize;
+ tmpBufOffset += sectorSize;
+ }
+ }
+ else
+ {
+ SetLastError (dwTmpErr); // Preserve the original error code
+
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+ }
+ else
+ {
+ SetLastError (dwTmpErr); // Preserve the original error code
+
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+ }
+
+ // Decrypt the ciphertext in RAM
+
+ DecryptDataUnits ((byte *) buf, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, masterCryptoInfo);
+
+
+
+ // Conceal initial portion of the filesystem
+
+ if (workChunkStartByteOffset - TC_VOLUME_DATA_OFFSET < TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE)
+ {
+ // We are decrypting the initial TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE bytes of the filesystem. We will
+ // conceal this portion to prevent Windows and applications from interfering with the volume.
+
+ for (i = 0; i < min (TC_INITIAL_NTFS_CONCEAL_PORTION_SIZE, workChunkStartByteOffset - TC_VOLUME_DATA_OFFSET + workChunkSize); i++)
+ buf[i] ^= TC_NTFS_CONCEAL_CONSTANT;
+ }
+
+
+ // Write the plaintext
+
+ offset.QuadPart = workChunkStartByteOffset - TC_VOLUME_DATA_OFFSET;
+
+ if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0)
+ {
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+
+ if (WriteFile (dev, buf, workChunkSize, &n, NULL) == 0)
+ {
+ // Write error
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+
+
+ masterCryptoInfo->EncryptedAreaStart.Value += workChunkSize;
+ masterCryptoInfo->EncryptedAreaLength.Value -= workChunkSize;
+
+ remainingBytes -= workChunkSize;
+ lastHeaderUpdateDistance += workChunkSize;
+
+ bEncryptedAreaSizeChanged = TRUE;
+
+ if (lastHeaderUpdateDistance >= TC_NONSYS_INPLACE_ENC_HEADER_UPDATE_INTERVAL)
+ {
+ nStatus = FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize);
+
+ if (nStatus != ERR_SUCCESS)
+ {
+ // Possible write error
+ goto closing_seq;
+ }
+
+ lastHeaderUpdateDistance = 0;
+ }
+
+ ExportProgressStats (masterCryptoInfo->EncryptedAreaLength.Value, masterCryptoInfo->VolumeSize.Value);
+
+ if (bVolTransformThreadCancel)
+ {
+ bPause = TRUE;
+ break;
+ }
+ }
+
+ nStatus = FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize);
+
+
+ if (nStatus != ERR_SUCCESS)
+ {
+ // Possible write error
+ goto closing_seq;
+ }
+
+
+ if (!bPause)
+ {
+ /* Volume has been fully decrypted. */
+
+
+ // Prevent attempts to update volume header during the closing sequence
+ bEncryptedAreaSizeChanged = FALSE;
+
+
+ SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_FINALIZING);
+
+
+
+ /* Undo concealing of the filesystem */
+
+ nStatus = ConcealNTFS (dev);
+
+ if (nStatus != ERR_SUCCESS)
+ goto closing_seq;
+
+
+
+ /* Ovewrite the backup header and the remaining ciphertext with all-zero blocks (the primary header was overwritten with the decrypted data). */
+
+ memset (tmpSectorBuf, 0, sectorSize);
+
+ for (offset.QuadPart = masterCryptoInfo->VolumeSize.Value;
+ offset.QuadPart <= deviceSize - sectorSize;
+ offset.QuadPart += sectorSize)
+ {
+ if (SetFilePointerEx (dev, offset, NULL, FILE_BEGIN) == 0)
+ {
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+
+ if (WriteFile (dev, tmpSectorBuf, sectorSize, &n, NULL) == 0)
+ {
+ // Write error
+ dwError = GetLastError();
+
+ SetLastError (dwError);
+ nStatus = ERR_OS_ERROR;
+ goto closing_seq;
+ }
+ }
+
+
+
+ /* Update the configuration files */
+
+ SaveNonSysInPlaceEncSettings (-1, TC_WIPE_NONE, TRUE);
+
+
+
+ SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_FINISHED);
+
+ nStatus = ERR_SUCCESS;
+
+ }
+ else
+ {
+ // The process has been paused by the user or aborted by the wizard (e.g. on app exit)
+
+ nStatus = ERR_USER_ABORT;
+
+ SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PAUSED);
+ }
+
+ if (dev != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle (dev);
+ dev = INVALID_HANDLE_VALUE;
+ }
+
+
+closing_seq:
+
+ dwError = GetLastError();
+
+ if (bEncryptedAreaSizeChanged
+ && dev != INVALID_HANDLE_VALUE
+ && masterCryptoInfo != NULL
+ && headerCryptoInfo != NULL
+ && deviceSize > 0)
+ {
+ // Execution of the core loop may have been interrupted due to an error or user action without updating the header
+ FastVolumeHeaderUpdate (dev, headerCryptoInfo, masterCryptoInfo, deviceSize);
+ }
+
+ if (dev != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle (dev);
+ dev = INVALID_HANDLE_VALUE;
+ }
+
+ if (masterCryptoInfo != NULL)
+ {
+ crypto_close (masterCryptoInfo);
+ masterCryptoInfo = NULL;
+ }
+
+ if (headerCryptoInfo != NULL)
+ {
+ crypto_close (headerCryptoInfo);
+ headerCryptoInfo = NULL;
+ }
+
+ if (dosDev[0])
+ RemoveFakeDosName (devicePath, dosDev);
+
+ if (buf != NULL)
+ {
+ TCfree (buf);
+ buf = NULL;
+ }
+
+ if (tmpSectorBuf != NULL)
+ {
+ TCfree (tmpSectorBuf);
+ tmpSectorBuf = NULL;
+ }
+
+ if (skippedBadSectorCount > 0)
+ {
+ wchar_t msg[30000] = {0};
+ wchar_t sizeStr[500] = {0};
+
+ GetSizeString (skippedBadSectorCount * sectorSize, sizeStr, sizeof(sizeStr));
+
+ StringCbPrintfW (msg, sizeof(msg),
+ GetString ("SKIPPED_BAD_SECTOR_COUNT"),
+ skippedBadSectorCount,
+ sizeStr);
+
+ WarningDirect (msg, hwndDlg);
+ }
+
+ if (nStatus != ERR_SUCCESS && nStatus != ERR_USER_ABORT)
+ SetLastError (dwError);
+
+ return nStatus;
+}
int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_INFO *masterCryptoInfo, __int64 deviceSize)
{
@@ -1168,6 +1723,13 @@ int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_IN
mputInt64 (fieldPos, (masterCryptoInfo->EncryptedAreaStart.Value));
mputInt64 (fieldPos, (masterCryptoInfo->EncryptedAreaLength.Value));
+ // We need to ensure the TC_HEADER_FLAG_NONSYS_INPLACE_ENC flag bit is set, because if volumes created by TC-format
+ // were decrypted in place, it would be possible to mount them partially encrypted and it wouldn't be possible
+ // to resume interrupted decryption after the wizard exits.
+ masterCryptoInfo->HeaderFlags |= TC_HEADER_FLAG_NONSYS_INPLACE_ENC;
+ fieldPos = (byte *) header + TC_HEADER_OFFSET_FLAGS;
+ mputLong (fieldPos, (masterCryptoInfo->HeaderFlags));
+
headerCrc32 = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
fieldPos = (byte *) header + TC_HEADER_OFFSET_HEADER_CRC;
@@ -1419,7 +1981,7 @@ void SetNonSysInplaceEncUIStatus (int nonSysInplaceEncStatus)
}
-BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId newWipeAlgorithm)
+BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId newWipeAlgorithm, BOOL bDecrypt)
{
int count;
char str[32];
@@ -1435,7 +1997,7 @@ BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId newWipeAlgorithm)
RemoveNonSysInPlaceEncNotifications();
return TRUE;
}
- else
+ else if (!bDecrypt)
{
if (newWipeAlgorithm != TC_WIPE_NONE)
{
@@ -1447,11 +2009,11 @@ BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId newWipeAlgorithm)
{
remove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE));
}
-
- StringCbPrintfA (str, sizeof(str), "%d", count);
-
- return SaveBufferToFile (str, GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), strlen(str), FALSE);
}
+
+ StringCbPrintfA (str, sizeof(str), "%d", count);
+
+ return SaveBufferToFile (str, GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), strlen(str), FALSE);
}
diff --git a/src/Format/InPlace.h b/src/Format/InPlace.h
index 90cf5f80..6b59bbd4 100644
--- a/src/Format/InPlace.h
+++ b/src/Format/InPlace.h
@@ -18,6 +18,7 @@ enum nonsys_inplace_enc_status
NONSYS_INPLACE_ENC_STATUS_PREPARING,
NONSYS_INPLACE_ENC_STATUS_RESIZING,
NONSYS_INPLACE_ENC_STATUS_ENCRYPTING,
+ NONSYS_INPLACE_ENC_STATUS_DECRYPTING,
NONSYS_INPLACE_ENC_STATUS_FINALIZING,
NONSYS_INPLACE_ENC_STATUS_PAUSED,
NONSYS_INPLACE_ENC_STATUS_FINISHED,
@@ -25,8 +26,10 @@ enum nonsys_inplace_enc_status
};
BOOL CheckRequirementsForNonSysInPlaceEnc (HWND hwndDlg, const char *devicePath, BOOL silent);
+BOOL CheckRequirementsForNonSysInPlaceDec (HWND hwndDlg, const char *devicePath, BOOL silent);
int EncryptPartitionInPlaceBegin (volatile FORMAT_VOL_PARAMETERS *volParams, volatile HANDLE *outHandle, WipeAlgorithmId wipeAlgorithm);
int EncryptPartitionInPlaceResume (HANDLE dev, volatile FORMAT_VOL_PARAMETERS *volParams, WipeAlgorithmId wipeAlgorithm, volatile BOOL *bTryToCorrectReadErrors);
+int DecryptPartitionInPlace (volatile FORMAT_VOL_PARAMETERS *volParams, volatile BOOL *DiscardUnreadableEncryptedSectors);
void ShowInPlaceEncErrMsgWAltSteps (HWND hwndDlg, char *iniStrId, BOOL bErr);
void SetNonSysInplaceEncUIStatus (int nonSysInplaceEncStatus);
int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_INFO *masterCryptoInfo, __int64 deviceSize);
@@ -34,7 +37,7 @@ int FastVolumeHeaderUpdate (HANDLE dev, CRYPTO_INFO *headerCryptoInfo, CRYPTO_IN
static HANDLE OpenPartitionVolume (HWND hwndDlg, const char *devName, BOOL bExclusiveRequired, BOOL bSharedRequired, BOOL bSharedRequiresConfirmation, BOOL bShowAlternativeSteps, BOOL bSilent);
static int DismountFileSystem (HWND hwndDlg, HANDLE dev, int driveLetter, BOOL bForcedAllowed, BOOL bForcedRequiresConfirmation, BOOL bSilent);
static int ConcealNTFS (HANDLE dev);
-BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId wipeAlgorithm);
+BOOL SaveNonSysInPlaceEncSettings (int delta, WipeAlgorithmId wipeAlgorithm, BOOL bDecrypting);
static void ExportProgressStats (__int64 bytesDone, __int64 totalSize);
int ZeroUnreadableSectors (HANDLE dev, LARGE_INTEGER startOffset, int64 size, int sectorSize, uint64 *zeroedSectorCount);
static int OpenBackupHeader (HANDLE dev, const char *devicePath, Password *password, int pkcs5, PCRYPTO_INFO *retCryptoInfo, CRYPTO_INFO *headerCryptoInfo, __int64 deviceSize);
diff --git a/src/Format/Resource.h b/src/Format/Resource.h
index 61a38332..feba5ec3 100644
--- a/src/Format/Resource.h
+++ b/src/Format/Resource.h
@@ -34,6 +34,7 @@
#define IDD_DEVICE_WIPE_MODE_PAGE_DLG 129
#define IDD_DEVICE_TRANSFORM_MODE_DLG 130
#define IDD_EXPANDED_LIST_SELECT_PAGE_DLG 131
+#define IDD_DRIVE_LETTER_SELECTION_PAGE 132
#define IDC_BOX_TITLE 1000
#define IDC_RESCUE_DISK_ISO_PATH 1001
#define IDC_COMBO_BOX 1002
@@ -137,15 +138,17 @@
#define IDT_PASS 1100
#define IDC_DEVICE_TRANSFORM_MODE_FORMAT 1101
#define IDC_DEVICE_TRANSFORM_MODE_INPLACE 1102
+#define IDC_DRIVE_LETTER_LIST 1103
+#define IDT_DRIVE_LETTER 1104
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
-#define _APS_NEXT_RESOURCE_VALUE 132
+#define _APS_NEXT_RESOURCE_VALUE 133
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1103
+#define _APS_NEXT_CONTROL_VALUE 1105
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/src/Format/Tcformat.c b/src/Format/Tcformat.c
index ba35c47e..a0d9b293 100644
--- a/src/Format/Tcformat.c
+++ b/src/Format/Tcformat.c
@@ -94,8 +94,9 @@ enum wizard_pages
NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE,
NONSYS_INPLACE_ENC_RAND_DATA_PAGE,
NONSYS_INPLACE_ENC_WIPE_MODE_PAGE,
- NONSYS_INPLACE_ENC_ENCRYPTION_PAGE,
- NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE,
+ NONSYS_INPLACE_ENC_TRANSFORM_PAGE,
+ NONSYS_INPLACE_ENC_TRANSFORM_FINISHED_PAGE,
+ NONSYS_INPLACE_DEC_TRANSFORM_FINISHED_DRIVE_LETTER_PAGE,
FORMAT_PAGE,
FORMAT_FINISHED_PAGE,
SYSENC_HIDDEN_OS_INITIAL_INFO_PAGE,
@@ -148,10 +149,13 @@ volatile BOOL bHiddenOS = FALSE; /* If TRUE, we are performing or (or supposed
BOOL bDirectSysEncMode = FALSE;
BOOL bDirectSysEncModeCommand = SYSENC_COMMAND_NONE;
BOOL DirectDeviceEncMode = FALSE;
+BOOL DirectNonSysInplaceDecStartMode = FALSE;
BOOL DirectNonSysInplaceEncResumeMode = FALSE;
+BOOL DirectNonSysInplaceDecResumeMode = FALSE;
BOOL DirectPromptNonSysInplaceEncResumeMode = FALSE;
-volatile BOOL bInPlaceEncNonSys = FALSE; /* If TRUE, existing data on a non-system partition/volume are to be encrypted (for system encryption, this flag is ignored) */
-volatile BOOL bInPlaceEncNonSysResumed = FALSE; /* If TRUE, the wizard is supposed to resume (or has resumed) process of non-system in-place encryption. */
+volatile BOOL bInPlaceEncNonSys = FALSE; /* If TRUE, existing data on a non-system partition/volume are to be encrypted (or decrypted if bInPlaceDecNonSys is TRUE) in place (for system encryption, this flag is ignored) */
+volatile BOOL bInPlaceDecNonSys = FALSE; /* If TRUE, existing data on a non-system partition/volume are to be decrypted in place (for system encryption, this flag is ignored) */
+volatile BOOL bInPlaceEncNonSysResumed = FALSE; /* If TRUE, the wizard is supposed to resume (or has resumed) process of non-system in-place encryption/decryption. */
volatile BOOL bFirstNonSysInPlaceEncResumeDone = FALSE;
__int64 NonSysInplaceEncBytesDone = 0;
__int64 NonSysInplaceEncTotalSize = 0;
@@ -657,7 +661,10 @@ static BOOL ChangeWizardMode (int newWizardMode)
}
if (newWizardMode != WIZARD_MODE_NONSYS_DEVICE)
+ {
bInPlaceEncNonSys = FALSE;
+ bInPlaceDecNonSys = FALSE;
+ }
if (newWizardMode == WIZARD_MODE_NONSYS_DEVICE && !IsAdmin() && IsUacSupported())
{
@@ -666,7 +673,8 @@ static BOOL ChangeWizardMode (int newWizardMode)
}
// The contents of the following items may be inappropriate after a change of mode
- szFileName[0] = 0;
+ if (! (bInPlaceDecNonSys && !bInPlaceEncNonSysResumed)) // If we are starting (but not resuming) decryption of non-system volume, we actually need szFileName as it contains the command line param.
+ szFileName[0] = 0;
szDiskFile[0] = 0;
nUIVolumeSize = 0;
nVolumeSize = 0;
@@ -1067,6 +1075,7 @@ BOOL SwitchWizardToHiddenOSMode (void)
bHiddenVolDirect = FALSE;
bWholeSysDrive = FALSE;
bInPlaceEncNonSys = FALSE;
+ bInPlaceDecNonSys = FALSE;
if (bDirectSysEncModeCommand == SYSENC_COMMAND_CREATE_HIDDEN_OS_ELEV)
{
@@ -1102,11 +1111,11 @@ BOOL SwitchWizardToHiddenOSMode (void)
return TRUE;
}
-void SwitchWizardToNonSysInplaceEncResumeMode (void)
+void SwitchWizardToNonSysInplaceEncResumeMode (BOOL bDecrypt)
{
if (!IsAdmin() && IsUacSupported())
{
- if (!ElevateWholeWizardProcess ("/zinplace"))
+ if (!ElevateWholeWizardProcess (bDecrypt ? "/resumeinplacedec" : "/zinplace"))
AbortProcessSilent ();
}
@@ -1116,6 +1125,7 @@ void SwitchWizardToNonSysInplaceEncResumeMode (void)
CreateNonSysInplaceEncMutex ();
bInPlaceEncNonSys = TRUE;
+ bInPlaceDecNonSys = bDecrypt;
bInPlaceEncNonSysResumed = TRUE;
ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE);
@@ -1123,6 +1133,31 @@ void SwitchWizardToNonSysInplaceEncResumeMode (void)
LoadPage (MainDlg, NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE);
}
+void SwitchWizardToNonSysInplaceDecStartMode (char *volPath)
+{
+ if (!IsAdmin() && IsUacSupported())
+ {
+ if (!ElevateWholeWizardProcess ((string ("/inplacedec \"") + volPath + "\"").c_str()))
+ AbortProcessSilent ();
+ }
+
+ if (!IsAdmin())
+ AbortProcess("ADMIN_PRIVILEGES_WARN_DEVICES");
+
+ if (!CheckRequirementsForNonSysInPlaceDec (MainDlg, volPath, FALSE))
+ AbortProcessSilent ();
+
+ CreateNonSysInplaceEncMutex ();
+
+ bInPlaceEncNonSys = TRUE;
+ bInPlaceDecNonSys = TRUE;
+ bInPlaceEncNonSysResumed = FALSE;
+
+ ChangeWizardMode (WIZARD_MODE_NONSYS_DEVICE);
+
+ LoadPage (MainDlg, NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE);
+}
+
// Use this function e.g. if the config file with the system encryption settings was lost or not written
// correctly, and we don't know whether to encrypt or decrypt (but we know that encryption or decryption
// is required). Returns FALSE if failed or cancelled.
@@ -1730,6 +1765,7 @@ static void SysEncResume (void)
return;
}
+ bVolTransformThreadCancel = FALSE;
bSystemEncryptionInProgress = FALSE;
WaitCursor ();
@@ -1906,6 +1942,9 @@ void ShowNonSysInPlaceEncUIStatus (void)
case NONSYS_INPLACE_ENC_STATUS_ENCRYPTING:
StringCbCopyW (nonSysInplaceEncUIStatus, sizeof(nonSysInplaceEncUIStatus), GetString ("PROGRESS_STATUS_ENCRYPTING"));
break;
+ case NONSYS_INPLACE_ENC_STATUS_DECRYPTING:
+ StringCbCopyW (nonSysInplaceEncUIStatus, sizeof(nonSysInplaceEncUIStatus), GetString ("PROGRESS_STATUS_DECRYPTING"));
+ break;
case NONSYS_INPLACE_ENC_STATUS_FINALIZING:
StringCbCopyW (nonSysInplaceEncUIStatus, sizeof(nonSysInplaceEncUIStatus), GetString ("PROGRESS_STATUS_FINALIZING"));
break;
@@ -1925,12 +1964,28 @@ void ShowNonSysInPlaceEncUIStatus (void)
void UpdateNonSysInPlaceEncControls (void)
{
- EnableWindow (GetDlgItem (hCurPage, IDC_WIPE_MODE), !(bVolTransformThreadRunning || bVolTransformThreadToRun));
+ // Reduce flickering by updating a GUI element only when a relevant change affects it
+ static BOOL lastbVolTransformThreadRunning = !bVolTransformThreadRunning;
+ static BOOL lastbVolTransformThreadToRun = !bVolTransformThreadToRun;
+ static BOOL lastbInPlaceEncNonSysResumed = !bInPlaceEncNonSysResumed;
- SetWindowTextW (GetDlgItem (hCurPage, IDC_PAUSE),
- GetString ((bVolTransformThreadRunning || bVolTransformThreadToRun) ? "IDC_PAUSE" : "RESUME"));
+ EnableWindow (GetDlgItem (hCurPage, IDC_WIPE_MODE), !(bVolTransformThreadRunning || bVolTransformThreadToRun) && !bInPlaceDecNonSys);
+
+ if (lastbVolTransformThreadRunning != bVolTransformThreadRunning
+ || lastbVolTransformThreadToRun != bVolTransformThreadToRun)
+ {
+ SetWindowTextW (GetDlgItem (hCurPage, IDC_PAUSE),
+ GetString ((bVolTransformThreadRunning || bVolTransformThreadToRun) ? "IDC_PAUSE" : "RESUME"));
- SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString (bInPlaceEncNonSysResumed ? "DEFER" : "CANCEL"));
+ lastbVolTransformThreadRunning = bVolTransformThreadRunning;
+ lastbVolTransformThreadToRun = bVolTransformThreadToRun;
+ }
+
+ if (lastbInPlaceEncNonSysResumed != bInPlaceEncNonSysResumed)
+ {
+ SetWindowTextW (GetDlgItem (MainDlg, IDCANCEL), GetString (bInPlaceEncNonSysResumed ? "DEFER" : "CANCEL"));
+ lastbInPlaceEncNonSysResumed = bInPlaceEncNonSysResumed;
+ }
EnableWindow (GetDlgItem (hCurPage, IDC_PAUSE), bFirstNonSysInPlaceEncResumeDone
&& NonSysInplaceEncStatus != NONSYS_INPLACE_ENC_STATUS_FINALIZING
@@ -1995,11 +2050,12 @@ static void UpdateNonSysInplaceEncProgressBar (void)
if (bVolTransformThreadRunning
&& (nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_ENCRYPTING
+ || nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_DECRYPTING
|| nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINALIZING
|| nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED))
{
if (lastNonSysInplaceEncStatus != nonSysInplaceEncStatus
- && nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_ENCRYPTING)
+ && (nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_ENCRYPTING || nonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_DECRYPTING))
{
InitNonSysInplaceEncProgressBar ();
}
@@ -2033,7 +2089,7 @@ static void InitNonSysInplaceEncProgressBar (void)
InitProgressBar (totalSize,
NonSysInplaceEncBytesDone,
- FALSE,
+ bInPlaceDecNonSys,
TRUE,
TRUE,
TRUE);
@@ -2436,7 +2492,7 @@ static void __cdecl volTransformThreadFunction (void *hwndDlgArg)
volParams->hiddenVolHostSize = nHiddenVolHostSize;
volParams->ea = nVolumeEA;
volParams->pkcs5 = hash_algo;
- volParams->headerFlags = CreatingHiddenSysVol() ? TC_HEADER_FLAG_ENCRYPTED_SYSTEM : 0;
+ volParams->headerFlags = (CreatingHiddenSysVol() ? TC_HEADER_FLAG_ENCRYPTED_SYSTEM : 0);
volParams->fileSystem = fileSystem;
volParams->clusterSize = clusterSize;
volParams->sparseFileSwitch = bSparseFileSwitch;
@@ -2446,8 +2502,19 @@ static void __cdecl volTransformThreadFunction (void *hwndDlgArg)
volParams->password = &volumePassword;
volParams->hwndDlg = hwndDlg;
- if (bInPlaceEncNonSys)
+ if (bInPlaceDecNonSys)
{
+ // In-place decryption of non-system volume
+
+ if (!bInPlaceEncNonSysResumed)
+ DiscardUnreadableEncryptedSectors = FALSE;
+
+ nStatus = DecryptPartitionInPlace (volParams, &DiscardUnreadableEncryptedSectors);
+ }
+ else if (bInPlaceEncNonSys)
+ {
+ // In-place encryption of non-system volume
+
HANDLE hPartition = INVALID_HANDLE_VALUE;
SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_PREPARING);
@@ -2475,6 +2542,8 @@ static void __cdecl volTransformThreadFunction (void *hwndDlgArg)
}
else
{
+ // Format-encryption
+
InitProgressBar (GetVolumeDataAreaSize (bHidden, nVolumeSize), 0, FALSE, FALSE, FALSE, TRUE);
nStatus = TCFormatVolume (volParams);
@@ -2492,7 +2561,7 @@ static void __cdecl volTransformThreadFunction (void *hwndDlgArg)
&& nStatus == ERR_USER_ABORT
&& NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED)
{
- // Ignore user abort if non-system in-place encryption successfully finished
+ // Ignore user abort if non-system in-place encryption/decryption successfully finished
nStatus = ERR_SUCCESS;
}
@@ -2519,7 +2588,7 @@ static void __cdecl volTransformThreadFunction (void *hwndDlgArg)
SetLastError (dwWin32FormatError);
if ((bVolTransformThreadCancel || nStatus == ERR_USER_ABORT)
- && !(bInPlaceEncNonSys && NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED)) // Ignore user abort if non-system in-place encryption successfully finished.
+ && !(bInPlaceEncNonSys && NonSysInplaceEncStatus == NONSYS_INPLACE_ENC_STATUS_FINISHED)) // Ignore user abort if non-system in-place encryption/decryption successfully finished.
{
if (!bDevice && !(bHiddenVol && !bHiddenVolHost)) // If we're not creating a hidden volume and if it's a file container
{
@@ -2549,7 +2618,11 @@ static void __cdecl volTransformThreadFunction (void *hwndDlgArg)
else
{
SetNonSysInplaceEncUIStatus (NONSYS_INPLACE_ENC_STATUS_ERROR);
- ShowInPlaceEncErrMsgWAltSteps (hwndDlg, "INPLACE_ENC_GENERIC_ERR_ALT_STEPS", TRUE);
+
+ if (bInPlaceDecNonSys)
+ Error ("INPLACE_DEC_GENERIC_ERR", hwndDlg);
+ else
+ ShowInPlaceEncErrMsgWAltSteps (hwndDlg, "INPLACE_ENC_GENERIC_ERR_ALT_STEPS", TRUE);
}
}
else if (!(bHiddenVolHost && hiddenVolHostDriveNo < 0)) // If the error was not that the hidden volume host could not be mounted (this error has already been reported to the user)
@@ -2589,9 +2662,16 @@ static void __cdecl volTransformThreadFunction (void *hwndDlgArg)
}
else if (bInPlaceEncNonSys)
{
- Warning ("NONSYS_INPLACE_ENC_FINISHED_INFO", hwndDlg);
+ if (!bInPlaceDecNonSys)
+ {
+ Warning ("NONSYS_INPLACE_ENC_FINISHED_INFO", hwndDlg);
- HandleOldAssignedDriveLetter ();
+ HandleOldAssignedDriveLetter ();
+ }
+ else
+ {
+ // NOP - Final steps for in-place decryption are handled with the TC_APPMSG_NONSYS_INPLACE_ENC_FINISHED message.
+ }
}
else
{
@@ -2868,16 +2948,21 @@ static void LoadPage (HWND hwndDlg, int nPageNo)
(DLGPROC) PageDialogProc);
break;
- case NONSYS_INPLACE_ENC_ENCRYPTION_PAGE:
+ case NONSYS_INPLACE_ENC_TRANSFORM_PAGE:
hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INPLACE_ENCRYPTION_PAGE_DLG), hwndDlg,
(DLGPROC) PageDialogProc);
break;
- case NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE:
+ case NONSYS_INPLACE_ENC_TRANSFORM_FINISHED_PAGE:
hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_INFO_PAGE_DLG), hwndDlg,
(DLGPROC) PageDialogProc);
break;
+ case NONSYS_INPLACE_DEC_TRANSFORM_FINISHED_DRIVE_LETTER_PAGE:
+ hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_DRIVE_LETTER_SELECTION_PAGE), hwndDlg,
+ (DLGPROC) PageDialogProc);
+ break;
+
case FORMAT_PAGE:
hCurPage = CreateDialogW (hInst, MAKEINTRESOURCEW (IDD_FORMAT_PAGE_DLG), hwndDlg,
(DLGPROC) PageDialogProc);
@@ -3272,7 +3357,7 @@ static BOOL FinalPreTransformPrompts (void)
if (bHiddenOS && bHiddenVolHost)
StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("OVERWRITEPROMPT_DEVICE_HIDDEN_OS_PARTITION"), szFileName, drive);
else
- StringCbPrintfW (szTmp, sizeof(szTmp), GetString (bInPlaceEncNonSys ? "NONSYS_INPLACE_ENC_CONFIRM" : "OVERWRITEPROMPT_DEVICE"), type, szFileName, drive);
+ StringCbPrintfW (szTmp, sizeof(szTmp), GetString (bInPlaceEncNonSys ? (bInPlaceDecNonSys ? "NONSYS_INPLACE_DEC_CONFIRM" : "NONSYS_INPLACE_ENC_CONFIRM") : "OVERWRITEPROMPT_DEVICE"), type, szFileName, drive);
x = MessageBoxW (MainDlg, szTmp, lpszTitle, YES_NO | MB_ICONWARNING | (bInPlaceEncNonSys ? MB_DEFBUTTON1 : MB_DEFBUTTON2));
@@ -3339,6 +3424,15 @@ static BOOL FinalPreTransformPrompts (void)
return TRUE;
}
+void UpdateLastDialogId (void)
+{
+ static char PageDebugId[128];
+
+ StringCbPrintfA (PageDebugId, sizeof(PageDebugId), "FORMAT_PAGE_%d", nCurPageNo);
+ LastDialogId = PageDebugId;
+}
+
+
void HandleOldAssignedDriveLetter (void)
{
if (bDevice)
@@ -3381,7 +3475,6 @@ static BOOL FileSize4GBLimitQuestionNeeded (void)
not. - see DialogProc */
BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- static char PageDebugId[128];
WORD lw = LOWORD (wParam);
WORD hw = HIWORD (wParam);
@@ -3392,8 +3485,7 @@ BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
case WM_INITDIALOG:
LocalizeDialog (hwndDlg, "IDD_VOL_CREATION_WIZARD_DLG");
- StringCbPrintfA (PageDebugId, sizeof(PageDebugId), "FORMAT_PAGE_%d", nCurPageNo);
- LastDialogId = PageDebugId;
+ UpdateLastDialogId ();
switch (nCurPageNo)
{
@@ -3974,7 +4066,7 @@ BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable);
- SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (bInPlaceEncNonSys ? "NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE_HELP" : "PASSWORD_HIDDENVOL_HOST_DIRECT_HELP"));
+ SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (bInPlaceEncNonSys ? (bInPlaceEncNonSysResumed ? "NONSYS_INPLACE_ENC_RESUME_PASSWORD_PAGE_HELP" : "NONSYS_INPLACE_DEC_PASSWORD_PAGE_HELP") : "PASSWORD_HIDDENVOL_HOST_DIRECT_HELP"));
SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bInPlaceEncNonSys ? "PASSWORD" : "PASSWORD_HIDVOL_HOST_TITLE"));
@@ -4367,7 +4459,7 @@ BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
break;
- case NONSYS_INPLACE_ENC_ENCRYPTION_PAGE:
+ case NONSYS_INPLACE_ENC_TRANSFORM_PAGE:
if (bInPlaceEncNonSysResumed)
{
@@ -4377,19 +4469,19 @@ BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
nWipeMode = savedWipeAlgorithm;
}
- SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("ENCRYPTION"));
+ SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bInPlaceDecNonSys ? "DECRYPTION" : "ENCRYPTION"));
- SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("NONSYS_INPLACE_ENC_ENCRYPTION_PAGE_INFO"));
+ SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (bInPlaceDecNonSys ? "NONSYS_INPLACE_DEC_DECRYPTION_PAGE_INFO" : "NONSYS_INPLACE_ENC_ENCRYPTION_PAGE_INFO"));
SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString (bInPlaceEncNonSysResumed ? "DEFER" : "CANCEL"));
SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV"));
- SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString (bInPlaceEncNonSysResumed ? "RESUME" : "ENCRYPT"));
+ SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString (bInPlaceEncNonSysResumed ? "RESUME" : (bInPlaceDecNonSys ? "DECRYPT" : "ENCRYPT")));
SetWindowTextW (GetDlgItem (hwndDlg, IDC_PAUSE), GetString ("IDC_PAUSE"));
- EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), !bInPlaceEncNonSysResumed);
+ EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), !bInPlaceEncNonSysResumed && !bInPlaceDecNonSys);
EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE);
EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), TRUE);
EnableWindow (GetDlgItem (GetParent (hwndDlg), IDHELP), TRUE);
@@ -4397,19 +4489,28 @@ BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
ShowWindow (GetDlgItem (hwndDlg, IDC_MORE_INFO_SYS_ENCRYPTION), SW_HIDE);
- EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_MODE), TRUE);
- PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), FALSE, TRUE, FALSE);
- SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode);
+ if (bInPlaceDecNonSys)
+ {
+ ShowWindow(GetDlgItem(hwndDlg, IDT_FORMAT_OPTIONS), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDT_WIPE_MODE), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_WIPE_MODE), SW_HIDE);
+ }
+ else
+ {
+ EnableWindow (GetDlgItem (hwndDlg, IDC_WIPE_MODE), TRUE);
+ PopulateWipeModeCombo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), FALSE, TRUE, FALSE);
+ SelectAlgo (GetDlgItem (hwndDlg, IDC_WIPE_MODE), (int *) &nWipeMode);
+ }
break;
- case NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE:
+ case NONSYS_INPLACE_ENC_TRANSFORM_FINISHED_PAGE:
bConfirmQuit = FALSE;
- SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("NONSYS_INPLACE_ENC_FINISHED_TITLE"));
+ SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString (bInPlaceDecNonSys ? "NONSYS_INPLACE_DEC_FINISHED_TITLE" : "NONSYS_INPLACE_ENC_FINISHED_TITLE"));
- SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("NONSYS_INPLACE_ENC_FINISHED_INFO"));
+ SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString (bInPlaceDecNonSys ? "NONSYS_INPLACE_DEC_FINISHED_INFO" : "NONSYS_INPLACE_ENC_FINISHED_INFO"));
SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV"));
SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("FINALIZE"));
@@ -4421,6 +4522,54 @@ BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
break;
+ case NONSYS_INPLACE_DEC_TRANSFORM_FINISHED_DRIVE_LETTER_PAGE:
+
+ SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_BOX_TITLE), GetString ("NONSYS_INPLACE_DEC_FINISHED_TITLE"));
+
+ SetWindowTextW (GetDlgItem (hwndDlg, IDC_BOX_HELP), GetString ("NONSYS_INPLACE_DEC_FINISHED_DRIVE_LETTER_SEL_INFO"));
+
+ SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_PREV), GetString ("PREV"));
+ SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), GetString ("FINALIZE"));
+ EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_PREV), FALSE);
+ EnableWindow (GetDlgItem (GetParent (hwndDlg), IDC_NEXT), TRUE);
+
+ SetWindowTextW (GetDlgItem (GetParent (hwndDlg), IDCANCEL), GetString ("CANCEL"));
+
+ // The Cancel button and the X button must be disabled to prevent the user from forgetting to assign a drive letter to the partition by closing
+ // the window accidentally or clicking Cancel. The user is forced to click Finish to assign at least the pre-selected free drive letter.
+ // This is critical because inexperienced users would not know how to access data on the decrypted volume without a drive letter.
+ EnableWindow (GetDlgItem (GetParent (hwndDlg), IDCANCEL), FALSE);
+ DisableCloseButton (MainDlg);
+ bConfirmQuit = TRUE; // Alt-F4 will still work but the user will be prompted to confirm the action.
+
+ // Decryption of non-system volume finished, no drive letter is assigned to the decrypted volume, and free drive letters are available.
+ // This is critical because inexperienced users would not know how to access data on the decrypted volume. We cannot allow exit
+ // until a drive letter is freed up and assigned to the decrypted volume.
+
+ while (GetFirstAvailableDrive () == -1)
+ {
+ Error ("NONSYS_INPLACE_DEC_FINISHED_NO_DRIVE_LETTER_AVAILABLE", hwndDlg);
+ }
+
+ // Populate the combobox with free drive letters
+ {
+ DWORD dwUsedDrives = GetLogicalDrives();
+ char szDriveLetter[] = {' ', ':', 0 };
+ int i;
+
+ for (i = 0; i < 26; i++)
+ {
+ if (!(dwUsedDrives & 1 << i))
+ {
+ // Add
+ szDriveLetter [0] = (char) (i + 'A');
+ AddComboPair (GetDlgItem (hCurPage, IDC_DRIVE_LETTER_LIST), szDriveLetter, i);
+ }
+ }
+ }
+ SendMessage (GetDlgItem (hwndDlg, IDC_DRIVE_LETTER_LIST), CB_SETCURSEL, 0, 0);
+ break;
+
case FORMAT_PAGE:
{
BOOL bNTFSallowed = FALSE;
@@ -4967,7 +5116,7 @@ BOOL CALLBACK PageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
}
break;
- case NONSYS_INPLACE_ENC_ENCRYPTION_PAGE:
+ case NONSYS_INPLACE_ENC_TRANSFORM_PAGE:
{
switch (lw)
{
@@ -5664,6 +5813,8 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
KillTimer (hwndDlg, TIMER_ID_SYSENC_PROGRESS);
+ UpdateLastDialogId ();
+
try
{
if (BootEncStatus.DriveMounted) // If we had been really encrypting/decrypting (not just proceeding to deinstall)
@@ -5788,6 +5939,8 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
if (!bVolTransformThreadRunning && !bVolTransformThreadToRun)
{
KillTimer (hwndDlg, TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS);
+
+ UpdateLastDialogId ();
}
UpdateNonSysInPlaceEncControls ();
@@ -5927,6 +6080,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
// The driver stopped wiping
KillTimer (hwndDlg, TIMER_ID_WIPE_PROGRESS);
+ UpdateLastDialogId ();
try
{
@@ -6010,8 +6164,29 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
KillTimer (hwndDlg, TIMER_ID_NONSYS_INPLACE_ENC_PROGRESS);
- LoadPage (hwndDlg, NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE);
+ if (bInPlaceDecNonSys)
+ {
+ // Decryption of non-system volume finished and free drive letters are available. Check if a drive letter is assigned to the decrypted volume.
+
+ WCHAR deviceName[MAX_PATH + 1];
+ StringCbCopyA ((char *)deviceName, sizeof(deviceName), szDiskFile);
+ ToUNICODE ((char *)deviceName, sizeof(deviceName));
+
+ if (GetDiskDeviceDriveLetter (deviceName) < 0)
+ {
+ // No drive letter is assigned to the device
+ MessageBeep (MB_OK);
+ LoadPage (hwndDlg, NONSYS_INPLACE_DEC_TRANSFORM_FINISHED_DRIVE_LETTER_PAGE);
+ return 1;
+ }
+ else
+ {
+ Info ("NONSYS_INPLACE_DEC_FINISHED_INFO", hwndDlg);
+ }
+ }
+
+ LoadPage (hwndDlg, NONSYS_INPLACE_ENC_TRANSFORM_FINISHED_PAGE);
return 1;
case TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED:
@@ -6050,7 +6225,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
case TC_APPMSG_FORMAT_USER_QUIT:
- if (nCurPageNo == NONSYS_INPLACE_ENC_ENCRYPTION_PAGE
+ if (nCurPageNo == NONSYS_INPLACE_ENC_TRANSFORM_PAGE
&& (bVolTransformThreadRunning || bVolTransformThreadToRun || bInPlaceEncNonSysResumed))
{
// Non-system encryption in progress
@@ -6970,10 +7145,10 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
}
}
}
- else
+ else if (bInPlaceEncNonSysResumed)
{
/* Scan all available partitions to discover all partitions where non-system in-place
- encryption has been interrupted. */
+ encryption/decryption has been interrupted. */
BOOL tmpbDevice;
@@ -7002,12 +7177,115 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
return 1;
}
- nNewPageNo = NONSYS_INPLACE_ENC_ENCRYPTION_PAGE - 1; // Skip irrelevant pages
+ nNewPageNo = NONSYS_INPLACE_ENC_TRANSFORM_PAGE - 1; // Skip irrelevant pages
}
NormalCursor();
}
+ else
+ {
+ /* Try to mount the non-system volume to decrypt in place (the process has not started yet, we are NOT trying to resume it).
+ We will try to mount it using the backup header, which we require to work (i.e. be non-damaged) before we start writing
+ to the volume (the primary header will be overwritten by decrypted data soon after the decryption process begins, so the
+ backup header will contain the only copy of the master key). */
+
+ int driveNo = -1;
+
+ // The volume may already be mounted. We need to dismount it first in order to verify the supplied password/keyfile(s) is/are correct.
+ if (IsMountedVolume (szFileName))
+ {
+ driveNo = GetMountedVolumeDriveNo (szFileName);
+
+ if (driveNo == -1
+ || !UnmountVolume (hwndDlg, driveNo, TRUE))
+ {
+ handleWin32Error (MainDlg);
+ AbortProcess ("CANT_DISMOUNT_VOLUME");
+ }
+ }
+
+ driveNo = GetLastAvailableDrive ();
+
+ if (driveNo < 0)
+ AbortProcess ("NO_FREE_DRIVES");
+
+ MountOptions mountOptions;
+ ZeroMemory (&mountOptions, sizeof (mountOptions));
+
+ mountOptions.UseBackupHeader = FALSE; // This must be FALSE at this point because otherwise we wouldn't be able to detect a legacy volume
+ mountOptions.ReadOnly = TRUE;
+ mountOptions.Removable = ConfigReadInt ("MountVolumesRemovable", FALSE);
+
+ // Check that it is not a hidden or legacy volume
+
+ if (MountVolume (hwndDlg, driveNo, szFileName, &volumePassword, hash_algo, FALSE, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
+ {
+ NormalCursor();
+ return 1;
+ }
+
+ {
+ DWORD dwResult;
+ VOLUME_PROPERTIES_STRUCT volProp;
+
+ memset (&volProp, 0, sizeof(volProp));
+ volProp.driveNo = driveNo;
+ if (!DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &volProp, sizeof (volProp), &volProp, sizeof (volProp), &dwResult, NULL) || dwResult == 0)
+ {
+ handleWin32Error (hwndDlg);
+ UnmountVolume (hwndDlg, driveNo, TRUE);
+ AbortProcess ("CANT_GET_VOL_INFO");
+ }
+
+ if (volProp.volFormatVersion == TC_VOLUME_FORMAT_VERSION_PRE_6_0)
+ {
+ UnmountVolume (hwndDlg, driveNo, TRUE);
+ AbortProcess ("NONSYS_INPLACE_DECRYPTION_BAD_VOL_FORMAT");
+ }
+
+ if (volProp.hiddenVolume)
+ {
+ UnmountVolume (hwndDlg, driveNo, TRUE);
+ AbortProcess ("NONSYS_INPLACE_DECRYPTION_CANT_DECRYPT_HID_VOL");
+ }
+ }
+
+ // Remount the volume using the backup header to verify it is working
+
+ if (!UnmountVolume (hwndDlg, driveNo, TRUE))
+ {
+ handleWin32Error (MainDlg);
+ AbortProcess ("CANT_DISMOUNT_VOLUME");
+ }
+
+ mountOptions.UseBackupHeader = TRUE; // This must be TRUE at this point (we won't be using the regular header, which will be lost soon after the decryption process starts)
+
+ if (MountVolume (hwndDlg, driveNo, szFileName, &volumePassword, hash_algo, FALSE, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
+ {
+ NormalCursor();
+ return 1;
+ }
+
+ if (!UnmountVolume (hwndDlg, driveNo, TRUE))
+ {
+ handleWin32Error (MainDlg);
+ AbortProcess ("CANT_DISMOUNT_VOLUME");
+ }
+
+ BOOL tmpbDevice;
+
+ CreateFullVolumePath (szDiskFile, sizeof(szDiskFile), szFileName, &tmpbDevice);
+
+ nVolumeSize = GetDeviceSize (szDiskFile);
+ if (nVolumeSize == -1)
+ {
+ handleWin32Error (MainDlg);
+ AbortProcessSilent ();
+ }
+ nNewPageNo = NONSYS_INPLACE_ENC_TRANSFORM_PAGE - 1; // Skip irrelevant pages
+ NormalCursor();
+ }
}
else if (nCurPageNo == FILESYS_PAGE)
@@ -7312,20 +7590,76 @@ retryCDDriveCheck:
}
else if (nCurPageNo == NONSYS_INPLACE_ENC_RESUME_PARTITION_SEL_PAGE)
{
- nNewPageNo = NONSYS_INPLACE_ENC_ENCRYPTION_PAGE - 1; // Skip irrelevant pages
+ nNewPageNo = NONSYS_INPLACE_ENC_TRANSFORM_PAGE - 1; // Skip irrelevant pages
}
- else if (nCurPageNo == NONSYS_INPLACE_ENC_ENCRYPTION_PAGE)
+ else if (nCurPageNo == NONSYS_INPLACE_ENC_TRANSFORM_PAGE)
{
/* In-place encryption start (the 'Next' button has been clicked) */
+ if (bInPlaceDecNonSys
+ && !bInPlaceEncNonSysResumed
+ && AskWarnYesNo ("NONSYS_INPLACE_ENC_CONFIRM_BACKUP", hwndDlg) == IDNO)
+ {
+ // Cancel
+ return 1;
+ }
NonSysInplaceEncResume ();
return 1;
}
- else if (nCurPageNo == NONSYS_INPLACE_ENC_ENCRYPTION_FINISHED_PAGE)
+ else if (nCurPageNo == NONSYS_INPLACE_ENC_TRANSFORM_FINISHED_PAGE)
{
PostMessage (hwndDlg, TC_APPMSG_FORMAT_USER_QUIT, 0, 0);
return 1;
}
+ else if (nCurPageNo == NONSYS_INPLACE_DEC_TRANSFORM_FINISHED_DRIVE_LETTER_PAGE)
+ {
+ BOOL bDrvLetterAssignResult = FALSE;
+
+ int tmpDriveLetter = (int) SendMessage (GetDlgItem (hCurPage, IDC_DRIVE_LETTER_LIST),
+ CB_GETITEMDATA,
+ SendMessage (GetDlgItem (hCurPage, IDC_DRIVE_LETTER_LIST), CB_GETCURSEL, 0, 0),
+ 0);
+
+ if (tmpDriveLetter < 0)
+ tmpDriveLetter = GetFirstAvailableDrive ();
+
+ do
+ {
+ char szDriveLetter[] = {'A', ':', 0 };
+ char rootPath[] = {'A', ':', '\\', 0 };
+ char uniqVolName[MAX_PATH+1] = { 0 };
+
+ rootPath[0] += (char) tmpDriveLetter;
+ szDriveLetter[0] += (char) tmpDriveLetter;
+
+ if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, szDiskFile))
+ {
+ bDrvLetterAssignResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH);
+
+ DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
+ szDriveLetter,
+ szDiskFile);
+
+ if (bDrvLetterAssignResult)
+ {
+ if (SetVolumeMountPoint (rootPath, uniqVolName) == 0)
+ bDrvLetterAssignResult = FALSE;
+ }
+ }
+
+ if (!bDrvLetterAssignResult)
+ {
+ if (AskErrYesNo ("ERR_CANNOT_ASSIGN_DRIVE_LETTER_NONSYS_DEC", hwndDlg) == IDNO)
+ break;
+ }
+
+ } while (bDrvLetterAssignResult == FALSE);
+
+ bConfirmQuit = FALSE;
+
+ PostMessage (hwndDlg, TC_APPMSG_FORMAT_USER_QUIT, 0, 0);
+ return 1;
+ }
else if (nCurPageNo == FORMAT_PAGE)
{
/* Format start (the 'Next' button has been clicked on the Format page) */
@@ -7906,26 +8240,33 @@ void ExtractCommandLine (HWND hwndDlg, char *lpszCommandLine)
CommandDecryptSysEnc,
CommandEncDev,
CommandHiddenSys,
- CommandResumeInplaceLogOn,
+ CommandResumeNonSysInplaceLogOn,
CommandResumeHiddenSys,
CommandSysEnc,
+ CommandInplaceDec,
+ CommandResumeInplaceDec,
CommandResumeInplace,
};
argument args[]=
{
+ // Public
{ OptionHistory, "/history", "/h", FALSE },
{ OptionNoIsoCheck, "/noisocheck", "/n", FALSE },
{ OptionTokenLib, "/tokenlib", NULL, FALSE },
{ OptionQuit, "/quit", "/q", FALSE },
+
+ // Internal
{ CommandResumeSysEncLogOn, "/acsysenc", "/a", TRUE },
{ CommandResumeSysEnc, "/csysenc", "/c", TRUE },
{ CommandDecryptSysEnc, "/dsysenc", "/d", TRUE },
{ CommandEncDev, "/encdev", "/e", TRUE },
{ CommandHiddenSys, "/isysenc", "/i", TRUE },
- { CommandResumeInplaceLogOn, "/prinplace", "/p", TRUE },
+ { CommandResumeNonSysInplaceLogOn, "/prinplace", "/p", TRUE },
{ CommandResumeHiddenSys, "/risysenc", "/r", TRUE },
{ CommandSysEnc, "/sysenc", "/s", TRUE },
+ { CommandInplaceDec, "/inplacedec", NULL, TRUE },
+ { CommandResumeInplaceDec, "/resumeinplacedec",NULL, TRUE },
{ CommandResumeInplace, "/zinplace", "/z", TRUE }
};
@@ -8053,12 +8394,36 @@ void ExtractCommandLine (HWND hwndDlg, char *lpszCommandLine)
DirectDeviceEncMode = TRUE;
break;
+ case CommandInplaceDec:
+ // Start (not resume) decrypting the specified non-system volume in place
+ {
+ char szTmp [TC_MAX_PATH + 8000] = {0};
+
+ GetArgumentValue (lpszCommandLineArgs, &i, nNoCommandLineArgs, szTmp, sizeof (szTmp));
+
+ if (strlen (szTmp) < 1)
+ {
+ // No valid volume path specified as command-line parameter
+ AbortProcess ("ERR_PARAMETER_INCORRECT");
+ }
+
+ memset (szFileName, 0, sizeof (szFileName));
+ StringCbCopyA (szFileName, sizeof (szFileName), szTmp);
+ DirectNonSysInplaceDecStartMode = TRUE;
+ }
+ break;
+
case CommandResumeInplace:
// Resume interrupted process of non-system in-place encryption of a partition
DirectNonSysInplaceEncResumeMode = TRUE;
break;
- case CommandResumeInplaceLogOn:
+ case CommandResumeInplaceDec:
+ // Resume interrupted process of non-system in-place decryption of a partition
+ DirectNonSysInplaceDecResumeMode = TRUE;
+ break;
+
+ case CommandResumeNonSysInplaceLogOn:
// Ask the user whether to resume interrupted process of non-system in-place encryption of a partition
// This switch is passed only by the system (from the startup sequence).
DirectPromptNonSysInplaceEncResumeMode = TRUE;
@@ -8641,7 +9006,7 @@ static void AfterWMInitTasks (HWND hwndDlg)
else
{
// Nothing to resume
- Warning ("NOTHING_TO_RESUME", hwndDlg);
+ Warning ("NO_SYS_ENC_PROCESS_TO_RESUME", hwndDlg);
EndMainDlg (MainDlg);
return;
@@ -8985,7 +9350,7 @@ static void AfterWMInitTasks (HWND hwndDlg)
&& !bInPlaceEncNonSysPending)
{
// This instance of the wizard has been launched via the system startup sequence to prompt for resume of
- // a non-system in-place encryption process. However, no config file indicates that any such process
+ // a non-system in-place encryption/decryption process. However, no config file indicates that any such process
// has been interrupted. This inconsistency may occur, for example, when the process is finished
// but the wizard is not removed from the startup sequence because system encryption is in progress.
// Therefore, we remove it from the startup sequence now if possible.
@@ -8996,9 +9361,16 @@ static void AfterWMInitTasks (HWND hwndDlg)
AbortProcessSilent ();
}
- if (DirectNonSysInplaceEncResumeMode)
+ BOOL bDecrypt = FALSE;
+
+ if (DirectNonSysInplaceDecStartMode)
+ {
+ SwitchWizardToNonSysInplaceDecStartMode (szFileName);
+ return;
+ }
+ else if (DirectNonSysInplaceEncResumeMode || DirectNonSysInplaceDecResumeMode)
{
- SwitchWizardToNonSysInplaceEncResumeMode();
+ SwitchWizardToNonSysInplaceEncResumeMode (DirectNonSysInplaceDecResumeMode);
return;
}
else if (DirectPromptNonSysInplaceEncResumeMode)
@@ -9006,8 +9378,8 @@ static void AfterWMInitTasks (HWND hwndDlg)
if (NonSysInplaceEncInProgressElsewhere ())
AbortProcessSilent ();
- if (AskNonSysInPlaceEncryptionResume(hwndDlg) == IDYES)
- SwitchWizardToNonSysInplaceEncResumeMode();
+ if (AskNonSysInPlaceEncryptionResume(hwndDlg, &bDecrypt) == IDYES)
+ SwitchWizardToNonSysInplaceEncResumeMode(bDecrypt);
else
AbortProcessSilent ();
@@ -9015,9 +9387,9 @@ static void AfterWMInitTasks (HWND hwndDlg)
}
else if (bInPlaceEncNonSysPending
&& !NonSysInplaceEncInProgressElsewhere ()
- && AskNonSysInPlaceEncryptionResume(hwndDlg) == IDYES)
+ && AskNonSysInPlaceEncryptionResume(hwndDlg, &bDecrypt) == IDYES)
{
- SwitchWizardToNonSysInplaceEncResumeMode();
+ SwitchWizardToNonSysInplaceEncResumeMode(bDecrypt);
return;
}
diff --git a/src/Format/Tcformat.h b/src/Format/Tcformat.h
index 77579f54..15a81534 100644
--- a/src/Format/Tcformat.h
+++ b/src/Format/Tcformat.h
@@ -42,6 +42,7 @@ void DisplaySizingErrorText ( HWND hwndTextBox );
void EnableDisableFileNext ( HWND hComboBox , HWND hMainButton );
BOOL QueryFreeSpace ( HWND hwndDlg , HWND hwndTextBox , BOOL display );
static BOOL FinalPreTransformPrompts (void);
+void UpdateLastDialogId (void);
void HandleOldAssignedDriveLetter (void);
void AddCipher ( HWND hComboBox , char *lpszCipher , int nCipher );
BOOL CALLBACK PageDialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam );
@@ -90,6 +91,7 @@ extern volatile BOOL bVolTransformThreadCancel;
extern volatile BOOL bInPlaceEncNonSysResumed;
extern volatile BOOL bFirstNonSysInPlaceEncResumeDone;
extern volatile BOOL bInPlaceEncNonSys;
+extern volatile BOOL bInPlaceDecNonSys;
extern __int64 NonSysInplaceEncBytesDone;
extern __int64 NonSysInplaceEncTotalSize;
extern int nPbar;