/* * Rufus: The Resourceful USB Formatting Utility * Formatting function calls * Copyright (c) 2011 Pete Batard * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifdef _CRTDBG_MAP_ALLOC #include #include #endif #include #include #include #include #include #include #include #include "msapi_utf8.h" #include "rufus.h" #include "resource.h" #include "br.h" #include "fat16.h" #include "fat32.h" #include "file.h" #include "format.h" /* * Globals */ DWORD FormatStatus; /* * FormatEx callback. Return FALSE to halt operations */ static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD Action, PVOID pData) { DWORD* percent; int task_number = 0; if (IS_ERROR(FormatStatus)) return FALSE; switch(Command) { case FCC_PROGRESS: percent = (DWORD*)pData; PostMessage(hMainDialog, UM_FORMAT_PROGRESS, (WPARAM)*percent, (LPARAM)0); uprintf("%d percent completed.\n", *percent); break; case FCC_STRUCTURE_PROGRESS: // No progress on quick format uprintf("Format task %d/? completed.\n", ++task_number); break; case FCC_DONE: if(*(BOOLEAN*)pData == FALSE) { uprintf("Error while formatting.\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE; } break; case FCC_DONE_WITH_STRUCTURE: // We get this message when formatting Small FAT16 // pData Seems to be a struct with at least one (32 BIT!!!) string pointer to the size in MB uprintf("Done with that sort of things: Action=%d pData=%0p\n", Action, pData); DumpBufferHex(pData, 8); uprintf("Volume size: %s MB\n", (char*)(LONG_PTR)(*(ULONG32*)pData)); break; case FCC_INCOMPATIBLE_FILE_SYSTEM: uprintf("Incompatible File System\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_INCOMPATIBLE_FS); break; case FCC_ACCESS_DENIED: uprintf("Access denied\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED; break; case FCC_MEDIA_WRITE_PROTECTED: uprintf("Media is write protected\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_PROTECT; break; case FCC_VOLUME_IN_USE: uprintf("Volume is in use\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_DEVICE_IN_USE; break; case FCC_CANT_QUICK_FORMAT: uprintf("Cannot quick format this volume\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_QUICK_FORMAT); break; case FCC_BAD_LABEL: uprintf("Bad label\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_LABEL_TOO_LONG; break; case FCC_OUTPUT: uprintf("%s\n", ((PTEXTOUTPUT)pData)->Output); break; case FCC_CLUSTER_SIZE_TOO_BIG: case FCC_CLUSTER_SIZE_TOO_SMALL: uprintf("Unsupported cluster size\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_INVALID_CLUSTER_SIZE); break; case FCC_VOLUME_TOO_BIG: case FCC_VOLUME_TOO_SMALL: uprintf("Volume is too %s\n", FCC_VOLUME_TOO_BIG?"big":"small"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_INVALID_VOLUME_SIZE); case FCC_NO_MEDIA_IN_DRIVE: uprintf("No media in drive\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NO_MEDIA_IN_DRIVE; break; default: uprintf("FormatExCallback: received unhandled command %X\n", Command); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED; break; } return (!IS_ERROR(FormatStatus)); } /* * Call on fmifs.dll's FormatEx() to format the drive */ static BOOL FormatDrive(char DriveLetter) { BOOL r = FALSE; PF_DECL(FormatEx); WCHAR wDriveRoot[] = L"?:\\"; WCHAR wFSType[32]; WCHAR wLabel[128]; size_t i; wDriveRoot[0] = (WCHAR)DriveLetter; PrintStatus("Formatting..."); PF_INIT_OR_OUT(FormatEx, fmifs); // TODO: properly set MediaType GetWindowTextW(hFileSystem, wFSType, ARRAYSIZE(wFSType)); // We may have a " (Default)" trail for (i=0; i= 10) { uprintf("Could not access volume after partitioning\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; goto out; } // Handle needs to be closed for FormatEx to be happy - we keep a lock though safe_closehandle(hLogicalVolume); if (!FormatDrive(drive_name[0])) { // Error will be set by FormatDrive() in FormatStatus uprintf("Format error: 0x%08X\n", FormatStatus); goto out; } // TODO: Enable compression on NTFS // TODO: optionally disable indexing on NTFS // TODO: use progress bar during MBR/FSBR/MSDOS copy // TODO: unlock/remount trick to make the volume reappear PrintStatus("Writing master boot record...\n"); if (!WriteMBR(hPhysicalDrive)) { // Errorcode has already been set goto out; } if (IsChecked(IDC_DOS)) { // We must have a lock to modify the FS boot record... hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, TRUE); if (hLogicalVolume == INVALID_HANDLE_VALUE) { uprintf("Could not re-mount volume for partition boot record access\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; goto out; } PrintStatus("Writing partition boot record...\n"); if (!WritePBR(hLogicalVolume)) { // Errorcode has already been set goto out; } // ... and we must have relinquished that lock to write the MS-DOS files safe_unlockclose(hLogicalVolume); PrintStatus("Copying MS-DOS files...\n"); if (!ExtractMSDOS(drive_name)) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; goto out; } } out: safe_unlockclose(hLogicalVolume); safe_unlockclose(hPhysicalDrive); PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0); _endthread(); }