]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - Ventoy2Disk/Ventoy2Disk/Utility.c
Add debug info fix
[Ventoy.git] / Ventoy2Disk / Ventoy2Disk / Utility.c
index 91403bd297457c3b1aa57f0669f0cbc801208260..f217bfed45b77d996fc37c16b0f81821112c895d 100644 (file)
@@ -1,7 +1,8 @@
 /******************************************************************************\r
  * Utility.c\r
  *\r
- * Copyright (c) 2020, longpanda <admin@ventoy.net>\r
+ * Copyright (c) 2021, longpanda <admin@ventoy.net>\r
+ * Copyright (c) 2011-2020, Pete Batard <pete@akeo.ie>\r
  *\r
  * This program is free software; you can redistribute it and/or\r
  * modify it under the terms of the GNU General Public License as\r
 #include <Windows.h>\r
 #include "Ventoy2Disk.h"\r
 \r
+void TraceOut(const char *Fmt, ...)\r
+{\r
+    va_list Arg;\r
+    int Len = 0;\r
+    FILE *File = NULL;\r
+    char szBuf[1024];\r
+\r
+    va_start(Arg, Fmt);\r
+    Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);\r
+    va_end(Arg);\r
+\r
+    fopen_s(&File, VENTOY_FILE_LOG, "a+");\r
+    if (File)\r
+    {\r
+        fwrite(szBuf, 1, Len, File);\r
+        fclose(File);\r
+    }\r
+}\r
+\r
 void Log(const char *Fmt, ...)\r
 {\r
     va_list Arg;\r
@@ -53,6 +73,17 @@ void Log(const char *Fmt, ...)
 \r
 }\r
 \r
+const char* GUID2String(void *guid, char *buf, int len)\r
+{\r
+    GUID* pGUID = (GUID*)guid;\r
+    sprintf_s(buf, len, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",\r
+        pGUID->Data1, pGUID->Data2, pGUID->Data3,\r
+        pGUID->Data4[0], pGUID->Data4[1],\r
+        pGUID->Data4[2], pGUID->Data4[3], pGUID->Data4[4], pGUID->Data4[5], pGUID->Data4[6], pGUID->Data4[7]\r
+    );\r
+    return buf;\r
+}\r
+\r
 BOOL IsPathExist(BOOL Dir, const char *Fmt, ...)\r
 {\r
     va_list Arg;\r
@@ -92,6 +123,22 @@ BOOL IsPathExist(BOOL Dir, const char *Fmt, ...)
     return TRUE;\r
 }\r
 \r
+int SaveBufToFile(const CHAR *FileName, const void *Buffer, int BufLen)\r
+{\r
+    FILE *File = NULL;\r
+    void *Data = NULL;\r
+\r
+    fopen_s(&File, FileName, "wb");\r
+    if (File == NULL)\r
+    {\r
+        Log("Failed to open file %s", FileName);\r
+        return 1;\r
+    }\r
+\r
+    fwrite(Buffer, 1, BufLen, File);\r
+    fclose(File);\r
+    return 0;\r
+}\r
 \r
 int ReadWholeFileToBuf(const CHAR *FileName, int ExtLen, void **Bufer, int *BufLen)\r
 {\r
@@ -195,6 +242,7 @@ BOOL IsWow64(void)
     typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);\r
     LPFN_ISWOW64PROCESS fnIsWow64Process;\r
     BOOL bIsWow64 = FALSE;\r
+       CHAR Wow64Dir[MAX_PATH];\r
 \r
     fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process");\r
     if (NULL != fnIsWow64Process)\r
@@ -202,76 +250,275 @@ BOOL IsWow64(void)
         fnIsWow64Process(GetCurrentProcess(), &bIsWow64);\r
     }\r
 \r
+       if (!bIsWow64)\r
+       {\r
+               if (GetSystemWow64DirectoryA(Wow64Dir, sizeof(Wow64Dir)))\r
+               {\r
+                       Log("GetSystemWow64DirectoryA=<%s>", Wow64Dir);\r
+                       bIsWow64 = TRUE;\r
+               }\r
+       }\r
+\r
     return bIsWow64;\r
 }\r
 \r
-void DumpWindowsVersion(void)\r
+/*\r
+* Some code and functions in the file are copied from rufus.\r
+* https://github.com/pbatard/rufus\r
+*/\r
+\r
+/* Windows versions */\r
+enum WindowsVersion {\r
+    WINDOWS_UNDEFINED = -1,\r
+    WINDOWS_UNSUPPORTED = 0,\r
+    WINDOWS_XP = 0x51,\r
+    WINDOWS_2003 = 0x52,       // Also XP_64\r
+    WINDOWS_VISTA = 0x60,      // Also Server 2008\r
+    WINDOWS_7 = 0x61,          // Also Server 2008_R2\r
+    WINDOWS_8 = 0x62,          // Also Server 2012\r
+    WINDOWS_8_1 = 0x63,                // Also Server 2012_R2\r
+    WINDOWS_10_PREVIEW1 = 0x64,\r
+    WINDOWS_10 = 0xA0,         // Also Server 2016, also Server 2019\r
+    WINDOWS_11 = 0xB0,         // Also Server 2022\r
+    WINDOWS_MAX\r
+};\r
+\r
+static const char* GetEdition(DWORD ProductType)\r
 {\r
-    int Bit; \r
-    BOOL WsVer;    \r
-    DWORD Major, Minor;\r
-    ULONGLONG MajorEqual, MinorEqual;\r
-    OSVERSIONINFOEXA Ver1, Ver2;\r
-    const CHAR *Ver = NULL; \r
-    CHAR WinVer[256] = { 0 };\r
-\r
-    memset(&Ver1, 0, sizeof(Ver1));\r
-    memset(&Ver2, 0, sizeof(Ver2));\r
-\r
-    Ver1.dwOSVersionInfoSize = sizeof(Ver1);\r
-    \r
+    // From: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getproductinfo\r
+    // These values can be found in the winnt.h header.\r
+    switch (ProductType) {\r
+               case 0x00000000: return "";     //  Undefined\r
+               case 0x00000001: return "Ultimate";\r
+               case 0x00000002: return "Home Basic";\r
+               case 0x00000003: return "Home Premium";\r
+               case 0x00000004: return "Enterprise";\r
+               case 0x00000005: return "Home Basic N";\r
+               case 0x00000006: return "Business";\r
+               case 0x00000007: return "Server Standard";\r
+               case 0x00000008: return "Server Datacenter";\r
+               case 0x00000009: return "Smallbusiness Server";\r
+               case 0x0000000A: return "Server Enterprise";\r
+               case 0x0000000B: return "Starter";\r
+               case 0x0000000C: return "Server Datacenter (Core)";\r
+               case 0x0000000D: return "Server Standard (Core)";\r
+               case 0x0000000E: return "Server Enterprise (Core)";\r
+               case 0x00000010: return "Business N";\r
+               case 0x00000011: return "Web Server";\r
+               case 0x00000012: return "HPC Edition";\r
+               case 0x00000013: return "Storage Server (Essentials)";\r
+               case 0x0000001A: return "Home Premium N";\r
+               case 0x0000001B: return "Enterprise N";\r
+               case 0x0000001C: return "Ultimate N";\r
+               case 0x00000022: return "Home Server";\r
+               case 0x00000024: return "Server Standard without Hyper-V";\r
+               case 0x00000025: return "Server Datacenter without Hyper-V";\r
+               case 0x00000026: return "Server Enterprise without Hyper-V";\r
+               case 0x00000027: return "Server Datacenter without Hyper-V (Core)";\r
+               case 0x00000028: return "Server Standard without Hyper-V (Core)";\r
+               case 0x00000029: return "Server Enterprise without Hyper-V (Core)";\r
+               case 0x0000002A: return "Hyper-V Server";\r
+               case 0x0000002F: return "Starter N";\r
+               case 0x00000030: return "Pro";\r
+               case 0x00000031: return "Pro N";\r
+               case 0x00000034: return "Server Solutions Premium";\r
+               case 0x00000035: return "Server Solutions Premium (Core)";\r
+               case 0x00000040: return "Server Hyper Core V";\r
+               case 0x00000042: return "Starter E";\r
+               case 0x00000043: return "Home Basic E";\r
+               case 0x00000044: return "Premium E";\r
+               case 0x00000045: return "Pro E";\r
+               case 0x00000046: return "Enterprise E";\r
+               case 0x00000047: return "Ultimate E";\r
+               case 0x00000048: return "Enterprise (Eval)";\r
+               case 0x0000004F: return "Server Standard (Eval)";\r
+               case 0x00000050: return "Server Datacenter (Eval)";\r
+               case 0x00000054: return "Enterprise N (Eval)";\r
+               case 0x00000057: return "Thin PC";\r
+               case 0x00000058: case 0x00000059: case 0x0000005A: case 0x0000005B: case 0x0000005C: return "Embedded";\r
+               case 0x00000062: return "Home N";\r
+               case 0x00000063: return "Home China";\r
+               case 0x00000064: return "Home Single Language";\r
+               case 0x00000065: return "Home";\r
+               case 0x00000067: return "Pro with Media Center";\r
+               case 0x00000069: case 0x0000006A: case 0x0000006B: case 0x0000006C: return "Embedded";\r
+               case 0x0000006F: return "Home Connected";\r
+               case 0x00000070: return "Pro Student";\r
+               case 0x00000071: return "Home Connected N";\r
+               case 0x00000072: return "Pro Student N";\r
+               case 0x00000073: return "Home Connected Single Language";\r
+               case 0x00000074: return "Home Connected China";\r
+               case 0x00000079: return "Education";\r
+               case 0x0000007A: return "Education N";\r
+               case 0x0000007D: return "Enterprise LTSB";\r
+               case 0x0000007E: return "Enterprise LTSB N";\r
+               case 0x0000007F: return "Pro S";\r
+               case 0x00000080: return "Pro S N";\r
+               case 0x00000081: return "Enterprise LTSB (Eval)";\r
+               case 0x00000082: return "Enterprise LTSB N (Eval)";\r
+               case 0x0000008A: return "Pro Single Language";\r
+               case 0x0000008B: return "Pro China";\r
+               case 0x0000008C: return "Enterprise Subscription";\r
+               case 0x0000008D: return "Enterprise Subscription N";\r
+               case 0x00000091: return "Server Datacenter SA (Core)";\r
+               case 0x00000092: return "Server Standard SA (Core)";\r
+               case 0x00000095: return "Utility VM";\r
+               case 0x000000A1: return "Pro for Workstations";\r
+               case 0x000000A2: return "Pro for Workstations N";\r
+               case 0x000000A4: return "Pro for Education";\r
+               case 0x000000A5: return "Pro for Education N";\r
+               case 0x000000AB: return "Enterprise G"; // I swear Microsoft are just making up editions...\r
+               case 0x000000AC: return "Enterprise G N";\r
+               case 0x000000B6: return "Home OS";\r
+               case 0x000000B7: return "Cloud E";\r
+               case 0x000000B8: return "Cloud E N";\r
+               case 0x000000BD: return "Lite";\r
+               case 0xABCDABCD: return "(Unlicensed)";\r
+               default: return "(Unknown Edition)";\r
+    }\r
+}\r
+\r
+#define is_x64 IsWow64\r
+#define static_strcpy safe_strcpy \r
+#define REGKEY_HKCU HKEY_CURRENT_USER\r
+#define REGKEY_HKLM HKEY_LOCAL_MACHINE\r
+static int  nWindowsVersion = WINDOWS_UNDEFINED;\r
+static int  nWindowsBuildNumber = -1;\r
+static char WindowsVersionStr[128] = "";\r
+\r
+/* Helpers for 32 bit registry operations */\r
+\r
+/*\r
+* Read a generic registry key value. If a short key_name is used, assume that\r
+* it belongs to the application and create the app subkey if required\r
+*/\r
+static __inline BOOL _GetRegistryKey(HKEY key_root, const char* key_name, DWORD reg_type,\r
+    LPBYTE dest, DWORD dest_size)\r
+{\r
+    const char software_prefix[] = "SOFTWARE\\";\r
+    char long_key_name[MAX_PATH] = { 0 };\r
+    BOOL r = FALSE;\r
+    size_t i;\r
+    LONG s;\r
+    HKEY hSoftware = NULL, hApp = NULL;\r
+    DWORD dwType = -1, dwSize = dest_size;\r
+\r
+    memset(dest, 0, dest_size);\r
+\r
+    if (key_name == NULL)\r
+        return FALSE;\r
+\r
+    for (i = strlen(key_name); i>0; i--) {\r
+        if (key_name[i] == '\\')\r
+            break;\r
+    }\r
+\r
+    if (i > 0) {\r
+        // Prefix with "SOFTWARE" if needed\r
+        if (_strnicmp(key_name, software_prefix, sizeof(software_prefix)-1) != 0) {\r
+            if (i + sizeof(software_prefix) >= sizeof(long_key_name))\r
+                return FALSE;\r
+            strcpy_s(long_key_name, sizeof(long_key_name), software_prefix);\r
+            strcat_s(long_key_name, sizeof(long_key_name), key_name);\r
+            long_key_name[sizeof(software_prefix)+i - 1] = 0;\r
+        }\r
+        else {\r
+            if (i >= sizeof(long_key_name))\r
+                return FALSE;\r
+            static_strcpy(long_key_name, key_name);\r
+            long_key_name[i] = 0;\r
+        }\r
+        i++;\r
+        if (RegOpenKeyExA(key_root, long_key_name, 0, KEY_READ, &hApp) != ERROR_SUCCESS) {\r
+            hApp = NULL;\r
+            goto out;\r
+        }\r
+    }\r
+    else {\r
+        if (RegOpenKeyExA(key_root, "SOFTWARE", 0, KEY_READ | KEY_CREATE_SUB_KEY, &hSoftware) != ERROR_SUCCESS) {\r
+            hSoftware = NULL;\r
+            goto out;\r
+        }        \r
+    }\r
+\r
+    s = RegQueryValueExA(hApp, &key_name[i], NULL, &dwType, (LPBYTE)dest, &dwSize);\r
+    // No key means default value of 0 or empty string\r
+    if ((s == ERROR_FILE_NOT_FOUND) || ((s == ERROR_SUCCESS) && (dwType == reg_type) && (dwSize > 0))) {\r
+        r = TRUE;\r
+    }\r
+out:\r
+    if (hSoftware != NULL)\r
+        RegCloseKey(hSoftware);\r
+    if (hApp != NULL)\r
+        RegCloseKey(hApp);\r
+    return r;\r
+}\r
+\r
+#define GetRegistryKey32(root, key, pval) _GetRegistryKey(root, key, REG_DWORD, (LPBYTE)pval, sizeof(DWORD))\r
+static __inline INT32 ReadRegistryKey32(HKEY root, const char* key) {\r
+    DWORD val;\r
+    GetRegistryKey32(root, key, &val);\r
+    return (INT32)val;\r
+}\r
+\r
+/*\r
+* Modified from smartmontools' os_win32.cpp\r
+*/\r
+void GetWindowsVersion(void)\r
+{   \r
+    OSVERSIONINFOEXA vi, vi2;\r
+    DWORD dwProductType;\r
+    const char* w = 0;\r
+    const char* w64 = "32 bit";\r
+    char *vptr;\r
+    size_t vlen;\r
+    unsigned major, minor;\r
+    ULONGLONG major_equal, minor_equal;\r
+    BOOL ws;\r
+\r
+    nWindowsVersion = WINDOWS_UNDEFINED;\r
+    static_strcpy(WindowsVersionStr, "Windows Undefined");\r
+\r
     // suppress the C4996 warning for GetVersionExA\r
     #pragma warning(push)\r
     #pragma warning(disable:4996)\r
-    if (!GetVersionExA((OSVERSIONINFOA *)&Ver1))\r
-    {\r
-        memset(&Ver1, 0, sizeof(Ver1));\r
-        Ver1.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);\r
-        if (!GetVersionExA((OSVERSIONINFOA *)&Ver1))\r
-        {\r
+\r
+    memset(&vi, 0, sizeof(vi));\r
+    vi.dwOSVersionInfoSize = sizeof(vi);\r
+    if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {\r
+        memset(&vi, 0, sizeof(vi));\r
+        vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);\r
+        if (!GetVersionExA((OSVERSIONINFOA *)&vi))\r
             return;\r
-        }\r
     }\r
+\r
     #pragma warning(pop)\r
 \r
-    if (Ver1.dwPlatformId == VER_PLATFORM_WIN32_NT)\r
-    {\r
-        if (Ver1.dwMajorVersion > 6 || (Ver1.dwMajorVersion == 6 && Ver1.dwMinorVersion >= 2))\r
-        {\r
-            // GetVersionEx() has problem on some Windows version \r
+    if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {\r
 \r
-            MajorEqual = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);\r
-            for (Major = Ver1.dwMajorVersion; Major <= 9; Major++) \r
-            {\r
-                memset(&Ver2, 0, sizeof(Ver2));\r
-                Ver2.dwOSVersionInfoSize = sizeof(Ver2);\r
-                Ver2.dwMajorVersion = Major;\r
+        if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) {\r
+            // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version\r
+            // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx\r
+            // And starting with Windows 10 Preview 2, Windows enforces the use of the application/supportedOS\r
+            // manifest in order for VerSetConditionMask() to report the ACTUAL OS major and minor...\r
 \r
-                if (!VerifyVersionInfoA(&Ver2, VER_MAJORVERSION, MajorEqual))\r
-                {\r
+            major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);\r
+            for (major = vi.dwMajorVersion; major <= 9; major++) {\r
+                memset(&vi2, 0, sizeof(vi2));\r
+                vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major;\r
+                if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))\r
                     continue;\r
-                }\r
-                    \r
-                if (Ver1.dwMajorVersion < Major) \r
-                {\r
-                    Ver1.dwMajorVersion = Major;\r
-                    Ver1.dwMinorVersion = 0;\r
+                if (vi.dwMajorVersion < major) {\r
+                    vi.dwMajorVersion = major; vi.dwMinorVersion = 0;\r
                 }\r
 \r
-                MinorEqual = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);\r
-                for (Minor = Ver1.dwMinorVersion; Minor <= 9; Minor++) \r
-                {\r
-                    memset(&Ver2, 0, sizeof(Ver2)); \r
-                    \r
-                    Ver2.dwOSVersionInfoSize = sizeof(Ver2);\r
-                    Ver2.dwMinorVersion = Minor;\r
-\r
-                    if (!VerifyVersionInfoA(&Ver2, VER_MINORVERSION, MinorEqual))\r
-                    {\r
+                minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);\r
+                for (minor = vi.dwMinorVersion; minor <= 9; minor++) {\r
+                    memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2);\r
+                    vi2.dwMinorVersion = minor;\r
+                    if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))\r
                         continue;\r
-                    }\r
-                        \r
-                    Ver1.dwMinorVersion = Minor;\r
+                    vi.dwMinorVersion = minor;\r
                     break;\r
                 }\r
 \r
@@ -279,87 +526,85 @@ void DumpWindowsVersion(void)
             }\r
         }\r
 \r
-        if (Ver1.dwMajorVersion <= 0xF && Ver1.dwMinorVersion <= 0xF)\r
-        {\r
-            WsVer = (Ver1.wProductType <= VER_NT_WORKSTATION);\r
-            switch ((Ver1.dwMajorVersion << 4) | Ver2.dwMinorVersion)\r
-            {\r
-                case 0x51:\r
-                {\r
-                    Ver = "XP";\r
-                    break;\r
-                }\r
-                case 0x52:\r
-                {\r
-                    Ver = GetSystemMetrics(89) ? "Server 2003 R2" : "Server 2003";\r
-                    break;\r
-                }\r
-                case 0x60:\r
-                {\r
-                    Ver = WsVer ? "Vista" : "Server 2008";\r
-                    break;\r
-                }\r
-                case 0x61:\r
-                {\r
-                    Ver = WsVer ? "7" : "Server 2008 R2";\r
-                    break;\r
-                }\r
-                case 0x62:\r
-                {\r
-                    Ver = WsVer ? "8" : "Server 2012";\r
-                    break;\r
-                }\r
-                case 0x63:\r
-                {\r
-                    Ver = WsVer ? "8.1" : "Server 2012 R2";\r
-                    break;\r
-                }\r
-                case 0x64:\r
-                {\r
-                    Ver = WsVer ? "10 (Preview 1)" : "Server 10 (Preview 1)";\r
-                    break;\r
-                }\r
-                case 0xA0:\r
-                {\r
-                    Ver = WsVer ? "10" : ((Ver1.dwBuildNumber > 15000) ? "Server 2019" : "Server 2016");\r
-                    break;\r
-                }\r
-                default:\r
-                {\r
-                    Ver = "10 or later";\r
+        if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {\r
+            ws = (vi.wProductType <= VER_NT_WORKSTATION);\r
+            nWindowsVersion = vi.dwMajorVersion << 4 | vi.dwMinorVersion;\r
+            switch (nWindowsVersion) {\r
+            case WINDOWS_XP: w = "XP";\r
+                break;\r
+            case WINDOWS_2003: w = (ws ? "XP_64" : (!GetSystemMetrics(89) ? "Server 2003" : "Server 2003_R2"));\r
+                break;\r
+            case WINDOWS_VISTA: w = (ws ? "Vista" : "Server 2008");\r
+                break;\r
+            case WINDOWS_7: w = (ws ? "7" : "Server 2008_R2");\r
+                break;\r
+            case WINDOWS_8: w = (ws ? "8" : "Server 2012");\r
+                break;\r
+            case WINDOWS_8_1: w = (ws ? "8.1" : "Server 2012_R2");\r
+                break;\r
+            case WINDOWS_10_PREVIEW1: w = (ws ? "10 (Preview 1)" : "Server 10 (Preview 1)");\r
+                break;\r
+                // Starting with Windows 10 Preview 2, the major is the same as the public-facing version\r
+            case WINDOWS_10:\r
+                if (vi.dwBuildNumber < 20000) {\r
+                    w = (ws ? "10" : ((vi.dwBuildNumber < 17763) ? "Server 2016" : "Server 2019"));\r
                     break;\r
                 }\r
+                nWindowsVersion = WINDOWS_11;\r
+                // Fall through\r
+            case WINDOWS_11: w = (ws ? "11" : "Server 2022");\r
+                break;\r
+            default:\r
+                if (nWindowsVersion < WINDOWS_XP)\r
+                    nWindowsVersion = WINDOWS_UNSUPPORTED;\r
+                else\r
+                    w = "12 or later";\r
+                break;\r
             }\r
         }\r
     }\r
 \r
-    Bit = IsWow64() ? 64 : 32;\r
+    if (is_x64())\r
+        w64 = "64-bit";\r
 \r
-    if (Ver1.wServicePackMinor)\r
-    {\r
-        safe_sprintf(WinVer, "Windows %s SP%u.%u %d-bit", Ver, Ver1.wServicePackMajor, Ver1.wServicePackMinor, Bit);\r
-    }\r
-    else if (Ver1.wServicePackMajor)\r
-    {\r
-        safe_sprintf(WinVer, "Windows %s SP%u %d-bit", Ver, Ver1.wServicePackMajor, Bit);\r
-    }\r
-    else\r
-    {\r
-        safe_sprintf(WinVer, "Windows %s %d-bit", Ver, Bit);\r
-    }\r
+    GetProductInfo(vi.dwMajorVersion, vi.dwMinorVersion, vi.wServicePackMajor, vi.wServicePackMinor, &dwProductType);\r
+    vptr = WindowsVersionStr;\r
+    vlen = sizeof(WindowsVersionStr) - 1;\r
 \r
-    if (((Ver1.dwMajorVersion << 4) | Ver2.dwMinorVersion) >= 0x62)\r
-    {\r
-        Log("Windows Version : %s (Build %u)", WinVer, Ver1.dwBuildNumber);\r
-    }\r
+    if (!w)\r
+        sprintf_s(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"),\r
+        (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64);\r
+    else if (vi.wServicePackMinor)\r
+        sprintf_s(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64);\r
+    else if (vi.wServicePackMajor)\r
+        sprintf_s(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64);\r
     else\r
-    {\r
-        Log("Windows Version : %s", WinVer);\r
+        sprintf_s(vptr, vlen, "%s%s%s, %s",\r
+        w, (dwProductType != PRODUCT_UNDEFINED) ? " " : "", GetEdition(dwProductType), w64);\r
+\r
+    // Add the build number (including UBR if available) for Windows 8.0 and later\r
+    nWindowsBuildNumber = vi.dwBuildNumber;\r
+    if (nWindowsVersion >= 0x62) {\r
+        int nUbr = ReadRegistryKey32(REGKEY_HKLM, "Software\\Microsoft\\Windows NT\\CurrentVersion\\UBR");\r
+        vptr = WindowsVersionStr + strlen(WindowsVersionStr);\r
+        vlen = sizeof(WindowsVersionStr) - strlen(WindowsVersionStr) - 1;\r
+        if (nUbr > 0)\r
+            sprintf_s(vptr, vlen, " (Build %d.%d)", nWindowsBuildNumber, nUbr);\r
+        else\r
+            sprintf_s(vptr, vlen, " (Build %d)", nWindowsBuildNumber);\r
     }\r
+}\r
 \r
+\r
+\r
+void DumpWindowsVersion(void)\r
+{\r
+    GetWindowsVersion();\r
+    Log("Windows Version: <<Windows %s>>", WindowsVersionStr);\r
     return;\r
 }\r
 \r
+\r
 BOOL IsVentoyLogicalDrive(CHAR DriveLetter)\r
 {\r
     int i;\r
@@ -443,6 +688,7 @@ int VentoyFillMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR, int PartStyle)
     Log("Disk signature: 0x%08x", DiskSignature);\r
 \r
     *((UINT32 *)(pMBR->BootCode + 0x1B8)) = DiskSignature;\r
+       memcpy(pMBR->BootCode + 0x180, &Guid, 16);\r
 \r
     if (DiskSizeBytes / 512 > 0xFFFFFFFF)\r
     {\r
@@ -468,6 +714,17 @@ int VentoyFillMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR, int PartStyle)
         ReservedSector += 33; // backup GPT part table\r
     }\r
 \r
+    // check aligned with 4KB\r
+    if (IsPartNeed4KBAlign())\r
+    {\r
+        UINT64 sectors = DiskSizeBytes / 512;\r
+        if (sectors % 8)\r
+        {\r
+            Log("Disk need to align with 4KB %u", (UINT32)(sectors % 8));\r
+            ReservedSector += (UINT32)(sectors % 8);\r
+        }\r
+    }\r
+\r
        Log("ReservedSector: %u", ReservedSector);\r
 \r
     //Part1\r
@@ -508,6 +765,7 @@ static int VentoyFillProtectMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR)
     Log("Disk signature: 0x%08x", DiskSignature);\r
 \r
     *((UINT32 *)(pMBR->BootCode + 0x1B8)) = DiskSignature;\r
+       memcpy(pMBR->BootCode + 0x180, &Guid, 16);\r
 \r
     DiskSectorCount = DiskSizeBytes / 512 - 1;\r
     if (DiskSectorCount > 0xFFFFFFFF)\r
@@ -581,6 +839,7 @@ int VentoyFillWholeGpt(UINT64 DiskSizeBytes, VTOY_GPT_INFO *pInfo)
 int VentoyFillGpt(UINT64 DiskSizeBytes, VTOY_GPT_INFO *pInfo)\r
 {\r
     INT64 ReservedValue = 0;\r
+    UINT64 ModSectorCount = 0;\r
     UINT64 ReservedSector = 33;\r
     UINT64 Part1SectorCount = 0;\r
     UINT64 DiskSectorCount = DiskSizeBytes / 512;\r
@@ -600,6 +859,26 @@ int VentoyFillGpt(UINT64 DiskSizeBytes, VTOY_GPT_INFO *pInfo)
 \r
     Part1SectorCount = DiskSectorCount - ReservedSector - (VENTOY_EFI_PART_SIZE / 512) - 2048;\r
 \r
+    ModSectorCount = (Part1SectorCount % 8);\r
+    if (ModSectorCount)\r
+    {\r
+        Log("Part1SectorCount:%llu is not aligned by 4KB (%llu)", (ULONGLONG)Part1SectorCount, (ULONGLONG)ModSectorCount);\r
+    }\r
+\r
+    // check aligned with 4KB\r
+    if (IsPartNeed4KBAlign())\r
+    {\r
+        if (ModSectorCount)\r
+        {\r
+            Log("Disk need to align with 4KB %u", (UINT32)ModSectorCount);\r
+            Part1SectorCount -= ModSectorCount;\r
+        }\r
+        else\r
+        {\r
+            Log("no need to align with 4KB");\r
+        }\r
+    }\r
+\r
     memcpy(Head->Signature, "EFI PART", 8);\r
     Head->Version[2] = 0x01;\r
     Head->Length = 92;\r
@@ -627,7 +906,7 @@ int VentoyFillGpt(UINT64 DiskSizeBytes, VTOY_GPT_INFO *pInfo)
     CoCreateGuid(&(Table[1].PartGuid));\r
     Table[1].StartLBA = Table[0].LastLBA + 1;\r
     Table[1].LastLBA = Table[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1;\r
-    Table[1].Attr = 0x8000000000000001ULL;\r
+    Table[1].Attr = 0xC000000000000001ULL;\r
     memcpy(Table[1].Name, L"VTOYEFI", 7 * 2);\r
 \r
 #if 0\r
@@ -746,6 +1025,11 @@ int GetHumanReadableGBSize(UINT64 SizeBytes)
     double Delta;\r
     double GB = SizeBytes * 1.0 / 1000 / 1000 / 1000;\r
 \r
+    if ((SizeBytes % 1073741824) == 0)\r
+    {\r
+        return (int)(SizeBytes / 1073741824);\r
+    }\r
+\r
     for (i = 0; i < 12; i++)\r
     {\r
         if (Pow2 > GB)\r