mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	misc] move formatting functions into their own source
* also add missing #pragma once in msapi_utf8.h
This commit is contained in:
		
							parent
							
								
									bc252400a1
								
							
						
					
					
						commit
						79f3e78ec3
					
				
					 11 changed files with 644 additions and 569 deletions
				
			
		|  | @ -151,12 +151,14 @@ | ||||||
|     <ClCompile Include="..\fat16.c" /> |     <ClCompile Include="..\fat16.c" /> | ||||||
|     <ClCompile Include="..\fat32.c" /> |     <ClCompile Include="..\fat32.c" /> | ||||||
|     <ClCompile Include="..\file.c" /> |     <ClCompile Include="..\file.c" /> | ||||||
|  |     <ClCompile Include="..\format.c" /> | ||||||
|     <ClCompile Include="..\msdos.c" /> |     <ClCompile Include="..\msdos.c" /> | ||||||
|     <ClCompile Include="..\rufus.c" /> |     <ClCompile Include="..\rufus.c" /> | ||||||
|     <ClCompile Include="..\stdio.c" /> |     <ClCompile Include="..\stdio.c" /> | ||||||
|     <ClCompile Include="..\stdlg.c" /> |     <ClCompile Include="..\stdlg.c" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|  |     <ClInclude Include="..\format.h" /> | ||||||
|     <ClInclude Include="..\inc\br.h" /> |     <ClInclude Include="..\inc\br.h" /> | ||||||
|     <ClInclude Include="..\inc\br_fat12_0x0.h" /> |     <ClInclude Include="..\inc\br_fat12_0x0.h" /> | ||||||
|     <ClInclude Include="..\inc\br_fat12_0x3e.h" /> |     <ClInclude Include="..\inc\br_fat12_0x3e.h" /> | ||||||
|  |  | ||||||
|  | @ -45,6 +45,9 @@ | ||||||
|     <ClCompile Include="..\stdio.c"> |     <ClCompile Include="..\stdio.c"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="..\format.c"> | ||||||
|  |       <Filter>Source Files</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="..\rufus.h"> |     <ClInclude Include="..\rufus.h"> | ||||||
|  | @ -146,6 +149,9 @@ | ||||||
|     <ClInclude Include="..\inc\mbr_zero.h"> |     <ClInclude Include="..\inc\mbr_zero.h"> | ||||||
|       <Filter>Header Files\inc</Filter> |       <Filter>Header Files\inc</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\format.h"> | ||||||
|  |       <Filter>Header Files</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="..\rufus.ico"> |     <None Include="..\rufus.ico"> | ||||||
|  |  | ||||||
|  | @ -23,13 +23,14 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ | ||||||
| # http://jpassing.com/2008/02/01/how-to-use-manifests-with-buildexe/ | # http://jpassing.com/2008/02/01/how-to-use-manifests-with-buildexe/ | ||||||
| SXS_APPLICATION_MANIFEST=common_controls_and_elevation.manifest | SXS_APPLICATION_MANIFEST=common_controls_and_elevation.manifest | ||||||
| 
 | 
 | ||||||
| SOURCES=rufus.c \ | SOURCES=rufus.c  \ | ||||||
|         stdio.c \ |         format.c \ | ||||||
|         stdlg.c \ |         stdio.c  \ | ||||||
|         msdos.c \ |         stdlg.c  \ | ||||||
|         file.c  \ |         msdos.c  \ | ||||||
|         br.c    \ |         file.c   \ | ||||||
|         fat12.c \ |         br.c     \ | ||||||
|         fat16.c \ |         fat12.c  \ | ||||||
|         fat32.c \ |         fat16.c  \ | ||||||
|  |         fat32.c  \ | ||||||
|         rufus.rc |         rufus.rc | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -17,7 +17,7 @@ | ||||||
| # along with this program; if not, see <http://www.gnu.org/licenses/>.
 | # along with this program; if not, see <http://www.gnu.org/licenses/>.
 | ||||||
| #
 | #
 | ||||||
| 
 | 
 | ||||||
| OBJECTS   = fat12.o fat16.o fat32.o br.o file.o msdos.o stdio.o stdlg.o rufus.o   | OBJECTS   = fat12.o fat16.o fat32.o br.o file.o msdos.o format.o stdio.o stdlg.o rufus.o   | ||||||
| TARGET    = rufus | TARGET    = rufus | ||||||
| 
 | 
 | ||||||
| CC        = gcc | CC        = gcc | ||||||
|  |  | ||||||
							
								
								
									
										435
									
								
								format.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										435
									
								
								format.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,435 @@ | ||||||
|  | /*
 | ||||||
|  |  * Rufus: The Resourceful USB Formatting Utility | ||||||
|  |  * Formatting function calls | ||||||
|  |  * Copyright (c) 2011 Pete Batard <pete@akeo.ie> | ||||||
|  |  * | ||||||
|  |  * 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 <http://www.gnu.org/licenses/>.
 | ||||||
|  |  */ | ||||||
|  | #ifdef _CRTDBG_MAP_ALLOC | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <crtdbg.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #include <windows.h> | ||||||
|  | #include <windowsx.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <process.h> | ||||||
|  | // #include <ctype.h>
 | ||||||
|  | 
 | ||||||
|  | #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" | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * 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)|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)|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)|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)|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<wcslen(wFSType); i++) { | ||||||
|  | 		if (wFSType[i] == ' ') { | ||||||
|  | 			uprintf("removed %d\n", i); | ||||||
|  | 			wFSType[i] = 0; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel)); | ||||||
|  | 	uprintf("Using cluster size: %d bytes\n", ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize))); | ||||||
|  | 	pfFormatEx(wDriveRoot, RemovableMedia, wFSType, wLabel, | ||||||
|  | 		IsChecked(IDC_QUICKFORMAT), (ULONG)ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)), | ||||||
|  | 		FormatExCallback); | ||||||
|  | 	if (!IS_ERROR(FormatStatus)) { | ||||||
|  | 		uprintf("Format completed.\n"); | ||||||
|  | 		r = TRUE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static BOOL AnalyzeMBR(HANDLE hPhysicalDrive) | ||||||
|  | { | ||||||
|  | 	FILE fake_fd; | ||||||
|  | 
 | ||||||
|  | 	fake_fd._ptr = (char*)hPhysicalDrive; | ||||||
|  | 	fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; | ||||||
|  | 
 | ||||||
|  | 	// TODO: Apply this detection before partitioning
 | ||||||
|  | 	// TODO: since we detect all these, might as well give some MBR choice to the user?
 | ||||||
|  | 	if (is_br(&fake_fd)) { | ||||||
|  | 		uprintf("Drive has an x86 boot sector\n"); | ||||||
|  | 	} else{ | ||||||
|  | 		uprintf("Drive is missing an x86 boot sector!\n"); | ||||||
|  | 		return FALSE; | ||||||
|  | 	} | ||||||
|  | 	// TODO: Add/Eliminate FAT12?
 | ||||||
|  | 	if (is_fat_16_br(&fake_fd) || is_fat_32_br(&fake_fd)) { | ||||||
|  | 		if (entire_fat_16_br_matches(&fake_fd)) { | ||||||
|  | 			uprintf("Exact FAT16 DOS boot record match\n"); | ||||||
|  | 		} else if (entire_fat_16_fd_br_matches(&fake_fd)) { | ||||||
|  | 			uprintf("Exact FAT16 FreeDOS boot record match\n"); | ||||||
|  | 		} else if (entire_fat_32_br_matches(&fake_fd)) { | ||||||
|  | 			uprintf("Exact FAT32 DOS boot record match\n"); | ||||||
|  | 		} else if (entire_fat_32_nt_br_matches(&fake_fd)) { | ||||||
|  | 			uprintf("Exact FAT32 NT boot record match\n"); | ||||||
|  | 		} else if (entire_fat_32_fd_br_matches(&fake_fd)) { | ||||||
|  | 			uprintf("Exactly FAT32 FreeDOS boot record match\n"); | ||||||
|  | 		} else { | ||||||
|  | 			uprintf("Unknown FAT16 or FAT32 boot record\n"); | ||||||
|  | 		} | ||||||
|  | 	} else if (is_dos_mbr(&fake_fd)) { | ||||||
|  | 		uprintf("Microsoft DOS/NT/95A master boot record match\n"); | ||||||
|  | 	} else if (is_dos_f2_mbr(&fake_fd)) { | ||||||
|  | 		uprintf("Microsoft DOS/NT/95A master boot record with the undocumented\n"); | ||||||
|  | 		uprintf("F2 instruction match\n"); | ||||||
|  | 	} else if (is_95b_mbr(&fake_fd)) { | ||||||
|  | 		uprintf("Microsoft 95B/98/98SE/ME master boot record match\n"); | ||||||
|  | 	} else if (is_2000_mbr(&fake_fd)) { | ||||||
|  | 		uprintf("Microsoft 2000/XP/2003 master boot record match\n"); | ||||||
|  | 	} else if (is_vista_mbr(&fake_fd)) { | ||||||
|  | 		uprintf("Microsoft Vista master boot record match\n"); | ||||||
|  | 	} else if (is_win7_mbr(&fake_fd)) { | ||||||
|  | 		uprintf("Microsoft 7 master boot record match\n"); | ||||||
|  | 	} else if (is_zero_mbr(&fake_fd)) { | ||||||
|  | 		uprintf("Zeroed non-bootable master boot record match\n"); | ||||||
|  | 	} else { | ||||||
|  | 		uprintf("Unknown boot record\n"); | ||||||
|  | 	} | ||||||
|  | 	return TRUE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Process the MBR | ||||||
|  |  */ | ||||||
|  | static BOOL ProcessMBR(HANDLE hPhysicalDrive) | ||||||
|  | { | ||||||
|  | 	BOOL r = FALSE; | ||||||
|  | 	unsigned char* buf = NULL; | ||||||
|  | 	size_t SecSize = SelectedDrive.Geometry.BytesPerSector; | ||||||
|  | 	size_t nSecs = (0x200 + SecSize -1) / SecSize; | ||||||
|  | 	FILE fake_fd; | ||||||
|  | 
 | ||||||
|  | 	if (!AnalyzeMBR(hPhysicalDrive)) return FALSE; | ||||||
|  | 
 | ||||||
|  | 	// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
 | ||||||
|  | 	// and FAT32 partitions - we need to correct this in the MBR
 | ||||||
|  | 	// TODO: something else for bootable GPT
 | ||||||
|  | 	buf = (unsigned char*)malloc(SecSize * nSecs); | ||||||
|  | 	if (buf == NULL) { | ||||||
|  | 		uprintf("Could not allocate memory for MBR"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) { | ||||||
|  | 		uprintf("Could not read MBR\n"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | //	DumpBufferHex(buf, 0x200);
 | ||||||
|  | 	switch (ComboBox_GetCurSel(hFileSystem)) { | ||||||
|  | 	// TODO: check for 0x06 & 0x0b?
 | ||||||
|  | 	case FS_FAT16: | ||||||
|  | 		buf[0x1c2] = 0x0e; | ||||||
|  | 		break; | ||||||
|  | 	case FS_FAT32: | ||||||
|  | 		buf[0x1c2] = 0x0c; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	if (IsChecked(IDC_DOSSTARTUP)) { | ||||||
|  | 		buf[0x1be] = 0x80;		// Set first partition bootable
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!write_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize*nSecs)) { | ||||||
|  | 		uprintf("Could not write MBR\n"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fake_fd._ptr = (char*)hPhysicalDrive; | ||||||
|  | 	fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; | ||||||
|  | 	r = write_95b_mbr(&fake_fd); | ||||||
|  | 
 | ||||||
|  | 	if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) { | ||||||
|  | 		uprintf("Could not re-read MBR\n"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	DumpBufferHex(buf, 0x200); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	safe_free(buf); | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static BOOL ProcessFS_BR(HANDLE hLogicalVolume) | ||||||
|  | { | ||||||
|  | 	BOOL r = FALSE; | ||||||
|  | 	unsigned char* buf = NULL; | ||||||
|  | 	FILE fake_fd; | ||||||
|  | 	size_t SecSize = SelectedDrive.Geometry.BytesPerSector; | ||||||
|  | 	size_t nSecs = (0x400 + SecSize -1) / SecSize; | ||||||
|  | 
 | ||||||
|  | 	fake_fd._ptr = (char*)hLogicalVolume; | ||||||
|  | 	fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; | ||||||
|  | 	write_fat_32_br(&fake_fd, 0); | ||||||
|  | 
 | ||||||
|  | 	// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
 | ||||||
|  | 	// and FAT32 partitions - we need to correct this in the MBR
 | ||||||
|  | 	// TODO: something else for bootable GPT
 | ||||||
|  | 	buf = (unsigned char*)malloc(SecSize * nSecs); | ||||||
|  | 	if (buf == NULL) { | ||||||
|  | 		uprintf("Could not allocate memory for FS BR"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!read_sectors(hLogicalVolume, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize*nSecs)) { | ||||||
|  | 		uprintf("Could not read FS BR\n"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	uprintf("FS_BR:\n"); | ||||||
|  | 	DumpBufferHex(buf, 0x400); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	safe_free(buf); | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa364562%28v=vs.85%29.aspx
 | ||||||
|  |    Dismounting a volume is useful when a volume needs to disappear for a while. For | ||||||
|  |    example, an application that changes a volume file system from the FAT file system | ||||||
|  |    to the NTFS file system might use the following procedure. | ||||||
|  | 
 | ||||||
|  |    To change a volume file system | ||||||
|  | 
 | ||||||
|  |     Open a volume. | ||||||
|  |     Lock the volume. | ||||||
|  |     Format the volume. | ||||||
|  |     Dismount the volume. | ||||||
|  |     Unlock the volume. | ||||||
|  |     Close the volume handle. | ||||||
|  | 
 | ||||||
|  |    A dismounting operation removes the volume from the FAT file system awareness. | ||||||
|  |    When the operating system mounts the volume, it appears as an NTFS file system volume. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Standalone thread for the formatting operation | ||||||
|  |  */ | ||||||
|  | void __cdecl FormatThread(void* param) | ||||||
|  | { | ||||||
|  | 	DWORD num = (DWORD)(uintptr_t)param; | ||||||
|  | 	HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE; | ||||||
|  | 	HANDLE hLogicalVolume = INVALID_HANDLE_VALUE; | ||||||
|  | 	char drive_name[] = "?:"; | ||||||
|  | 	int i; | ||||||
|  | //	DWORD size;
 | ||||||
|  | 
 | ||||||
|  | 	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
 | ||||||
|  | 
 | ||||||
|  | 	if (!CreatePartition(hPhysicalDrive)) { | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Make sure we can access the volume again before trying to format it
 | ||||||
|  | 	for (i=0; i<10; i++) { | ||||||
|  | 		Sleep(500); | ||||||
|  | 		hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE); | ||||||
|  | 		if (hLogicalVolume != INVALID_HANDLE_VALUE) { | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (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
 | ||||||
|  | 
 | ||||||
|  | 	// Ideally we would lock, FSCTL_DISMOUNT_VOLUME, unlock and close our volume
 | ||||||
|  | 	// handle, but some explorer versions have problems with volumes disappear
 | ||||||
|  | // #define VOL_DISMOUNT
 | ||||||
|  | #ifdef VOL_DISMOUNT | ||||||
|  | 	// Dismount the volume
 | ||||||
|  | 	hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE); | ||||||
|  | 	if (hLogicalVolume == INVALID_HANDLE_VALUE) { | ||||||
|  | 		uprintf("Could not open the volume for dismount\n"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!DeviceIoControl(hLogicalVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &size, NULL)) { | ||||||
|  | 		uprintf("Could not dismount volume\n"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | 	PrintStatus("Writing master boot record...\n"); | ||||||
|  | 	if (!ProcessMBR(hPhysicalDrive)) { | ||||||
|  | 		// Errorcode has already been set
 | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | #ifdef VOL_DISMOUNT | ||||||
|  | 	safe_unlockclose(hLogicalVolume); | ||||||
|  | //	Sleep(10000);
 | ||||||
|  | 	hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, FALSE); | ||||||
|  | 	if (hLogicalVolume == INVALID_HANDLE_VALUE) { | ||||||
|  | 		uprintf("Could not re-mount volume\n"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	if (IsChecked(IDC_DOSSTARTUP)) { | ||||||
|  | 		hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE); | ||||||
|  | 		if (hLogicalVolume == INVALID_HANDLE_VALUE) { | ||||||
|  | 			uprintf("Could not re-mount volume\n"); | ||||||
|  | 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 		PrintStatus("Writing filesystem boot record...\n"); | ||||||
|  | 		if (!ProcessFS_BR(hLogicalVolume)) { | ||||||
|  | 			// Errorcode has already been set
 | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 		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(); | ||||||
|  | } | ||||||
							
								
								
									
										106
									
								
								format.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								format.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,106 @@ | ||||||
|  | /*
 | ||||||
|  |  * Rufus: The Resourceful USB Formatting Utility | ||||||
|  |  * Formatting function calls | ||||||
|  |  * Copyright (c) 2011 Pete Batard <pete@akeo.ie> | ||||||
|  |  * | ||||||
|  |  * 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 <http://www.gnu.org/licenses/>.
 | ||||||
|  |  */ | ||||||
|  | #include <Windows.h> | ||||||
|  | #include <winioctl.h>				// for MEDIA_TYPE | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * typedefs for the function prototypes. Use the something like: | ||||||
|  |  *   PF_DECL(FormatEx); | ||||||
|  |  * which translates to: | ||||||
|  |  *   FormatEx_t pfFormatEx = NULL; | ||||||
|  |  * in your code, to declare the entrypoint and then use: | ||||||
|  |  *   PF_INIT(FormatEx, fmifs); | ||||||
|  |  * which translates to: | ||||||
|  |  *   pfFormatEx = (FormatEx_t) GetProcAddress(GetDLLHandle("fmifs"), "FormatEx"); | ||||||
|  |  * to make it accessible. | ||||||
|  |  */ | ||||||
|  | static __inline HMODULE GetDLLHandle(char* szDLLName) | ||||||
|  | { | ||||||
|  | 	HMODULE h = NULL; | ||||||
|  | 	if ((h = GetModuleHandleA(szDLLName)) == NULL) | ||||||
|  | 		h = LoadLibraryA(szDLLName); | ||||||
|  | 	return h; | ||||||
|  | } | ||||||
|  | #define PF_DECL(proc) proc##_t pf##proc = NULL | ||||||
|  | #define PF_INIT(proc, dllname) pf##proc = (proc##_t) GetProcAddress(GetDLLHandle(#dllname), #proc) | ||||||
|  | #define PF_INIT_OR_OUT(proc, dllname) \ | ||||||
|  | 	PF_INIT(proc, dllname); if (pf##proc == NULL) { \ | ||||||
|  | 	uprintf("unable to access %s DLL: %s", #dllname, \ | ||||||
|  | 	WindowsErrorString()); goto out; } | ||||||
|  | 
 | ||||||
|  | /* Callback command types (some errorcode were filled from HPUSBFW V2.2.3 and their
 | ||||||
|  |    designation from msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */ | ||||||
|  | typedef enum { | ||||||
|  | 	FCC_PROGRESS, | ||||||
|  | 	FCC_DONE_WITH_STRUCTURE, | ||||||
|  | 	FCC_UNKNOWN2, | ||||||
|  | 	FCC_INCOMPATIBLE_FILE_SYSTEM, | ||||||
|  | 	FCC_UNKNOWN4, | ||||||
|  | 	FCC_UNKNOWN5, | ||||||
|  | 	FCC_ACCESS_DENIED, | ||||||
|  | 	FCC_MEDIA_WRITE_PROTECTED, | ||||||
|  | 	FCC_VOLUME_IN_USE, | ||||||
|  | 	FCC_CANT_QUICK_FORMAT, | ||||||
|  | 	FCC_UNKNOWNA, | ||||||
|  | 	FCC_DONE, | ||||||
|  | 	FCC_BAD_LABEL, | ||||||
|  | 	FCC_UNKNOWND, | ||||||
|  | 	FCC_OUTPUT, | ||||||
|  | 	FCC_STRUCTURE_PROGRESS, | ||||||
|  | 	FCC_CLUSTER_SIZE_TOO_SMALL, | ||||||
|  | 	FCC_CLUSTER_SIZE_TOO_BIG, | ||||||
|  | 	FCC_VOLUME_TOO_SMALL, | ||||||
|  | 	FCC_VOLUME_TOO_BIG, | ||||||
|  | 	FCC_NO_MEDIA_IN_DRIVE, | ||||||
|  | } FILE_SYSTEM_CALLBACK_COMMAND; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  | 	DWORD Lines; | ||||||
|  | 	CHAR* Output; | ||||||
|  | } TEXTOUTPUT, *PTEXTOUTPUT; | ||||||
|  | 
 | ||||||
|  | typedef BOOLEAN (__stdcall *FILE_SYSTEM_CALLBACK)( | ||||||
|  | 	FILE_SYSTEM_CALLBACK_COMMAND Command, | ||||||
|  | 	ULONG                        Action, | ||||||
|  | 	PVOID                        pData | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | /* Parameter names aligned to
 | ||||||
|  |    http://msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */
 | ||||||
|  | typedef VOID (WINAPI *FormatEx_t)( | ||||||
|  | 	WCHAR*               DriveRoot, | ||||||
|  | 	MEDIA_TYPE           MediaType,		// See WinIoCtl.h
 | ||||||
|  | 	WCHAR*               FileSystemTypeName, | ||||||
|  | 	WCHAR*               Label, | ||||||
|  | 	BOOL                 QuickFormat, | ||||||
|  | 	ULONG                DesiredUnitAllocationSize, | ||||||
|  | 	FILE_SYSTEM_CALLBACK Callback | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa383357.aspx */ | ||||||
|  | typedef enum  { | ||||||
|  | 	FPF_COMPRESSED   = 0x01  | ||||||
|  | } FILE_SYSTEM_PROP_FLAG; | ||||||
|  | 
 | ||||||
|  | typedef BOOLEAN (WINAPI* EnableVolumeCompression_t)( | ||||||
|  | 	WCHAR*          DriveRoot, | ||||||
|  | 	ULONG           CompressionFlags	// FILE_SYSTEM_PROP_FLAG
 | ||||||
|  | ); | ||||||
|  | @ -25,6 +25,8 @@ | ||||||
| #include <shellapi.h> | #include <shellapi.h> | ||||||
| #include <setupapi.h> | #include <setupapi.h> | ||||||
| 
 | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
							
								
								
									
										441
									
								
								rufus.c
									
										
									
									
									
								
							
							
						
						
									
										441
									
								
								rufus.c
									
										
									
									
									
								
							|  | @ -40,26 +40,20 @@ | ||||||
| #include <io.h> | #include <io.h> | ||||||
| 
 | 
 | ||||||
| // http://git.kernel.org/?p=fs/ext2/e2fsprogs.git;a=blob;f=misc/badblocks.c
 | // http://git.kernel.org/?p=fs/ext2/e2fsprogs.git;a=blob;f=misc/badblocks.c
 | ||||||
| // http://ms-sys.sourceforge.net/
 |  | ||||||
| // http://thestarman.pcministry.com/asm/mbr/MSWIN41.htm
 | // http://thestarman.pcministry.com/asm/mbr/MSWIN41.htm
 | ||||||
| // http://www.c-jump.com/CIS24/Slides/FAT/lecture.html#F01_0130_sector_assignments
 |  | ||||||
| 
 | 
 | ||||||
| #include "msapi_utf8.h" | #include "msapi_utf8.h" | ||||||
| #include "resource.h" | #include "resource.h" | ||||||
| #include "rufus.h" | #include "rufus.h" | ||||||
| #include "sys_types.h" | #include "sys_types.h" | ||||||
| #include "br.h" |  | ||||||
| #include "fat16.h" |  | ||||||
| #include "fat32.h" |  | ||||||
| #include "file.h" |  | ||||||
| 
 | 
 | ||||||
| #if !defined(GUID_DEVINTERFACE_DISK) | #if !defined(GUID_DEVINTERFACE_DISK) | ||||||
| const GUID GUID_DEVINTERFACE_DISK = { 0x53f56307L, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b} }; | const GUID GUID_DEVINTERFACE_DISK = { 0x53f56307L, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b} }; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "exFAT" }; | static const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "exFAT" }; | ||||||
| // Don't ask me - just following the MS standard here
 | // Don't ask me - just following the MS standard here
 | ||||||
| const char* ClusterSizeLabel[] = { "512 bytes", "1024 bytes","2048 bytes","4096 bytes","8192 bytes", | static const char* ClusterSizeLabel[] = { "512 bytes", "1024 bytes","2048 bytes","4096 bytes","8192 bytes", | ||||||
| 	"16 kilobytes", "32 kilobytes", "64 kilobytes", "128 kilobytes", "256 kilobytes", "512 kilobytes", | 	"16 kilobytes", "32 kilobytes", "64 kilobytes", "128 kilobytes", "256 kilobytes", "512 kilobytes", | ||||||
| 	"1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" }; | 	"1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" }; | ||||||
| 
 | 
 | ||||||
|  | @ -81,27 +75,14 @@ HWND hStatus; | ||||||
| float fScale = 1.0f; | float fScale = 1.0f; | ||||||
| int default_fs; | int default_fs; | ||||||
| ULONG default_clutersize; | ULONG default_clutersize; | ||||||
| 
 | RUFUS_DRIVE_INFO SelectedDrive; | ||||||
| BOOL bBootable; | BOOL bBootable; | ||||||
| BOOL bQuickFormat; | BOOL bQuickFormat; | ||||||
| 
 | DWORD FormatStatus; | ||||||
| struct { | HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel; | ||||||
| 	DWORD DeviceNumber; |  | ||||||
| 	LONGLONG DiskSize; |  | ||||||
| 	DISK_GEOMETRY Geometry; |  | ||||||
| 	DWORD FirstSector; |  | ||||||
| 	int FSType; |  | ||||||
| 	struct { |  | ||||||
| 		ULONG Allowed; |  | ||||||
| 		ULONG Default; |  | ||||||
| 	} ClusterSize[FS_MAX]; |  | ||||||
| } SelectedDrive; |  | ||||||
| 
 |  | ||||||
| static HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel; |  | ||||||
| static HWND hDeviceTooltip = NULL, hFSTooltip = NULL; | static HWND hDeviceTooltip = NULL, hFSTooltip = NULL; | ||||||
| static StrArray DriveID, DriveLabel; |  | ||||||
| static DWORD FormatStatus; |  | ||||||
| 
 | 
 | ||||||
|  | static StrArray DriveID, DriveLabel; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Convert a partition type to its human readable form using |  * Convert a partition type to its human readable form using | ||||||
|  | @ -119,7 +100,7 @@ static const char* GetPartitionType(BYTE Type) | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Open a drive with optional write access - returns a drive HANDLE and the drive letter |  * Open a drive with optional write access - returns a drive HANDLE and the drive letter | ||||||
|  * or INVALID_HANDLE_VALUE (/!\ which is != NULL /!\) on failure |  * or INVALID_HANDLE_VALUE (/!\ which is DIFFERENT from NULL /!\) on failure | ||||||
|  * This call is quite risky (left unchecked, inadvertently passing 0 as index would |  * This call is quite risky (left unchecked, inadvertently passing 0 as index would | ||||||
|  * return a handle to C:, which we might then proceed to unknowingly repartition!), |  * return a handle to C:, which we might then proceed to unknowingly repartition!), | ||||||
|  * so we apply the following mitigation factors: |  * so we apply the following mitigation factors: | ||||||
|  | @ -128,7 +109,7 @@ static const char* GetPartitionType(BYTE Type) | ||||||
|  *   typically be the case on C:\ or any other drive in use, we report failure |  *   typically be the case on C:\ or any other drive in use, we report failure | ||||||
|  * - We report the full path of any drive that was successfully opened for write acces |  * - We report the full path of any drive that was successfully opened for write acces | ||||||
|  */ |  */ | ||||||
| static HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive) | HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive) | ||||||
| { | { | ||||||
| 	BOOL r; | 	BOOL r; | ||||||
| 	DWORD size; | 	DWORD size; | ||||||
|  | @ -212,12 +193,6 @@ out: | ||||||
| 	return hDrive; | 	return hDrive; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static __inline BOOL UnlockDrive(HANDLE hDrive) |  | ||||||
| { |  | ||||||
| 	DWORD size; |  | ||||||
| 	return DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * Return the drive letter and volume label |  * Return the drive letter and volume label | ||||||
|  */ |  */ | ||||||
|  | @ -242,12 +217,10 @@ static BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label) | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| #define KB          1024LL | #define KB          1024LL | ||||||
| #define MB       1048576LL | #define MB       1048576LL | ||||||
| #define GB    1073741824LL | #define GB    1073741824LL | ||||||
| #define TB 1099511627776LL | #define TB 1099511627776LL | ||||||
| 
 |  | ||||||
| /* 
 | /* 
 | ||||||
|  * Set cluster size values according to http://support.microsoft.com/kb/140365
 |  * Set cluster size values according to http://support.microsoft.com/kb/140365
 | ||||||
|  * this call will return FALSE if we can't find a supportable FS for the drive |  * this call will return FALSE if we can't find a supportable FS for the drive | ||||||
|  | @ -559,7 +532,7 @@ static BOOL PopulateProperties(int ComboIndex) | ||||||
| /*
 | /*
 | ||||||
|  * Create a partition table |  * Create a partition table | ||||||
|  */ |  */ | ||||||
| static BOOL CreatePartition(HANDLE hDrive) | BOOL CreatePartition(HANDLE hDrive) | ||||||
| { | { | ||||||
| 	BYTE layout[sizeof(DRIVE_LAYOUT_INFORMATION_EX) + 3*sizeof(PARTITION_INFORMATION_EX)] = {0}; | 	BYTE layout[sizeof(DRIVE_LAYOUT_INFORMATION_EX) + 3*sizeof(PARTITION_INFORMATION_EX)] = {0}; | ||||||
| 	PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = (PDRIVE_LAYOUT_INFORMATION_EX)layout; | 	PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = (PDRIVE_LAYOUT_INFORMATION_EX)layout; | ||||||
|  | @ -605,402 +578,6 @@ static BOOL CreatePartition(HANDLE hDrive) | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * 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)|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)|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)|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)|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<wcslen(wFSType); i++) { |  | ||||||
| 		if (wFSType[i] == ' ') { |  | ||||||
| 			uprintf("removed %d\n", i); |  | ||||||
| 			wFSType[i] = 0; |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel)); |  | ||||||
| 	uprintf("Using cluster size: %d bytes\n", ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize))); |  | ||||||
| 	pfFormatEx(wDriveRoot, RemovableMedia, wFSType, wLabel, |  | ||||||
| 		IsChecked(IDC_QUICKFORMAT), (ULONG)ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)), |  | ||||||
| 		FormatExCallback); |  | ||||||
| 	if (!IS_ERROR(FormatStatus)) { |  | ||||||
| 		uprintf("Format completed.\n"); |  | ||||||
| 		r = TRUE; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| out: |  | ||||||
| 	return r; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static BOOL AnalyzeMBR(HANDLE hPhysicalDrive) |  | ||||||
| { |  | ||||||
| 	FILE fake_fd; |  | ||||||
| 
 |  | ||||||
| 	fake_fd._ptr = (char*)hPhysicalDrive; |  | ||||||
| 	fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; |  | ||||||
| 
 |  | ||||||
| 	// TODO: Apply this detection before partitioning
 |  | ||||||
| 	// TODO: since we detect all these, might as well give some MBR choice to the user?
 |  | ||||||
| 	if (is_br(&fake_fd)) { |  | ||||||
| 		uprintf("Drive has an x86 boot sector\n"); |  | ||||||
| 	} else{ |  | ||||||
| 		uprintf("Drive is missing an x86 boot sector!\n"); |  | ||||||
| 		return FALSE; |  | ||||||
| 	} |  | ||||||
| 	// TODO: Add/Eliminate FAT12?
 |  | ||||||
| 	if (is_fat_16_br(&fake_fd) || is_fat_32_br(&fake_fd)) { |  | ||||||
| 		if (entire_fat_16_br_matches(&fake_fd)) { |  | ||||||
| 			uprintf("Exact FAT16 DOS boot record match\n"); |  | ||||||
| 		} else if (entire_fat_16_fd_br_matches(&fake_fd)) { |  | ||||||
| 			uprintf("Exact FAT16 FreeDOS boot record match\n"); |  | ||||||
| 		} else if (entire_fat_32_br_matches(&fake_fd)) { |  | ||||||
| 			uprintf("Exact FAT32 DOS boot record match\n"); |  | ||||||
| 		} else if (entire_fat_32_nt_br_matches(&fake_fd)) { |  | ||||||
| 			uprintf("Exact FAT32 NT boot record match\n"); |  | ||||||
| 		} else if (entire_fat_32_fd_br_matches(&fake_fd)) { |  | ||||||
| 			uprintf("Exactly FAT32 FreeDOS boot record match\n"); |  | ||||||
| 		} else { |  | ||||||
| 			uprintf("Unknown FAT16 or FAT32 boot record\n"); |  | ||||||
| 		} |  | ||||||
| 	} else if (is_dos_mbr(&fake_fd)) { |  | ||||||
| 		uprintf("Microsoft DOS/NT/95A master boot record match\n"); |  | ||||||
| 	} else if (is_dos_f2_mbr(&fake_fd)) { |  | ||||||
| 		uprintf("Microsoft DOS/NT/95A master boot record with the undocumented\n"); |  | ||||||
| 		uprintf("F2 instruction match\n"); |  | ||||||
| 	} else if (is_95b_mbr(&fake_fd)) { |  | ||||||
| 		uprintf("Microsoft 95B/98/98SE/ME master boot record match\n"); |  | ||||||
| 	} else if (is_2000_mbr(&fake_fd)) { |  | ||||||
| 		uprintf("Microsoft 2000/XP/2003 master boot record match\n"); |  | ||||||
| 	} else if (is_vista_mbr(&fake_fd)) { |  | ||||||
| 		uprintf("Microsoft Vista master boot record match\n"); |  | ||||||
| 	} else if (is_win7_mbr(&fake_fd)) { |  | ||||||
| 		uprintf("Microsoft 7 master boot record match\n"); |  | ||||||
| 	} else if (is_zero_mbr(&fake_fd)) { |  | ||||||
| 		uprintf("Zeroed non-bootable master boot record match\n"); |  | ||||||
| 	} else { |  | ||||||
| 		uprintf("Unknown boot record\n"); |  | ||||||
| 	} |  | ||||||
| 	return TRUE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Process the MBR |  | ||||||
|  */ |  | ||||||
| static BOOL ProcessMBR(HANDLE hPhysicalDrive) |  | ||||||
| { |  | ||||||
| 	BOOL r = FALSE; |  | ||||||
| 	unsigned char* buf = NULL; |  | ||||||
| 	size_t SecSize = SelectedDrive.Geometry.BytesPerSector; |  | ||||||
| 	size_t nSecs = (0x200 + SecSize -1) / SecSize; |  | ||||||
| 	FILE fake_fd; |  | ||||||
| 
 |  | ||||||
| 	if (!AnalyzeMBR(hPhysicalDrive)) return FALSE; |  | ||||||
| 
 |  | ||||||
| 	// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
 |  | ||||||
| 	// and FAT32 partitions - we need to correct this in the MBR
 |  | ||||||
| 	// TODO: something else for bootable GPT
 |  | ||||||
| 	buf = (unsigned char*)malloc(SecSize * nSecs); |  | ||||||
| 	if (buf == NULL) { |  | ||||||
| 		uprintf("Could not allocate memory for MBR"); |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) { |  | ||||||
| 		uprintf("Could not read MBR\n"); |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| //	DumpBufferHex(buf, 0x200);
 |  | ||||||
| 	switch (ComboBox_GetCurSel(hFileSystem)) { |  | ||||||
| 	// TODO: check for 0x06 & 0x0b?
 |  | ||||||
| 	case FS_FAT16: |  | ||||||
| 		buf[0x1c2] = 0x0e; |  | ||||||
| 		break; |  | ||||||
| 	case FS_FAT32: |  | ||||||
| 		buf[0x1c2] = 0x0c; |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
| 	if (IsChecked(IDC_DOSSTARTUP)) { |  | ||||||
| 		buf[0x1be] = 0x80;		// Set first partition bootable
 |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!write_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize*nSecs)) { |  | ||||||
| 		uprintf("Could not write MBR\n"); |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	fake_fd._ptr = (char*)hPhysicalDrive; |  | ||||||
| 	fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; |  | ||||||
| 	r = write_95b_mbr(&fake_fd); |  | ||||||
| 
 |  | ||||||
| 	if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) { |  | ||||||
| 		uprintf("Could not re-read MBR\n"); |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 	DumpBufferHex(buf, 0x200); |  | ||||||
| 
 |  | ||||||
| out: |  | ||||||
| 	safe_free(buf); |  | ||||||
| 	return r; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static BOOL ProcessFS_BR(HANDLE hLogicalVolume) |  | ||||||
| { |  | ||||||
| 	BOOL r = FALSE; |  | ||||||
| 	unsigned char* buf = NULL; |  | ||||||
| 	FILE fake_fd; |  | ||||||
| 	size_t SecSize = SelectedDrive.Geometry.BytesPerSector; |  | ||||||
| 	size_t nSecs = (0x400 + SecSize -1) / SecSize; |  | ||||||
| 
 |  | ||||||
| 	fake_fd._ptr = (char*)hLogicalVolume; |  | ||||||
| 	fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; |  | ||||||
| 	write_fat_32_br(&fake_fd, 0); |  | ||||||
| 
 |  | ||||||
| 	// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
 |  | ||||||
| 	// and FAT32 partitions - we need to correct this in the MBR
 |  | ||||||
| 	// TODO: something else for bootable GPT
 |  | ||||||
| 	buf = (unsigned char*)malloc(SecSize * nSecs); |  | ||||||
| 	if (buf == NULL) { |  | ||||||
| 		uprintf("Could not allocate memory for FS BR"); |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!read_sectors(hLogicalVolume, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize*nSecs)) { |  | ||||||
| 		uprintf("Could not read FS BR\n"); |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 	uprintf("FS_BR:\n"); |  | ||||||
| 	DumpBufferHex(buf, 0x400); |  | ||||||
| 
 |  | ||||||
| out: |  | ||||||
| 	safe_free(buf); |  | ||||||
| 	return r; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa364562%28v=vs.85%29.aspx
 |  | ||||||
|    Dismounting a volume is useful when a volume needs to disappear for a while. For |  | ||||||
|    example, an application that changes a volume file system from the FAT file system |  | ||||||
|    to the NTFS file system might use the following procedure. |  | ||||||
| 
 |  | ||||||
|    To change a volume file system |  | ||||||
| 
 |  | ||||||
|     Open a volume. |  | ||||||
|     Lock the volume. |  | ||||||
|     Format the volume. |  | ||||||
|     Dismount the volume. |  | ||||||
|     Unlock the volume. |  | ||||||
|     Close the volume handle. |  | ||||||
| 
 |  | ||||||
|    A dismounting operation removes the volume from the FAT file system awareness. |  | ||||||
|    When the operating system mounts the volume, it appears as an NTFS file system volume. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Standalone thread for the formatting operation |  | ||||||
|  */ |  | ||||||
| static void __cdecl FormatThread(void* param) |  | ||||||
| { |  | ||||||
| 	DWORD num = (DWORD)(uintptr_t)param; |  | ||||||
| 	HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE; |  | ||||||
| 	HANDLE hLogicalVolume = INVALID_HANDLE_VALUE; |  | ||||||
| 	char drive_name[] = "?:"; |  | ||||||
| 	int i; |  | ||||||
| //	DWORD size;
 |  | ||||||
| 
 |  | ||||||
| 	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
 |  | ||||||
| 
 |  | ||||||
| 	if (!CreatePartition(hPhysicalDrive)) { |  | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE; |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Make sure we can access the volume again before trying to format it
 |  | ||||||
| 	for (i=0; i<10; i++) { |  | ||||||
| 		Sleep(500); |  | ||||||
| 		hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE); |  | ||||||
| 		if (hLogicalVolume != INVALID_HANDLE_VALUE) { |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if (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
 |  | ||||||
| 
 |  | ||||||
| 	// Ideally we would lock, FSCTL_DISMOUNT_VOLUME, unlock and close our volume
 |  | ||||||
| 	// handle, but some explorer versions have problems with volumes disappear
 |  | ||||||
| // #define VOL_DISMOUNT
 |  | ||||||
| #ifdef VOL_DISMOUNT |  | ||||||
| 	// Dismount the volume
 |  | ||||||
| 	hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE); |  | ||||||
| 	if (hLogicalVolume == INVALID_HANDLE_VALUE) { |  | ||||||
| 		uprintf("Could not open the volume for dismount\n"); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!DeviceIoControl(hLogicalVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &size, NULL)) { |  | ||||||
| 		uprintf("Could not dismount volume\n"); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 	PrintStatus("Writing master boot record...\n"); |  | ||||||
| 	if (!ProcessMBR(hPhysicalDrive)) { |  | ||||||
| 		// Errorcode has already been set
 |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| #ifdef VOL_DISMOUNT |  | ||||||
| 	safe_unlockclose(hLogicalVolume); |  | ||||||
| //	Sleep(10000);
 |  | ||||||
| 	hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, FALSE); |  | ||||||
| 	if (hLogicalVolume == INVALID_HANDLE_VALUE) { |  | ||||||
| 		uprintf("Could not re-mount volume\n"); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 	if (IsChecked(IDC_DOSSTARTUP)) { |  | ||||||
| 		hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE); |  | ||||||
| 		if (hLogicalVolume == INVALID_HANDLE_VALUE) { |  | ||||||
| 			uprintf("Could not re-mount volume\n"); |  | ||||||
| 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
| 		PrintStatus("Writing filesystem boot record...\n"); |  | ||||||
| 		if (!ProcessFS_BR(hLogicalVolume)) { |  | ||||||
| 			// Errorcode has already been set
 |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
| 		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(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * Refresh the list of USB devices |  * Refresh the list of USB devices | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
							
								
								
									
										184
									
								
								rufus.h
									
										
									
									
									
								
							
							
						
						
									
										184
									
								
								rufus.h
									
										
									
									
									
								
							|  | @ -15,8 +15,8 @@ | ||||||
|  * You should have received a copy of the GNU General Public License |  * You should have received a copy of the GNU General Public License | ||||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 |  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  */ |  */ | ||||||
| #include <Windows.h> | #include <windows.h> | ||||||
| #include <winioctl.h>				// for MEDIA_TYPE | #include <winioctl.h>				// for DISK_GEOMETRY | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | @ -62,42 +62,6 @@ | ||||||
| #define safe_vsnprintf vsnprintf | #define safe_vsnprintf vsnprintf | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * Globals |  | ||||||
|  */ |  | ||||||
| extern HINSTANCE hMainInstance; |  | ||||||
| extern HWND hMainDialog; |  | ||||||
| extern HWND hStatus; |  | ||||||
| extern float fScale; |  | ||||||
| extern char szFolderPath[MAX_PATH]; |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Shared prototypes |  | ||||||
|  */ |  | ||||||
| extern char *WindowsErrorString(void); |  | ||||||
| extern void DumpBufferHex(void *buf, size_t size); |  | ||||||
| extern void PrintStatus(const char *format, ...); |  | ||||||
| extern void CenterDialog(HWND hDlg); |  | ||||||
| extern void CreateStatusBar(void); |  | ||||||
| extern INT_PTR CreateAboutBox(void); |  | ||||||
| extern HWND CreateTooltip(HWND hControl, const char* message, int duration); |  | ||||||
| extern void DestroyTooltip(HWND hWnd); |  | ||||||
| extern void DestroyAllTooltips(void); |  | ||||||
| extern void Notification(int type, char* text, char* title); |  | ||||||
| extern BOOL ExtractMSDOS(const char* path); |  | ||||||
| 
 |  | ||||||
| /* Basic String Array */ |  | ||||||
| typedef struct { |  | ||||||
| 	char** Table; |  | ||||||
| 	size_t Size; |  | ||||||
| 	size_t Index; |  | ||||||
| 	size_t Max; |  | ||||||
| } StrArray; |  | ||||||
| extern void StrArrayCreate(StrArray* arr, size_t initial_size); |  | ||||||
| extern void StrArrayAdd(StrArray* arr, const char* str); |  | ||||||
| extern void StrArrayClear(StrArray* arr); |  | ||||||
| extern void StrArrayDestroy(StrArray* arr); |  | ||||||
| 
 |  | ||||||
| #ifdef RUFUS_DEBUG | #ifdef RUFUS_DEBUG | ||||||
| extern void _uprintf(const char *format, ...); | extern void _uprintf(const char *format, ...); | ||||||
| #define uprintf(...) _uprintf(__VA_ARGS__) | #define uprintf(...) _uprintf(__VA_ARGS__) | ||||||
|  | @ -131,95 +95,73 @@ enum { | ||||||
| 	FS_MAX | 	FS_MAX | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /* Current drive info */ | ||||||
|  | typedef struct { | ||||||
|  | 	DWORD DeviceNumber; | ||||||
|  | 	LONGLONG DiskSize; | ||||||
|  | 	DISK_GEOMETRY Geometry; | ||||||
|  | 	DWORD FirstSector; | ||||||
|  | 	int FSType; | ||||||
|  | 	struct { | ||||||
|  | 		ULONG Allowed; | ||||||
|  | 		ULONG Default; | ||||||
|  | 	} ClusterSize[FS_MAX]; | ||||||
|  | } RUFUS_DRIVE_INFO; | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Globals | ||||||
|  |  */ | ||||||
|  | extern HINSTANCE hMainInstance; | ||||||
|  | extern HWND hMainDialog, hStatus, hDeviceList, hCapacity; | ||||||
|  | extern HWND hFileSystem, hClusterSize, hLabel;  | ||||||
|  | extern float fScale; | ||||||
|  | extern char szFolderPath[MAX_PATH]; | ||||||
|  | extern DWORD FormatStatus; | ||||||
|  | extern RUFUS_DRIVE_INFO SelectedDrive; | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Shared prototypes | ||||||
|  |  */ | ||||||
|  | extern char *WindowsErrorString(void); | ||||||
|  | extern void DumpBufferHex(void *buf, size_t size); | ||||||
|  | extern void PrintStatus(const char *format, ...); | ||||||
|  | extern void CenterDialog(HWND hDlg); | ||||||
|  | extern void CreateStatusBar(void); | ||||||
|  | extern INT_PTR CreateAboutBox(void); | ||||||
|  | extern HWND CreateTooltip(HWND hControl, const char* message, int duration); | ||||||
|  | extern void DestroyTooltip(HWND hWnd); | ||||||
|  | extern void DestroyAllTooltips(void); | ||||||
|  | extern void Notification(int type, char* text, char* title); | ||||||
|  | extern BOOL ExtractMSDOS(const char* path); | ||||||
|  | extern void __cdecl FormatThread(void* param); | ||||||
|  | extern BOOL CreatePartition(HANDLE hDrive); | ||||||
|  | extern HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive); | ||||||
|  | 
 | ||||||
|  | __inline static BOOL UnlockDrive(HANDLE hDrive) | ||||||
|  | { | ||||||
|  | 	DWORD size; | ||||||
|  | 	return DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Basic String Array */ | ||||||
|  | typedef struct { | ||||||
|  | 	char** Table; | ||||||
|  | 	size_t Size; | ||||||
|  | 	size_t Index; | ||||||
|  | 	size_t Max; | ||||||
|  | } StrArray; | ||||||
|  | extern void StrArrayCreate(StrArray* arr, size_t initial_size); | ||||||
|  | extern void StrArrayAdd(StrArray* arr, const char* str); | ||||||
|  | extern void StrArrayClear(StrArray* arr); | ||||||
|  | extern void StrArrayDestroy(StrArray* arr); | ||||||
|  | 
 | ||||||
|  | /* We need a redef of this MS structure */ | ||||||
| typedef struct { | typedef struct { | ||||||
| 	DWORD DeviceType; | 	DWORD DeviceType; | ||||||
| 	ULONG DeviceNumber; | 	ULONG DeviceNumber; | ||||||
| 	ULONG PartitionNumber; | 	ULONG PartitionNumber; | ||||||
| } STORAGE_DEVICE_NUMBER_REDEF; | } STORAGE_DEVICE_NUMBER_REDEF; | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * typedefs for the function prototypes. Use the something like: |  | ||||||
|  *   PF_DECL(FormatEx); |  | ||||||
|  * which translates to: |  | ||||||
|  *   FormatEx_t pfFormatEx = NULL; |  | ||||||
|  * in your code, to declare the entrypoint and then use: |  | ||||||
|  *   PF_INIT(FormatEx, fmifs); |  | ||||||
|  * which translates to: |  | ||||||
|  *   pfFormatEx = (FormatEx_t) GetProcAddress(GetDLLHandle("fmifs"), "FormatEx"); |  | ||||||
|  * to make it accessible. |  | ||||||
|  */ |  | ||||||
| static __inline HMODULE GetDLLHandle(char* szDLLName) |  | ||||||
| { |  | ||||||
| 	HMODULE h = NULL; |  | ||||||
| 	if ((h = GetModuleHandleA(szDLLName)) == NULL) |  | ||||||
| 		h = LoadLibraryA(szDLLName); |  | ||||||
| 	return h; |  | ||||||
| } |  | ||||||
| #define PF_DECL(proc) proc##_t pf##proc = NULL |  | ||||||
| #define PF_INIT(proc, dllname) pf##proc = (proc##_t) GetProcAddress(GetDLLHandle(#dllname), #proc) |  | ||||||
| #define PF_INIT_OR_OUT(proc, dllname) \ |  | ||||||
| 	PF_INIT(proc, dllname); if (pf##proc == NULL) { \ |  | ||||||
| 	uprintf("unable to access %s DLL: %s", #dllname, \ |  | ||||||
| 	WindowsErrorString()); goto out; } |  | ||||||
| 
 |  | ||||||
| /* Callback command types (some errorcode were filled from HPUSBFW V2.2.3 and their
 |  | ||||||
|    designation from msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */ |  | ||||||
| typedef enum { |  | ||||||
| 	FCC_PROGRESS, |  | ||||||
| 	FCC_DONE_WITH_STRUCTURE, |  | ||||||
| 	FCC_UNKNOWN2, |  | ||||||
| 	FCC_INCOMPATIBLE_FILE_SYSTEM, |  | ||||||
| 	FCC_UNKNOWN4, |  | ||||||
| 	FCC_UNKNOWN5, |  | ||||||
| 	FCC_ACCESS_DENIED, |  | ||||||
| 	FCC_MEDIA_WRITE_PROTECTED, |  | ||||||
| 	FCC_VOLUME_IN_USE, |  | ||||||
| 	FCC_CANT_QUICK_FORMAT, |  | ||||||
| 	FCC_UNKNOWNA, |  | ||||||
| 	FCC_DONE, |  | ||||||
| 	FCC_BAD_LABEL, |  | ||||||
| 	FCC_UNKNOWND, |  | ||||||
| 	FCC_OUTPUT, |  | ||||||
| 	FCC_STRUCTURE_PROGRESS, |  | ||||||
| 	FCC_CLUSTER_SIZE_TOO_SMALL, |  | ||||||
| 	FCC_CLUSTER_SIZE_TOO_BIG, |  | ||||||
| 	FCC_VOLUME_TOO_SMALL, |  | ||||||
| 	FCC_VOLUME_TOO_BIG, |  | ||||||
| 	FCC_NO_MEDIA_IN_DRIVE, |  | ||||||
| } FILE_SYSTEM_CALLBACK_COMMAND; |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
| 	DWORD Lines; |  | ||||||
| 	CHAR* Output; |  | ||||||
| } TEXTOUTPUT, *PTEXTOUTPUT; |  | ||||||
| 
 |  | ||||||
| typedef BOOLEAN (__stdcall *FILE_SYSTEM_CALLBACK)( |  | ||||||
| 	FILE_SYSTEM_CALLBACK_COMMAND Command, |  | ||||||
| 	ULONG                        Action, |  | ||||||
| 	PVOID                        pData |  | ||||||
| ); |  | ||||||
| 
 |  | ||||||
| /* Parameter names aligned to
 |  | ||||||
|    http://msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */
 |  | ||||||
| typedef VOID (WINAPI *FormatEx_t)( |  | ||||||
| 	WCHAR*               DriveRoot, |  | ||||||
| 	MEDIA_TYPE           MediaType,		// See WinIoCtl.h
 |  | ||||||
| 	WCHAR*               FileSystemTypeName, |  | ||||||
| 	WCHAR*               Label, |  | ||||||
| 	BOOL                 QuickFormat, |  | ||||||
| 	ULONG                DesiredUnitAllocationSize, |  | ||||||
| 	FILE_SYSTEM_CALLBACK Callback |  | ||||||
| ); |  | ||||||
| 
 |  | ||||||
| /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa383357.aspx */ |  | ||||||
| typedef enum  { |  | ||||||
| 	FPF_COMPRESSED   = 0x01  |  | ||||||
| } FILE_SYSTEM_PROP_FLAG; |  | ||||||
| 
 |  | ||||||
| typedef BOOLEAN (WINAPI* EnableVolumeCompression_t)( |  | ||||||
| 	WCHAR*          DriveRoot, |  | ||||||
| 	ULONG           CompressionFlags	// FILE_SYSTEM_PROP_FLAG
 |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| /* Custom application errors */ | /* Custom application errors */ | ||||||
| #define FAC(f)                         (f<<16) | #define FAC(f)                         (f<<16) | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								rufus.rc
									
										
									
									
									
								
							|  | @ -63,7 +63,7 @@ BEGIN | ||||||
|     DEFPUSHBUTTON   "OK",IDOK,231,175,50,14,WS_GROUP |     DEFPUSHBUTTON   "OK",IDOK,231,175,50,14,WS_GROUP | ||||||
|     CONTROL         "<a href=""https://github.com/pbatard/rufus/wiki/Rufus"">https://github.com/pbatard/rufus</a>",IDC_ABOUT_RUFUS_URL, |     CONTROL         "<a href=""https://github.com/pbatard/rufus/wiki/Rufus"">https://github.com/pbatard/rufus</a>",IDC_ABOUT_RUFUS_URL, | ||||||
|                     "SysLink",WS_TABSTOP,46,47,114,9 |                     "SysLink",WS_TABSTOP,46,47,114,9 | ||||||
|     LTEXT           "Version 1.0.0 (Build 57)",IDC_STATIC,46,19,78,8 |     LTEXT           "Version 1.0.0 (Build 58)",IDC_STATIC,46,19,78,8 | ||||||
|     PUSHBUTTON      "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP |     PUSHBUTTON      "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP | ||||||
|     EDITTEXT        IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL |     EDITTEXT        IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL | ||||||
|     LTEXT           "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 |     LTEXT           "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 | ||||||
|  | @ -162,8 +162,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 1,0,0,57 |  FILEVERSION 1,0,0,58 | ||||||
|  PRODUCTVERSION 1,0,0,57 |  PRODUCTVERSION 1,0,0,58 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -180,13 +180,13 @@ BEGIN | ||||||
|         BEGIN |         BEGIN | ||||||
|             VALUE "CompanyName", "akeo.ie" |             VALUE "CompanyName", "akeo.ie" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "1.0.0.57" |             VALUE "FileVersion", "1.0.0.58" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" |             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||||
|             VALUE "OriginalFilename", "rufus.exe" |             VALUE "OriginalFilename", "rufus.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "1.0.0.57" |             VALUE "ProductVersion", "1.0.0.58" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  | @ -212,7 +212,7 @@ IDI_ICON                ICON                    "rufus.ico" | ||||||
| 
 | 
 | ||||||
| STRINGTABLE | STRINGTABLE | ||||||
| BEGIN | BEGIN | ||||||
|     IDS_VERSION             "Rufus v1.0.0.57" |     IDS_VERSION             "Rufus v1.0.0.58" | ||||||
| END | END | ||||||
| 
 | 
 | ||||||
| #endif    // English resources | #endif    // English resources | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								stdio.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								stdio.c
									
										
									
									
									
								
							|  | @ -16,6 +16,10 @@ | ||||||
|  * You should have received a copy of the GNU General Public License |  * You should have received a copy of the GNU General Public License | ||||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 |  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  */ |  */ | ||||||
|  | #ifdef _CRTDBG_MAP_ALLOC | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <crtdbg.h> | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #include <windows.h> | #include <windows.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue