]> glassweightruler.freedombox.rocks Git - Ventoy.git/commitdiff
1.0.29 release v1.0.29
authorlongpanda <admin@ventoy.net>
Thu, 19 Nov 2020 12:45:17 +0000 (20:45 +0800)
committerlongpanda <admin@ventoy.net>
Thu, 19 Nov 2020 12:45:17 +0000 (20:45 +0800)
27 files changed:
GRUB2/MOD_SRC/grub-2.04/grub-core/commands/search.c [new file with mode: 0644]
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
IMG/cpio/ventoy/hook/rhel7/ventoy-hook.sh
IMG/cpio/ventoy/hook/suse/ventoy-hook.sh
IMG/cpio/ventoy/hook/ventoy-os-lib.sh
INSTALL/EFI/BOOT/grubx64_real.efi
INSTALL/grub/debug.cfg
INSTALL/grub/grub.cfg
INSTALL/grub/i386-pc/core.img
INSTALL/grub/i386-pc/search_fs_file.mod
INSTALL/grub/i386-pc/search_fs_uuid.mod
INSTALL/grub/i386-pc/search_label.mod
INSTALL/grub/localboot.cfg
INSTALL/grub/x86_64-efi/search_fs_file.mod
INSTALL/grub/x86_64-efi/search_fs_uuid.mod
INSTALL/grub/x86_64-efi/search_label.mod
INSTALL/tool/VentoyWorker.sh
INSTALL/tool/ventoy_lib.sh
INSTALL/ventoy/ventoy.cpio
INSTALL/ventoy/vtoyjump32.exe
INSTALL/ventoy/vtoyjump64.exe
LANGUAGES/languages.ini
vtoyjump/vtoyjump/vtoyjump.c

diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/search.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/search.c
new file mode 100644 (file)
index 0000000..3852c0c
--- /dev/null
@@ -0,0 +1,353 @@
+/* search.c - search devices based on a file or a filesystem label */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2007,2008,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB 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.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/device.h>
+#include <grub/file.h>
+#include <grub/env.h>
+#include <grub/command.h>
+#include <grub/search.h>
+#include <grub/i18n.h>
+#include <grub/disk.h>
+#include <grub/partition.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static int g_no_vtoyefi_part = 0;
+static char g_vtoyefi_dosname[64];
+static char g_vtoyefi_gptname[64];
+
+struct cache_entry
+{
+  struct cache_entry *next;
+  char *key;
+  char *value;
+};
+
+static struct cache_entry *cache;
+
+/* Context for FUNC_NAME.  */
+struct search_ctx
+{
+  const char *key;
+  const char *var;
+  int no_floppy;
+  char **hints;
+  unsigned nhints;
+  int count;
+  int is_cache;
+};
+
+/* Helper for FUNC_NAME.  */
+static int
+iterate_device (const char *name, void *data)
+{
+  struct search_ctx *ctx = data;
+  int found = 0;
+
+  /* Skip floppy drives when requested.  */
+  if (ctx->no_floppy &&
+      name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
+    return 1;
+
+  if (g_no_vtoyefi_part && (grub_strcmp(name, g_vtoyefi_dosname) == 0 || grub_strcmp(name, g_vtoyefi_gptname) == 0)) {
+    return 0;
+  }
+
+#ifdef DO_SEARCH_FS_UUID
+#define compare_fn grub_strcasecmp
+#else
+#define compare_fn grub_strcmp
+#endif
+
+#ifdef DO_SEARCH_FILE
+    {
+      char *buf;
+      grub_file_t file;
+
+      buf = grub_xasprintf ("(%s)%s", name, ctx->key);
+      if (! buf)
+       return 1;
+
+      file = grub_file_open (buf, GRUB_FILE_TYPE_FS_SEARCH
+                            | GRUB_FILE_TYPE_NO_DECOMPRESS);
+      if (file)
+       {
+         found = 1;
+         grub_file_close (file);
+       }
+      grub_free (buf);
+    }
+#else
+    {
+      /* SEARCH_FS_UUID or SEARCH_LABEL */
+      grub_device_t dev;
+      grub_fs_t fs;
+      char *quid;
+
+      dev = grub_device_open (name);
+      if (dev)
+       {
+         fs = grub_fs_probe (dev);
+
+#ifdef DO_SEARCH_FS_UUID
+#define read_fn fs_uuid
+#else
+#define read_fn fs_label
+#endif
+
+         if (fs && fs->read_fn)
+           {
+             fs->read_fn (dev, &quid);
+
+             if (grub_errno == GRUB_ERR_NONE && quid)
+               {
+                 if (compare_fn (quid, ctx->key) == 0)
+                   found = 1;
+
+                 grub_free (quid);
+               }
+           }
+
+         grub_device_close (dev);
+       }
+    }
+#endif
+
+  if (!ctx->is_cache && found && ctx->count == 0)
+    {
+      struct cache_entry *cache_ent;
+      cache_ent = grub_malloc (sizeof (*cache_ent));
+      if (cache_ent)
+       {
+         cache_ent->key = grub_strdup (ctx->key);
+         cache_ent->value = grub_strdup (name);
+         if (cache_ent->value && cache_ent->key)
+           {
+             cache_ent->next = cache;
+             cache = cache_ent;
+           }
+         else
+           {
+             grub_free (cache_ent->value);
+             grub_free (cache_ent->key);
+             grub_free (cache_ent);
+             grub_errno = GRUB_ERR_NONE;
+           }
+       }
+      else
+       grub_errno = GRUB_ERR_NONE;
+    }
+
+  if (found)
+    {
+      ctx->count++;
+      if (ctx->var)
+       grub_env_set (ctx->var, name);
+      else
+       grub_printf (" %s", name);
+    }
+
+  grub_errno = GRUB_ERR_NONE;
+  return (found && ctx->var);
+}
+
+/* Helper for FUNC_NAME.  */
+static int
+part_hook (grub_disk_t disk, const grub_partition_t partition, void *data)
+{
+  struct search_ctx *ctx = data;
+  char *partition_name, *devname;
+  int ret;
+
+  partition_name = grub_partition_get_name (partition);
+  if (! partition_name)
+    return 1;
+
+  devname = grub_xasprintf ("%s,%s", disk->name, partition_name);
+  grub_free (partition_name);
+  if (!devname)
+    return 1;
+  ret = iterate_device (devname, ctx);
+  grub_free (devname);    
+
+  return ret;
+}
+
+/* Helper for FUNC_NAME.  */
+static void
+try (struct search_ctx *ctx)    
+{
+  unsigned i;
+  struct cache_entry **prev;
+  struct cache_entry *cache_ent;
+
+  for (prev = &cache, cache_ent = *prev; cache_ent;
+       prev = &cache_ent->next, cache_ent = *prev)
+    if (compare_fn (cache_ent->key, ctx->key) == 0)
+      break;
+  if (cache_ent)
+    {
+      ctx->is_cache = 1;
+      if (iterate_device (cache_ent->value, ctx))
+       {
+         ctx->is_cache = 0;
+         return;
+       }
+      ctx->is_cache = 0;
+      /* Cache entry was outdated. Remove it.  */
+      if (!ctx->count)
+       {
+         *prev = cache_ent->next;
+         grub_free (cache_ent->key);
+         grub_free (cache_ent->value);
+         grub_free (cache_ent);
+       }
+    }
+
+  for (i = 0; i < ctx->nhints; i++)
+    {
+      char *end;
+      if (!ctx->hints[i][0])
+       continue;
+      end = ctx->hints[i] + grub_strlen (ctx->hints[i]) - 1;
+      if (*end == ',')
+       *end = 0;
+      if (iterate_device (ctx->hints[i], ctx))
+       {
+         if (!*end)
+           *end = ',';
+         return;
+       }
+      if (!*end)
+       {
+         grub_device_t dev;
+         int ret;
+         dev = grub_device_open (ctx->hints[i]);
+         if (!dev)
+           {
+             if (!*end)
+               *end = ',';
+             continue;
+           }
+         if (!dev->disk)
+           {
+             grub_device_close (dev);
+             if (!*end)
+               *end = ',';
+             continue;
+           }
+         ret = grub_partition_iterate (dev->disk, part_hook, ctx);
+         if (!*end)
+           *end = ',';
+         grub_device_close (dev);
+         if (ret)
+           return;
+       }
+    }
+  grub_device_iterate (iterate_device, ctx);
+}
+
+void
+FUNC_NAME (const char *key, const char *var, int no_floppy,
+          char **hints, unsigned nhints)
+{
+  struct search_ctx ctx = {
+    .key = key,
+    .var = var,
+    .no_floppy = no_floppy,
+    .hints = hints,
+    .nhints = nhints,
+    .count = 0,
+    .is_cache = 0
+  };
+  grub_fs_autoload_hook_t saved_autoload;
+
+  g_no_vtoyefi_part = 0;
+  if (grub_env_get("VTOY_SEARCH_NO_VTOYEFI"))
+  {
+      grub_snprintf(g_vtoyefi_dosname, sizeof(g_vtoyefi_dosname), "%s,msdos2", grub_env_get("vtoydev"));
+      grub_snprintf(g_vtoyefi_gptname, sizeof(g_vtoyefi_gptname), "%s,gpt2", grub_env_get("vtoydev"));
+      g_no_vtoyefi_part = 1;
+  }
+
+  /* First try without autoloading if we're setting variable. */
+  if (var)
+    {
+      saved_autoload = grub_fs_autoload_hook;
+      grub_fs_autoload_hook = 0;
+      try (&ctx);
+
+      /* Restore autoload hook.  */
+      grub_fs_autoload_hook = saved_autoload;
+
+      /* Retry with autoload if nothing found.  */
+      if (grub_errno == GRUB_ERR_NONE && ctx.count == 0)
+       try (&ctx);
+    }
+  else
+    try (&ctx);
+
+  if (grub_errno == GRUB_ERR_NONE && ctx.count == 0)
+    grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
+}
+
+static grub_err_t
+grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc,
+                   char **args)
+{
+  if (argc == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+
+  FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2),
+            argc > 2 ? argc - 2 : 0);
+
+  return grub_errno;
+}
+
+static grub_command_t cmd;
+
+#ifdef DO_SEARCH_FILE
+GRUB_MOD_INIT(search_fs_file)
+#elif defined (DO_SEARCH_FS_UUID)
+GRUB_MOD_INIT(search_fs_uuid)
+#else
+GRUB_MOD_INIT(search_label)
+#endif
+{
+  cmd =
+    grub_register_command (COMMAND_NAME, grub_cmd_do_search,
+                          N_("NAME [VARIABLE] [HINTS]"),
+                          HELP_MESSAGE);
+}
+
+#ifdef DO_SEARCH_FILE
+GRUB_MOD_FINI(search_fs_file)
+#elif defined (DO_SEARCH_FS_UUID)
+GRUB_MOD_FINI(search_fs_uuid)
+#else
+GRUB_MOD_FINI(search_label)
+#endif
+{
+  grub_unregister_command (cmd);
+}
index 8be06582c1ff6070cd432c23a20c86c42d8b3a6d..e21bd63bab27ef1ba6bfc3315e1a4feed0e0e9e2 100644 (file)
@@ -1111,26 +1111,13 @@ void ventoy_swap_img(img_info *img1, img_info *img2)
 
 static int ventoy_img_name_valid(const char *filename, grub_size_t namelen)
 {
-    grub_size_t i;
-
+    (void)namelen;
+    
     if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
     {
         return 0;
     }
 
-    for (i = 0; i < namelen; i++)
-    {
-        if (filename[i] == ' ' || filename[i] == '\t')
-        {
-            return 0;
-        }
-
-        if ((grub_uint8_t)(filename[i]) >= 127)
-        {
-            return 0;
-        }
-    }
-
     return 1;
 }
 
@@ -1150,7 +1137,7 @@ static int ventoy_check_ignore_flag(const char *filename, const struct grub_dirh
 
 static int ventoy_colect_img_files(const char *filename, const struct grub_dirhook_info *info, void *data)
 {
-    int i = 0;
+    //int i = 0;
     int type = 0;
     int ignore = 0;
     int index = 0;
@@ -1297,15 +1284,6 @@ static int ventoy_colect_img_files(const char *filename, const struct grub_dirho
             img->plugin_list_index = index;
             grub_snprintf(img->name, sizeof(img->name), "%s", filename);
 
-            for (i = 0; i < (int)len; i++)
-            {
-                if (filename[i] == ' ' || filename[i] == '\t' || (0 == grub_isprint(filename[i])))
-                {
-                    img->name[i] = '*';
-                    img->unsupport = 1;
-                }
-            }
-            
             img->pathlen = grub_snprintf(img->path, sizeof(img->path), "%s%s", node->dir, img->name);
 
             img->size = info->size;
@@ -4001,6 +3979,7 @@ static cmd_para ventoy_cmds[] =
     { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch, 0, NULL, "", "", NULL },
     { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count, 0, NULL, "", "", NULL },
     { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch, 0, NULL, "", "", NULL },
+    { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable, 0, NULL, "", "", NULL },
     { "vt_wim_chain_data", ventoy_cmd_wim_chain_data, 0, NULL, "", "", NULL },
 
     { "vt_add_replace_file", ventoy_cmd_add_replace_file, 0, NULL, "", "", NULL },
index 207aee965285057a81a0ba3fd24c23eb7d9752f8..ae0f6f00ee7b7b4429d6e99814e89a936e6471c3 100644 (file)
@@ -508,6 +508,7 @@ grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **a
 grub_err_t ventoy_cmd_wimdows_reset(grub_extcmd_context_t ctxt, int argc, char **args);
 grub_err_t ventoy_cmd_windows_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
 grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
+grub_err_t ventoy_cmd_wim_check_bootable(grub_extcmd_context_t ctxt, int argc, char **args);
 grub_err_t ventoy_cmd_dump_wim_patch(grub_extcmd_context_t ctxt, int argc, char **args);
 
 VTOY_JSON *vtoy_json_find_item
@@ -731,6 +732,24 @@ typedef struct install_template
     struct install_template *next;
 }install_template;
 
+typedef struct dudfile
+{
+    int size;
+    char *buf;
+}dudfile;
+
+typedef struct dud
+{
+    int pathlen;
+    char isopath[256];
+
+    int dudnum;
+    file_fullpath *dudpath;
+    dudfile *files;
+
+    struct dud *next;
+}dud;
+
 typedef struct persistence_config
 {
     int pathlen;
@@ -855,6 +874,8 @@ const char * ventoy_plugin_get_menu_class(int type, const char *name);
 int ventoy_plugin_check_memdisk(const char *isopath);
 int ventoy_plugin_get_image_list_index(int type, const char *name);
 conf_replace * ventoy_plugin_find_conf_replace(const char *iso);
+dud * ventoy_plugin_find_dud(const char *iso);
+int ventoy_plugin_load_dud(dud *node, const char *isopart);
 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 1718e19dea0a23f3f7136e6b87190473b7a4a498..21ac4f5feca8277843ee9fbe4bf74e5d6454fd65 100644 (file)
@@ -1044,11 +1044,15 @@ grub_err_t ventoy_cmd_cpio_busybox_64(grub_extcmd_context_t ctxt, int argc, char
 
 grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
 {
+    int i;
     int rc;
+    char *pos = NULL;
     char *template_file = NULL;
     char *template_buf = NULL;
     char *persistent_buf = NULL;
     char *injection_buf = NULL;
+    dud *dudnode = NULL;
+    char tmpname[128];
     const char *injection_file = NULL;
     grub_uint8_t *buf = NULL;
     grub_uint32_t mod;
@@ -1059,6 +1063,7 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
     grub_uint32_t template_size = 0;
     grub_uint32_t persistent_size = 0;
     grub_uint32_t injection_size = 0;
+    grub_uint32_t dud_size = 0;
     grub_file_t file;
     grub_file_t tmpfile;
     ventoy_img_chunk_list chunk_list;
@@ -1152,11 +1157,30 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
         debug("injection not configed %s\n", args[1]);
     }
 
-    g_ventoy_cpio_buf = grub_malloc(file->size + 4096 + template_size + persistent_size + injection_size + img_chunk_size);
+    dudnode = ventoy_plugin_find_dud(args[1]);
+    if (dudnode)
+    {
+        debug("dud file: <%d>\n", dudnode->dudnum);
+        ventoy_plugin_load_dud(dudnode, args[2]);
+        for (i = 0; i < dudnode->dudnum; i++)
+        {
+            if (dudnode->files[i].size > 0)
+            {
+                dud_size += dudnode->files[i].size + sizeof(cpio_newc_header);                
+            }
+        }
+    }
+    else
+    {
+        debug("dud not configed %s\n", args[1]);
+    }
+
+    g_ventoy_cpio_buf = grub_malloc(file->size + 40960 + template_size + 
+        persistent_size + injection_size + dud_size + img_chunk_size);
     if (NULL == g_ventoy_cpio_buf)
     {
         grub_file_close(file);
-        return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't alloc memory %llu\n", file->size + 4096 + img_chunk_size); 
+        return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't alloc memory %llu\n", file->size);
     }
 
     grub_file_read(file, g_ventoy_cpio_buf, file->size);
@@ -1198,6 +1222,18 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
         injection_buf = NULL;
     }
 
+    if (dud_size > 0)
+    {
+        for (i = 0; i < dudnode->dudnum; i++)
+        {
+            pos = grub_strrchr(dudnode->dudpath[i].path, '.');
+            grub_snprintf(tmpname, sizeof(tmpname), "ventoy/ventoy_dud%d%s", i, (pos ? pos : ".iso"));
+            dud_size = dudnode->files[i].size;
+            headlen = ventoy_cpio_newc_fill_head(buf, dud_size, dudnode->files[i].buf, tmpname);
+            buf += headlen + ventoy_align(dud_size, 4);
+        }
+    }
+
     /* step2: insert os param to cpio */
     headlen = ventoy_cpio_newc_fill_head(buf, 0, NULL, "ventoy/ventoy_os_param");
     padlen = sizeof(ventoy_os_param);
index a5c2c030dc42cb4323270764e0f3dfd14114dcac..0f92a008a4d6c928fab69fbab3078296e6d9ec89 100644 (file)
@@ -41,6 +41,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 
 static char g_iso_disk_name[128];
 static install_template *g_install_template_head = NULL;
+static dud *g_dud_head = NULL;
 static persistence_config *g_persistence_head = NULL;
 static menu_alias *g_menu_alias_head = NULL;
 static menu_class *g_menu_class_head = NULL;
@@ -590,6 +591,110 @@ static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk
     return 0;
 }
 
+static int ventoy_plugin_dud_check(VTOY_JSON *json, const char *isodisk)
+{
+    int pathnum = 0;
+    const char *iso = NULL;
+    VTOY_JSON *pNode = NULL;
+
+    if (json->enDataType != JSON_TYPE_ARRAY)
+    {
+        grub_printf("Not array type %d\n", json->enDataType);
+        return 1;
+    }
+
+    for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
+    {
+        if (pNode->enDataType != JSON_TYPE_OBJECT)
+        {
+            grub_printf("NOT object type\n");
+        }
+    
+        iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
+        if (iso)
+        {
+            if (0 == ventoy_plugin_check_path(isodisk, iso))
+            {
+                grub_printf("image: %s [OK]\n", iso);
+                ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "dud", &pathnum);
+            }
+            else
+            {
+                grub_printf("image: %s [FAIL]\n", iso);
+            }
+        }
+        else
+        {
+            grub_printf("image not found\n");
+        }
+    }
+
+    return 0;
+}
+
+static int ventoy_plugin_dud_entry(VTOY_JSON *json, const char *isodisk)
+{
+    int pathnum = 0;
+    const char *iso = NULL;
+    VTOY_JSON *pNode = NULL;
+    dud *node = NULL;
+    dud *next = NULL;
+    file_fullpath *dudpath = NULL;
+
+    if (json->enDataType != JSON_TYPE_ARRAY)
+    {
+        debug("Not array %d\n", json->enDataType);
+        return 0;
+    }
+
+    if (g_dud_head)
+    {
+        for (node = g_dud_head; node; node = next)
+        {
+            next = node->next;
+            grub_check_free(node->dudpath);
+            grub_free(node);
+        }
+
+        g_dud_head = NULL;
+    }
+
+    for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
+    {
+        iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
+        if (iso && iso[0] == '/')
+        {
+            if (0 == ventoy_plugin_parse_fullpath(pNode->pstChild, isodisk, "dud", &dudpath, &pathnum))
+            {
+                node = grub_zalloc(sizeof(dud));
+                if (node)
+                {
+                    node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
+                    node->dudpath = dudpath;
+                    node->dudnum = pathnum;
+                    node->files = grub_zalloc(sizeof(dudfile) * pathnum);
+
+                    if (node->files)
+                    {
+                        if (g_dud_head)
+                        {
+                            node->next = g_dud_head;
+                        }
+                        
+                        g_dud_head = node;
+                    }
+                    else
+                    {
+                        grub_free(node);
+                    }
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
 static int ventoy_plugin_persistence_check(VTOY_JSON *json, const char *isodisk)
 {
     int autosel = 0;
@@ -1333,6 +1438,7 @@ static plugin_entry g_plugin_entries[] =
     { "auto_memdisk", ventoy_plugin_auto_memdisk_entry, ventoy_plugin_auto_memdisk_check },
     { "image_list", ventoy_plugin_image_list_entry, ventoy_plugin_image_list_check },
     { "conf_replace", ventoy_plugin_conf_replace_entry, ventoy_plugin_conf_replace_check },
+    { "dud", ventoy_plugin_dud_entry, ventoy_plugin_dud_check },
 };
 
 static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
@@ -1761,6 +1867,59 @@ conf_replace * ventoy_plugin_find_conf_replace(const char *iso)
     return NULL;
 }
 
+dud * ventoy_plugin_find_dud(const char *iso)
+{
+    int len;
+    dud *node;
+
+    if (!g_dud_head)
+    {
+        return NULL;
+    }
+
+    len = (int)grub_strlen(iso);
+    for (node = g_dud_head; node; node = node->next)
+    {
+        if (node->pathlen == len && grub_strncmp(iso, node->isopath, len) == 0)
+        {
+            return node;
+        }
+    }
+    
+    return NULL;
+}
+
+int ventoy_plugin_load_dud(dud *node, const char *isopart)
+{
+    int i;
+    char *buf;
+    grub_file_t file;
+
+    for (i = 0; i < node->dudnum; i++)
+    {
+        if (node->files[i].size > 0)
+        {
+            debug("file %d has been loaded\n", i);
+            continue;
+        }
+    
+        file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", isopart, node->dudpath[i].path);
+        if (file)
+        {
+            buf = grub_malloc(file->size);
+            if (buf)
+            {
+                grub_file_read(file, buf, file->size);            
+                node->files[i].size = (int)file->size;
+                node->files[i].buf = buf;                
+            }
+            grub_file_close(file);
+        }
+    }
+
+    return 0;
+}
+
 grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args)
 {
     int i = 0;
@@ -1782,6 +1941,7 @@ grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, ch
     if (!file)
     {
         grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
+        grub_printf("Attention: directory name and filename are both case-sensitive.\n");
         goto end;
     }
 
index a9d3c81f63ad914473c7d81e7bfcfb29b5f35666..3f7612be5776d7eb015c6785bff7daf8c59e8543 100644 (file)
@@ -1542,6 +1542,41 @@ static int ventoy_get_wim_chunklist(const char *filename, ventoy_img_chunk_list
     return 0;
 }
 
+grub_err_t ventoy_cmd_wim_check_bootable(grub_extcmd_context_t ctxt, int argc, char **args)
+{
+    grub_uint32_t boot_index;
+    grub_file_t file = NULL;
+    wim_header *wimhdr = NULL;
+    
+    (void)ctxt;
+    (void)argc;
+
+    wimhdr = grub_zalloc(sizeof(wim_header));
+    if (!wimhdr)
+    {
+        return 1;
+    }
+
+    file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
+    if (!file)
+    {
+        grub_free(wimhdr);
+        return 1;
+    }
+
+    grub_file_read(file, wimhdr, sizeof(wim_header));
+    grub_file_close(file);
+    boot_index = wimhdr->boot_index;
+    grub_free(wimhdr);
+
+    if (boot_index == 0)
+    {
+        return 1;
+    }
+    
+    VENTOY_CMD_RETURN(GRUB_ERR_NONE);
+}
+
 grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
 {
     grub_uint32_t i = 0;
index ed53f4cad656f541d2ecf3eb6a1b51beae7b7806..cff0f1078a09499003ea12ed34d7331821b00756 100644 (file)
@@ -42,10 +42,17 @@ fi
 
 echo "VTKS=$VTKS" >> $VTLOG
 
+if ls $VTOY_PATH | $GREP -q 'ventoy_dud[0-9]'; then
+    for vtDud in $(ls $VTOY_PATH/ventoy_dud*); do
+        vtInstDD="$vtInstDD inst.dd=file:$vtDud"
+    done
+fi
+echo "vtInstDD=$vtInstDD" >> $VTLOG
+
 if $GREP -q 'root=live' /proc/cmdline; then
-    $SED "s#printf\(.*\)\$CMDLINE#printf\1\$CMDLINE root=live:/dev/dm-0 $VTKS#" -i /lib/dracut-lib.sh
+    $SED "s#printf\(.*\)\$CMDLINE#printf\1\$CMDLINE root=live:/dev/dm-0 $VTKS $vtInstDD#" -i /lib/dracut-lib.sh
 else
-    $SED "s#printf\(.*\)\$CMDLINE#printf\1\$CMDLINE inst.stage2=hd:/dev/dm-0 $VTKS#" -i /lib/dracut-lib.sh
+    $SED "s#printf\(.*\)\$CMDLINE#printf\1\$CMDLINE inst.stage2=hd:/dev/dm-0 $VTKS $vtInstDD#" -i /lib/dracut-lib.sh
 fi
 
 ventoy_set_inotify_script  rhel7/ventoy-inotifyd-hook.sh
index 9574efe57f4909e99361f70f720fd8767c337450..47aa0504e958b495d8baa9c790ea0353b3db9dcd 100644 (file)
@@ -26,6 +26,32 @@ if [ -f $VTOY_PATH/autoinstall ]; then
     fi
 fi
 
+if $BUSYBOX_PATH/ls $VTOY_PATH | $GREP -q 'ventoy_dud[0-9]'; then
+    if [ -f /linuxrc.config ]; then
+        vtKerVer=$($BUSYBOX_PATH/uname -r)
+        ventoy_check_insmod /modules/loop.ko
+        ventoy_check_insmod /modules/squashfs.ko
+        
+        ventoy_check_mount /parts/00_lib /modules
+        ventoy_check_insmod /modules/lib/modules/$vtKerVer/initrd/isofs.ko
+        $BUSYBOX_PATH/umount /modules
+    
+        for vtDud in $($BUSYBOX_PATH/ls $VTOY_PATH/ventoy_dud*); do
+            $BUSYBOX_PATH/mkdir -p ${vtDud%.*}_mnt
+            if $BUSYBOX_PATH/mount $vtDud ${vtDud%.*}_mnt > /dev/null 2>&1; then
+                $BUSYBOX_PATH/cp -a ${vtDud%.*}_mnt  ${vtDud%.*}_data
+                $BUSYBOX_PATH/umount ${vtDud%.*}_mnt
+                echo "dud: file://${vtDud%.*}_data" >> /linuxrc.config
+            else
+                echo "mount $vtDud failed" >> $VTLOG
+            fi
+        done
+        
+        $BUSYBOX_PATH/rmmod isofs >> $VTLOG 2>&1
+        $BUSYBOX_PATH/rmmod squashfs >> $VTLOG 2>&1
+        $BUSYBOX_PATH/rmmod loop >> $VTLOG 2>&1
+    fi
+fi
 
 #echo "Exec: /bin/sh $VTOY_PATH/hook/suse/cdrom-hook.sh" >> /info-ventoy
 #echo "install: hd:/?device=/dev/mapper/ventoy" >> /info-ventoy
index fb36ac25f0d5405c10103f13caf4b52cfa950472..dbd015f877e91228d2f636e9c1587e77448fc054 100644 (file)
@@ -110,4 +110,14 @@ ventoy_set_loop_inotify_script() {
     echo $VTOY_PATH/loop/$1 > $VTOY_PATH/inotifyd-loop-script.txt
 }
 
+ventoy_check_insmod() {
+    if [ -e $1 ]; then
+        $BUSYBOX_PATH/insmod $1
+    fi
+}
 
+ventoy_check_mount() {
+    if [ -e $1 ]; then
+        $BUSYBOX_PATH/mount $1 $2
+    fi
+}
index 21649902323a37fa70001e94108ce2be8b237999..f6bf038f11ab5ec8bc2d54dc990ca4fc5f11d16c 100644 (file)
Binary files a/INSTALL/EFI/BOOT/grubx64_real.efi and b/INSTALL/EFI/BOOT/grubx64_real.efi differ
index d62d26becd7746b726fd3d7c116b361a67f2dfb9..9be152dbf9bd235d02b489458845b76d88dc726d 100644 (file)
@@ -94,6 +94,15 @@ submenu 'Check plugin json configuration (ventoy.json)' --class=debug_json {
         unset pager
     }
     
+    menuentry 'Check dud plugin configuration' --class=debug_dud {
+        set pager=1
+        vt_check_plugin_json $vt_plugin_path dud $vtoy_iso_part
+        
+        echo -e "\npress ENTER to exit ..."
+        read vtInputKey
+        unset pager
+    }
+    
     menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET {
         echo 'Return ...'
     }
index ac0ccde9ed8881aa6c9a4f5734dc141fa962b3f5..82fdbbbeb3cfbbfe0d2c7bc0d1b943580608811f 100644 (file)
@@ -46,7 +46,7 @@ function ventoy_gui_console {
 
 function ventoy_acpi_param {  
     if [ "$VTOY_PARAM_NO_ACPI" != "1" ]; then
-        vt_acpi_param $1 $2
+        vt_acpi_param "$1" "$2"
     fi
 }
 
@@ -283,7 +283,7 @@ function distro_specify_initrd_file_phase2 {
 
 function ventoy_get_ghostbsd_ver {
 
-    # vt_parse_iso_create_date $1/${chosen_path} vt_create_date    
+    # vt_parse_iso_create_date "$1/${chosen_path}" vt_create_date    
     # if regexp "^202005" "$vt_create_date"; then
         # set vt_freebsd_ver=12.x
     # fi
@@ -322,11 +322,11 @@ function ventoy_freebsd_proc {
     set vtFreeBsdDistro=FreeBSD
 
     if vt_strstr "$vt_volume_id" "GHOSTBSD"; then
-        ventoy_get_ghostbsd_ver $1 ${chosen_path}
+        ventoy_get_ghostbsd_ver "$1" "${chosen_path}"
     elif vt_strstr "$vt_volume_id" "FREENAS"; then
-        ventoy_get_freenas_ver $1 ${chosen_path}   
+        ventoy_get_freenas_ver "$1" "${chosen_path}"
     elif vt_strstr "$vt_volume_id" "FURYBSD"; then
-        ventoy_get_furybsd_ver $1 ${chosen_path}   
+        ventoy_get_furybsd_ver "$1" "${chosen_path}"  
     elif regexp "^13_[0-9]" "$vt_volume_id"; then
         set vt_freebsd_ver=13.x
     elif regexp "^12_[0-9]" "$vt_volume_id"; then
@@ -338,7 +338,7 @@ function ventoy_freebsd_proc {
     elif regexp "^9_[0-9]" "$vt_volume_id"; then
         set vt_freebsd_ver=9.x
     elif [ -d (loop)/usr/midnightbsd-dist ]; then
-        ventoy_get_midnightbsd_ver $1 ${chosen_path}
+        ventoy_get_midnightbsd_ver "$1" "${chosen_path}"
         set vtFreeBsdDistro=MidnightBSD
     elif [ -e (loop)/bin/freebsd-version ]; then
         vt_unix_parse_freebsd_ver (loop)/bin/freebsd-version vt_userland_ver
@@ -399,7 +399,7 @@ function ventoy_freebsd_proc {
     fi
     
     vt_unix_replace_ko $vt_unix_mod_path (vtunix)/ventoy_unix/$vtFreeBsdDistro/geom_ventoy_ko/$vt_freebsd_ver/$vt_freebsd_bit/geom_ventoy.ko.xz
-    vt_unix_replace_conf FreeBSD ${1}${chosen_path} 
+    vt_unix_replace_conf FreeBSD "${1}${chosen_path}"
 }
 
 function ventoy_unix_comm_proc {
@@ -409,7 +409,7 @@ function ventoy_unix_comm_proc {
         loopback vtunix $vtoy_efi_part/ventoy/ventoy_unix.cpio
         
         if [ "$vt_unix_type" = "FreeBSD" ]; then
-            ventoy_freebsd_proc $1 ${chosen_path}        
+            ventoy_freebsd_proc "$1" "${chosen_path}"
         elif [ "$vt_unix_type" = "NetBSD" ]; then
             echo "NetBSD not supported"
             
@@ -422,7 +422,7 @@ function ventoy_unix_comm_proc {
         fi
     fi
     
-    vt_unix_chain_data ${1}${chosen_path}    
+    vt_unix_chain_data "${1}${chosen_path}"
     ventoy_debug_pause
 }
 
@@ -435,7 +435,7 @@ function uefi_windows_menu_func {
         if [ "$ventoy_fs_probe" = "iso9660" ]; then
             loopback -d loop
             vt_iso9660_nojoliet 1            
-            loopback loop $1$2
+            loopback loop "$1$2"
         fi
         
         for file in "efi/microsoft/boot/bcd"; do
@@ -451,7 +451,7 @@ function uefi_windows_menu_func {
         locate_wim
     fi
 
-    vt_windows_chain_data ${1}${chosen_path}    
+    vt_windows_chain_data "${1}${chosen_path}"
     ventoy_debug_pause
     
     if [ -n "$vtoy_chain_mem_addr" ]; then
@@ -472,10 +472,10 @@ function uefi_linux_menu_func {
         if [ "$ventoy_fs_probe" = "udf" ]; then
             loopback -d loop            
             set ventoy_fs_probe=iso9660
-            loopback loop $1$2
+            loopback loop "$1$2"
         fi
         
-        vt_load_cpio  ${vtoy_path}/ventoy.cpio   $2 $1 "busybox=$ventoy_busybox_ver"
+        vt_load_cpio  ${vtoy_path}/ventoy.cpio   "$2" "$1" "busybox=$ventoy_busybox_ver"
         
         vt_linux_clear_initrd
         
@@ -561,7 +561,7 @@ function uefi_linux_menu_func {
         
     fi
     
-    vt_linux_chain_data ${1}${chosen_path}
+    vt_linux_chain_data "${1}${chosen_path}"
 
     if [ -n "$vtoy_chain_mem_addr" ]; then
         ventoy_acpi_param ${vtoy_chain_mem_addr} 2048
@@ -575,7 +575,7 @@ function uefi_linux_menu_func {
 }
 
 function uefi_unix_menu_func {
-    ventoy_unix_comm_proc $1 ${chosen_path}
+    ventoy_unix_comm_proc $1 "${chosen_path}"
     
     if [ -n "$vtoy_chain_mem_addr" ]; then
         ventoy_acpi_param ${vtoy_chain_mem_addr} 2048
@@ -603,18 +603,18 @@ function uefi_iso_menu_func {
         unset LoadIsoEfiDriver
     fi
 
-    set chosen_path=$2
-    vt_select_auto_install ${chosen_path}
-    vt_select_persistence ${chosen_path}
+    set chosen_path="$2"
+    vt_select_auto_install "${chosen_path}"
+    vt_select_persistence "${chosen_path}"
 
-    if vt_is_udf ${1}${chosen_path}; then
+    if vt_is_udf "${1}${chosen_path}"; then
         set ventoy_fs_probe=udf
     else
         set ventoy_fs_probe=iso9660
         vt_iso9660_nojoliet 0
     fi
 
-    loopback loop ${1}${chosen_path}    
+    loopback loop "${1}${chosen_path}"
     get_os_type (loop)
     
     if [ -d (loop)/EFI ]; then
@@ -634,19 +634,19 @@ function uefi_iso_menu_func {
         vt_check_compatible (loop)        
     fi
     
-    vt_img_sector ${1}${chosen_path}
+    vt_img_sector "${1}${chosen_path}"
     
     if [ "$ventoy_fs_probe" = "iso9660" ]; then
-        vt_select_conf_replace ${1} ${chosen_path}
+        vt_select_conf_replace "${1}" "${chosen_path}"
     fi
     
     if [ "$vtoy_os" = "Windows" ]; then
         vt_check_compatible_pe (loop)        
-        uefi_windows_menu_func  $1 ${chosen_path}
+        uefi_windows_menu_func  "$1" "${chosen_path}"
     elif [ "$vtoy_os" = "Unix" ]; then
-        uefi_unix_menu_func $1 ${chosen_path}
+        uefi_unix_menu_func "$1" "${chosen_path}"
     else
-        uefi_linux_menu_func  $1 ${chosen_path}
+        uefi_linux_menu_func  "$1" "${chosen_path}"
     fi
 
     ventoy_gui_console
@@ -654,7 +654,7 @@ function uefi_iso_menu_func {
 
 function uefi_iso_memdisk {    
     echo 'Loading ISO file to memory ...'
-    vt_load_img_memdisk ${1}${2} vtoy_iso_buf
+    vt_load_img_memdisk "${1}${2}" vtoy_iso_buf
     
     ventoy_cli_console
     chainloader ${vtoy_path}/ventoy_x64.efi memdisk env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_iso_buf_addr}:size:${vtoy_iso_buf_size}
@@ -672,7 +672,7 @@ function legacy_windows_menu_func {
         if [ "$ventoy_fs_probe" = "iso9660" ]; then
             loopback -d loop
             vt_iso9660_nojoliet 1
-            loopback loop $1$2
+            loopback loop "$1$2"
         fi
         
         for file in "boot/bcd" "/efi/microsoft/boot/bcd" "SSTR/BCD"; do
@@ -690,7 +690,7 @@ function legacy_windows_menu_func {
         locate_wim
     fi
 
-    vt_windows_chain_data ${1}${chosen_path}    
+    vt_windows_chain_data "${1}${chosen_path}"
     ventoy_debug_pause    
     
     if [ -n "$vtoy_chain_mem_addr" ]; then
@@ -709,10 +709,10 @@ function legacy_linux_menu_func {
         if [ "$ventoy_fs_probe" = "udf" ]; then
             loopback -d loop
             set ventoy_fs_probe=iso9660
-            loopback loop $1$2
+            loopback loop "$1$2"
         fi
     
-        vt_load_cpio  $vtoy_path/ventoy.cpio  $2 $1 "busybox=$ventoy_busybox_ver"
+        vt_load_cpio  $vtoy_path/ventoy.cpio  "$2" "$1" "busybox=$ventoy_busybox_ver"
 
         vt_linux_clear_initrd
         
@@ -755,7 +755,7 @@ function legacy_linux_menu_func {
         locate_initrd
     fi
     
-    vt_linux_chain_data ${1}${chosen_path}    
+    vt_linux_chain_data "${1}${chosen_path}"
     ventoy_debug_pause
     
     if [ -n "$vtoy_chain_mem_addr" ]; then
@@ -770,7 +770,7 @@ function legacy_linux_menu_func {
 
 
 function legacy_unix_menu_func {    
-    ventoy_unix_comm_proc $1 ${chosen_path}
+    ventoy_unix_comm_proc $1 "${chosen_path}"
     
     if [ -n "$vtoy_chain_mem_addr" ]; then
         #ventoy_acpi_param ${vtoy_chain_mem_addr} 2048
@@ -789,18 +789,19 @@ function legacy_iso_menu_func {
         loopback -d loop
     fi
 
-    set chosen_path=$2
-    vt_select_auto_install ${chosen_path}
-    vt_select_persistence ${chosen_path}
+    set chosen_path="$2"
+    
+    vt_select_auto_install "${chosen_path}"
+    vt_select_persistence "${chosen_path}"
 
-    if vt_is_udf ${1}${chosen_path}; then
+    if vt_is_udf "${1}${chosen_path}"; then
         set ventoy_fs_probe=udf
     else
         set ventoy_fs_probe=iso9660
         vt_iso9660_nojoliet 0
     fi
     
-    loopback loop ${1}${chosen_path}
+    loopback loop "${1}${chosen_path}"
     
     get_os_type (loop)
     
@@ -813,19 +814,19 @@ function legacy_iso_menu_func {
         vt_check_compatible (loop)
     fi
     
-    vt_img_sector ${1}${chosen_path}
+    vt_img_sector "${1}${chosen_path}"
 
     if [ "$ventoy_fs_probe" = "iso9660" ]; then
-        vt_select_conf_replace ${1} ${chosen_path}
+        vt_select_conf_replace "${1}" "${chosen_path}"
     fi
 
     if [ "$vtoy_os" = "Windows" ]; then
         vt_check_compatible_pe (loop)        
-        legacy_windows_menu_func  $1 ${chosen_path}
+        legacy_windows_menu_func  "$1" "${chosen_path}"
     elif [ "$vtoy_os" = "Unix" ]; then
-        legacy_unix_menu_func $1 ${chosen_path}
+        legacy_unix_menu_func "$1" "${chosen_path}"
     else
-        legacy_linux_menu_func  $1 ${chosen_path}
+        legacy_linux_menu_func  "$1" "${chosen_path}"
     fi
 }
 
@@ -833,7 +834,7 @@ function legacy_iso_memdisk {
 
     linux16   $vtoy_path/memdisk iso raw    
     echo "Loading ISO file to memory ..."
-    initrd16  ${1}${2}
+    initrd16  "${1}${2}"
     boot
 }
 
@@ -843,11 +844,11 @@ function iso_endless_os_proc {
         loopback -d loop
     fi
 
-    loopback loop ${1}${2}   
-    vt_img_sector ${1}${2}
+    loopback loop "${1}${2}"
+    vt_img_sector "${1}${2}"
 
-    vt_load_cpio  $vtoy_path/ventoy.cpio  $2 $1  "busybox=$ventoy_busybox_ver"
-    vt_trailer_cpio $1 $2 noinit
+    vt_load_cpio  $vtoy_path/ventoy.cpio  "$2" "$1"  "busybox=$ventoy_busybox_ver"
+    vt_trailer_cpio "$1" "$2" noinit
     
     ventoy_debug_pause
 
@@ -873,7 +874,7 @@ function ventoy_iso_busybox_ver {
     
     #special process for deepin-live iso
     if [ "$vt_chosen_size" = "403701760" ]; then
-        if vt_str_str $vt_chosen_path "/deepin-live"; then
+        if vt_str_str "$vt_chosen_path" "/deepin-live"; then
             set ventoy_busybox_ver=64
         fi
     elif vt_str_begin $vt_volume_id "PHOTON_"; then
@@ -889,28 +890,28 @@ function iso_common_menuentry {
     unset vt_volume_id
     
     vt_chosen_img_path vt_chosen_path vt_chosen_size
-    vt_parse_iso_volume ${vtoy_iso_part}${vt_chosen_path} vt_system_id vt_volume_id
+    vt_parse_iso_volume "${vtoy_iso_part}${vt_chosen_path}" vt_system_id vt_volume_id
     
     ventoy_iso_busybox_ver
     
     #special process for Endless OS
     if vt_str_begin $vt_volume_id "Endless-OS"; then
-        iso_endless_os_proc $vtoy_iso_part $vt_chosen_path
+        iso_endless_os_proc $vtoy_iso_part "$vt_chosen_path"
     elif vt_str_begin $vt_volume_id "TENS-Public"; then
         set vtcompat=1
     fi
 
     if [ "$grub_platform" = "pc" ]; then
         if vt_check_mode 0; then
-            legacy_iso_memdisk $vtoy_iso_part $vt_chosen_path
+            legacy_iso_memdisk $vtoy_iso_part "$vt_chosen_path"
         else
-            legacy_iso_menu_func $vtoy_iso_part $vt_chosen_path
+            legacy_iso_menu_func $vtoy_iso_part "$vt_chosen_path"
         fi
     else
         if vt_check_mode 0; then
-            uefi_iso_memdisk $vtoy_iso_part  $vt_chosen_path
+            uefi_iso_memdisk $vtoy_iso_part  "$vt_chosen_path"
         else
-            uefi_iso_menu_func $vtoy_iso_part  $vt_chosen_path             
+            uefi_iso_menu_func $vtoy_iso_part  "$vt_chosen_path"
         fi
     fi      
 }
@@ -923,9 +924,9 @@ function miso_common_menuentry {
     ventoy_debug_pause
 
     if [ "$grub_platform" = "pc" ]; then
-        legacy_iso_memdisk $vtoy_iso_part $vt_chosen_path
+        legacy_iso_memdisk $vtoy_iso_part "$vt_chosen_path"
     else
-        uefi_iso_memdisk $vtoy_iso_part  $vt_chosen_path
+        uefi_iso_memdisk $vtoy_iso_part  "$vt_chosen_path"
     fi      
 }
 
@@ -947,7 +948,12 @@ function iso_unsupport_menuentry {
 
 function wim_common_menuentry {
     vt_chosen_img_path vt_chosen_path vt_chosen_size
-    vt_wim_chain_data ${vtoy_iso_part}${vt_chosen_path}
+    if vt_wim_check_bootable "${vtoy_iso_part}${vt_chosen_path}"; then
+        vt_wim_chain_data "${vtoy_iso_part}${vt_chosen_path}"
+    else
+        echo -e "\n This is NOT a bootable WIM file. \n"
+        echo -e " 这不是一个可启动的 WIM 文件。\n"
+    fi
     
     ventoy_debug_pause    
     
@@ -973,7 +979,7 @@ function wim_unsupport_menuentry {
 function efi_common_menuentry {
     vt_chosen_img_path vt_chosen_path vt_chosen_size
     
-    vt_concat_efi_iso ${vtoy_iso_part}${vt_chosen_path} vtoy_iso_buf
+    vt_concat_efi_iso "${vtoy_iso_part}${vt_chosen_path}" vtoy_iso_buf
     
     ventoy_debug_pause
     
@@ -985,7 +991,7 @@ function efi_common_menuentry {
     
     if [ -n "$vtoy_dotefi_retry" ]; then
         unset vtoy_dotefi_retry
-        chainloader ${vtoy_iso_part}${vt_chosen_path}
+        chainloader "${vtoy_iso_part}${vt_chosen_path}"
         boot
     fi
     
@@ -1009,7 +1015,7 @@ function vhd_common_menuentry {
     fi
 
     vt_chosen_img_path vt_chosen_path vt_chosen_size
-    vt_patch_vhdboot $vt_chosen_path
+    vt_patch_vhdboot "$vt_chosen_path"
     
     ventoy_debug_pause    
     
@@ -1038,7 +1044,7 @@ function vtoyboot_common_func {
     set AltBootPart=0
     set vtoysupport=0
     
-    vt_get_vtoy_type ${1} vtoytype parttype AltBootPart
+    vt_get_vtoy_type "${1}" vtoytype parttype AltBootPart
     
     if vt_str_begin $vtoytype vhd; then    
         set vtoysupport=1
@@ -1063,8 +1069,8 @@ function vtoyboot_common_func {
             fi
         fi
     
-        vt_img_sector ${1}
-        vt_raw_chain_data ${1}
+        vt_img_sector "${1}"
+        vt_raw_chain_data "${1}"
 
         ventoy_debug_pause
         
@@ -1092,7 +1098,7 @@ function vtoyboot_common_func {
 
 function vtoy_common_menuentry {    
     vt_chosen_img_path vt_chosen_path vt_chosen_size        
-    vtoyboot_common_func ${vtoy_iso_part}${vt_chosen_path}
+    vtoyboot_common_func "${vtoy_iso_part}${vt_chosen_path}"
 }
 
 function vtoy_unsupport_menuentry {
@@ -1107,8 +1113,8 @@ function vtoy_unsupport_menuentry {
 
 
 function ventoy_img_easyos {
-    vt_load_cpio  $vtoy_path/ventoy.cpio  ${vt_chosen_path} ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
-    vt_trailer_cpio ${vtoy_iso_part} ${vt_chosen_path} noinit
+    vt_load_cpio  $vtoy_path/ventoy.cpio  "${vt_chosen_path}" ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
+    vt_trailer_cpio ${vtoy_iso_part} "${vt_chosen_path}" noinit
     
     loopback easysfs (vtimghd,1)/easy.sfs
     vt_get_lib_module_ver (easysfs) /lib/modules/ vt_module_ver
@@ -1133,8 +1139,8 @@ function ventoy_img_easyos {
 }
 
 function ventoy_img_volumio {
-    vt_load_cpio  $vtoy_path/ventoy.cpio  ${vt_chosen_path} ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
-    vt_trailer_cpio ${vtoy_iso_part} ${vt_chosen_path} noinit
+    vt_load_cpio  $vtoy_path/ventoy.cpio  "${vt_chosen_path}" ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
+    vt_trailer_cpio ${vtoy_iso_part} "${vt_chosen_path}" noinit
 
     ventoy_debug_pause
 
@@ -1151,8 +1157,8 @@ function ventoy_img_volumio {
 function ventoy_img_openelec {
     elec_ver=$1
     
-    vt_load_cpio  $vtoy_path/ventoy.cpio  ${vt_chosen_path} ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
-    vt_trailer_cpio ${vtoy_iso_part} ${vt_chosen_path} noinit
+    vt_load_cpio  $vtoy_path/ventoy.cpio  "${vt_chosen_path}" ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
+    vt_trailer_cpio ${vtoy_iso_part} "${vt_chosen_path}" noinit
 
     loopback vtloopex $vtoy_efi_part/ventoy/vtloopex.cpio    
     vt_img_extra_initrd_append  (vtloopex)/$elec_ver/vtloopex.tar.xz
@@ -1173,8 +1179,8 @@ function ventoy_img_openelec {
 
 
 function ventoy_img_freedombox {
-    vt_load_cpio  $vtoy_path/ventoy.cpio  ${vt_chosen_path} ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
-    vt_trailer_cpio ${vtoy_iso_part} ${vt_chosen_path} noinit
+    vt_load_cpio  $vtoy_path/ventoy.cpio  "${vt_chosen_path}" ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
+    vt_trailer_cpio ${vtoy_iso_part} "${vt_chosen_path}" noinit
 
     vt_get_lib_module_ver (vtimghd,1) /lib/modules/ vt_module_ver
     if [ -n "$vt_module_ver" ]; then        
@@ -1194,8 +1200,8 @@ function ventoy_img_freedombox {
 }
 
 function ventoy_img_paldo {
-    vt_load_cpio  $vtoy_path/ventoy.cpio  ${vt_chosen_path} ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
-    vt_trailer_cpio ${vtoy_iso_part} ${vt_chosen_path} noinit
+    vt_load_cpio  $vtoy_path/ventoy.cpio  "${vt_chosen_path}" ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
+    vt_trailer_cpio ${vtoy_iso_part} "${vt_chosen_path}" noinit
 
     ventoy_debug_pause
 
@@ -1216,8 +1222,8 @@ function ventoy_img_paldo {
 }
 
 function ventoy_img_ubos {
-    vt_load_cpio  $vtoy_path/ventoy.cpio  ${vt_chosen_path} ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
-    vt_trailer_cpio ${vtoy_iso_part} ${vt_chosen_path} noinit
+    vt_load_cpio  $vtoy_path/ventoy.cpio  "${vt_chosen_path}" ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
+    vt_trailer_cpio ${vtoy_iso_part} "${vt_chosen_path}" noinit
 
     vt_get_lib_module_ver (vtimghd,3) /lib/modules/ vt_module_ver
     if [ -n "$vt_module_ver" ]; then        
@@ -1240,8 +1246,8 @@ function ventoy_img_ubos {
 }
 
 function ventoy_img_recalbox {
-    vt_load_cpio  $vtoy_path/ventoy.cpio  ${vt_chosen_path} ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
-    vt_trailer_cpio ${vtoy_iso_part} ${vt_chosen_path} noinit
+    vt_load_cpio  $vtoy_path/ventoy.cpio  "${vt_chosen_path}" ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
+    vt_trailer_cpio ${vtoy_iso_part} "${vt_chosen_path}" noinit
 
     ventoy_debug_pause
 
@@ -1257,8 +1263,8 @@ function ventoy_img_recalbox {
 }
 
 function ventoy_img_batocera {
-    vt_load_cpio  $vtoy_path/ventoy.cpio  ${vt_chosen_path} ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
-    vt_trailer_cpio ${vtoy_iso_part} ${vt_chosen_path} noinit
+    vt_load_cpio  $vtoy_path/ventoy.cpio  "${vt_chosen_path}" ${vtoy_iso_part} "busybox=$ventoy_busybox_ver"
+    vt_trailer_cpio ${vtoy_iso_part} "${vt_chosen_path}" noinit
 
     ventoy_debug_pause
 
@@ -1295,8 +1301,8 @@ function img_common_menuentry {
         loopback -d vtimghd
     fi
 
-    loopback vtimghd ${vtoy_iso_part}${vt_chosen_path}
-    vt_img_sector ${vtoy_iso_part}${vt_chosen_path}
+    loopback vtimghd "${vtoy_iso_part}${vt_chosen_path}"
+    vt_img_sector "${vtoy_iso_part}${vt_chosen_path}"
 
     vt_img_part_info (vtimghd)
 
@@ -1340,7 +1346,7 @@ function img_common_menuentry {
             ventoy_img_memtest86            
         fi
     else
-        vt_linux_chain_data ${vtoy_iso_part}${vt_chosen_path}
+        vt_linux_chain_data "${vtoy_iso_part}${vt_chosen_path}"
         ventoy_acpi_param ${vtoy_chain_mem_addr} 512
         if [ "$grub_platform" = "pc" ]; then 
             linux16 $vtoy_path/ipxe.krn ${vtdebug_flag}  sector512  mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}   
@@ -1369,7 +1375,7 @@ function img_unsupport_menuentry {
 #############################################################
 #############################################################
 
-set VENTOY_VERSION="1.0.28"
+set VENTOY_VERSION="1.0.29"
 
 #ACPI not compatible with Window7/8, so disable by default
 set VTOY_PARAM_NO_ACPI=1
index 04828f1208b6540793fac023a66fbcc2cf25e36f..627411b73034751e0e75a2ac270c63fa79fa0b8a 100644 (file)
Binary files a/INSTALL/grub/i386-pc/core.img and b/INSTALL/grub/i386-pc/core.img differ
index 2ec78500117c60c3f995bc01c232f2310f8c5a8a..6548924588d7b77f0347ebe5313bf34c428af6f3 100644 (file)
Binary files a/INSTALL/grub/i386-pc/search_fs_file.mod and b/INSTALL/grub/i386-pc/search_fs_file.mod differ
index 218adc714fbf62597c37ddb3c30dd7e6590c993e..1612551ac0a04e639b2c06d9cf9175c0106dee0a 100644 (file)
Binary files a/INSTALL/grub/i386-pc/search_fs_uuid.mod and b/INSTALL/grub/i386-pc/search_fs_uuid.mod differ
index 71f941a2e6d38f5ea3391c5fd036faafb5e37db2..73ec8182c66857bd8ba5416791e3a8be226054b7 100644 (file)
Binary files a/INSTALL/grub/i386-pc/search_label.mod and b/INSTALL/grub/i386-pc/search_label.mod differ
index 8400886527d9bbe6a70d9e6f0c8164ea2deca1ff..e82677eeede850eede89958e6a6e41b233140e4e 100644 (file)
@@ -92,12 +92,15 @@ else
         fi        
     }
     
-    menuentry 'Search and boot BOOTX64.EFI' --class=boot_uefi {    
+    menuentry 'Search and boot BOOTX64.EFI' --class=boot_uefi {
+        set VTOY_SEARCH_NO_VTOYEFI=1
         if search -n -s -f /efi/boot/bootx64.efi; then
+            unset VTOY_SEARCH_NO_VTOYEFI
             terminal_output  console
             chainloader /efi/boot/bootx64.efi
             boot
         else
+            unset VTOY_SEARCH_NO_VTOYEFI
             echo "BOOTX64.EFI NOT found ..."
         fi        
     }
index 83720396c4724d15d55d680c88acf740bdebfcd8..d02316d569dbf232dedad2ee28ab53bcb5e4f00a 100644 (file)
Binary files a/INSTALL/grub/x86_64-efi/search_fs_file.mod and b/INSTALL/grub/x86_64-efi/search_fs_file.mod differ
index 63701d19c733a7d5ea88966dd0d956ca4d809a2d..bd5f5558211f344e99a1fcbd8e4da947fb6f647b 100644 (file)
Binary files a/INSTALL/grub/x86_64-efi/search_fs_uuid.mod and b/INSTALL/grub/x86_64-efi/search_fs_uuid.mod differ
index f1b82658950550ed777a756f9a5b27da92db337d..68ce50dd0a6374638fa79a44a714abba7a4be742 100644 (file)
Binary files a/INSTALL/grub/x86_64-efi/search_label.mod and b/INSTALL/grub/x86_64-efi/search_label.mod differ
index c74d3c9cfc1abb8baaae2e5de26cd8b487d607d4..f12fbb7e0d3cbe588b880607dc2f5709fb3eebac 100644 (file)
@@ -9,6 +9,7 @@ print_usage() {
     echo '   -i  install ventoy to sdX (fail if disk already installed with ventoy)'
     echo '   -I  force install ventoy to sdX (no matter installed or not)'
     echo '   -u  update ventoy in sdX'
+    echo '   -l  list Ventoy information in sdX'
     echo ''
     echo '  OPTION: (optional)'
     echo '   -r SIZE_MB  preserve some space at the bottom of the disk (only for install)'
@@ -29,6 +30,8 @@ while [ -n "$1" ]; do
         FORCE="Y"
     elif [ "$1" = "-u" ]; then
         MODE="update"
+    elif [ "$1" = "-l" ]; then
+        MODE="list"
     elif [ "$1" = "-s" ]; then
         SECUREBOOT="YES"
     elif [ "$1" = "-g" ]; then
@@ -42,7 +45,7 @@ while [ -n "$1" ]; do
         RESERVE_SIZE_MB=$1
     elif [ "$1" = "-V" ] || [ "$1" = "--version" ]; then
         exit 0
-    elif [ "$1" == "-h" ] || [ "$1" = "--help" ]; then
+    elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
         print_usage
         exit 0
     else
@@ -76,7 +79,7 @@ if [ -e /sys/class/block/${DISK#/dev/}/start ]; then
     exit 1
 fi
 
-if [ -n "$RESERVE_SPACE" ]; then
+if [ -n "$RESERVE_SPACE" -a "$MODE" = "install" ]; then
     if echo $RESERVE_SIZE_MB | grep -q '^[0-9][0-9]*$'; then
         vtdebug "User will reserve $RESERVE_SIZE_MB MB disk space"
     else
@@ -104,6 +107,36 @@ else
     exit 1
 fi
 
+if [ "$MODE" = "list" ]; then
+    version=$(get_disk_ventoy_version $DISK)
+    if [ $? -eq 0 ]; then
+        echo "Ventoy Version in Disk: $version"
+        
+        vtPart1Type=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e  '1/1 "%02X"')
+        if [ "$vtPart1Type" = "EE" ]; then            
+            echo "Disk Partition Style  : GPT"
+        else
+            echo "Disk Partition Style  : MBR"
+        fi
+        
+        vtPART2=$(get_disk_part_name $DISK 2)        
+        rm -rf ./tmpmntp2 && mkdir ./tmpmntp2
+        mount $vtPART2 ./tmpmntp2 > /dev/null 2>&1
+
+        if [ -e ./tmpmntp2/EFI/BOOT/MokManager.efi ]; then
+            echo "Secure Boot Support   : YES"
+        else
+            echo "Secure Boot Support   : NO"
+        fi        
+        umount ./tmpmntp2 > /dev/null 2>&1
+        rm -rf ./tmpmntp2
+    else
+        echo "Ventoy Version: NA"
+    fi
+    echo ""
+    exit 0
+fi
+
 #check mountpoint
 grep "^$DISK" /proc/mounts | while read mtline; do
     mtpnt=$(echo $mtline | awk '{print $2}')
@@ -345,7 +378,7 @@ else
     SHORT_PART2=${PART2#/dev/}
     part2_start=$(cat /sys/class/block/$SHORT_PART2/start)
     
-    PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | ./tool/hexdump -n1 -e  '1/1 "%02X"')
+    PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e  '1/1 "%02X"')
     
     if [ "$PART1_TYPE" = "EE" ]; then
         vtdebug "This is GPT partition style ..."        
@@ -355,8 +388,8 @@ else
         vtdebug "This is MBR partition style ..."
         dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=440
     
-        PART1_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=446 status=none | ./tool/hexdump -n1 -e  '1/1 "%02X"')
-        PART2_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=462 status=none | ./tool/hexdump -n1 -e  '1/1 "%02X"')
+        PART1_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=446 status=none | hexdump -n1 -e  '1/1 "%02X"')
+        PART2_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=462 status=none | hexdump -n1 -e  '1/1 "%02X"')
         
         vtdebug "PART1_ACTIVE=$PART1_ACTIVE  PART2_ACTIVE=$PART2_ACTIVE"
         if [ "$PART1_ACTIVE" = "00" ] && [ "$PART2_ACTIVE" = "80" ]; then
index b4bf1db3f59cb60496197b67c9ff60c67aaf3a37..7fe771a03a5da00ec8d1535b5ae5ef99469f5d5e 100644 (file)
@@ -128,8 +128,8 @@ is_disk_contains_ventoy() {
         return
     fi
     
-    PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | ./tool/hexdump -n1 -e  '1/1 "%02X"')
-    PART2_TYPE=$(dd if=$DISK bs=1 count=1 skip=466 status=none | ./tool/hexdump -n1 -e  '1/1 "%02X"')
+    PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e  '1/1 "%02X"')
+    PART2_TYPE=$(dd if=$DISK bs=1 count=1 skip=466 status=none | hexdump -n1 -e  '1/1 "%02X"')
     
     # if [ "$PART1_TYPE" != "EE" ]; then
         # if [ "$PART2_TYPE" != "EF" ]; then
@@ -139,7 +139,7 @@ is_disk_contains_ventoy() {
         # fi
     # fi
     
-    # PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | ./tool/hexdump -n1 -e  '1/1 "%02X"')
+    # PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e  '1/1 "%02X"')
     # if [ "$PART1_TYPE" != "07" ]; then
         # vtdebug "part1 type is $PART2_TYPE not 07"
         # ventoy_false
index 88fec99c626e6707ad5adf0b759a757c504e805e..be35a22865c003091d8f181278a8d24e1ffb206f 100644 (file)
Binary files a/INSTALL/ventoy/ventoy.cpio and b/INSTALL/ventoy/ventoy.cpio differ
index a2610ef0161e13baa0e826a62b339e8fe5a3ea3a..bcff924051adcd309b3105452a146d86c30b9b31 100644 (file)
Binary files a/INSTALL/ventoy/vtoyjump32.exe and b/INSTALL/ventoy/vtoyjump32.exe differ
index 7881e63a9a324a9e05fa02994cecd892a58c8bdd..4edb6de39484296a52bbc3bc6d57592c67d2bb92 100644 (file)
Binary files a/INSTALL/ventoy/vtoyjump64.exe and b/INSTALL/ventoy/vtoyjump64.exe differ
index 41ec7803d36879d23f4f2a3be9beabc140ee2a94..f74709bc29855deefa9612758e136992d477a8f6 100644 (file)
Binary files a/LANGUAGES/languages.ini and b/LANGUAGES/languages.ini differ
index ec671f59df64728bb250d78675d2826c7442a3a9..f5e404164e5c00a1f49f9468867712da8a1a9967 100644 (file)
-/******************************************************************************
-* vtoyjump.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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <Windows.h>
-#include <virtdisk.h>
-#include <winioctl.h>
-#include <VersionHelpers.h>
-#include "vtoyjump.h"
-#include "fat_filelib.h"
-
-static ventoy_os_param g_os_param;
-static ventoy_windows_data g_windows_data;
-static UINT8 g_os_param_reserved[32];
-static BOOL g_64bit_system = FALSE;
-static ventoy_guid g_ventoy_guid = VENTOY_GUID;
-
-void Log(const char *Fmt, ...)
-{
-       va_list Arg;
-       int Len = 0;
-       FILE *File = NULL;
-       SYSTEMTIME Sys;
-       char szBuf[1024];
-
-       GetLocalTime(&Sys);
-       Len += sprintf_s(szBuf, sizeof(szBuf),
-               "[%4d/%02d/%02d %02d:%02d:%02d.%03d] ",
-               Sys.wYear, Sys.wMonth, Sys.wDay,
-               Sys.wHour, Sys.wMinute, Sys.wSecond,
-               Sys.wMilliseconds);
-
-       va_start(Arg, Fmt);
-       Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);
-       va_end(Arg);
-
-       fopen_s(&File, "ventoy.log", "a+");
-       if (File)
-       {
-               fwrite(szBuf, 1, Len, File);
-               fwrite("\n", 1, 1, File);
-               fclose(File);
-       }
-}
-
-
-static int LoadNtDriver(const char *DrvBinPath)
-{
-       int i;
-       int rc = 0;
-       BOOL Ret;
-       DWORD Status;
-       SC_HANDLE hServiceMgr;
-       SC_HANDLE hService;
-       char name[256] = { 0 };
-
-       for (i = (int)strlen(DrvBinPath) - 1; i >= 0; i--)
-       {
-               if (DrvBinPath[i] == '\\' || DrvBinPath[i] == '/')
-               {
-                       sprintf_s(name, sizeof(name), "%s", DrvBinPath + i + 1);
-                       break;
-               }
-       }
-
-       Log("Load NT driver: %s %s", DrvBinPath, name);
-
-       hServiceMgr = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
-       if (hServiceMgr == NULL)
-       {
-               Log("OpenSCManager failed Error:%u", GetLastError());
-               return 1;
-       }
-
-       Log("OpenSCManager OK");
-
-       hService = CreateServiceA(hServiceMgr,
-               name,
-               name,
-               SERVICE_ALL_ACCESS,
-               SERVICE_KERNEL_DRIVER,
-               SERVICE_DEMAND_START,
-               SERVICE_ERROR_NORMAL,
-               DrvBinPath,
-               NULL, NULL, NULL, NULL, NULL);
-       if (hService == NULL)
-       {
-               Status = GetLastError();
-               if (Status != ERROR_IO_PENDING && Status != ERROR_SERVICE_EXISTS)
-               {
-                       Log("CreateService failed v %u", Status);
-                       CloseServiceHandle(hServiceMgr);
-                       return 1;
-               }
-
-               hService = OpenServiceA(hServiceMgr, name, SERVICE_ALL_ACCESS);
-               if (hService == NULL)
-               {
-                       Log("OpenService failed %u", Status);
-                       CloseServiceHandle(hServiceMgr);
-                       return 1;
-               }
-       }
-
-       Log("CreateService imdisk OK");
-
-       Ret = StartServiceA(hService, 0, NULL);
-       if (Ret)
-       {
-               Log("StartService OK");
-       }
-       else
-       {
-               Status = GetLastError();
-               if (Status == ERROR_SERVICE_ALREADY_RUNNING)
-               {
-                       rc = 0;
-               }
-               else
-               {
-                       Log("StartService error  %u", Status);
-                       rc = 1;
-               }
-       }
-
-       CloseServiceHandle(hService);
-       CloseServiceHandle(hServiceMgr);
-
-       Log("Load NT driver %s", rc ? "failed" : "success");
-
-       return rc;
-}
-
-static int ReadWholeFile2Buf(const char *Fullpath, void **Data, DWORD *Size)
-{
-       int rc = 1;
-       DWORD FileSize;
-       DWORD dwSize;
-       HANDLE Handle;
-       BYTE *Buffer = NULL;
-
-       Log("ReadWholeFile2Buf <%s>", Fullpath);
-
-       Handle = CreateFileA(Fullpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
-       if (Handle == INVALID_HANDLE_VALUE)
-       {
-               Log("Could not open the file<%s>, error:%u", Fullpath, GetLastError());
-               goto End;
-       }
-
-       FileSize = SetFilePointer(Handle, 0, NULL, FILE_END);
-
-       Buffer = malloc(FileSize);
-       if (!Buffer)
-       {
-               Log("Failed to alloc memory size:%u", FileSize);
-               goto End;
-       }
-
-       SetFilePointer(Handle, 0, NULL, FILE_BEGIN);
-       if (!ReadFile(Handle, Buffer, FileSize, &dwSize, NULL))
-       {
-               Log("ReadFile failed, dwSize:%u  error:%u", dwSize, GetLastError());
-               goto End;
-       }
-
-       *Data = Buffer;
-       *Size = FileSize;
-
-       Log("Success read file size:%u", FileSize);
-
-       rc = 0;
-
-End:
-       SAFE_CLOSE_HANDLE(Handle);
-
-       return rc;
-}
-
-static BOOL CheckPeHead(BYTE *Head)
-{
-       UINT32 PeOffset;
-
-       if (Head[0] != 'M' || Head[1] != 'Z')
-       {
-               return FALSE;
-       }
-
-       PeOffset = *(UINT32 *)(Head + 60);
-       if (*(UINT32 *)(Head + PeOffset) != 0x00004550)
-       {
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-static BOOL IsPe64(BYTE *buffer)
-{
-       DWORD pe_off;
-
-       if (!CheckPeHead(buffer))
-       {
-               return FALSE;
-       }
-
-       pe_off = *(UINT32 *)(buffer + 60);
-       if (*(UINT16 *)(buffer + pe_off + 24) == 0x020b)
-       {
-               return TRUE;
-       }
-
-       return FALSE;
-}
-
-
-static BOOL CheckOsParam(ventoy_os_param *param)
-{
-       UINT32 i;
-       BYTE Sum = 0;
-
-       if (memcmp(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid)))
-       {
-               return FALSE;
-       }
-
-       for (i = 0; i < sizeof(ventoy_os_param); i++)
-       {
-               Sum += *((BYTE *)param + i);
-       }
-       
-       if (Sum)
-       {
-               return FALSE;
-       }
-
-       if (param->vtoy_img_location_addr % 4096)
-       {
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-static int SaveBuffer2File(const char *Fullpath, void *Buffer, DWORD Length)
-{
-       int rc = 1;
-       DWORD dwSize;
-       HANDLE Handle;
-
-       Log("SaveBuffer2File <%s> len:%u", Fullpath, Length);
-
-       Handle = CreateFileA(Fullpath, GENERIC_READ | GENERIC_WRITE,
-               FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, 0, 0);
-       if (Handle == INVALID_HANDLE_VALUE)
-       {
-               Log("Could not create new file, error:%u", GetLastError());
-               goto End;
-       }
-
-       WriteFile(Handle, Buffer, Length, &dwSize, NULL);
-
-       rc = 0;
-
-End:
-       SAFE_CLOSE_HANDLE(Handle);
-
-       return rc;
-}
-
-static BOOL IsPathExist(BOOL Dir, const char *Fmt, ...)
-{
-       va_list Arg;
-       HANDLE hFile;
-       DWORD Attr;
-       CHAR FilePath[MAX_PATH];
-
-       va_start(Arg, Fmt);
-       vsnprintf_s(FilePath, sizeof(FilePath), sizeof(FilePath), Fmt, Arg);
-       va_end(Arg);
-
-       hFile = CreateFileA(FilePath, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
-       if (INVALID_HANDLE_VALUE == hFile)
-       {
-               return FALSE;
-       }
-
-       CloseHandle(hFile);
-
-       Attr = GetFileAttributesA(FilePath);
-
-       if (Dir)
-       {
-               if ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
-               {
-                       return FALSE;
-               }
-       }
-       else
-       {
-               if (Attr & FILE_ATTRIBUTE_DIRECTORY)
-               {
-                       return FALSE;
-               }
-       }
-
-       return TRUE;
-}
-
-static int GetPhyDiskUUID(const char LogicalDrive, UINT8 *UUID, DISK_EXTENT *DiskExtent)
-{
-       BOOL Ret;
-       DWORD dwSize;
-       HANDLE Handle;
-       VOLUME_DISK_EXTENTS DiskExtents;
-       CHAR PhyPath[128];
-       UINT8 SectorBuf[512];
-
-       Log("GetPhyDiskUUID %C", LogicalDrive);
-
-       sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", LogicalDrive);
-       Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
-       if (Handle == INVALID_HANDLE_VALUE)
-       {
-               Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
-               return 1;
-       }
-
-       Ret = DeviceIoControl(Handle,
-               IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
-               NULL,
-               0,
-               &DiskExtents,
-               (DWORD)(sizeof(DiskExtents)),
-               (LPDWORD)&dwSize,
-               NULL);
-       if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
-       {
-               Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());
-               CloseHandle(Handle);
-               return 1;
-       }
-       CloseHandle(Handle);
-
-       memcpy(DiskExtent, DiskExtents.Extents, sizeof(DiskExtent));
-       Log("%C: is in PhysicalDrive%d ", LogicalDrive, DiskExtents.Extents[0].DiskNumber);
-
-       sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskExtents.Extents[0].DiskNumber);
-       Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
-       if (Handle == INVALID_HANDLE_VALUE)
-       {
-               Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
-               return 1;
-       }
-
-       if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))
-       {
-               Log("ReadFile failed, dwSize:%u  error:%u", dwSize, GetLastError());
-               CloseHandle(Handle);
-               return 1;
-       }
-       
-       memcpy(UUID, SectorBuf + 0x180, 16);
-       CloseHandle(Handle);
-       return 0;
-}
-
-int VentoyMountISOByAPI(const char *IsoPath)
-{
-       HANDLE Handle;
-       DWORD Status;
-       WCHAR wFilePath[512] = { 0 };
-       VIRTUAL_STORAGE_TYPE StorageType;
-       OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters;
-       ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters;
-
-       Log("VentoyMountISOByAPI <%s>", IsoPath);
-
-       MultiByteToWideChar(CP_ACP, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));
-
-       memset(&StorageType, 0, sizeof(StorageType));
-       memset(&OpenParameters, 0, sizeof(OpenParameters));
-       memset(&AttachParameters, 0, sizeof(AttachParameters));
-
-       OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;
-       AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
-
-       Status = OpenVirtualDisk(&StorageType, wFilePath, VIRTUAL_DISK_ACCESS_READ, 0, &OpenParameters, &Handle);
-       if (Status != ERROR_SUCCESS)
-       {
-               if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND == Status)
-               {
-                       Log("VirtualDisk for ISO file is not supported in current system");
-               }
-               else
-               {
-                       Log("Failed to open virtual disk ErrorCode:%u", Status);
-               }
-               return 1;
-       }
-
-       Log("OpenVirtualDisk success");
-
-       Status = AttachVirtualDisk(Handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME, 0, &AttachParameters, NULL);
-       if (Status != ERROR_SUCCESS)
-       {
-               Log("Failed to attach virtual disk ErrorCode:%u", Status);
-               CloseHandle(Handle);
-               return 1;
-       }
-
-       CloseHandle(Handle);
-       return 0;
-}
-
-
-static HANDLE g_FatPhyDrive;
-static UINT64 g_Part2StartSec;
-
-static int CopyFileFromFatDisk(const CHAR* SrcFile, const CHAR *DstFile)
-{
-       int rc = 1;
-       int size = 0;
-       char *buf = NULL;
-       void *flfile = NULL;
-
-       Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile, DstFile);
-
-       flfile = fl_fopen(SrcFile, "rb");
-       if (flfile)
-       {
-               fl_fseek(flfile, 0, SEEK_END);
-               size = (int)fl_ftell(flfile);
-               fl_fseek(flfile, 0, SEEK_SET);
-
-               buf = (char *)malloc(size);
-               if (buf)
-               {
-                       fl_fread(buf, 1, size, flfile);
-
-                       rc = 0;
-                       SaveBuffer2File(DstFile, buf, size);
-                       free(buf);
-               }
-
-               fl_fclose(flfile);
-       }
-
-       return rc;
-}
-
-static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
-{
-       DWORD dwSize;
-       BOOL bRet;
-       DWORD ReadSize;
-       LARGE_INTEGER liCurrentPosition;
-
-       liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
-       liCurrentPosition.QuadPart *= 512;
-       SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
-
-       ReadSize = (DWORD)(SectorCount * 512);
-
-       bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
-       if (bRet == FALSE || dwSize != ReadSize)
-       {
-               Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, GetLastError());
-       }
-
-       return 1;
-}
-
-static CHAR GetMountLogicalDrive(void)
-{
-       CHAR Letter = 'Y';
-       DWORD Drives;
-       DWORD Mask = 0x1000000;
-
-       Drives = GetLogicalDrives();
-    Log("Drives=0x%x", Drives);
-    
-       while (Mask)
-       {
-               if ((Drives & Mask) == 0)
-               {
-                       break;
-               }
-
-               Letter--;
-               Mask >>= 1;
-       }
-
-       return Letter;
-}
-
-UINT64 GetVentoyEfiPartStartSector(HANDLE hDrive)
-{
-       BOOL bRet;
-       DWORD dwSize; 
-       MBR_HEAD MBR;   
-       VTOY_GPT_INFO *pGpt = NULL;
-       UINT64 StartSector = 0;
-
-       SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
-
-       bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
-       Log("Read MBR Ret:%u Size:%u code:%u", bRet, dwSize, LASTERR);
-
-       if ((!bRet) || (dwSize != sizeof(MBR)))
-       {
-               0;
-       }
-
-       if (MBR.PartTbl[0].FsFlag == 0xEE)
-       {
-               Log("GPT partition style");
-
-               pGpt = malloc(sizeof(VTOY_GPT_INFO));
-               if (!pGpt)
-               {
-                       return 0;
-               }
-
-               SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
-               bRet = ReadFile(hDrive, pGpt, sizeof(VTOY_GPT_INFO), &dwSize, NULL);            
-               if ((!bRet) || (dwSize != sizeof(VTOY_GPT_INFO)))
-               {
-                       Log("Failed to read gpt info %d %u %d", bRet, dwSize, LASTERR);
-                       return 0;
-               }
-
-               StartSector = pGpt->PartTbl[1].StartLBA;
-               free(pGpt);
-       }
-       else
-       {
-               Log("MBR partition style");
-               StartSector = MBR.PartTbl[1].StartSectorId;
-       }
-
-       Log("GetVentoyEfiPart StartSector: %llu", StartSector);
-       return StartSector;
-}
-
-int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive)
-{
-       int rc = 1;
-       BOOL bRet;
-       CHAR Letter;
-       DWORD dwBytes;
-       HANDLE hDrive;
-       CHAR PhyPath[MAX_PATH];
-       STARTUPINFOA Si;
-       PROCESS_INFORMATION Pi;
-       GET_LENGTH_INFORMATION LengthInfo;
-
-       Log("VentoyMountISOByImdisk %s", IsoPath);
-
-       sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", PhyDrive);
-       hDrive = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
-       if (hDrive == INVALID_HANDLE_VALUE)
-       {
-               Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
-               goto End;
-       }
-
-       bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);
-       if (!bRet)
-       {
-               Log("Could not get phy disk %s size, error:%u", PhyPath, GetLastError());
-               goto End;
-       }
-
-       g_FatPhyDrive = hDrive;
-       g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);
-
-       Log("Parse FAT fs...");
-
-       fl_init();
-
-       if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
-       {
-               if (g_64bit_system)
-               {
-                       CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");
-                       CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");
-                       CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");
-               }
-               else
-               {
-                       CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");
-                       CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");
-                       CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");
-               }
-               
-               GetCurrentDirectoryA(sizeof(PhyPath), PhyPath);
-               strcat_s(PhyPath, sizeof(PhyPath), "\\ventoy\\imdisk.sys");
-
-               if (LoadNtDriver(PhyPath) == 0)
-               {
-                       rc = 0;
-
-                       Letter = GetMountLogicalDrive();
-            sprintf_s(PhyPath, sizeof(PhyPath), "ventoy\\imdisk.exe -a -o ro -f %s -m %C:", IsoPath, Letter);
-
-                       Log("mount iso to %C: use imdisk cmd <%s>", Letter, PhyPath);
-
-            GetStartupInfoA(&Si);
-
-            Si.dwFlags |= STARTF_USESHOWWINDOW;
-            Si.wShowWindow = SW_HIDE;
-
-                       CreateProcessA(NULL, PhyPath, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
-                       WaitForSingleObject(Pi.hProcess, INFINITE);
-               }
-       }
-       fl_shutdown();
-
-End:
-
-       SAFE_CLOSE_HANDLE(hDrive);
-
-       return rc;
-}
-
-static int MountIsoFile(CONST CHAR *IsoPath, DWORD PhyDrive)
-{
-    if (IsWindows8OrGreater())
-    {
-        Log("This is Windows 8 or latter...");
-        if (VentoyMountISOByAPI(IsoPath) == 0)
-        {
-            Log("Mount iso by API success");
-            return 0;
-        }
-        else
-        {
-            Log("Mount iso by API failed, maybe not supported, try imdisk");
-            return VentoyMountISOByImdisk(IsoPath, PhyDrive);
-        }
-    }
-    else
-    {
-        Log("This is before Windows 8 ...");
-        if (VentoyMountISOByImdisk(IsoPath, PhyDrive) == 0)
-        {
-            Log("Mount iso by imdisk success");
-            return 0;
-        }
-        else
-        {
-            return VentoyMountISOByAPI(IsoPath);
-        }
-    }
-}
-
-static int GetPhyDriveByLogicalDrive(int DriveLetter)
-{
-    BOOL Ret;
-    DWORD dwSize;
-    HANDLE Handle;
-    VOLUME_DISK_EXTENTS DiskExtents;
-    CHAR PhyPath[128];
-
-    sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", (CHAR)DriveLetter);
-
-    Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
-    if (Handle == INVALID_HANDLE_VALUE)
-    {
-        Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
-        return -1;
-    }
-
-    Ret = DeviceIoControl(Handle,
-        IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
-        NULL,
-        0,
-        &DiskExtents,
-        (DWORD)(sizeof(DiskExtents)),
-        (LPDWORD)&dwSize,
-        NULL);
-
-    if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
-    {
-        Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, GetLastError());
-        SAFE_CLOSE_HANDLE(Handle);
-        return -1;
-    }
-    SAFE_CLOSE_HANDLE(Handle);
-
-    Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
-        PhyPath,
-        DiskExtents.Extents[0].DiskNumber,
-        DiskExtents.Extents[0].StartingOffset.QuadPart,
-        DiskExtents.Extents[0].ExtentLength.QuadPart
-        );
-
-    return (int)DiskExtents.Extents[0].DiskNumber;
-}
-
-
-static int DeleteVentoyPart2MountPoint(DWORD PhyDrive)
-{
-    CHAR Letter = 'A';
-    DWORD Drives;
-    DWORD PhyDisk;
-    CHAR DriveName[] = "?:\\";
-
-    Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive);
-
-    Drives = GetLogicalDrives();
-    while (Drives)
-    {
-        if ((Drives & 0x01) && IsPathExist(FALSE, "%C:\\ventoy\\ventoy.cpio", Letter))
-        {
-            Log("File %C:\\ventoy\\ventoy.cpio exist", Letter);
-
-            PhyDisk = GetPhyDriveByLogicalDrive(Letter);
-            Log("PhyDisk=%u for %C", PhyDisk, Letter);
-
-            if (PhyDisk == PhyDrive)
-            {
-                DriveName[0] = Letter;
-                DeleteVolumeMountPointA(DriveName);
-                return 0;
-            }
-        }
-
-        Letter++;
-        Drives >>= 1;
-    }
-
-    return 1;
-}
-
-static BOOL check_tar_archive(const char *archive, CHAR *tarName)
-{
-    int len;
-    int nameLen;
-    const char *pos = archive;
-    const char *slash = archive;
-
-    while (*pos)
-    {
-        if (*pos == '\\' || *pos == '/')
-        {
-            slash = pos;
-        }
-        pos++;
-    }
-
-    len = (int)strlen(slash);
-
-    if (len > 7 && (strncmp(slash + len - 7, ".tar.gz", 7) == 0 || strncmp(slash + len - 7, ".tar.xz", 7) == 0))
-    {
-        nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
-        tarName[nameLen - 3] = 0;
-        return TRUE;
-    }
-    else if (len > 8 && strncmp(slash + len - 8, ".tar.bz2", 8) == 0)
-    {
-        nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
-        tarName[nameLen - 4] = 0;
-        return TRUE;
-    }
-    else if (len > 9 && strncmp(slash + len - 9, ".tar.lzma", 9) == 0)
-    {
-        nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
-        tarName[nameLen - 5] = 0;
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive)
-{
-    int rc = 1;
-    BOOL bRet;
-    DWORD dwBytes;
-    HANDLE hDrive;
-    HANDLE hOut;
-    DWORD flags = CREATE_NO_WINDOW;
-    CHAR StrBuf[MAX_PATH];
-    CHAR tarName[MAX_PATH];
-    STARTUPINFOA Si;
-    PROCESS_INFORMATION Pi;
-    PROCESS_INFORMATION NewPi;
-    GET_LENGTH_INFORMATION LengthInfo;
-    SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
-
-    Log("DecompressInjectionArchive %s", archive);
-
-    sprintf_s(StrBuf, sizeof(StrBuf), "\\\\.\\PhysicalDrive%d", PhyDrive);
-    hDrive = CreateFileA(StrBuf, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
-    if (hDrive == INVALID_HANDLE_VALUE)
-    {
-        Log("Could not open the disk<%s>, error:%u", StrBuf, GetLastError());
-        goto End;
-    }
-
-    bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);
-    if (!bRet)
-    {
-        Log("Could not get phy disk %s size, error:%u", StrBuf, GetLastError());
-        goto End;
-    }
-
-    g_FatPhyDrive = hDrive;
-       g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);
-
-    Log("Parse FAT fs...");
-
-    fl_init();
-
-    if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
-    {
-        if (g_64bit_system)
-        {
-            CopyFileFromFatDisk("/ventoy/7z/64/7za.exe", "ventoy\\7za.exe");
-        }
-        else
-        {
-            CopyFileFromFatDisk("/ventoy/7z/32/7za.exe", "ventoy\\7za.exe");
-        }
-
-        sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive);
-
-        Log("extract inject to X:");
-        Log("cmdline:<%s>", StrBuf);
-
-        GetStartupInfoA(&Si);
-
-        hOut = CreateFileA("ventoy\\7z.log",
-            FILE_APPEND_DATA,
-            FILE_SHARE_WRITE | FILE_SHARE_READ,
-            &Sa,
-            OPEN_ALWAYS,
-            FILE_ATTRIBUTE_NORMAL,
-            NULL);
-
-        Si.dwFlags |= STARTF_USESTDHANDLES;
-
-        if (hOut != INVALID_HANDLE_VALUE)
-        {
-            Si.hStdError = hOut;
-            Si.hStdOutput = hOut;
-        }
-
-        CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi);
-        WaitForSingleObject(Pi.hProcess, INFINITE);
-
-        //
-        // decompress tar archive, for tar.gz/tar.xz/tar.bz2
-        //
-        if (check_tar_archive(archive, tarName))
-        {
-            Log("Decompress tar archive...<%s>", tarName);
-
-            sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName);
-
-            CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &NewPi);
-            WaitForSingleObject(NewPi.hProcess, INFINITE);
-
-            Log("Now delete %s", tarName);
-            DeleteFileA(tarName);
-        }
-
-        SAFE_CLOSE_HANDLE(hOut);
-    }
-    fl_shutdown();
-
-End:
-
-    SAFE_CLOSE_HANDLE(hDrive);
-
-    return rc;
-}
-
-static int ProcessUnattendedInstallation(const char *script)
-{
-    DWORD dw;
-    HKEY hKey;
-    LSTATUS Ret;
-    CHAR Letter;
-    CHAR CurDir[MAX_PATH];
-
-    Log("Copy unattended XML ...");
-    
-    GetCurrentDirectory(sizeof(CurDir), CurDir);
-    Letter = CurDir[0];
-    if ((Letter >= 'A' && Letter <= 'Z') || (Letter >= 'a' && Letter <= 'z'))
-    {
-        Log("Current Drive Letter: %C", Letter);
-    }
-    else
-    {
-        Letter = 'X';
-    }
-    
-    sprintf_s(CurDir, sizeof(CurDir), "%C:\\Autounattend.xml", Letter);
-    Log("Copy file <%s> --> <%s>", script, CurDir);
-    CopyFile(script, CurDir, FALSE);
-
-    Ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dw);
-    if (ERROR_SUCCESS == Ret)
-    {
-        Ret = RegSetValueEx(hKey, "UnattendFile", 0, REG_SZ, CurDir, (DWORD)(strlen(CurDir) + 1));
-    }
-
-    return 0;
-}
-
-static int VentoyHook(ventoy_os_param *param)
-{
-    int rc;
-       CHAR Letter = 'A';
-       DISK_EXTENT DiskExtent;
-       DWORD Drives = GetLogicalDrives();
-       UINT8 UUID[16];
-       CHAR IsoPath[MAX_PATH];
-
-       Log("Logical Drives=0x%x Path:<%s>", Drives, param->vtoy_img_path);
-
-       while (Drives)
-       {
-        if (Drives & 0x01)
-        {
-            sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);
-            if (IsPathExist(FALSE, "%s", IsoPath))
-            {
-                Log("File exist under %C:", Letter);
-                if (GetPhyDiskUUID(Letter, UUID, &DiskExtent) == 0)
-                {
-                    if (memcmp(UUID, param->vtoy_disk_guid, 16) == 0)
-                    {
-                        Log("Disk UUID match");
-                        break;
-                    }
-                }
-            }
-            else
-            {
-                Log("File NOT exist under %C:", Letter);
-            }
-        }
-
-               Drives >>= 1;
-               Letter++;
-       }
-
-       if (Drives == 0)
-       {
-               Log("Failed to find ISO file");
-               return 1;
-       }
-
-       Log("Find ISO file <%s>", IsoPath);
-    
-    rc = MountIsoFile(IsoPath, DiskExtent.DiskNumber);
-    Log("Mount ISO FILE: %s", rc == 0 ? "SUCCESS" : "FAILED");
-
-    // for protect
-    rc = DeleteVentoyPart2MountPoint(DiskExtent.DiskNumber);
-    Log("Delete ventoy mountpoint: %s", rc == 0 ? "SUCCESS" : "NO NEED");
-    
-    if (g_windows_data.auto_install_script[0])
-    {
-        sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.auto_install_script);
-        if (IsPathExist(FALSE, "%s", IsoPath))
-        {
-            Log("use auto install script %s...", IsoPath);
-            ProcessUnattendedInstallation(IsoPath);
-        }
-        else
-        {
-            Log("auto install script %s not exist", IsoPath);
-        }
-    }
-    else
-    {
-        Log("auto install no need");
-    }
-
-    if (g_windows_data.injection_archive[0])
-    {
-        sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.injection_archive);
-        if (IsPathExist(FALSE, "%s", IsoPath))
-        {
-            Log("decompress injection archive %s...", IsoPath);
-            DecompressInjectionArchive(IsoPath, DiskExtent.DiskNumber);
-        }
-        else
-        {
-            Log("injection archive %s not exist", IsoPath);
-        }
-    }
-    else
-    {
-        Log("no injection archive found");
-    }
-
-    return 0;
-}
-
-const char * GetFileNameInPath(const char *fullpath)
-{
-       int i;
-       const char *pos = NULL;
-
-       if (strstr(fullpath, ":"))
-       {
-               for (i = (int)strlen(fullpath); i > 0; i--)
-               {
-                       if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\')
-                       {
-                               return fullpath + i;
-                       }
-               }
-       }
-       
-       return fullpath;
-}
-
-int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
-{
-       int rc = 1;
-       DWORD Pos;
-       DWORD PeStart;
-    DWORD FileSize;
-       BYTE *Buffer = NULL; 
-       CHAR ExeFileName[MAX_PATH];
-
-       sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]);
-       if (!IsPathExist(FALSE, "%s", ExeFileName))
-       {
-               Log("File %s NOT exist, now try %s.exe", ExeFileName, ExeFileName);
-               sprintf_s(ExeFileName, sizeof(ExeFileName), "%s.exe", argv[0]);
-
-               Log("File %s exist ? %s", ExeFileName, IsPathExist(FALSE, "%s", ExeFileName) ? "YES" : "NO");
-       }
-
-       if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize))
-       {
-               goto End;
-       }
-       
-       g_64bit_system = IsPe64(Buffer);
-
-       if (!IsPathExist(TRUE, "ventoy"))
-       {
-               if (!CreateDirectoryA("ventoy", NULL))
-               {
-                       Log("Failed to create ventoy directory err:%u", GetLastError());
-                       goto End;
-               }
-       }
-
-       for (PeStart = 0; PeStart < FileSize; PeStart += 16)
-       {
-               if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) && 
-            CheckPeHead(Buffer + PeStart + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data)))
-               {
-                       Log("Find os pararm at %u", PeStart);
-
-            memcpy(&g_os_param, Buffer + PeStart, sizeof(ventoy_os_param));
-            memcpy(&g_windows_data, Buffer + PeStart + sizeof(ventoy_os_param), sizeof(ventoy_windows_data));            
-            memcpy(g_os_param_reserved, g_os_param.vtoy_reserved, sizeof(g_os_param_reserved));
-
-            if (g_os_param_reserved[0] == 1)
-                       {
-                               Log("break here for debug .....");
-                               goto End;
-                       }
-
-                       // convert / to \\   
-            for (Pos = 0; Pos < sizeof(g_os_param.vtoy_img_path) && g_os_param.vtoy_img_path[Pos]; Pos++)
-                       {
-                if (g_os_param.vtoy_img_path[Pos] == '/')
-                               {
-                    g_os_param.vtoy_img_path[Pos] = '\\';
-                               }
-                       }
-
-                       PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data);
-                       sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName));
-                       SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart);
-                       break;
-               }
-       }
-
-       if (PeStart >= FileSize)
-       {
-               Log("OS param not found");
-               goto End;
-       }
-
-    if (g_os_param_reserved[0] == 2)
-    {
-        Log("skip hook for debug .....");
-        rc = 0;
-        goto End;
-    }
-
-    rc = VentoyHook(&g_os_param);
-
-End:
-
-       if (Buffer)
-       {
-               free(Buffer);
-       }
-
-       return rc;
-}
-
-int main(int argc, char **argv)
-{
-    int i = 0;
-    int rc = 0;
-       CHAR *Pos = NULL;
-       CHAR CurDir[MAX_PATH];
-       CHAR LunchFile[MAX_PATH];
-       STARTUPINFOA Si;
-       PROCESS_INFORMATION Pi;
-
-       if (argv[0] && argv[0][0] && argv[0][1] == ':')
-       {
-               GetCurrentDirectoryA(sizeof(CurDir), CurDir);
-
-               strcpy_s(LunchFile, sizeof(LunchFile), argv[0]);
-               Pos = (char *)GetFileNameInPath(LunchFile);
-
-               strcat_s(CurDir, sizeof(CurDir), "\\");
-               strcat_s(CurDir, sizeof(CurDir), Pos);
-               
-               if (_stricmp(argv[0], CurDir) != 0)
-               {
-                       *Pos = 0;
-                       SetCurrentDirectoryA(LunchFile);
-               }
-       }
-
-       Log("######## VentoyJump ##########");
-       Log("argc = %d argv[0] = <%s>", argc, argv[0]);
-
-       if (Pos && *Pos == 0)
-       {
-               Log("Old current directory = <%s>", CurDir);
-               Log("New current directory = <%s>", LunchFile);
-       }
-       else
-       {
-               GetCurrentDirectoryA(sizeof(CurDir), CurDir);
-               Log("Current directory = <%s>", CurDir);
-       }
-
-    GetStartupInfoA(&Si);
-
-    memset(LunchFile, 0, sizeof(LunchFile));
-    rc = VentoyJump(argc, argv, LunchFile);
-
-    if (g_os_param_reserved[0] == 3)
-    {
-        Log("Open log for debug ...");
-        sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log");
-    }
-    else
-    {
-        Si.dwFlags |= STARTF_USESHOWWINDOW;
-        Si.wShowWindow = SW_HIDE;
-        Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed");
-    }
-
-       CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
-
-    while (rc)
-    {
-        Log("Ventoy hook failed, now wait and retry ...");
-        Sleep(1000);
-
-        rc = VentoyHook(&g_os_param);
-    }
-
-       WaitForSingleObject(Pi.hProcess, INFINITE);
-
-       return 0;
-}
+/******************************************************************************\r
+* vtoyjump.c\r
+*\r
+* Copyright (c) 2020, longpanda <admin@ventoy.net>\r
+*\r
+* This program is free software; you can redistribute it and/or\r
+* modify it under the terms of the GNU General Public License as\r
+* published by the Free Software Foundation; either version 3 of the\r
+* License, or (at your option) any later version.\r
+*\r
+* This program is distributed in the hope that it will be useful, but\r
+* WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+* General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <Windows.h>\r
+#include <virtdisk.h>\r
+#include <winioctl.h>\r
+#include <VersionHelpers.h>\r
+#include "vtoyjump.h"\r
+#include "fat_filelib.h"\r
+\r
+static ventoy_os_param g_os_param;\r
+static ventoy_windows_data g_windows_data;\r
+static UINT8 g_os_param_reserved[32];\r
+static BOOL g_64bit_system = FALSE;\r
+static ventoy_guid g_ventoy_guid = VENTOY_GUID;\r
+\r
+void Log(const char *Fmt, ...)\r
+{\r
+       va_list Arg;\r
+       int Len = 0;\r
+       FILE *File = NULL;\r
+       SYSTEMTIME Sys;\r
+       char szBuf[1024];\r
+\r
+       GetLocalTime(&Sys);\r
+       Len += sprintf_s(szBuf, sizeof(szBuf),\r
+               "[%4d/%02d/%02d %02d:%02d:%02d.%03d] ",\r
+               Sys.wYear, Sys.wMonth, Sys.wDay,\r
+               Sys.wHour, Sys.wMinute, Sys.wSecond,\r
+               Sys.wMilliseconds);\r
+\r
+       va_start(Arg, Fmt);\r
+       Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);\r
+       va_end(Arg);\r
+\r
+       fopen_s(&File, "ventoy.log", "a+");\r
+       if (File)\r
+       {\r
+               fwrite(szBuf, 1, Len, File);\r
+               fwrite("\n", 1, 1, File);\r
+               fclose(File);\r
+       }\r
+}\r
+\r
+\r
+static int LoadNtDriver(const char *DrvBinPath)\r
+{\r
+       int i;\r
+       int rc = 0;\r
+       BOOL Ret;\r
+       DWORD Status;\r
+       SC_HANDLE hServiceMgr;\r
+       SC_HANDLE hService;\r
+       char name[256] = { 0 };\r
+\r
+       for (i = (int)strlen(DrvBinPath) - 1; i >= 0; i--)\r
+       {\r
+               if (DrvBinPath[i] == '\\' || DrvBinPath[i] == '/')\r
+               {\r
+                       sprintf_s(name, sizeof(name), "%s", DrvBinPath + i + 1);\r
+                       break;\r
+               }\r
+       }\r
+\r
+       Log("Load NT driver: %s %s", DrvBinPath, name);\r
+\r
+       hServiceMgr = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);\r
+       if (hServiceMgr == NULL)\r
+       {\r
+               Log("OpenSCManager failed Error:%u", GetLastError());\r
+               return 1;\r
+       }\r
+\r
+       Log("OpenSCManager OK");\r
+\r
+       hService = CreateServiceA(hServiceMgr,\r
+               name,\r
+               name,\r
+               SERVICE_ALL_ACCESS,\r
+               SERVICE_KERNEL_DRIVER,\r
+               SERVICE_DEMAND_START,\r
+               SERVICE_ERROR_NORMAL,\r
+               DrvBinPath,\r
+               NULL, NULL, NULL, NULL, NULL);\r
+       if (hService == NULL)\r
+       {\r
+               Status = GetLastError();\r
+               if (Status != ERROR_IO_PENDING && Status != ERROR_SERVICE_EXISTS)\r
+               {\r
+                       Log("CreateService failed v %u", Status);\r
+                       CloseServiceHandle(hServiceMgr);\r
+                       return 1;\r
+               }\r
+\r
+               hService = OpenServiceA(hServiceMgr, name, SERVICE_ALL_ACCESS);\r
+               if (hService == NULL)\r
+               {\r
+                       Log("OpenService failed %u", Status);\r
+                       CloseServiceHandle(hServiceMgr);\r
+                       return 1;\r
+               }\r
+       }\r
+\r
+       Log("CreateService imdisk OK");\r
+\r
+       Ret = StartServiceA(hService, 0, NULL);\r
+       if (Ret)\r
+       {\r
+               Log("StartService OK");\r
+       }\r
+       else\r
+       {\r
+               Status = GetLastError();\r
+               if (Status == ERROR_SERVICE_ALREADY_RUNNING)\r
+               {\r
+                       rc = 0;\r
+               }\r
+               else\r
+               {\r
+                       Log("StartService error  %u", Status);\r
+                       rc = 1;\r
+               }\r
+       }\r
+\r
+       CloseServiceHandle(hService);\r
+       CloseServiceHandle(hServiceMgr);\r
+\r
+       Log("Load NT driver %s", rc ? "failed" : "success");\r
+\r
+       return rc;\r
+}\r
+\r
+static int ReadWholeFile2Buf(const char *Fullpath, void **Data, DWORD *Size)\r
+{\r
+       int rc = 1;\r
+       DWORD FileSize;\r
+       DWORD dwSize;\r
+       HANDLE Handle;\r
+       BYTE *Buffer = NULL;\r
+\r
+       Log("ReadWholeFile2Buf <%s>", Fullpath);\r
+\r
+       Handle = CreateFileA(Fullpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+       if (Handle == INVALID_HANDLE_VALUE)\r
+       {\r
+               Log("Could not open the file<%s>, error:%u", Fullpath, GetLastError());\r
+               goto End;\r
+       }\r
+\r
+       FileSize = SetFilePointer(Handle, 0, NULL, FILE_END);\r
+\r
+       Buffer = malloc(FileSize);\r
+       if (!Buffer)\r
+       {\r
+               Log("Failed to alloc memory size:%u", FileSize);\r
+               goto End;\r
+       }\r
+\r
+       SetFilePointer(Handle, 0, NULL, FILE_BEGIN);\r
+       if (!ReadFile(Handle, Buffer, FileSize, &dwSize, NULL))\r
+       {\r
+               Log("ReadFile failed, dwSize:%u  error:%u", dwSize, GetLastError());\r
+               goto End;\r
+       }\r
+\r
+       *Data = Buffer;\r
+       *Size = FileSize;\r
+\r
+       Log("Success read file size:%u", FileSize);\r
+\r
+       rc = 0;\r
+\r
+End:\r
+       SAFE_CLOSE_HANDLE(Handle);\r
+\r
+       return rc;\r
+}\r
+\r
+static BOOL CheckPeHead(BYTE *Head)\r
+{\r
+       UINT32 PeOffset;\r
+\r
+       if (Head[0] != 'M' || Head[1] != 'Z')\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       PeOffset = *(UINT32 *)(Head + 60);\r
+       if (*(UINT32 *)(Head + PeOffset) != 0x00004550)\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+static BOOL IsPe64(BYTE *buffer)\r
+{\r
+       DWORD pe_off;\r
+\r
+       if (!CheckPeHead(buffer))\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       pe_off = *(UINT32 *)(buffer + 60);\r
+       if (*(UINT16 *)(buffer + pe_off + 24) == 0x020b)\r
+       {\r
+               return TRUE;\r
+       }\r
+\r
+       return FALSE;\r
+}\r
+\r
+\r
+static BOOL CheckOsParam(ventoy_os_param *param)\r
+{\r
+       UINT32 i;\r
+       BYTE Sum = 0;\r
+\r
+       if (memcmp(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid)))\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       for (i = 0; i < sizeof(ventoy_os_param); i++)\r
+       {\r
+               Sum += *((BYTE *)param + i);\r
+       }\r
+       \r
+       if (Sum)\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       if (param->vtoy_img_location_addr % 4096)\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+static int SaveBuffer2File(const char *Fullpath, void *Buffer, DWORD Length)\r
+{\r
+       int rc = 1;\r
+       DWORD dwSize;\r
+       HANDLE Handle;\r
+\r
+       Log("SaveBuffer2File <%s> len:%u", Fullpath, Length);\r
+\r
+       Handle = CreateFileA(Fullpath, GENERIC_READ | GENERIC_WRITE,\r
+               FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, 0, 0);\r
+       if (Handle == INVALID_HANDLE_VALUE)\r
+       {\r
+               Log("Could not create new file, error:%u", GetLastError());\r
+               goto End;\r
+       }\r
+\r
+       WriteFile(Handle, Buffer, Length, &dwSize, NULL);\r
+\r
+       rc = 0;\r
+\r
+End:\r
+       SAFE_CLOSE_HANDLE(Handle);\r
+\r
+       return rc;\r
+}\r
+\r
+static int IsUTF8Encode(const char *src)\r
+{\r
+    int i;\r
+    const UCHAR *Byte = (const UCHAR *)src;\r
+\r
+    for (i = 0; i < MAX_PATH && Byte[i]; i++)\r
+    {\r
+        if (Byte[i] > 127)\r
+        {\r
+            return 1;\r
+        }\r
+    }\r
+    \r
+    return 0;\r
+}\r
+\r
+static int Utf8ToUtf16(const char* src, WCHAR * dst)\r
+{\r
+    int size = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, 0);\r
+    return MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size + 1);\r
+}\r
+\r
+static BOOL IsPathExist(BOOL Dir, const char *Fmt, ...)\r
+{\r
+       va_list Arg;\r
+       HANDLE hFile;\r
+       DWORD Attr;\r
+    int UTF8 = 0;\r
+       CHAR FilePathA[MAX_PATH];\r
+       WCHAR FilePathW[MAX_PATH];\r
+\r
+       va_start(Arg, Fmt);\r
+       vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);\r
+       va_end(Arg);\r
+\r
+    UTF8 = IsUTF8Encode(FilePathA);\r
+\r
+    if (UTF8)\r
+    {\r
+        Utf8ToUtf16(FilePathA, FilePathW);\r
+        hFile = CreateFileW(FilePathW, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);\r
+    }\r
+    else\r
+    {\r
+        hFile = CreateFileA(FilePathA, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);\r
+    }\r
+       if (INVALID_HANDLE_VALUE == hFile)\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       CloseHandle(hFile);\r
+\r
+    if (UTF8)\r
+    {\r
+        Attr = GetFileAttributesW(FilePathW);\r
+    }\r
+    else\r
+    {\r
+        Attr = GetFileAttributesA(FilePathA);\r
+    }\r
+       \r
+       if (Dir)\r
+       {\r
+               if ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0)\r
+               {\r
+                       return FALSE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (Attr & FILE_ATTRIBUTE_DIRECTORY)\r
+               {\r
+                       return FALSE;\r
+               }\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+static int GetPhyDiskUUID(const char LogicalDrive, UINT8 *UUID, DISK_EXTENT *DiskExtent)\r
+{\r
+       BOOL Ret;\r
+       DWORD dwSize;\r
+       HANDLE Handle;\r
+       VOLUME_DISK_EXTENTS DiskExtents;\r
+       CHAR PhyPath[128];\r
+       UINT8 SectorBuf[512];\r
+\r
+       Log("GetPhyDiskUUID %C", LogicalDrive);\r
+\r
+       sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", LogicalDrive);\r
+       Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+       if (Handle == INVALID_HANDLE_VALUE)\r
+       {\r
+               Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());\r
+               return 1;\r
+       }\r
+\r
+       Ret = DeviceIoControl(Handle,\r
+               IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,\r
+               NULL,\r
+               0,\r
+               &DiskExtents,\r
+               (DWORD)(sizeof(DiskExtents)),\r
+               (LPDWORD)&dwSize,\r
+               NULL);\r
+       if (!Ret || DiskExtents.NumberOfDiskExtents == 0)\r
+       {\r
+               Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());\r
+               CloseHandle(Handle);\r
+               return 1;\r
+       }\r
+       CloseHandle(Handle);\r
+\r
+       memcpy(DiskExtent, DiskExtents.Extents, sizeof(DiskExtent));\r
+       Log("%C: is in PhysicalDrive%d ", LogicalDrive, DiskExtents.Extents[0].DiskNumber);\r
+\r
+       sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskExtents.Extents[0].DiskNumber);\r
+       Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+       if (Handle == INVALID_HANDLE_VALUE)\r
+       {\r
+               Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());\r
+               return 1;\r
+       }\r
+\r
+       if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))\r
+       {\r
+               Log("ReadFile failed, dwSize:%u  error:%u", dwSize, GetLastError());\r
+               CloseHandle(Handle);\r
+               return 1;\r
+       }\r
+       \r
+       memcpy(UUID, SectorBuf + 0x180, 16);\r
+       CloseHandle(Handle);\r
+       return 0;\r
+}\r
+\r
+int VentoyMountISOByAPI(const char *IsoPath)\r
+{\r
+       HANDLE Handle;\r
+       DWORD Status;\r
+       WCHAR wFilePath[512] = { 0 };\r
+       VIRTUAL_STORAGE_TYPE StorageType;\r
+       OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters;\r
+       ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters;\r
+\r
+       Log("VentoyMountISOByAPI <%s>", IsoPath);\r
+\r
+    if (IsUTF8Encode(IsoPath))\r
+    {\r
+        MultiByteToWideChar(CP_UTF8, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));\r
+    }\r
+    else\r
+    {\r
+        MultiByteToWideChar(CP_ACP, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));\r
+    }\r
+\r
+       memset(&StorageType, 0, sizeof(StorageType));\r
+       memset(&OpenParameters, 0, sizeof(OpenParameters));\r
+       memset(&AttachParameters, 0, sizeof(AttachParameters));\r
+\r
+       OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;\r
+       AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;\r
+\r
+       Status = OpenVirtualDisk(&StorageType, wFilePath, VIRTUAL_DISK_ACCESS_READ, 0, &OpenParameters, &Handle);\r
+       if (Status != ERROR_SUCCESS)\r
+       {\r
+               if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND == Status)\r
+               {\r
+                       Log("VirtualDisk for ISO file is not supported in current system");\r
+               }\r
+               else\r
+               {\r
+                       Log("Failed to open virtual disk ErrorCode:%u", Status);\r
+               }\r
+               return 1;\r
+       }\r
+\r
+       Log("OpenVirtualDisk success");\r
+\r
+       Status = AttachVirtualDisk(Handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME, 0, &AttachParameters, NULL);\r
+       if (Status != ERROR_SUCCESS)\r
+       {\r
+               Log("Failed to attach virtual disk ErrorCode:%u", Status);\r
+               CloseHandle(Handle);\r
+               return 1;\r
+       }\r
+\r
+       CloseHandle(Handle);\r
+       return 0;\r
+}\r
+\r
+\r
+static HANDLE g_FatPhyDrive;\r
+static UINT64 g_Part2StartSec;\r
+\r
+static int CopyFileFromFatDisk(const CHAR* SrcFile, const CHAR *DstFile)\r
+{\r
+       int rc = 1;\r
+       int size = 0;\r
+       char *buf = NULL;\r
+       void *flfile = NULL;\r
+\r
+       Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile, DstFile);\r
+\r
+       flfile = fl_fopen(SrcFile, "rb");\r
+       if (flfile)\r
+       {\r
+               fl_fseek(flfile, 0, SEEK_END);\r
+               size = (int)fl_ftell(flfile);\r
+               fl_fseek(flfile, 0, SEEK_SET);\r
+\r
+               buf = (char *)malloc(size);\r
+               if (buf)\r
+               {\r
+                       fl_fread(buf, 1, size, flfile);\r
+\r
+                       rc = 0;\r
+                       SaveBuffer2File(DstFile, buf, size);\r
+                       free(buf);\r
+               }\r
+\r
+               fl_fclose(flfile);\r
+       }\r
+\r
+       return rc;\r
+}\r
+\r
+static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)\r
+{\r
+       DWORD dwSize;\r
+       BOOL bRet;\r
+       DWORD ReadSize;\r
+       LARGE_INTEGER liCurrentPosition;\r
+\r
+       liCurrentPosition.QuadPart = Sector + g_Part2StartSec;\r
+       liCurrentPosition.QuadPart *= 512;\r
+       SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);\r
+\r
+       ReadSize = (DWORD)(SectorCount * 512);\r
+\r
+       bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);\r
+       if (bRet == FALSE || dwSize != ReadSize)\r
+       {\r
+               Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, GetLastError());\r
+       }\r
+\r
+       return 1;\r
+}\r
+\r
+static CHAR GetMountLogicalDrive(void)\r
+{\r
+       CHAR Letter = 'Y';\r
+       DWORD Drives;\r
+       DWORD Mask = 0x1000000;\r
+\r
+       Drives = GetLogicalDrives();\r
+    Log("Drives=0x%x", Drives);\r
+    \r
+       while (Mask)\r
+       {\r
+               if ((Drives & Mask) == 0)\r
+               {\r
+                       break;\r
+               }\r
+\r
+               Letter--;\r
+               Mask >>= 1;\r
+       }\r
+\r
+       return Letter;\r
+}\r
+\r
+UINT64 GetVentoyEfiPartStartSector(HANDLE hDrive)\r
+{\r
+       BOOL bRet;\r
+       DWORD dwSize; \r
+       MBR_HEAD MBR;   \r
+       VTOY_GPT_INFO *pGpt = NULL;\r
+       UINT64 StartSector = 0;\r
+\r
+       SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
+\r
+       bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);\r
+       Log("Read MBR Ret:%u Size:%u code:%u", bRet, dwSize, LASTERR);\r
+\r
+       if ((!bRet) || (dwSize != sizeof(MBR)))\r
+       {\r
+               0;\r
+       }\r
+\r
+       if (MBR.PartTbl[0].FsFlag == 0xEE)\r
+       {\r
+               Log("GPT partition style");\r
+\r
+               pGpt = malloc(sizeof(VTOY_GPT_INFO));\r
+               if (!pGpt)\r
+               {\r
+                       return 0;\r
+               }\r
+\r
+               SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
+               bRet = ReadFile(hDrive, pGpt, sizeof(VTOY_GPT_INFO), &dwSize, NULL);            \r
+               if ((!bRet) || (dwSize != sizeof(VTOY_GPT_INFO)))\r
+               {\r
+                       Log("Failed to read gpt info %d %u %d", bRet, dwSize, LASTERR);\r
+                       return 0;\r
+               }\r
+\r
+               StartSector = pGpt->PartTbl[1].StartLBA;\r
+               free(pGpt);\r
+       }\r
+       else\r
+       {\r
+               Log("MBR partition style");\r
+               StartSector = MBR.PartTbl[1].StartSectorId;\r
+       }\r
+\r
+       Log("GetVentoyEfiPart StartSector: %llu", StartSector);\r
+       return StartSector;\r
+}\r
+\r
+int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive)\r
+{\r
+       int rc = 1;\r
+       BOOL bRet;\r
+       CHAR Letter;\r
+       DWORD dwBytes;\r
+       HANDLE hDrive;\r
+       CHAR PhyPath[MAX_PATH];\r
+       WCHAR PhyPathW[MAX_PATH];\r
+       STARTUPINFOA Si;\r
+       PROCESS_INFORMATION Pi;\r
+       GET_LENGTH_INFORMATION LengthInfo;\r
+\r
+       Log("VentoyMountISOByImdisk %s", IsoPath);\r
+\r
+       sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", PhyDrive);\r
+    if (IsUTF8Encode(PhyPath))\r
+    {\r
+        Utf8ToUtf16(PhyPath, PhyPathW);\r
+        hDrive = CreateFileW(PhyPathW, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+    }\r
+    else\r
+    {\r
+        hDrive = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+    }\r
+    \r
+       if (hDrive == INVALID_HANDLE_VALUE)\r
+       {\r
+               Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());\r
+               goto End;\r
+       }\r
+\r
+       bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);\r
+       if (!bRet)\r
+       {\r
+               Log("Could not get phy disk %s size, error:%u", PhyPath, GetLastError());\r
+               goto End;\r
+       }\r
+\r
+       g_FatPhyDrive = hDrive;\r
+       g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);\r
+\r
+       Log("Parse FAT fs...");\r
+\r
+       fl_init();\r
+\r
+       if (0 == fl_attach_media(VentoyFatDiskRead, NULL))\r
+       {\r
+               if (g_64bit_system)\r
+               {\r
+                       CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");\r
+                       CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");\r
+                       CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");\r
+               }\r
+               else\r
+               {\r
+                       CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");\r
+                       CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");\r
+                       CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");\r
+               }\r
+               \r
+               GetCurrentDirectoryA(sizeof(PhyPath), PhyPath);\r
+               strcat_s(PhyPath, sizeof(PhyPath), "\\ventoy\\imdisk.sys");\r
+\r
+               if (LoadNtDriver(PhyPath) == 0)\r
+               {\r
+                       rc = 0;\r
+\r
+                       Letter = GetMountLogicalDrive();\r
+            sprintf_s(PhyPath, sizeof(PhyPath), "ventoy\\imdisk.exe -a -o ro -f %s -m %C:", IsoPath, Letter);\r
+\r
+                       Log("mount iso to %C: use imdisk cmd <%s>", Letter, PhyPath);\r
+\r
+            GetStartupInfoA(&Si);\r
+\r
+            Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+            Si.wShowWindow = SW_HIDE;\r
+\r
+                       CreateProcessA(NULL, PhyPath, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+                       WaitForSingleObject(Pi.hProcess, INFINITE);\r
+               }\r
+       }\r
+       fl_shutdown();\r
+\r
+End:\r
+\r
+       SAFE_CLOSE_HANDLE(hDrive);\r
+\r
+       return rc;\r
+}\r
+\r
+static int MountIsoFile(CONST CHAR *IsoPath, DWORD PhyDrive)\r
+{\r
+    if (IsWindows8OrGreater())\r
+    {\r
+        Log("This is Windows 8 or latter...");\r
+        if (VentoyMountISOByAPI(IsoPath) == 0)\r
+        {\r
+            Log("Mount iso by API success");\r
+            return 0;\r
+        }\r
+        else\r
+        {\r
+            Log("Mount iso by API failed, maybe not supported, try imdisk");\r
+            return VentoyMountISOByImdisk(IsoPath, PhyDrive);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        Log("This is before Windows 8 ...");\r
+        if (VentoyMountISOByImdisk(IsoPath, PhyDrive) == 0)\r
+        {\r
+            Log("Mount iso by imdisk success");\r
+            return 0;\r
+        }\r
+        else\r
+        {\r
+            return VentoyMountISOByAPI(IsoPath);\r
+        }\r
+    }\r
+}\r
+\r
+static int GetPhyDriveByLogicalDrive(int DriveLetter)\r
+{\r
+    BOOL Ret;\r
+    DWORD dwSize;\r
+    HANDLE Handle;\r
+    VOLUME_DISK_EXTENTS DiskExtents;\r
+    CHAR PhyPath[128];\r
+\r
+    sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", (CHAR)DriveLetter);\r
+\r
+    Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+    if (Handle == INVALID_HANDLE_VALUE)\r
+    {\r
+        Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());\r
+        return -1;\r
+    }\r
+\r
+    Ret = DeviceIoControl(Handle,\r
+        IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,\r
+        NULL,\r
+        0,\r
+        &DiskExtents,\r
+        (DWORD)(sizeof(DiskExtents)),\r
+        (LPDWORD)&dwSize,\r
+        NULL);\r
+\r
+    if (!Ret || DiskExtents.NumberOfDiskExtents == 0)\r
+    {\r
+        Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, GetLastError());\r
+        SAFE_CLOSE_HANDLE(Handle);\r
+        return -1;\r
+    }\r
+    SAFE_CLOSE_HANDLE(Handle);\r
+\r
+    Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",\r
+        PhyPath,\r
+        DiskExtents.Extents[0].DiskNumber,\r
+        DiskExtents.Extents[0].StartingOffset.QuadPart,\r
+        DiskExtents.Extents[0].ExtentLength.QuadPart\r
+        );\r
+\r
+    return (int)DiskExtents.Extents[0].DiskNumber;\r
+}\r
+\r
+\r
+static int DeleteVentoyPart2MountPoint(DWORD PhyDrive)\r
+{\r
+    CHAR Letter = 'A';\r
+    DWORD Drives;\r
+    DWORD PhyDisk;\r
+    CHAR DriveName[] = "?:\\";\r
+\r
+    Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive);\r
+\r
+    Drives = GetLogicalDrives();\r
+    while (Drives)\r
+    {\r
+        if ((Drives & 0x01) && IsPathExist(FALSE, "%C:\\ventoy\\ventoy.cpio", Letter))\r
+        {\r
+            Log("File %C:\\ventoy\\ventoy.cpio exist", Letter);\r
+\r
+            PhyDisk = GetPhyDriveByLogicalDrive(Letter);\r
+            Log("PhyDisk=%u for %C", PhyDisk, Letter);\r
+\r
+            if (PhyDisk == PhyDrive)\r
+            {\r
+                DriveName[0] = Letter;\r
+                DeleteVolumeMountPointA(DriveName);\r
+                return 0;\r
+            }\r
+        }\r
+\r
+        Letter++;\r
+        Drives >>= 1;\r
+    }\r
+\r
+    return 1;\r
+}\r
+\r
+static BOOL check_tar_archive(const char *archive, CHAR *tarName)\r
+{\r
+    int len;\r
+    int nameLen;\r
+    const char *pos = archive;\r
+    const char *slash = archive;\r
+\r
+    while (*pos)\r
+    {\r
+        if (*pos == '\\' || *pos == '/')\r
+        {\r
+            slash = pos;\r
+        }\r
+        pos++;\r
+    }\r
+\r
+    len = (int)strlen(slash);\r
+\r
+    if (len > 7 && (strncmp(slash + len - 7, ".tar.gz", 7) == 0 || strncmp(slash + len - 7, ".tar.xz", 7) == 0))\r
+    {\r
+        nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);\r
+        tarName[nameLen - 3] = 0;\r
+        return TRUE;\r
+    }\r
+    else if (len > 8 && strncmp(slash + len - 8, ".tar.bz2", 8) == 0)\r
+    {\r
+        nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);\r
+        tarName[nameLen - 4] = 0;\r
+        return TRUE;\r
+    }\r
+    else if (len > 9 && strncmp(slash + len - 9, ".tar.lzma", 9) == 0)\r
+    {\r
+        nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);\r
+        tarName[nameLen - 5] = 0;\r
+        return TRUE;\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive)\r
+{\r
+    int rc = 1;\r
+    BOOL bRet;\r
+    DWORD dwBytes;\r
+    HANDLE hDrive;\r
+    HANDLE hOut;\r
+    DWORD flags = CREATE_NO_WINDOW;\r
+    CHAR StrBuf[MAX_PATH];\r
+    CHAR tarName[MAX_PATH];\r
+    STARTUPINFOA Si;\r
+    PROCESS_INFORMATION Pi;\r
+    PROCESS_INFORMATION NewPi;\r
+    GET_LENGTH_INFORMATION LengthInfo;\r
+    SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };\r
+\r
+    Log("DecompressInjectionArchive %s", archive);\r
+\r
+    sprintf_s(StrBuf, sizeof(StrBuf), "\\\\.\\PhysicalDrive%d", PhyDrive);\r
+    hDrive = CreateFileA(StrBuf, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+    if (hDrive == INVALID_HANDLE_VALUE)\r
+    {\r
+        Log("Could not open the disk<%s>, error:%u", StrBuf, GetLastError());\r
+        goto End;\r
+    }\r
+\r
+    bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);\r
+    if (!bRet)\r
+    {\r
+        Log("Could not get phy disk %s size, error:%u", StrBuf, GetLastError());\r
+        goto End;\r
+    }\r
+\r
+    g_FatPhyDrive = hDrive;\r
+       g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);\r
+\r
+    Log("Parse FAT fs...");\r
+\r
+    fl_init();\r
+\r
+    if (0 == fl_attach_media(VentoyFatDiskRead, NULL))\r
+    {\r
+        if (g_64bit_system)\r
+        {\r
+            CopyFileFromFatDisk("/ventoy/7z/64/7za.exe", "ventoy\\7za.exe");\r
+        }\r
+        else\r
+        {\r
+            CopyFileFromFatDisk("/ventoy/7z/32/7za.exe", "ventoy\\7za.exe");\r
+        }\r
+\r
+        sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive);\r
+\r
+        Log("extract inject to X:");\r
+        Log("cmdline:<%s>", StrBuf);\r
+\r
+        GetStartupInfoA(&Si);\r
+\r
+        hOut = CreateFileA("ventoy\\7z.log",\r
+            FILE_APPEND_DATA,\r
+            FILE_SHARE_WRITE | FILE_SHARE_READ,\r
+            &Sa,\r
+            OPEN_ALWAYS,\r
+            FILE_ATTRIBUTE_NORMAL,\r
+            NULL);\r
+\r
+        Si.dwFlags |= STARTF_USESTDHANDLES;\r
+\r
+        if (hOut != INVALID_HANDLE_VALUE)\r
+        {\r
+            Si.hStdError = hOut;\r
+            Si.hStdOutput = hOut;\r
+        }\r
+\r
+        CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi);\r
+        WaitForSingleObject(Pi.hProcess, INFINITE);\r
+\r
+        //\r
+        // decompress tar archive, for tar.gz/tar.xz/tar.bz2\r
+        //\r
+        if (check_tar_archive(archive, tarName))\r
+        {\r
+            Log("Decompress tar archive...<%s>", tarName);\r
+\r
+            sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName);\r
+\r
+            CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &NewPi);\r
+            WaitForSingleObject(NewPi.hProcess, INFINITE);\r
+\r
+            Log("Now delete %s", tarName);\r
+            DeleteFileA(tarName);\r
+        }\r
+\r
+        SAFE_CLOSE_HANDLE(hOut);\r
+    }\r
+    fl_shutdown();\r
+\r
+End:\r
+\r
+    SAFE_CLOSE_HANDLE(hDrive);\r
+\r
+    return rc;\r
+}\r
+\r
+static int ProcessUnattendedInstallation(const char *script)\r
+{\r
+    DWORD dw;\r
+    HKEY hKey;\r
+    LSTATUS Ret;\r
+    CHAR Letter;\r
+    CHAR CurDir[MAX_PATH];\r
+\r
+    Log("Copy unattended XML ...");\r
+    \r
+    GetCurrentDirectory(sizeof(CurDir), CurDir);\r
+    Letter = CurDir[0];\r
+    if ((Letter >= 'A' && Letter <= 'Z') || (Letter >= 'a' && Letter <= 'z'))\r
+    {\r
+        Log("Current Drive Letter: %C", Letter);\r
+    }\r
+    else\r
+    {\r
+        Letter = 'X';\r
+    }\r
+    \r
+    sprintf_s(CurDir, sizeof(CurDir), "%C:\\Autounattend.xml", Letter);\r
+    Log("Copy file <%s> --> <%s>", script, CurDir);\r
+    CopyFile(script, CurDir, FALSE);\r
+\r
+    Ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dw);\r
+    if (ERROR_SUCCESS == Ret)\r
+    {\r
+        Ret = RegSetValueEx(hKey, "UnattendFile", 0, REG_SZ, CurDir, (DWORD)(strlen(CurDir) + 1));\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+static int VentoyHook(ventoy_os_param *param)\r
+{\r
+    int rc;\r
+       CHAR Letter = 'A';\r
+       DISK_EXTENT DiskExtent;\r
+       DWORD Drives = GetLogicalDrives();\r
+       UINT8 UUID[16];\r
+       CHAR IsoPath[MAX_PATH];\r
+\r
+       Log("Logical Drives=0x%x Path:<%s>", Drives, param->vtoy_img_path);\r
+\r
+    if (IsUTF8Encode(param->vtoy_img_path))\r
+    {\r
+        Log("This file is UTF8 encoding\n");\r
+    }\r
+\r
+       while (Drives)\r
+       {\r
+        if (Drives & 0x01)\r
+        {\r
+            sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);\r
+            if (IsPathExist(FALSE, "%s", IsoPath))\r
+            {\r
+                Log("File exist under %C:", Letter);\r
+                if (GetPhyDiskUUID(Letter, UUID, &DiskExtent) == 0)\r
+                {\r
+                    if (memcmp(UUID, param->vtoy_disk_guid, 16) == 0)\r
+                    {\r
+                        Log("Disk UUID match");\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+            else\r
+            {\r
+                Log("File NOT exist under %C:", Letter);\r
+            }\r
+        }\r
+\r
+               Drives >>= 1;\r
+               Letter++;\r
+       }\r
+\r
+       if (Drives == 0)\r
+       {\r
+               Log("Failed to find ISO file");\r
+               return 1;\r
+       }\r
+\r
+       Log("Find ISO file <%s>", IsoPath);\r
+    \r
+    rc = MountIsoFile(IsoPath, DiskExtent.DiskNumber);\r
+    Log("Mount ISO FILE: %s", rc == 0 ? "SUCCESS" : "FAILED");\r
+\r
+    // for protect\r
+    rc = DeleteVentoyPart2MountPoint(DiskExtent.DiskNumber);\r
+    Log("Delete ventoy mountpoint: %s", rc == 0 ? "SUCCESS" : "NO NEED");\r
+    \r
+    if (g_windows_data.auto_install_script[0])\r
+    {\r
+        sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.auto_install_script);\r
+        if (IsPathExist(FALSE, "%s", IsoPath))\r
+        {\r
+            Log("use auto install script %s...", IsoPath);\r
+            ProcessUnattendedInstallation(IsoPath);\r
+        }\r
+        else\r
+        {\r
+            Log("auto install script %s not exist", IsoPath);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        Log("auto install no need");\r
+    }\r
+\r
+    if (g_windows_data.injection_archive[0])\r
+    {\r
+        sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.injection_archive);\r
+        if (IsPathExist(FALSE, "%s", IsoPath))\r
+        {\r
+            Log("decompress injection archive %s...", IsoPath);\r
+            DecompressInjectionArchive(IsoPath, DiskExtent.DiskNumber);\r
+        }\r
+        else\r
+        {\r
+            Log("injection archive %s not exist", IsoPath);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        Log("no injection archive found");\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+const char * GetFileNameInPath(const char *fullpath)\r
+{\r
+       int i;\r
+       const char *pos = NULL;\r
+\r
+       if (strstr(fullpath, ":"))\r
+       {\r
+               for (i = (int)strlen(fullpath); i > 0; i--)\r
+               {\r
+                       if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\')\r
+                       {\r
+                               return fullpath + i;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       return fullpath;\r
+}\r
+\r
+int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)\r
+{\r
+       int rc = 1;\r
+       DWORD Pos;\r
+       DWORD PeStart;\r
+    DWORD FileSize;\r
+       BYTE *Buffer = NULL; \r
+       CHAR ExeFileName[MAX_PATH];\r
+\r
+       sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]);\r
+       if (!IsPathExist(FALSE, "%s", ExeFileName))\r
+       {\r
+               Log("File %s NOT exist, now try %s.exe", ExeFileName, ExeFileName);\r
+               sprintf_s(ExeFileName, sizeof(ExeFileName), "%s.exe", argv[0]);\r
+\r
+               Log("File %s exist ? %s", ExeFileName, IsPathExist(FALSE, "%s", ExeFileName) ? "YES" : "NO");\r
+       }\r
+\r
+       if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize))\r
+       {\r
+               goto End;\r
+       }\r
+       \r
+       g_64bit_system = IsPe64(Buffer);\r
+\r
+       if (!IsPathExist(TRUE, "ventoy"))\r
+       {\r
+               if (!CreateDirectoryA("ventoy", NULL))\r
+               {\r
+                       Log("Failed to create ventoy directory err:%u", GetLastError());\r
+                       goto End;\r
+               }\r
+       }\r
+\r
+       for (PeStart = 0; PeStart < FileSize; PeStart += 16)\r
+       {\r
+               if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) && \r
+            CheckPeHead(Buffer + PeStart + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data)))\r
+               {\r
+                       Log("Find os pararm at %u", PeStart);\r
+\r
+            memcpy(&g_os_param, Buffer + PeStart, sizeof(ventoy_os_param));\r
+            memcpy(&g_windows_data, Buffer + PeStart + sizeof(ventoy_os_param), sizeof(ventoy_windows_data));            \r
+            memcpy(g_os_param_reserved, g_os_param.vtoy_reserved, sizeof(g_os_param_reserved));\r
+\r
+            if (g_os_param_reserved[0] == 1)\r
+                       {\r
+                               Log("break here for debug .....");\r
+                               goto End;\r
+                       }\r
+\r
+                       // convert / to \\   \r
+            for (Pos = 0; Pos < sizeof(g_os_param.vtoy_img_path) && g_os_param.vtoy_img_path[Pos]; Pos++)\r
+                       {\r
+                if (g_os_param.vtoy_img_path[Pos] == '/')\r
+                               {\r
+                    g_os_param.vtoy_img_path[Pos] = '\\';\r
+                               }\r
+                       }\r
+\r
+                       PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data);\r
+                       sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName));\r
+                       SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart);\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (PeStart >= FileSize)\r
+       {\r
+               Log("OS param not found");\r
+               goto End;\r
+       }\r
+\r
+    if (g_os_param_reserved[0] == 2)\r
+    {\r
+        Log("skip hook for debug .....");\r
+        rc = 0;\r
+        goto End;\r
+    }\r
+\r
+    rc = VentoyHook(&g_os_param);\r
+\r
+End:\r
+\r
+       if (Buffer)\r
+       {\r
+               free(Buffer);\r
+       }\r
+\r
+       return rc;\r
+}\r
+\r
+int main(int argc, char **argv)\r
+{\r
+    int i = 0;\r
+    int rc = 0;\r
+       CHAR *Pos = NULL;\r
+       CHAR CurDir[MAX_PATH];\r
+       CHAR LunchFile[MAX_PATH];\r
+       STARTUPINFOA Si;\r
+       PROCESS_INFORMATION Pi;\r
+\r
+       if (argv[0] && argv[0][0] && argv[0][1] == ':')\r
+       {\r
+               GetCurrentDirectoryA(sizeof(CurDir), CurDir);\r
+\r
+               strcpy_s(LunchFile, sizeof(LunchFile), argv[0]);\r
+               Pos = (char *)GetFileNameInPath(LunchFile);\r
+\r
+               strcat_s(CurDir, sizeof(CurDir), "\\");\r
+               strcat_s(CurDir, sizeof(CurDir), Pos);\r
+               \r
+               if (_stricmp(argv[0], CurDir) != 0)\r
+               {\r
+                       *Pos = 0;\r
+                       SetCurrentDirectoryA(LunchFile);\r
+               }\r
+       }\r
+\r
+       Log("######## VentoyJump ##########");\r
+       Log("argc = %d argv[0] = <%s>", argc, argv[0]);\r
+\r
+       if (Pos && *Pos == 0)\r
+       {\r
+               Log("Old current directory = <%s>", CurDir);\r
+               Log("New current directory = <%s>", LunchFile);\r
+       }\r
+       else\r
+       {\r
+               GetCurrentDirectoryA(sizeof(CurDir), CurDir);\r
+               Log("Current directory = <%s>", CurDir);\r
+       }\r
+\r
+    GetStartupInfoA(&Si);\r
+\r
+    memset(LunchFile, 0, sizeof(LunchFile));\r
+    rc = VentoyJump(argc, argv, LunchFile);\r
+\r
+    if (g_os_param_reserved[0] == 3)\r
+    {\r
+        Log("Open log for debug ...");\r
+        sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log");\r
+    }\r
+    else\r
+    {\r
+        Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+        Si.wShowWindow = SW_HIDE;\r
+        Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed");\r
+    }\r
+\r
+       CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+\r
+    while (rc)\r
+    {\r
+        Log("Ventoy hook failed, now wait and retry ...");\r
+        Sleep(1000);\r
+\r
+        rc = VentoyHook(&g_os_param);\r
+    }\r
+\r
+       WaitForSingleObject(Pi.hProcess, INFINITE);\r
+\r
+       return 0;\r
+}\r