mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[format] add large FAT32 support
* Based on fat32format from Ridgecrop Consultants Ltd: http://www.ridgecrop.demon.co.uk/index.htm?fat32format.htm * Initial implementation by Tom Ehlert of DriveSnapshot: http://www.drivesnapshot.de/en/index.htm * Closes #101
This commit is contained in:
		
							parent
							
								
									8dc5429d9f
								
							
						
					
					
						commit
						22800bb8a5
					
				
					 6 changed files with 473 additions and 29 deletions
				
			
		
							
								
								
									
										381
									
								
								src/format.c
									
										
									
									
									
								
							
							
						
						
									
										381
									
								
								src/format.c
									
										
									
									
									
								
							|  | @ -1,6 +1,7 @@ | |||
| /*
 | ||||
|  * Rufus: The Reliable USB Formatting Utility | ||||
|  * Formatting function calls | ||||
|  * Copyright (c) 2007-2009 Tom Thornhill/Ridgecrop | ||||
|  * Copyright (c) 2011-2012 Pete Batard <pete@akeo.ie> | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  | @ -251,6 +252,349 @@ static void ToValidLabel(WCHAR* name, BOOL bFAT) | |||
| 	wchar_to_utf8_no_alloc(name, iso_report.usb_label, sizeof(iso_report.usb_label)); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 28.2  CALCULATING THE VOLUME SERIAL NUMBER | ||||
|  * | ||||
|  * For example, say a disk was formatted on 26 Dec 95 at 9:55 PM and 41.94 | ||||
|  * seconds.  DOS takes the date and time just before it writes it to the | ||||
|  * disk. | ||||
|  *  | ||||
|  * Low order word is calculated:               Volume Serial Number is: | ||||
|  * Month & Day         12/26   0c1ah | ||||
|  * Sec & Hundrenths    41:94   295eh               3578:1d02 | ||||
|  * ----- | ||||
|  * 3578h | ||||
|  *  | ||||
|  * High order word is calculated: | ||||
|  * Hours & Minutes     21:55   1537h | ||||
|  * Year                1995    07cbh | ||||
|  * ----- | ||||
|  * 1d02h | ||||
|  */ | ||||
| static DWORD GetVolumeID(void) | ||||
| { | ||||
| 	SYSTEMTIME s; | ||||
| 	DWORD d; | ||||
| 	WORD lo,hi,tmp; | ||||
| 
 | ||||
| 	GetLocalTime(&s); | ||||
| 
 | ||||
| 	lo = s.wDay + (s.wMonth << 8); | ||||
| 	tmp = (s.wMilliseconds/10) + (s.wSecond << 8); | ||||
| 	lo += tmp; | ||||
| 
 | ||||
| 	hi = s.wMinute + (s.wHour << 8); | ||||
| 	hi += s.wYear; | ||||
| 
 | ||||
| 	d = lo + (hi << 16); | ||||
| 	return d; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This is the Microsoft calculation from FATGEN | ||||
|  *  | ||||
|  * DWORD RootDirSectors = 0; | ||||
|  * DWORD TmpVal1, TmpVal2, FATSz; | ||||
|  * | ||||
|  * TmpVal1 = DskSize - (ReservedSecCnt + RootDirSectors); | ||||
|  * TmpVal2 = (256 * SecPerClus) + NumFATs; | ||||
|  * TmpVal2 = TmpVal2 / 2; | ||||
|  * FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2; | ||||
|  * | ||||
|  * return( FatSz ); | ||||
|  */ | ||||
| static DWORD GetFATSizeSectors(DWORD DskSize, DWORD ReservedSecCnt, DWORD SecPerClus, DWORD NumFATs, DWORD BytesPerSect) | ||||
| { | ||||
| 	ULONGLONG Numerator, Denominator; | ||||
| 	ULONGLONG FatElementSize = 4; | ||||
| 	ULONGLONG FatSz; | ||||
| 
 | ||||
| 	// This is based on 
 | ||||
| 	// http://hjem.get2net.dk/rune_moeller_barnkob/filesystems/fat.html
 | ||||
| 	Numerator = FatElementSize * (DskSize - ReservedSecCnt); | ||||
| 	Denominator = (SecPerClus * BytesPerSect) + (FatElementSize * NumFATs); | ||||
| 	FatSz = Numerator / Denominator; | ||||
| 	// round up
 | ||||
| 	FatSz += 1; | ||||
| 
 | ||||
| 	return (DWORD)FatSz; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Large FAT32 volume formatting from fat32format by Tom Thornhill | ||||
|  * http://www.ridgecrop.demon.co.uk/index.htm?fat32format.htm
 | ||||
|  */ | ||||
| // TODO: disable slow format for > 32 GB FAT32
 | ||||
| static BOOL FormatFAT32(DWORD DriveIndex) | ||||
| { | ||||
| 	BOOL r = FALSE; | ||||
| 	char DriveLetter; | ||||
| 	DWORD i; | ||||
| 	HANDLE hLogicalVolume; | ||||
| 	DWORD cbRet; | ||||
| 	DISK_GEOMETRY dgDrive; | ||||
| 	PARTITION_INFORMATION piDrive; | ||||
| 	// Recommended values
 | ||||
| 	DWORD ReservedSectCount = 32; | ||||
| 	DWORD NumFATs = 2; | ||||
| 	DWORD BackupBootSect = 6; | ||||
| 	DWORD VolumeId = 0; // calculated before format
 | ||||
| 	WCHAR wLabel[64], wDriveName[] = L"#:\\"; | ||||
| 	DWORD BurstSize = 128; // Zero in blocks of 64K typically
 | ||||
| 
 | ||||
| 	// Calculated later
 | ||||
| 	DWORD FatSize = 0;  | ||||
| 	DWORD BytesPerSect = 0; | ||||
| 	DWORD ClusterSize = 0; | ||||
| 	DWORD SectorsPerCluster = 0; | ||||
| 	DWORD TotalSectors = 0; | ||||
| 	DWORD SystemAreaSize = 0; | ||||
| 	DWORD UserAreaSize = 0; | ||||
| 	ULONGLONG qTotalSectors = 0; | ||||
| 
 | ||||
| 	// Structures to be written to the disk
 | ||||
| 	FAT_BOOTSECTOR32 *pFAT32BootSect = NULL; | ||||
| 	FAT_FSINFO *pFAT32FsInfo = NULL; | ||||
| 	DWORD *pFirstSectOfFat = NULL; | ||||
| 	BYTE* pZeroSect = NULL; | ||||
| 	char VolId[12] = "NO NAME    "; | ||||
| 
 | ||||
| 	// Debug temp vars
 | ||||
| 	ULONGLONG FatNeeded, ClusterCount; | ||||
| 
 | ||||
| 	PrintStatus(0, TRUE, "Formatting..."); | ||||
| 	uprintf("Using large FAT32 format method\n"); | ||||
| 	VolumeId = GetVolumeID(); | ||||
| 
 | ||||
| 	// Open the drive (volume should already be locked)
 | ||||
| 	hLogicalVolume = GetDriveHandle(DriveIndex, &DriveLetter, TRUE, FALSE); | ||||
| 	if (IS_ERROR(FormatStatus)) goto out; | ||||
| 	if (hLogicalVolume == INVALID_HANDLE_VALUE) | ||||
| 		die("Could not access logical volume\n", ERROR_OPEN_FAILED); | ||||
| 
 | ||||
| 	// Make sure we get exclusive access
 | ||||
| 	if (!UnmountDrive(hLogicalVolume)) | ||||
| 		return r; | ||||
| 
 | ||||
| 	// Work out drive params
 | ||||
| 	if (!DeviceIoControl (hLogicalVolume, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dgDrive, | ||||
| 		sizeof(dgDrive), &cbRet, NULL)) { | ||||
| 		die("Failed to get device geometry\n", ERROR_NOT_SUPPORTED); | ||||
| 	} | ||||
| 	if (IS_ERROR(FormatStatus)) goto out; | ||||
| 	if (!DeviceIoControl (hLogicalVolume, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &piDrive, | ||||
| 		sizeof(piDrive), &cbRet, NULL)) { | ||||
| 		die("Failed to get parition info\n", ERROR_NOT_SUPPORTED); | ||||
| 	} | ||||
| 
 | ||||
| 	BytesPerSect = dgDrive.BytesPerSector; | ||||
| 
 | ||||
| 	// Checks on Disk Size
 | ||||
| 	qTotalSectors = piDrive.PartitionLength.QuadPart/dgDrive.BytesPerSector; | ||||
| 	// Low end limit - 65536 sectors
 | ||||
| 	if (qTotalSectors < 65536) { | ||||
| 		// Most FAT32 implementations would probably mount this volume just fine,
 | ||||
| 		// but the spec says that we shouldn't do this, so we won't
 | ||||
| 		die("This drive is too small for FAT32 - there must be at least 64K clusters\n", APPERR(ERROR_INVALID_CLUSTER_SIZE)); | ||||
| 	} | ||||
| 
 | ||||
| 	if (qTotalSectors >= 0xffffffff) { | ||||
| 		// This is a more fundamental limitation on FAT32 - the total sector count in the root dir
 | ||||
| 		// ís 32bit. With a bit of creativity, FAT32 could be extended to handle at least 2^28 clusters
 | ||||
| 		// There would need to be an extra field in the FSInfo sector, and the old sector count could
 | ||||
| 		// be set to 0xffffffff. This is non standard though, the Windows FAT driver FASTFAT.SYS won't
 | ||||
| 		// understand this. Perhaps a future version of FAT32 and FASTFAT will handle this.
 | ||||
| 		die ("This drive is too big for FAT32 - max 2TB supported\n", APPERR(ERROR_INVALID_VOLUME_SIZE)); | ||||
| 	} | ||||
| 
 | ||||
| 	pFAT32BootSect = (FAT_BOOTSECTOR32*) calloc(BytesPerSect, 1); | ||||
| 	pFAT32FsInfo = (FAT_FSINFO*) calloc(BytesPerSect, 1); | ||||
| 	pFirstSectOfFat = (DWORD*) calloc(BytesPerSect, 1); | ||||
| 	if (!pFAT32BootSect || !pFAT32FsInfo || !pFirstSectOfFat) { | ||||
| 		die("Failed to allocate memory\n", ERROR_NOT_ENOUGH_MEMORY); | ||||
| 	} | ||||
| 
 | ||||
| 	// fill out the boot sector and fs info
 | ||||
| 	pFAT32BootSect->sJmpBoot[0]=0xEB; | ||||
| 	pFAT32BootSect->sJmpBoot[1]=0x5A; | ||||
| 	pFAT32BootSect->sJmpBoot[2]=0x90; | ||||
| 	strncpy((char*)pFAT32BootSect->sOEMName, "MSWIN4.1", 8); | ||||
| 	pFAT32BootSect->wBytsPerSec = (WORD) BytesPerSect; | ||||
| 
 | ||||
| 	ClusterSize = ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)); | ||||
| 	SectorsPerCluster = ClusterSize / BytesPerSect; | ||||
| 
 | ||||
| 	pFAT32BootSect->bSecPerClus = (BYTE) SectorsPerCluster ; | ||||
| 	pFAT32BootSect->wRsvdSecCnt = (WORD) ReservedSectCount; | ||||
| 	pFAT32BootSect->bNumFATs = (BYTE) NumFATs; | ||||
| 	pFAT32BootSect->wRootEntCnt = 0; | ||||
| 	pFAT32BootSect->wTotSec16 = 0; | ||||
| 	pFAT32BootSect->bMedia = 0xF8; | ||||
| 	pFAT32BootSect->wFATSz16 = 0; | ||||
| 	pFAT32BootSect->wSecPerTrk = (WORD) dgDrive.SectorsPerTrack; | ||||
| 	pFAT32BootSect->wNumHeads = (WORD) dgDrive.TracksPerCylinder; | ||||
| 	pFAT32BootSect->dHiddSec = (DWORD) piDrive.HiddenSectors; | ||||
| 	TotalSectors = (DWORD)  (piDrive.PartitionLength.QuadPart/dgDrive.BytesPerSector); | ||||
| 	pFAT32BootSect->dTotSec32 = TotalSectors; | ||||
| 
 | ||||
| 	FatSize = GetFATSizeSectors(pFAT32BootSect->dTotSec32, pFAT32BootSect->wRsvdSecCnt,  | ||||
| 		pFAT32BootSect->bSecPerClus, pFAT32BootSect->bNumFATs, BytesPerSect); | ||||
| 
 | ||||
| 	pFAT32BootSect->dFATSz32 = FatSize; | ||||
| 	pFAT32BootSect->wExtFlags = 0; | ||||
| 	pFAT32BootSect->wFSVer = 0; | ||||
| 	pFAT32BootSect->dRootClus = 2; | ||||
| 	pFAT32BootSect->wFSInfo = 1; | ||||
| 	pFAT32BootSect->wBkBootSec = (WORD) BackupBootSect; | ||||
| 	pFAT32BootSect->bDrvNum = 0x80; | ||||
| 	pFAT32BootSect->Reserved1 = 0; | ||||
| 	pFAT32BootSect->bBootSig = 0x29; | ||||
| 
 | ||||
| 	pFAT32BootSect->dBS_VolID = VolumeId; | ||||
| 	memcpy(pFAT32BootSect->sVolLab, VolId, 11); | ||||
| 	memcpy(pFAT32BootSect->sBS_FilSysType, "FAT32   ", 8); | ||||
| 	((BYTE*)pFAT32BootSect)[510] = 0x55; | ||||
| 	((BYTE*)pFAT32BootSect)[511] = 0xaa; | ||||
| 
 | ||||
| 	// FATGEN103.DOC says "NOTE: Many FAT documents mistakenly say that this 0xAA55 signature occupies the "last 2 bytes of 
 | ||||
| 	// the boot sector". This statement is correct if - and only if - BPB_BytsPerSec is 512. If BPB_BytsPerSec is greater than 
 | ||||
| 	// 512, the offsets of these signature bytes do not change (although it is perfectly OK for the last two bytes at the end 
 | ||||
| 	// of the boot sector to also contain this signature)." 
 | ||||
| 	// 
 | ||||
| 	// Windows seems to only check the bytes at offsets 510 and 511. Other OSs might check the ones at the end of the sector,
 | ||||
| 	// so we'll put them there too.
 | ||||
| 	if (BytesPerSect != 512) { | ||||
| 		((BYTE*)pFAT32BootSect)[BytesPerSect-2] = 0x55; | ||||
| 		((BYTE*)pFAT32BootSect)[BytesPerSect-1] = 0xaa; | ||||
| 	} | ||||
| 
 | ||||
| 	// FSInfo sect
 | ||||
| 	pFAT32FsInfo->dLeadSig = 0x41615252; | ||||
| 	pFAT32FsInfo->dStrucSig = 0x61417272; | ||||
| 	pFAT32FsInfo->dFree_Count = (DWORD) -1; | ||||
| 	pFAT32FsInfo->dNxt_Free = (DWORD) -1; | ||||
| 	pFAT32FsInfo->dTrailSig = 0xaa550000; | ||||
| 
 | ||||
| 	// First FAT Sector
 | ||||
| 	pFirstSectOfFat[0] = 0x0ffffff8;  // Reserved cluster 1 media id in low byte
 | ||||
| 	pFirstSectOfFat[1] = 0x0fffffff;  // Reserved cluster 2 EOC
 | ||||
| 	pFirstSectOfFat[2] = 0x0fffffff;  // end of cluster chain for root dir
 | ||||
| 
 | ||||
| 	// Write boot sector, fats
 | ||||
| 	// Sector 0 Boot Sector
 | ||||
| 	// Sector 1 FSInfo 
 | ||||
| 	// Sector 2 More boot code - we write zeros here
 | ||||
| 	// Sector 3 unused
 | ||||
| 	// Sector 4 unused
 | ||||
| 	// Sector 5 unused
 | ||||
| 	// Sector 6 Backup boot sector
 | ||||
| 	// Sector 7 Backup FSInfo sector
 | ||||
| 	// Sector 8 Backup 'more boot code'
 | ||||
| 	// zero'd sectors upto ReservedSectCount
 | ||||
| 	// FAT1  ReservedSectCount to ReservedSectCount + FatSize
 | ||||
| 	// ...
 | ||||
| 	// FATn  ReservedSectCount to ReservedSectCount + FatSize
 | ||||
| 	// RootDir - allocated to cluster2
 | ||||
| 
 | ||||
| 	UserAreaSize = TotalSectors - ReservedSectCount - (NumFATs*FatSize); | ||||
| 	ClusterCount = UserAreaSize / SectorsPerCluster; | ||||
| 
 | ||||
| 	// Sanity check for a cluster count of >2^28, since the upper 4 bits of the cluster values in 
 | ||||
| 	// the FAT are reserved.
 | ||||
| 	if (ClusterCount > 0x0FFFFFFF) { | ||||
| 		die("This drive has more than 2^28 clusters, try to specify a larger cluster size or use the default\n", | ||||
| 			ERROR_INVALID_CLUSTER_SIZE); | ||||
| 	} | ||||
| 
 | ||||
| 	// Sanity check - < 64K clusters means that the volume will be misdetected as FAT16
 | ||||
| 	if (ClusterCount < 65536) { | ||||
| 		die("FAT32 must have at least 65536 clusters, try to specify a smaller cluster size or use the default\n", | ||||
| 			ERROR_INVALID_CLUSTER_SIZE); | ||||
| 	} | ||||
| 
 | ||||
| 	// Sanity check, make sure the fat is big enough
 | ||||
| 	// Convert the cluster count into a Fat sector count, and check the fat size value we calculated 
 | ||||
| 	// earlier is OK.
 | ||||
| 	FatNeeded = ClusterCount * 4; | ||||
| 	FatNeeded += (BytesPerSect-1); | ||||
| 	FatNeeded /= BytesPerSect; | ||||
| 	if (FatNeeded > FatSize) { | ||||
| 		die("This drive is too big for large FAT32 format\n", APPERR(ERROR_INVALID_VOLUME_SIZE)); | ||||
| 	} | ||||
| 
 | ||||
| 	// Now we're commited - print some info first
 | ||||
| 	uprintf("Size : %gGB %u sectors\n", (double) (piDrive.PartitionLength.QuadPart / (1000*1000*1000)), TotalSectors); | ||||
| 	uprintf("Cluster size %d bytes, %d Bytes Per Sector\n", SectorsPerCluster*BytesPerSect, BytesPerSect); | ||||
| 	uprintf("Volume ID is %x:%x\n", VolumeId>>16, VolumeId&0xffff); | ||||
| 	uprintf("%d Reserved Sectors, %d Sectors per FAT, %d FATs\n", ReservedSectCount, FatSize, NumFATs); | ||||
| 	uprintf("%d Total clusters\n", ClusterCount); | ||||
| 
 | ||||
| 	// Fix up the FSInfo sector
 | ||||
| 	pFAT32FsInfo->dFree_Count = (UserAreaSize/SectorsPerCluster) - 1; | ||||
| 	pFAT32FsInfo->dNxt_Free = 3; // clusters 0-1 resered, we used cluster 2 for the root dir
 | ||||
| 
 | ||||
| 	uprintf("%d Free Clusters\n", pFAT32FsInfo->dFree_Count); | ||||
| 	// Work out the Cluster count
 | ||||
| 
 | ||||
| 	// First zero out ReservedSect + FatSize * NumFats + SectorsPerCluster
 | ||||
| 	SystemAreaSize = ReservedSectCount + (NumFATs*FatSize) + SectorsPerCluster; | ||||
| 	uprintf("Clearing out %d sectors for reserved sectors, FATs and root cluster...\n", SystemAreaSize); | ||||
| 
 | ||||
| 	// Not the most effective, but easy on RAM
 | ||||
| 	pZeroSect = (BYTE*)calloc(BytesPerSect, BurstSize); | ||||
| 	if (!pZeroSect) { | ||||
| 		die("Failed to allocate memory\n", ERROR_NOT_ENOUGH_MEMORY); | ||||
| 	} | ||||
| 
 | ||||
| 	format_percent = 0.0f; | ||||
| 	for (i=0; i<(SystemAreaSize+BurstSize-1); i+=BurstSize) { | ||||
| 		format_percent = (100.0f*i)/(1.0f*(SystemAreaSize+BurstSize)); | ||||
| 		PrintStatus(0, FALSE, "Formatting: %d%% completed.", (int)format_percent); | ||||
| 		UpdateProgress(OP_FORMAT, format_percent); | ||||
| 		if (IS_ERROR(FormatStatus)) goto out;	// For cancellation
 | ||||
| 		if (write_sectors(hLogicalVolume, BytesPerSect, i, BurstSize, pZeroSect) != (BytesPerSect*BurstSize)) { | ||||
| 			die("Error clearing reserved sectors\n", ERROR_WRITE_FAULT); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	uprintf ("Initialising reserved sectors and FATs...\n"); | ||||
| 	// Now we should write the boot sector and fsinfo twice, once at 0 and once at the backup boot sect position
 | ||||
| 	for (i=0; i<2; i++) { | ||||
| 		int SectorStart = (i==0) ? 0 : BackupBootSect; | ||||
| 		write_sectors(hLogicalVolume, BytesPerSect, SectorStart, 1, pFAT32BootSect); | ||||
| 		write_sectors(hLogicalVolume, BytesPerSect, SectorStart+1, 1, pFAT32FsInfo); | ||||
| 	} | ||||
| 
 | ||||
| 	// Write the first fat sector in the right places
 | ||||
| 	for ( i=0; i<NumFATs; i++ ) { | ||||
| 		int SectorStart = ReservedSectCount + (i * FatSize ); | ||||
| 		uprintf("FAT #%d sector at address: %d\n", i, SectorStart); | ||||
| 		write_sectors(hLogicalVolume, BytesPerSect, SectorStart, 1, pFirstSectOfFat); | ||||
| 	} | ||||
| 
 | ||||
| 	// Set the FAT32 volume label
 | ||||
| 	GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel)); | ||||
| 	ToValidLabel(wLabel, TRUE); | ||||
| 	wDriveName[0] = DriveLetter; | ||||
| 	// Handle must be closed for SetVolumeLabel to work
 | ||||
| 	safe_closehandle(hLogicalVolume); | ||||
| 
 | ||||
| 	PrintStatus(0, TRUE, "Setting Label (This can take while)..."); | ||||
| 	if (!SetVolumeLabelW(wDriveName, wLabel)) { | ||||
| 		uprintf("Could not set label: %s\n", WindowsErrorString()); | ||||
| 	} | ||||
| 	uprintf("Format completed.\n"); | ||||
| 	r = TRUE; | ||||
| 
 | ||||
| out: | ||||
| 	safe_closehandle(hLogicalVolume); | ||||
| 	safe_free(pFAT32BootSect); | ||||
| 	safe_free(pFAT32FsInfo); | ||||
| 	safe_free(pFirstSectOfFat); | ||||
| 	safe_free(pZeroSect); | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Call on fmifs.dll's FormatEx() to format the drive | ||||
|  */ | ||||
|  | @ -398,11 +742,24 @@ static BOOL AnalyzePBR(HANDLE hLogicalVolume) | |||
| 
 | ||||
| static BOOL ClearMBR(HANDLE hPhysicalDrive) | ||||
| { | ||||
| 	FILE fake_fd = { 0 }; | ||||
| 	BOOL r = FALSE; | ||||
| 	// Clearing the first 64K seems to help with reluctant access to large drive
 | ||||
| 	size_t SectorSize = 65536; | ||||
| 	unsigned char* pBuf = (unsigned char*) calloc(SectorSize, 1); | ||||
| 
 | ||||
| 	fake_fd._ptr = (char*)hPhysicalDrive; | ||||
| 	fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; | ||||
| 	return clear_mbr(&fake_fd); | ||||
| 	PrintStatus(0, TRUE, "Clearing MBR..."); | ||||
| 	if (pBuf == NULL) { | ||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if ((IS_ERROR(FormatStatus)) || (write_sectors(hPhysicalDrive, SectorSize, 0, 1, pBuf) != SectorSize)) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 	r = TRUE; | ||||
| 
 | ||||
| out: | ||||
| 	safe_free(pBuf); | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -741,6 +1098,10 @@ static BOOL RemountVolume(char drive_letter) | |||
|  */ | ||||
| DWORD WINAPI FormatThread(LPVOID param) | ||||
| { | ||||
| 	int r; | ||||
| 	int fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)); | ||||
| 	int dt = (int)ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)); | ||||
| 	BOOL ret; | ||||
| 	DWORD num = (DWORD)(uintptr_t)param; | ||||
| 	HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE; | ||||
| 	HANDLE hLogicalVolume = INVALID_HANDLE_VALUE; | ||||
|  | @ -749,7 +1110,6 @@ DWORD WINAPI FormatThread(LPVOID param) | |||
| 	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) { | ||||
|  | @ -839,7 +1199,8 @@ DWORD WINAPI FormatThread(LPVOID param) | |||
| 	// 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; | ||||
| 		if (!FormatStatus) | ||||
| 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; | ||||
| 		goto out; | ||||
| 	}  | ||||
| 	UpdateProgress(OP_ZERO_MBR, -1.0f); | ||||
|  | @ -853,7 +1214,11 @@ DWORD WINAPI FormatThread(LPVOID param) | |||
| 	// Add a small delay after partitioning to be safe
 | ||||
| 	Sleep(200); | ||||
| 
 | ||||
| 	if (!FormatDrive(drive_name[0])) { | ||||
| 	// If FAT32 is requested and we have a large drive (>32 GB) use 
 | ||||
| 	// large FAT32 format, else use MS's FormatEx.
 | ||||
| 	ret = ((fs == FS_FAT32) && (SelectedDrive.DiskSize > LARGE_FAT32_SIZE))? | ||||
| 		FormatFAT32(num):FormatDrive(drive_name[0]); | ||||
| 	if (!ret) { | ||||
| 		// Error will be set by FormatDrive() in FormatStatus
 | ||||
| 		uprintf("Format error: %s\n", StrError(FormatStatus)); | ||||
| 		goto out; | ||||
|  | @ -867,8 +1232,6 @@ DWORD WINAPI FormatThread(LPVOID param) | |||
| 	} | ||||
| 	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 
 | ||||
|  |  | |||
							
								
								
									
										51
									
								
								src/format.h
									
										
									
									
									
								
							
							
						
						
									
										51
									
								
								src/format.h
									
										
									
									
									
								
							|  | @ -1,6 +1,7 @@ | |||
| /*
 | ||||
|  * Rufus: The Reliable USB Formatting Utility | ||||
|  * Formatting function calls | ||||
|  * Copyright (c) 2007-2009 Tom Thornhill/Ridgecrop | ||||
|  * Copyright (c) 2011-2012 Pete Batard <pete@akeo.ie> | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  | @ -103,3 +104,53 @@ typedef BOOLEAN (WINAPI* EnableVolumeCompression_t)( | |||
| 	WCHAR*          DriveRoot, | ||||
| 	ULONG           CompressionFlags	// FILE_SYSTEM_PROP_FLAG
 | ||||
| ); | ||||
| 
 | ||||
| /* Large FAT32 */ | ||||
| #pragma pack(push, 1) | ||||
| typedef struct tagFAT_BOOTSECTOR32 | ||||
| { | ||||
| 	// Common fields.
 | ||||
| 	BYTE sJmpBoot[3]; | ||||
| 	BYTE sOEMName[8]; | ||||
| 	WORD wBytsPerSec; | ||||
| 	BYTE bSecPerClus; | ||||
| 	WORD wRsvdSecCnt; | ||||
| 	BYTE bNumFATs; | ||||
| 	WORD wRootEntCnt; | ||||
| 	WORD wTotSec16;           // if zero, use dTotSec32 instead
 | ||||
| 	BYTE bMedia; | ||||
| 	WORD wFATSz16; | ||||
| 	WORD wSecPerTrk; | ||||
| 	WORD wNumHeads; | ||||
| 	DWORD dHiddSec; | ||||
| 	DWORD dTotSec32; | ||||
| 	// Fat 32/16 only
 | ||||
| 	DWORD dFATSz32; | ||||
| 	WORD wExtFlags; | ||||
| 	WORD wFSVer; | ||||
| 	DWORD dRootClus; | ||||
| 	WORD wFSInfo; | ||||
| 	WORD wBkBootSec; | ||||
| 	BYTE Reserved[12]; | ||||
| 	BYTE bDrvNum; | ||||
| 	BYTE Reserved1; | ||||
| 	BYTE bBootSig;           // == 0x29 if next three fields are ok
 | ||||
| 	DWORD dBS_VolID; | ||||
| 	BYTE sVolLab[11]; | ||||
| 	BYTE sBS_FilSysType[8]; | ||||
| } FAT_BOOTSECTOR32; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	DWORD dLeadSig;         // 0x41615252
 | ||||
| 	BYTE sReserved1[480];   // zeros
 | ||||
| 	DWORD dStrucSig;        // 0x61417272
 | ||||
| 	DWORD dFree_Count;      // 0xFFFFFFFF
 | ||||
| 	DWORD dNxt_Free;        // 0xFFFFFFFF
 | ||||
| 	BYTE sReserved2[12];    // zeros
 | ||||
| 	DWORD dTrailSig;        // 0xAA550000
 | ||||
| } FAT_FSINFO; | ||||
| #pragma pack(pop) | ||||
| 
 | ||||
| #define die(msg, err) do { uprintf(msg); \ | ||||
| 	FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|err; \ | ||||
| 	goto out; } while(0) | ||||
|  |  | |||
|  | @ -42,6 +42,10 @@ const char* additional_copyrights = | |||
| "http://e2fsprogs.sourceforge.net\r\n" | ||||
| "GNU General Public License (GPL) v3 compatible\r\n" | ||||
| "\r\n" | ||||
| "Large FAT32 volume formatting from fat32format by Tom Thornhill:\r\n" | ||||
| "http://www.ridgecrop.demon.co.uk/index.htm?fat32format.htm\r\n" | ||||
| "GNU General Public License (GPL) v2 or later\r\n" | ||||
| "\r\n" | ||||
| "fmifs.dll usage based on Formatx by Mark Russinovich:\r\n" | ||||
| "http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/source/fmifs.shtml\r\n" | ||||
| "http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/fmifs\r\n" | ||||
|  |  | |||
							
								
								
									
										53
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										53
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -124,7 +124,7 @@ static int64_t last_iso_blocking_status; | |||
|  */ | ||||
| static int nb_slots[OP_MAX]; | ||||
| static float slot_end[OP_MAX+1];	// shifted +1 so that we can substract 1 to OP indexes
 | ||||
| static float previous_end = 0.0f; | ||||
| static float previous_end; | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert a partition type to its human readable form using | ||||
|  | @ -164,7 +164,7 @@ static BOOL DefineClusterSizes(void) | |||
| 	} | ||||
| 
 | ||||
| /*
 | ||||
|  * The following is MS's allowed cluster sizes for FAT16 and FAT32: | ||||
|  * The following are MS's allowed cluster sizes for FAT16 and FAT32: | ||||
|  * | ||||
|  * FAT16 | ||||
|  * 31M  :  512 - 4096 | ||||
|  | @ -188,8 +188,9 @@ static BOOL DefineClusterSizes(void) | |||
|  * 4095M: 1024 - 32k | ||||
|  * 7GB  : 2048 - 64k | ||||
|  * 15GB : 4096 - 64k | ||||
|  * 31GB : 8192 - 64k | ||||
|  * 32GB+: possible but N/A from Microsoft (see below) | ||||
|  * 31GB : 8192 - 64k This is as far as Microsoft's FormatEx goes... | ||||
|  * 63GB :  16k - 64k ...but we can go higher using fat32format from RidgeCrop. | ||||
|  * 2TB+ : N/A | ||||
|  */ | ||||
| 
 | ||||
| 	// FAT 16
 | ||||
|  | @ -206,10 +207,11 @@ static BOOL DefineClusterSizes(void) | |||
| 	} | ||||
| 
 | ||||
| 	// FAT 32
 | ||||
| 	// > 32GB FAT32 is not supported by MS (and likely FormatEx) but is feasible
 | ||||
| 	// > 32GB FAT32 is not supported by MS and FormatEx but is achieved using fat32fomat
 | ||||
| 	// See: http://www.ridgecrop.demon.co.uk/index.htm?fat32format.htm
 | ||||
| 	// < 32 MB FAT32 is not allowed by FormatEx
 | ||||
| 	if ((SelectedDrive.DiskSize >= 32*MB) && (SelectedDrive.DiskSize < 32*GB)) { | ||||
| 	// < 32 MB FAT32 is not allowed by FormatEx, so we don't bother
 | ||||
| 
 | ||||
| 	if ((SelectedDrive.DiskSize >= 32*MB) && (SelectedDrive.DiskSize < 2*TB)) { | ||||
| 		SelectedDrive.ClusterSize[FS_FAT32].Allowed = 0x000001F8; | ||||
| 		for (i=32; i<=(32*1024); i<<=1) {			// 32 MB -> 32 GB
 | ||||
| 			if (SelectedDrive.DiskSize < i*MB) { | ||||
|  | @ -221,7 +223,7 @@ static BOOL DefineClusterSizes(void) | |||
| 		SelectedDrive.ClusterSize[FS_FAT32].Allowed &= 0x0001FE00; | ||||
| 
 | ||||
| 		// Default cluster sizes in the 256MB to 32 GB range do not follow the rule above
 | ||||
| 		if (SelectedDrive.DiskSize >= 256*MB) { | ||||
| 		if ((SelectedDrive.DiskSize >= 256*MB) && (SelectedDrive.DiskSize < 32*GB)) { | ||||
| 			for (i=8; i<=32; i<<=1) {				// 256 MB -> 32 GB
 | ||||
| 				if (SelectedDrive.DiskSize < i*GB) { | ||||
| 					SelectedDrive.ClusterSize[FS_FAT32].Default = ((ULONG)i/2)*1024; | ||||
|  | @ -229,6 +231,11 @@ static BOOL DefineClusterSizes(void) | |||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		// More adjustments for large drives
 | ||||
| 		if (SelectedDrive.DiskSize >= 32*GB) { | ||||
| 			SelectedDrive.ClusterSize[FS_FAT32].Allowed &= 0x0001C000; | ||||
| 			SelectedDrive.ClusterSize[FS_FAT32].Default = 0x00008000; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// NTFS
 | ||||
|  | @ -484,12 +491,10 @@ static void SetFSFromISO(void) | |||
| 
 | ||||
| void SetMBRProps(void) | ||||
| { | ||||
| 	int fs, dt; | ||||
| 	int fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)); | ||||
| 	int dt = (int)ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)); | ||||
| 	BOOL needs_masquerading = (IS_WINPE(iso_report.winpe) && (!iso_report.uses_minint)); | ||||
| 
 | ||||
| 	fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)); | ||||
| 	dt = (int)ComboBox_GetItemData(hDOSType, ComboBox_GetCurSel(hDOSType)); | ||||
| 
 | ||||
| 	if ((!mbr_selected_by_user) && ((iso_path == NULL) || (dt != DT_ISO) || (fs != FS_NTFS))) { | ||||
| 		CheckDlgButton(hMainDialog, IDC_RUFUS_MBR, BST_UNCHECKED); | ||||
| 		IGNORE_RETVAL(ComboBox_SetCurSel(hDiskID, 0)); | ||||
|  | @ -812,6 +817,10 @@ static void InitProgress(void) | |||
| 	memset(&slot_end, 0, sizeof(slot_end)); | ||||
| 	previous_end = 0.0f; | ||||
| 
 | ||||
| 	memset(nb_slots, 0, sizeof(nb_slots)); | ||||
| 	memset(slot_end, 0, sizeof(slot_end)); | ||||
| 	previous_end = 0.0f; | ||||
| 
 | ||||
| 	nb_slots[OP_ZERO_MBR] = 1; | ||||
| 	if (IsChecked(IDC_BADBLOCKS)) { | ||||
| 		nb_slots[OP_BADBLOCKS] = -1; | ||||
|  | @ -837,7 +846,8 @@ static void InitProgress(void) | |||
| 	nb_slots[OP_FIX_MBR] = 1; | ||||
| 	nb_slots[OP_CREATE_FS] =  | ||||
| 		nb_steps[ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem))]; | ||||
| 	if (!IsChecked(IDC_QUICKFORMAT)) { | ||||
| 	if ( (!IsChecked(IDC_QUICKFORMAT)) | ||||
| 	  || ((fs == FS_FAT32) && (SelectedDrive.DiskSize >= LARGE_FAT32_SIZE)) ) { | ||||
| 		nb_slots[OP_FORMAT] = -1; | ||||
| 	} | ||||
| 	nb_slots[OP_FINALIZE] = ((dt == DT_ISO) && (fs == FS_NTFS))?2:1; | ||||
|  | @ -1512,7 +1522,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 	int nDeviceIndex, fs, i, nWidth, nHeight; | ||||
| 	static DWORD DeviceNum = 0; | ||||
| 	wchar_t wtmp[128], wstr[MAX_PATH]; | ||||
| 	static UINT uDOSChecked = BST_CHECKED; | ||||
| 	static UINT uDOSChecked = BST_CHECKED, uQFChecked; | ||||
| 	static BOOL first_log_display = TRUE; | ||||
| 
 | ||||
| 	switch (message) { | ||||
|  | @ -1625,6 +1635,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 			PrintStatus(0, TRUE, "%d device%s found.", ComboBox_GetCount(hDeviceList), | ||||
| 				(ComboBox_GetCount(hDeviceList)!=1)?"s":""); | ||||
| 			PopulateProperties(ComboBox_GetCurSel(hDeviceList)); | ||||
| 			SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_FILESYSTEM, | ||||
| 				ComboBox_GetCurSel(hFileSystem)); | ||||
| 			break; | ||||
| 		case IDC_NBPASSES: | ||||
| 			if (HIWORD(wParam) != CBN_SELCHANGE) | ||||
|  | @ -1649,6 +1661,19 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 				break; | ||||
| 			fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)); | ||||
| 			SetClusterSizes(fs); | ||||
| 			// Disable/restore the quick format control depending on large FAT32
 | ||||
| 			if ((fs == FS_FAT32) && (SelectedDrive.DiskSize > LARGE_FAT32_SIZE)) { | ||||
| 				if (IsWindowEnabled(GetDlgItem(hMainDialog, IDC_QUICKFORMAT))) { | ||||
| 					uQFChecked = IsDlgButtonChecked(hMainDialog, IDC_QUICKFORMAT); | ||||
| 					CheckDlgButton(hMainDialog, IDC_QUICKFORMAT, BST_CHECKED); | ||||
| 					EnableWindow(GetDlgItem(hMainDialog, IDC_QUICKFORMAT), FALSE); | ||||
| 				} | ||||
| 			} else { | ||||
| 				if (!IsWindowEnabled(GetDlgItem(hMainDialog, IDC_QUICKFORMAT))) { | ||||
| 					CheckDlgButton(hMainDialog, IDC_QUICKFORMAT, uQFChecked); | ||||
| 					EnableWindow(GetDlgItem(hMainDialog, IDC_QUICKFORMAT), TRUE); | ||||
| 				} | ||||
| 			} | ||||
| 			if (fs < 0) { | ||||
| 				EnableBootOptions(TRUE); | ||||
| 				SetMBRProps(); | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ | |||
| #define MAX_LOG_SIZE                0x7FFFFFFE | ||||
| #define PROPOSEDLABEL_TOLERANCE     0.10 | ||||
| #define FS_DEFAULT                  FS_FAT32 | ||||
| #define LARGE_FAT32_SIZE            (32*1073741824LL)	// Size at which we need to use fat32format
 | ||||
| #define WHITE                       RGB(255,255,255) | ||||
| #define SEPARATOR_GREY              RGB(223,223,223) | ||||
| #define RUFUS_URL                   "http://rufus.akeo.ie"
 | ||||
|  |  | |||
							
								
								
									
										12
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL | |||
| IDD_DIALOG DIALOGEX 12, 12, 206, 316 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_APPWINDOW | ||||
| CAPTION "Rufus v1.2.0.185" | ||||
| CAPTION "Rufus v1.2.0.186" | ||||
| FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||
| BEGIN | ||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,278,50,14 | ||||
|  | @ -77,7 +77,7 @@ BEGIN | |||
|     DEFPUSHBUTTON   "OK",IDOK,231,175,50,14,WS_GROUP | ||||
|     CONTROL         "<a href=""http://rufus.akeo.ie"">http://rufus.akeo.ie</a>",IDC_ABOUT_RUFUS_URL, | ||||
|                     "SysLink",WS_TABSTOP,46,47,114,9 | ||||
|     LTEXT           "Version 1.2.0 (Build 185)",IDC_STATIC,46,19,78,8 | ||||
|     LTEXT           "Version 1.2.0 (Build 186)",IDC_STATIC,46,19,78,8 | ||||
|     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 | ||||
|     LTEXT           "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 | ||||
|  | @ -237,8 +237,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 1,2,0,185 | ||||
|  PRODUCTVERSION 1,2,0,185 | ||||
|  FILEVERSION 1,2,0,186 | ||||
|  PRODUCTVERSION 1,2,0,186 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -255,13 +255,13 @@ BEGIN | |||
|         BEGIN | ||||
|             VALUE "CompanyName", "akeo.ie" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "1.2.0.185" | ||||
|             VALUE "FileVersion", "1.2.0.186" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||
|             VALUE "OriginalFilename", "rufus.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "1.2.0.185" | ||||
|             VALUE "ProductVersion", "1.2.0.186" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue