mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[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
This commit is contained in:
		
							parent
							
								
									7ae6715b55
								
							
						
					
					
						commit
						1b20310395
					
				
					 5 changed files with 371 additions and 79 deletions
				
			
		
							
								
								
									
										25
									
								
								license.h
									
										
									
									
									
								
							
							
						
						
									
										25
									
								
								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" | ||||
|  |  | |||
							
								
								
									
										244
									
								
								msdos.c
									
										
									
									
									
								
							
							
						
						
									
										244
									
								
								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<FAT12_ROOTDIR_NB_ENTRIES; i++) { | ||||
| 		if (DiskImage[FAT12_ROOTDIR_OFFSET + i*FAT12_ROOTDIR_ENTRY_SIZE] == FAT12_DELETED_ENTRY) | ||||
| 	for (i=0; i<FAT_FN_DIR_ENTRY_LAST; i++) { | ||||
| 		if (DiskImage[FAT12_ROOTDIR_OFFSET + i*FAT_BYTES_PER_DIRENT] == FAT_DIRENT_DELETED) | ||||
| 			continue; | ||||
| 		for (j=0; j<ARRAYSIZE(extractlist); j++) { | ||||
| 			if (memcmp(extractlist[j], &DiskImage[FAT12_ROOTDIR_OFFSET + i*FAT12_ROOTDIR_ENTRY_SIZE], 8+3) == 0) { | ||||
| 			if (memcmp(extractlist[j], &DiskImage[FAT12_ROOTDIR_OFFSET + i*FAT_BYTES_PER_DIRENT], 8+3) == 0) { | ||||
| 				ExtractFAT(i, path); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	FreeLibrary(hDLL); | ||||
| 
 | ||||
| 	return TRUE; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										138
									
								
								msdos.h
									
										
									
									
									
								
							
							
						
						
									
										138
									
								
								msdos.h
									
										
									
									
									
								
							|  | @ -17,34 +17,122 @@ | |||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| /* 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) | ||||
|  |  | |||
							
								
								
									
										31
									
								
								rufus.c
									
										
									
									
									
								
							
							
						
						
									
										31
									
								
								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; | ||||
|  |  | |||
							
								
								
									
										12
									
								
								rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								rufus.rc
									
										
									
									
									
								
							|  | @ -63,7 +63,7 @@ BEGIN | |||
|     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, | ||||
|                     "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 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue