From f72125ea71f98d0147bb742b48d1097844949c9e Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 17 May 2015 12:14:58 +0200 Subject: Windows: First implementation of non-system volumes decryption. --- src/Format/Format.rc | 19 +- src/Format/InPlace.c | 578 +++++++++++++++++++++++++++++++++++++++++++++++++- src/Format/InPlace.h | 5 +- src/Format/Resource.h | 7 +- src/Format/Tcformat.c | 488 +++++++++++++++++++++++++++++++++++++----- src/Format/Tcformat.h | 2 + 6 files changed, 1029 insertions(+), 70 deletions(-) (limited to 'src/Format') 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; -- cgit v1.2.3