]> glassweightruler.freedombox.rocks Git - Ventoy.git/commitdiff
update
authorlongpanda <admin@ventoy.net>
Fri, 3 Jul 2020 15:20:35 +0000 (23:20 +0800)
committerlongpanda <admin@ventoy.net>
Fri, 3 Jul 2020 15:20:41 +0000 (23:20 +0800)
33 files changed:
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.h
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyDebug.c
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/VentoyProtocol.c
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/Memhole.c [new file with mode: 0644]
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.c [new file with mode: 0644]
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.h [new file with mode: 0644]
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.inf [new file with mode: 0644]
EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/MdeModulePkg.dsc
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c
GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h
GRUB2/MOD_SRC/grub-2.04/install.sh
INSTALL/grub/debug.cfg
INSTALL/ventoy_pack.sh
IPXE/ipxe_mod_code/ipxe-3fe683e/src/arch/x86/core/ventoy_vdisk.c
IPXE/ipxe_mod_code/ipxe-3fe683e/src/include/ventoy.h
LANGUAGES/languages.ini
Ventoy2Disk/Ventoy2Disk/Language.h
Ventoy2Disk/Ventoy2Disk/PhyDrive.c
Ventoy2Disk/Ventoy2Disk/Utility.c
Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c
Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h
Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.rc
Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj
Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj.filters
Ventoy2Disk/Ventoy2Disk/WinDialog.c
Ventoy2Disk/Ventoy2Disk/process.c [new file with mode: 0644]
Ventoy2Disk/Ventoy2Disk/process.h [new file with mode: 0644]
Ventoy2Disk/Ventoy2Disk/resource.h

index 7c2267f5e017a4a6d24c457cc85086841038e117..968049afa72e0cae5f2f39d56154a2faa6c2c699 100644 (file)
@@ -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))
             {
index 354496e76f36f89d1092ef484e9e1b8d0bcaf0e1..1056f8cc6a648a05a3bfdf598999a106e0db146a 100644 (file)
 
 #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
 
index d96c6b2e1694928c3b73ba09274ff30f8fbbd50d..7af3349bc862742e67b387f0fbaabd81399ae570 100644 (file)
@@ -36,9 +36,9 @@
 #include <Protocol/SimpleFileSystem.h>
 #include <Ventoy.h>
 
-#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;
 }
index 0e19153ceaf08de9adcf7659708601c861ecb2a3..8afbd9a1ac851f07973f1e7fb36a0fe88ded8db2 100644 (file)
@@ -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 (file)
index 0000000..715d7bc
--- /dev/null
@@ -0,0 +1,179 @@
+/******************************************************************************
+ * Memhole.c
+ *
+ * Copyright (c) 2020, longpanda <admin@ventoy.net>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Protocol/LoadedImage.h>
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/RamDisk.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <VtoyUtil.h>
+
+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 (file)
index 0000000..9f4d7b3
--- /dev/null
@@ -0,0 +1,135 @@
+/******************************************************************************
+ * VtoyUtil.c
+ *
+ * Copyright (c) 2020, longpanda <admin@ventoy.net>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Protocol/LoadedImage.h>
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/RamDisk.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <VtoyUtil.h>
+
+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 (file)
index 0000000..9adf6c7
--- /dev/null
@@ -0,0 +1,61 @@
+/******************************************************************************
+ * VtoyUtil.h
+ *
+ * Copyright (c) 2020, longpanda <admin@ventoy.net>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+#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 (file)
index 0000000..9a4fbf2
--- /dev/null
@@ -0,0 +1,80 @@
+#************************************************************************************
+# Copyright (c) 2020, longpanda <admin@ventoy.net>
+# 
+# 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 <http://www.gnu.org/licenses/>.
+# 
+#************************************************************************************
+
+[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
+  
+  
+  
+  
+  
+  
index 2bdadd28e89083a90028717da3a4c3e5c4c86621..f47ea6fbe5eb2bbd06b3ed3a97d029b891dc3333 100644 (file)
 
 [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
index 32200f148ab8c91d44b30fc819f8bc013210c92f..708d4c1516b1a15acbd4bdb6aff788bfdcb78aac 100644 (file)
@@ -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);
     }
index 4717f09450be30cf9f68037a8efd2525ff7eac8f..169c56e9a425823d2e22848af19dbb405f3a8d11 100644 (file)
@@ -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);
index ddd7499aa97725effc15fea86c8c1e8f79d7d4ca..e8ec502acc56eb9d60f0566bb4a3cdc9548275ce 100644 (file)
@@ -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 */
index 6bb4e9c0b89181161790460b5c80f13cbe01324c..c7fda9cf7a13fdfc00b51025c2250922512ad750 100644 (file)
@@ -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;
index 76975dbfa113e7e53da963ec01d1441e65333989..1100fd38648e8822645ecc116f238b9858bbc6d6 100644 (file)
@@ -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 */
index 5b684b495a69d4a38e4a5f2575178f6661f3fd3e..93365c73391adb9c3b38f4270cc2d28b0e1400e6 100644 (file)
@@ -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()
index 1dc952af454a9abd991e97a0a69c0d8d15b32629..8d9ba4cb322a409aa6c654e67c803d4f91471a79 100644 (file)
@@ -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
index 0def325c831602ae51dd8661e5b903a0099c942b..77f3dc5b8cfe8d9849472b558dce4172360e3b15 100644 (file)
@@ -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 ...'
 }
index b17feeff82627419c03efd9b8e6278db5fa51553..1660a50ba6251627fbd91d6c68d6b82fdaf97afc 100644 (file)
@@ -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
index d3ccb2b43d0d96e009d736b35b4a9700f63fd957..fcc0c0e2420dd8c07610f59a213d4b5e67bf4af4 100644 (file)
@@ -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;
     }
index 1898d7ac078bfc4f996c2772e2f5b16c52283474..286bb33c4fa312f18bc50fc56ea73e33f3707ddb 100644 (file)
@@ -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
index b09f213b6732f46d137069a29e9f7218b2062635..926f47653e731905b45af22fec35469fed195d83 100644 (file)
Binary files a/LANGUAGES/languages.ini and b/LANGUAGES/languages.ini differ
index 3623dc332c58ad46513e7813cb412ac6aff82c6b..6705b86fe11a04fb5651cbfc86141a067d655991 100644 (file)
@@ -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
 
 
index 07c168cd000fd4192d324883aae28ae9a93b01e9..7dde3154f7f8a6618cd855cb00bea40b69ac20cd 100644 (file)
@@ -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;
 }
 
+
index 21b0245d8e01d1cf07dd57c645af344d36c86cf0..e7df557b1505b00acd8a214b2dab05dc6660abb2 100644 (file)
@@ -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;
index f0ea679bd69ca2a3687731b0af636e18c9e5797b..59ca86c013d9ec8efe1939d8314fe45cf738ee08 100644 (file)
@@ -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)
     {
index 26352ddf3277631541528e74200a4d816cb8e92f..13b71f76a6ee721dfc6b79b6b1881d85185afc63 100644 (file)
@@ -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
index 2df0e8afecd1299565f25bf76d6d73d1a560661d..43075fb6642c13a25e7891e363f7af9d5a73fea9 100644 (file)
Binary files a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.rc and b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.rc differ
index 4b9ccf82e6a9e8a8bee7ce90730858dcc803f952..f82d5fcfe916cf51521d83af657ee10277b6026d 100644 (file)
     <ClCompile Include="Language.c" />
     <ClCompile Include="PartDialog.c" />
     <ClCompile Include="PhyDrive.c" />
+    <ClCompile Include="process.c" />
     <ClCompile Include="Utility.c" />
     <ClCompile Include="Ventoy2Disk.c" />
     <ClCompile Include="WinDialog.c" />
     <ClInclude Include="ff14\source\ff.h" />
     <ClInclude Include="ff14\source\ffconf.h" />
     <ClInclude Include="Language.h" />
+    <ClInclude Include="process.h" />
     <ClInclude Include="resource.h" />
     <ClInclude Include="Ventoy2Disk.h" />
   </ItemGroup>
     <ResourceCompile Include="Ventoy2Disk.rc" />
   </ItemGroup>
   <ItemGroup>
+    <Image Include="res\icon2.ico" />
+    <Image Include="Res\refresh.ico" />
     <Image Include="Res\ventoy.ico" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
index 8370af2ccce504c8af12cf41ee6410626b508036..9c74bea84953fb4e3751b9d7871db36189c15a92 100644 (file)
@@ -72,6 +72,9 @@
     <ClCompile Include="PartDialog.c">
       <Filter>源文件</Filter>
     </ClCompile>
+    <ClCompile Include="process.c">
+      <Filter>源文件</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Ventoy2Disk.h">
     <ClInclude Include="ff14\source\ffconf.h">
       <Filter>头文件</Filter>
     </ClInclude>
+    <ClInclude Include="process.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Ventoy2Disk.rc">
     <Image Include="Res\ventoy.ico">
       <Filter>资源文件</Filter>
     </Image>
+    <Image Include="res\icon2.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="Res\refresh.ico">
+      <Filter>资源文件</Filter>
+    </Image>
   </ItemGroup>
 </Project>
\ No newline at end of file
index afceab56d468d262141043b0331c652b6ac250fe..42bda379646ec0cd006264f62b34c1e71f5fa502 100644 (file)
Binary files a/Ventoy2Disk/Ventoy2Disk/WinDialog.c and b/Ventoy2Disk/Ventoy2Disk/WinDialog.c differ
diff --git a/Ventoy2Disk/Ventoy2Disk/process.c b/Ventoy2Disk/Ventoy2Disk/process.c
new file mode 100644 (file)
index 0000000..5064d1f
--- /dev/null
@@ -0,0 +1,672 @@
+/*
+* Rufus: The Reliable USB Formatting Utility
+* Process search functionality
+*
+* Modified from Process Hacker:
+*   https://github.com/processhacker2/processhacker2/
+* Copyright © 2017-2019 Pete Batard <pete@akeo.ie>
+* Copyright © 2017 dmex
+* Copyright © 2009-2016 wj32
+* Copyright (c) 2020, longpanda <admin@ventoy.net>
+*
+* 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 <http://www.gnu.org/licenses/>.
+*/
+
+
+#include <Windows.h>
+#include <winternl.h>
+#include <commctrl.h>
+#include <initguid.h>
+#include <vds.h>
+#include "resource.h"
+#include "Language.h"
+#include "Ventoy2Disk.h"
+#include "fat_filelib.h"
+#include "ff.h"
+#include "process.h"
+#include <Psapi.h>
+
+
+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 (file)
index 0000000..39ebe40
--- /dev/null
@@ -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 <pete@akeo.ie>
+* Copyright © 2017 dmex
+* Copyright © 2009-2016 wj32
+* Copyright (c) 2020, longpanda <admin@ventoy.net>
+*
+* 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <windows.h>
+#include <winnt.h>
+#include <winternl.h>
+
+#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)
+
index 9626e52e4c4a62be8fe37f2500a730f89e143918..9de7e743bd97c2911172148a787431f251ffb9b4 100644 (file)
Binary files a/Ventoy2Disk/Ventoy2Disk/resource.h and b/Ventoy2Disk/Ventoy2Disk/resource.h differ