diff --git a/src/fat16.c b/src/fat16.c index 12c1dad1..92fcd48a 100644 --- a/src/fat16.c +++ b/src/fat16.c @@ -58,18 +58,23 @@ int write_fat_16_br(FILE *fp, int bKeepLabel) #include "label_11_char.h" #include "br_fat16_0x0.h" #include "br_fat16_0x3e.h" + const unsigned char offset_x24 = 0x80; if(bKeepLabel) return ( write_data(fp, 0x0, br_fat16_0x0, sizeof(br_fat16_0x0)) && /* BIOS Parameter Block should not be overwritten */ - write_data(fp, 0x3e, br_fat16_0x3e, sizeof(br_fat16_0x3e)) ); + write_data(fp, 0x3e, br_fat16_0x3e, sizeof(br_fat16_0x3e)) && + /* except offset 0x24 which may have to be corrected */ + write_data(fp, 0x24, &offset_x24, 1) ); else return ( write_data(fp, 0x0, br_fat16_0x0, sizeof(br_fat16_0x0)) && /* BIOS Parameter Block should not be overwritten */ write_data(fp, 0x2b, label_11_char, sizeof(label_11_char)) && - write_data(fp, 0x3e, br_fat16_0x3e, sizeof(br_fat16_0x3e)) ); + write_data(fp, 0x3e, br_fat16_0x3e, sizeof(br_fat16_0x3e)) && + /* except offset 0x24 which may have to be corrected */ + write_data(fp, 0x24, &offset_x24, 1) ); } /* write_fat_16_br */ int entire_fat_16_fd_br_matches(FILE *fp) diff --git a/src/fat32.c b/src/fat32.c index 8b785b5d..608cc42e 100644 --- a/src/fat32.c +++ b/src/fat32.c @@ -64,12 +64,16 @@ int write_fat_32_br(FILE *fp, int bKeepLabel) #include "br_fat32_0x0.h" #include "br_fat32_0x52.h" #include "br_fat32_0x3f0.h" + const unsigned char offset_x40 = 0x80; if(bKeepLabel) return ( write_data(fp, 0x0, br_fat32_0x0, sizeof(br_fat32_0x0)) && /* BIOS Parameter Block should not be overwritten */ write_data(fp, 0x52, br_fat32_0x52, sizeof(br_fat32_0x52)) && + /* except offsets 0x40 & 0xC40 which may have to be corrected */ + write_data(fp, 0x40, &offset_x40, 1) && + write_data(fp, 0xc40, &offset_x40, 1) && /* Cluster information is not overwritten, however, it would bo OK to write 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff here. */ write_data(fp, 0x3f0, br_fat32_0x3f0, sizeof(br_fat32_0x3f0)) ); @@ -79,6 +83,9 @@ int write_fat_32_br(FILE *fp, int bKeepLabel) /* BIOS Parameter Block should not be overwritten */ write_data(fp, 0x47, label_11_char, sizeof(label_11_char)) && write_data(fp, 0x52, br_fat32_0x52, sizeof(br_fat32_0x52)) && + /* except offsets 0x40 & 0xC40 which may have to be corrected */ + write_data(fp, 0x40, &offset_x40, 1) && + write_data(fp, 0xc40, &offset_x40, 1) && /* Cluster information is not overwritten, however, it would bo OK to write 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff here. */ write_data(fp, 0x3f0, br_fat32_0x3f0, sizeof(br_fat32_0x3f0)) ); diff --git a/src/format.c b/src/format.c index f8fac057..23c26965 100644 --- a/src/format.c +++ b/src/format.c @@ -61,7 +61,6 @@ static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, switch(Command) { case FCC_PROGRESS: - // TODO: send this percentage to the status bar percent = (DWORD*)pData; PrintStatus(0, "Formatting: %d%% completed.\n", *percent); // uprintf("%d percent completed.\n", *percent); @@ -84,9 +83,10 @@ static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, break; case FCC_DONE_WITH_STRUCTURE: // We get this message when formatting Small FAT16 // pData Seems to be a struct with at least one (32 BIT!!!) string pointer to the size in MB - uprintf("Done with that sort of things: Action=%d pData=%0p\n", Action, pData); - DumpBufferHex(pData, 8); - uprintf("Volume size: %s MB\n", (char*)(LONG_PTR)(*(ULONG32*)pData)); + uprintf("Done with that sort of thing: Action=%d pData=%0p\n", Action, pData); + // /!\ THE FOLLOWING ONLY WORKS ON VISTA OR LATER - DO NOT ENABLE ON XP! + // DumpBufferHex(pData, 8); + // uprintf("Volume size: %s MB\n", (char*)(LONG_PTR)(*(ULONG32*)pData)); break; case FCC_INCOMPATIBLE_FILE_SYSTEM: uprintf("Incompatible File System\n"); @@ -318,6 +318,7 @@ static BOOL WritePBR(HANDLE hLogicalVolume) if (write_fat_16_br(&fake_fd, 0)) return TRUE; case FS_FAT32: + // TODO: we may have to validate the 0xc40 offset of second FS boot sector if (write_fat_32_br(&fake_fd, 0)) return TRUE; default: diff --git a/src/rufus.c b/src/rufus.c index 898a6244..50df95ce 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -105,39 +105,75 @@ static BOOL DefineClusterSizes(void) default_fs = FS_UNKNOWN; memset(&SelectedDrive.ClusterSize, 0, sizeof(SelectedDrive.ClusterSize)); if (SelectedDrive.DiskSize < 8*MB) { - // TODO: muck with FAT12 and Small FAT16 like Microsoft does - uprintf("This application does not support volumes smaller than 8 MB yet\n"); + // TODO: muck with FAT12 and Small FAT16 like Microsoft does to support small drives? + uprintf("This application does not support volumes smaller than 8 MB\n"); goto out; } +/* + * The following is MS's allowed cluster sizes for FAT16 and FAT32: + * + * FAT16 + * 31M : 512 - 4096 + * 63M : 1024 - 8192 + * 127M : 2048 - 16k + * 255M : 4096 - 32k + * 511M : 8192 - 64k + * 1023M: 16k - 64k + * 2047M: 32k - 64k + * 4095M: 64k + * 4GB+ : N/A + * + * FAT32 + * 31M : N/A + * 63M : N/A (NB unlike MS, we're allowing 512-512 here - UNTESTED) + * 127M : 512 - 1024 + * 255M : 512 - 2048 + * 511M : 512 - 4096 + * 1023M: 512 - 8192 + * 2047M: 512 - 16k + * 4095M: 1024 - 32k + * 7GB : 2048 - 64k + * 15GB : 4096 - 64k + * 31GB : 8192 - 64k + * 32GB+: possible but N/A from Microsoft (see below) + */ + // FAT 16 if (SelectedDrive.DiskSize < 4*GB) { - // TODO: Refine the following according to size - SelectedDrive.ClusterSize[FS_FAT16].Allowed = 0x0001FE00; + SelectedDrive.ClusterSize[FS_FAT16].Allowed = 0x00001E00; for (i=32; i<=4096; i<<=1) { // 8 MB -> 4 GB if (SelectedDrive.DiskSize < i*MB) { SelectedDrive.ClusterSize[FS_FAT16].Default = 16*(ULONG)i; break; } + SelectedDrive.ClusterSize[FS_FAT16].Allowed <<= 1; } + SelectedDrive.ClusterSize[FS_FAT16].Allowed &= 0x0001FE00; } // FAT 32 - if (SelectedDrive.DiskSize < 256*MB) { - // TODO: Refine the following according to size - SelectedDrive.ClusterSize[FS_FAT32].Allowed = 0x0001FE00; - for (i=64; i<=256; i<<=1) { // 8 MB -> 256 MB + // > 32GB FAT32 is not supported by MS (and likely FormatEx) but is feasible + // See: http://www.ridgecrop.demon.co.uk/index.htm?fat32format.htm + // < 32 MB FAT32 is not allowed by FormatEx + if ((SelectedDrive.DiskSize >= 32*MB) && (SelectedDrive.DiskSize < 32*GB)) { + SelectedDrive.ClusterSize[FS_FAT32].Allowed = 0x000001F8; + for (i=32; i<=(32*1024); i<<=1) { // 32 MB -> 32 GB if (SelectedDrive.DiskSize < i*MB) { SelectedDrive.ClusterSize[FS_FAT32].Default = 8*(ULONG)i; break; } + SelectedDrive.ClusterSize[FS_FAT32].Allowed <<= 1; } - } else if (SelectedDrive.DiskSize < 32*GB) { - SelectedDrive.ClusterSize[FS_FAT32].Allowed = 0x0001FE00; - for (i=8; i<=32; i<<=1) { // 256 MB -> 32 GB - if (SelectedDrive.DiskSize < i*GB) { - SelectedDrive.ClusterSize[FS_FAT32].Default = ((ULONG)i/2)*1024; - break; + SelectedDrive.ClusterSize[FS_FAT32].Allowed &= 0x0001FE00; + + // Default cluster sizes in the 256MB to 32 GB range do not follow the rule above + if (SelectedDrive.DiskSize >= 256*MB) { + for (i=8; i<=32; i<<=1) { // 256 MB -> 32 GB + if (SelectedDrive.DiskSize < i*GB) { + SelectedDrive.ClusterSize[FS_FAT32].Default = ((ULONG)i/2)*1024; + break; + } } } } @@ -192,7 +228,7 @@ out: static BOOL SetClusterSizes(int FSType) { char szClustSize[64]; - int i, default_index = 0; + int i, k, default_index = 0; ULONG j; IGNORE_RETVAL(ComboBox_ResetContent(hClusterSize)); @@ -208,14 +244,15 @@ static BOOL SetClusterSizes(int FSType) return FALSE; } - for(i=0,j=0x200;j<0x10000000;i++,j<<=1) { + for(i=0,j=0x200,k=0;j<0x10000000;i++,j<<=1) { if (j & SelectedDrive.ClusterSize[FSType].Allowed) { safe_sprintf(szClustSize, sizeof(szClustSize), "%s", ClusterSizeLabel[i]); if (j == SelectedDrive.ClusterSize[FSType].Default) { safe_strcat(szClustSize, sizeof(szClustSize), " (Default)"); - default_index = i; + default_index = k; } IGNORE_RETVAL(ComboBox_SetItemData(hClusterSize, ComboBox_AddStringU(hClusterSize, szClustSize), j)); + k++; } } @@ -663,50 +700,48 @@ void UpdateProgress(int op, float percent) /* * Set or restore a Local Group Policy DWORD key indexed by szPath/SzPolicy */ -typedef enum _GROUP_POLICY_OBJECT_TYPE { - GPOTypeLocal = 0,GPOTypeRemote,GPOTypeDS -} GROUP_POLICY_OBJECT_TYPE,*PGROUP_POLICY_OBJECT_TYPE; - -#define REGISTRY_EXTENSION_GUID { 0x35378EAC,0x683F,0x11D2, {0xA8,0x9A,0x00,0xC0,0x4F,0xBB,0xCF,0xA2} } -#define GPO_OPEN_LOAD_REGISTRY 0x00000001 -#define GPO_SECTION_MACHINE 2 - -#undef INTERFACE +#pragma push_macro("INTERFACE") +#undef INTERFACE #define INTERFACE IGroupPolicyObject - DECLARE_INTERFACE_(IGroupPolicyObject,IUnknown) { - STDMETHOD(QueryInterface) (THIS_ REFIID riid,LPVOID *ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - STDMETHOD(New) (THIS_ LPOLESTR pszDomainName,LPOLESTR pszDisplayName,DWORD dwFlags) PURE; - STDMETHOD(OpenDSGPO) (THIS_ LPOLESTR pszPath,DWORD dwFlags) PURE; - STDMETHOD(OpenLocalMachineGPO) (THIS_ DWORD dwFlags) PURE; - STDMETHOD(OpenRemoteMachineGPO) (THIS_ LPOLESTR pszComputerName,DWORD dwFlags) PURE; - STDMETHOD(Save) (THIS_ BOOL bMachine, BOOL bAdd,GUID *pGuidExtension,GUID *pGuid) PURE; - STDMETHOD(Delete) (THIS) PURE; - STDMETHOD(GetName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; - STDMETHOD(GetDisplayName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; - STDMETHOD(SetDisplayName) (THIS_ LPOLESTR pszName) PURE; - STDMETHOD(GetPath) (THIS_ LPOLESTR pszPath,int cchMaxPath) PURE; - STDMETHOD(GetDSPath) (THIS_ DWORD dwSection,LPOLESTR pszPath,int cchMaxPath) PURE; - STDMETHOD(GetFileSysPath) (THIS_ DWORD dwSection,LPOLESTR pszPath,int cchMaxPath) PURE; - STDMETHOD(GetRegistryKey) (THIS_ DWORD dwSection,HKEY *hKey) PURE; - STDMETHOD(GetOptions) (THIS_ DWORD *dwOptions) PURE; - STDMETHOD(SetOptions) (THIS_ DWORD dwOptions,DWORD dwMask) PURE; - STDMETHOD(GetType) (THIS_ GROUP_POLICY_OBJECT_TYPE *gpoType) PURE; - STDMETHOD(GetMachineName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; - STDMETHOD(GetPropertySheetPages) (THIS_ HPROPSHEETPAGE **hPages,UINT *uPageCount) PURE; - }; - typedef IGroupPolicyObject *LPGROUPPOLICYOBJECT; +#define REGISTRY_EXTENSION_GUID { 0x35378EAC, 0x683F, 0x11D2, {0xA8, 0x9A, 0x00, 0xC0, 0x4F, 0xBB, 0xCF, 0xA2} } +#define GPO_OPEN_LOAD_REGISTRY 1 +#define GPO_SECTION_MACHINE 2 +typedef enum _GROUP_POLICY_OBJECT_TYPE { + GPOTypeLocal = 0, GPOTypeRemote, GPOTypeDS +} GROUP_POLICY_OBJECT_TYPE, *PGROUP_POLICY_OBJECT_TYPE; +DECLARE_INTERFACE_(IGroupPolicyObject, IUnknown) { + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID *ppvObj) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + STDMETHOD(New) (THIS_ LPOLESTR pszDomainName, LPOLESTR pszDisplayName, DWORD dwFlags) PURE; + STDMETHOD(OpenDSGPO) (THIS_ LPOLESTR pszPath, DWORD dwFlags) PURE; + STDMETHOD(OpenLocalMachineGPO) (THIS_ DWORD dwFlags) PURE; + STDMETHOD(OpenRemoteMachineGPO) (THIS_ LPOLESTR pszComputerName, DWORD dwFlags) PURE; + STDMETHOD(Save) (THIS_ BOOL bMachine, BOOL bAdd,GUID *pGuidExtension, GUID *pGuid) PURE; + STDMETHOD(Delete) (THIS) PURE; + STDMETHOD(GetName) (THIS_ LPOLESTR pszName, int cchMaxLength) PURE; + STDMETHOD(GetDisplayName) (THIS_ LPOLESTR pszName, int cchMaxLength) PURE; + STDMETHOD(SetDisplayName) (THIS_ LPOLESTR pszName) PURE; + STDMETHOD(GetPath) (THIS_ LPOLESTR pszPath, int cchMaxPath) PURE; + STDMETHOD(GetDSPath) (THIS_ DWORD dwSection, LPOLESTR pszPath ,int cchMaxPath) PURE; + STDMETHOD(GetFileSysPath) (THIS_ DWORD dwSection, LPOLESTR pszPath, int cchMaxPath) PURE; + STDMETHOD(GetRegistryKey) (THIS_ DWORD dwSection, HKEY *hKey) PURE; + STDMETHOD(GetOptions) (THIS_ DWORD *dwOptions) PURE; + STDMETHOD(SetOptions) (THIS_ DWORD dwOptions, DWORD dwMask) PURE; + STDMETHOD(GetType) (THIS_ GROUP_POLICY_OBJECT_TYPE *gpoType) PURE; + STDMETHOD(GetMachineName) (THIS_ LPOLESTR pszName, int cchMaxLength) PURE; + STDMETHOD(GetPropertySheetPages) (THIS_ HPROPSHEETPAGE **hPages, UINT *uPageCount) PURE; +}; +typedef IGroupPolicyObject *LPGROUPPOLICYOBJECT; BOOL SetLGP(BOOL bRestore, const char* szPath, const char* szPolicy, DWORD dwValue) { - OSVERSIONINFO os_version; LONG r; DWORD disp, regtype, val, val_size=sizeof(DWORD); HRESULT hr; IGroupPolicyObject* pLGPO; // These statuc values are used to restore initial state - static BOOL key_was_present = FALSE; + static BOOL existing_key = FALSE; static DWORD original_val; HKEY path_key = NULL, policy_key = NULL; // MSVC is finicky about these ones => redefine them @@ -718,16 +753,6 @@ BOOL SetLGP(BOOL bRestore, const char* szPath, const char* szPolicy, DWORD dwVal // Can be anything really GUID snap_guid = { 0x3D271CFC, 0x2BC6, 0x4AC2, {0xB6, 0x33, 0x3B, 0xDF, 0xF5, 0xBD, 0xAB, 0x2A} }; - // Vista or later - // TODO: should we do this on XP too? - memset(&os_version, 0, sizeof(OSVERSIONINFO)); - os_version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if ((GetVersionEx(&os_version) != 0) && (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT)) { - if (os_version.dwMajorVersion < 6) { - return TRUE; - } - } - // We need an IGroupPolicyObject instance to set a Local Group Policy hr = CoCreateInstance(&my_CLSID_GroupPolicyObject, NULL, CLSCTX_INPROC_SERVER, &my_IID_IGroupPolicyObject, (LPVOID*)&pLGPO); if (FAILED(hr)) { @@ -755,20 +780,20 @@ BOOL SetLGP(BOOL bRestore, const char* szPath, const char* szPolicy, DWORD dwVal goto error; } - if ((disp == REG_OPENED_EXISTING_KEY) && (!bRestore) && (!key_was_present)) { + if ((disp == REG_OPENED_EXISTING_KEY) && (!bRestore) && (!existing_key)) { // backup existing value for restore - key_was_present = TRUE; + existing_key = TRUE; regtype = REG_DWORD; r = RegQueryValueExA(policy_key, szPolicy, NULL, ®type, (LPBYTE)&original_val, &val_size); if (r == ERROR_FILE_NOT_FOUND) { // The Key exists but not its value, which is OK - key_was_present = FALSE; + existing_key = FALSE; } else if (r != ERROR_SUCCESS) { uprintf("SetLGP: Failed to read original %s policy value - error %x\n", szPolicy, r); } } - if ((!bRestore) || (key_was_present)) { + if ((!bRestore) || (existing_key)) { val = (bRestore)?original_val:dwValue; r = RegSetValueExA(policy_key, szPolicy, 0, REG_DWORD, (BYTE*)&val, sizeof(val)); } else { @@ -786,7 +811,11 @@ BOOL SetLGP(BOOL bRestore, const char* szPath, const char* szPolicy, DWORD dwVal uprintf("SetLGP: Unable to apply %s policy - error %x\n", szPolicy, hr); goto error; } else { - uprintf("SetLGP: Successfully %s %s policy\n", (bRestore)?"restored":"disabled", szPolicy); + if ((bRestore) && (!existing_key)) { + uprintf("SetLGP: Successfully removed %s policy key\n", szPolicy); + } else { + uprintf("SetLGP: Successfully %s %s policy to 0x%08X\n", (bRestore)?"restored":"set", szPolicy, val); + } } RegCloseKey(path_key); @@ -799,6 +828,7 @@ error: if (pLGPO != NULL) pLGPO->lpVtbl->Release(pLGPO); return FALSE; } +#pragma pop_macro("INTERFACE") /* * Toggle controls according to operation diff --git a/src/rufus.rc b/src/rufus.rc index 3394c45a..f54677b6 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 278 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.0.3.91" +CAPTION "Rufus v1.0.3.92" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,236,50,14 @@ -64,7 +64,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP CONTROL "http://rufus.akeo.ie",IDC_ABOUT_RUFUS_URL, "SysLink",WS_TABSTOP,46,47,114,9 - LTEXT "Version 1.0.3 (Build 91)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.0.3 (Build 92)",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 @@ -163,8 +163,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,3,91 - PRODUCTVERSION 1,0,3,91 + FILEVERSION 1,0,3,92 + PRODUCTVERSION 1,0,3,92 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -181,13 +181,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.0.3.91" + VALUE "FileVersion", "1.0.3.92" 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.3.91" + VALUE "ProductVersion", "1.0.3.92" END END BLOCK "VarFileInfo"