From 88143701ed3a761561088e3e30a8bf442bcd1bf5 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 29 Nov 2011 23:45:19 +0000 Subject: [PATCH] [mbr] added mbr detection * also added write_data() for Windows in file.h * also merged/removed fat16/32 includes * also removed disk-signature for zeroed MBR detection --- .msvc/rufus_2010.vcxproj | 3 -- .msvc/rufus_2010.vcxproj.filters | 9 ----- fat16.c | 1 - fat32.c | 2 - file.c | 53 +++++++++++++-------------- inc/fat16.h | 9 +++++ inc/fat16fd.h | 15 -------- inc/fat32.h | 18 +++++++++ inc/fat32fd.h | 15 -------- inc/fat32nt.h | 15 -------- inc/mbr_zero.h | 6 +-- rufus.c | 63 ++++++++++++++++++++++++++++---- rufus.rc | 12 +++--- 13 files changed, 116 insertions(+), 105 deletions(-) delete mode 100644 inc/fat16fd.h delete mode 100644 inc/fat32fd.h delete mode 100644 inc/fat32nt.h diff --git a/.msvc/rufus_2010.vcxproj b/.msvc/rufus_2010.vcxproj index fde20c6f..73dffd2a 100644 --- a/.msvc/rufus_2010.vcxproj +++ b/.msvc/rufus_2010.vcxproj @@ -173,10 +173,7 @@ - - - diff --git a/.msvc/rufus_2010.vcxproj.filters b/.msvc/rufus_2010.vcxproj.filters index 03dee667..a844cfd8 100644 --- a/.msvc/rufus_2010.vcxproj.filters +++ b/.msvc/rufus_2010.vcxproj.filters @@ -110,18 +110,9 @@ Header Files\inc - - Header Files\inc - Header Files\inc - - Header Files\inc - - - Header Files\inc - Header Files\inc diff --git a/fat16.c b/fat16.c index 9db91fa8..12c1dad1 100644 --- a/fat16.c +++ b/fat16.c @@ -20,7 +20,6 @@ #include "file.h" #include "fat16.h" -#include "fat16fd.h" int is_fat_16_fs(FILE *fp) { diff --git a/fat32.c b/fat32.c index 2154be6f..8b785b5d 100644 --- a/fat32.c +++ b/fat32.c @@ -20,8 +20,6 @@ #include "file.h" #include "fat32.h" -#include "fat32fd.h" -#include "fat32nt.h" int is_fat_32_fs(FILE *fp) { diff --git a/file.c b/file.c index 01d81746..15140671 100644 --- a/file.c +++ b/file.c @@ -1,6 +1,6 @@ /****************************************************************** Copyright (C) 2009 Henrik Carlqvist - Modified for Windows/Rufus (C) 2011 Pete Batard + Modified for Rufus/Windows (C) 2011 Pete Batard This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -106,38 +106,37 @@ int contains_data(FILE *fp, unsigned long ulPosition, if(memcmp(pData, &aucBuf[ulPosition - ulStartSector*ulSectorSize], uiLen)) return 0; return 1; - -/* - // ONLY WORKS IN SECTORS!!! - ptr.QuadPart = ulPosition; - uprintf("HANDLE = %p\n", (HANDLE)fp); - if (!SetFilePointerEx((HANDLE)fp, ptr, NULL, FILE_BEGIN)) - { - uprintf("Could not access byte %d - %s\n", ulPosition, WindowsErrorString()); - return 0; - } - uprintf("SEEK to %d OK\n", WindowsErrorString()); - - uiLen = 512; - if ((!ReadFile((HANDLE)fp, aucBuf, (DWORD)uiLen, &size, NULL)) || (size != (DWORD)uiLen)) { - uprintf("Read error (size = %d vs %d) - %s\n", size, (DWORD)uiLen, WindowsErrorString()); - return 0; - } - - uiLen = 2; - uprintf("aucBuf[0] = %02X, aucBuf[1] = %02X\n", aucBuf[0], aucBuf[1]); - if(memcmp(pData, aucBuf, uiLen)) - return 0; - return 1; -*/ } /* contains_data */ +/* May read/write the same sector many times, but compatible with existing ms-sys */ int write_data(FILE *fp, unsigned long ulPosition, const void *pData, unsigned int uiLen) { - if(fseek(fp, ulPosition, SEEK_SET)) + unsigned char aucBuf[MAX_DATA_LEN]; + HANDLE hDrive = (HANDLE)fp->_ptr; + unsigned long ulSectorSize = (unsigned long)fp->_bufsiz; + unsigned long ulStartSector, ulEndSector, ulNumSectors; + + ulStartSector = ulPosition/ulSectorSize; + ulEndSector = (ulPosition+uiLen+ulSectorSize-1)/ulSectorSize; + ulNumSectors = ulEndSector - ulStartSector; + + if((ulNumSectors*ulSectorSize) > MAX_DATA_LEN) + { + uprintf("Please increase MAX_DATA_LEN in file.h\n"); return 0; - if(!fwrite(pData, uiLen, 1, fp)) + } + + /* Data to write may not be aligned on a sector boundary => read into a sector buffer first */ + if(!read_sectors(hDrive, ulSectorSize, ulStartSector, + ulNumSectors, aucBuf, sizeof(aucBuf))) + return 0; + + if(!memcpy(&aucBuf[ulPosition - ulStartSector*ulSectorSize], pData, uiLen)) + return 0; + + if(!write_sectors(hDrive, ulSectorSize, ulStartSector, + ulNumSectors, aucBuf, sizeof(aucBuf))) return 0; return 1; } /* write_data */ diff --git a/inc/fat16.h b/inc/fat16.h index a8704bac..222e4812 100644 --- a/inc/fat16.h +++ b/inc/fat16.h @@ -20,4 +20,13 @@ int entire_fat_16_br_matches(FILE *fp); FALSE */ int write_fat_16_br(FILE *fp, int bKeepLabel); +/* returns TRUE if the file has an exact match ot the FAT16 boot record this + program would create for FreeDOS, otherwise FALSE. + The file position will change when this function is called! */ +int entire_fat_16_fd_br_matches(FILE *fp); + +/* Writes a FAT16 FreeDOS boot record to a file, returns TRUE on success, + otherwise FALSE */ +int write_fat_16_fd_br(FILE *fp, int bKeepLabel); + #endif diff --git a/inc/fat16fd.h b/inc/fat16fd.h deleted file mode 100644 index d9698a6b..00000000 --- a/inc/fat16fd.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef FAT16FD_H -#define FAT16FD_H - -#include - -/* returns TRUE if the file has an exact match ot the FAT16 boot record this - program would create for FreeDOS, otherwise FALSE. - The file position will change when this function is called! */ -int entire_fat_16_fd_br_matches(FILE *fp); - -/* Writes a FAT16 FreeDOS boot record to a file, returns TRUE on success, - otherwise FALSE */ -int write_fat_16_fd_br(FILE *fp, int bKeepLabel); - -#endif diff --git a/inc/fat32.h b/inc/fat32.h index 6eb7f5bf..dbd61ecb 100644 --- a/inc/fat32.h +++ b/inc/fat32.h @@ -20,4 +20,22 @@ int entire_fat_32_br_matches(FILE *fp); FALSE */ int write_fat_32_br(FILE *fp, int bKeepLabel); +/* returns TRUE if the file has an exact match ot the FAT32 boot record this + program would create for FreeDOS, otherwise FALSE. + The file position will change when this function is called! */ +int entire_fat_32_fd_br_matches(FILE *fp); + +/* Writes a FAT32 FreeDOS boot record to a file, returns TRUE on success, + otherwise FALSE */ +int write_fat_32_fd_br(FILE *fp, int bKeepLabel); + +/* returns TRUE if the file has an exact match ot the FAT32 boot record this + program would create for NT, otherwise FALSE. + The file position will change when this function is called! */ +int entire_fat_32_nt_br_matches(FILE *fp); + +/* Writes a FAT32 NT boot record to a file, returns TRUE on success, otherwise + FALSE */ +int write_fat_32_nt_br(FILE *fp, int bKeepLabel); + #endif diff --git a/inc/fat32fd.h b/inc/fat32fd.h deleted file mode 100644 index 6451814b..00000000 --- a/inc/fat32fd.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef FAT32FD_H -#define FAT32FD_H - -#include - -/* returns TRUE if the file has an exact match ot the FAT32 boot record this - program would create for FreeDOS, otherwise FALSE. - The file position will change when this function is called! */ -int entire_fat_32_fd_br_matches(FILE *fp); - -/* Writes a FAT32 FreeDOS boot record to a file, returns TRUE on success, - otherwise FALSE */ -int write_fat_32_fd_br(FILE *fp, int bKeepLabel); - -#endif diff --git a/inc/fat32nt.h b/inc/fat32nt.h deleted file mode 100644 index c3cb0d2f..00000000 --- a/inc/fat32nt.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef FAT32NT_H -#define FAT32NT_H - -#include - -/* returns TRUE if the file has an exact match ot the FAT32 boot record this - program would create for NT, otherwise FALSE. - The file position will change when this function is called! */ -int entire_fat_32_nt_br_matches(FILE *fp); - -/* Writes a FAT32 NT boot record to a file, returns TRUE on success, otherwise - FALSE */ -int write_fat_32_nt_br(FILE *fp, int bKeepLabel); - -#endif diff --git a/inc/mbr_zero.h b/inc/mbr_zero.h index 1470717e..09535624 100644 --- a/inc/mbr_zero.h +++ b/inc/mbr_zero.h @@ -1,4 +1,4 @@ -/* First 446 bytes of a zeroed MBR*/ +/* First 440 bytes of a zeroed MBR (disk signature is excluded) */ unsigned char mbr_zero_0x0[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -36,6 +36,4 @@ unsigned char mbr_zero_0x0[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/rufus.c b/rufus.c index e9951cb9..b846de64 100644 --- a/rufus.c +++ b/rufus.c @@ -49,6 +49,7 @@ #include "rufus.h" #include "sys_types.h" #include "br.h" +#include "fat16.h" #include "fat32.h" #include "file.h" @@ -646,14 +647,63 @@ out: return r; } +static BOOL AnalyzeMBR(HANDLE hPhysicalDrive) +{ + FILE fake_fd; + + fake_fd._ptr = (char*)hPhysicalDrive; + fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; + + // TODO: Apply this detection before partitioning + // TODO: since we detect all these, might as well give some MBR choice to the user? + if (is_br(&fake_fd)) { + uprintf("Drive has an x86 boot sector\n"); + } else{ + uprintf("Drive is missing an x86 boot sector!\n"); + return FALSE; + } + // TODO: Add/Eliminate FAT12? + if (is_fat_16_br(&fake_fd) || is_fat_32_br(&fake_fd)) { + if (entire_fat_16_br_matches(&fake_fd)) { + uprintf("Exact FAT16 DOS boot record match\n"); + } else if (entire_fat_16_fd_br_matches(&fake_fd)) { + uprintf("Exact FAT16 FreeDOS boot record match\n"); + } else if (entire_fat_32_br_matches(&fake_fd)) { + uprintf("Exact FAT32 DOS boot record match\n"); + } else if (entire_fat_32_nt_br_matches(&fake_fd)) { + uprintf("Exact FAT32 NT boot record match\n"); + } else if (entire_fat_32_fd_br_matches(&fake_fd)) { + uprintf("Exactly FAT32 FreeDOS boot record match\n"); + } else { + uprintf("Unknown FAT16 or FAT32 boot record\n"); + } + } else if (is_dos_mbr(&fake_fd)) { + uprintf("Microsoft DOS/NT/95A master boot record match\n"); + } else if (is_dos_f2_mbr(&fake_fd)) { + uprintf("Microsoft DOS/NT/95A master boot record with the undocumented\n"); + uprintf("F2 instruction match\n"); + } else if (is_95b_mbr(&fake_fd)) { + uprintf("Microsoft 95B/98/98SE/ME master boot record match\n"); + } else if (is_2000_mbr(&fake_fd)) { + uprintf("Microsoft 2000/XP/2003 master boot record match\n"); + } else if (is_vista_mbr(&fake_fd)) { + uprintf("Microsoft Vista master boot record match\n"); + } else if (is_win7_mbr(&fake_fd)) { + uprintf("Microsoft 7 master boot record match\n"); + } else if (is_zero_mbr(&fake_fd)) { + uprintf("Zeroed non-bootable master boot record match\n"); + } else { + uprintf("Unknown boot record\n"); + } + return TRUE; +} + /* * Process the MBR */ static BOOL ProcessMBR(HANDLE hPhysicalDrive) { BOOL r = FALSE; - HANDLE hDrive = hPhysicalDrive; - FILE fake_fd; unsigned char* buf = NULL; size_t SecSize = SelectedDrive.Geometry.BytesPerSector; size_t nSecs = 0x200/min(0x200, SelectedDrive.Geometry.BytesPerSector); @@ -665,10 +715,7 @@ static BOOL ProcessMBR(HANDLE hPhysicalDrive) } PrintStatus("Processing MBR...\n"); - - fake_fd._ptr = (char*)hPhysicalDrive; - fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector; - uprintf("I'm %sa boot record\n", is_br(&fake_fd)?"":"NOT "); + if (!AnalyzeMBR(hPhysicalDrive)) return FALSE; // FormatEx rewrites the MBR and removes the LBA attribute of FAT16 // and FAT32 partitions - we need to correct this in the MBR @@ -680,7 +727,7 @@ static BOOL ProcessMBR(HANDLE hPhysicalDrive) goto out; } - if (!read_sectors(hDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) { + if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) { uprintf("Could not read MBR\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; goto out; @@ -696,7 +743,7 @@ static BOOL ProcessMBR(HANDLE hPhysicalDrive) break; } - if (!write_sectors(hDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) { + if (!write_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) { uprintf("Could not write MBR\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; goto out; diff --git a/rufus.rc b/rufus.rc index 7fd9c268..dd1f64d3 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 48)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.0.0 (Build 49)",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,48 - PRODUCTVERSION 1,0,0,48 + FILEVERSION 1,0,0,49 + PRODUCTVERSION 1,0,0,49 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -180,13 +180,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.0.0.48" + VALUE "FileVersion", "1.0.0.49" 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.48" + VALUE "ProductVersion", "1.0.0.49" END END BLOCK "VarFileInfo" @@ -212,7 +212,7 @@ IDI_ICON ICON "rufus.ico" STRINGTABLE BEGIN - IDS_VERSION "Rufus v1.0.0.48" + IDS_VERSION "Rufus v1.0.0.49" END #endif // English resources