diff options
author | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2023-07-01 15:16:46 +0200 |
---|---|---|
committer | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2023-07-01 15:16:46 +0200 |
commit | 0bfed6553d08131fd8e0bd725642ff8509a2a1d4 (patch) | |
tree | a4325dd52e48b00eea5dfcd5dcb37c29f06c156d /src/Common/Format.c | |
parent | 17dcd73936a99105c736477a9f49f2ac606440dc (diff) | |
download | VeraCrypt-0bfed6553d08131fd8e0bd725642ff8509a2a1d4.tar.gz VeraCrypt-0bfed6553d08131fd8e0bd725642ff8509a2a1d4.zip |
Windows: Fix formatting issue during volume creation by using /Y for format.com and specifying removal parameter in FormatEx
The usage of /Y parameter in format.com simplifies the logic and makes the code robust since we don't need to send \n to the format.com process.
Specifying RemovableMedia parameter to FormatEx fixes its failure in Windows 10 and later to perform quick format. This is also more adequate since we are mounting the volume as removable media for the formatting process.
We also add better error management in order to display adequate error message to the user in case of failure
Diffstat (limited to 'src/Common/Format.c')
-rw-r--r-- | src/Common/Format.c | 104 |
1 files changed, 76 insertions, 28 deletions
diff --git a/src/Common/Format.c b/src/Common/Format.c index 15ca9518..d5514bf9 100644 --- a/src/Common/Format.c +++ b/src/Common/Format.c @@ -797,16 +797,26 @@ error: } retCode = ExternalFormatFs (driveNo, volParams->clusterSize, fsType); - if (retCode != TRUE) + if (retCode != 0) { + wchar_t auxLine[2048]; + StringCbPrintfW (auxLine, sizeof(auxLine), GetString ("FORMAT_EXTERNAL_FAILED"), retCode); + WarningDirect(auxLine, volParams->hwndDlg); + /* fallback to using FormatEx function from fmifs.dll */ if (!Silent && !IsAdmin () && IsUacSupported ()) retCode = UacFormatFs (volParams->hwndDlg, driveNo, volParams->clusterSize, fsType); else retCode = FormatFs (driveNo, volParams->clusterSize, fsType); + + if (retCode != 0) + { + StringCbPrintfW (auxLine, sizeof(auxLine), GetString ("FORMATEX_API_FAILED"), FormatExGetMessage(retCode)); + ErrorDirect(auxLine, volParams->hwndDlg); + } } - if (retCode != TRUE) + if (retCode != 0) { if (!UnmountVolumeAfterFormatExCall (volParams->hwndDlg, driveNo) && !Silent) MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND); @@ -1030,6 +1040,46 @@ fail: volatile BOOLEAN FormatExError; +volatile int FormatExErrorCommand; + +LPCWSTR FormatExGetMessage (int command) +{ + static WCHAR h_szMsg[32]; + switch (command) + { + case FMIFS_DONE: + return L"FORMAT_FINISHED"; + case FMIFS_STRUCTURE_PROGRESS: + return L"FORMAT_STRUCTURE_PROGRESS"; + case FMIFS_MEDIA_WRITE_PROTECTED: + return L"FORMAT_MEDIA_WRITE_PROTECTED"; + case FMIFS_INCOMPATIBLE_FILE_SYSTEM: + return L"FORMAT_INCOMPATIBLE_FILE_SYSTEM"; + case FMIFS_ACCESS_DENIED: + return L"FORMAT_ACCESS_DENIED"; + case FMIFS_VOLUME_IN_USE: + return L"FORMAT_VOLUME_IN_USE"; + case FMIFS_CLUSTER_SIZE_TOO_SMALL: + return L"FORMAT_CLUSTER_SIZE_TOO_SMALL"; + case FMIFS_CLUSTER_SIZE_TOO_BIG: + return L"FORMAT_CLUSTER_SIZE_TOO_BIG"; + case FMIFS_VOLUME_TOO_SMALL: + return L"FORMAT_VOLUME_TOO_SMALL"; + case FMIFS_VOLUME_TOO_BIG: + return L"FORMAT_VOLUME_TOO_BIG"; + case FMIFS_NO_MEDIA_IN_DRIVE: + return L"FORMAT_NO_MEDIA_IN_DRIVE"; + case FMIFS_DEVICE_NOT_READY: + return L"FORMAT_DEVICE_NOT_READY"; + case FMIFS_BAD_LABEL: + return L"FORMAT_BAD_LABEL"; + case FMIFS_CANT_QUICK_FORMAT: + return L"FORMAT_CANT_QUICK_FORMAT"; + default: + StringCbPrintfW (h_szMsg, sizeof(h_szMsg), L"0x%.8X", command); + return h_szMsg; + } +} BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter) { @@ -1086,10 +1136,14 @@ BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID paramet FormatExError = TRUE; break; } + if (FormatExError) + { + FormatExErrorCommand = command; + } return (FormatExError? FALSE : TRUE); } -BOOL FormatFs (int driveNo, int clusterSize, int fsType) +int FormatFs (int driveNo, int clusterSize, int fsType) { wchar_t dllPath[MAX_PATH] = {0}; WCHAR dir[8] = { (WCHAR) driveNo + L'A', 0 }; @@ -1135,29 +1189,31 @@ BOOL FormatFs (int driveNo, int clusterSize, int fsType) StringCchCatW (dir, ARRAYSIZE(dir), L":\\"); FormatExError = TRUE; + FormatExErrorCommand = 0; // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS. // It often helps to retry several times. for (i = 0; i < 50 && FormatExError; i++) { FormatExError = FALSE; - FormatEx (dir, FMIFS_HARDDISK, szFsFormat, szLabel, TRUE, clusterSize * FormatSectorSize, FormatExCallback); + FormatExErrorCommand = 0; + FormatEx (dir, FMIFS_REMOVAL, szFsFormat, szLabel, TRUE, clusterSize * FormatSectorSize, FormatExCallback); } // The device may be referenced for some time after FormatEx() returns Sleep (4000); FreeLibrary (hModule); - return FormatExError? FALSE : TRUE; + return FormatExError? FormatExErrorCommand : 0; } -BOOL FormatNtfs (int driveNo, int clusterSize) +int FormatNtfs (int driveNo, int clusterSize) { return FormatFs (driveNo, clusterSize, FILESYS_NTFS); } /* call Windows format.com program to perform formatting */ -BOOL ExternalFormatFs (int driveNo, int clusterSize, int fsType) +int ExternalFormatFs (int driveNo, int clusterSize, int fsType) { wchar_t exePath[MAX_PATH] = {0}; HANDLE hChildStd_IN_Rd = NULL; @@ -1170,6 +1226,7 @@ BOOL ExternalFormatFs (int driveNo, int clusterSize, int fsType) PROCESS_INFORMATION piProcInfo; BOOL bSuccess = FALSE; SECURITY_ATTRIBUTES saAttr; + int iRet = 0; switch (fsType) { @@ -1222,7 +1279,7 @@ BOOL ExternalFormatFs (int driveNo, int clusterSize, int fsType) else StringCchCopyW(exePath, ARRAYSIZE(exePath), L"C:\\Windows\\System32\\format.com"); - StringCbPrintf (szCmdline, sizeof(szCmdline), L"%s %c: /FS:%s /Q /X /V:\"\"", exePath, (WCHAR) driveNo + L'A', szFsFormat); + StringCbPrintf (szCmdline, sizeof(szCmdline), L"%s %c: /FS:%s /Q /X /V:\"\" /Y", exePath, (WCHAR) driveNo + L'A', szFsFormat); if (clusterSize) { @@ -1269,42 +1326,33 @@ BOOL ExternalFormatFs (int driveNo, int clusterSize, int fsType) if (bSuccess) { - /* Unblock the format process by simulating hit on ENTER key */ - DWORD dwExitCode, dwWritten; - LPCSTR newLine = "\n"; - - if (WriteFile(hChildStd_IN_Wr, (LPCVOID) newLine, 1, &dwWritten, NULL)) - { - /* wait for the format process to finish */ - WaitForSingleObject (piProcInfo.hProcess, INFINITE); - } - else - { - /* we failed to write "\n". Maybe process exited too quickly. We wait 1 second */ - WaitForSingleObject (piProcInfo.hProcess, 1000); - } + DWORD dwExitCode; + + /* wait for the format process to finish */ + WaitForSingleObject (piProcInfo.hProcess, INFINITE); /* check if it was successfull */ if (GetExitCodeProcess (piProcInfo.hProcess, &dwExitCode)) { - if (dwExitCode == 0) - bSuccess = TRUE; - else - bSuccess = FALSE; + iRet = (int) dwExitCode; /* dwExitCode will be 0 in case of success */ } else - bSuccess = FALSE; + iRet = (int) GetLastError(); CloseHandle (piProcInfo.hThread); CloseHandle (piProcInfo.hProcess); } + else + { + iRet = (int) GetLastError(); + } CloseHandle(hChildStd_OUT_Wr); CloseHandle(hChildStd_OUT_Rd); CloseHandle(hChildStd_IN_Rd); CloseHandle(hChildStd_IN_Wr); - return bSuccess; + return iRet; } BOOL WriteSector (void *dev, char *sector, |