From 3c03df31ce9981926226c4e6c1980effc0737cc6 Mon Sep 17 00:00:00 2001 From: longpanda Date: Sat, 7 Jan 2023 15:57:53 +0800 Subject: [PATCH] 1.0.87 release --- .github/ISSUE_TEMPLATE/issue_template.yml | 2 +- INSTALL/grub/grub.cfg | 15 +- vtoyjump/vtoyjump/setupmon.c | 513 ++++++++++++++++++++++ 3 files changed, 526 insertions(+), 4 deletions(-) create mode 100644 vtoyjump/vtoyjump/setupmon.c diff --git a/.github/ISSUE_TEMPLATE/issue_template.yml b/.github/ISSUE_TEMPLATE/issue_template.yml index acdc7067..d628916d 100644 --- a/.github/ISSUE_TEMPLATE/issue_template.yml +++ b/.github/ISSUE_TEMPLATE/issue_template.yml @@ -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 diff --git a/INSTALL/grub/grub.cfg b/INSTALL/grub/grub.cfg index 0534cabe..f055d888 100644 --- a/INSTALL/grub/grub.cfg +++ b/INSTALL/grub/grub.cfg @@ -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 index 00000000..f444903b --- /dev/null +++ b/vtoyjump/vtoyjump/setupmon.c @@ -0,0 +1,513 @@ +/****************************************************************************** +* setupmon.c +* +* Copyright (c) 2022, longpanda +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 3 of the +* License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, see . +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "vtoyjump.h" + + +#define PROMPT_MAX 1024 +typedef struct VTOY_MUI_DATA +{ + WCHAR Prompt[PROMPT_MAX]; + struct VTOY_MUI_DATA* pNext; +}VTOY_MUI_DATA; + +static VTOY_MUI_DATA* g_MuiDataHead = NULL; +static FILETIME g_SetupMonStartTime; + +#pragma pack(1) +typedef struct { + WORD dlgVer; + WORD signature; + DWORD helpID; + DWORD exStyle; + DWORD style; + WORD cDlgItems; + short x; + short y; + short cx; + short cy; + //sz_Or_Ord menu; + //sz_Or_Ord windowClass; + //WCHAR title[titleLen]; + //WORD pointsize; + //WORD weight; + //BYTE italic; + //BYTE charset; + //WCHAR typeface[stringLen]; +} DLGTEMPLATEEX; + +typedef struct { + DWORD helpID; + DWORD exStyle; + DWORD style; + short x; + short y; + short cx; + short cy; + DWORD id; + // sz_Or_Ord windowClass; + // sz_Or_Ord title; + // WORD extraCount; +} DLGITEMTEMPLATEEX; + + +#pragma pack() + +#define wchar_to_utf8_no_alloc(wsrc, dest, dest_size) \ + WideCharToMultiByte(CP_UTF8, 0, wsrc, -1, dest, dest_size, NULL, NULL) +#define utf8_to_wchar_no_alloc(src, wdest, wdest_size) \ + MultiByteToWideChar(CP_UTF8, 0, src, -1, wdest, wdest_size) + +#define VTOY_DLG_SKIP_SZ_ORD(pWord) \ +{\ + if (*pWord == 0x0000)\ + {\ + pWordData += 1;\ + }\ + else if (*pWordData == 0xFFFF)\ + {\ + pWordData += 2;\ + }\ + else\ + {\ + while (*pWordData++)\ + {\ + ;\ + }\ + }\ +} + +#define VTOY_DLG_SKIP_SZ(pWord) \ +{\ + while (*pWord)\ + {\ + pWord++;\ + }\ + pWord++;\ +} + + +static BOOL LoadSetupRebootDialogPrompt(HMODULE hMui, DWORD ID, WCHAR* Prompt, DWORD Len) +{ + DWORD i = 0; + UINT64 Addr = 0; + WORD* pWordData = NULL; + HRSRC hDlg = NULL; + HGLOBAL hTemplate = NULL; + DLGTEMPLATEEX* pDlgTempEx = NULL; + DLGITEMTEMPLATEEX* pDlgItemTempEx = NULL; + + hDlg = FindResource(hMui, MAKEINTRESOURCE(ID), RT_DIALOG); + if (!hDlg) + { + return FALSE; + } + + hTemplate = LoadResource(hMui, hDlg); + if (!hTemplate) + { + return FALSE; + } + + pDlgTempEx = (DLGTEMPLATEEX*)LockResource(hTemplate); + if (!pDlgTempEx) + { + return FALSE; + } + + if (pDlgTempEx->signature != 0xFFFF) + { + return FALSE; + } + + pWordData = (WORD*)(pDlgTempEx + 1); + + //skip menu + VTOY_DLG_SKIP_SZ_ORD(pWordData); + + //skip windowClass + VTOY_DLG_SKIP_SZ_ORD(pWordData); + + //skip title + VTOY_DLG_SKIP_SZ(pWordData); + + //skip pointsize/weight/italic + charset + pWordData += 3; + + //skip typeface + VTOY_DLG_SKIP_SZ(pWordData); + + //align to DWORD + Addr = (UINT64)pWordData; + if ((Addr % 4) > 0) + { + Addr += 4 - (Addr % 4); + pWordData = (WORD*)Addr; + } + + //First Dlg Item + pDlgItemTempEx = (DLGITEMTEMPLATEEX*)pWordData; + + if (pDlgItemTempEx->id != 1023) + { + return FALSE; + } + + pWordData = (WORD*)(pDlgItemTempEx + 1); + + //skip windowClass + VTOY_DLG_SKIP_SZ_ORD(pWordData); + + for (i = 0; i < Len; i++) + { + Prompt[i] = pWordData[i]; + if (Prompt[i] == 0) + { + break; + } + } + + return TRUE; +} + +static int LoadPromptString(const char* szDir) +{ + BOOL bRet; + HMODULE hMui; + CHAR MuiFile[MAX_PATH]; + WCHAR Prompt[PROMPT_MAX]; + VTOY_MUI_DATA* Node = NULL; + + sprintf_s(MuiFile, sizeof(MuiFile), "X:\\Sources\\%s\\w32uires.dll.mui", szDir); + + hMui = LoadLibraryA(MuiFile); + if (!hMui) + { + Log("Failed to loadlibrary <%s> %u", MuiFile, LASTERR); + return 1; + } + + bRet = LoadSetupRebootDialogPrompt(hMui, 103, Prompt, PROMPT_MAX); + if (bRet) + { + Node = malloc(sizeof(VTOY_MUI_DATA)); + if (Node) + { + memset(Node, 0, sizeof(VTOY_MUI_DATA)); + memcpy(Node->Prompt, Prompt, sizeof(Prompt)); + if (g_MuiDataHead == NULL) + { + g_MuiDataHead = Node; + } + else + { + Node->pNext = g_MuiDataHead; + g_MuiDataHead = Node; + } + + Log("Successfully add prompt string for <%s>", szDir); + } + } + else + { + Log("Failed to load prompt string from %s", szDir); + } + + FreeLibrary(hMui); + return 0; +} + +static int FindAllPromptStrings(void) +{ + HANDLE hFind; + WIN32_FIND_DATAA FindData; + + hFind = FindFirstFileA("X:\\Sources\\*", &FindData); + if (hFind == INVALID_HANDLE_VALUE) + { + Log("FindFirstFileA failed %u", LASTERR); + return 0; + } + + do + { + if ((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (strlen(FindData.cFileName) == 5)) + { + if (IsFileExist("X:\\Sources\\%s\\w32uires.dll.mui", FindData.cFileName)) + { + LoadPromptString(FindData.cFileName); + } + } + } while (FindNextFileA(hFind, &FindData)); + + return 0; +} + +static BOOL CALLBACK SetupPromptCallback(HWND hWnd, LPARAM lParam) +{ + VTOY_MUI_DATA* Node = NULL; + WCHAR Prompt[PROMPT_MAX] = { 0 }; + BOOL* found = (BOOL*)lParam; + + if (GetWindowTextW(hWnd, Prompt, PROMPT_MAX - 1) > 0) + { + for (Node = g_MuiDataHead; Node; Node = Node->pNext) + { + if (wcscmp(Node->Prompt, Prompt) == 0) + { + *found = TRUE; + break; + } + } + } + + return TRUE; +} + +static BOOL CALLBACK EnumWindowsProcFunc(HWND hWnd, LPARAM lParam) +{ + EnumChildWindows(hWnd, SetupPromptCallback, lParam); + return TRUE; +} + + +static CHAR FindWindowsInstallDstDrive(void) +{ + CHAR ret = 0; + CHAR Drv = 'A'; + DWORD Drives; + CHAR ChkFilePath[MAX_PATH]; + HANDLE hFile; + UINT64 Time1, Time2, Time3; + FILETIME fTime; + FILETIME sysftime; + SYSTEMTIME cur_systime; + + GetSystemTime(&cur_systime); + SystemTimeToFileTime(&cur_systime, &sysftime); + + memcpy(&Time1, &g_SetupMonStartTime, 8); + memcpy(&Time2, &sysftime, 8); + + Drives = GetLogicalDrives(); + Log("Find Windows: Logical Drives: 0x%x", Drives); + + while ((Drives > 0) && (ret == 0)) + { + if ((Drives & 1) && Drv != 'X') + { + sprintf_s(ChkFilePath, sizeof(ChkFilePath), "%C:\\$WINDOWS.~BT\\Sources\\Panther\\setupact.log", Drv); + hFile = CreateFileA(ChkFilePath, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if (hFile != INVALID_HANDLE_VALUE) + { + Log("%s Exist", ChkFilePath); + + if (GetFileTime(hFile, NULL, NULL, &fTime)) + { + memcpy(&Time3, &fTime, 8); + + Log("### %s %llu %llu %llu", ChkFilePath, Time1, Time2, Time3); + + if (Time3 > Time1 && Time3 < Time2) + { + Log("Detect Windows11 install drive:<%C>", Drv); + ret = Drv; + } + } + CloseHandle(hFile); + } + else + { + Log("%s NOT Exist %u", ChkFilePath, LASTERR); + } + } + + Drives >>= 1; + Drv++; + } + + return ret; +} + +static int AddBypassNROReg(const CHAR* OfflineRegPath) +{ + int ret = 1; + BOOL Unload = FALSE; + LSTATUS Status; + HKEY hKey = NULL; + HKEY hSubKey = NULL; + DWORD dwValue = 1; + DWORD dwSize; + HANDLE htoken; + DWORD s = 0; + TOKEN_PRIVILEGES* p = NULL; + + Log("AddBypassNROReg<%s>", OfflineRegPath); + + if (!IsFileExist(OfflineRegPath)) + { + return ret; + } + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &htoken)) + { + Log("Open process token failed! %u", LASTERR); + return ret; + } + + s = sizeof(TOKEN_PRIVILEGES) + 2 * sizeof(LUID_AND_ATTRIBUTES); + p = (PTOKEN_PRIVILEGES)malloc(s); + if (!p) + { + Log("Failed to alloc privileges memory"); + return ret; + } + + if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &(p->Privileges[0].Luid)) || + !LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &(p->Privileges[1].Luid)) || + !LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &(p->Privileges[2].Luid))) + { + Log("LookupPrivilegeValue failed!"); + goto End; + } + + p->PrivilegeCount = 3; + p->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + p->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; + p->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(htoken, FALSE, p, s, NULL, NULL) || GetLastError() != ERROR_SUCCESS) + { + Log("AdjustTokenPrivileges failed!"); + goto End; + } + + Log("AdjustTokenPrivileges success"); + + Status = RegLoadKeyA(HKEY_LOCAL_MACHINE, "VTOYNEWSW", OfflineRegPath); + if (Status != ERROR_SUCCESS) + { + Log("RegLoadKey Failed 0x%x", Status); + goto End; + } + Unload = TRUE; + + Status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "VTOYNEWSW\\Microsoft\\Windows\\CurrentVersion", 0, NULL, REG_OPTION_BACKUP_RESTORE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize); + if (ERROR_SUCCESS != Status) + { + Log("Failed to create reg key VTOYNEWSW\\Microsoft\\Windows\\CurrentVersion %u %u", LASTERR, Status); + goto End; + } + + Status = RegCreateKeyExA(hKey, "OOBE", 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_CREATE_SUB_KEY, NULL, &hSubKey, &dwSize); + if (ERROR_SUCCESS != Status) + { + Log("Failed to create OOBE reg %u %u", LASTERR, Status); + goto End; + } + + Status = RegSetValueExA(hSubKey, "BypassNRO", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD)); + Log("Create BypassNRO registry %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status); + + Status = RegFlushKey(hSubKey); + Status += RegCloseKey(hSubKey); + Log("Flush and close subkey %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status); + + Status = RegFlushKey(hKey); + Status += RegCloseKey(hKey); + Log("Flush and close key %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status); + + ret = 0; + +End: + if (Unload) + { + Status = RegUnLoadKeyA(HKEY_LOCAL_MACHINE, "VTOYNEWSW"); + Log("RegUnLoadKey %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status); + } + + if (p) + { + free(p); + } + + return ret; +} + +static DWORD WINAPI WaitSetupFinishThread(void* Param) +{ + CHAR Drv; + BOOL Found = FALSE; + CHAR OfflineRegPath[MAX_PATH]; + + while (!Found) + { + Sleep(300); + EnumWindows(EnumWindowsProcFunc, (LPARAM)&Found); + } + + Log("### Setup finish detected"); + + // Add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE\BypassNRO + Drv = FindWindowsInstallDstDrive(); + Log("Find Windows install drive %d", Drv); + if (Drv) + { + sprintf_s(OfflineRegPath, sizeof(OfflineRegPath), "%C:\\Windows\\system32\\config\\SOFTWARE", Drv); + AddBypassNROReg(OfflineRegPath); + } + + return 0; +} + +int SetupMonNroStart(const char *isopath) +{ + SYSTEMTIME systime; + + Log("SetupMonNroStart ..."); + + FindAllPromptStrings(); + + if (!g_MuiDataHead) + { + Log("Prompt not found, add default"); + g_MuiDataHead = malloc(sizeof(VTOY_MUI_DATA)); + if (g_MuiDataHead) + { + wcscpy_s(g_MuiDataHead->Prompt, PROMPT_MAX, L"Windows needs to restart to continue"); + g_MuiDataHead->pNext = NULL; + } + } + + Log("Wait for setup finish..."); + GetSystemTime(&systime); + SystemTimeToFileTime(&systime, &g_SetupMonStartTime); + + CreateThread(NULL, 0, WaitSetupFinishThread, NULL, 0, NULL); + + return 0; +}