Windows: Make API formatting fallback to format.com in case of elevation. remove dead code from ExternalFormatFs

We also modify UacFormatNtfs/UacFormatFs to return actual error code in case of failure
This commit is contained in:
Mounir IDRASSI 2023-07-01 22:46:01 +02:00
parent e28de414e0
commit 7a3daa389c
No known key found for this signature in database
GPG Key ID: 02C30AE90FAE4A6F
3 changed files with 24 additions and 57 deletions

View File

@ -45,12 +45,13 @@ HRESULT CreateElevatedComObject (HWND hwnd, REFGUID guid, REFIID iid, void **ppv
BOOL ComGetInstanceBase (HWND hWnd, REFCLSID clsid, REFIID iid, void **tcServer) BOOL ComGetInstanceBase (HWND hWnd, REFCLSID clsid, REFIID iid, void **tcServer)
{ {
BOOL r; BOOL r;
HRESULT hr;
if (IsUacSupported ()) if (IsUacSupported ())
{ {
while (true) while (true)
{ {
r = CreateElevatedComObject (hWnd, clsid, iid, tcServer) == S_OK; r = (hr = CreateElevatedComObject (hWnd, clsid, iid, tcServer)) == S_OK;
if (r) if (r)
break; break;
else else
@ -64,11 +65,16 @@ BOOL ComGetInstanceBase (HWND hWnd, REFCLSID clsid, REFIID iid, void **tcServer)
} }
else else
{ {
r = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER, iid, tcServer) == S_OK; r = (hr = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER, iid, tcServer)) == S_OK;
if (!r) if (!r)
Error ("UAC_INIT_ERROR", hWnd); Error ("UAC_INIT_ERROR", hWnd);
} }
if (!r)
{
SetLastError((DWORD) hr);
}
return r; return r;
} }

View File

@ -799,18 +799,16 @@ error:
retCode = ExternalFormatFs (driveNo, volParams->clusterSize, fsType); retCode = ExternalFormatFs (driveNo, volParams->clusterSize, fsType);
if (retCode != 0) 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 */ /* fallback to using FormatEx function from fmifs.dll */
if (!Silent && !IsAdmin () && IsUacSupported ()) if (!Silent && !IsAdmin () && IsUacSupported ())
retCode = UacFormatFs (volParams->hwndDlg, driveNo, volParams->clusterSize, fsType); retCode = UacFormatFs (volParams->hwndDlg, driveNo, volParams->clusterSize, fsType);
else else
retCode = FormatFs (driveNo, volParams->clusterSize, fsType); retCode = FormatFs (driveNo, volParams->clusterSize, fsType, FALSE); /* no need to fallback to format.com since we have already tried it without elevation */
if (retCode != 0) if (retCode != 0)
{ {
wchar_t auxLine[2048];
StringCbPrintfW (auxLine, sizeof(auxLine), GetString ("FORMATEX_API_FAILED"), FormatExGetMessage(retCode)); StringCbPrintfW (auxLine, sizeof(auxLine), GetString ("FORMATEX_API_FAILED"), FormatExGetMessage(retCode));
ErrorDirect(auxLine, volParams->hwndDlg); ErrorDirect(auxLine, volParams->hwndDlg);
} }
@ -1143,7 +1141,7 @@ BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID paramet
return (FormatExError? FALSE : TRUE); return (FormatExError? FALSE : TRUE);
} }
int FormatFs (int driveNo, int clusterSize, int fsType) int FormatFs (int driveNo, int clusterSize, int fsType, BOOL bFallBackExternal)
{ {
wchar_t dllPath[MAX_PATH] = {0}; wchar_t dllPath[MAX_PATH] = {0};
WCHAR dir[8] = { (WCHAR) driveNo + L'A', 0 }; WCHAR dir[8] = { (WCHAR) driveNo + L'A', 0 };
@ -1204,28 +1202,29 @@ int FormatFs (int driveNo, int clusterSize, int fsType)
Sleep (4000); Sleep (4000);
FreeLibrary (hModule); FreeLibrary (hModule);
if (FormatExError && bFallBackExternal)
{
return ExternalFormatFs (driveNo, clusterSize, fsType);
}
return FormatExError? FormatExErrorCommand : 0; return FormatExError? FormatExErrorCommand : 0;
} }
int FormatNtfs (int driveNo, int clusterSize) int FormatNtfs (int driveNo, int clusterSize, BOOL bFallBackExternal)
{ {
return FormatFs (driveNo, clusterSize, FILESYS_NTFS); return FormatFs (driveNo, clusterSize, FILESYS_NTFS, bFallBackExternal);
} }
/* call Windows format.com program to perform formatting */ /* call Windows format.com program to perform formatting */
int ExternalFormatFs (int driveNo, int clusterSize, int fsType) int ExternalFormatFs (int driveNo, int clusterSize, int fsType)
{ {
wchar_t exePath[MAX_PATH] = {0}; 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]; WCHAR szFsFormat[16];
TCHAR szCmdline[2 * MAX_PATH]; TCHAR szCmdline[2 * MAX_PATH];
STARTUPINFO siStartInfo; STARTUPINFO siStartInfo;
PROCESS_INFORMATION piProcInfo; PROCESS_INFORMATION piProcInfo;
BOOL bSuccess = FALSE; BOOL bSuccess = FALSE;
SECURITY_ATTRIBUTES saAttr;
int iRet = 0; int iRet = 0;
switch (fsType) switch (fsType)
@ -1243,35 +1242,6 @@ int ExternalFormatFs (int driveNo, int clusterSize, int fsType)
return FALSE; 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)) if (GetSystemDirectory (exePath, MAX_PATH))
{ {
StringCchCatW(exePath, ARRAYSIZE(exePath), L"\\format.com"); StringCchCatW(exePath, ARRAYSIZE(exePath), L"\\format.com");
@ -1302,15 +1272,11 @@ int ExternalFormatFs (int driveNo, int clusterSize, int fsType)
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
/* Set up members of the STARTUPINFO structure. /* Set up members of the STARTUPINFO structure.
This structure specifies the STDIN and STDOUT handles for redirection.
*/ */
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hChildStd_OUT_Wr;
siStartInfo.hStdOutput = hChildStd_OUT_Wr;
siStartInfo.hStdInput = hChildStd_IN_Rd;
siStartInfo.wShowWindow = SW_HIDE; siStartInfo.wShowWindow = SW_HIDE;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; siStartInfo.dwFlags |= STARTF_USESHOWWINDOW;
/* Create the child process. */ /* Create the child process. */
bSuccess = CreateProcess(NULL, bSuccess = CreateProcess(NULL,
@ -1347,11 +1313,6 @@ int ExternalFormatFs (int driveNo, int clusterSize, int fsType)
iRet = (int) GetLastError(); iRet = (int) GetLastError();
} }
CloseHandle(hChildStd_OUT_Wr);
CloseHandle(hChildStd_OUT_Rd);
CloseHandle(hChildStd_IN_Rd);
CloseHandle(hChildStd_IN_Wr);
return iRet; return iRet;
} }

View File

@ -92,7 +92,7 @@ public:
virtual BOOL STDMETHODCALLTYPE FormatNtfs (int driveNo, int clusterSize) virtual BOOL STDMETHODCALLTYPE FormatNtfs (int driveNo, int clusterSize)
{ {
return ::FormatNtfs (driveNo, clusterSize); return ::FormatNtfs (driveNo, clusterSize, TRUE);
} }
virtual int STDMETHODCALLTYPE AnalyzeHiddenVolumeHost ( virtual int STDMETHODCALLTYPE AnalyzeHiddenVolumeHost (
@ -134,7 +134,7 @@ public:
virtual BOOL STDMETHODCALLTYPE FormatFs (int driveNo, int clusterSize, int fsType) virtual BOOL STDMETHODCALLTYPE FormatFs (int driveNo, int clusterSize, int fsType)
{ {
return ::FormatFs (driveNo, clusterSize, fsType); return ::FormatFs (driveNo, clusterSize, fsType, TRUE);
} }
virtual DWORD STDMETHODCALLTYPE GetFileSize (BSTR filePath, unsigned __int64 *pSize) virtual DWORD STDMETHODCALLTYPE GetFileSize (BSTR filePath, unsigned __int64 *pSize)
@ -250,7 +250,7 @@ extern "C" int UacFormatNtfs (HWND hWnd, int driveNo, int clusterSize)
if (ComGetInstance (hWnd, &tc)) if (ComGetInstance (hWnd, &tc))
r = tc->FormatNtfs (driveNo, clusterSize); r = tc->FormatNtfs (driveNo, clusterSize);
else else
r = 0; r = (int) GetLastError();
CoUninitialize (); CoUninitialize ();
@ -267,7 +267,7 @@ extern "C" int UacFormatFs (HWND hWnd, int driveNo, int clusterSize, int fsType)
if (ComGetInstance (hWnd, &tc)) if (ComGetInstance (hWnd, &tc))
r = tc->FormatFs (driveNo, clusterSize, fsType); r = tc->FormatFs (driveNo, clusterSize, fsType);
else else
r = 0; r = (int) GetLastError();
CoUninitialize (); CoUninitialize ();