/*++ Copyright (c) 1999 Microsoft Corporation Module Name: format.cpp Abstract: Routines to format volumes, using file-system information passed in. Uses undocumented fmifs calls. Authors: Steve DeVos (Veritas) (v-stevde) 15-May-1998 Guhan Suriyanarayanan (guhans) 21-Aug-1999 Environment: User-mode only. Revision History: 15-May-1998 v-stevde Initial creation 21-Aug-1999 guhans Cleaned up and re-wrote this module. --*/ #include "stdafx.h" #include #include "fmifs.h" #include "asr_fmt.h" #include "asr_dlg.h" BOOL g_bFormatInProgress = FALSE; BOOL g_bFormatSuccessful = FALSE; INT g_iFormatPercentComplete = 0; HINSTANCE g_hIfsDll = NULL; INT FormatVolumeThread(PASRFMT_VOLUME_INFO pVolume); PFMIFS_FORMATEX_ROUTINE g_FormatRoutineEx = NULL; BOOL FormatInitialise() { // // Loadlib if needed // if (!g_hIfsDll) { g_hIfsDll = LoadLibrary(L"fmifs.dll"); if (!g_hIfsDll) { // // FMIFS not available // return FALSE; } g_FormatRoutineEx = (PFMIFS_FORMATEX_ROUTINE)GetProcAddress(g_hIfsDll, "FormatEx"); if (!g_FormatRoutineEx) { return FALSE; } } return TRUE; } BOOL IsFsTypeOkay( IN PASRFMT_VOLUME_INFO pVolume, OUT PBOOL pIsLabelIntact ) { WCHAR currentFSName[ASRFMT_CCH_FS_NAME]; WCHAR szVolumeGuid[ASRFMT_CCH_VOLUME_GUID]; WCHAR currentLabel[ASRFMT_CCH_VOLUME_LABEL]; DWORD cchGuid = 0; BOOL fsOkay = TRUE, result = TRUE; ASSERT(pIsLabelIntact); ZeroMemory(currentFSName, sizeof(WCHAR) * ASRFMT_CCH_FS_NAME); *pIsLabelIntact = TRUE; if (wcslen(pVolume->szGuid) >= ASRFMT_CCH_VOLUME_GUID) { return TRUE; // something's wrong with this GUID } if ((wcslen(pVolume->szFsName) <= 0)) { return TRUE; // no check for RAW volumes } // // We don't want the "please insert floppy in drive A" messages ... // SetErrorMode(SEM_FAILCRITICALERRORS); // // GetVolumeInformation needs the volume guid in the dos-name-space, while the // the sif file has the volume guid in the nt-name-space. Convert // the name by changing the \??\ at the beginning to \\?\, and adding // a back-slash at the end. // cchGuid = wcslen(pVolume->szGuid); wcsncpy(szVolumeGuid, pVolume->szGuid, cchGuid); szVolumeGuid[1] = L'\\'; szVolumeGuid[cchGuid] = L'\\'; // Trailing back-slash szVolumeGuid[cchGuid+1] = L'\0'; fsOkay = TRUE; // // Call GetVolumeInfo to see if the FS is the same // result = GetVolumeInformation(szVolumeGuid, currentLabel, // lpVolumeNameBuffer ASRFMT_CCH_VOLUME_LABEL, // nVolumeNameSize NULL, // lpVolumeSerialNumber NULL, // lpMaximumComponentLength NULL, // lpFileSystemFlags currentFSName, ASRFMT_CCH_FS_NAME ); if ((!result) || wcscmp(currentFSName, pVolume->szFsName) ) { fsOkay = FALSE; *pIsLabelIntact = FALSE; } if (wcscmp(currentLabel, pVolume->szLabel)) { *pIsLabelIntact = FALSE; } /* if (fsOkay) { // // // Call FindFirst in root to see if drive is readable. // guhans: If drive is empty but formatted, this will still // say fsOkay = FALSE; // hFindData = FindFirstFile(szPath, &win32FindData); if (!hFindData || (INVALID_HANDLE_VALUE == hFindData)) { fsOkay = FALSE; } } */ return fsOkay; } BOOL IsVolumeIntact( IN PASRFMT_VOLUME_INFO pVolume ){ // // Call autochk to see if the FS is intact // return TRUE; } /// // Asynchronous function to launch the format routine. // BOOL FormatVolume( IN PASRFMT_VOLUME_INFO pVolume ) { HANDLE hThread = NULL; // // Set the global flags // g_bFormatInProgress = TRUE; g_bFormatSuccessful = TRUE; g_iFormatPercentComplete = 0; // // Loadlib if needed // if (!g_hIfsDll && !FormatInitialise()) { g_bFormatSuccessful = FALSE; g_bFormatInProgress = FALSE; return FALSE; } hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) FormatVolumeThread, pVolume, 0, NULL ); if (!hThread || (INVALID_HANDLE_VALUE == hThread)) { g_bFormatSuccessful = FALSE; g_bFormatInProgress = FALSE; return FALSE; } return TRUE; } BOOL FormatCleanup() { if (g_hIfsDll) { FreeLibrary(g_hIfsDll); g_hIfsDll = NULL; g_FormatRoutineEx = NULL; } return TRUE; } FmIfsCallback( IN FMIFS_PACKET_TYPE PacketType, IN DWORD PacketLength, IN PVOID PacketData ) { switch (PacketType) { case FmIfsPercentCompleted: g_iFormatPercentComplete = ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted ; break; case FmIfsFormattingDestination: case FmIfsInsertDisk: case FmIfsFormatReport: case FmIfsHiddenStatus: default: break; case FmIfsFinished: g_bFormatSuccessful = g_bFormatSuccessful && ((PFMIFS_FINISHED_INFORMATION) PacketData)->Success; g_iFormatPercentComplete = 101; g_bFormatInProgress = FALSE; break; case FmIfsIncompatibleFileSystem: case FmIfsIncompatibleMedia: case FmIfsAccessDenied: case FmIfsMediaWriteProtected: case FmIfsCantLock: case FmIfsBadLabel: case FmIfsCantQuickFormat: case FmIfsIoError: case FmIfsVolumeTooSmall: case FmIfsVolumeTooBig: case FmIfsClusterSizeTooSmall: case FmIfsClusterSizeTooBig: g_bFormatSuccessful = FALSE; break; } return TRUE; } INT FormatVolumeThread(PASRFMT_VOLUME_INFO pVolume) { WCHAR szPath[ASRFMT_CCH_DEVICE_PATH + 1]; swprintf(szPath, TEXT("\\\\?%s"), pVolume->szGuid+3); (g_FormatRoutineEx)(szPath, FmMediaUnknown, pVolume->szFsName, pVolume->szLabel, #if 0 TRUE, // Quick Format for testing #else g_bQuickFormat, #endif pVolume->dwClusterSize, (FMIFS_CALLBACK) &FmIfsCallback ); return TRUE; } VOID MountFileSystem( IN PASRFMT_VOLUME_INFO pVolume ) /*++ (based on code in base\fs\utils\hsm\wsb\wsbfmt.cpp) Routine Description: Ensures a filesystem is mounted at the given root: a) Opens the mount point and closes it. b) Does a FindFirstFile on the mount point The latter may sound redundant but is not because if we create the first FAT32 filesystem then just opening and closing is not enough Arguments: Return Value: none --*/ { WCHAR szPath[ASRFMT_CCH_DEVICE_PATH + 1]; HANDLE handle = NULL; WIN32_FIND_DATA win32FindData; if (!pVolume) { ASSERT(0 && L"pVolume is NULL"); return; } if (!memcmp(pVolume->szDosPath, ASRFMT_WSZ_DOS_DEVICES_PREFIX, ASRFMT_CB_DOS_DEVICES_PREFIX)) { swprintf(szPath, L"\\\\?\\%ws", pVolume->szDosPath + wcslen(ASRFMT_WSZ_DOS_DEVICES_PREFIX)); } else { swprintf(szPath, L"\\\\%ws", pVolume->szDosPath + 2); } handle = CreateFile( szPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 ); if ((handle) && (INVALID_HANDLE_VALUE != handle)) { CloseHandle(handle); } // // Try to find the first file, this will make sure that // the file system is mounted // if (!memcmp(pVolume->szDosPath, ASRFMT_WSZ_DOS_DEVICES_PREFIX, ASRFMT_CB_DOS_DEVICES_PREFIX)) { swprintf(szPath, L"\\\\?\\%ws\\*", pVolume->szDosPath + wcslen(ASRFMT_WSZ_DOS_DEVICES_PREFIX)); } else { swprintf(szPath, L"\\\\%ws\\*", pVolume->szDosPath + 2); } handle = FindFirstFile(szPath, &win32FindData); if ((handle) && (INVALID_HANDLE_VALUE != handle)) { FindClose(handle); } }