]> glassweightruler.freedombox.rocks Git - Ventoy.git/commitdiff
1.0.87 release v1.0.87
authorlongpanda <admin@ventoy.net>
Sat, 7 Jan 2023 07:57:53 +0000 (15:57 +0800)
committerlongpanda <admin@ventoy.net>
Sat, 7 Jan 2023 07:57:53 +0000 (15:57 +0800)
.github/ISSUE_TEMPLATE/issue_template.yml
INSTALL/grub/grub.cfg
vtoyjump/vtoyjump/setupmon.c [new file with mode: 0644]

index acdc706762c739de6c4c7746dd90a5dc2843e9a2..d628916d288918f9ca6b8e0e51fad6608bc3781a 100644 (file)
@@ -21,7 +21,7 @@ body:
     attributes:
       label: Ventoy Version
       description: What version of ventoy are you running?
-      placeholder: 1.0.84
+      placeholder: 1.0.87
     validations:
       required: true
   - type: dropdown
index 0534cabef620e162b5aee7715eb50270494017f8..f055d88847659ee75c8204cae04904f6698b10dd 100644 (file)
@@ -2386,7 +2386,7 @@ function mimg_common_menuentry {
 #############################################################
 #############################################################
 
-set VENTOY_VERSION="1.0.86"
+set VENTOY_VERSION="1.0.87"
 
 #ACPI not compatible with Window7/8, so disable by default
 set VTOY_PARAM_NO_ACPI=1
@@ -2545,9 +2545,18 @@ elif [ "$vtoy_display_mode" = "serial_console" ]; then
     terminal_input   serial console
     terminal_output  serial console    
 else
-    if [ "$vtoy_res_fit" = "1" ]; then
+    if [ "$vtoy_gfxmode" = "max" ]; then
+        set gfxmode=1024x768
         terminal_output  gfxterm
-    fi
+
+        vt_enum_video_mode
+        vt_get_video_mode 0 vtCurMode
+        terminal_output console
+        set gfxmode=$vtCurMode
+        terminal_output gfxterm
+    elif [ "$vtoy_res_fit" = "1" ]; then
+        terminal_output  gfxterm
+    fi    
 
     if [ -n "$vtoy_theme" ]; then
         vt_set_theme
diff --git a/vtoyjump/vtoyjump/setupmon.c b/vtoyjump/vtoyjump/setupmon.c
new file mode 100644 (file)
index 0000000..f444903
--- /dev/null
@@ -0,0 +1,513 @@
+/******************************************************************************\r
+* setupmon.c\r
+*\r
+* Copyright (c) 2022, longpanda <admin@ventoy.net>\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
+* published by the Free Software Foundation; either version 3 of the\r
+* License, or (at your option) any later version.\r
+*\r
+* This program is distributed in the hope that it will be useful, but\r
+* WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+* General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <Windows.h>\r
+#include <virtdisk.h>\r
+#include <winioctl.h>\r
+#include <VersionHelpers.h>\r
+#include "vtoyjump.h"\r
+\r
+\r
+#define PROMPT_MAX  1024\r
+typedef struct VTOY_MUI_DATA\r
+{\r
+    WCHAR Prompt[PROMPT_MAX];\r
+    struct VTOY_MUI_DATA* pNext;\r
+}VTOY_MUI_DATA;\r
+\r
+static VTOY_MUI_DATA* g_MuiDataHead = NULL;\r
+static FILETIME g_SetupMonStartTime;\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+    WORD      dlgVer;\r
+    WORD      signature;\r
+    DWORD     helpID;\r
+    DWORD     exStyle;\r
+    DWORD     style;\r
+    WORD      cDlgItems;\r
+    short     x;\r
+    short     y;\r
+    short     cx;\r
+    short     cy;\r
+    //sz_Or_Ord menu;\r
+    //sz_Or_Ord windowClass;\r
+    //WCHAR     title[titleLen];\r
+    //WORD      pointsize;\r
+    //WORD      weight;\r
+    //BYTE      italic;\r
+    //BYTE      charset;\r
+    //WCHAR     typeface[stringLen];\r
+} DLGTEMPLATEEX;\r
+\r
+typedef struct {\r
+    DWORD     helpID;\r
+    DWORD     exStyle;\r
+    DWORD     style;\r
+    short     x;\r
+    short     y;\r
+    short     cx;\r
+    short     cy;\r
+    DWORD     id;\r
+    //  sz_Or_Ord windowClass;\r
+    //  sz_Or_Ord title;\r
+    //  WORD      extraCount;\r
+} DLGITEMTEMPLATEEX;\r
+\r
+\r
+#pragma pack()\r
+\r
+#define wchar_to_utf8_no_alloc(wsrc, dest, dest_size) \\r
+       WideCharToMultiByte(CP_UTF8, 0, wsrc, -1, dest, dest_size, NULL, NULL)\r
+#define utf8_to_wchar_no_alloc(src, wdest, wdest_size) \\r
+       MultiByteToWideChar(CP_UTF8, 0, src, -1, wdest, wdest_size)\r
+\r
+#define VTOY_DLG_SKIP_SZ_ORD(pWord) \\r
+{\\r
+    if (*pWord == 0x0000)\\r
+    {\\r
+        pWordData += 1;\\r
+    }\\r
+    else if (*pWordData == 0xFFFF)\\r
+    {\\r
+        pWordData += 2;\\r
+    }\\r
+    else\\r
+    {\\r
+        while (*pWordData++)\\r
+        {\\r
+            ;\\r
+        }\\r
+    }\\r
+}\r
+\r
+#define VTOY_DLG_SKIP_SZ(pWord) \\r
+{\\r
+    while (*pWord)\\r
+    {\\r
+        pWord++;\\r
+    }\\r
+    pWord++;\\r
+}\r
+\r
+\r
+static BOOL LoadSetupRebootDialogPrompt(HMODULE hMui, DWORD ID, WCHAR* Prompt, DWORD Len)\r
+{\r
+    DWORD i = 0;\r
+    UINT64 Addr = 0;\r
+    WORD* pWordData = NULL;\r
+    HRSRC hDlg = NULL;\r
+    HGLOBAL hTemplate = NULL;\r
+    DLGTEMPLATEEX* pDlgTempEx = NULL;\r
+    DLGITEMTEMPLATEEX* pDlgItemTempEx = NULL;\r
+\r
+    hDlg = FindResource(hMui, MAKEINTRESOURCE(ID), RT_DIALOG);\r
+    if (!hDlg)\r
+    {\r
+        return FALSE;\r
+    }\r
+\r
+    hTemplate = LoadResource(hMui, hDlg);\r
+    if (!hTemplate)\r
+    {\r
+        return FALSE;\r
+    }\r
+\r
+    pDlgTempEx = (DLGTEMPLATEEX*)LockResource(hTemplate);\r
+    if (!pDlgTempEx)\r
+    {\r
+        return FALSE;\r
+    }\r
+\r
+    if (pDlgTempEx->signature != 0xFFFF)\r
+    {\r
+        return FALSE;\r
+    }\r
+\r
+    pWordData = (WORD*)(pDlgTempEx + 1);\r
+\r
+    //skip menu\r
+    VTOY_DLG_SKIP_SZ_ORD(pWordData);\r
+\r
+    //skip windowClass\r
+    VTOY_DLG_SKIP_SZ_ORD(pWordData);\r
+\r
+    //skip title\r
+    VTOY_DLG_SKIP_SZ(pWordData);\r
+\r
+    //skip pointsize/weight/italic + charset\r
+    pWordData += 3;\r
+\r
+    //skip typeface\r
+    VTOY_DLG_SKIP_SZ(pWordData);\r
+\r
+    //align to DWORD\r
+    Addr = (UINT64)pWordData;\r
+    if ((Addr % 4) > 0)\r
+    {\r
+        Addr += 4 - (Addr % 4);\r
+        pWordData = (WORD*)Addr;\r
+    }\r
+\r
+    //First Dlg Item \r
+    pDlgItemTempEx = (DLGITEMTEMPLATEEX*)pWordData;\r
+\r
+    if (pDlgItemTempEx->id != 1023)\r
+    {\r
+        return FALSE;\r
+    }\r
+\r
+    pWordData = (WORD*)(pDlgItemTempEx + 1);\r
+\r
+    //skip windowClass\r
+    VTOY_DLG_SKIP_SZ_ORD(pWordData);\r
+\r
+    for (i = 0; i < Len; i++)\r
+    {\r
+        Prompt[i] = pWordData[i];\r
+        if (Prompt[i] == 0)\r
+        {\r
+            break;\r
+        }\r
+    }\r
+\r
+    return TRUE;\r
+}\r
+\r
+static int LoadPromptString(const char* szDir)\r
+{\r
+    BOOL bRet;\r
+    HMODULE hMui;\r
+    CHAR MuiFile[MAX_PATH];\r
+    WCHAR Prompt[PROMPT_MAX];\r
+    VTOY_MUI_DATA* Node = NULL;\r
+\r
+    sprintf_s(MuiFile, sizeof(MuiFile), "X:\\Sources\\%s\\w32uires.dll.mui", szDir);\r
+\r
+    hMui = LoadLibraryA(MuiFile);\r
+    if (!hMui)\r
+    {\r
+        Log("Failed to loadlibrary <%s> %u", MuiFile, LASTERR);\r
+        return 1;\r
+    }\r
+\r
+    bRet = LoadSetupRebootDialogPrompt(hMui, 103, Prompt, PROMPT_MAX);\r
+    if (bRet)\r
+    {\r
+        Node = malloc(sizeof(VTOY_MUI_DATA));\r
+        if (Node)\r
+        {\r
+            memset(Node, 0, sizeof(VTOY_MUI_DATA));\r
+            memcpy(Node->Prompt, Prompt, sizeof(Prompt));\r
+            if (g_MuiDataHead == NULL)\r
+            {\r
+                g_MuiDataHead = Node;\r
+            }\r
+            else\r
+            {\r
+                Node->pNext = g_MuiDataHead;\r
+                g_MuiDataHead = Node;\r
+            }\r
+\r
+            Log("Successfully add prompt string for <%s>", szDir);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        Log("Failed to load prompt string from %s", szDir);\r
+    }\r
+\r
+    FreeLibrary(hMui);\r
+    return 0;\r
+}\r
+\r
+static int FindAllPromptStrings(void)\r
+{\r
+    HANDLE hFind;\r
+    WIN32_FIND_DATAA FindData;\r
+\r
+    hFind = FindFirstFileA("X:\\Sources\\*", &FindData);\r
+    if (hFind == INVALID_HANDLE_VALUE)\r
+    {\r
+        Log("FindFirstFileA failed %u", LASTERR);\r
+        return 0;\r
+    }\r
+\r
+    do\r
+    {\r
+        if ((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (strlen(FindData.cFileName) == 5))\r
+        {\r
+            if (IsFileExist("X:\\Sources\\%s\\w32uires.dll.mui", FindData.cFileName))\r
+            {\r
+                LoadPromptString(FindData.cFileName);\r
+            }\r
+        }        \r
+    } while (FindNextFileA(hFind, &FindData));\r
+\r
+    return 0;\r
+}\r
+\r
+static BOOL CALLBACK SetupPromptCallback(HWND hWnd, LPARAM lParam)\r
+{\r
+    VTOY_MUI_DATA* Node = NULL;\r
+    WCHAR Prompt[PROMPT_MAX] = { 0 };\r
+    BOOL* found = (BOOL*)lParam;\r
+\r
+    if (GetWindowTextW(hWnd, Prompt, PROMPT_MAX - 1) > 0)\r
+    {\r
+        for (Node = g_MuiDataHead; Node; Node = Node->pNext)\r
+        {\r
+            if (wcscmp(Node->Prompt, Prompt) == 0)\r
+            {\r
+                *found = TRUE;\r
+                break;\r
+            }\r
+        }\r
+    }\r
+    \r
+    return TRUE;\r
+}\r
+\r
+static BOOL CALLBACK EnumWindowsProcFunc(HWND hWnd, LPARAM lParam)\r
+{\r
+    EnumChildWindows(hWnd, SetupPromptCallback, lParam);\r
+    return TRUE;\r
+}\r
+\r
+\r
+static CHAR FindWindowsInstallDstDrive(void)\r
+{\r
+    CHAR ret = 0;\r
+    CHAR Drv = 'A';\r
+    DWORD Drives;\r
+    CHAR ChkFilePath[MAX_PATH];\r
+    HANDLE hFile;\r
+    UINT64 Time1, Time2, Time3;\r
+    FILETIME fTime;\r
+    FILETIME sysftime;\r
+    SYSTEMTIME cur_systime;\r
+\r
+    GetSystemTime(&cur_systime);\r
+    SystemTimeToFileTime(&cur_systime, &sysftime);\r
+\r
+    memcpy(&Time1, &g_SetupMonStartTime, 8);\r
+    memcpy(&Time2, &sysftime, 8);\r
+\r
+    Drives = GetLogicalDrives();\r
+    Log("Find Windows: Logical Drives: 0x%x", Drives);\r
+\r
+    while ((Drives > 0) && (ret == 0))\r
+    {\r
+        if ((Drives & 1) && Drv != 'X')\r
+        {\r
+            sprintf_s(ChkFilePath, sizeof(ChkFilePath), "%C:\\$WINDOWS.~BT\\Sources\\Panther\\setupact.log", Drv);\r
+            hFile = CreateFileA(ChkFilePath, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);\r
+            if (hFile != INVALID_HANDLE_VALUE)\r
+            {\r
+                Log("%s Exist", ChkFilePath);\r
+\r
+                if (GetFileTime(hFile, NULL, NULL, &fTime))\r
+                {\r
+                    memcpy(&Time3, &fTime, 8);\r
+\r
+                    Log("### %s %llu %llu %llu", ChkFilePath, Time1, Time2, Time3);\r
+\r
+                    if (Time3 > Time1 && Time3 < Time2)\r
+                    {\r
+                        Log("Detect Windows11 install drive:<%C>", Drv);\r
+                        ret = Drv;\r
+                    }\r
+                }\r
+                CloseHandle(hFile);\r
+            }\r
+            else\r
+            {\r
+                Log("%s NOT Exist %u", ChkFilePath, LASTERR);\r
+            }\r
+        }\r
+\r
+        Drives >>= 1;\r
+        Drv++;\r
+    }\r
+\r
+    return ret;\r
+}\r
+\r
+static int AddBypassNROReg(const CHAR* OfflineRegPath)\r
+{\r
+    int ret = 1;\r
+    BOOL Unload = FALSE;\r
+    LSTATUS Status;\r
+    HKEY hKey = NULL;\r
+    HKEY hSubKey = NULL;    \r
+    DWORD dwValue = 1;\r
+    DWORD dwSize;\r
+    HANDLE htoken;\r
+    DWORD s = 0;\r
+    TOKEN_PRIVILEGES* p = NULL;\r
+\r
+    Log("AddBypassNROReg<%s>", OfflineRegPath);\r
+\r
+    if (!IsFileExist(OfflineRegPath))\r
+    {\r
+        return ret;\r
+    }\r
+    \r
+    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &htoken))\r
+    {\r
+        Log("Open process token failed! %u", LASTERR);\r
+        return ret;\r
+    }\r
+\r
+    s = sizeof(TOKEN_PRIVILEGES) + 2 * sizeof(LUID_AND_ATTRIBUTES);\r
+    p = (PTOKEN_PRIVILEGES)malloc(s);\r
+    if (!p)\r
+    {\r
+        Log("Failed to alloc privileges memory");\r
+        return ret;\r
+    }\r
+\r
+    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &(p->Privileges[0].Luid)) ||\r
+        !LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &(p->Privileges[1].Luid)) ||\r
+        !LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &(p->Privileges[2].Luid))) \r
+    {\r
+        Log("LookupPrivilegeValue failed!");\r
+        goto End;\r
+    }\r
+\r
+    p->PrivilegeCount = 3;    \r
+    p->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
+    p->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;\r
+    p->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED;\r
+\r
+    if (!AdjustTokenPrivileges(htoken, FALSE, p, s, NULL, NULL) || GetLastError() != ERROR_SUCCESS) \r
+    {\r
+        Log("AdjustTokenPrivileges failed!");\r
+        goto End;\r
+    }\r
+\r
+    Log("AdjustTokenPrivileges success");\r
+\r
+    Status = RegLoadKeyA(HKEY_LOCAL_MACHINE, "VTOYNEWSW", OfflineRegPath);\r
+    if (Status != ERROR_SUCCESS)\r
+    {\r
+        Log("RegLoadKey Failed 0x%x", Status);\r
+        goto End;\r
+    }\r
+    Unload = TRUE;\r
+\r
+    Status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "VTOYNEWSW\\Microsoft\\Windows\\CurrentVersion", 0, NULL, REG_OPTION_BACKUP_RESTORE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize);\r
+    if (ERROR_SUCCESS != Status)\r
+    {\r
+        Log("Failed to create reg key VTOYNEWSW\\Microsoft\\Windows\\CurrentVersion %u %u", LASTERR, Status);\r
+        goto End;\r
+    }\r
+\r
+    Status = RegCreateKeyExA(hKey, "OOBE", 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_CREATE_SUB_KEY, NULL, &hSubKey, &dwSize);\r
+    if (ERROR_SUCCESS != Status)\r
+    {\r
+        Log("Failed to create OOBE reg  %u %u", LASTERR, Status);\r
+        goto End;\r
+    }\r
+\r
+    Status = RegSetValueExA(hSubKey, "BypassNRO", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));\r
+    Log("Create BypassNRO registry %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status);\r
+\r
+    Status = RegFlushKey(hSubKey);\r
+    Status += RegCloseKey(hSubKey);\r
+    Log("Flush and close subkey %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status);\r
+\r
+    Status = RegFlushKey(hKey);\r
+    Status += RegCloseKey(hKey);\r
+    Log("Flush and close key %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status);\r
+\r
+    ret = 0;\r
+    \r
+End:\r
+    if (Unload)\r
+    {\r
+        Status = RegUnLoadKeyA(HKEY_LOCAL_MACHINE, "VTOYNEWSW");\r
+        Log("RegUnLoadKey %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status);\r
+    }\r
+    \r
+    if (p)\r
+    {\r
+        free(p);\r
+    }\r
+\r
+    return ret;\r
+}\r
+\r
+static DWORD WINAPI WaitSetupFinishThread(void* Param)\r
+{\r
+    CHAR Drv;\r
+    BOOL Found = FALSE;\r
+    CHAR OfflineRegPath[MAX_PATH];\r
+\r
+    while (!Found)\r
+    {\r
+        Sleep(300);\r
+        EnumWindows(EnumWindowsProcFunc, (LPARAM)&Found);\r
+    }\r
+\r
+    Log("### Setup finish detected");\r
+\r
+    // Add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE\BypassNRO\r
+    Drv = FindWindowsInstallDstDrive();\r
+    Log("Find Windows install drive %d", Drv);\r
+    if (Drv)\r
+    {\r
+        sprintf_s(OfflineRegPath, sizeof(OfflineRegPath), "%C:\\Windows\\system32\\config\\SOFTWARE", Drv);\r
+        AddBypassNROReg(OfflineRegPath);\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+int SetupMonNroStart(const char *isopath)\r
+{\r
+    SYSTEMTIME systime;\r
+\r
+    Log("SetupMonNroStart ...");\r
+\r
+    FindAllPromptStrings();\r
+\r
+    if (!g_MuiDataHead)\r
+    {\r
+        Log("Prompt not found, add default");\r
+        g_MuiDataHead = malloc(sizeof(VTOY_MUI_DATA));\r
+        if (g_MuiDataHead)\r
+        {\r
+            wcscpy_s(g_MuiDataHead->Prompt, PROMPT_MAX, L"Windows needs to restart to continue");\r
+            g_MuiDataHead->pNext = NULL;\r
+        }\r
+    }\r
+\r
+    Log("Wait for setup finish...");\r
+    GetSystemTime(&systime);\r
+    SystemTimeToFileTime(&systime, &g_SetupMonStartTime);\r
+\r
+    CreateThread(NULL, 0, WaitSetupFinishThread, NULL, 0, NULL);\r
+\r
+    return 0;\r
+}\r