From 1b20310395583bd002cac9aa548ada04b9a46fa1 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Wed, 30 Nov 2011 17:42:25 +0000 Subject: [PATCH] [boot] fixup for crippled WinME COMMAND.COM and IO.SYS * see http://www.multiboot.ru/msdos8.htm * also added attributes & timestamps from FAT12 image files * reworked FAT12 handling based on ReactOS code --- license.h | 25 ++++-- msdos.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++------ msdos.h | 138 ++++++++++++++++++++++++------ rufus.c | 31 ++++--- rufus.rc | 12 +-- 5 files changed, 371 insertions(+), 79 deletions(-) diff --git a/license.h b/license.h index e87eef01..878bc3b3 100644 --- a/license.h +++ b/license.h @@ -18,10 +18,6 @@ */ const char* additional_copyrights = -"Device enumeration based on TestUSBDriveEject.cpp by ahmd:\r\n" -"http://www.codeguru.com/forum/showthread.php?p=1951973\r\n" -"Assumed Public Domain\r\n" -"\r\n" "Icon by PC Unleashed:\r\n" "http://pcunleashed.com\r\n" "Freeware\r\n" @@ -30,18 +26,29 @@ const char* additional_copyrights = "http://ms-sys.sourceforge.net\r\n" "GNU General Public License (GPL) v2 or later\r\n" "\r\n" -"FS Type description from by GNU fdisk:\r\n" -"http://www.gnu.org/software/fdisk\r\n" -"GNU General Public License (GPL) v3 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" "Public Domain\r\n" "\r\n" +"Device enumeration based on TestUSBDriveEject.cpp by ahmd:\r\n" +"http://www.codeguru.com/forum/showthread.php?p=1951973\r\n" +"Public Domain\r\n" +"\r\n" +"Some FAT and time-conversion handling by ReactOS:\r\n" +"http://svn.reactos.org/svn/reactos/trunk/reactos\r\n" +"GNU General Public License (GPL) v3 compatible\r\n" +"\r\n" +"FS Type description from by GNU fdisk:\r\n" +"http://www.gnu.org/software/fdisk\r\n" +"GNU General Public License (GPL) v3 or later\r\n" +"\r\n" "About and License dialogs inspired by WinSCP\r\n" "Copyright (c) 2000-2011 Martin Prikryl\r\n" -"GNU General Public License (GPL) v3 or later"; +"GNU General Public License (GPL) v3 or later\r\n" +"\r\n" +"\r\n" +"All other references are to be found in the source.\r\n"; const char* gplv3 = " GNU GENERAL PUBLIC LICENSE\r\n" diff --git a/msdos.c b/msdos.c index 9c6ce37e..4b67d17a 100644 --- a/msdos.c +++ b/msdos.c @@ -33,15 +33,182 @@ static BYTE* DiskImage; static size_t DiskImageSize; +/* + * FAT time conversion, from ReactOS' time.c + */ +#define TICKSPERMIN 600000000 +#define TICKSPERSEC 10000000 +#define TICKSPERMSEC 10000 +#define SECSPERDAY 86400 +#define SECSPERHOUR 3600 +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define EPOCHWEEKDAY 1 +#define DAYSPERWEEK 7 +#define EPOCHYEAR 1601 +#define DAYSPERNORMALYEAR 365 +#define DAYSPERLEAPYEAR 366 +#define MONSPERYEAR 12 + +typedef struct _TIME_FIELDS { + short Year; + short Month; + short Day; + short Hour; + short Minute; + short Second; + short Milliseconds; + short Weekday; +} TIME_FIELDS, *PTIME_FIELDS; + +#define ARGUMENT_PRESENT(ArgumentPointer) \ + ((CHAR*)((ULONG_PTR)(ArgumentPointer)) != (CHAR*)NULL) + +static const int YearLengths[2] = +{ + DAYSPERNORMALYEAR, DAYSPERLEAPYEAR +}; +static const UCHAR MonthLengths[2][MONSPERYEAR] = +{ + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static __inline int IsLeapYear(int Year) +{ + return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0; +} + +static int DaysSinceEpoch(int Year) +{ + int Days; + Year--; /* Don't include a leap day from the current year */ + Days = Year * DAYSPERNORMALYEAR + Year / 4 - Year / 100 + Year / 400; + Days -= (EPOCHYEAR - 1) * DAYSPERNORMALYEAR + (EPOCHYEAR - 1) / 4 - (EPOCHYEAR - 1) / 100 + (EPOCHYEAR - 1) / 400; + return Days; +} + +static BOOLEAN RtlTimeFieldsToTime(PTIME_FIELDS TimeFields, PLARGE_INTEGER Time) +{ + int CurMonth; + TIME_FIELDS IntTimeFields; + + memcpy(&IntTimeFields, + TimeFields, + sizeof(TIME_FIELDS)); + + if (TimeFields->Milliseconds < 0 || TimeFields->Milliseconds > 999 || + TimeFields->Second < 0 || TimeFields->Second > 59 || + TimeFields->Minute < 0 || TimeFields->Minute > 59 || + TimeFields->Hour < 0 || TimeFields->Hour > 23 || + TimeFields->Month < 1 || TimeFields->Month > 12 || + TimeFields->Day < 1 || + TimeFields->Day > + MonthLengths[IsLeapYear(TimeFields->Year)][TimeFields->Month - 1] || + TimeFields->Year < 1601) { + return FALSE; + } + + /* Compute the time */ + Time->QuadPart = DaysSinceEpoch(IntTimeFields.Year); + for (CurMonth = 1; CurMonth < IntTimeFields.Month; CurMonth++) { + Time->QuadPart += MonthLengths[IsLeapYear(IntTimeFields.Year)][CurMonth - 1]; + } + Time->QuadPart += IntTimeFields.Day - 1; + Time->QuadPart *= SECSPERDAY; + Time->QuadPart += IntTimeFields.Hour * SECSPERHOUR + IntTimeFields.Minute * SECSPERMIN + + IntTimeFields.Second; + Time->QuadPart *= TICKSPERSEC; + Time->QuadPart += IntTimeFields.Milliseconds * TICKSPERMSEC; + + return TRUE; +} + +static void FatDateTimeToSystemTime(PLARGE_INTEGER SystemTime, PFAT_DATETIME FatDateTime, UCHAR TenMs OPTIONAL) +{ + TIME_FIELDS TimeFields; + + /* Setup time fields */ + TimeFields.Year = FatDateTime->Date.Year + 1980; + TimeFields.Month = FatDateTime->Date.Month; + TimeFields.Day = FatDateTime->Date.Day; + TimeFields.Hour = FatDateTime->Time.Hour; + TimeFields.Minute = FatDateTime->Time.Minute; + TimeFields.Second = (FatDateTime->Time.DoubleSeconds << 1); + + /* Adjust up to 10 milliseconds + * if the parameter was supplied + */ + if (ARGUMENT_PRESENT(TenMs)) { + TimeFields.Second += TenMs / 100; + TimeFields.Milliseconds = (TenMs % 100) * 10; + } else { + TimeFields.Milliseconds = 0; + } + + /* Fix seconds value that might get beyond the bound */ + if (TimeFields.Second > 59) TimeFields.Second = 0; + + /* Perform ceonversion to system time if possible */ + if (!RtlTimeFieldsToTime(&TimeFields, SystemTime)) { + /* Set to default time if conversion failed */ + SystemTime->QuadPart = 0; + } +} + +/* http://www.multiboot.ru/msdos8.htm & http://en.wikipedia.org/wiki/Windows_Me#Real_mode_DOS + * COMMAND.COM and IO.SYS from diskcopy.dll are from the WinME crippled version + * that removed real mode DOS => they must be patched: + * IO.SYS 000003AA 75 -> EB + * COMMAND.COM 00006510 75 -> EB + */ +static BOOL Patch_COMMAND_COM(size_t filestart, size_t filesize) +{ + const BYTE expected[8] = { 0x15, 0x80, 0xFA, 0x03, 0x75, 0x10, 0xB8, 0x0E }; + + uprintf("Patching COMMAND.COM...\n"); + if (filesize != 93040) { + uprintf(" unexpected file size\n"); + return FALSE; + } + if (memcmp(&DiskImage[filestart+0x650c], expected, sizeof(expected)) != 0) { + uprintf(" unexpected binary data\n"); + return FALSE; + } + DiskImage[filestart+0x6510] = 0xeb; + return TRUE; +} + +static BOOL Patch_IO_SYS(size_t filestart, size_t filesize) +{ + const BYTE expected[8] = { 0xFA, 0x80, 0x75, 0x09, 0x8D, 0xB6, 0x99, 0x00 }; + + uprintf("Patching IO.SYS...\n"); + if (filesize != 116736) { + uprintf(" unexpected file size\n"); + return FALSE; + } + if (memcmp(&DiskImage[filestart+0x3a8], expected, sizeof(expected)) != 0) { + uprintf(" unexpected binary data\n"); + return FALSE; + } + DiskImage[filestart+0x3aa] = 0xeb; + return TRUE; +} + /* Extract the file identified by FAT RootDir index 'entry' to 'path' */ static BOOL ExtractFAT(int entry, const char* path) { - FILE* fd; + HANDLE hFile; + DWORD Size; char filename[MAX_PATH]; - size_t i, pos; - size_t filestart; - size_t filesize; - size_t FATFile = FAT12_ROOTDIR_OFFSET + entry*FAT12_ROOTDIR_ENTRY_SIZE; + size_t i, pos, fnamepos; + size_t filestart, filesize; + FAT_DATETIME LastAccessTime; + LARGE_INTEGER liCreationTime, liLastAccessTime, liLastWriteTime; + FILETIME ftCreationTime, ftLastAccessTime, ftLastWriteTime; + PDIR_ENTRY dir_entry = (PDIR_ENTRY)&DiskImage[FAT12_ROOTDIR_OFFSET + entry*FAT_BYTES_PER_DIRENT]; if ((path == NULL) || ((safe_strlen(path) + 14) > sizeof(filename))) { uprintf("invalid path supplied for MS-DOS FAT extraction\n"); @@ -50,44 +217,68 @@ static BOOL ExtractFAT(int entry, const char* path) strcpy(filename, path); pos = strlen(path); filename[pos++] = '\\'; + fnamepos = pos; for(i=0; i<8; i++) { - if (DiskImage[FATFile + i] == ' ') + if (dir_entry->FileName[i] == ' ') break; - filename[pos++] = DiskImage[FATFile + i]; + filename[pos++] = dir_entry->FileName[i]; } filename[pos++] = '.'; for (i=8; i<11; i++) { - if (DiskImage[FATFile + i] == ' ') + if (dir_entry->FileName[i] == ' ') break; - filename[pos++] = DiskImage[FATFile + i]; + filename[pos++] = dir_entry->FileName[i]; } filename[pos] = 0; - GET_ULONG_LE(filesize, DiskImage, FATFile + FAT12_ROOTDIR_FILESIZE); - GET_USHORT_LE(filestart, DiskImage, FATFile + FAT12_ROOTDIR_FIRSTCLUSTER); - filestart += FAT12_CLUSTER_OFFSET; - filestart *= FAT12_CLUSTER_SIZE; + filestart = (dir_entry->FirstCluster + FAT12_CLUSTER_OFFSET)*FAT12_CLUSTER_SIZE; + filesize = dir_entry->FileSize; if ((filestart + filesize) > DiskImageSize) { - uprintf("FAT File %s would be out of bounds\n", filename); + uprintf("FAT File %s would be out of bounds: %X, %X\n", filename, filestart, filesize); + uprintf("%X, %X\n", dir_entry->FirstCluster, dir_entry->FileSize); return FALSE; } - fd = fopen(filename, "wb"); - if (fd == NULL) { - uprintf("Unable to create file '%s'.\n", filename); + /* WinME DOS files need to be patched */ + if (strcmp(&filename[fnamepos], "COMMAND.COM") == 0) { + Patch_COMMAND_COM(filestart, filesize); + } else if (strcmp(&filename[fnamepos], "IO.SYS") == 0) { + Patch_IO_SYS(filestart, filesize); + } + + /* Create a file, using the same attributes as found in the FAT */ + hFile = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, CREATE_ALWAYS, dir_entry->Attributes, 0); + if (hFile == INVALID_HANDLE_VALUE) { + uprintf("Unable to create file '%s': %s.\n", filename, WindowsErrorString()); return FALSE; } - if (fwrite(&DiskImage[filestart], 1, filesize, fd) != filesize) { - uprintf("Couldn't write file '%s'.\n", filename); - fclose(fd); - return FALSE; + if ((!WriteFile(hFile, &DiskImage[filestart], (DWORD)filesize, &Size, 0)) || (filesize != Size)) { + uprintf("Couldn't write file '%s': %s.\n", filename, WindowsErrorString()); + safe_closehandle(hFile); + return FALSE; safe_closehandle(hFile); } - fclose(fd); + /* Restore timestamps from FAT */ + FatDateTimeToSystemTime(&liCreationTime, &dir_entry->CreationDateTime, dir_entry->CreationTimeTenMs); + ftCreationTime.dwHighDateTime = liCreationTime.HighPart; + ftCreationTime.dwLowDateTime = liCreationTime.LowPart; + LastAccessTime.Value = 0; + LastAccessTime.Date = dir_entry->LastAccessDate; + FatDateTimeToSystemTime(&liLastAccessTime, &LastAccessTime, 0); + ftLastAccessTime.dwHighDateTime = liLastAccessTime.HighPart; + ftLastAccessTime.dwLowDateTime = liLastAccessTime.LowPart; + FatDateTimeToSystemTime(&liLastWriteTime, &dir_entry->LastWriteDateTime, 0); + ftLastWriteTime.dwHighDateTime = liLastWriteTime.HighPart; + ftLastWriteTime.dwLowDateTime = liLastWriteTime.LowPart; + if (!SetFileTime(hFile, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime)) { + uprintf("Could not set timestamps: %s\n", WindowsErrorString()); + } + + safe_closehandle(hFile); uprintf("Succesfully wrote '%s' (%d bytes)\n", filename, filesize); - // TODO: MSDOS.SYS and IO.SYS should have 'rahs' attributes return TRUE; } @@ -130,16 +321,17 @@ BOOL ExtractMSDOS(const char* path) return FALSE; } - for (i=0; i. */ -/* http://www.c-jump.com/CIS24/Slides/FAT/lecture.html */ -#define FAT12_ROOTDIR_OFFSET 0x2600 -#define FAT12_ROOTDIR_ENTRY_SIZE 0x20 -#define FAT12_ROOTDIR_NB_ENTRIES 0xE0 -#define FAT12_ROOTDIR_FIRSTCLUSTER 0x1A // No need for high word on a 1.44 MB media -#define FAT12_ROOTDIR_FILESIZE 0x1C -#define FAT12_DELETED_ENTRY 0xE5 - -/* Ideally, we'd read those from the FAT Boot Sector, but we have +/* http://www.c-jump.com/CIS24/Slides/FAT/lecture.html + Ideally, we'd read the following from the FAT Boot Sector, but we have a pretty good idea of what they are for a 1.44 MB floppy image */ +#define FAT12_ROOTDIR_OFFSET 0x2600 #define FAT12_CLUSTER_SIZE 0x200 // = sector size #define FAT12_DATA_START 0x4200 #define FAT12_CLUSTER_OFFSET ((FAT12_DATA_START/FAT12_CLUSTER_SIZE)-2) // First cluster in data area is #2 -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i) \ -{ \ - (n) = ( (ULONG) (b)[(i) ] ) \ - | ( (ULONG) (b)[(i) + 1] << 8 ) \ - | ( (ULONG) (b)[(i) + 2] << 16 ) \ - | ( (ULONG) (b)[(i) + 3] << 24 ); \ -} -#endif +/* + * Lifted from ReactOS: + * http://reactos-mirror.googlecode.com/svn/trunk/reactos/drivers/filesystems/fastfat_new/fat.h + */ -#ifndef GET_USHORT_LE -#define GET_USHORT_LE(n,b,i) \ -{ \ - (n) = ( (USHORT) (b)[(i) ] ) \ - | ( (USHORT) (b)[(i) + 1] << 8 ); \ -} -#endif +#pragma pack(push, 1) // You *DO* want packed structs here + +// +// Directory Structure: +// +typedef struct _FAT_TIME +{ + union { + struct { + USHORT DoubleSeconds : 5; + USHORT Minute : 6; + USHORT Hour : 5; + }; + USHORT Value; + }; +} FAT_TIME, *PFAT_TIME; +// +// +// +typedef struct _FAT_DATE { + union { + struct { + USHORT Day : 5; + USHORT Month : 4; + /* Relative to 1980 */ + USHORT Year : 7; + }; + USHORT Value; + }; +} FAT_DATE, *PFAT_DATE; +// +// +// +typedef struct _FAT_DATETIME { + union { + struct { + FAT_TIME Time; + FAT_DATE Date; + }; + ULONG Value; + }; +} FAT_DATETIME, *PFAT_DATETIME; +// +// +// +typedef struct _DIR_ENTRY +{ + UCHAR FileName[11]; + UCHAR Attributes; + UCHAR Case; + UCHAR CreationTimeTenMs; + FAT_DATETIME CreationDateTime; + FAT_DATE LastAccessDate; + union { + USHORT ExtendedAttributes; + USHORT FirstClusterOfFileHi; + }; + FAT_DATETIME LastWriteDateTime; + USHORT FirstCluster; + ULONG FileSize; +} DIR_ENTRY, *PDIR_ENTRY; +// sizeof = 0x020 + +typedef struct _LONG_FILE_NAME_ENTRY { + UCHAR SeqNum; + UCHAR NameA[10]; + UCHAR Attributes; + UCHAR Type; + UCHAR Checksum; + USHORT NameB[6]; + USHORT Reserved; + USHORT NameC[2]; +} LONG_FILE_NAME_ENTRY, *PLONG_FILE_NAME_ENTRY; +// sizeof = 0x020 + +#pragma pack() + +#define FAT_LFN_NAME_LENGTH \ + (RTL_FIELD_SIZE(LONG_FILE_NAME_ENTRY, NameA) \ + + RTL_FIELD_SIZE(LONG_FILE_NAME_ENTRY, NameB) \ + + RTL_FIELD_SIZE(LONG_FILE_NAME_ENTRY, NameC)) + +#define FAT_FN_DIR_ENTRY_LAST 0x40 +#define FAT_FN_MAX_DIR_ENTIES 0x14 + +#define FAT_BYTES_PER_DIRENT 0x20 +#define FAT_BYTES_PER_DIRENT_LOG 0x05 +#define FAT_DIRENT_NEVER_USED 0x00 +#define FAT_DIRENT_REALLY_0E5 0x05 +#define FAT_DIRENT_DIRECTORY_ALIAS 0x2e +#define FAT_DIRENT_DELETED 0xe5 + +#define FAT_CASE_LOWER_BASE 0x08 +#define FAT_CASE_LOWER_EXT 0x10 + +#define FAT_DIRENT_ATTR_READ_ONLY 0x01 +#define FAT_DIRENT_ATTR_HIDDEN 0x02 +#define FAT_DIRENT_ATTR_SYSTEM 0x04 +#define FAT_DIRENT_ATTR_VOLUME_ID 0x08 +#define FAT_DIRENT_ATTR_DIRECTORY 0x10 +#define FAT_DIRENT_ATTR_ARCHIVE 0x20 +#define FAT_DIRENT_ATTR_DEVICE 0x40 +#define FAT_DIRENT_ATTR_LFN (FAT_DIRENT_ATTR_READ_ONLY | \ + FAT_DIRENT_ATTR_HIDDEN | \ + FAT_DIRENT_ATTR_SYSTEM | \ + FAT_DIRENT_ATTR_VOLUME_ID) diff --git a/rufus.c b/rufus.c index 60abc5c4..b1ad1803 100644 --- a/rufus.c +++ b/rufus.c @@ -637,7 +637,8 @@ static BOOL FormatDrive(char DriveLetter) 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), ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)), FormatExCallback); + IsChecked(IDC_QUICKFORMAT), (ULONG)ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)), + FormatExCallback); if (!IS_ERROR(FormatStatus)) { uprintf("Format completed.\n"); r = TRUE; @@ -709,7 +710,6 @@ static BOOL ProcessMBR(HANDLE hPhysicalDrive) size_t nSecs = (0x200 + SecSize -1) / SecSize; FILE fake_fd; - PrintStatus("Processing MBR...\n"); if (!AnalyzeMBR(hPhysicalDrive)) return FALSE; // FormatEx rewrites the MBR and removes the LBA attribute of FAT16 @@ -775,7 +775,6 @@ static BOOL ProcessFS_BR(HANDLE hLogicalVolume) fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; write_fat_32_br(&fake_fd, 0); - PrintStatus("Processing FS BR...\n"); // 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 @@ -864,7 +863,8 @@ static void __cdecl FormatThread(void* param) } // TODO: Enable compression on NTFS - // TODO: disable indexing 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 @@ -882,7 +882,9 @@ static void __cdecl FormatThread(void* param) goto out; } #endif + PrintStatus("Writing master boot record...\n"); if (!ProcessMBR(hPhysicalDrive)) { + // Errorcode has already been set goto out; } @@ -900,17 +902,19 @@ static void __cdecl FormatThread(void* param) 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; } - ProcessFS_BR(hLogicalVolume); - // TODO: check return value & set bootblock - ExtractMSDOS(drive_name); - // TODO: - // http://www.multiboot.ru/msdos8.htm & http://en.wikipedia.org/wiki/Windows_Me#Real_mode_DOS - // COMMAND.COM and IO.SYS from diskcopy.dll are from the WinME crippled version of DOS - // that removed real mode DOS => they must be patched: - // IO.SYS 000003AA 75 -> EB - // COMMAND.COM 00006510 75 -> EB } out: @@ -1204,6 +1208,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA SendMessage(hProgress, PBM_SETPOS, FormatStatus?0:100, 0); EnableControls(TRUE); GetUSBDevices(); + // TODO: process and report error code to user PrintStatus(!IS_ERROR(FormatStatus)?"DONE": ((SCODE_CODE(FormatStatus)==ERROR_CANCELLED)?"Cancelled":"FAILED")); return (INT_PTR)TRUE; diff --git a/rufus.rc b/rufus.rc index d20f9cfe..5db70cde 100644 --- a/rufus.rc +++ b/rufus.rc @@ -63,7 +63,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP CONTROL "https://github.com/pbatard/rufus",IDC_ABOUT_RUFUS_URL, "SysLink",WS_TABSTOP,46,47,114,9 - LTEXT "Version 1.0.0 (Build 50)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.0.0 (Build 51)",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 @@ -162,8 +162,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,50 - PRODUCTVERSION 1,0,0,50 + FILEVERSION 1,0,0,51 + PRODUCTVERSION 1,0,0,51 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -180,13 +180,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.0.0.50" + VALUE "FileVersion", "1.0.0.51" 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.0.0.50" + VALUE "ProductVersion", "1.0.0.51" END END BLOCK "VarFileInfo" @@ -212,7 +212,7 @@ IDI_ICON ICON "rufus.ico" STRINGTABLE BEGIN - IDS_VERSION "Rufus v1.0.0.50" + IDS_VERSION "Rufus v1.0.0.51" END #endif // English resources