1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2025-11-11 11:08:02 -06:00

Windows: Fallback to Windows native formatting tool if we fail to format a volume as NTFS/exFAT/ReFS using FormatEx function from fmifs.dll

This commit is contained in:
Mounir IDRASSI
2020-06-29 00:45:24 +02:00
parent 7ee5c671e9
commit 14fa3de4b6
2 changed files with 153 additions and 2 deletions

View File

@@ -762,7 +762,7 @@ error:
}
mountOptions.ReadOnly = FALSE;
mountOptions.Removable = FALSE;
mountOptions.Removable = TRUE; /* mount as removal media to allow formatting without admin rights */
mountOptions.ProtectHiddenVolume = FALSE;
mountOptions.PreserveTimestamp = bPreserveTimestamp;
mountOptions.PartitionInInactiveSysEncScope = FALSE;
@@ -778,12 +778,18 @@ error:
nStatus = ERR_VOL_MOUNT_FAILED;
goto fv_end;
}
if (!Silent && !IsAdmin () && IsUacSupported ())
retCode = UacFormatFs (volParams->hwndDlg, driveNo, volParams->clusterSize, fsType);
else
retCode = FormatFs (driveNo, volParams->clusterSize, fsType);
if (retCode != TRUE)
{
/* fallback to calling Windows native formatting tool */
retCode = ExternalFormatFs (driveNo, volParams->clusterSize, fsType);
}
if (retCode != TRUE)
{
if (!UnmountVolumeAfterFormatExCall (volParams->hwndDlg, driveNo) && !Silent)
@@ -1094,6 +1100,150 @@ BOOL FormatNtfs (int driveNo, int clusterSize)
return FormatFs (driveNo, clusterSize, FILESYS_NTFS);
}
/* call Windows format.com program to perform formatting */
BOOL ExternalFormatFs (int driveNo, int clusterSize, int fsType)
{
wchar_t exePath[MAX_PATH] = {0};
HANDLE hChildStd_IN_Rd = NULL;
HANDLE hChildStd_IN_Wr = NULL;
HANDLE hChildStd_OUT_Rd = NULL;
HANDLE hChildStd_OUT_Wr = NULL;
WCHAR szFsFormat[16];
TCHAR szCmdline[2 * MAX_PATH];
STARTUPINFO siStartInfo;
PROCESS_INFORMATION piProcInfo;
BOOL bSuccess = FALSE;
SECURITY_ATTRIBUTES saAttr;
switch (fsType)
{
case FILESYS_NTFS:
StringCchCopyW (szFsFormat, ARRAYSIZE (szFsFormat),L"NTFS");
break;
case FILESYS_EXFAT:
StringCchCopyW (szFsFormat, ARRAYSIZE (szFsFormat),L"exFAT");
break;
case FILESYS_REFS:
StringCchCopyW (szFsFormat, ARRAYSIZE (szFsFormat),L"ReFS");
break;
default:
return FALSE;
}
/* Set the bInheritHandle flag so pipe handles are inherited. */
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
/* Create a pipe for the child process's STDOUT. */
if ( !CreatePipe(&hChildStd_OUT_Rd, &hChildStd_OUT_Wr, &saAttr, 0) )
return FALSE;
/* Ensure the read handle to the pipe for STDOUT is not inherited. */
/* Create a pipe for the child process's STDIN. */
if ( !SetHandleInformation(hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)
|| !CreatePipe(&hChildStd_IN_Rd, &hChildStd_IN_Wr, &saAttr, 0))
{
CloseHandle (hChildStd_OUT_Rd);
CloseHandle (hChildStd_OUT_Wr);
return FALSE;
}
/* Ensure the write handle to the pipe for STDIN is not inherited. */
if ( !SetHandleInformation(hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
{
CloseHandle (hChildStd_OUT_Rd);
CloseHandle (hChildStd_OUT_Wr);
CloseHandle (hChildStd_IN_Rd);
CloseHandle (hChildStd_IN_Wr);
return FALSE;
}
if (GetSystemDirectory (exePath, MAX_PATH))
{
StringCchCatW(exePath, ARRAYSIZE(exePath), L"\\format.com");
}
else
StringCchCopyW(exePath, ARRAYSIZE(exePath), L"C:\\Windows\\System32\\format.com");
StringCbPrintf (szCmdline, sizeof(szCmdline), L"%s %c: /FS:%s /Q /X /V:\"\"", exePath, (WCHAR) driveNo + L'A', szFsFormat);
if (clusterSize)
{
WCHAR szSize[8];
uint32 unitSize = (uint32) clusterSize * FormatSectorSize;
if (unitSize <= 8192)
StringCbPrintf (szSize, sizeof (szSize), L"%d", unitSize);
else if (unitSize < BYTES_PER_MB)
{
StringCbPrintf (szSize, sizeof (szSize), L"%dK", unitSize / BYTES_PER_KB);
}
else
StringCbPrintf (szSize, sizeof (szSize), L"%dM", unitSize / BYTES_PER_MB);
StringCbCat (szCmdline, sizeof (szCmdline), L" /A:");
StringCbCat (szCmdline, sizeof (szCmdline), szSize);
}
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
/* Set up members of the STARTUPINFO structure.
This structure specifies the STDIN and STDOUT handles for redirection.
*/
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hChildStd_OUT_Wr;
siStartInfo.hStdOutput = hChildStd_OUT_Wr;
siStartInfo.hStdInput = hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
/* Create the child process. */
bSuccess = CreateProcess(NULL,
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if (bSuccess)
{
/* Unblock the format process by simulating hit on ENTER key */
DWORD dwExitCode, dwWritten;
LPCSTR newLine = "\n";
WriteFile(hChildStd_IN_Wr, (LPCVOID) newLine, 1, &dwWritten, NULL);
/* wait for the format process to finish */
WaitForSingleObject (piProcInfo.hProcess, INFINITE);
/* check if it was successfull */
if (GetExitCodeProcess (piProcInfo.hProcess, &dwExitCode))
{
if (dwExitCode == 0)
bSuccess = TRUE;
else
bSuccess = FALSE;
}
else
bSuccess = FALSE;
CloseHandle (piProcInfo.hThread);
CloseHandle (piProcInfo.hProcess);
}
CloseHandle(hChildStd_OUT_Wr);
CloseHandle(hChildStd_OUT_Rd);
CloseHandle(hChildStd_IN_Rd);
CloseHandle(hChildStd_IN_Wr);
return bSuccess;
}
BOOL WriteSector (void *dev, char *sector,
char *write_buf, int *write_buf_cnt,
__int64 *nSecNo, PCRYPTO_INFO cryptoInfo)

View File

@@ -76,6 +76,7 @@ extern int FormatWriteBufferSize;
int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams);
BOOL FormatNtfs (int driveNo, int clusterSize);
BOOL FormatFs (int driveNo, int clusterSize, int fsType);
BOOL ExternalFormatFs (int driveNo, int clusterSize, int fsType);
uint64 GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize);
int FormatNoFs (HWND hwndDlg, unsigned __int64 startSector, __int64 num_sectors, void *dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat);
BOOL WriteSector ( void *dev , char *sector , char *write_buf , int *write_buf_cnt , __int64 *nSecNo , PCRYPTO_INFO cryptoInfo );