diff options
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, |