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/Tcformat.c | 488 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 430 insertions(+), 58 deletions(-) (limited to 'src/Format/Tcformat.c') 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; } -- cgit v1.2.3