From 1d034f0a24ed466d5942689540fcbdc7ec262d05 Mon Sep 17 00:00:00 2001 From: longpanda Date: Fri, 3 Jul 2020 23:20:35 +0800 Subject: [PATCH] update --- .../MdeModulePkg/Application/Ventoy/Ventoy.c | 73 +- .../MdeModulePkg/Application/Ventoy/Ventoy.h | 28 +- .../Application/Ventoy/VentoyDebug.c | 88 ++- .../Application/Ventoy/VentoyProtocol.c | 101 ++- .../Application/VtoyUtil/Memhole.c | 179 +++++ .../Application/VtoyUtil/VtoyUtil.c | 135 ++++ .../Application/VtoyUtil/VtoyUtil.h | 61 ++ .../Application/VtoyUtil/VtoyUtil.inf | 80 +++ .../MdeModulePkg/MdeModulePkg.dsc | 1 + .../grub-2.04/grub-core/ventoy/ventoy.c | 98 ++- .../grub-2.04/grub-core/ventoy/ventoy_def.h | 15 +- .../grub-2.04/grub-core/ventoy/ventoy_linux.c | 2 +- .../grub-core/ventoy/ventoy_plugin.c | 168 ++++- .../grub-core/ventoy/ventoy_windows.c | 20 +- GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h | 18 +- GRUB2/MOD_SRC/grub-2.04/install.sh | 4 +- INSTALL/grub/debug.cfg | 18 +- INSTALL/ventoy_pack.sh | 2 +- .../src/arch/x86/core/ventoy_vdisk.c | 2 +- .../ipxe-3fe683e/src/include/ventoy.h | 9 + LANGUAGES/languages.ini | Bin 83990 -> 96532 bytes Ventoy2Disk/Ventoy2Disk/Language.h | 5 + Ventoy2Disk/Ventoy2Disk/PhyDrive.c | 287 +++++++- Ventoy2Disk/Ventoy2Disk/Utility.c | 2 +- Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c | 1 + Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h | 8 + Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.rc | Bin 10530 -> 10832 bytes Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj | 4 + .../Ventoy2Disk/Ventoy2Disk.vcxproj.filters | 12 + Ventoy2Disk/Ventoy2Disk/WinDialog.c | Bin 43160 -> 50772 bytes Ventoy2Disk/Ventoy2Disk/process.c | 672 ++++++++++++++++++ Ventoy2Disk/Ventoy2Disk/process.h | 405 +++++++++++ Ventoy2Disk/Ventoy2Disk/resource.h | Bin 3556 -> 3830 bytes 33 files changed, 2361 insertions(+), 137 deletions(-) create mode 100644 EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/Memhole.c create mode 100644 EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.c create mode 100644 EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.h create mode 100644 EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf create mode 100644 Ventoy2Disk/Ventoy2Disk/process.c create mode 100644 Ventoy2Disk/Ventoy2Disk/process.h diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c index 7c2267f5..968049af 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c @@ -52,6 +52,8 @@ static grub_env_get_pf grub_env_get = NULL; ventoy_grub_param_file_replace *g_file_replace_list = NULL; ventoy_efi_file_replace g_efi_file_replace; +BOOLEAN g_fix_windows_1st_cdrom_issue = FALSE; + STATIC BOOLEAN g_hook_keyboard = FALSE; CHAR16 gFirstTryBootFile[256] = {0}; @@ -493,6 +495,7 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) EFI_STATUS Status = EFI_SUCCESS; ventoy_grub_param *pGrubParam = NULL; EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL; + ventoy_chain_head *chain = NULL; Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo); if (EFI_ERROR(Status)) @@ -559,12 +562,15 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) ); pPos = StrStr(pCmdLine, L"mem:"); - g_chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4); + chain = (ventoy_chain_head *)StrHexToUintn(pPos + 4); pPos = StrStr(pPos, L"size:"); size = StrDecimalToUintn(pPos + 5); - debug("memory addr:%p size:%lu", g_chain, size); + debug("memory addr:%p size:%lu", chain, size); + + g_chain = AllocatePool(size); + CopyMem(g_chain, chain, size); if (StrStr(pCmdLine, L"memdisk")) { @@ -583,12 +589,12 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) g_os_param_reserved = (UINT8 *)(g_chain->os_param.vtoy_reserved); /* Workaround for Windows & ISO9660 */ - if (g_os_param_reserved[2] == 1 && g_os_param_reserved[3] == 0) + if (g_os_param_reserved[2] == ventoy_chain_windows && g_os_param_reserved[3] == 0) { g_fixup_iso9660_secover_enable = TRUE; } - if (g_os_param_reserved[2] == 1 && g_os_param_reserved[4] != 1) + if (g_os_param_reserved[2] == ventoy_chain_windows && g_os_param_reserved[4] != 1) { g_hook_keyboard = TRUE; } @@ -613,6 +619,17 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) } } + g_fix_windows_1st_cdrom_issue = FALSE; + if (ventoy_chain_windows == g_os_param_reserved[2] || + ventoy_chain_wim == g_os_param_reserved[2]) + { + if (ventoy_is_cdrom_dp_exist()) + { + debug("fixup the 1st cdrom influences when boot windows ..."); + g_fix_windows_1st_cdrom_issue = TRUE; + } + } + FreePool(pCmdLine); return EFI_SUCCESS; } @@ -636,6 +653,44 @@ EFI_STATUS EFIAPI ventoy_clean_env(VOID) FreePool((VOID *)(UINTN)g_chain->os_param.vtoy_img_location_addr); } + FreePool(g_chain); + + return EFI_SUCCESS; +} + +STATIC EFI_STATUS ventoy_hook_start(VOID) +{ + /* don't add debug print in this function */ + + if (g_fix_windows_1st_cdrom_issue) + { + ventoy_hook_1st_cdrom_start(); + } + + /* let this the last */ + if (g_hook_keyboard) + { + ventoy_hook_keyboard_start(); + } + + return EFI_SUCCESS; +} + +STATIC EFI_STATUS ventoy_hook_stop(VOID) +{ + /* don't add debug print in this function */ + + if (g_fix_windows_1st_cdrom_issue) + { + ventoy_hook_1st_cdrom_stop(); + } + + /* let this the last */ + if (g_hook_keyboard) + { + ventoy_hook_keyboard_stop(); + } + return EFI_SUCCESS; } @@ -725,17 +780,11 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle) pFile->OpenVolume = ventoy_wrapper_open_volume; } - if (g_hook_keyboard) - { - ventoy_hook_keyboard_start(); - } + ventoy_hook_start(); /* can't add debug print here */ //ventoy_wrapper_system(); Status = gBS->StartImage(Image, NULL, NULL); - if (g_hook_keyboard) - { - ventoy_hook_keyboard_stop(); - } + ventoy_hook_stop(); if (EFI_ERROR(Status)) { diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h index 354496e7..1056f8cc 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h @@ -25,6 +25,15 @@ #define VENTOY_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }} +typedef enum ventoy_chain_type +{ + ventoy_chain_linux = 0, /* 0: linux */ + ventoy_chain_windows, /* 1: windows */ + ventoy_chain_wim, /* 2: wim */ + + ventoy_chain_max +}ventoy_chain_type; + #pragma pack(1) typedef struct ventoy_guid @@ -216,6 +225,7 @@ if (gDebugPrint) \ } typedef const char * (*grub_env_get_pf)(const char *name); +typedef int (*grub_env_printf_pf)(const char *fmt, ...); #pragma pack(1) @@ -242,8 +252,8 @@ typedef struct ventoy_grub_param_file_replace typedef struct ventoy_grub_param { grub_env_get_pf grub_env_get; - ventoy_grub_param_file_replace file_replace; + grub_env_printf_pf grub_env_printf; }ventoy_grub_param; typedef struct ventoy_ram_disk @@ -279,6 +289,18 @@ typedef struct ventoy_system_wrapper EFI_OPEN_PROTOCOL NewOpenProtocol; EFI_OPEN_PROTOCOL OriOpenProtocol; + + EFI_LOCATE_HANDLE_BUFFER NewLocateHandleBuffer; + EFI_LOCATE_HANDLE_BUFFER OriLocateHandleBuffer; + + EFI_PROTOCOLS_PER_HANDLE NewProtocolsPerHandle; + EFI_PROTOCOLS_PER_HANDLE OriProtocolsPerHandle; + + EFI_LOCATE_HANDLE NewLocateHandle; + EFI_LOCATE_HANDLE OriLocateHandle; + + EFI_LOCATE_DEVICE_PATH NewLocateDevicePath; + EFI_LOCATE_DEVICE_PATH OriLocateDevicePath; } ventoy_system_wrapper; #define ventoy_wrapper(bs, wrapper, func, newfunc) \ @@ -317,6 +339,7 @@ extern UINTN g_iso_buf_size; extern ventoy_grub_param_file_replace *g_file_replace_list; extern BOOLEAN g_fixup_iso9660_secover_enable; extern EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex; +extern BOOLEAN g_fix_windows_1st_cdrom_issue; EFI_STATUS EFIAPI ventoy_wrapper_open_volume ( @@ -327,6 +350,9 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 Im EFI_STATUS EFIAPI ventoy_wrapper_push_openvolume(IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume); EFI_STATUS ventoy_hook_keyboard_start(VOID); EFI_STATUS ventoy_hook_keyboard_stop(VOID); +BOOLEAN ventoy_is_cdrom_dp_exist(VOID); +EFI_STATUS ventoy_hook_1st_cdrom_start(VOID); +EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID); #endif diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyDebug.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyDebug.c index d96c6b2e..7af3349b 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyDebug.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyDebug.c @@ -36,9 +36,9 @@ #include #include -#define PROCOTOL_SLEEP_SECONDS 0 +#define PROCOTOL_SLEEP_MSECONDS 0 -#define debug_sleep() if (PROCOTOL_SLEEP_SECONDS) sleep(PROCOTOL_SLEEP_SECONDS) +#define debug_sleep() if (PROCOTOL_SLEEP_MSECONDS) gBS->Stall(1000 * PROCOTOL_SLEEP_MSECONDS) STATIC ventoy_system_wrapper g_system_wrapper; @@ -126,7 +126,7 @@ STATIC EFI_STATUS EFIAPI ventoy_open_protocol IN UINT32 Attributes ) { - debug("ventoy_open_protocol:%a", ventoy_get_guid_name(Protocol)); debug_sleep(); + debug("ventoy_open_protocol:<%p> %a", Handle, ventoy_get_guid_name(Protocol)); debug_sleep(); return g_system_wrapper.OriOpenProtocol(Handle, Protocol, Interface, AgentHandle, ControllerHandle, Attributes); } @@ -141,11 +141,87 @@ STATIC EFI_STATUS EFIAPI ventoy_locate_protocol return g_system_wrapper.OriLocateProtocol(Protocol, Registration, Interface); } +STATIC EFI_STATUS EFIAPI ventoy_locate_handle_buffer +( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer +) +{ + debug("ventoy_locate_handle_buffer:%a", ventoy_get_guid_name(Protocol)); debug_sleep(); + return g_system_wrapper.OriLocateHandleBuffer(SearchType, Protocol, SearchKey, NoHandles, Buffer); +} + +STATIC EFI_STATUS EFIAPI ventoy_protocol_per_handle +( + IN EFI_HANDLE Handle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount +) +{ + debug("ventoy_protocol_per_handle:%p", Handle); debug_sleep(); + return g_system_wrapper.OriProtocolsPerHandle(Handle, ProtocolBuffer, ProtocolBufferCount); +} + +EFI_STATUS EFIAPI ventoy_locate_handle +( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer +) +{ + UINTN i; + EFI_HANDLE Handle; + EFI_STATUS Status = EFI_SUCCESS; + + debug("ventoy_locate_handle: %d %a %p", SearchType, ventoy_get_guid_name(Protocol), SearchKey); + Status = g_system_wrapper.OriLocateHandle(SearchType, Protocol, SearchKey, BufferSize, Buffer); + debug("ventoy_locate_handle: %r Handle Count:%u", Status, *BufferSize/sizeof(EFI_HANDLE)); + + if (EFI_SUCCESS == Status) + { + for (i = 0; i < *BufferSize / sizeof(EFI_HANDLE); i++) + { + if (Buffer[i] == gBlockData.Handle) + { + Handle = Buffer[0]; + Buffer[0] = Buffer[i]; + Buffer[i] = Handle; + debug("####### Handle at %u", i); + break; + } + } + } + + debug_sleep(); + + return Status; +} + +STATIC EFI_STATUS EFIAPI ventoy_locate_device_path +( + IN EFI_GUID *Protocol, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT EFI_HANDLE *Device +) +{ + debug("ventoy_locate_device_path:%a", ventoy_get_guid_name(Protocol)); debug_sleep(); + return g_system_wrapper.OriLocateDevicePath(Protocol, DevicePath, Device); +} + EFI_STATUS EFIAPI ventoy_wrapper_system(VOID) { - ventoy_wrapper(gBS, g_system_wrapper, LocateProtocol, ventoy_locate_protocol); - ventoy_wrapper(gBS, g_system_wrapper, HandleProtocol, ventoy_handle_protocol); - ventoy_wrapper(gBS, g_system_wrapper, OpenProtocol, ventoy_open_protocol); + ventoy_wrapper(gBS, g_system_wrapper, LocateProtocol, ventoy_locate_protocol); + ventoy_wrapper(gBS, g_system_wrapper, HandleProtocol, ventoy_handle_protocol); + ventoy_wrapper(gBS, g_system_wrapper, OpenProtocol, ventoy_open_protocol); + ventoy_wrapper(gBS, g_system_wrapper, LocateHandleBuffer, ventoy_locate_handle_buffer); + ventoy_wrapper(gBS, g_system_wrapper, ProtocolsPerHandle, ventoy_protocol_per_handle); + ventoy_wrapper(gBS, g_system_wrapper, LocateHandle, ventoy_locate_handle); + ventoy_wrapper(gBS, g_system_wrapper, LocateDevicePath, ventoy_locate_device_path); return EFI_SUCCESS; } diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c index 0e19153c..8afbd9a1 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c @@ -65,6 +65,47 @@ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex = NULL; STATIC EFI_INPUT_READ_KEY_EX g_org_read_key_ex = NULL; STATIC EFI_INPUT_READ_KEY g_org_read_key = NULL; +STATIC EFI_LOCATE_HANDLE g_org_locate_handle = NULL; + +BOOLEAN ventoy_is_cdrom_dp_exist(VOID) +{ + UINTN i = 0; + UINTN Count = 0; + EFI_HANDLE *Handles = NULL; + EFI_STATUS Status = EFI_SUCCESS; + EFI_DEVICE_PATH_PROTOCOL *DevicePath = NULL; + + Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiDevicePathProtocolGuid, + NULL, &Count, &Handles); + if (EFI_ERROR(Status)) + { + return FALSE; + } + + for (i = 0; i < Count; i++) + { + Status = gBS->HandleProtocol(Handles[i], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath); + if (EFI_ERROR(Status)) + { + continue; + } + + while (!IsDevicePathEnd(DevicePath)) + { + if (MEDIA_DEVICE_PATH == DevicePath->Type && MEDIA_CDROM_DP == DevicePath->SubType) + { + FreePool(Handles); + return TRUE; + } + + DevicePath = NextDevicePathNode(DevicePath); + } + } + + FreePool(Handles); + return FALSE; +} + #if 0 /* Block IO procotol */ #endif @@ -475,7 +516,7 @@ EFI_STATUS EFIAPI ventoy_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST if (i < Count) { Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE); - debug("Connect partition driver:<%r>", Status); + debug("ventoy_connect_driver:<%s> <%r>", DrvName, Status); goto end; } @@ -517,7 +558,7 @@ EFI_STATUS EFIAPI ventoy_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST if (i < Count) { Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE); - debug("Connect partition driver:<%r>", Status); + debug("ventoy_connect_driver:<%s> <%r>", DrvName, Status); goto end; } @@ -535,6 +576,9 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 Im EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gBlockData.BlockIo); ventoy_fill_device_path(); + + debug("install block io protocol %p", ImageHandle); + ventoy_debug_pause(); gBlockData.Media.BlockSize = 2048; gBlockData.Media.LastBlock = ImgSize / 2048 - 1; @@ -561,7 +605,6 @@ EFI_STATUS EFIAPI ventoy_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 Im Status = ventoy_connect_driver(gBlockData.Handle, L"Disk I/O Driver"); debug("Connect disk IO driver %r", Status); - ventoy_debug_pause(); Status = ventoy_connect_driver(gBlockData.Handle, L"Partition Driver"); debug("Connect partition driver %r", Status); @@ -916,3 +959,55 @@ EFI_STATUS ventoy_hook_keyboard_stop(VOID) return EFI_SUCCESS; } +#if 0 +/* Fixup the 1st cdrom influnce for Windows boot */ +#endif + +STATIC EFI_STATUS EFIAPI ventoy_wrapper_locate_handle +( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer +) +{ + UINTN i; + EFI_HANDLE Handle = NULL; + EFI_STATUS Status = EFI_SUCCESS; + + Status = g_org_locate_handle(SearchType, Protocol, SearchKey, BufferSize, Buffer); + + if (EFI_SUCCESS == Status && Protocol && CompareGuid(&gEfiBlockIoProtocolGuid, Protocol)) + { + for (i = 0; i < (*BufferSize) / sizeof(EFI_HANDLE); i++) + { + if (Buffer[i] == gBlockData.Handle) + { + Handle = Buffer[0]; + Buffer[0] = Buffer[i]; + Buffer[i] = Handle; + break; + } + } + } + + return Status; +} + +EFI_STATUS ventoy_hook_1st_cdrom_start(VOID) +{ + g_org_locate_handle = gBS->LocateHandle; + gBS->LocateHandle = ventoy_wrapper_locate_handle; + + return EFI_SUCCESS; +} + +EFI_STATUS ventoy_hook_1st_cdrom_stop(VOID) +{ + gBS->LocateHandle = g_org_locate_handle; + g_org_locate_handle = NULL; + + return EFI_SUCCESS; +} + diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/Memhole.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/Memhole.c new file mode 100644 index 00000000..715d7bce --- /dev/null +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/Memhole.c @@ -0,0 +1,179 @@ +/****************************************************************************** + * Memhole.c + * + * Copyright (c) 2020, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +STATIC BOOLEAN IsMemContiguous +( + IN CONST EFI_MEMORY_DESCRIPTOR *Prev, + IN CONST EFI_MEMORY_DESCRIPTOR *Curr, + IN CONST EFI_MEMORY_DESCRIPTOR *Next +) +{ + UINTN Addr1 = 0; + UINTN Addr2 = 0; + + if (Prev == NULL || Curr == NULL || Next == NULL) + { + return FALSE; + } + + if (Prev->Type == EfiBootServicesData && + Curr->Type == EfiConventionalMemory && + Next->Type == EfiBootServicesData) + { + Addr1 = Prev->PhysicalStart + MultU64x64(SIZE_4KB, Prev->NumberOfPages); + Addr2 = Curr->PhysicalStart + MultU64x64(SIZE_4KB, Curr->NumberOfPages); + + if (Addr1 == Curr->PhysicalStart && Addr2 == Next->PhysicalStart) + { + return TRUE; + } + } + + return FALSE; +} + +STATIC EFI_MEMORY_DESCRIPTOR* GetMemDesc +( + OUT UINTN *pSize, + OUT UINTN *pItemSize, + OUT UINTN *pDescCount +) +{ + UINTN Size = 0; + UINTN MapKey = 0; + UINTN ItemSize = 0; + UINTN DescCount = 0; + UINT32 Version = 0; + EFI_STATUS Status = EFI_SUCCESS; + EFI_MEMORY_DESCRIPTOR *pDesc = NULL; + EFI_MEMORY_DESCRIPTOR *Curr = NULL; + + Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version); + if (EFI_BUFFER_TOO_SMALL != Status) + { + debug("GetMemoryMap: %r", Status); + return NULL; + } + + Size += SIZE_1KB; + pDesc = AllocatePool(Size); + if (!pDesc) + { + debug("AllocatePool: %lu failed", Size); + return NULL; + } + + ZeroMem(pDesc, Size); + + Status = gBS->GetMemoryMap(&Size, pDesc, &MapKey, &ItemSize, &Version); + if (EFI_ERROR(Status)) + { + debug("GetMemoryMap: %r", Status); + FreePool(pDesc); + return NULL; + } + + Curr = pDesc; + while (Curr && Curr < (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)pDesc + Size)) + { + DescCount++; + Curr = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize); + } + + *pSize = Size; + *pItemSize = ItemSize; + *pDescCount = DescCount; + + debug("GetMemoryMap: ItemSize:%lu Count:%lu", ItemSize, DescCount); + + return pDesc; +} + +EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine) +{ + UINTN Size = 0; + UINTN ItemSize = 0; + UINTN DescCount = 0; + UINTN TotalMem = 0; + EFI_STATUS Status = EFI_SUCCESS; + EFI_PHYSICAL_ADDRESS AllocAddr = 0; + EFI_MEMORY_DESCRIPTOR *pDescs = NULL; + EFI_MEMORY_DESCRIPTOR *Prev = NULL; + EFI_MEMORY_DESCRIPTOR *Next = NULL; + EFI_MEMORY_DESCRIPTOR *Curr = NULL; + + (VOID)ImageHandle; + (VOID)CmdLine; + + pDescs = GetMemDesc(&Size, &ItemSize, &DescCount); + if (!pDescs) + { + return EFI_NOT_FOUND; + } + + if (DescCount < 500) + { + FreePool(pDescs); + Printf("There is no need to fixup (%lu)\n", DescCount); + return EFI_SUCCESS; + } + + Curr = pDescs; + while ((UINT8 *)Curr < (UINT8 *)pDescs + Size) + { + Next = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Curr + ItemSize); + + if (IsMemContiguous(Prev, Curr, Next)) + { + AllocAddr = Curr->PhysicalStart; + Status = gBS->AllocatePages(AllocateAddress, EfiBootServicesData, Curr->NumberOfPages, &AllocAddr); + if (EFI_SUCCESS == Status) + { + TotalMem += MultU64x64(SIZE_4KB, Curr->NumberOfPages); + } + } + + Prev = Curr; + Curr = Next; + } + + Printf("Fixup Windows mmap issue OK (%lu)\n", TotalMem); + + return EFI_SUCCESS; +} + diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.c new file mode 100644 index 00000000..9f4d7b3a --- /dev/null +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.c @@ -0,0 +1,135 @@ +/****************************************************************************** + * VtoyUtil.c + * + * Copyright (c) 2020, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BOOLEAN gVtoyDebugPrint = FALSE; +STATIC CONST CHAR16 *gCurFeature= NULL; +STATIC CHAR16 *gCmdLine = NULL; +STATIC grub_env_printf_pf g_env_printf = NULL; + +STATIC VtoyUtilFeature gFeatureList[] = +{ + { L"fix_windows_mmap", FixWindowsMemhole }, +}; + +VOID EFIAPI VtoyUtilDebug(IN CONST CHAR8 *Format, ...) +{ + VA_LIST Marker; + CHAR8 Buffer[512]; + + VA_START (Marker, Format); + AsciiVSPrint(Buffer, sizeof(Buffer), Format, Marker); + VA_END (Marker); + + if (g_env_printf) + { + g_env_printf("%s", Buffer); + } +} + +STATIC EFI_STATUS ParseCmdline(IN EFI_HANDLE ImageHandle) +{ + CHAR16 *pPos = NULL; + CHAR16 *pCmdLine = NULL; + EFI_STATUS Status = EFI_SUCCESS; + ventoy_grub_param *pGrubParam = NULL; + EFI_LOADED_IMAGE_PROTOCOL *pImageInfo = NULL; + + Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&pImageInfo); + if (EFI_ERROR(Status)) + { + return Status; + } + + pCmdLine = (CHAR16 *)AllocatePool(pImageInfo->LoadOptionsSize + 4); + SetMem(pCmdLine, pImageInfo->LoadOptionsSize + 4, 0); + CopyMem(pCmdLine, pImageInfo->LoadOptions, pImageInfo->LoadOptionsSize); + + if (StrStr(pCmdLine, L"debug")) + { + gVtoyDebugPrint = TRUE; + } + + pPos = StrStr(pCmdLine, L"env_param="); + if (!pPos) + { + return EFI_INVALID_PARAMETER; + } + + pGrubParam = (ventoy_grub_param *)StrHexToUintn(pPos + StrLen(L"env_param=")); + g_env_printf = pGrubParam->grub_env_printf; + + pPos = StrStr(pCmdLine, L"feature="); + if (!pPos) + { + return EFI_INVALID_PARAMETER; + } + + gCurFeature = pPos + StrLen(L"feature="); + + gCmdLine = pCmdLine; + return EFI_SUCCESS; +} + +EFI_STATUS EFIAPI VtoyUtilEfiMain +( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + UINTN i; + UINTN Len; + + ParseCmdline(ImageHandle); + + for (i = 0; i < ARRAY_SIZE(gFeatureList); i++) + { + Len = StrLen(gFeatureList[i].Cmd); + if (StrnCmp(gFeatureList[i].Cmd, gCurFeature, Len) == 0) + { + debug("Find main proc <%s>", gFeatureList[i].Cmd); + gFeatureList[i].MainProc(ImageHandle, gCurFeature + Len); + break; + } + } + + FreePool(gCmdLine); + gCmdLine = NULL; + + return EFI_SUCCESS; +} + diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.h b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.h new file mode 100644 index 00000000..9adf6c70 --- /dev/null +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * VtoyUtil.h + * + * Copyright (c) 2020, 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 . + * + */ + +#ifndef __VTOYUTIL_H__ +#define __VTOYUTIL_H__ + +#pragma pack(1) + +typedef EFI_STATUS (*VTOY_UTIL_PROC_PF)(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine); +typedef const char * (*grub_env_get_pf)(const char *name); +typedef int (*grub_env_printf_pf)(const char *fmt, ...); + +typedef struct ventoy_grub_param_file_replace +{ + UINT32 magic; + char old_file_name[4][256]; + UINT32 old_file_cnt; + UINT32 new_file_virtual_id; +}ventoy_grub_param_file_replace; + +typedef struct ventoy_grub_param +{ + grub_env_get_pf grub_env_get; + ventoy_grub_param_file_replace file_replace; + grub_env_printf_pf grub_env_printf; +}ventoy_grub_param; +#pragma pack() + + +typedef struct VtoyUtilFeature +{ + CONST CHAR16 *Cmd; + VTOY_UTIL_PROC_PF MainProc; +}VtoyUtilFeature; + +extern BOOLEAN gVtoyDebugPrint; +VOID EFIAPI VtoyUtilDebug(IN CONST CHAR8 *Format, ...); +#define debug(expr, ...) if (gVtoyDebugPrint) VtoyUtilDebug("[VTOY] "expr"\n", ##__VA_ARGS__) +#define Printf VtoyUtilDebug + +EFI_STATUS FixWindowsMemhole(IN EFI_HANDLE ImageHandle, IN CONST CHAR16 *CmdLine); + +#endif + diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf new file mode 100644 index 00000000..9a4fbf27 --- /dev/null +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf @@ -0,0 +1,80 @@ +#************************************************************************************ +# Copyright (c) 2020, 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 . +# +#************************************************************************************ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VtoyUtil + FILE_GUID = a43466a0-68c6-469d-ba4b-678bbe90bc47 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = VtoyUtilEfiMain + + +[Sources] + VtoyUtil.h + VtoyUtil.c + Memhole.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + DebugLib + +[Guids] + gShellVariableGuid + gEfiVirtualCdGuid + gEfiFileInfoGuid + +[Protocols] + gEfiLoadedImageProtocolGuid + gEfiBlockIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiRamDiskProtocolGuid + gEfiAbsolutePointerProtocolGuid + gEfiAcpiTableProtocolGuid + gEfiBlockIo2ProtocolGuid + gEfiBusSpecificDriverOverrideProtocolGuid + gEfiComponentNameProtocolGuid + gEfiComponentName2ProtocolGuid + gEfiDriverBindingProtocolGuid + gEfiDiskIoProtocolGuid + gEfiDiskIo2ProtocolGuid + gEfiGraphicsOutputProtocolGuid + gEfiHiiConfigAccessProtocolGuid + gEfiHiiFontProtocolGuid + gEfiLoadFileProtocolGuid + gEfiLoadFile2ProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiLoadedImageDevicePathProtocolGuid + gEfiPciIoProtocolGuid + gEfiSerialIoProtocolGuid + gEfiSimpleTextInProtocolGuid + gEfiSimpleTextInputExProtocolGuid + gEfiSimpleTextOutProtocolGuid + + + + + + diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/MdeModulePkg.dsc b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/MdeModulePkg.dsc index 2bdadd28..f47ea6fb 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/MdeModulePkg.dsc +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/MdeModulePkg.dsc @@ -204,6 +204,7 @@ [Components] MdeModulePkg/Application/Ventoy/Ventoy.inf + MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf MdeModulePkg/Application/HelloWorld/HelloWorld.inf MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c index 32200f14..708d4c15 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c @@ -891,8 +891,8 @@ static int ventoy_colect_img_files(const char *filename, const struct grub_dirho *((img_info **)(node->tail)) = img; g_ventoy_img_count++; - img->alias = ventoy_plugin_get_menu_alias(img->path); - img->class = ventoy_plugin_get_menu_class(img->name); + img->alias = ventoy_plugin_get_menu_alias(vtoy_alias_image_file, img->path); + img->class = ventoy_plugin_get_menu_class(vtoy_class_image_file, img->name); if (!img->class) { img->class = g_menu_class[type]; @@ -1029,7 +1029,9 @@ static img_iterator_node * ventoy_get_min_child(img_iterator_node *node) static int ventoy_dynamic_tree_menu(img_iterator_node *node) { int offset = 1; - img_info *img; + img_info *img = NULL; + const char *dir_class = NULL; + const char *dir_alias = NULL; img_iterator_node *child = NULL; if (node->isocnt == 0 || node->done == 1) @@ -1055,9 +1057,25 @@ static int ventoy_dynamic_tree_menu(img_iterator_node *node) else { node->dir[node->dirlen - 1] = 0; - vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, - "submenu \"%-10s [%s]\" --class=\"vtoydir\" {\n", - "DIR", node->dir + offset); + dir_class = ventoy_plugin_get_menu_class(vtoy_class_directory, node->dir); + if (!dir_class) + { + dir_class = "vtoydir"; + } + + dir_alias = ventoy_plugin_get_menu_alias(vtoy_alias_directory, node->dir); + if (dir_alias) + { + vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, + "submenu \"%-10s %s\" --class=\"%s\" {\n", + "DIR", dir_alias, dir_class); + } + else + { + vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, + "submenu \"%-10s [%s]\" --class=\"%s\" {\n", + "DIR", node->dir + offset, dir_class); + } vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n " @@ -1662,7 +1680,7 @@ static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int ar (void)argc; (void)args; - debug("select auto installation %d\n", argc); + debug("select auto installation argc:%d\n", argc); if (argc < 1) { @@ -1672,7 +1690,14 @@ static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int ar node = ventoy_plugin_find_install_template(args[0]); if (!node) { - debug("Install template not found for %s\n", args[0]); + debug("Auto install template not found for %s\n", args[0]); + return 0; + } + + if (node->autosel >= 0 && node->autosel <= node->templatenum) + { + node->cursel = node->autosel - 1; + debug("Auto install template auto select %d\n", node->autosel); return 0; } @@ -1720,7 +1745,7 @@ static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int arg (void)argc; (void)args; - debug("select persistece %d\n", argc); + debug("select persistence argc:%d\n", argc); if (argc < 1) { @@ -1734,6 +1759,13 @@ static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int arg return 0; } + if (node->autosel >= 0 && node->autosel <= node->backendnum) + { + node->cursel = node->autosel - 1; + debug("Persistence image auto select %d\n", node->autosel); + return 0; + } + buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF); if (!buf) { @@ -1979,27 +2011,6 @@ static grub_err_t ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt, int a (void)argc; (void)args; -{ - grub_file_t file; - char *buf; - char name[128]; - - file = grub_file_open("(hd0,1)/ventoy/ventoy.disk.img.xz", GRUB_FILE_TYPE_NONE); - if (file) - { - grub_printf("Open File OK (size:%llu)\n", (ulonglong)file->size); - - buf = grub_malloc(file->size); - grub_file_read(file, buf, file->size); - - grub_file_close(file); - - grub_snprintf(name, sizeof(name), "mem:0x%llx:size:%llu", (ulonglong)(ulong)buf, (ulonglong)file->size); - grub_printf("<%s>\n", name); - } -} - - ventoy_plugin_dump_auto_install(); return 0; @@ -2267,6 +2278,32 @@ int ventoy_is_file_exist(const char *fmt, ...) return 0; } +int ventoy_is_dir_exist(const char *fmt, ...) +{ + va_list ap; + int len; + char *pos = NULL; + char buf[256] = {0}; + + grub_snprintf(buf, sizeof(buf), "%s", "[ -d "); + pos = buf + 5; + + va_start (ap, fmt); + len = grub_vsnprintf(pos, 255, fmt, ap); + va_end (ap); + + grub_strncpy(pos + len, " ]", 2); + + debug("script exec %s\n", buf); + + if (0 == grub_script_execute_sourcecode(buf)) + { + return 1; + } + + return 0; +} + static int ventoy_env_init(void) { char buf[64]; @@ -2285,6 +2322,7 @@ static int ventoy_env_init(void) if (g_grub_param) { g_grub_param->grub_env_get = grub_env_get; + g_grub_param->grub_env_printf = (grub_env_printf_pf)grub_printf; grub_snprintf(buf, sizeof(buf), "%p", g_grub_param); grub_env_set("env_param", buf); } diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h index 4717f094..169c56e9 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h @@ -460,6 +460,7 @@ int ventoy_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, co grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...); grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...); int ventoy_is_file_exist(const char *fmt, ...); +int ventoy_is_dir_exist(const char *fmt, ...); int ventoy_fill_data(grub_uint32_t buflen, char *buffer); grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args); grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args); @@ -600,6 +601,7 @@ typedef struct install_template int pathlen; char isopath[256]; + int autosel; int cursel; int templatenum; file_fullpath *templatepath; @@ -612,6 +614,7 @@ typedef struct persistence_config int pathlen; char isopath[256]; + int autosel; int cursel; int backendnum; file_fullpath *backendpath; @@ -619,8 +622,12 @@ typedef struct persistence_config struct persistence_config *next; }persistence_config; +#define vtoy_alias_image_file 0 +#define vtoy_alias_directory 1 + typedef struct menu_alias { + int type; int pathlen; char isopath[256]; char alias[256]; @@ -628,8 +635,12 @@ typedef struct menu_alias struct menu_alias *next; }menu_alias; +#define vtoy_class_image_file 0 +#define vtoy_class_directory 1 + typedef struct menu_class { + int type; int patlen; char pattern[256]; char class[64]; @@ -654,8 +665,8 @@ persistence_config * ventoy_plugin_find_persistent(const char *isopath); void ventoy_plugin_dump_auto_install(void); int ventoy_fill_windows_rtdata(void *buf, char *isopath); int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list); -const char * ventoy_plugin_get_menu_alias(const char *isopath); -const char * ventoy_plugin_get_menu_class(const char *isoname); +const char * ventoy_plugin_get_menu_alias(int type, const char *isopath); +const char * ventoy_plugin_get_menu_class(int type, const char *name); int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start); int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start); void ventoy_plugin_dump_persistence(void); diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c index ddd7499a..e8ec502a 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c @@ -1144,7 +1144,7 @@ grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, cha grub_memset(chain, 0, sizeof(ventoy_chain_head)); /* part 1: os parameter */ - g_ventoy_chain_type = 0; + g_ventoy_chain_type = ventoy_chain_linux; ventoy_fill_os_param(file, &(chain->os_param)); /* part 2: chain head */ diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c index 6bb4e9c0..c7fda9cf 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c @@ -310,11 +310,13 @@ static int ventoy_plugin_check_fullpath ( VTOY_JSON *json, const char *isodisk, - const char *key + const char *key, + int *pathnum ) { int rc = 0; int ret = 0; + int cnt = 0; VTOY_JSON *node = json; VTOY_JSON *child = NULL; @@ -334,6 +336,7 @@ static int ventoy_plugin_check_fullpath if (JSON_TYPE_STRING == node->enDataType) { + cnt = 1; ret = ventoy_plugin_check_path(isodisk, node->unData.pcStrVal); grub_printf("%s: %s [%s]\n", key, node->unData.pcStrVal, ret ? "FAIL" : "OK"); } @@ -350,10 +353,12 @@ static int ventoy_plugin_check_fullpath rc = ventoy_plugin_check_path(isodisk, child->unData.pcStrVal); grub_printf("%s: %s [%s]\n", key, child->unData.pcStrVal, rc ? "FAIL" : "OK"); ret += rc; + cnt++; } } } + *pathnum = cnt; return ret; } @@ -443,6 +448,8 @@ static int ventoy_plugin_parse_fullpath static int ventoy_plugin_auto_install_check(VTOY_JSON *json, const char *isodisk) { + int pathnum = 0; + int autosel = 0; const char *iso = NULL; VTOY_JSON *pNode = NULL; @@ -465,7 +472,19 @@ static int ventoy_plugin_auto_install_check(VTOY_JSON *json, const char *isodisk if (0 == ventoy_plugin_check_path(isodisk, iso)) { grub_printf("image: %s [OK]\n", iso); - ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "template"); + ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "template", &pathnum); + + if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel)) + { + if (autosel >= 0 && autosel <= pathnum) + { + grub_printf("autosel: %d [OK]\n", autosel); + } + else + { + grub_printf("autosel: %d [FAIL]\n", autosel); + } + } } else { @@ -484,6 +503,7 @@ static int ventoy_plugin_auto_install_check(VTOY_JSON *json, const char *isodisk static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk) { int pathnum = 0; + int autosel = 0; const char *iso = NULL; VTOY_JSON *pNode = NULL; install_template *node = NULL; @@ -522,6 +542,15 @@ static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk node->templatepath = templatepath; node->templatenum = pathnum; + node->autosel = -1; + if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel)) + { + if (autosel >= 0 && autosel <= pathnum) + { + node->autosel = autosel; + } + } + if (g_install_template_head) { node->next = g_install_template_head; @@ -538,6 +567,8 @@ static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk static int ventoy_plugin_persistence_check(VTOY_JSON *json, const char *isodisk) { + int autosel = 0; + int pathnum = 0; const char *iso = NULL; VTOY_JSON *pNode = NULL; @@ -560,7 +591,19 @@ static int ventoy_plugin_persistence_check(VTOY_JSON *json, const char *isodisk) if (0 == ventoy_plugin_check_path(isodisk, iso)) { grub_printf("image: %s [OK]\n", iso); - ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "backend"); + ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "backend", &pathnum); + + if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel)) + { + if (autosel >= 0 && autosel <= pathnum) + { + grub_printf("autosel: %d [OK]\n", autosel); + } + else + { + grub_printf("autosel: %d [FAIL]\n", autosel); + } + } } else { @@ -578,6 +621,7 @@ static int ventoy_plugin_persistence_check(VTOY_JSON *json, const char *isodisk) static int ventoy_plugin_persistence_entry(VTOY_JSON *json, const char *isodisk) { + int autosel = 0; int pathnum = 0; const char *iso = NULL; VTOY_JSON *pNode = NULL; @@ -619,6 +663,15 @@ static int ventoy_plugin_persistence_entry(VTOY_JSON *json, const char *isodisk) node->backendpath = backendpath; node->backendnum = pathnum; + node->autosel = -1; + if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel)) + { + if (autosel >= 0 && autosel <= pathnum) + { + node->autosel = autosel; + } + } + if (g_persistence_head) { node->next = g_persistence_head; @@ -635,7 +688,8 @@ static int ventoy_plugin_persistence_entry(VTOY_JSON *json, const char *isodisk) static int ventoy_plugin_menualias_check(VTOY_JSON *json, const char *isodisk) { - const char *iso = NULL; + int type; + const char *path = NULL; const char *alias = NULL; VTOY_JSON *pNode = NULL; @@ -649,17 +703,38 @@ static int ventoy_plugin_menualias_check(VTOY_JSON *json, const char *isodisk) for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) { - iso = vtoy_json_get_string_ex(pNode->pstChild, "image"); + type = vtoy_alias_image_file; + path = vtoy_json_get_string_ex(pNode->pstChild, "image"); + if (!path) + { + path = vtoy_json_get_string_ex(pNode->pstChild, "dir"); + type = vtoy_alias_directory; + } + alias = vtoy_json_get_string_ex(pNode->pstChild, "alias"); - if (iso && iso[0] == '/' && alias) + if (path && path[0] == '/' && alias) { - if (ventoy_is_file_exist("%s%s", isodisk, iso)) - { - grub_printf("image: <%s> [ OK ]\n", iso); + if (vtoy_alias_image_file == type) + { + if (ventoy_is_file_exist("%s%s", isodisk, path)) + { + grub_printf("image: <%s> [ OK ]\n", path); + } + else + { + grub_printf("image: <%s> [ NOT EXIST ]\n", path); + } } else { - grub_printf("image: <%s> [ NOT EXIST ]\n", iso); + if (ventoy_is_dir_exist("%s%s", isodisk, path)) + { + grub_printf("dir: <%s> [ OK ]\n", path); + } + else + { + grub_printf("dir: <%s> [ NOT EXIST ]\n", path); + } } grub_printf("alias: <%s>\n\n", alias); @@ -671,7 +746,8 @@ static int ventoy_plugin_menualias_check(VTOY_JSON *json, const char *isodisk) static int ventoy_plugin_menualias_entry(VTOY_JSON *json, const char *isodisk) { - const char *iso = NULL; + int type; + const char *path = NULL; const char *alias = NULL; VTOY_JSON *pNode = NULL; menu_alias *node = NULL; @@ -698,14 +774,22 @@ static int ventoy_plugin_menualias_entry(VTOY_JSON *json, const char *isodisk) for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) { - iso = vtoy_json_get_string_ex(pNode->pstChild, "image"); + type = vtoy_alias_image_file; + path = vtoy_json_get_string_ex(pNode->pstChild, "image"); + if (!path) + { + path = vtoy_json_get_string_ex(pNode->pstChild, "dir"); + type = vtoy_alias_directory; + } + alias = vtoy_json_get_string_ex(pNode->pstChild, "alias"); - if (iso && iso[0] == '/' && alias) + if (path && path[0] == '/' && alias) { node = grub_zalloc(sizeof(menu_alias)); if (node) { - node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso); + node->type = type; + node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path); grub_snprintf(node->alias, sizeof(node->alias), "%s", alias); if (g_menu_alias_head) @@ -723,6 +807,7 @@ static int ventoy_plugin_menualias_entry(VTOY_JSON *json, const char *isodisk) static int ventoy_plugin_menuclass_entry(VTOY_JSON *json, const char *isodisk) { + int type; const char *key = NULL; const char *class = NULL; VTOY_JSON *pNode = NULL; @@ -751,13 +836,21 @@ static int ventoy_plugin_menuclass_entry(VTOY_JSON *json, const char *isodisk) for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) { + type = vtoy_class_image_file; key = vtoy_json_get_string_ex(pNode->pstChild, "key"); + if (!key) + { + key = vtoy_json_get_string_ex(pNode->pstChild, "dir"); + type = vtoy_class_directory; + } + class = vtoy_json_get_string_ex(pNode->pstChild, "class"); if (key && class) { node = grub_zalloc(sizeof(menu_class)); if (node) { + node->type = type; node->patlen = grub_snprintf(node->pattern, sizeof(node->pattern), "%s", key); grub_snprintf(node->class, sizeof(node->class), "%s", class); @@ -779,6 +872,7 @@ static int ventoy_plugin_menuclass_entry(VTOY_JSON *json, const char *isodisk) static int ventoy_plugin_menuclass_check(VTOY_JSON *json, const char *isodisk) { + int type; const char *key = NULL; const char *class = NULL; VTOY_JSON *pNode = NULL; @@ -793,11 +887,18 @@ static int ventoy_plugin_menuclass_check(VTOY_JSON *json, const char *isodisk) for (pNode = json->pstChild; pNode; pNode = pNode->pstNext) { + type = vtoy_class_image_file; key = vtoy_json_get_string_ex(pNode->pstChild, "key"); + if (!key) + { + key = vtoy_json_get_string_ex(pNode->pstChild, "dir"); + type = vtoy_class_directory; + } + class = vtoy_json_get_string_ex(pNode->pstChild, "class"); if (key && class) { - grub_printf("key: <%s>\n", key); + grub_printf("%s: <%s>\n", (type == vtoy_class_directory) ? "dir" : "key", key); grub_printf("class: <%s>\n\n", class); } } @@ -901,7 +1002,7 @@ void ventoy_plugin_dump_auto_install(void) for (node = g_install_template_head; node; node = node->next) { - grub_printf("\nIMAGE:<%s>\n", node->isopath); + grub_printf("\nIMAGE:<%s> <%d>\n", node->isopath, node->templatenum); for (i = 0; i < node->templatenum; i++) { grub_printf("SCRIPT %d:<%s>\n", i, node->templatepath[i].path); @@ -920,7 +1021,7 @@ void ventoy_plugin_dump_persistence(void) for (node = g_persistence_head; node; node = node->next) { - grub_printf("\nIMAGE:<%s>\n", node->isopath); + grub_printf("\nIMAGE:<%s> <%d>\n", node->isopath, node->backendnum); for (i = 0; i < node->backendnum; i++) { @@ -1050,14 +1151,15 @@ end: return rc; } -const char * ventoy_plugin_get_menu_alias(const char *isopath) +const char * ventoy_plugin_get_menu_alias(int type, const char *isopath) { menu_alias *node = NULL; int len = (int)grub_strlen(isopath); - + for (node = g_menu_alias_head; node; node = node->next) { - if (node->pathlen == len && grub_strcmp(node->isopath, isopath) == 0) + if (node->type == type && node->pathlen && + node->pathlen == len && grub_strcmp(node->isopath, isopath) == 0) { return node->alias; } @@ -1066,23 +1168,35 @@ const char * ventoy_plugin_get_menu_alias(const char *isopath) return NULL; } -const char * ventoy_plugin_get_menu_class(const char *isoname) +const char * ventoy_plugin_get_menu_class(int type, const char *name) { menu_class *node = NULL; - int len = (int)grub_strlen(isoname); - - for (node = g_menu_class_head; node; node = node->next) + int len = (int)grub_strlen(name); + + if (vtoy_class_image_file == type) + { + for (node = g_menu_class_head; node; node = node->next) + { + if (node->type == type && node->patlen <= len && grub_strstr(name, node->pattern)) + { + return node->class; + } + } + } + else { - if (node->patlen <= len && grub_strstr(isoname, node->pattern)) + for (node = g_menu_class_head; node; node = node->next) { - return node->class; + if (node->type == type && node->patlen == len && grub_strncmp(name, node->pattern, len) == 0) + { + return node->class; + } } } return NULL; } - grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args) { int i = 0; diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c index 76975dbf..1100fd38 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c @@ -332,7 +332,7 @@ grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char * g_wim_patch_head = NULL; g_wim_total_patch_count = 0; g_wim_valid_patch_count = 0; - + return 0; } @@ -549,13 +549,9 @@ static wim_directory_entry * search_full_wim_dirent { subdir = (wim_directory_entry *)((char *)meta_data + search->subdir); search = search_wim_dirent(subdir, *path); - if (!search) - { - debug("%s search failed\n", *path); - } - path++; } + return search; } @@ -563,16 +559,18 @@ static wim_directory_entry * search_replace_wim_dirent(void *meta_data, wim_dire { wim_directory_entry *wim_dirent = NULL; const char *winpeshl_path[] = { "Windows", "System32", "winpeshl.exe", NULL }; - //const char *pecmd_path[] = { "Windows", "System32", "PECMD.exe", NULL }; + //const char *native_path[] = { "Windows", "System32", "native.exe", NULL }; wim_dirent = search_full_wim_dirent(meta_data, dir, winpeshl_path); + debug("search winpeshl.exe %p\n", wim_dirent); if (wim_dirent) { return wim_dirent; } - + #if 0 - wim_dirent = search_full_wim_dirent(meta_data, dir, pecmd_path); + wim_dirent = search_full_wim_dirent(meta_data, dir, native_path); + debug("search native.exe %p\n", wim_dirent); if (wim_dirent) { return wim_dirent; @@ -1385,7 +1383,7 @@ grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, c grub_memset(chain, 0, sizeof(ventoy_chain_head)); /* part 1: os parameter */ - g_ventoy_chain_type = 1; + g_ventoy_chain_type = ventoy_chain_windows; ventoy_fill_os_param(file, &(chain->os_param)); if (0 == unknown_image) @@ -1597,7 +1595,7 @@ grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char grub_memset(chain, 0, sizeof(ventoy_chain_head)); /* part 1: os parameter */ - g_ventoy_chain_type = 0; + g_ventoy_chain_type = ventoy_chain_wim; ventoy_fill_os_param(file, &(chain->os_param)); /* part 2: chain head */ diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h index 5b684b49..93365c73 100644 --- a/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h +++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h @@ -40,6 +40,15 @@ typedef enum ventoy_fs_type ventoy_fs_max }ventoy_fs_type; +typedef enum ventoy_chain_type +{ + ventoy_chain_linux = 0, /* 0: linux */ + ventoy_chain_windows, /* 1: windows */ + ventoy_chain_wim, /* 2: wim */ + + ventoy_chain_max +}ventoy_chain_type; + #pragma pack(1) typedef struct ventoy_guid @@ -109,7 +118,7 @@ typedef struct ventoy_os_param * * vtoy_reserved[0]: vtoy_break_level * vtoy_reserved[1]: vtoy_debug_level - * vtoy_reserved[2]: vtoy_chain_type 0:Linux 1:Windows + * vtoy_reserved[2]: vtoy_chain_type 0:Linux 1:Windows 2:wimfile * vtoy_reserved[3]: vtoy_iso_format 0:iso9660 1:udf * vtoy_reserved[4]: vtoy_windows_cd_prompt * @@ -204,12 +213,13 @@ typedef struct ventoy_img_chunk_list #define ventoy_filt_register grub_file_filter_register -typedef const char * (*grub_env_get_pf)(const char *name); - #pragma pack(1) #define GRUB_FILE_REPLACE_MAGIC 0x1258BEEF +typedef const char * (*grub_env_get_pf)(const char *name); +typedef int (*grub_env_printf_pf)(const char *fmt, ...); + typedef struct ventoy_grub_param_file_replace { grub_uint32_t magic; @@ -221,8 +231,8 @@ typedef struct ventoy_grub_param_file_replace typedef struct ventoy_grub_param { grub_env_get_pf grub_env_get; - ventoy_grub_param_file_replace file_replace; + grub_env_printf_pf grub_env_printf; }ventoy_grub_param; #pragma pack() diff --git a/GRUB2/MOD_SRC/grub-2.04/install.sh b/GRUB2/MOD_SRC/grub-2.04/install.sh index 1dc952af..8d9ba4cb 100644 --- a/GRUB2/MOD_SRC/grub-2.04/install.sh +++ b/GRUB2/MOD_SRC/grub-2.04/install.sh @@ -21,10 +21,10 @@ all_extra_modules="elf macho offsetio regexp file" if [ "$1" = "uefi" ]; then all_modules="$net_modules_uefi $all_modules_uefi $all_extra_modules" - grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi" --prefix '(,msdos2)/grub' --output "$VT_DIR/INSTALL/EFI/BOOT/grubx64_real.efi" --format 'x86_64-efi' --compression 'auto' $all_modules_uefi 'fat' 'part_msdos' + grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/x86_64-efi" --prefix '(,2)/grub' --output "$VT_DIR/INSTALL/EFI/BOOT/grubx64_real.efi" --format 'x86_64-efi' --compression 'auto' $all_modules_uefi 'fat' 'part_msdos' else all_modules="$net_modules_legacy $all_modules_legacy" - grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc" --prefix '(,msdos2)/grub' --output "$VT_DIR/INSTALL/grub/i386-pc/core.img" --format 'i386-pc' --compression 'auto' $all_modules_legacy 'fat' 'part_msdos' 'biosdisk' + grub-mkimage -v --directory "$VT_DIR/GRUB2/INSTALL/lib/grub/i386-pc" --prefix '(,2)/grub' --output "$VT_DIR/INSTALL/grub/i386-pc/core.img" --format 'i386-pc' --compression 'auto' $all_modules_legacy 'fat' 'part_msdos' 'biosdisk' fi grub-mknetdir --modules="$all_modules" --net-directory=$VT_DIR/GRUB2/PXE --subdir=grub2 --locales=en@quot || exit 1 diff --git a/INSTALL/grub/debug.cfg b/INSTALL/grub/debug.cfg index 0def325c..77f3dc5b 100644 --- a/INSTALL/grub/debug.cfg +++ b/INSTALL/grub/debug.cfg @@ -1,5 +1,5 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json { - menuentry 'Check global control plugin configuration' { + menuentry 'Check global control plugin configuration' --class=debug_control { set pager=1 vt_check_plugin_json $vt_plugin_path control $iso_path @@ -61,6 +61,22 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json { } } + +if [ "$grub_platform" != "pc" ]; then + submenu 'Ventoy UEFI Utilities' --class=debug_util { + menuentry 'Fixup Windows BlinitializeLibrary Failure' { + chainloader ${vtoy_path}/vtoyutil_x64.efi env_param=${env_param} ${vtdebug_flag} feature=fix_windows_mmap + boot + echo -e "\npress ENTER to exit ..." + read vtInputKey + } + + menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET { + echo 'Return ...' + } + } +fi + menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET { echo 'Return ...' } diff --git a/INSTALL/ventoy_pack.sh b/INSTALL/ventoy_pack.sh index b17feeff..1660a50b 100644 --- a/INSTALL/ventoy_pack.sh +++ b/INSTALL/ventoy_pack.sh @@ -104,7 +104,7 @@ cd $CurDir tar -czvf ventoy-${curver}-linux.tar.gz $tmpdir rm -f ventoy-${curver}-windows.zip -cp -a Ventoy2Disk.exe $tmpdir/ +cp -a Ventoy2Disk*.exe $tmpdir/ cp -a $LANG_DIR/languages.ini $tmpdir/ventoy/ rm -rf $tmpdir/tool rm -f $tmpdir/*.sh diff --git a/IPXE/ipxe_mod_code/ipxe-3fe683e/src/arch/x86/core/ventoy_vdisk.c b/IPXE/ipxe_mod_code/ipxe-3fe683e/src/arch/x86/core/ventoy_vdisk.c index d3ccb2b4..fcc0c0e2 100644 --- a/IPXE/ipxe_mod_code/ipxe-3fe683e/src/arch/x86/core/ventoy_vdisk.c +++ b/IPXE/ipxe_mod_code/ipxe-3fe683e/src/arch/x86/core/ventoy_vdisk.c @@ -574,7 +574,7 @@ int ventoy_boot_vdisk(void *data) g_os_param_reserved = (uint8_t *)(g_chain->os_param.vtoy_reserved); /* Workaround for Windows & ISO9660 */ - if (g_os_param_reserved[2] == 1 && g_os_param_reserved[3] == 0) + if (g_os_param_reserved[2] == ventoy_chain_windows && g_os_param_reserved[3] == 0) { g_fixup_iso9660_secover_enable = 1; } diff --git a/IPXE/ipxe_mod_code/ipxe-3fe683e/src/include/ventoy.h b/IPXE/ipxe_mod_code/ipxe-3fe683e/src/include/ventoy.h index 1898d7ac..286bb33c 100644 --- a/IPXE/ipxe_mod_code/ipxe-3fe683e/src/include/ventoy.h +++ b/IPXE/ipxe_mod_code/ipxe-3fe683e/src/include/ventoy.h @@ -13,6 +13,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define VENTOY_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }} +typedef enum ventoy_chain_type +{ + ventoy_chain_linux = 0, /* 0: linux */ + ventoy_chain_windows, /* 1: windows */ + ventoy_chain_wim, /* 2: wim */ + + ventoy_chain_max +}ventoy_chain_type; + #pragma pack(1) typedef struct ventoy_guid diff --git a/LANGUAGES/languages.ini b/LANGUAGES/languages.ini index b09f213b6732f46d137069a29e9f7218b2062635..926f47653e731905b45af22fec35469fed195d83 100644 GIT binary patch delta 4721 zcmbO>fpy9!)(t!?tVRrG47QUM1%+ds8GIOA85|jc7pRq8EhGX8A5>kcm{-A zJWwnY$ae;+4F*DpS_>R%-GJtKg3R5_%5t1T((K8Onfk3WEYe8c{6SmEw45OWs4fqvE*Wlv0z(*BtOTg95@7<6mBNt8P|T1$xm~Msa+(FJ&5Lm|7zT!Kc{sbplEAgUpg{x>1^^!NU%>zX delta 265 zcmbR8iFMip)(t!?n>$zz@J;S8li6$~I)`KWC22;b&FAFzu}{Ay%_y_^jK(AG%^hYs z++glxg&>yA>zr$Nfa>KoD+Rp(F=RF+hJfkKUim(}V3T_4xS)*Q90=pxoEC_hjMbkY zjDTJLcp!GToK%3aqOSjfShU&e=`5bf*XBrUzV-PTSpD{GOpHw&U=7>#cp1+@1V2eL z-r?E4LW{8o!WXb)?1Q*``zc38DTv@Le?|@n>qabN7B|S)?H1XLzqna=8Mqh#F$rb7 diff --git a/Ventoy2Disk/Ventoy2Disk/Language.h b/Ventoy2Disk/Ventoy2Disk/Language.h index 3623dc33..6705b86f 100644 --- a/Ventoy2Disk/Ventoy2Disk/Language.h +++ b/Ventoy2Disk/Ventoy2Disk/Language.h @@ -57,6 +57,10 @@ typedef enum STR_ID STR_PRESERVE_SPACE,//24 STR_SPACE_VAL_INVALID,//25 + STR_MENU_CLEAR, //26 + STR_CLEAR_SUCCESS, //27 + STR_CLEAR_FAILED, //28 + STR_ID_MAX }STR_ID; @@ -64,6 +68,7 @@ extern BOOL g_SecureBoot; #define VTOY_MENU_SECURE_BOOT 0xA000 #define VTOY_MENU_PART_CFG 0xA001 +#define VTOY_MENU_CLEAN 0xA002 #define VTOY_MENU_LANGUAGE_BEGIN 0xB000 diff --git a/Ventoy2Disk/Ventoy2Disk/PhyDrive.c b/Ventoy2Disk/Ventoy2Disk/PhyDrive.c index 07c168cd..7dde3154 100644 --- a/Ventoy2Disk/Ventoy2Disk/PhyDrive.c +++ b/Ventoy2Disk/Ventoy2Disk/PhyDrive.c @@ -1232,9 +1232,13 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes) Ret = f_mount(0, TEXT("0:"), 1); Log("umount part %d", Ret); + return 0; + } + else + { + Log("mount exfat failed %d", Ret); + return 1; } - - return 0; } else { @@ -1244,6 +1248,201 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes) } + +int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter) +{ + int i; + int rc = 0; + int state = 0; + HANDLE hDrive; + DWORD dwSize; + BOOL bRet; + CHAR MountDrive; + CHAR DriveName[] = "?:\\"; + CHAR DriveLetters[MAX_PATH] = { 0 }; + LARGE_INTEGER liCurrentPosition; + char *pTmpBuf = NULL; + MBR_HEAD MBR; + + *pDrvLetter = 0; + + Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>", + pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, + GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); + + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); + + Log("Lock disk for clean ............................. "); + + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to open physical disk"); + return 1; + } + + GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); + + if (DriveLetters[0] == 0) + { + Log("No drive letter was assigned..."); + DriveName[0] = GetFirstUnusedDriveLetter(); + Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]); + } + else + { + // Unmount all mounted volumes that belong to this drive + // Do it in reverse so that we always end on the first volume letter + for (i = (int)strlen(DriveLetters); i > 0; i--) + { + DriveName[0] = DriveLetters[i - 1]; + bRet = DeleteVolumeMountPointA(DriveName); + Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError()); + } + } + + MountDrive = DriveName[0]; + Log("Will use '%C:' as volume mountpoint", DriveName[0]); + + // It kind of blows, but we have to relinquish access to the physical drive + // for VDS to be able to delete the partitions that reside on it... + DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); + CHECK_CLOSE_HANDLE(hDrive); + + PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART); + + if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE)) + { + Log("Notice: Could not delete partitions: %u", GetLastError()); + } + + Log("Deleting all partitions ......................... OK"); + + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE); + + Log("Lock disk for write ............................. "); + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to GetPhysicalHandle for write."); + rc = 1; + goto End; + } + + // clear first and last 1MB space + pTmpBuf = malloc(SIZE_1MB); + if (!pTmpBuf) + { + Log("Failed to alloc memory."); + rc = 1; + goto End; + } + memset(pTmpBuf, 0, SIZE_1MB); + + SET_FILE_POS(512); + bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB - 512, &dwSize, NULL); + Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR); + if (!bRet) + { + rc = 1; + goto End; + } + + SET_FILE_POS(SIZE_1MB); + bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB, &dwSize, NULL); + Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR); + if (!bRet) + { + rc = 1; + goto End; + } + + SET_FILE_POS(0); + bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL); + Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR); + if (!bRet) + { + rc = 1; + goto End; + } + + //clear boot code and partition table (reserved disk signature) + memset(MBR.BootCode, 0, 440); + memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl)); + + VentoyFillLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl); + + MBR.PartTbl[0].Active = 0x80; // bootable + MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS + + SET_FILE_POS(0); + bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL); + Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR); + if (!bRet) + { + rc = 1; + goto End; + } + + Log("Clear Ventoy successfully finished"); + +End: + + PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME); + + if (pTmpBuf) + { + free(pTmpBuf); + } + + if (rc == 0) + { + Log("Mounting Ventoy Partition ....................... "); + Sleep(1000); + + state = 0; + memset(DriveLetters, 0, sizeof(DriveLetters)); + GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); + Log("Logical drive letter after write ventoy: <%s>", DriveLetters); + + for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++) + { + DriveName[0] = DriveLetters[i]; + Log("%s is ventoy part1, already mounted", DriveName); + state = 1; + } + + if (state != 1) + { + Log("need to mount ventoy part1..."); + if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE)) + { + DriveName[0] = MountDrive; + bRet = SetVolumeMountPointA(DriveName, DriveLetters); + Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError()); + + *pDrvLetter = MountDrive; + } + else + { + Log("Failed to find ventoy volume"); + } + } + + Log("OK\n"); + } + else + { + FindProcessOccupyDisk(hDrive, pPhyDrive); + } + + //Refresh Drive Layout + DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); + + CHECK_CLOSE_HANDLE(hDrive); + return rc; +} + int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive) { int i; @@ -1332,6 +1531,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive) Log("Formatting part1 exFAT ..."); if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes)) { + log("FormatPart1exFAT failed."); rc = 1; goto End; } @@ -1340,6 +1540,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive) Log("Writing part2 FAT img ..."); if (0 != FormatPart2Fat(hDrive, MBR.PartTbl[1].StartSectorId)) { + log("FormatPart2Fat failed."); rc = 1; goto End; } @@ -1348,11 +1549,11 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive) Log("Writting Boot Image ............................. "); if (WriteGrubStage1ToPhyDrive(hDrive) != 0) { + log("WriteGrubStage1ToPhyDrive failed."); rc = 1; goto End; } - PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE); Log("Writting Partition Table ........................ "); SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); @@ -1369,49 +1570,56 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive) DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); End: - CHECK_CLOSE_HANDLE(hDrive); PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME); - Log("Mounting Ventoy Partition ....................... "); - Sleep(1000); - - state = 0; - memset(DriveLetters, 0, sizeof(DriveLetters)); - GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); - Log("Logical drive letter after write ventoy: <%s>", DriveLetters); - for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++) + if (rc == 0) { - DriveName[0] = DriveLetters[i]; - if (IsVentoyLogicalDrive(DriveName[0])) + Log("Mounting Ventoy Partition ....................... "); + Sleep(1000); + + state = 0; + memset(DriveLetters, 0, sizeof(DriveLetters)); + GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); + Log("Logical drive letter after write ventoy: <%s>", DriveLetters); + + for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++) { - Log("%s is ventoy part2, delete mountpoint", DriveName); - DeleteVolumeMountPointA(DriveName); + DriveName[0] = DriveLetters[i]; + if (IsVentoyLogicalDrive(DriveName[0])) + { + Log("%s is ventoy part2, delete mountpoint", DriveName); + DeleteVolumeMountPointA(DriveName); + } + else + { + Log("%s is ventoy part1, already mounted", DriveName); + state = 1; + } } - else + + if (state != 1) { - Log("%s is ventoy part1, already mounted", DriveName); - state = 1; + Log("need to mount ventoy part1..."); + if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE)) + { + DriveName[0] = MountDrive; + bRet = SetVolumeMountPointA(DriveName, DriveLetters); + Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError()); + } + else + { + Log("Failed to find ventoy volume"); + } } + Log("OK\n"); } - - if (state != 1) + else { - Log("need to mount ventoy part1..."); - if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE)) - { - DriveName[0] = MountDrive; - bRet = SetVolumeMountPointA(DriveName, DriveLetters); - Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError()); - } - else - { - Log("Failed to find ventoy volume"); - } + FindProcessOccupyDisk(hDrive, pPhyDrive); } - Log("OK\n"); - + CHECK_CLOSE_HANDLE(hDrive); return rc; } @@ -1616,8 +1824,19 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive) DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); End: + + if (rc == 0) + { + Log("OK"); + } + else + { + FindProcessOccupyDisk(hDrive, pPhyDrive); + } + CHECK_CLOSE_HANDLE(hDrive); return rc; } + diff --git a/Ventoy2Disk/Ventoy2Disk/Utility.c b/Ventoy2Disk/Ventoy2Disk/Utility.c index 21b0245d..e7df557b 100644 --- a/Ventoy2Disk/Ventoy2Disk/Utility.c +++ b/Ventoy2Disk/Ventoy2Disk/Utility.c @@ -382,7 +382,7 @@ BOOL IsVentoyLogicalDrive(CHAR DriveLetter) } -static int VentoyFillLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table) +int VentoyFillLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table) { BYTE Head; BYTE Sector; diff --git a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c index f0ea679b..59ca86c0 100644 --- a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c +++ b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c @@ -276,6 +276,7 @@ int SortPhysicalDrive(PHY_DRIVE_INFO *pDriveList, DWORD DriveCount) int Ventoy2DiskInit(void) { + Log("\n===================== Enum All PhyDrives ====================="); g_PhyDriveList = (PHY_DRIVE_INFO *)malloc(sizeof(PHY_DRIVE_INFO)* VENTOY_MAX_PHY_DRIVE); if (NULL == g_PhyDriveList) { diff --git a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h index 26352ddf..13b71f76 100644 --- a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h +++ b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h @@ -161,5 +161,13 @@ int INIT unxz(unsigned char *in, int in_size, void disk_io_set_param(HANDLE Handle, UINT64 SectorCount); INT_PTR CALLBACK PartDialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam); int GetReservedSpaceInMB(void); +int FindProcessOccupyDisk(HANDLE hDrive, PHY_DRIVE_INFO *pPhyDrive); +int VentoyFillLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table); +int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter); + +#define SET_FILE_POS(pos) \ + liCurrentPosition.QuadPart = pos; \ + SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN)\ + #endif diff --git a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.rc b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.rc index 2df0e8afecd1299565f25bf76d6d73d1a560661d..43075fb6642c13a25e7891e363f7af9d5a73fea9 100644 GIT binary patch delta 303 zcmZ1!bRlFz3#XtbgA0QvLp%^WGx#(3F&It0s3JdEkJCoHh#{3BjR8a!Gh{I6F=R3% zGvqTUO=e_XJy}7BYqJSg7zd-}`M- zLk0^5gUKgF_VQaW=r9;D7y_{lgE7#ihcfz;kBE9P8c*gIYXz&8oV-pfiqUkkw1o9! z7jZwZj6P6IX|jN<#NCQ834`FVX&OMU&2}t| delta 177 zcmcZ*vM6Xn3+HAYE;dd^^T`jTyeG#A%Zd6jcry3_F^G<0aAj~}@MnmaoG+}rd5y3g zBct);*CLUuMhpfF#*;lo_wrjZ=r9;D7y>bfww%l_r$5<6%!|=za=%zBSheJ2J@F_; zlgYCstS284_XEr51I3gk+sR2xu91)f%e69^PF9p$&uaoU2WUEww%pt;)yXmWj-bS5 I9c2}E0I9(&@c;k- diff --git a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj index 4b9ccf82..f82d5fcf 100644 --- a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj +++ b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj @@ -106,6 +106,7 @@ + @@ -128,6 +129,7 @@ + @@ -135,6 +137,8 @@ + + diff --git a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj.filters b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj.filters index 8370af2c..9c74bea8 100644 --- a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj.filters +++ b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj.filters @@ -72,6 +72,9 @@ 源文件 + + 源文件 + @@ -128,6 +131,9 @@ 头文件 + + 头文件 + @@ -138,5 +144,11 @@ 资源文件 + + 资源文件 + + + 资源文件 + \ No newline at end of file diff --git a/Ventoy2Disk/Ventoy2Disk/WinDialog.c b/Ventoy2Disk/Ventoy2Disk/WinDialog.c index afceab56d468d262141043b0331c652b6ac250fe..42bda379646ec0cd006264f62b34c1e71f5fa502 100644 GIT binary patch delta 2250 zcmb_dUrdu%6u(_-_gM<5{A+<$zETQ^P!Np+=Bi?;XrN$0WYtUxt;#5E1!c342zyYY z(<#5`h|Xk*4=z3s=Jzy{Ii42d5~GRP115_alaW1a@Ukp>a69)>K5WEgS(Y!~_nmw1 zIp_Y)xxaJnQ&5KkBe`NO9?91fA()YcsdKk6-?$sIwPl(b?0IKL zx`*vz?QA=1V9l%%pLq*b@8A;6_z<35tcA!H^5hD)Y!2wmW61c1s5+%=r*s#y~0Bi;S9`t$zKT%6FRi@NpQ&$&X9eR zT)d1bt&#cOj7df4hbF%OFR$s<=qXan$(u1-Y$7NUYV5TtfHAut53ji}Z+GLVqXN^# z`G^#ilkCC$Vi|FZ1mC2dqnmI@VtDrYZc@)hmxHTulX`5+Gr?6^u_)_f$Jh>{)&P+!#y%$b7#k$Am9Zwa zj}q=7UL7GRit$l1ngU+j4FoW^#)#=&KmIfsomH%gbV4jlR$;OZ(7?+1{K?N}*CX@YmaPB0Nh$Hi#z!2ebCl7CZ+s0UM-j4YM#FrJE_ohBbU@(eB!qnJ6@d4Oyl8|h}mJ-4%tMR z1%?gi3a!OYCk;ppXRq#6@wLWwA~J5m)mRax3nWC%lF+&z%YQ{{A(q2)fT^>FjlJam zJ$nBSY}Eysh{wxC8|mz+#)EiBWwRe!kN%KsUSmTUxOyW04SM?$M^)~0_B7nEjA+Pf zE=DJ%oY(S8$d_7|WtCV(Fq~6aO5`XNnJc01N>*D$)TJ!IN-=)f%sX2p*AwSSHasUQ z*;UfK@Q#I$ZL!6eu;rp5W%J;_+&uB0HYe}2c^%cwGF+a7EVV<<+jZu4Y6e~+)*w+U zNK{K|b7HkDTXK3WYPJxidG&bc>!G^xQVRDHl{-X*y{gknROPx}vEGbF#d*noTaRB( zWh%Pk&)49=Itym3x+*_0{Sbi&vmxSl0|AK&uJy5A*1vMcYHTLhhiR>dIg*b|6&GV4 z5!h6Ja%$DkF7lF%xF$E>q@Mp3_4i8>Hs37cfBQdoP%3&naaM8cis5uQ-6B?fL9+Z) z%C<~xu^Z8Sno8}sguA0wJWUs}@?!MND&GHYOr6uDbdWrJacVcukFx1J-4px{-E^^D zEfgR2gq)7nWST_VS!rJu!q*A2lDIURa?y2s?n>wVuSN7n>YdnrxfEBg94Jjq-0KG+ QE)4Rjxw2mAn%rjk8{X((LjV8( delta 321 zcmW;Gy-NZC9L90fx*V?S5|Jo4^*GHOgfxUhghPwq5DgL0)F03k(c$#K=es=pBgaY4Zay&d#dJL|QXFE!0es$D zB>h!rMi_e{3#qvbMJ&MJoHjpt;#}*TL;BbSdB%;X5CJcxp+B)`v{+On1!i8ryOe?) z5bzrGU^@_kZ#o9eI|(yX!No@0@ +* Copyright © 2017 dmex +* Copyright © 2009-2016 wj32 +* Copyright (c) 2020, 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 "resource.h" +#include "Language.h" +#include "Ventoy2Disk.h" +#include "fat_filelib.h" +#include "ff.h" +#include "process.h" +#include + + +OPENED_LIBRARIES_VARS; + +STATIC WCHAR *_wHandleName = NULL; +static PVOID PhHeapHandle = NULL; + + +/* +* Convert an NT Status to an error message +* +* \param Status An operattonal status. +* +* \return An error message string. +* +*/ +char* NtStatusError(NTSTATUS Status) { + static char unknown[32]; + + switch (Status) { + case STATUS_SUCCESS: + return "Operation Successful"; + case STATUS_UNSUCCESSFUL: + return "Operation Failed"; + case STATUS_BUFFER_OVERFLOW: + return "Buffer Overflow"; + case STATUS_NOT_IMPLEMENTED: + return "Not Implemented"; + case STATUS_INFO_LENGTH_MISMATCH: + return "Info Length Mismatch"; + case STATUS_INVALID_HANDLE: + return "Invalid Handle."; + case STATUS_INVALID_PARAMETER: + return "Invalid Parameter"; + case STATUS_NO_MEMORY: + return "Not Enough Quota"; + case STATUS_ACCESS_DENIED: + return "Access Denied"; + case STATUS_BUFFER_TOO_SMALL: + return "Buffer Too Small"; + case STATUS_OBJECT_TYPE_MISMATCH: + return "Wrong Type"; + case STATUS_OBJECT_NAME_INVALID: + return "Object Name Invalid"; + case STATUS_OBJECT_NAME_NOT_FOUND: + return "Object Name not found"; + case STATUS_OBJECT_PATH_INVALID: + return "Object Path Invalid"; + case STATUS_SHARING_VIOLATION: + return "Sharing Violation"; + case STATUS_INSUFFICIENT_RESOURCES: + return "Insufficient resources"; + case STATUS_NOT_SUPPORTED: + return "Operation is not supported"; + default: + safe_sprintf(unknown, "Unknown error 0x%08lx", Status); + return unknown; + } +} + + +static NTSTATUS PhCreateHeap(VOID) +{ + NTSTATUS status = STATUS_SUCCESS; + + if (PhHeapHandle != NULL) + return STATUS_ALREADY_COMPLETE; + + PF_INIT_OR_SET_STATUS(RtlCreateHeap, Ntdll); + + if (NT_SUCCESS(status)) { + PhHeapHandle = pfRtlCreateHeap(HEAP_NO_SERIALIZE | HEAP_GROWABLE, NULL, 2 * MB, 1 * MB, NULL, NULL); + if (PhHeapHandle == NULL) + status = STATUS_UNSUCCESSFUL; + } + + return status; +} + +static NTSTATUS PhDestroyHeap(VOID) +{ + NTSTATUS status = STATUS_SUCCESS; + + if (PhHeapHandle == NULL) + return STATUS_ALREADY_COMPLETE; + + PF_INIT_OR_SET_STATUS(RtlDestroyHeap, Ntdll); + + if (NT_SUCCESS(status)) { + if (pfRtlDestroyHeap(PhHeapHandle) == NULL) { + PhHeapHandle = NULL; + } + else { + status = STATUS_UNSUCCESSFUL; + } + } + + return status; +} + +/** +* Allocates a block of memory. +* +* \param Size The number of bytes to allocate. +* +* \return A pointer to the allocated block of memory. +* +*/ +static PVOID PhAllocate(SIZE_T Size) +{ + PF_INIT(RtlAllocateHeap, Ntdll); + if (pfRtlAllocateHeap == NULL) + return NULL; + + return pfRtlAllocateHeap(PhHeapHandle, 0, Size); +} + +/** +* Frees a block of memory allocated with PhAllocate(). +* +* \param Memory A pointer to a block of memory. +* +*/ +static VOID PhFree(PVOID Memory) +{ + PF_INIT(RtlFreeHeap, Ntdll); + + if (pfRtlFreeHeap != NULL) + pfRtlFreeHeap(PhHeapHandle, 0, Memory); +} + +/** +* Enumerates all open handles. +* +* \param Handles A variable which receives a pointer to a structure containing information about +* all opened handles. You must free the structure using PhFree() when you no longer need it. +* +* \return An NTStatus indicating success or the error code. +*/ +NTSTATUS PhEnumHandlesEx(PSYSTEM_HANDLE_INFORMATION_EX *Handles) +{ + static ULONG initialBufferSize = 0x10000; + NTSTATUS status = STATUS_SUCCESS; + PVOID buffer; + ULONG bufferSize; + + PF_INIT_OR_SET_STATUS(NtQuerySystemInformation, Ntdll); + if (!NT_SUCCESS(status)) + return status; + + bufferSize = initialBufferSize; + buffer = PhAllocate(bufferSize); + if (buffer == NULL) + return STATUS_NO_MEMORY; + + while ((status = pfNtQuerySystemInformation(SystemExtendedHandleInformation, + buffer, bufferSize, NULL)) == STATUS_INFO_LENGTH_MISMATCH) { + PhFree(buffer); + bufferSize *= 2; + + // Fail if we're resizing the buffer to something very large. + if (bufferSize > PH_LARGE_BUFFER_SIZE) + return STATUS_INSUFFICIENT_RESOURCES; + + buffer = PhAllocate(bufferSize); + if (buffer == NULL) + return STATUS_NO_MEMORY; + } + + if (!NT_SUCCESS(status)) { + PhFree(buffer); + return status; + } + + if (bufferSize <= 0x200000) + initialBufferSize = bufferSize; + *Handles = (PSYSTEM_HANDLE_INFORMATION_EX)buffer; + + return status; +} + +/** +* Opens a process. +* +* \param ProcessHandle A variable which receives a handle to the process. +* \param DesiredAccess The desired access to the process. +* \param ProcessId The ID of the process. +* +* \return An NTStatus indicating success or the error code. +*/ +NTSTATUS PhOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, HANDLE ProcessId) +{ + NTSTATUS status = STATUS_SUCCESS; + OBJECT_ATTRIBUTES objectAttributes; + CLIENT_ID clientId; + + if ((LONG_PTR)ProcessId == (LONG_PTR)GetCurrentProcessId()) { + *ProcessHandle = NtCurrentProcess(); + return 0; + } + + PF_INIT_OR_SET_STATUS(NtOpenProcess, Ntdll); + if (!NT_SUCCESS(status)) + return status; + + clientId.UniqueProcess = ProcessId; + clientId.UniqueThread = NULL; + + InitializeObjectAttributes(&objectAttributes, NULL, 0, NULL, NULL); + status = pfNtOpenProcess(ProcessHandle, DesiredAccess, &objectAttributes, &clientId); + + return status; +} + +/** +* Query processes with open handles to a file, volume or disk. +* +* \param VolumeOrFileHandle The handle to the target. +* \param Information The returned list of processes. +* +* \return An NTStatus indicating success or the error code. +*/ +NTSTATUS PhQueryProcessesUsingVolumeOrFile(HANDLE VolumeOrFileHandle, + PFILE_PROCESS_IDS_USING_FILE_INFORMATION *Information) +{ + static ULONG initialBufferSize = 16 * KB; + NTSTATUS status = STATUS_SUCCESS; + PVOID buffer; + ULONG bufferSize; + IO_STATUS_BLOCK isb; + + PF_INIT_OR_SET_STATUS(NtQueryInformationFile, NtDll); + if (!NT_SUCCESS(status)) + return status; + + bufferSize = initialBufferSize; + buffer = PhAllocate(bufferSize); + if (buffer == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + while ((status = pfNtQueryInformationFile(VolumeOrFileHandle, &isb, buffer, bufferSize, + FileProcessIdsUsingFileInformation)) == STATUS_INFO_LENGTH_MISMATCH) { + PhFree(buffer); + bufferSize *= 2; + // Fail if we're resizing the buffer to something very large. + if (bufferSize > 64 * MB) + return STATUS_INSUFFICIENT_RESOURCES; + buffer = PhAllocate(bufferSize); + } + + if (!NT_SUCCESS(status)) { + PhFree(buffer); + return status; + } + + if (bufferSize <= 64 * MB) + initialBufferSize = bufferSize; + *Information = (PFILE_PROCESS_IDS_USING_FILE_INFORMATION)buffer; + + return status; +} + +/** +* Query the full commandline that was used to create a process. +* This can be helpful to differentiate between service instances (svchost.exe). +* Taken from: https://stackoverflow.com/a/14012919/1069307 +* +* \param hProcess A handle to a process. +* +* \return A Unicode commandline string, or NULL on error. +* The returned string must be freed by the caller. +*/ +static PWSTR GetProcessCommandLine(HANDLE hProcess) +{ + PWSTR wcmdline = NULL; + BOOL wow; + DWORD pp_offset, cmd_offset; + NTSTATUS status = STATUS_SUCCESS; + SYSTEM_INFO si; + PBYTE peb = NULL, pp = NULL; + + // Determine if 64 or 32-bit processor + GetNativeSystemInfo(&si); + if ((si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) || (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64)) { + pp_offset = 0x20; + cmd_offset = 0x70; + } + else { + pp_offset = 0x10; + cmd_offset = 0x40; + } + + // PEB and Process Parameters (we only need the beginning of these structs) + peb = (PBYTE)calloc(pp_offset + 8, 1); + if (peb == NULL) + goto out; + pp = (PBYTE)calloc(cmd_offset + 16, 1); + if (pp == NULL) + goto out; + + IsWow64Process(GetCurrentProcess(), &wow); + if (wow) { + // 32-bit process running on a 64-bit OS + PROCESS_BASIC_INFORMATION_WOW64 pbi = { 0 }; + ULONGLONG params; + UNICODE_STRING_WOW64* ucmdline; + + PF_INIT_OR_OUT(NtWow64QueryInformationProcess64, NtDll); + PF_INIT_OR_OUT(NtWow64ReadVirtualMemory64, NtDll); + + status = pfNtWow64QueryInformationProcess64(hProcess, 0, &pbi, sizeof(pbi), NULL); + if (!NT_SUCCESS(status)) + goto out; + + status = pfNtWow64ReadVirtualMemory64(hProcess, pbi.PebBaseAddress, peb, pp_offset + 8, NULL); + if (!NT_SUCCESS(status)) + goto out; + + // Read Process Parameters from the 64-bit address space + params = (ULONGLONG)*((ULONGLONG*)(peb + pp_offset)); + status = pfNtWow64ReadVirtualMemory64(hProcess, params, pp, cmd_offset + 16, NULL); + if (!NT_SUCCESS(status)) + goto out; + + ucmdline = (UNICODE_STRING_WOW64*)(pp + cmd_offset); + wcmdline = (PWSTR)calloc(ucmdline->Length + 1, sizeof(WCHAR)); + if (wcmdline == NULL) + goto out; + status = pfNtWow64ReadVirtualMemory64(hProcess, ucmdline->Buffer, wcmdline, ucmdline->Length, NULL); + if (!NT_SUCCESS(status)) { + safe_free(wcmdline); + goto out; + } + } + else { + // 32-bit process on a 32-bit OS, or 64-bit process on a 64-bit OS + PROCESS_BASIC_INFORMATION pbi = { 0 }; + PBYTE* params; + UNICODE_STRING* ucmdline; + + PF_INIT_OR_OUT(NtQueryInformationProcess, NtDll); + + status = pfNtQueryInformationProcess(hProcess, 0, &pbi, sizeof(pbi), NULL); + if (!NT_SUCCESS(status)) + goto out; + + // Read PEB + if (!ReadProcessMemory(hProcess, pbi.PebBaseAddress, peb, pp_offset + 8, NULL)) + goto out; + + // Read Process Parameters + params = (PBYTE*)*(LPVOID*)(peb + pp_offset); + if (!ReadProcessMemory(hProcess, params, pp, cmd_offset + 16, NULL)) + goto out; + + ucmdline = (UNICODE_STRING*)(pp + cmd_offset); + // In the absolute, someone could craft a process with dodgy attributes to try to cause an overflow + ucmdline->Length = min(ucmdline->Length, 512); + wcmdline = (PWSTR)calloc(ucmdline->Length + 1, sizeof(WCHAR)); + if (!ReadProcessMemory(hProcess, ucmdline->Buffer, wcmdline, ucmdline->Length, NULL)) { + safe_free(wcmdline); + goto out; + } + } + +out: + free(peb); + free(pp); + return wcmdline; +} + + +static int GetDevicePathName(PHY_DRIVE_INFO *pPhyDrive, WCHAR *wDevPath) +{ + int i; + CHAR PhyDrive[128]; + CHAR DevPath[MAX_PATH] = { 0 }; + + safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", pPhyDrive->PhyDrive); + + if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath))) + { + Log("QueryDosDeviceA failed error:%u", GetLastError()); + strcpy_s(DevPath, sizeof(DevPath), "???"); + } + else + { + Log("QueryDosDeviceA success %s", DevPath); + } + + for (i = 0; DevPath[i] && i < MAX_PATH; i++) + { + wDevPath[i] = DevPath[i]; + } + + return 0; +} + + +static __inline DWORD GetModuleFileNameExU(HANDLE hProcess, HMODULE hModule, char* lpFilename, DWORD nSize) +{ + DWORD ret = 0, err = ERROR_INVALID_DATA; + // coverity[returned_null] + walloc(lpFilename, nSize); + ret = GetModuleFileNameExW(hProcess, hModule, wlpFilename, nSize); + err = GetLastError(); + if ((ret != 0) + && ((ret = wchar_to_utf8_no_alloc(wlpFilename, lpFilename, nSize)) == 0)) { + err = GetLastError(); + } + wfree(lpFilename); + SetLastError(err); + return ret; +} + +int FindProcessOccupyDisk(HANDLE hDrive, PHY_DRIVE_INFO *pPhyDrive) +{ + WCHAR wDevPath[MAX_PATH] = { 0 }; + const char *access_rights_str[8] = { "n", "r", "w", "rw", "x", "rx", "wx", "rwx" }; + NTSTATUS status = STATUS_SUCCESS; + PSYSTEM_HANDLE_INFORMATION_EX handles = NULL; + POBJECT_NAME_INFORMATION buffer = NULL; + ULONG_PTR i; + ULONG_PTR pid[2]; + ULONG_PTR last_access_denied_pid = 0; + ULONG bufferSize; + USHORT wHandleNameLen; + HANDLE dupHandle = NULL; + HANDLE processHandle = NULL; + BOOLEAN bFound = FALSE, bGotCmdLine, verbose = TRUE; + ULONG access_rights = 0; + DWORD size; + char cmdline[MAX_PATH] = { 0 }; + wchar_t wexe_path[MAX_PATH], *wcmdline; + int cur_pid; + + + Log("FindProcessOccupyDisk for PhyDrive %d", pPhyDrive->PhyDrive); + + GetDevicePathName(pPhyDrive, wDevPath); + _wHandleName = wDevPath; + + + PF_INIT_OR_SET_STATUS(NtQueryObject, Ntdll); + PF_INIT_OR_SET_STATUS(NtDuplicateObject, NtDll); + PF_INIT_OR_SET_STATUS(NtClose, NtDll); + + if (NT_SUCCESS(status)) + status = PhCreateHeap(); + + if (NT_SUCCESS(status)) + status = PhEnumHandlesEx(&handles); + + if (!NT_SUCCESS(status)) { + Log("Warning: Could not enumerate process handles: %s", NtStatusError(status)); + goto out; + } + + pid[0] = (ULONG_PTR)0; + cur_pid = 1; + + wHandleNameLen = (USHORT)wcslen(_wHandleName); + + bufferSize = 0x200; + buffer = PhAllocate(bufferSize); + if (buffer == NULL) + goto out; + + for (i = 0;; i++) { + ULONG attempts = 8; + PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo = + (i < handles->NumberOfHandles) ? &handles->Handles[i] : NULL; + + if ((dupHandle != NULL) && (processHandle != NtCurrentProcess())) { + pfNtClose(dupHandle); + dupHandle = NULL; + } + + // Update the current handle's process PID and compare against last + // Note: Be careful about not trying to overflow our list! + pid[cur_pid] = (handleInfo != NULL) ? handleInfo->UniqueProcessId : -1; + + if (pid[0] != pid[1]) { + cur_pid = (cur_pid + 1) % 2; + + // If we're switching process and found a match, print it + if (bFound) { + Log("* [%06u] %s (%s)", (UINT32)pid[cur_pid], cmdline, access_rights_str[access_rights & 0x7]); + bFound = FALSE; + access_rights = 0; + } + + // Close the previous handle + if (processHandle != NULL) { + if (processHandle != NtCurrentProcess()) + pfNtClose(processHandle); + processHandle = NULL; + } + } + + // Exit loop condition + if (i >= handles->NumberOfHandles) + break; + + // Don't bother with processes we can't access + if (handleInfo->UniqueProcessId == last_access_denied_pid) + continue; + + // Filter out handles that aren't opened with Read (bit 0), Write (bit 1) or Execute (bit 5) access + if ((handleInfo->GrantedAccess & 0x23) == 0) + continue; + + // Open the process to which the handle we are after belongs, if not already opened + if (pid[0] != pid[1]) { + status = PhOpenProcess(&processHandle, PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + (HANDLE)handleInfo->UniqueProcessId); + // There exists some processes we can't access + if (!NT_SUCCESS(status)) { + //Log("SearchProcess: Could not open process %ld: %s", + // handleInfo->UniqueProcessId, NtStatusError(status)); + processHandle = NULL; + if (status == STATUS_ACCESS_DENIED) { + last_access_denied_pid = handleInfo->UniqueProcessId; + } + continue; + } + } + + // Now duplicate this handle onto our own process, so that we can access its properties + if (processHandle == NtCurrentProcess()) { + continue; + } + else { + status = pfNtDuplicateObject(processHandle, (HANDLE)handleInfo->HandleValue, + NtCurrentProcess(), &dupHandle, 0, 0, 0); + if (!NT_SUCCESS(status)) + continue; + } + + // Filter non-storage handles. We're not interested in them and they make NtQueryObject() freeze + if (GetFileType(dupHandle) != FILE_TYPE_DISK) + continue; + + // A loop is needed because the I/O subsystem likes to give us the wrong return lengths... + do { + ULONG returnSize; + // TODO: We might potentially still need a timeout on ObjectName queries, as PH does... + status = pfNtQueryObject(dupHandle, ObjectNameInformation, buffer, bufferSize, &returnSize); + if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH || + status == STATUS_BUFFER_TOO_SMALL) { + Log("SearchProcess: Realloc from %d to %d", bufferSize, returnSize); + bufferSize = returnSize; + PhFree(buffer); + buffer = PhAllocate(bufferSize); + } + else { + break; + } + } while (--attempts); + if (!NT_SUCCESS(status)) { + Log("SearchProcess: NtQueryObject failed for handle %X of process %ld: %s", + handleInfo->HandleValue, handleInfo->UniqueProcessId, NtStatusError(status)); + continue; + } + + // we are looking for a partial match and the current length is smaller + if (wHandleNameLen > buffer->Name.Length) + continue; + + // Match against our target string + if (wcsncmp(_wHandleName, buffer->Name.Buffer, wHandleNameLen) != 0) + continue; + + // If we are here, we have a process accessing our target! + bFound = TRUE; + + // Keep a mask of all the access rights being used + access_rights |= handleInfo->GrantedAccess; + // The Executable bit is in a place we don't like => reposition it + if (access_rights & 0x20) + access_rights = (access_rights & 0x03) | 0x04; + + // If this is the very first process we find, print a header + if (cmdline[0] == 0) + Log("WARNING: The following process(es) or service(s) are accessing %S:", _wHandleName); + + // Where possible, try to get the full command line + bGotCmdLine = FALSE; + size = MAX_PATH; + wcmdline = GetProcessCommandLine(processHandle); + if (wcmdline != NULL) { + bGotCmdLine = TRUE; + wchar_to_utf8_no_alloc(wcmdline, cmdline, sizeof(cmdline)); + free(wcmdline); + } + + // If we couldn't get the full commandline, try to get the executable path + if (!bGotCmdLine) + bGotCmdLine = (GetModuleFileNameExU(processHandle, 0, cmdline, MAX_PATH - 1) != 0); + + // The above may not work on Windows 7, so try QueryFullProcessImageName (Vista or later) + if (!bGotCmdLine) { + bGotCmdLine = QueryFullProcessImageNameW(processHandle, 0, wexe_path, &size); + if (bGotCmdLine) + wchar_to_utf8_no_alloc(wexe_path, cmdline, sizeof(cmdline)); + } + + // Still nothing? Try GetProcessImageFileName. Note that GetProcessImageFileName uses + // '\Device\Harddisk#\Partition#\' instead drive letters + if (!bGotCmdLine) { + bGotCmdLine = (GetProcessImageFileNameW(processHandle, wexe_path, MAX_PATH) != 0); + if (bGotCmdLine) + wchar_to_utf8_no_alloc(wexe_path, cmdline, sizeof(cmdline)); + } + + // Complete failure => Just craft a default process name that includes the PID + if (!bGotCmdLine) { + safe_sprintf(cmdline, "Unknown_Process_0x%llx", (ULONGLONG)handleInfo->UniqueProcessId); + } + } + +out: + if (cmdline[0] != 0) + Log("You should close these applications before attempting to reformat the drive."); + else + Log("NOTE: Could not identify the process(es) or service(s) accessing %S", _wHandleName); + + PhFree(buffer); + PhFree(handles); + PhDestroyHeap(); + + return 0; +} + diff --git a/Ventoy2Disk/Ventoy2Disk/process.h b/Ventoy2Disk/Ventoy2Disk/process.h new file mode 100644 index 00000000..39ebe404 --- /dev/null +++ b/Ventoy2Disk/Ventoy2Disk/process.h @@ -0,0 +1,405 @@ +/* +* Rufus: The Reliable USB Formatting Utility +* Process search functionality +* +* Modified from Process Hacker: +* https://github.com/processhacker2/processhacker2/ +* Copyright © 2017-2019 Pete Batard +* Copyright © 2017 dmex +* Copyright © 2009-2016 wj32 +* Copyright (c) 2020, 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 + +#pragma once + +#define PH_LARGE_BUFFER_SIZE (256 * 1024 * 1024) + +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +#define STATUS_ALREADY_COMPLETE ((NTSTATUS)0x000000FFL) +#define STATUS_UNSUCCESSFUL ((NTSTATUS)0x80000001L) +#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L) +#define STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) +//#define STATUS_INVALID_HANDLE ((NTSTATUS)0xC0000008L) +#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) +#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L) +#define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS)0xC0000024L) +#define STATUS_OBJECT_NAME_INVALID ((NTSTATUS)0xC0000033L) +#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L) +#define STATUS_OBJECT_PATH_INVALID ((NTSTATUS)0xC0000039L) +#define STATUS_SHARING_VIOLATION ((NTSTATUS)0xC0000043L) +#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009AL) +#define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BBL) + +#define SystemExtendedHandleInformation 64 +#define FileProcessIdsUsingFileInformation 47 + +// MinGW doesn't know this one yet +#if !defined(PROCESSOR_ARCHITECTURE_ARM64) +#define PROCESSOR_ARCHITECTURE_ARM64 12 +#endif + +#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1) + +typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX +{ + PVOID Object; + ULONG_PTR UniqueProcessId; + ULONG_PTR HandleValue; + ULONG GrantedAccess; + USHORT CreatorBackTraceIndex; + USHORT ObjectTypeIndex; + ULONG HandleAttributes; + ULONG Reserved; +} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; + +typedef struct _SYSTEM_HANDLE_INFORMATION_EX +{ + ULONG_PTR NumberOfHandles; + ULONG_PTR Reserved; + SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1]; +} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; + +#if defined(_MSC_VER) +typedef struct _OBJECT_NAME_INFORMATION +{ + UNICODE_STRING Name; +} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; + +typedef struct _OBJECT_TYPE_INFORMATION +{ + UNICODE_STRING TypeName; + ULONG TotalNumberOfObjects; + ULONG TotalNumberOfHandles; + ULONG TotalPagedPoolUsage; + ULONG TotalNonPagedPoolUsage; + ULONG TotalNamePoolUsage; + ULONG TotalHandleTableUsage; + ULONG HighWaterNumberOfObjects; + ULONG HighWaterNumberOfHandles; + ULONG HighWaterPagedPoolUsage; + ULONG HighWaterNonPagedPoolUsage; + ULONG HighWaterNamePoolUsage; + ULONG HighWaterHandleTableUsage; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccessMask; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; + UCHAR TypeIndex; // since WINBLUE + CHAR ReservedByte; + ULONG PoolType; + ULONG DefaultPagedPoolCharge; + ULONG DefaultNonPagedPoolCharge; +} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; + +#define ObjectNameInformation 1 +#endif +#define ObjectTypesInformation 3 + +typedef struct _OBJECT_TYPES_INFORMATION +{ + ULONG NumberOfTypes; +} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION; + +typedef struct _PROCESS_BASIC_INFORMATION_WOW64 +{ + PVOID Reserved1[2]; + // MinGW32 screws us with a sizeof(PVOID64) of 4 instead of 8 => Use ULONGLONG instead + ULONGLONG PebBaseAddress; + PVOID Reserved2[4]; + ULONG_PTR UniqueProcessId[2]; + PVOID Reserved3[2]; +} PROCESS_BASIC_INFORMATION_WOW64; + +typedef struct _UNICODE_STRING_WOW64 +{ + USHORT Length; + USHORT MaximumLength; + ULONGLONG Buffer; +} UNICODE_STRING_WOW64; + +typedef struct _FILE_PROCESS_IDS_USING_FILE_INFORMATION +{ + ULONG NumberOfProcessIdsInList; + ULONG_PTR ProcessIdList[1]; +} FILE_PROCESS_IDS_USING_FILE_INFORMATION, *PFILE_PROCESS_IDS_USING_FILE_INFORMATION; + +#define ALIGN_UP_BY(Address, Align) (((ULONG_PTR)(Address) + (Align) - 1) & ~((Align) - 1)) +#define ALIGN_UP(Address, Type) ALIGN_UP_BY(Address, sizeof(Type)) + +#define PH_FIRST_OBJECT_TYPE(ObjectTypes) \ + (POBJECT_TYPE_INFORMATION)((PCHAR)(ObjectTypes)+ALIGN_UP(sizeof(OBJECT_TYPES_INFORMATION), ULONG_PTR)) + +#define PH_NEXT_OBJECT_TYPE(ObjectType) \ + (POBJECT_TYPE_INFORMATION)((PCHAR)(ObjectType)+sizeof(OBJECT_TYPE_INFORMATION)+\ + ALIGN_UP(ObjectType->TypeName.MaximumLength, ULONG_PTR)) + +// Heaps + +typedef struct _RTL_HEAP_ENTRY +{ + SIZE_T Size; + USHORT Flags; + USHORT AllocatorBackTraceIndex; + union + { + struct + { + SIZE_T Settable; + ULONG Tag; + } s1; + struct + { + SIZE_T CommittedSize; + PVOID FirstBlock; + } s2; + } u; +} RTL_HEAP_ENTRY, *PRTL_HEAP_ENTRY; + +#define RTL_HEAP_BUSY (USHORT)0x0001 +#define RTL_HEAP_SEGMENT (USHORT)0x0002 +#define RTL_HEAP_SETTABLE_VALUE (USHORT)0x0010 +#define RTL_HEAP_SETTABLE_FLAG1 (USHORT)0x0020 +#define RTL_HEAP_SETTABLE_FLAG2 (USHORT)0x0040 +#define RTL_HEAP_SETTABLE_FLAG3 (USHORT)0x0080 +#define RTL_HEAP_SETTABLE_FLAGS (USHORT)0x00e0 +#define RTL_HEAP_UNCOMMITTED_RANGE (USHORT)0x0100 +#define RTL_HEAP_PROTECTED_ENTRY (USHORT)0x0200 + +typedef struct _RTL_HEAP_TAG +{ + ULONG NumberOfAllocations; + ULONG NumberOfFrees; + SIZE_T BytesAllocated; + USHORT TagIndex; + USHORT CreatorBackTraceIndex; + WCHAR TagName[24]; +} RTL_HEAP_TAG, *PRTL_HEAP_TAG; + +typedef struct _RTL_HEAP_INFORMATION +{ + PVOID BaseAddress; + ULONG Flags; + USHORT EntryOverhead; + USHORT CreatorBackTraceIndex; + SIZE_T BytesAllocated; + SIZE_T BytesCommitted; + ULONG NumberOfTags; + ULONG NumberOfEntries; + ULONG NumberOfPseudoTags; + ULONG PseudoTagGranularity; + ULONG Reserved[5]; + PRTL_HEAP_TAG Tags; + PRTL_HEAP_ENTRY Entries; +} RTL_HEAP_INFORMATION, *PRTL_HEAP_INFORMATION; + +typedef struct _RTL_PROCESS_HEAPS +{ + ULONG NumberOfHeaps; + RTL_HEAP_INFORMATION Heaps[1]; +} RTL_PROCESS_HEAPS, *PRTL_PROCESS_HEAPS; + +typedef NTSTATUS(NTAPI *PRTL_HEAP_COMMIT_ROUTINE)( + _In_ PVOID Base, + _Inout_ PVOID *CommitAddress, + _Inout_ PSIZE_T CommitSize + ); + +#if defined(_MSC_VER) +typedef struct _RTL_HEAP_PARAMETERS +{ + ULONG Length; + SIZE_T SegmentReserve; + SIZE_T SegmentCommit; + SIZE_T DeCommitFreeBlockThreshold; + SIZE_T DeCommitTotalFreeThreshold; + SIZE_T MaximumAllocationSize; + SIZE_T VirtualMemoryThreshold; + SIZE_T InitialCommit; + SIZE_T InitialReserve; + PRTL_HEAP_COMMIT_ROUTINE CommitRoutine; + SIZE_T Reserved[2]; +} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS; +#endif + +#define HEAP_SETTABLE_USER_VALUE 0x00000100 +#define HEAP_SETTABLE_USER_FLAG1 0x00000200 +#define HEAP_SETTABLE_USER_FLAG2 0x00000400 +#define HEAP_SETTABLE_USER_FLAG3 0x00000800 +#define HEAP_SETTABLE_USER_FLAGS 0x00000e00 + +#define HEAP_CLASS_0 0x00000000 // Process heap +#define HEAP_CLASS_1 0x00001000 // Private heap +#define HEAP_CLASS_2 0x00002000 // Kernel heap +#define HEAP_CLASS_3 0x00003000 // GDI heap +#define HEAP_CLASS_4 0x00004000 // User heap +#define HEAP_CLASS_5 0x00005000 // Console heap +#define HEAP_CLASS_6 0x00006000 // User desktop heap +#define HEAP_CLASS_7 0x00007000 // CSR shared heap +#define HEAP_CLASS_8 0x00008000 // CSR port heap +#define HEAP_CLASS_MASK 0x0000f000 + +// Privileges + +#define SE_MIN_WELL_KNOWN_PRIVILEGE (2L) +#define SE_CREATE_TOKEN_PRIVILEGE (2L) +#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE (3L) +#define SE_LOCK_MEMORY_PRIVILEGE (4L) +#define SE_INCREASE_QUOTA_PRIVILEGE (5L) +#define SE_MACHINE_ACCOUNT_PRIVILEGE (6L) +#define SE_TCB_PRIVILEGE (7L) +#define SE_SECURITY_PRIVILEGE (8L) +#define SE_TAKE_OWNERSHIP_PRIVILEGE (9L) +#define SE_LOAD_DRIVER_PRIVILEGE (10L) +#define SE_SYSTEM_PROFILE_PRIVILEGE (11L) +#define SE_SYSTEMTIME_PRIVILEGE (12L) +#define SE_PROF_SINGLE_PROCESS_PRIVILEGE (13L) +#define SE_INC_BASE_PRIORITY_PRIVILEGE (14L) +#define SE_CREATE_PAGEFILE_PRIVILEGE (15L) +#define SE_CREATE_PERMANENT_PRIVILEGE (16L) +#define SE_BACKUP_PRIVILEGE (17L) +#define SE_RESTORE_PRIVILEGE (18L) +#define SE_SHUTDOWN_PRIVILEGE (19L) +#define SE_DEBUG_PRIVILEGE (20L) +#define SE_AUDIT_PRIVILEGE (21L) +#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L) +#define SE_CHANGE_NOTIFY_PRIVILEGE (23L) +#define SE_REMOTE_SHUTDOWN_PRIVILEGE (24L) +#define SE_UNDOCK_PRIVILEGE (25L) +#define SE_SYNC_AGENT_PRIVILEGE (26L) +#define SE_ENABLE_DELEGATION_PRIVILEGE (27L) +#define SE_MANAGE_VOLUME_PRIVILEGE (28L) +#define SE_IMPERSONATE_PRIVILEGE (29L) +#define SE_CREATE_GLOBAL_PRIVILEGE (30L) +#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE (31L) +#define SE_RELABEL_PRIVILEGE (32L) +#define SE_INC_WORKING_SET_PRIVILEGE (33L) +#define SE_TIME_ZONE_PRIVILEGE (34L) +#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE (35L) +#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_SYMBOLIC_LINK_PRIVILEGE + + + +/* +* typedefs for the function prototypes. Use the something like: +* PF_DECL(FormatEx); +* which translates to: +* FormatEx_t pfFormatEx = NULL; +* in your code, to declare the entrypoint and then use: +* PF_INIT(FormatEx, Fmifs); +* which translates to: +* pfFormatEx = (FormatEx_t) GetProcAddress(GetDLLHandle("fmifs"), "FormatEx"); +* to make it accessible. +*/ +#define MAX_LIBRARY_HANDLES 32 +extern HMODULE OpenedLibrariesHandle[MAX_LIBRARY_HANDLES]; +extern UINT16 OpenedLibrariesHandleSize; +#define OPENED_LIBRARIES_VARS HMODULE OpenedLibrariesHandle[MAX_LIBRARY_HANDLES]; UINT16 OpenedLibrariesHandleSize = 0 +#define CLOSE_OPENED_LIBRARIES while(OpenedLibrariesHandleSize > 0) FreeLibrary(OpenedLibrariesHandle[--OpenedLibrariesHandleSize]) +static __inline HMODULE GetLibraryHandle(char* szLibraryName) { + HMODULE h = NULL; + if ((h = GetModuleHandleA(szLibraryName)) == NULL) { + if (OpenedLibrariesHandleSize >= MAX_LIBRARY_HANDLES) { + Log("Error: MAX_LIBRARY_HANDLES is too small\n"); + } + else { + h = LoadLibraryA(szLibraryName); + if (h != NULL) + OpenedLibrariesHandle[OpenedLibrariesHandleSize++] = h; + } + } + return h; +} +#define PF_TYPE(api, ret, proc, args) typedef ret (api *proc##_t)args +#define PF_DECL(proc) static proc##_t pf##proc = NULL +#define PF_TYPE_DECL(api, ret, proc, args) PF_TYPE(api, ret, proc, args); PF_DECL(proc) +#define PF_INIT(proc, name) if (pf##proc == NULL) pf##proc = \ + (proc##_t) GetProcAddress(GetLibraryHandle(#name), #proc) +#define PF_INIT_OR_OUT(proc, name) do {PF_INIT(proc, name); \ +if (pf##proc == NULL) { Log("Unable to locate %s() in %s.dll: %d\n", \ +#proc, #name, GetLastError()); goto out;} } while (0) + +#define PF_INIT_OR_SET_STATUS(proc, name) do {PF_INIT(proc, name); \ +if ((pf##proc == NULL) && (NT_SUCCESS(status))) status = STATUS_NOT_IMPLEMENTED; \ + } while (0) + +/* Custom application errors */ +#define FAC(f) ((f)<<16) +#define APPERR(err) (APPLICATION_ERROR_MASK|(err)) +#define ERROR_INCOMPATIBLE_FS 0x1201 +#define ERROR_CANT_QUICK_FORMAT 0x1202 +#define ERROR_INVALID_CLUSTER_SIZE 0x1203 +#define ERROR_INVALID_VOLUME_SIZE 0x1204 +#define ERROR_CANT_START_THREAD 0x1205 +#define ERROR_BADBLOCKS_FAILURE 0x1206 +#define ERROR_ISO_SCAN 0x1207 +#define ERROR_ISO_EXTRACT 0x1208 +#define ERROR_CANT_REMOUNT_VOLUME 0x1209 +#define ERROR_CANT_PATCH 0x120A +#define ERROR_CANT_ASSIGN_LETTER 0x120B +#define ERROR_CANT_MOUNT_VOLUME 0x120C +#define ERROR_BAD_SIGNATURE 0x120D +#define ERROR_CANT_DOWNLOAD 0x120E + + +#define KB 1024LL +#define MB 1048576LL +#define GB 1073741824LL +#define TB 1099511627776LL + +typedef struct _CLIENT_ID { + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID; + + + + +PF_TYPE_DECL(NTAPI, PVOID, RtlCreateHeap, (ULONG, PVOID, SIZE_T, SIZE_T, PVOID, PRTL_HEAP_PARAMETERS)); +PF_TYPE_DECL(NTAPI, PVOID, RtlDestroyHeap, (PVOID)); +PF_TYPE_DECL(NTAPI, PVOID, RtlAllocateHeap, (PVOID, ULONG, SIZE_T)); +PF_TYPE_DECL(NTAPI, BOOLEAN, RtlFreeHeap, (PVOID, ULONG, PVOID)); + +PF_TYPE_DECL(NTAPI, NTSTATUS, NtQuerySystemInformation, (SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryInformationFile, (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryInformationProcess, (HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtWow64QueryInformationProcess64, (HANDLE, ULONG, PVOID, ULONG, PULONG)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtWow64ReadVirtualMemory64, (HANDLE, ULONGLONG, PVOID, ULONG64, PULONG64)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryObject, (HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtDuplicateObject, (HANDLE, HANDLE, HANDLE, PHANDLE, ACCESS_MASK, ULONG, ULONG)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtOpenProcess, (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, CLIENT_ID*)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtOpenProcessToken, (HANDLE, ACCESS_MASK, PHANDLE)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtAdjustPrivilegesToken, (HANDLE, BOOLEAN, PTOKEN_PRIVILEGES, ULONG, PTOKEN_PRIVILEGES, PULONG)); +PF_TYPE_DECL(NTAPI, NTSTATUS, NtClose, (HANDLE)); + + +#define safe_free(p) do {free((void*)p); p = NULL;} while(0) + +#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 sfree(p) do {if (p != NULL) {free((void*)(p)); p = NULL;}} while(0) +#define wconvert(p) wchar_t* w ## p = utf8_to_wchar(p) +#define walloc(p, size) wchar_t* w ## p = (p == NULL)?NULL:(wchar_t*)calloc(size, sizeof(wchar_t)) +#define wfree(p) sfree(w ## p) + diff --git a/Ventoy2Disk/Ventoy2Disk/resource.h b/Ventoy2Disk/Ventoy2Disk/resource.h index 9626e52e4c4a62be8fe37f2500a730f89e143918..9de7e743bd97c2911172148a787431f251ffb9b4 100644 GIT binary patch delta 105 zcmaDN{Y`d*2Ghg?Jd>v|=}dNDWn(sEFrCcEC^`876U*cY>|C48m^QHjIRcD^6EEsd zPU4lA+`z;ElwsraWpHHhV{lEu8j J&B=YdVE~|SA5{PV delta 51 zcmew+`$T$!2Gitu99)w>u(NEQz_f{V^DmA=EQ}_T85u<<8}La?e#P4}xrIXv$QGHr HfG-RH@2L^Q