[ui] improve the allowed cluster sizes

* follow what MS/FormatEx actually allow
* closes #15
* also fixed potential empty selection in cluster size dropdown
* also improved Local Group Policy handling
This commit is contained in:
Pete Batard 2011-12-12 14:22:40 +00:00
parent 72485b7568
commit d59854ef4f
4 changed files with 110 additions and 69 deletions

13
TODO
View file

@ -1,9 +1,10 @@
o create a report file with failed block details when bad blocks are found o Create a report file with failed block details on bad blocks
o use the umount/remount trick to make the volume reappear post formatting o Integrate FreeDOS
o set keyboard according to locale in DOS o Allow the provision of external DOS files
o allow selection of one of the existing compatible volume (keep existing MBR) / full repartitioning (overwrite MBR) o Set DOS keyboard according to locale
o FreeDOS integration o Allow selection of one of the existing compatible partitions (keep existing MBR) vs. full repartitioning (overwrite MBR)
o Enable compression for NTFS
o Bootable NTFS/exFAT (http://sourceforge.net/projects/grub4dos)? o Bootable NTFS/exFAT (http://sourceforge.net/projects/grub4dos)?
o GPT support? o GPT support?
o Enable compression for NTFS?
o disable indexing support on NTFS? o disable indexing support on NTFS?
o FAT32 formatting for volumes > 32 GB?

View file

@ -61,7 +61,6 @@ static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command,
switch(Command) { switch(Command) {
case FCC_PROGRESS: case FCC_PROGRESS:
// TODO: send this percentage to the status bar
percent = (DWORD*)pData; percent = (DWORD*)pData;
PrintStatus(0, "Formatting: %d%% completed.\n", *percent); PrintStatus(0, "Formatting: %d%% completed.\n", *percent);
// uprintf("%d percent completed.\n", *percent); // uprintf("%d percent completed.\n", *percent);

View file

@ -105,35 +105,70 @@ static BOOL DefineClusterSizes(void)
default_fs = FS_UNKNOWN; default_fs = FS_UNKNOWN;
memset(&SelectedDrive.ClusterSize, 0, sizeof(SelectedDrive.ClusterSize)); memset(&SelectedDrive.ClusterSize, 0, sizeof(SelectedDrive.ClusterSize));
if (SelectedDrive.DiskSize < 8*MB) { if (SelectedDrive.DiskSize < 8*MB) {
// TODO: muck with FAT12 and Small FAT16 like Microsoft does // 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 yet\n"); uprintf("This application does not support volumes smaller than 8 MB\n");
goto out; 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 // FAT 16
if (SelectedDrive.DiskSize < 4*GB) { if (SelectedDrive.DiskSize < 4*GB) {
// TODO: Refine the following according to size SelectedDrive.ClusterSize[FS_FAT16].Allowed = 0x00001E00;
SelectedDrive.ClusterSize[FS_FAT16].Allowed = 0x0001FE00;
for (i=32; i<=4096; i<<=1) { // 8 MB -> 4 GB for (i=32; i<=4096; i<<=1) { // 8 MB -> 4 GB
if (SelectedDrive.DiskSize < i*MB) { if (SelectedDrive.DiskSize < i*MB) {
SelectedDrive.ClusterSize[FS_FAT16].Default = 16*(ULONG)i; SelectedDrive.ClusterSize[FS_FAT16].Default = 16*(ULONG)i;
break; break;
} }
SelectedDrive.ClusterSize[FS_FAT16].Allowed <<= 1;
} }
SelectedDrive.ClusterSize[FS_FAT16].Allowed &= 0x0001FE00;
} }
// FAT 32 // FAT 32
if (SelectedDrive.DiskSize < 256*MB) { // > 32GB FAT32 is not supported by MS (and likely FormatEx) but is feasible
// TODO: Refine the following according to size // See: http://www.ridgecrop.demon.co.uk/index.htm?fat32format.htm
SelectedDrive.ClusterSize[FS_FAT32].Allowed = 0x0001FE00; // < 32 MB FAT32 is not allowed by FormatEx
for (i=64; i<=256; i<<=1) { // 8 MB -> 256 MB 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) { if (SelectedDrive.DiskSize < i*MB) {
SelectedDrive.ClusterSize[FS_FAT32].Default = 8*(ULONG)i; SelectedDrive.ClusterSize[FS_FAT32].Default = 8*(ULONG)i;
break; break;
} }
SelectedDrive.ClusterSize[FS_FAT32].Allowed <<= 1;
} }
} else if (SelectedDrive.DiskSize < 32*GB) { SelectedDrive.ClusterSize[FS_FAT32].Allowed &= 0x0001FE00;
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 for (i=8; i<=32; i<<=1) { // 256 MB -> 32 GB
if (SelectedDrive.DiskSize < i*GB) { if (SelectedDrive.DiskSize < i*GB) {
SelectedDrive.ClusterSize[FS_FAT32].Default = ((ULONG)i/2)*1024; SelectedDrive.ClusterSize[FS_FAT32].Default = ((ULONG)i/2)*1024;
@ -141,6 +176,7 @@ static BOOL DefineClusterSizes(void)
} }
} }
} }
}
// NTFS // NTFS
if (SelectedDrive.DiskSize < 256*TB) { if (SelectedDrive.DiskSize < 256*TB) {
@ -192,7 +228,7 @@ out:
static BOOL SetClusterSizes(int FSType) static BOOL SetClusterSizes(int FSType)
{ {
char szClustSize[64]; char szClustSize[64];
int i, default_index = 0; int i, k, default_index = 0;
ULONG j; ULONG j;
IGNORE_RETVAL(ComboBox_ResetContent(hClusterSize)); IGNORE_RETVAL(ComboBox_ResetContent(hClusterSize));
@ -208,14 +244,15 @@ static BOOL SetClusterSizes(int FSType)
return FALSE; 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) { if (j & SelectedDrive.ClusterSize[FSType].Allowed) {
safe_sprintf(szClustSize, sizeof(szClustSize), "%s", ClusterSizeLabel[i]); safe_sprintf(szClustSize, sizeof(szClustSize), "%s", ClusterSizeLabel[i]);
if (j == SelectedDrive.ClusterSize[FSType].Default) { if (j == SelectedDrive.ClusterSize[FSType].Default) {
safe_strcat(szClustSize, sizeof(szClustSize), " (Default)"); safe_strcat(szClustSize, sizeof(szClustSize), " (Default)");
default_index = i; default_index = k;
} }
IGNORE_RETVAL(ComboBox_SetItemData(hClusterSize, ComboBox_AddStringU(hClusterSize, szClustSize), j)); IGNORE_RETVAL(ComboBox_SetItemData(hClusterSize, ComboBox_AddStringU(hClusterSize, szClustSize), j));
k++;
} }
} }
@ -663,40 +700,39 @@ void UpdateProgress(int op, float percent)
/* /*
* Set or restore a Local Group Policy DWORD key indexed by szPath/SzPolicy * Set or restore a Local Group Policy DWORD key indexed by szPath/SzPolicy
*/ */
typedef enum _GROUP_POLICY_OBJECT_TYPE { #pragma push_macro("INTERFACE")
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 #undef INTERFACE
#define INTERFACE IGroupPolicyObject #define INTERFACE IGroupPolicyObject
DECLARE_INTERFACE_(IGroupPolicyObject,IUnknown) { #define REGISTRY_EXTENSION_GUID { 0x35378EAC, 0x683F, 0x11D2, {0xA8, 0x9A, 0x00, 0xC0, 0x4F, 0xBB, 0xCF, 0xA2} }
STDMETHOD(QueryInterface) (THIS_ REFIID riid,LPVOID *ppvObj) PURE; #define GPO_OPEN_LOAD_REGISTRY 1
STDMETHOD_(ULONG,AddRef) (THIS) PURE; #define GPO_SECTION_MACHINE 2
STDMETHOD_(ULONG,Release) (THIS) PURE; typedef enum _GROUP_POLICY_OBJECT_TYPE {
STDMETHOD(New) (THIS_ LPOLESTR pszDomainName,LPOLESTR pszDisplayName,DWORD dwFlags) PURE; GPOTypeLocal = 0, GPOTypeRemote, GPOTypeDS
STDMETHOD(OpenDSGPO) (THIS_ LPOLESTR pszPath,DWORD dwFlags) PURE; } 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(OpenLocalMachineGPO) (THIS_ DWORD dwFlags) PURE;
STDMETHOD(OpenRemoteMachineGPO) (THIS_ LPOLESTR pszComputerName,DWORD dwFlags) PURE; STDMETHOD(OpenRemoteMachineGPO) (THIS_ LPOLESTR pszComputerName, DWORD dwFlags) PURE;
STDMETHOD(Save) (THIS_ BOOL bMachine, BOOL bAdd,GUID *pGuidExtension,GUID *pGuid) PURE; STDMETHOD(Save) (THIS_ BOOL bMachine, BOOL bAdd,GUID *pGuidExtension, GUID *pGuid) PURE;
STDMETHOD(Delete) (THIS) PURE; STDMETHOD(Delete) (THIS) PURE;
STDMETHOD(GetName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; STDMETHOD(GetName) (THIS_ LPOLESTR pszName, int cchMaxLength) PURE;
STDMETHOD(GetDisplayName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; STDMETHOD(GetDisplayName) (THIS_ LPOLESTR pszName, int cchMaxLength) PURE;
STDMETHOD(SetDisplayName) (THIS_ LPOLESTR pszName) PURE; STDMETHOD(SetDisplayName) (THIS_ LPOLESTR pszName) PURE;
STDMETHOD(GetPath) (THIS_ LPOLESTR pszPath,int cchMaxPath) PURE; STDMETHOD(GetPath) (THIS_ LPOLESTR pszPath, int cchMaxPath) PURE;
STDMETHOD(GetDSPath) (THIS_ DWORD dwSection,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(GetFileSysPath) (THIS_ DWORD dwSection, LPOLESTR pszPath, int cchMaxPath) PURE;
STDMETHOD(GetRegistryKey) (THIS_ DWORD dwSection,HKEY *hKey) PURE; STDMETHOD(GetRegistryKey) (THIS_ DWORD dwSection, HKEY *hKey) PURE;
STDMETHOD(GetOptions) (THIS_ DWORD *dwOptions) PURE; STDMETHOD(GetOptions) (THIS_ DWORD *dwOptions) PURE;
STDMETHOD(SetOptions) (THIS_ DWORD dwOptions,DWORD dwMask) PURE; STDMETHOD(SetOptions) (THIS_ DWORD dwOptions, DWORD dwMask) PURE;
STDMETHOD(GetType) (THIS_ GROUP_POLICY_OBJECT_TYPE *gpoType) PURE; STDMETHOD(GetType) (THIS_ GROUP_POLICY_OBJECT_TYPE *gpoType) PURE;
STDMETHOD(GetMachineName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; STDMETHOD(GetMachineName) (THIS_ LPOLESTR pszName, int cchMaxLength) PURE;
STDMETHOD(GetPropertySheetPages) (THIS_ HPROPSHEETPAGE **hPages,UINT *uPageCount) PURE; STDMETHOD(GetPropertySheetPages) (THIS_ HPROPSHEETPAGE **hPages, UINT *uPageCount) PURE;
}; };
typedef IGroupPolicyObject *LPGROUPPOLICYOBJECT; typedef IGroupPolicyObject *LPGROUPPOLICYOBJECT;
BOOL SetLGP(BOOL bRestore, const char* szPath, const char* szPolicy, DWORD dwValue) BOOL SetLGP(BOOL bRestore, const char* szPath, const char* szPolicy, DWORD dwValue)
{ {
@ -706,7 +742,7 @@ BOOL SetLGP(BOOL bRestore, const char* szPath, const char* szPolicy, DWORD dwVal
HRESULT hr; HRESULT hr;
IGroupPolicyObject* pLGPO; IGroupPolicyObject* pLGPO;
// These statuc values are used to restore initial state // These statuc values are used to restore initial state
static BOOL key_was_present = FALSE; static BOOL existing_key = FALSE;
static DWORD original_val; static DWORD original_val;
HKEY path_key = NULL, policy_key = NULL; HKEY path_key = NULL, policy_key = NULL;
// MSVC is finicky about these ones => redefine them // MSVC is finicky about these ones => redefine them
@ -755,20 +791,20 @@ BOOL SetLGP(BOOL bRestore, const char* szPath, const char* szPolicy, DWORD dwVal
goto error; 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 // backup existing value for restore
key_was_present = TRUE; existing_key = TRUE;
regtype = REG_DWORD; regtype = REG_DWORD;
r = RegQueryValueExA(policy_key, szPolicy, NULL, &regtype, (LPBYTE)&original_val, &val_size); r = RegQueryValueExA(policy_key, szPolicy, NULL, &regtype, (LPBYTE)&original_val, &val_size);
if (r == ERROR_FILE_NOT_FOUND) { if (r == ERROR_FILE_NOT_FOUND) {
// The Key exists but not its value, which is OK // The Key exists but not its value, which is OK
key_was_present = FALSE; existing_key = FALSE;
} else if (r != ERROR_SUCCESS) { } else if (r != ERROR_SUCCESS) {
uprintf("SetLGP: Failed to read original %s policy value - error %x\n", szPolicy, r); 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; val = (bRestore)?original_val:dwValue;
r = RegSetValueExA(policy_key, szPolicy, 0, REG_DWORD, (BYTE*)&val, sizeof(val)); r = RegSetValueExA(policy_key, szPolicy, 0, REG_DWORD, (BYTE*)&val, sizeof(val));
} else { } else {
@ -786,7 +822,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); uprintf("SetLGP: Unable to apply %s policy - error %x\n", szPolicy, hr);
goto error; goto error;
} else { } 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); RegCloseKey(path_key);
@ -799,6 +839,7 @@ error:
if (pLGPO != NULL) pLGPO->lpVtbl->Release(pLGPO); if (pLGPO != NULL) pLGPO->lpVtbl->Release(pLGPO);
return FALSE; return FALSE;
} }
#pragma pop_macro("INTERFACE")
/* /*
* Toggle controls according to operation * Toggle controls according to operation

View file

@ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 206, 278 IDD_DIALOG DIALOGEX 12, 12, 206, 278
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW EXSTYLE WS_EX_APPWINDOW
CAPTION "Rufus v1.0.2.89 (Beta)" CAPTION "Rufus v1.0.2.90 (Beta)"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,94,236,50,14 DEFPUSHBUTTON "Start",IDC_START,94,236,50,14
@ -64,7 +64,7 @@ BEGIN
DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP
CONTROL "<a href=""http://rufus.akeo.ie"">http://rufus.akeo.ie</a>",IDC_ABOUT_RUFUS_URL, CONTROL "<a href=""http://rufus.akeo.ie"">http://rufus.akeo.ie</a>",IDC_ABOUT_RUFUS_URL,
"SysLink",WS_TABSTOP,46,47,114,9 "SysLink",WS_TABSTOP,46,47,114,9
LTEXT "Version 1.0.2 (Build 89)",IDC_STATIC,46,19,78,8 LTEXT "Version 1.0.2 (Build 90)",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
@ -163,8 +163,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,2,89 FILEVERSION 1,0,2,90
PRODUCTVERSION 1,0,2,89 PRODUCTVERSION 1,0,2,90
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -181,13 +181,13 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "akeo.ie" VALUE "CompanyName", "akeo.ie"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "1.0.2.89" VALUE "FileVersion", "1.0.2.90"
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.2.89" VALUE "ProductVersion", "1.0.2.90"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"