From 86d5f02a20aba3089e05b83962c7a3edcf45c51b Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 5 Nov 2013 02:16:49 +0000 Subject: [PATCH] [misc] improve Windows version detection * Also update README.txt * Closes #220 --- README.txt | 4 +- src/license.h | 4 ++ src/rufus.c | 19 +------ src/rufus.h | 20 ++++--- src/rufus.rc | 10 ++-- src/stdfn.c | 150 ++++++++++++++++++++++++++++++++++++-------------- 6 files changed, 132 insertions(+), 75 deletions(-) diff --git a/README.txt b/README.txt index a2792d13..3f8d64c5 100644 --- a/README.txt +++ b/README.txt @@ -2,12 +2,12 @@ Rufus: The Reliable USB Formatting Utility Features: - Formats USB flash drives to FAT/FAT32/NTFS/UDF/exFAT -- Creates DOS bootable USB drives, with no external files required +- Creates DOS bootable USB drives, using FreeDOS or MS-DOS with no external files required - Creates MBR or GPT/UEFI bootable USB drives - Creates bootable USB drives from bootable ISOs (Windows, Linux, etc.) - Twice as fast as Microsoft's USB/DVD tool or UNetbootin, on ISO->USB (1) - Can perform bad blocks check, with fake drive detection -- Modern UI +- Modern and familiar UI - Small footprint, no installation required - 100% Free Source Software (GPL v3) diff --git a/src/license.h b/src/license.h index 43da88f1..b9aeecde 100644 --- a/src/license.h +++ b/src/license.h @@ -75,6 +75,10 @@ const char* additional_copyrights = "http://svn.reactos.org/svn/reactos/trunk/reactos\\line\n" "GNU General Public License (GPL) v3 compatible\\line\n" "\\line\n" +"Some generic function calls from smartmontools:\\line\n" +"https://sourceforge.net/projects/smartmontools\\line\n" +"GNU General Public License (GPL) v2 or later\\line\n" +"\\line\n" "FS Type description from by GNU fdisk:\\line\n" "http://www.gnu.org/software/fdisk\\line\n" "GNU General Public License (GPL) v3 or later\\line\n" diff --git a/src/rufus.c b/src/rufus.c index 66d070f8..3aefd7cf 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -1272,8 +1272,6 @@ void InitDialog(HWND hDlg) HDC hDC; int i, i16, s16; char tmp[128], *token; - BOOL is_x64 = FALSE; - BOOL (__stdcall *pIsWow64Process)(HANDLE, PBOOL) = NULL; #ifdef RUFUS_TEST ShowWindow(GetDlgItem(hDlg, IDC_TEST), SW_SHOW); @@ -1318,20 +1316,7 @@ void InitDialog(HWND hDlg) for (i=0; (i<4) && ((token = strtok(NULL, ".")) != NULL); i++) rufus_version[i] = (uint16_t)atoi(token); uprintf(APPLICATION_NAME " version %d.%d.%d.%d\n", rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]); - - // Detect if we're running a 32 or 64 bit system - if (sizeof(uintptr_t) < 8) { - pIsWow64Process = (BOOL (__stdcall *)(HANDLE, PBOOL)) - GetProcAddress(GetModuleHandleA("KERNEL32"), "IsWow64Process"); - if (pIsWow64Process != NULL) { - (*pIsWow64Process)(GetCurrentProcess(), &is_x64); - } - } else { - is_x64 = TRUE; - } - uprintf("Windows version: %s %d-bit\n", PrintWindowsVersion(nWindowsVersion), is_x64?64:32); - - // Detect the LCID + uprintf("Windows version: %s\n", WindowsVersionStr); uprintf("LCID: 0x%04X\n", GetUserDefaultLCID()); SetClusterSizeLabels(); @@ -2103,7 +2088,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine } // Set the Windows version - nWindowsVersion = DetectWindowsVersion(); + GetWindowsVersion(); // We use local group policies rather than direct registry manipulation // 0x9e disables removable and fixed drive notifications diff --git a/src/rufus.h b/src/rufus.h index 1c283a15..4e3fac36 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -251,13 +251,14 @@ typedef enum TASKBAR_PROGRESS_FLAGS /* Windows versions */ enum WindowsVersion { - WINDOWS_UNDEFINED = 0, - WINDOWS_UNSUPPORTED, - WINDOWS_XP, - WINDOWS_2003, // Also XP x64 - WINDOWS_VISTA, - WINDOWS_7, - WINDOWS_8_OR_LATER, + WINDOWS_UNDEFINED = -1, + WINDOWS_UNSUPPORTED = 0, + WINDOWS_XP = 0x51, + WINDOWS_2003 = 0x52, // Also XP x64 + WINDOWS_VISTA = 0x60, + WINDOWS_7 = 0x61, + WINDOWS_8 = 0x62, + WINDOWS_8_1_OR_LATER = 0x63, WINDOWS_MAX }; @@ -278,14 +279,15 @@ extern BOOL use_own_c32[NB_OLD_C32], detect_fakes, iso_op_in_progress, format_op extern RUFUS_ISO_REPORT iso_report; extern int64_t iso_blocking_status; extern uint16_t rufus_version[4]; -extern enum WindowsVersion nWindowsVersion; +extern int nWindowsVersion; +extern char WindowsVersionStr[128]; extern RUFUS_UPDATE update; extern int dialog_showing; /* * Shared prototypes */ -extern enum WindowsVersion DetectWindowsVersion(void); +extern void GetWindowsVersion(void); extern const char* PrintWindowsVersion(enum WindowsVersion version); extern const char *WindowsErrorString(void); extern void DumpBufferHex(void *buf, size_t size); diff --git a/src/rufus.rc b/src/rufus.rc index 173862ba..f7e1fed9 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 329 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.4.0.307" +CAPTION "Rufus v1.4.0.308" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,291,50,14 @@ -289,8 +289,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,0,307 - PRODUCTVERSION 1,4,0,307 + FILEVERSION 1,4,0,308 + PRODUCTVERSION 1,4,0,308 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -307,13 +307,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.4.0.307" + VALUE "FileVersion", "1.4.0.308" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2013 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.4.0.307" + VALUE "ProductVersion", "1.4.0.308" END END BLOCK "VarFileInfo" diff --git a/src/stdfn.c b/src/stdfn.c index da666421..2e4b6f55 100644 --- a/src/stdfn.c +++ b/src/stdfn.c @@ -29,53 +29,119 @@ #include "resource.h" #include "localization.h" -// Must be in the same order as enum WindowsVersion -static const char* WindowsVersionName[WINDOWS_MAX] = { - "Undefined", - "Windows 2000 or earlier (unsupported)", - "Windows XP", - "Windows 2003 (or XP x64)", - "Windows Vista", - "Windows 7", - "Windows 8 or later", -}; +int nWindowsVersion = WINDOWS_UNDEFINED; +char WindowsVersionStr[128] = "Windows "; -enum WindowsVersion nWindowsVersion = WINDOWS_UNDEFINED; - -/* - * Detect Windows version - */ -enum WindowsVersion DetectWindowsVersion(void) +static BOOL is_x64(void) { - OSVERSIONINFO OSVersion; - - memset(&OSVersion, 0, sizeof(OSVERSIONINFO)); - OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (GetVersionEx(&OSVersion) == 0) - return WINDOWS_UNDEFINED; - if (OSVersion.dwPlatformId != VER_PLATFORM_WIN32_NT) - return WINDOWS_UNSUPPORTED; - // See the Remarks section from http://msdn.microsoft.com/en-us/library/windows/desktop/ms724833.aspx - if ((OSVersion.dwMajorVersion < 5) || ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 0))) - return WINDOWS_UNSUPPORTED; // Win2k or earlier - if ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 1)) - return WINDOWS_XP; - if ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 2)) - return WINDOWS_2003; - if ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion == 0)) - return WINDOWS_VISTA; - if ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion == 1)) - return WINDOWS_7; - if ((OSVersion.dwMajorVersion > 6) || ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion >= 2))) - return WINDOWS_8_OR_LATER; - return WINDOWS_UNSUPPORTED; + BOOL ret = FALSE; + BOOL (__stdcall *pIsWow64Process)(HANDLE, PBOOL) = NULL; + // Detect if we're running a 32 or 64 bit system + if (sizeof(uintptr_t) < 8) { + pIsWow64Process = (BOOL (__stdcall *)(HANDLE, PBOOL)) + GetProcAddress(GetModuleHandleA("KERNEL32"), "IsWow64Process"); + if (pIsWow64Process != NULL) { + (*pIsWow64Process)(GetCurrentProcess(), &ret); + } + } else { + ret = TRUE; + } + return ret; } -const char* PrintWindowsVersion(enum WindowsVersion version) +// From smartmontools os_win32.cpp +void GetWindowsVersion(void) { - if ((version < 0) || (version >= WINDOWS_MAX)) - version = WINDOWS_UNDEFINED; - return WindowsVersionName[version]; + OSVERSIONINFOEXA vi, vi2; + const char* w = 0; + const char* w64 = "32 bit"; + char* vptr; + size_t vlen; + unsigned major, minor; + ULONGLONG major_equal, minor_equal; + BOOL ws; + + nWindowsVersion = WINDOWS_UNDEFINED; + safe_strcpy(WindowsVersionStr, sizeof(WindowsVersionStr), "Windows Undefined"); + + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); + if (!GetVersionExA((OSVERSIONINFOA *)&vi)) + return; + } + + if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) { + + if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) { + // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version + // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx + + major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); + for (major = vi.dwMajorVersion; major <= 9; major++) { + memset(&vi2, 0, sizeof(vi2)); + vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major; + if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) + continue; + if (vi.dwMajorVersion < major) { + vi.dwMajorVersion = major; vi.dwMinorVersion = 0; + } + + minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); + for (minor = vi.dwMinorVersion; minor <= 9; minor++) { + memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2); + vi2.dwMinorVersion = minor; + if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) + continue; + vi.dwMinorVersion = minor; + break; + } + + break; + } + } + + if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) { + ws = (vi.wProductType <= VER_NT_WORKSTATION); + nWindowsVersion = vi.dwMajorVersion << 4 | vi.dwMinorVersion; + switch (nWindowsVersion) { + case 0x50: w = "2000"; + break; + case 0x51: w = "XP"; + break; + case 0x52: w = (!GetSystemMetrics(89)?"2003":"2003_R2"); + break; + case 0x60: w = (ws?"Vista":"2008"); + break; + case 0x61: w = (ws?"7":"2008_R2"); + break; + case 0x62: w = (ws?"8":"2012"); + break; + case 0x63: w = (ws?"8.1":"2012_R2"); + break; + default: + nWindowsVersion = WINDOWS_UNSUPPORTED; + break; + } + } + } + + if (is_x64()) + w64 = "64-bit"; + + vptr = &WindowsVersionStr[sizeof("Windows ") - 1]; + vlen = sizeof(WindowsVersionStr) - sizeof("Windows ") - 1; + if (!w) + safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId==VER_PLATFORM_WIN32_NT?"NT":"??"), + (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64); + else if (vi.wServicePackMinor) + safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64); + else if (vi.wServicePackMajor) + safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64); + else + safe_sprintf(vptr, vlen, "%s %s", w, w64); } /*