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…
Reference in a new issue