diff --git a/src/format.c b/src/format.c index f81b22c1..63df05fb 100644 --- a/src/format.c +++ b/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 * * 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; i32 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 diff --git a/src/format.h b/src/format.h index 948efae5..18c904f3 100644 --- a/src/format.h +++ b/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 * * 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) diff --git a/src/license.h b/src/license.h index d819d446..82ff17e5 100644 --- a/src/license.h +++ b/src/license.h @@ -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" diff --git a/src/rufus.c b/src/rufus.c index 70b299bc..0e07230a 100644 --- a/src/rufus.c +++ b/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(); diff --git a/src/rufus.h b/src/rufus.h index 5d7e3e6d..1997c327 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -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" diff --git a/src/rufus.rc b/src/rufus.rc index f4d856e5..2682ffdc 100644 --- a/src/rufus.rc +++ b/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 "http://rufus.akeo.ie",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"