/* * Rufus: The Reliable USB Formatting Utility * Formatting function calls * Copyright (c) 2011-2012 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 #include "msapi_utf8.h" #include "rufus.h" #include "resource.h" #include "br.h" #include "fat16.h" #include "fat32.h" #include "ntfs.h" #include "partition_info.h" #include "file.h" #include "format.h" #include "badblocks.h" /* * Globals */ DWORD FormatStatus; badblocks_report report; static float format_percent = 0.0f; static int task_number = 0; /* Number of steps for each FS for FCC_STRUCTURE_PROGRESS */ const int nb_steps[FS_MAX] = { 5, 5, 12, 10 }; static int fs_index = 0; /* * FormatEx callback. Return FALSE to halt operations */ static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD Action, PVOID pData) { DWORD* percent; if (IS_ERROR(FormatStatus)) return FALSE; switch(Command) { case FCC_PROGRESS: percent = (DWORD*)pData; PrintStatus(0, FALSE, "Formatting: %d%% completed.", *percent); UpdateProgress(OP_FORMAT, 1.0f * (*percent)); break; case FCC_STRUCTURE_PROGRESS: // No progress on quick format PrintStatus(0, TRUE, "Creating file system: Task %d/%d completed.", ++task_number, nb_steps[fs_index]); format_percent += 100.0f / (1.0f * nb_steps[fs_index]); UpdateProgress(OP_CREATE_FS, format_percent); break; case FCC_DONE: PrintStatus(0, TRUE, "Creating file system: Task %d/%d completed.", nb_steps[fs_index], nb_steps[fs_index]); UpdateProgress(OP_CREATE_FS, 100.0f); 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 thing: Action=%d pData=%0p\n", Action, pData); // /!\ THE FOLLOWING ONLY WORKS ON VISTA OR LATER - DO NOT ENABLE ON XP! // 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)); } /* * Chkdsk callback. Return FALSE to halt operations */ static BOOLEAN __stdcall ChkdskCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD Action, PVOID pData) { DWORD* percent; if (IS_ERROR(FormatStatus)) return FALSE; switch(Command) { case FCC_PROGRESS: case FCC_CHECKDISK_PROGRESS: percent = (DWORD*)pData; PrintStatus(0, FALSE, "NTFS Fixup: %d%% completed.", *percent); break; case FCC_DONE: if(*(BOOLEAN*)pData == FALSE) { uprintf("Error while checking disk.\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE; } break; case FCC_UNKNOWN1A: case FCC_DONE_WITH_STRUCTURE: // Silence these specific calls 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_OUTPUT: uprintf("%s\n", ((PTEXTOUTPUT)pData)->Output); break; 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("ChkdskExCallback: received unhandled command %X\n", Command); // Assume the command isn't an error break; } return (!IS_ERROR(FormatStatus)); } /* * Converts an UTF-16 label to a valid FAT/NTFS one */ static void ToValidLabel(WCHAR* name, BOOL bFAT) { size_t i, j, k; BOOL found; WCHAR unauthorized[] = L"*?.,;:/\\|+=<>[]"; WCHAR to_underscore[] = L"\t"; if (name == NULL) return; for (i=0, k=0; i= 0x80) { name[k++] = '_'; found = TRUE; } if (found) continue; } found = FALSE; for (j=0; j return true // \minint and no \i386 without /minint is unclear => return error if (iso_report.winpe&WINPE_MININT) { if (minint) { uprintf("Detected \\minint directory with /minint option: nothing to patch\n"); r = TRUE; } else if (!(iso_report.winpe&WINPE_I386)) { uprintf("Detected \\minint directory only but no /minint option: not sure what to do\n"); } goto out; } // At this stage we only handle \i386 handle = CreateFileA(dst, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (handle == INVALID_HANDLE_VALUE) { uprintf("Could not open %s for patching: %s\n", dst, WindowsErrorString()); goto out; } size = GetFileSize(handle, NULL); if (size == INVALID_FILE_SIZE) { uprintf("Could not get size for file %s: %s\n", dst, WindowsErrorString()); goto out; } buf = (char*)malloc(size); if (buf == NULL) goto out; if ((!ReadFile(handle, buf, size, &rw_size, NULL)) || (size != rw_size)) { uprintf("Could not read file %s: %s\n", dst, WindowsErrorString()); goto out; } SetFilePointer(handle, 0, NULL, FILE_BEGIN); /* Patch setupldr.bin so that [\$]\i386 can be used instead of \minint */ uprintf("Patching file %s\n", dst); for (i=0; i '%s'\n", i, &buf[i], &patch_str_rep[j][minint?2:0]); strcpy(&buf[i], &patch_str_rep[j][minint?2:0]); } } } if (minint) { if ((!WriteFile(handle, buf, size, &rw_size, NULL)) || (size != rw_size)) { uprintf("Could not write patched file: %s\n", WindowsErrorString()); goto out; } }else { // Finish patching \bootmgr for (i=0; i $\i386 if (safe_strnicmp(&buf[i], win_nt_bt_org, strlen(win_nt_bt_org)-1) == 0) { uprintf(" 0x%08X: '%s' -> '%s%s'\n", i, &buf[i], win_nt_bt_rep, &buf[i+strlen(win_nt_bt_org)]); strcpy(&buf[i], win_nt_bt_rep); buf[i+strlen(win_nt_bt_rep)] = buf[i+strlen(win_nt_bt_org)]; buf[i+strlen(win_nt_bt_rep)+1] = 0; } // rdisk(0) -> rdisk(1) (MBR disk masquerading) // TODO: only the first one seems to be needed if (safe_strnicmp(&buf[i], rdisk_zero, strlen(rdisk_zero)-1) == 0) { buf[i+6] = '1'; uprintf(" 0x%08X: '%s' -> 'rdisk(1)'\n", i, rdisk_zero); } } if ((!WriteFile(handle, buf, size, &rw_size, NULL)) || (size != rw_size)) { uprintf("Could not write patched file: %s\n", WindowsErrorString()); goto out; } safe_free(buf); safe_closehandle(handle); // Rename \i386 to \$\i386 safe_sprintf(src, sizeof(src), "%c:\\$", drive_letter); if (!CreateDirectoryA(src, NULL)) { uprintf("Could not create %s: %s\n", src, WindowsErrorString()); goto out; } safe_sprintf(src, sizeof(src), "%c:\\i386", drive_letter); safe_sprintf(dst, sizeof(dst), "%c:\\$\\i386", drive_letter); uprintf("Renaming '%s' to '%s'\n", src, dst); if (!MoveFileA(src, dst)) { uprintf(" failed: %s\n", WindowsErrorString()); goto out; } // Create a \$\i386\winnt.sif (avoids "Please insert" errors) safe_sprintf(src, sizeof(src), "%c:\\$\\i386\\winnt.sif", drive_letter); size = strlen(winnt_sif); handle = CreateFileA(src, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (handle == INVALID_HANDLE_VALUE) { uprintf("Could not create %s: %s\n", src, WindowsErrorString()); goto out; } if ((!WriteFile(handle, winnt_sif, size, &rw_size, NULL)) || (size != rw_size)) { uprintf("Could not write %s: %s\n", src, WindowsErrorString()); goto out; } safe_closehandle(handle); // Uncompress $\\i386\\setupdd.sy_ // Don't bother calling Extract() from cabinet.dll - calling expand.exe is much simpler // TODO: factorize CreateProcess()? memset(&si, 0, sizeof(si)); si.cb = sizeof(si); memset(&pi, 0, sizeof(pi)); uprintf("Decompressing %c:\\$\\i386\\setupdd.sy_\n", drive_letter); safe_sprintf(src, sizeof(src), "expand %c:\\$\\i386\\setupdd.sy_ %c:\\$\\i386\\setupdd.sys", drive_letter, drive_letter); if (!CreateProcessA(NULL, src, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { uprintf("Could not launch command '%s': %s", src, WindowsErrorString()); goto out; } WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exit_code); safe_closehandle(pi.hProcess); safe_closehandle(pi.hThread); if (exit_code != 0) { uprintf("Command '%s' failed with exit code: %d\n", src, exit_code); goto out; } // Patch the uncompressed $\\i386\\setupdd.sys safe_sprintf(dst, sizeof(dst), "%c:\\$\\i386\\setupdd.sys", drive_letter); handle = CreateFileA(dst, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (handle == INVALID_HANDLE_VALUE) { uprintf("Could not open %s for patching: %s\n", dst, WindowsErrorString()); goto out; } size = GetFileSize(handle, NULL); if (size == INVALID_FILE_SIZE) { uprintf("Could not get size for file %s: %s\n", dst, WindowsErrorString()); goto out; } buf = (char*)malloc(size); if (buf == NULL) goto out; if ((!ReadFile(handle, buf, size, &rw_size, NULL)) || (size != rw_size)) { uprintf("Could not read file %s: %s\n", dst, WindowsErrorString()); goto out; } SetFilePointer(handle, 0, NULL, FILE_BEGIN); uprintf("Patching %s\n", dst); for (i=0; i '$'\n", i); buf[i+2] = 0; } } if ((!WriteFile(handle, buf, size, &rw_size, NULL)) || (size != rw_size)) { uprintf("Could not write patched file: %s\n", WindowsErrorString()); goto out; } safe_closehandle(handle); // Recompress to $\\i386\\setupdd.sy_ memset(&si, 0, sizeof(si)); si.cb = sizeof(si); memset(&pi, 0, sizeof(pi)); uprintf("Compressing back %s\n", dst); safe_sprintf(src, sizeof(src), "makecab %c:\\$\\i386\\setupdd.sys %c:\\$\\i386\\setupdd.sy_", drive_letter, drive_letter); if (!CreateProcessA(NULL, src, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { uprintf("Could not launch command '%s': %s", src, WindowsErrorString()); goto out; } WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exit_code); safe_closehandle(pi.hProcess); safe_closehandle(pi.hThread); if (exit_code != 0) { uprintf("Command '%s' failed with exit code: %d\n", src, exit_code); goto out; } // Delete uncompressed file _unlink(dst); } r = TRUE; out: safe_closehandle(handle); safe_free(buf); return r; } /* * Issue a complete remount of the volume */ static BOOL RemountVolume(char drive_letter) { char drive_guid[50]; char drive_name[] = "?:\\"; drive_name[0] = drive_letter; if (GetVolumeNameForVolumeMountPointA(drive_name, drive_guid, sizeof(drive_guid))) { if (DeleteVolumeMountPointA(drive_name)) { Sleep(200); if (SetVolumeMountPointA(drive_name, drive_guid)) { uprintf("Successfully remounted %s on %s\n", drive_guid, drive_name); } else { uprintf("Failed to remount %s on %s\n", drive_guid, drive_name); // This will leave the drive unaccessible and must be flagged as an error FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_REMOUNT_VOLUME); return FALSE; } } else { uprintf("Could not remount %s %s\n", drive_name, WindowsErrorString()); // Try to continue regardless } } return TRUE; } /* * Standalone thread for the formatting operation */ DWORD WINAPI FormatThread(LPVOID param) { DWORD num = (DWORD)(uintptr_t)param; HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE; HANDLE hLogicalVolume = INVALID_HANDLE_VALUE; SYSTEMTIME lt; char drive_name[] = "?:\\"; char bb_msg[512]; char logfile[MAX_PATH], *userdir; FILE* log_fd; int r, fs, dt; hPhysicalDrive = GetDriveHandle(num, NULL, TRUE, TRUE); if (hPhysicalDrive == INVALID_HANDLE_VALUE) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; goto out; } // At this stage with have both a handle and a lock to the physical drive... // ... but we can't write sectors that are part of a volume, even if we have // access to physical, unless we have a lock (which doesn't have to be write) // Also, having a volume handle allows us to unmount the volume hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE); if (hLogicalVolume == INVALID_HANDLE_VALUE) { uprintf("Could not lock volume\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; goto out; } UnmountDrive(hLogicalVolume); AnalyzeMBR(hPhysicalDrive); AnalyzePBR(hLogicalVolume); if (IsChecked(IDC_BADBLOCKS)) { do { // create a log file for bad blocks report. Since %USERPROFILE% may // have localised characters, we use the UTF-8 API. userdir = getenvU("USERPROFILE"); safe_strcpy(logfile, MAX_PATH, userdir); safe_free(userdir); GetLocalTime(<); safe_sprintf(&logfile[strlen(logfile)], sizeof(logfile)-strlen(logfile)-1, "\\rufus_%04d%02d%02d_%02d%02d%02d.log", lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond); log_fd = fopenU(logfile, "w+"); if (log_fd == NULL) { uprintf("Could not create log file for bad blocks check\n"); } else { fprintf(log_fd, "Rufus bad blocks check started on: %04d.%02d.%02d %02d:%02d:%02d\n", lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond); fflush(log_fd); } if (!BadBlocks(hPhysicalDrive, SelectedDrive.DiskSize, SelectedDrive.Geometry.BytesPerSector, ComboBox_GetCurSel(hNBPasses)+1, &report, log_fd)) { uprintf("Bad blocks: Check failed.\n"); if (!FormatStatus) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)| APPERR(ERROR_BADBLOCKS_FAILURE); ClearMBR(hPhysicalDrive); fclose(log_fd); _unlink(logfile); goto out; } uprintf("Bad Blocks: Check completed, %u bad block%s found. (%d/%d/%d errors)\n", report.bb_count, (report.bb_count==1)?"":"s", report.num_read_errors, report.num_write_errors, report.num_corruption_errors); r = IDOK; if (report.bb_count) { safe_sprintf(bb_msg, sizeof(bb_msg), "Check completed: %u bad block%s found.\n" " %d read errors\n %d write errors\n %d corruption errors\n", report.bb_count, (report.bb_count==1)?"":"s", report.num_read_errors, report.num_write_errors, report.num_corruption_errors); fprintf(log_fd, "%s", bb_msg); GetLocalTime(<); fprintf(log_fd, "Rufus bad blocks check ended on: %04d.%02d.%02d %02d:%02d:%02d\n", lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond); fclose(log_fd); safe_sprintf(&bb_msg[strlen(bb_msg)], sizeof(bb_msg)-strlen(bb_msg)-1, "\nA more detailed report can be found in:\n%s\n", logfile); r = MessageBoxU(hMainDialog, bb_msg, "Bad blocks found", MB_ABORTRETRYIGNORE|MB_ICONWARNING); } else { // We didn't get any errors => delete the log file fclose(log_fd); _unlink(logfile); } } while (r == IDRETRY); if (r == IDABORT) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED; goto out; } } // Close the (unmounted) volume before formatting, but keep the lock safe_closehandle(hLogicalVolume); // Especially after destructive badblocks test, you must zero the MBR completely // before repartitioning. Else, all kind of bad things happen if (!ClearMBR(hPhysicalDrive)) { uprintf("unable to zero MBR\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; goto out; } UpdateProgress(OP_ZERO_MBR, -1.0f); if (!CreatePartition(hPhysicalDrive)) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE; goto out; } UpdateProgress(OP_PARTITION, -1.0f); // Add a small delay after partitioning to be safe Sleep(200); if (!FormatDrive(drive_name[0])) { // Error will be set by FormatDrive() in FormatStatus uprintf("Format error: %s\n", StrError(FormatStatus)); goto out; } PrintStatus(0, TRUE, "Writing master boot record..."); if (!WriteMBR(hPhysicalDrive)) { if (!FormatStatus) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; goto out; } UpdateProgress(OP_FIX_MBR, -1.0f); fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)); dt = (int)ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)); if (IsChecked(IDC_DOS)) { if ((dt == DT_WINME) || (dt == DT_FREEDOS) || ((dt == DT_ISO) && (fs == FS_NTFS))) { // We still have a lock, which we need to modify the volume boot record // => no need to reacquire the lock... hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE); 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; } // NB: if you unmount the logical volume here, XP will report error: // [0x00000456] The media in the drive may have changed PrintStatus(0, TRUE, "Writing partition boot record..."); if (!WritePBR(hLogicalVolume)) { if (!FormatStatus) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; goto out; } // We must close and unlock the volume to write files to it safe_unlockclose(hLogicalVolume); } else if ((dt == DT_ISO) && ((fs == FS_FAT16) || (fs == FS_FAT32))) { PrintStatus(0, TRUE, "Installing Syslinux..."); if (!InstallSyslinux(num, drive_name)) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INSTALL_FAILURE; } } } else { if (IsChecked(IDC_SET_ICON)) SetAutorun(drive_name); } // We issue a complete remount of the filesystem at on account of: // - Ensuring the file explorer properly detects that the volume was updated // - Ensuring that an NTFS system will be reparsed so that it becomes bootable if (!RemountVolume(drive_name[0])) goto out; if (IsChecked(IDC_DOS)) { UpdateProgress(OP_DOS, -1.0f); if ((dt == DT_WINME) || (dt == DT_FREEDOS)) { PrintStatus(0, TRUE, "Copying DOS files..."); if (!ExtractDOS(drive_name)) { if (!FormatStatus) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; goto out; } } else if (dt == DT_ISO) { if (iso_path != NULL) { PrintStatus(0, TRUE, "Copying ISO files..."); drive_name[2] = 0; if (!ExtractISO(iso_path, drive_name, FALSE)) { if (!FormatStatus) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; goto out; } } if (IS_WINPE(iso_report.winpe)) { // Apply WinPe fixup SetupWinPE(drive_name[0]); } } if (IsChecked(IDC_SET_ICON)) SetAutorun(drive_name); UpdateProgress(OP_DOS, -1.0f); // Issue another complete remount before we exit, to ensure we're clean RemountVolume(drive_name[0]); // NTFS fixup (WinPE/AIK images don't seem to boot without an extra checkdisk) if ((dt == DT_ISO) && (fs == FS_NTFS)) CheckDisk(drive_name[0]); } out: SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0); safe_unlockclose(hLogicalVolume); safe_unlockclose(hPhysicalDrive); PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0); ExitThread(0); }