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 = | 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" | "Icon by PC Unleashed:\r\n" | ||||||
| "http://pcunleashed.com\r\n" | "http://pcunleashed.com\r\n" | ||||||
| "Freeware\r\n" | "Freeware\r\n" | ||||||
|  | @ -30,18 +26,29 @@ const char* additional_copyrights = | ||||||
| "http://ms-sys.sourceforge.net\r\n" | "http://ms-sys.sourceforge.net\r\n" | ||||||
| "GNU General Public License (GPL) v2 or later\r\n" | "GNU General Public License (GPL) v2 or later\r\n" | ||||||
| "\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" | "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://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" | "http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/fmifs\r\n" | ||||||
| "Public Domain\r\n" | "Public Domain\r\n" | ||||||
| "\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" | "About and License dialogs inspired by WinSCP\r\n" | ||||||
| "Copyright (c) 2000-2011 Martin Prikryl\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 = | const char* gplv3 = | ||||||
| "                    GNU GENERAL PUBLIC LICENSE\r\n" | "                    GNU GENERAL PUBLIC LICENSE\r\n" | ||||||
|  |  | ||||||
							
								
								
									
										244
									
								
								msdos.c
									
										
									
									
									
								
							
							
						
						
									
										244
									
								
								msdos.c
									
										
									
									
									
								
							|  | @ -33,15 +33,182 @@ | ||||||
| static BYTE* DiskImage; | static BYTE* DiskImage; | ||||||
| static size_t DiskImageSize; | 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' */ | /* Extract the file identified by FAT RootDir index 'entry' to 'path' */ | ||||||
| static BOOL ExtractFAT(int entry, const char* path) | static BOOL ExtractFAT(int entry, const char* path) | ||||||
| { | { | ||||||
| 	FILE* fd; | 	HANDLE hFile; | ||||||
|  | 	DWORD Size; | ||||||
| 	char filename[MAX_PATH]; | 	char filename[MAX_PATH]; | ||||||
| 	size_t i, pos; | 	size_t i, pos, fnamepos; | ||||||
| 	size_t filestart; | 	size_t filestart, filesize; | ||||||
| 	size_t filesize; | 	FAT_DATETIME LastAccessTime; | ||||||
| 	size_t FATFile = FAT12_ROOTDIR_OFFSET + entry*FAT12_ROOTDIR_ENTRY_SIZE; | 	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))) { | 	if ((path == NULL) || ((safe_strlen(path) + 14) > sizeof(filename))) { | ||||||
| 		uprintf("invalid path supplied for MS-DOS FAT extraction\n"); | 		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); | 	strcpy(filename, path); | ||||||
| 	pos = strlen(path); | 	pos = strlen(path); | ||||||
| 	filename[pos++] = '\\'; | 	filename[pos++] = '\\'; | ||||||
|  | 	fnamepos = pos; | ||||||
| 
 | 
 | ||||||
| 	for(i=0; i<8; i++) { | 	for(i=0; i<8; i++) { | ||||||
| 		if (DiskImage[FATFile + i] == ' ') | 		if (dir_entry->FileName[i] == ' ') | ||||||
| 			break; | 			break; | ||||||
| 		filename[pos++] = DiskImage[FATFile + i]; | 		filename[pos++] = dir_entry->FileName[i]; | ||||||
| 	} | 	} | ||||||
| 	filename[pos++] = '.'; | 	filename[pos++] = '.'; | ||||||
| 	for (i=8; i<11; i++) { | 	for (i=8; i<11; i++) { | ||||||
| 		if (DiskImage[FATFile + i] == ' ') | 		if (dir_entry->FileName[i] == ' ') | ||||||
| 			break; | 			break; | ||||||
| 		filename[pos++] = DiskImage[FATFile + i]; | 		filename[pos++] = dir_entry->FileName[i]; | ||||||
| 	} | 	} | ||||||
| 	filename[pos] = 0; | 	filename[pos] = 0; | ||||||
| 	GET_ULONG_LE(filesize, DiskImage, FATFile + FAT12_ROOTDIR_FILESIZE); | 	filestart = (dir_entry->FirstCluster + FAT12_CLUSTER_OFFSET)*FAT12_CLUSTER_SIZE; | ||||||
| 	GET_USHORT_LE(filestart, DiskImage, FATFile + FAT12_ROOTDIR_FIRSTCLUSTER); | 	filesize = dir_entry->FileSize; | ||||||
| 	filestart += FAT12_CLUSTER_OFFSET; |  | ||||||
| 	filestart *= FAT12_CLUSTER_SIZE; |  | ||||||
| 	if ((filestart + filesize) > DiskImageSize) { | 	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; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fd = fopen(filename, "wb"); | 	/* WinME DOS files need to be patched */ | ||||||
| 	if (fd == NULL) { | 	if (strcmp(&filename[fnamepos], "COMMAND.COM") == 0) { | ||||||
| 		uprintf("Unable to create file '%s'.\n", filename); | 		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; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (fwrite(&DiskImage[filestart], 1, filesize, fd) != filesize) { | 	if ((!WriteFile(hFile, &DiskImage[filestart], (DWORD)filesize, &Size, 0)) || (filesize != Size)) { | ||||||
| 		uprintf("Couldn't write file '%s'.\n", filename); | 		uprintf("Couldn't write file '%s': %s.\n", filename, WindowsErrorString()); | ||||||
| 		fclose(fd); | 		safe_closehandle(hFile); | ||||||
| 		return FALSE; | 		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); | 	uprintf("Succesfully wrote '%s' (%d bytes)\n", filename, filesize); | ||||||
| 
 | 
 | ||||||
| 	// TODO: MSDOS.SYS and IO.SYS should have 'rahs' attributes
 |  | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -130,16 +321,17 @@ BOOL ExtractMSDOS(const char* path) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i=0; i<FAT12_ROOTDIR_NB_ENTRIES; i++) { | 	for (i=0; i<FAT_FN_DIR_ENTRY_LAST; i++) { | ||||||
| 		if (DiskImage[FAT12_ROOTDIR_OFFSET + i*FAT12_ROOTDIR_ENTRY_SIZE] == FAT12_DELETED_ENTRY) | 		if (DiskImage[FAT12_ROOTDIR_OFFSET + i*FAT_BYTES_PER_DIRENT] == FAT_DIRENT_DELETED) | ||||||
| 			continue; | 			continue; | ||||||
| 		for (j=0; j<ARRAYSIZE(extractlist); j++) { | 		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); | 				ExtractFAT(i, path); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	FreeLibrary(hDLL); | 	FreeLibrary(hDLL); | ||||||
|  | 
 | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										138
									
								
								msdos.h
									
										
									
									
									
								
							
							
						
						
									
										138
									
								
								msdos.h
									
										
									
									
									
								
							|  | @ -17,34 +17,122 @@ | ||||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 |  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* http://www.c-jump.com/CIS24/Slides/FAT/lecture.html */ | /* http://www.c-jump.com/CIS24/Slides/FAT/lecture.html
 | ||||||
| #define FAT12_ROOTDIR_OFFSET        0x2600 |    Ideally, we'd read the following from the FAT Boot Sector, but we have | ||||||
| #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
 |  | ||||||
|    a pretty good idea of what they are for a 1.44 MB floppy image */ |    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_CLUSTER_SIZE          0x200	// = sector size
 | ||||||
| #define FAT12_DATA_START            0x4200 | #define FAT12_DATA_START            0x4200 | ||||||
| #define FAT12_CLUSTER_OFFSET        ((FAT12_DATA_START/FAT12_CLUSTER_SIZE)-2)	// First cluster in data area is #2
 | #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)                     \ |  * Lifted from ReactOS: | ||||||
| {                                               \ |  * http://reactos-mirror.googlecode.com/svn/trunk/reactos/drivers/filesystems/fastfat_new/fat.h
 | ||||||
|     (n) = ( (ULONG) (b)[(i)    ]       )        \ |  */ | ||||||
|         | ( (ULONG) (b)[(i) + 1] <<  8 )        \ |  | ||||||
|         | ( (ULONG) (b)[(i) + 2] << 16 )        \ |  | ||||||
|         | ( (ULONG) (b)[(i) + 3] << 24 );       \ |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| #ifndef GET_USHORT_LE | #pragma pack(push, 1)	// You *DO* want packed structs here
 | ||||||
| #define GET_USHORT_LE(n,b,i)                    \ | 
 | ||||||
| {                                               \ | //
 | ||||||
|     (n) = ( (USHORT) (b)[(i)    ]       )       \ | //  Directory Structure:
 | ||||||
|         | ( (USHORT) (b)[(i) + 1] <<  8 );      \ | //
 | ||||||
| } | typedef struct _FAT_TIME | ||||||
| #endif | { | ||||||
|  |     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)); | 	GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel)); | ||||||
| 	uprintf("Using cluster size: %d bytes\n", ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize))); | 	uprintf("Using cluster size: %d bytes\n", ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize))); | ||||||
| 	pfFormatEx(wDriveRoot, RemovableMedia, wFSType, wLabel, | 	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)) { | 	if (!IS_ERROR(FormatStatus)) { | ||||||
| 		uprintf("Format completed.\n"); | 		uprintf("Format completed.\n"); | ||||||
| 		r = TRUE; | 		r = TRUE; | ||||||
|  | @ -709,7 +710,6 @@ static BOOL ProcessMBR(HANDLE hPhysicalDrive) | ||||||
| 	size_t nSecs = (0x200 + SecSize -1) / SecSize; | 	size_t nSecs = (0x200 + SecSize -1) / SecSize; | ||||||
| 	FILE fake_fd; | 	FILE fake_fd; | ||||||
| 
 | 
 | ||||||
| 	PrintStatus("Processing MBR...\n"); |  | ||||||
| 	if (!AnalyzeMBR(hPhysicalDrive)) return FALSE; | 	if (!AnalyzeMBR(hPhysicalDrive)) return FALSE; | ||||||
| 
 | 
 | ||||||
| 	// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
 | 	// 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; | 	fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; | ||||||
| 	write_fat_32_br(&fake_fd, 0); | 	write_fat_32_br(&fake_fd, 0); | ||||||
| 
 | 
 | ||||||
| 	PrintStatus("Processing FS BR...\n"); |  | ||||||
| 	// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
 | 	// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
 | ||||||
| 	// and FAT32 partitions - we need to correct this in the MBR
 | 	// and FAT32 partitions - we need to correct this in the MBR
 | ||||||
| 	// TODO: something else for bootable GPT
 | 	// TODO: something else for bootable GPT
 | ||||||
|  | @ -864,7 +863,8 @@ static void __cdecl FormatThread(void* param) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// TODO: Enable compression on NTFS
 | 	// 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
 | 	// Ideally we would lock, FSCTL_DISMOUNT_VOLUME, unlock and close our volume
 | ||||||
| 	// handle, but some explorer versions have problems with volumes disappear
 | 	// handle, but some explorer versions have problems with volumes disappear
 | ||||||
|  | @ -882,7 +882,9 @@ static void __cdecl FormatThread(void* param) | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
|  | 	PrintStatus("Writing master boot record...\n"); | ||||||
| 	if (!ProcessMBR(hPhysicalDrive)) { | 	if (!ProcessMBR(hPhysicalDrive)) { | ||||||
|  | 		// Errorcode has already been set
 | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -900,17 +902,19 @@ static void __cdecl FormatThread(void* param) | ||||||
| 		hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE); | 		hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE); | ||||||
| 		if (hLogicalVolume == INVALID_HANDLE_VALUE) { | 		if (hLogicalVolume == INVALID_HANDLE_VALUE) { | ||||||
| 			uprintf("Could not re-mount volume\n"); | 			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; | 			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: | 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); | 		SendMessage(hProgress, PBM_SETPOS, FormatStatus?0:100, 0); | ||||||
| 		EnableControls(TRUE); | 		EnableControls(TRUE); | ||||||
| 		GetUSBDevices(); | 		GetUSBDevices(); | ||||||
|  | 		// TODO: process and report error code to user
 | ||||||
| 		PrintStatus(!IS_ERROR(FormatStatus)?"DONE": | 		PrintStatus(!IS_ERROR(FormatStatus)?"DONE": | ||||||
| 			((SCODE_CODE(FormatStatus)==ERROR_CANCELLED)?"Cancelled":"FAILED")); | 			((SCODE_CODE(FormatStatus)==ERROR_CANCELLED)?"Cancelled":"FAILED")); | ||||||
| 		return (INT_PTR)TRUE; | 		return (INT_PTR)TRUE; | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								rufus.rc
									
										
									
									
									
								
							|  | @ -63,7 +63,7 @@ BEGIN | ||||||
|     DEFPUSHBUTTON   "OK",IDOK,231,175,50,14,WS_GROUP |     DEFPUSHBUTTON   "OK",IDOK,231,175,50,14,WS_GROUP | ||||||
|     CONTROL         "<a href=""https://github.com/pbatard/rufus/wiki/Rufus"">https://github.com/pbatard/rufus</a>",IDC_ABOUT_RUFUS_URL, |     CONTROL         "<a href=""https://github.com/pbatard/rufus/wiki/Rufus"">https://github.com/pbatard/rufus</a>",IDC_ABOUT_RUFUS_URL, | ||||||
|                     "SysLink",WS_TABSTOP,46,47,114,9 |                     "SysLink",WS_TABSTOP,46,47,114,9 | ||||||
|     LTEXT           "Version 1.0.0 (Build 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 |     PUSHBUTTON      "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP | ||||||
|     EDITTEXT        IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL |     EDITTEXT        IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL | ||||||
|     LTEXT           "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 |     LTEXT           "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 | ||||||
|  | @ -162,8 +162,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 1,0,0,50 |  FILEVERSION 1,0,0,51 | ||||||
|  PRODUCTVERSION 1,0,0,50 |  PRODUCTVERSION 1,0,0,51 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -180,13 +180,13 @@ BEGIN | ||||||
|         BEGIN |         BEGIN | ||||||
|             VALUE "CompanyName", "akeo.ie" |             VALUE "CompanyName", "akeo.ie" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "1.0.0.50" |             VALUE "FileVersion", "1.0.0.51" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" |             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||||
|             VALUE "OriginalFilename", "rufus.exe" |             VALUE "OriginalFilename", "rufus.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "1.0.0.50" |             VALUE "ProductVersion", "1.0.0.51" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  | @ -212,7 +212,7 @@ IDI_ICON                ICON                    "rufus.ico" | ||||||
| 
 | 
 | ||||||
| STRINGTABLE | STRINGTABLE | ||||||
| BEGIN | BEGIN | ||||||
|     IDS_VERSION             "Rufus v1.0.0.50" |     IDS_VERSION             "Rufus v1.0.0.51" | ||||||
| END | END | ||||||
| 
 | 
 | ||||||
| #endif    // English resources | #endif    // English resources | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue