]> glassweightruler.freedombox.rocks Git - Ventoy.git/commitdiff
wimboot mode support Bob.Ombs.Modified.Win10PEx64 (#1842)
authorlongpanda <admin@ventoy.net>
Thu, 15 Sep 2022 17:05:58 +0000 (01:05 +0800)
committerlongpanda <admin@ventoy.net>
Thu, 15 Sep 2022 17:05:58 +0000 (01:05 +0800)
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c
GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h
INSTALL/grub/grub.cfg
INSTALL/ventoy/vtoyjump32.exe
INSTALL/ventoy/vtoyjump64.exe
vtoyjump/vtoyjump/vtoyjump.c
vtoyjump/vtoyjump/vtoyjump.h

index 562ede6c9e76d8d1182717da0d74994ebf5faa05..e4f4275052c4a86b23f68fe6c0de06d40cf6c3b9 100644 (file)
@@ -148,8 +148,6 @@ static char g_iso_vd_id_application[130];
 static int g_pager_flag = 0;
 static char g_old_pager[32];
 
-static const char *g_vtoy_winpeshl_ini = "[LaunchApps]\r\nvtoyjump.exe";
-
 const char *g_menu_class[img_type_max] = 
 {
     "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
@@ -1148,6 +1146,10 @@ grub_ssize_t ventoy_load_file_with_prompt(grub_file_t file, void *buf, grub_ssiz
         left -= VTOY_SIZE_2MB;
 
         div = grub_divmod64((grub_uint64_t)((size - left) * 100), (grub_uint64_t)size, &ro);
+        if (div < 1)
+        {
+            div = 1;
+        }
         grub_printf("\r%s   %d%%    ", g_vtoy_prompt_msg, (int)div);
         grub_refresh();  
     }
@@ -5987,12 +5989,6 @@ int ventoy_env_init(void)
         grub_env_export("ventoy_env_param");
     }
 
-    grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)g_vtoy_winpeshl_ini);
-    grub_env_set("vtoy_winpeshl_ini_addr", buf);
-
-    grub_snprintf(buf, sizeof(buf), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini));
-    grub_env_set("vtoy_winpeshl_ini_size", buf);
-
     grub_env_export("vtoy_winpeshl_ini_addr");
     grub_env_export("vtoy_winpeshl_ini_size");
 
index 987b04ac82bffb22a768d5463994c36a7c92bd92..2fc7f20acfc20f815e1ce473eb3d316c1429276a 100644 (file)
@@ -1790,19 +1790,150 @@ end:
     return rc;
 }
 
+static int ventoy_extract_init_exe(char *wimfile, grub_uint8_t **pexe_data, grub_uint32_t *pexe_len, char *exe_name)
+{
+    int rc;
+    int ret = 1;
+    grub_uint16_t i;
+    grub_file_t file = NULL;
+    grub_uint32_t exe_len = 0;
+    wim_header *head = NULL;
+    grub_uint16_t *uname = NULL;
+    grub_uint8_t *exe_data = NULL;
+    grub_uint8_t *decompress_data = NULL;
+    wim_lookup_entry *lookup = NULL;
+    wim_security_header *security = NULL;
+    wim_directory_entry *rootdir = NULL;
+    wim_directory_entry *search = NULL;
+    wim_stream_entry *stream = NULL;
+    wim_lookup_entry *replace_look = NULL;
+    wim_header wimhdr;
+    wim_hash hashdata;
+
+    head = &wimhdr;
+
+    file = grub_file_open(wimfile, VENTOY_FILE_TYPE);
+    if (!file)
+    {
+        goto out;
+    }
+
+    grub_file_read(file, head, sizeof(wim_header));
+    rc = ventoy_read_resource(file, head, &head->metadata, (void **)&decompress_data);
+    if (rc)
+    {
+        grub_printf("failed to read meta data %d\n", rc);
+        goto out;
+    }
+
+    security = (wim_security_header *)decompress_data;
+    if (security->len > 0)
+    {
+        rootdir = (wim_directory_entry *)(decompress_data + ((security->len + 7) & 0xFFFFFFF8U));
+    }
+    else
+    {
+        rootdir = (wim_directory_entry *)(decompress_data + 8);
+    }
+
+    debug("read lookup offset:%llu size:%llu\n", (ulonglong)head->lookup.offset, (ulonglong)head->lookup.raw_size);
+    lookup = grub_malloc(head->lookup.raw_size);
+    grub_file_seek(file, head->lookup.offset);
+    grub_file_read(file, lookup, head->lookup.raw_size);
+
+    /* search winpeshl.exe dirent entry */
+    search = search_replace_wim_dirent(file, head, lookup, decompress_data, rootdir);
+    if (!search)
+    {
+        debug("Failed to find replace file %p\n", search);
+        goto out;
+    }
+    
+    uname = (grub_uint16_t *)(search + 1);
+    for (i = 0; i < search->name_len / 2 && i < 200; i++)
+    {
+        exe_name[i] = (char)uname[i];
+    }
+    exe_name[i] = 0;
+    debug("find replace file at %p <%s>\n", search, exe_name);
+
+    grub_memset(&hashdata, 0, sizeof(wim_hash));
+    if (grub_memcmp(&hashdata, search->hash.sha1, sizeof(wim_hash)) == 0)
+    {
+        debug("search hash all 0, now do deep search\n");
+        stream = (wim_stream_entry *)((char *)search + search->len);
+        for (i = 0; i < search->streams; i++)
+        {
+            if (stream->name_len == 0)
+            {
+                grub_memcpy(&hashdata, stream->hash.sha1, sizeof(wim_hash));
+                debug("new search hash: %02x %02x %02x %02x %02x %02x %02x %02x\n", 
+                    ventoy_varg_8(hashdata.sha1));
+                break;
+            }
+            stream = (wim_stream_entry *)((char *)stream + stream->len);
+        }
+    }
+    else
+    {
+        grub_memcpy(&hashdata, search->hash.sha1, sizeof(wim_hash));        
+    }
+
+    /* find and extact winpeshl.exe */
+    replace_look = ventoy_find_look_entry(head, lookup, &hashdata);
+    if (replace_look)
+    {
+        exe_len = (grub_uint32_t)replace_look->resource.raw_size;
+        debug("find replace lookup entry_id:%ld raw_size:%u\n", 
+            ((long)replace_look - (long)lookup) / sizeof(wim_lookup_entry), exe_len);
+
+        if (0 != ventoy_read_resource(file, head, &(replace_look->resource), (void **)&(exe_data)))
+        {
+            exe_len = 0;
+            exe_data = NULL;
+            debug("failed to read replace file meta data %u\n", exe_len);
+        }
+    }
+    else
+    {
+        debug("failed to find lookup entry for replace file %02x %02x %02x %02x\n", 
+            ventoy_varg_4(hashdata.sha1));
+    }
+
+    if (exe_data)
+    {
+        ret = 0;
+        *pexe_data = exe_data;
+        *pexe_len = exe_len;
+    }
+    
+out:
+
+    grub_check_free(lookup);
+    grub_check_free(decompress_data);
+    check_free(file, grub_file_close);
+
+    return ret;
+}
+
 grub_err_t ventoy_cmd_windows_wimboot_data(grub_extcmd_context_t ctxt, int argc, char **args)
 {
+    int rc = 0;
     int datalen = 0;
     int dataflag = 0;
-    grub_uint32_t size = 0;
+    grub_uint32_t exe_len = 0;
+    grub_uint32_t jump_align = 0;
     const char *addr = NULL;
     ventoy_chain_head *chain = NULL;
-    ventoy_os_param *param = NULL;
-    char envbuf[64];
+    grub_uint8_t *param = NULL;
+    grub_uint8_t *exe_data = NULL;
+    ventoy_windows_data *rtdata = NULL;
+    char envbuf[64] = {0};
+    char exename[128] = {0};
+    wim_tail wim_data;
 
     (void)ctxt;
     (void)argc;
-    (void)args;
 
     addr = grub_env_get("vtoy_chain_mem_addr");
     if (!addr)
@@ -1821,24 +1952,34 @@ grub_err_t ventoy_cmd_windows_wimboot_data(grub_extcmd_context_t ctxt, int argc,
 
     datalen = ventoy_get_windows_rtdata_len(chain->os_param.vtoy_img_path, &dataflag);
 
-    size = sizeof(ventoy_os_param) + datalen;
-    param = (ventoy_os_param *)grub_zalloc(size);
-    if (!param)
+    rc = ventoy_extract_init_exe(args[0], &exe_data, &exe_len, exename);
+    if (rc)
     {
         return 1;
     }
 
-    grub_memcpy(param, &chain->os_param, sizeof(ventoy_os_param));
-    ventoy_fill_windows_rtdata(param + 1, param->vtoy_img_path, dataflag);
+    grub_memset(&wim_data, 0, sizeof(wim_data));
+    ventoy_cat_exe_file_data(&wim_data, exe_len, exe_data, datalen);
+    grub_check_free(exe_data);
+
+    jump_align = ventoy_align(wim_data.jump_exe_len, 16);
+    param = wim_data.jump_bin_data;
 
-    grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)param);
+    grub_memcpy(param + jump_align, &chain->os_param, sizeof(ventoy_os_param));
+
+    rtdata = (ventoy_windows_data *)(param + jump_align + sizeof(ventoy_os_param));
+    ventoy_fill_windows_rtdata(rtdata, chain->os_param.vtoy_img_path, dataflag);
+
+    grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (ulong)param);
     grub_env_set("vtoy_wimboot_mem_addr", envbuf);
     debug("vtoy_wimboot_mem_addr: %s\n", envbuf);
     
-    grub_snprintf(envbuf, sizeof(envbuf), "%u", size);
+    grub_snprintf(envbuf, sizeof(envbuf), "%u", wim_data.bin_align_len);
     grub_env_set("vtoy_wimboot_mem_size", envbuf);
     debug("vtoy_wimboot_mem_size: %s\n", envbuf);
-    
+
+    grub_env_set(args[1], exename);
+
     VENTOY_CMD_RETURN(GRUB_ERR_NONE);
 }
 
index c140b9257923ba3dd42db5fafc5e9b5cbac69b78..f5357253762c0421762f94c51ee1727537df49cc 100644 (file)
@@ -141,7 +141,7 @@ typedef struct ventoy_windows_data
     grub_uint8_t windows11_bypass_check;
 
     grub_uint32_t auto_install_len;
-    
+
     grub_uint8_t reserved[255 - 4];
 
     /* auto_intall file buf */
index 487dae0d10c21e025dd72532a3848136e3102401..a53de0a05af0b95f8e0c1d7e152f75656269b2df 100644 (file)
@@ -599,34 +599,35 @@ function ventoy_unix_comm_proc {
 function uefi_windows_menu_func {
     vt_windows_reset
 
-    if [ "$ventoy_compatible" = "NO" ]; then   
-        
-        if [ "$ventoy_fs_probe" = "iso9660" ]; then
-            loopback -d loop
-            vt_iso9660_nojoliet 1            
-            loopback loop "$1$2"
-        fi
-        
-        for file in "efi/microsoft/boot/bcd"; do
-            vt_windows_collect_wim_patch bcd (loop)/$file                
-        done
+    if vt_check_mode 4 "$vt_chosen_name"; then
+        vt_windows_chain_data "${1}${chosen_path}"
+        ventoy_debug_pause
+        vtoy_wimboot_func
+    else
+        if [ "$ventoy_compatible" = "NO" ]; then   
+            
+            if [ "$ventoy_fs_probe" = "iso9660" ]; then
+                loopback -d loop
+                vt_iso9660_nojoliet 1            
+                loopback loop "$1$2"
+            fi
+            
+            for file in "efi/microsoft/boot/bcd"; do
+                vt_windows_collect_wim_patch bcd (loop)/$file                
+            done
 
-        vt_windows_count_wim_patch vt_wim_cnt
-        if [ $vt_wim_cnt -eq 0 ]; then
-            distro_specify_wim_patch_phase2
+            vt_windows_count_wim_patch vt_wim_cnt
+            if [ $vt_wim_cnt -eq 0 ]; then
+                distro_specify_wim_patch_phase2
+            fi
+            
+            ventoy_debug_pause        
+            locate_wim "${chosen_path}"
         fi
-        
-        ventoy_debug_pause        
-        locate_wim "${chosen_path}"
+        vt_windows_chain_data "${1}${chosen_path}"
+        ventoy_debug_pause
     fi
 
-    vt_windows_chain_data "${1}${chosen_path}"
-    ventoy_debug_pause
-    
-    if vt_check_mode 4 "$vt_chosen_name"; then
-        vtoy_windows_wimboot_func
-    fi
-    
     if [ -n "$vtoy_chain_mem_addr" ]; then
         ventoy_acpi_param ${vtoy_chain_mem_addr} 2048
         ventoy_cli_console
@@ -942,8 +943,7 @@ function uefi_iso_memdisk {
     ventoy_gui_console
 }
 
-
-function vtoy_windows_wimboot_func {
+function vtoy_windows_wimboot {
     if [ -f (loop)/x86/sources/boot.wim -a -f (loop)/x64/sources/boot.wim ]; then
         vt_sel_wimboot vtoy_wimboot_bit
         if [ "$vtoy_wimboot_bit" = "32" ]; then
@@ -961,7 +961,7 @@ function vtoy_windows_wimboot_func {
     fi
 
     if [ -n "${vtdebug_flag}" ]; then
-        echo vtoy_wimboot_prefix=$vtoy_wimboot_prefix vtoy_wimboot_bit=$vtoy_wimboot_bit
+        echo vtoy_wimboot_prefix=$vtoy_wimboot_prefix vtoy_wimboot_bit=$vtoy_wimboot_bit vt_wimkernel=$vt_wimkernel
     fi
 
     for wmfile in sources/boot.wim boot/bcd boot/boot.sdi; do
@@ -971,33 +971,24 @@ function vtoy_windows_wimboot_func {
     done
 
     if [ -f $vtoy_wimboot_prefix/sources/install.wim -o -f $vtoy_wimboot_prefix/sources/install.esd ]; then
-        vt_windows_wimboot_data
+        vt_windows_wimboot_data "$vtoy_wimboot_prefix/sources/boot.wim" vtoy_init_exe
     else
         return
     fi
     
     if [ "$grub_platform" = "pc" ]; then
-        set vt_wimkernel=wimboot.x86_64.xz
-        
         linux16  "$vtoy_path/$vt_wimkernel"  quiet
         ventoy_debug_pause
 
         vt_set_wim_load_prompt 1 "Loading files......"
-        initrd16 newc:vtoyjump.exe:$vtoy_path/vtoyjump${vtoy_wimboot_bit}.exe \
-             newc:wimboot.data:mem:${vtoy_wimboot_mem_addr}:size:${vtoy_wimboot_mem_size} \
-             newc:winpeshl.ini:mem:${vtoy_winpeshl_ini_addr}:size:${vtoy_winpeshl_ini_size} \
+        initrd16 newc:winpeshl.exe:mem:${vtoy_wimboot_mem_addr}:size:${vtoy_wimboot_mem_size} \
+             newc:vtoy_wimboot:$vtoy_wimboot_prefix/boot/bcd \
              newc:bcd:$vtoy_wimboot_prefix/boot/bcd \
              newc:boot.sdi:$vtoy_wimboot_prefix/boot/boot.sdi \
              newc:boot.wim:$vtoy_wimboot_prefix/sources/boot.wim
         vt_set_wim_load_prompt 0
         boot
     else
-        if [ "$grub_cpu" = "i386" ]; then
-            set vt_wimkernel=wimboot.i386.efi.xz
-        else
-            set vt_wimkernel=wimboot.x86_64.xz
-        fi
-
         vt_set_wim_load_prompt 1 "Loading files......"
         vt_load_file_to_mem "nodecompress" $vtoy_wimboot_prefix/sources/boot.wim vtoy_wimfile_mem
         vt_set_wim_load_prompt 0
@@ -1010,9 +1001,8 @@ function vtoy_windows_wimboot_func {
 
         ventoy_cli_console
         chainloader "$vtoy_path/$vt_wimkernel" quiet \
-            "vf=wimboot.data:mem:${vtoy_wimboot_mem_addr}:size:${vtoy_wimboot_mem_size}" \
-            "vf=winpeshl.ini:mem:${vtoy_winpeshl_ini_addr}:size:${vtoy_winpeshl_ini_size}" \
-            "vf=vtoyjump.exe:$vtoy_path/vtoyjump${vtoy_wimboot_bit}.exe" \
+            "vf=winpeshl.exe:mem:${vtoy_wimboot_mem_addr}:size:${vtoy_wimboot_mem_size}" \
+            "vf=vtoy_wimboot:$vtoy_wimboot_prefix/boot/bcd" \
             "vf=bcd:$vtoy_wimboot_prefix/boot/bcd" \
             "vf=boot.sdi:$vtoy_wimboot_prefix/boot/boot.sdi" \
             "vf=boot.wim:$vtoy_wimfile_path" \
@@ -1023,37 +1013,118 @@ function vtoy_windows_wimboot_func {
     fi
 }
 
-function legacy_windows_menu_func {
-    vt_windows_reset
+function vtoy_winpe_wimboot {
+    unset vtoy_boot_mgr_exe
+    unset vtoy_boot_mgr_efi
+    set vtoy_wimboot_prefix=(loop)
+    set vtoy_bcd_path="$1"
+    set vtoy_sdi_path="$2"
+    set vtoy_wim_path="$3"
+    set vtoy_mgr_flag="$4"
     
-    if [ "$ventoy_compatible" = "NO" ]; then   
-        
-        if [ "$ventoy_fs_probe" = "iso9660" ]; then
-            loopback -d loop
-            vt_iso9660_nojoliet 1
-            loopback loop "$1$2"
+    if [ $vtoy_mgr_flag -eq 1 ]; then
+        set vtoy_boot_mgr_exe="newc:bootmgr.exe:$vtoy_wimboot_prefix/$5"
+    elif [ $vtoy_mgr_flag -eq 2 ]; then
+        set vtoy_boot_mgr_efi="vf=bootmgr.efi:$vtoy_wimboot_prefix/$5"
+    elif [ $vtoy_mgr_flag -eq 3 ]; then
+        set vtoy_boot_mgr_exe="newc:bootmgr.exe:$vtoy_wimboot_prefix/$5"
+        set vtoy_boot_mgr_efi="vf=bootmgr.efi:$vtoy_wimboot_prefix/$6"
+    fi
+
+    vt_windows_wimboot_data $vtoy_wimboot_prefix/$vtoy_wim_path vtoy_init_exe
+    
+    if [ "$grub_platform" = "pc" ]; then
+        linux16  "$vtoy_path/$vt_wimkernel"  quiet
+        ventoy_debug_pause
+
+        vt_set_wim_load_prompt 1 "Loading files......"        
+        initrd16 newc:$vtoy_init_exe:mem:${vtoy_wimboot_mem_addr}:size:${vtoy_wimboot_mem_size} \
+             $vtoy_boot_mgr_exe \
+             newc:vtoy_wimboot:$vtoy_wimboot_prefix/$vtoy_bcd_path \
+             newc:bcd:$vtoy_wimboot_prefix/$vtoy_bcd_path \
+             newc:boot.sdi:$vtoy_wimboot_prefix/$vtoy_sdi_path \
+             newc:boot.wim:$vtoy_wimboot_prefix/$vtoy_wim_path
+        vt_set_wim_load_prompt 0
+        boot
+    else
+        vt_set_wim_load_prompt 1 "Loading files......"
+        vt_load_file_to_mem "nodecompress" $vtoy_wimboot_prefix/$vtoy_wim_path vtoy_wimfile_mem
+        vt_set_wim_load_prompt 0
+
+        if [ $? -eq 0 ]; then
+            set vtoy_wimfile_path=mem:${vtoy_wimfile_mem_addr}:size:${vtoy_wimfile_mem_size}
+        else
+            set vtoy_wimfile_path=$vtoy_wimboot_prefix/$vtoy_wim_path
         fi
-        
-        for file in "boot/bcd" "/efi/microsoft/boot/bcd" "SSTR/BCD" "boot/bce"; do
-            vt_windows_collect_wim_patch bcd (loop)/$file                
-        done
-        
-        distro_specify_wim_patch
 
-        vt_windows_count_wim_patch vt_wim_cnt
-        if [ $vt_wim_cnt -eq 0 ]; then
-            distro_specify_wim_patch_phase2
+        ventoy_cli_console
+        chainloader "$vtoy_path/$vt_wimkernel" quiet \
+            "vf=$vtoy_init_exe:mem:${vtoy_wimboot_mem_addr}:size:${vtoy_wimboot_mem_size}" \
+            "vf=vtoy_wimboot:$vtoy_wimboot_prefix/$vtoy_bcd_path" \
+            "$vtoy_boot_mgr_efi" \
+            "vf=bcd:$vtoy_wimboot_prefix/$vtoy_bcd_path" \
+            "vf=boot.sdi:$vtoy_wimboot_prefix/$vtoy_sdi_path" \
+            "vf=boot.wim:$vtoy_wimfile_path" \
+            pfsize=$vtoy_chain_file_size  \
+            pfread=$vtoy_chain_file_read
+        boot
+        ventoy_gui_console
+    fi
+}
+
+function vtoy_wimboot_func {
+    echo -e "\n===================== VENTOY WIMBOOT ===================\n"
+
+    if [ "$grub_platform" = "pc" ]; then
+        set vt_wimkernel=wimboot.x86_64.xz        
+    else
+        if [ "$grub_cpu" = "i386" ]; then
+            set vt_wimkernel=wimboot.i386.efi.xz
+        else
+            set vt_wimkernel=wimboot.x86_64.xz
         fi
-        
-        ventoy_debug_pause        
-        locate_wim "${chosen_path}"
     fi
 
-    vt_windows_chain_data "${1}${chosen_path}"
-    ventoy_debug_pause    
+    if vt_str_begin "$vt_volume_id" "Modified-Win10PEx64"; then
+        vtoy_winpe_wimboot 'Boot/bcd' 'Boot/boot.sdi' 'sources/boot.wim' 1 'bootmgr.exe'
+    else
+        vtoy_windows_wimboot
+    fi
+}
 
+function legacy_windows_menu_func {
+    vt_windows_reset
+    
     if vt_check_mode 4 "$vt_chosen_name"; then
-        vtoy_windows_wimboot_func
+        vt_windows_chain_data "${1}${chosen_path}"
+        ventoy_debug_pause
+        vtoy_wimboot_func
+    else
+        if [ "$ventoy_compatible" = "NO" ]; then   
+            
+            if [ "$ventoy_fs_probe" = "iso9660" ]; then
+                loopback -d loop
+                vt_iso9660_nojoliet 1
+                loopback loop "$1$2"
+            fi
+            
+            for file in "boot/bcd" "/efi/microsoft/boot/bcd" "SSTR/BCD" "boot/bce"; do
+                vt_windows_collect_wim_patch bcd (loop)/$file                
+            done
+            
+            distro_specify_wim_patch
+
+            vt_windows_count_wim_patch vt_wim_cnt
+            if [ $vt_wim_cnt -eq 0 ]; then
+                distro_specify_wim_patch_phase2
+            fi
+            
+            ventoy_debug_pause        
+            locate_wim "${chosen_path}"
+        fi
+        
+        vt_windows_chain_data "${1}${chosen_path}"
+        ventoy_debug_pause
     fi
 
     if [ -n "$vtoy_chain_mem_addr" ]; then
index d5deb3ac2324bda1a972f0d814b23e2d756e94c2..2cd7eff2644930ae94796c8458f04fb0eea150c5 100644 (file)
Binary files a/INSTALL/ventoy/vtoyjump32.exe and b/INSTALL/ventoy/vtoyjump32.exe differ
index 4d36cf67f9e0ab6a05954c7b914e9743a3e7b909..65a2fb1e738f46627260fe6809b0747fb63aab38 100644 (file)
Binary files a/INSTALL/ventoy/vtoyjump64.exe and b/INSTALL/ventoy/vtoyjump64.exe differ
index 96edd9285a716831f05a42473f641bcb91b5961b..f9a903463a53d9f11b24e4fcfd7001d8fdb8679c 100644 (file)
@@ -36,6 +36,8 @@ static ventoy_guid g_ventoy_guid = VENTOY_GUID;
 static HANDLE g_vtoylog_mutex = NULL;\r
 static HANDLE g_vtoyins_mutex = NULL;\r
 \r
+static BOOL g_wimboot_mode = FALSE;\r
+\r
 static DWORD g_vtoy_disk_drive;\r
 \r
 static CHAR g_prog_full_path[MAX_PATH];\r
@@ -46,33 +48,34 @@ static CHAR g_prog_name[MAX_PATH];
 #define ORG_PECMD_PATH       "X:\\Windows\\system32\\PECMD.EXE"\r
 #define ORG_PECMD_BK_PATH    "X:\\Windows\\system32\\PECMD.EXE_BACK.EXE"\r
 \r
+#define WIMBOOT_FILE         "X:\\Windows\\system32\\vtoy_wimboot"\r
+#define WIMBOOT_DONE         "X:\\Windows\\system32\\vtoy_wimboot_done"\r
+\r
 #define AUTO_RUN_BAT    "X:\\VentoyAutoRun.bat"\r
 #define AUTO_RUN_LOG    "X:\\VentoyAutoRun.log"\r
 \r
 #define VTOY_AUTO_FILE   "X:\\_vtoy_auto_install"\r
 \r
-#define WINPESHL_INI    "X:\\Windows\\system32\\winpeshl.ini"\r
-\r
 #define LOG_FILE  "X:\\Windows\\system32\\ventoy.log"\r
 #define MUTEX_LOCK(hmutex)  if (hmutex != NULL) LockStatus = WaitForSingleObject(hmutex, INFINITE)\r
 #define MUTEX_UNLOCK(hmutex)  if (hmutex != NULL && WAIT_OBJECT_0 == LockStatus) ReleaseMutex(hmutex)\r
 \r
 static const char * GetFileNameInPath(const char *fullpath)\r
 {\r
-       int i;\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
+    int i;\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
 static int split_path_name(char *fullpath, char *dir, char *name)\r
@@ -92,27 +95,59 @@ static int split_path_name(char *fullpath, char *dir, char *name)
     return 0;\r
 }\r
 \r
+static void TrimString(CHAR *String, BOOL TrimLeft)\r
+{\r
+    CHAR *Pos1 = String;\r
+    CHAR *Pos2 = String;\r
+    size_t Len = strlen(String);\r
+\r
+    while (Len > 0)\r
+    {\r
+        if (String[Len - 1] != ' ' && String[Len - 1] != '\t')\r
+        {\r
+            break;\r
+        }\r
+        String[Len - 1] = 0;\r
+        Len--;\r
+    }\r
+\r
+    if (TrimLeft)\r
+    {        \r
+        while (*Pos1 == ' ' || *Pos1 == '\t')\r
+        {\r
+            Pos1++;\r
+        }\r
+\r
+        while (*Pos1)\r
+        {\r
+            *Pos2++ = *Pos1++;\r
+        }\r
+        *Pos2++ = 0;\r
+    }\r
+\r
+    return;\r
+}\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
+    va_list Arg;\r
+    int Len = 0;\r
+    FILE *File = NULL;\r
+    SYSTEMTIME Sys;\r
+    char szBuf[1024];\r
     DWORD LockStatus = 0;\r
     DWORD PID = GetCurrentProcessId();\r
 \r
-       GetLocalTime(&Sys);\r
-       Len += sprintf_s(szBuf, sizeof(szBuf),\r
-               "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ",\r
-               Sys.wYear, Sys.wMonth, Sys.wDay,\r
-               Sys.wHour, Sys.wMinute, Sys.wSecond,\r
+    GetLocalTime(&Sys);\r
+    Len += sprintf_s(szBuf, sizeof(szBuf),\r
+        "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ",\r
+        Sys.wYear, Sys.wMonth, Sys.wDay,\r
+        Sys.wHour, Sys.wMinute, Sys.wSecond,\r
         Sys.wMilliseconds, PID);\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
+    va_start(Arg, Fmt);\r
+    Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);\r
+    va_end(Arg);\r
 \r
     MUTEX_LOCK(g_vtoylog_mutex);\r
 \r
@@ -130,140 +165,140 @@ void Log(const char *Fmt, ...)
 \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
+    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
+    int rc = 1;\r
+    DWORD FileSize;\r
+    DWORD dwSize;\r
+    HANDLE Handle;\r
+    BYTE *Buffer = NULL;\r
 \r
-       Log("ReadWholeFile2Buf <%s>", Fullpath);\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
+    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
+    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
+    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
+    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
+    *Data = Buffer;\r
+    *Size = FileSize;\r
 \r
-       Log("Success read file size:%u", FileSize);\r
+    Log("Success read file size:%u", FileSize);\r
 \r
-       rc = 0;\r
+    rc = 0;\r
 \r
 End:\r
-       SAFE_CLOSE_HANDLE(Handle);\r
+    SAFE_CLOSE_HANDLE(Handle);\r
 \r
-       return rc;\r
+    return rc;\r
 }\r
 \r
 static BOOL CheckPeHead(BYTE *Buffer, DWORD Size, DWORD Offset)\r
 {\r
-       UINT32 PeOffset;\r
+    UINT32 PeOffset;\r
     BYTE *Head = NULL;\r
     DWORD End;\r
     ventoy_windows_data *pdata = NULL;\r
@@ -281,73 +316,73 @@ static BOOL CheckPeHead(BYTE *Buffer, DWORD Size, DWORD Offset)
         }\r
     }\r
 \r
-       if (Head[0] != 'M' || Head[1] != 'Z')\r
-       {\r
-               return FALSE;\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
+    PeOffset = *(UINT32 *)(Head + 60);\r
+    if (*(UINT32 *)(Head + PeOffset) != 0x00004550)\r
+    {\r
+        return FALSE;\r
+    }\r
 \r
-       return TRUE;\r
+    return TRUE;\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
+    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
+    int rc = 1;\r
+    DWORD dwSize;\r
+    HANDLE Handle;\r
 \r
-       Log("SaveBuffer2File <%s> len:%u", Fullpath, Length);\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
+    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
+    WriteFile(Handle, Buffer, Length, &dwSize, NULL);\r
 \r
-       rc = 0;\r
+    rc = 0;\r
 \r
 End:\r
-       SAFE_CLOSE_HANDLE(Handle);\r
+    SAFE_CLOSE_HANDLE(Handle);\r
 \r
-       return rc;\r
+    return rc;\r
 }\r
 \r
 static int IsUTF8Encode(const char *src)\r
@@ -406,17 +441,17 @@ static BOOL IsDirExist(const char *Fmt, ...)
 \r
 static BOOL IsFileExist(const char *Fmt, ...)\r
 {\r
-       va_list Arg;\r
-       HANDLE hFile;\r
-       DWORD Attr;\r
+    va_list Arg;\r
+    HANDLE hFile;\r
+    DWORD Attr;\r
     BOOL bRet = FALSE;\r
     int UTF8 = 0;\r
-       CHAR FilePathA[MAX_PATH];\r
-       WCHAR FilePathW[MAX_PATH];\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
+    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
@@ -429,12 +464,12 @@ static BOOL IsFileExist(const char *Fmt, ...)
     {\r
         hFile = CreateFileA(FilePathA, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);\r
     }\r
-       if (INVALID_HANDLE_VALUE == hFile)\r
-       {\r
+    if (INVALID_HANDLE_VALUE == hFile)\r
+    {\r
         goto out;\r
-       }\r
+    }\r
 \r
-       CloseHandle(hFile);\r
+    CloseHandle(hFile);\r
 \r
     if (UTF8)\r
     {\r
@@ -444,7 +479,7 @@ static BOOL IsFileExist(const char *Fmt, ...)
     {\r
         Attr = GetFileAttributesA(FilePathA);\r
     }\r
-       \r
+    \r
     if (Attr & FILE_ATTRIBUTE_DIRECTORY)\r
     {\r
         goto out;\r
@@ -459,66 +494,66 @@ out:
 \r
 static int GetPhyDiskUUID(const char LogicalDrive, UINT8 *UUID, UINT32 *DiskSig, 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
+    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(DISK_EXTENT));\r
     Log("%C: is in PhysicalDrive%d Offset:%llu", LogicalDrive, DiskExtents.Extents[0].DiskNumber, \r
         (ULONGLONG)(DiskExtents.Extents[0].StartingOffset.QuadPart));\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
+    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
     if (DiskSig)\r
     {\r
         memcpy(DiskSig, SectorBuf + 0x1B8, 4);\r
     }\r
 \r
-       CloseHandle(Handle);\r
-       return 0;\r
+    CloseHandle(Handle);\r
+    return 0;\r
 }\r
 \r
 static int VentoyMountAnywhere(HANDLE Handle)\r
@@ -605,7 +640,7 @@ int VentoyMountY(HANDLE Handle)
 \r
 static BOOL VentoyAPINeedMountY(const char *IsoPath)\r
 {\r
-       (void)IsoPath;\r
+    (void)IsoPath;\r
 \r
     /* TBD */\r
     return FALSE;\r
@@ -628,7 +663,7 @@ static int VentoyAttachVirtualDisk(HANDLE Handle, const char *IsoPath)
         DriveYFree = 1;\r
     }\r
 \r
-       if (DriveYFree && VentoyAPINeedMountY(IsoPath))\r
+    if (DriveYFree && VentoyAPINeedMountY(IsoPath))\r
     {\r
         return VentoyMountY(Handle);\r
     }\r
@@ -641,13 +676,13 @@ static int VentoyAttachVirtualDisk(HANDLE Handle, const char *IsoPath)
 int VentoyMountISOByAPI(const char *IsoPath)\r
 {\r
     int i;\r
-       HANDLE Handle;\r
-       DWORD Status;\r
-       WCHAR wFilePath[512] = { 0 };\r
-       VIRTUAL_STORAGE_TYPE StorageType;\r
-       OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters;\r
+    HANDLE Handle;\r
+    DWORD Status;\r
+    WCHAR wFilePath[512] = { 0 };\r
+    VIRTUAL_STORAGE_TYPE StorageType;\r
+    OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters;\r
 \r
-       Log("VentoyMountISOByAPI <%s>", IsoPath);\r
+    Log("VentoyMountISOByAPI <%s>", IsoPath);\r
 \r
     if (IsUTF8Encode(IsoPath))\r
     {\r
@@ -660,10 +695,10 @@ int VentoyMountISOByAPI(const char *IsoPath)
         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
-       \r
-       OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;\r
+    memset(&StorageType, 0, sizeof(StorageType));\r
+    memset(&OpenParameters, 0, sizeof(OpenParameters));\r
+    \r
+    OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;\r
 \r
     for (i = 0; i < 10; i++)\r
     {\r
@@ -691,309 +726,400 @@ int VentoyMountISOByAPI(const char *IsoPath)
         }\r
     }\r
 \r
-    if (Status != ERROR_SUCCESS)\r
+    if (Status != ERROR_SUCCESS)\r
+    {\r
+        return 1;\r
+    }\r
+\r
+    Log("OpenVirtualDisk success");\r
+\r
+    Status = VentoyAttachVirtualDisk(Handle, IsoPath);\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
+    Log("VentoyAttachVirtualDisk success");\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", bRet, ReadSize, dwSize, GetLastError());\r
+    }\r
+\r
+    return 1;\r
+}\r
+\r
+static BOOL Is2K10PE(void)\r
+{\r
+    BOOL bRet = FALSE;\r
+    FILE *fp = NULL;\r
+    CHAR szLine[1024];\r
+\r
+    fopen_s(&fp, "X:\\Windows\\System32\\PECMD.INI", "r");\r
+    if (!fp)\r
+    {\r
+        return FALSE;\r
+    }\r
+\r
+    memset(szLine, 0, sizeof(szLine));\r
+    while (fgets(szLine, sizeof(szLine) - 1, fp))\r
+    {\r
+        if (strstr(szLine, "2k10\\"))\r
+        {\r
+            bRet = TRUE;\r
+            break;\r
+        }\r
+    }\r
+\r
+    fclose(fp);\r
+    return bRet;\r
+}\r
+\r
+static CHAR GetIMDiskMountLogicalDrive(void)\r
+{\r
+    CHAR Letter = 'Y';\r
+    DWORD Drives;\r
+    DWORD Mask = 0x1000000;\r
+\r
+    // fixed use M as mountpoint for 2K10 PE\r
+    if (Is2K10PE())\r
+    {\r
+        Log("Use M: for 2K10 PE");\r
+        return 'M';\r
+    }\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
+static int VentoyRunImdisk(const char *IsoPath, const char *imdiskexe)\r
+{\r
+    CHAR Letter;\r
+    CHAR Cmdline[512];\r
+    WCHAR CmdlineW[512];\r
+    PROCESS_INFORMATION Pi;\r
+\r
+    Log("VentoyRunImdisk <%s> <%s>", IsoPath, imdiskexe);\r
+\r
+    Letter = GetIMDiskMountLogicalDrive();\r
+    sprintf_s(Cmdline, sizeof(Cmdline), "%s -a -o ro -f \"%s\" -m %C:", imdiskexe, IsoPath, Letter);\r
+    Log("mount iso to %C: use imdisk cmd <%s>", Letter, Cmdline);\r
+\r
+    if (IsUTF8Encode(IsoPath))\r
+    {\r
+        STARTUPINFOW Si;\r
+        GetStartupInfoW(&Si);\r
+        Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+        Si.wShowWindow = SW_HIDE;\r
+\r
+        Utf8ToUtf16(Cmdline, CmdlineW);\r
+        CreateProcessW(NULL, CmdlineW, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+\r
+        Log("This is UTF8 encoding");\r
+    }\r
+    else\r
+    {\r
+        STARTUPINFOA Si;\r
+        GetStartupInfoA(&Si);\r
+        Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+        Si.wShowWindow = SW_HIDE;\r
+\r
+        CreateProcessA(NULL, Cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+\r
+        Log("This is ANSI encoding");\r
+    }\r
+\r
+    Log("Wait for imdisk process ...");\r
+    WaitForSingleObject(Pi.hProcess, INFINITE);\r
+    Log("imdisk process finished");\r
+\r
+    return 0;\r
+}\r
+\r
+int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive)\r
+{\r
+    int rc = 1;\r
+    BOOL bRet;\r
+    DWORD dwBytes;\r
+    HANDLE hDrive;\r
+    CHAR PhyPath[MAX_PATH];\r
+    GET_LENGTH_INFORMATION LengthInfo;\r
+\r
+    Log("VentoyMountISOByImdisk %s", IsoPath);\r
+\r
+    if (IsFileExist("X:\\Windows\\System32\\imdisk.exe"))\r
+    {\r
+        Log("imdisk.exe exist, use it directly...");\r
+        VentoyRunImdisk(IsoPath, "imdisk.exe");\r
+        return 0;\r
+    }\r
+\r
+    sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", PhyDrive);\r
+    hDrive = CreateFileA(PhyPath, 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", 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
-        return 1;\r
+        Log("Could not get phy disk %s size, error:%u", PhyPath, GetLastError());\r
+        goto End;\r
     }\r
 \r
-       Log("OpenVirtualDisk success");\r
+    g_FatPhyDrive = hDrive;\r
+    g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);\r
 \r
-    Status = VentoyAttachVirtualDisk(Handle, IsoPath);\r
-       if (Status != ERROR_SUCCESS)\r
-       {\r
-               Log("Failed to attach virtual disk ErrorCode:%u", Status);\r
-               CloseHandle(Handle);\r
-               return 1;\r
-       }\r
+    Log("Parse FAT fs...");\r
 \r
-    Log("VentoyAttachVirtualDisk success");\r
+    fl_init();\r
 \r
-       CloseHandle(Handle);\r
-       return 0;\r
-}\r
+    if (0 == fl_attach_media(VentoyFatDiskRead, NULL))\r
+    {\r
+        if (g_system_bit == 64)\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
+            VentoyRunImdisk(IsoPath, "ventoy\\imdisk.exe");\r
+            rc = 0;\r
+        }\r
+    }\r
+    fl_shutdown();\r
 \r
+End:\r
 \r
-static HANDLE g_FatPhyDrive;\r
-static UINT64 g_Part2StartSec;\r
+    SAFE_CLOSE_HANDLE(hDrive);\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
+    return rc;\r
 }\r
 \r
-static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)\r
+static int GetIsoId(CONST CHAR *IsoPath, IsoId *ids)\r
 {\r
-       DWORD dwSize;\r
-       BOOL bRet;\r
-       DWORD ReadSize;\r
-       LARGE_INTEGER liCurrentPosition;\r
+    int i;\r
+    int n = 0;\r
+    HANDLE hFile;\r
+    DWORD dwSize = 0;\r
+    BOOL bRet[8];\r
 \r
-       liCurrentPosition.QuadPart = Sector + g_Part2StartSec;\r
-       liCurrentPosition.QuadPart *= 512;\r
-       SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);\r
+    hFile = CreateFileA(IsoPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);\r
+    if (hFile == INVALID_HANDLE_VALUE)\r
+    {\r
+        return 1;\r
+    }\r
 \r
-       ReadSize = (DWORD)(SectorCount * 512);\r
+    SetFilePointer(hFile, 2048 * 16 + 8, NULL, FILE_BEGIN);\r
+    bRet[n++] = ReadFile(hFile, ids->SystemId, 32, &dwSize, NULL);\r
+    \r
+    SetFilePointer(hFile, 2048 * 16 + 40, NULL, FILE_BEGIN);\r
+    bRet[n++] = ReadFile(hFile, ids->VolumeId, 32, &dwSize, NULL);\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", bRet, ReadSize, dwSize, GetLastError());\r
-       }\r
+    SetFilePointer(hFile, 2048 * 16 + 318, NULL, FILE_BEGIN);\r
+    bRet[n++] = ReadFile(hFile, ids->PulisherId, 128, &dwSize, NULL);\r
 \r
-       return 1;\r
-}\r
+    SetFilePointer(hFile, 2048 * 16 + 446, NULL, FILE_BEGIN);\r
+    bRet[n++] = ReadFile(hFile, ids->PreparerId, 128, &dwSize, NULL);\r
 \r
-static BOOL Is2K10PE(void)\r
-{\r
-       BOOL bRet = FALSE;\r
-       FILE *fp = NULL;\r
-       CHAR szLine[1024];\r
-\r
-       fopen_s(&fp, "X:\\Windows\\System32\\PECMD.INI", "r");\r
-       if (!fp)\r
-       {\r
-               return FALSE;\r
-       }\r
-\r
-       memset(szLine, 0, sizeof(szLine));\r
-       while (fgets(szLine, sizeof(szLine) - 1, fp))\r
-       {\r
-               if (strstr(szLine, "2k10\\"))\r
-               {\r
-                       bRet = TRUE;\r
-                       break;\r
-               }\r
-       }\r
-\r
-       fclose(fp);\r
-       return bRet;\r
-}\r
+    CloseHandle(hFile);\r
 \r
-static CHAR GetIMDiskMountLogicalDrive(void)\r
-{\r
-       CHAR Letter = 'Y';\r
-       DWORD Drives;\r
-       DWORD Mask = 0x1000000;\r
-\r
-       // fixed use M as mountpoint for 2K10 PE\r
-       if (Is2K10PE())\r
-       {\r
-               Log("Use M: for 2K10 PE");\r
-               return 'M';\r
-       }\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
+    for (i = 0; i < n; i++)\r
+    {\r
+        if (bRet[i] == FALSE)\r
+        {\r
+            return 1;\r
+        }\r
+    }\r
 \r
-static int VentoyRunImdisk(const char *IsoPath, const char *imdiskexe)\r
-{\r
-       CHAR Letter;\r
-       CHAR Cmdline[512];\r
-       WCHAR CmdlineW[512];\r
-       PROCESS_INFORMATION Pi;\r
-\r
-       Log("VentoyRunImdisk <%s> <%s>", IsoPath, imdiskexe);\r
-\r
-       Letter = GetIMDiskMountLogicalDrive();\r
-       sprintf_s(Cmdline, sizeof(Cmdline), "%s -a -o ro -f \"%s\" -m %C:", imdiskexe, IsoPath, Letter);\r
-       Log("mount iso to %C: use imdisk cmd <%s>", Letter, Cmdline);\r
-\r
-       if (IsUTF8Encode(IsoPath))\r
-       {\r
-               STARTUPINFOW Si;\r
-               GetStartupInfoW(&Si);\r
-               Si.dwFlags |= STARTF_USESHOWWINDOW;\r
-               Si.wShowWindow = SW_HIDE;\r
-\r
-               Utf8ToUtf16(Cmdline, CmdlineW);\r
-               CreateProcessW(NULL, CmdlineW, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
-\r
-               Log("This is UTF8 encoding");\r
-       }\r
-       else\r
-       {\r
-               STARTUPINFOA Si;\r
-               GetStartupInfoA(&Si);\r
-               Si.dwFlags |= STARTF_USESHOWWINDOW;\r
-               Si.wShowWindow = SW_HIDE;\r
-\r
-               CreateProcessA(NULL, Cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
-\r
-               Log("This is ANSI encoding");\r
-       }\r
-\r
-       Log("Wait for imdisk process ...");\r
-       WaitForSingleObject(Pi.hProcess, INFINITE);\r
-       Log("imdisk process finished");\r
-\r
-       return 0;\r
+\r
+    TrimString(ids->SystemId, FALSE);\r
+    TrimString(ids->VolumeId, FALSE);\r
+    TrimString(ids->PulisherId, FALSE);\r
+    TrimString(ids->PreparerId, FALSE);\r
+\r
+    Log("ISO ID: System<%s> Volume<%s> Pulisher<%s> Preparer<%s>", \r
+        ids->SystemId, ids->VolumeId, ids->PulisherId, ids->PreparerId);\r
+\r
+    return 0;\r
 }\r
 \r
-int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive)\r
+static int CheckSkipMountIso(CONST CHAR *IsoPath)\r
 {\r
-       int rc = 1;\r
-       BOOL bRet;\r
-       DWORD dwBytes;\r
-       HANDLE hDrive;\r
-       CHAR PhyPath[MAX_PATH];\r
-       GET_LENGTH_INFORMATION LengthInfo;\r
-\r
-       Log("VentoyMountISOByImdisk %s", IsoPath);\r
-\r
-       if (IsFileExist("X:\\Windows\\System32\\imdisk.exe"))\r
-       {\r
-               Log("imdisk.exe exist, use it directly...");\r
-               VentoyRunImdisk(IsoPath, "imdisk.exe");\r
-               return 0;\r
-       }\r
-\r
-       sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", PhyDrive);\r
-    hDrive = CreateFileA(PhyPath, 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", 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_system_bit == 64)\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
-                       VentoyRunImdisk(IsoPath, "ventoy\\imdisk.exe");\r
-                       rc = 0;\r
-               }\r
-       }\r
-       fl_shutdown();\r
+    BOOL InRoot = FALSE;\r
+    int slashcnt = 0;\r
+    CONST CHAR *p = NULL;\r
+    IsoId ID;\r
 \r
-End:\r
+    // C:\\xxx\r
+    for (p = IsoPath; *p; p++)\r
+    {\r
+        if (*p == '\\' || *p == '/')\r
+        {\r
+            slashcnt++;\r
+        }\r
+    }\r
+\r
+    if (slashcnt == 2)\r
+    {\r
+        InRoot = TRUE;\r
+    }\r
 \r
-       SAFE_CLOSE_HANDLE(hDrive);\r
+    memset(&ID, 0, sizeof(ID));\r
+    if (GetIsoId(IsoPath, &ID))\r
+    {\r
+        return 0;\r
+    }\r
+\r
+    //Bob.Ombs.Modified.Win10PEx64.iso will auto find ISO file in root, so we can skip the mount\r
+    if (InRoot && strcmp(ID.VolumeId, "Modified-Win10PEx64") == 0)\r
+    {\r
+        return 1;\r
+    }\r
 \r
-       return rc;\r
+    return 0;\r
 }\r
 \r
 static int MountIsoFile(CONST CHAR *IsoPath, DWORD PhyDrive)\r
 {\r
+    if (CheckSkipMountIso(IsoPath))\r
+    {\r
+        Log("Skip mount ISO file for <%s>", IsoPath);\r
+        return 0;\r
+    }\r
+\r
     if (IsWindows8OrGreater())\r
     {\r
         Log("This is Windows 8 or latter...");\r
@@ -1196,7 +1322,7 @@ static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive)
     }\r
 \r
     g_FatPhyDrive = hDrive;\r
-       g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);\r
+    g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);\r
 \r
     Log("Parse FAT fs...");\r
 \r
@@ -1204,7 +1330,7 @@ static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive)
 \r
     if (0 == fl_attach_media(VentoyFatDiskRead, NULL))\r
     {\r
-               if (g_system_bit == 64)\r
+        if (g_system_bit == 64)\r
         {\r
             CopyFileFromFatDisk("/ventoy/7z/64/7za.xz", "ventoy\\7za.xz");\r
         }\r
@@ -1301,10 +1427,10 @@ static int UnattendNeedVarExpand(const char *script)
     char szLine[4096];\r
 \r
     fopen_s(&fp, script, "r");\r
-       if (!fp)\r
-       {\r
-               return 0;\r
-       }\r
+    if (!fp)\r
+    {\r
+        return 0;\r
+    }\r
 \r
     szLine[0] = szLine[4095] = 0;\r
     \r
@@ -1417,36 +1543,6 @@ static int ExpandSingleVar(VarDiskInfo *pDiskInfo, int DiskNum, const char *var,
     return 0;\r
 }\r
 \r
-static void TrimString(CHAR *String)\r
-{\r
-    CHAR *Pos1 = String;\r
-    CHAR *Pos2 = String;\r
-    size_t Len = strlen(String);\r
-\r
-    while (Len > 0)\r
-    {\r
-        if (String[Len - 1] != ' ' && String[Len - 1] != '\t')\r
-        {\r
-            break;\r
-        }\r
-        String[Len - 1] = 0;\r
-        Len--;\r
-    }\r
-\r
-    while (*Pos1 == ' ' || *Pos1 == '\t')\r
-    {\r
-        Pos1++;\r
-    }\r
-\r
-    while (*Pos1)\r
-    {\r
-        *Pos2++ = *Pos1++;\r
-    }\r
-    *Pos2++ = 0;\r
-\r
-    return;\r
-}\r
-\r
 static int GetRegDwordValue(HKEY Key, LPCSTR SubKey, LPCSTR ValueName, DWORD *pValue)\r
 {\r
     HKEY hKey;\r
@@ -1655,25 +1751,25 @@ static int EnumerateAllDisk(VarDiskInfo **ppDiskInfo, int *pDiskNum)
         if (pDevDesc->VendorIdOffset)\r
         {\r
             safe_strcpy(pDiskInfo[i].VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset);\r
-            TrimString(pDiskInfo[i].VendorId);\r
+            TrimString(pDiskInfo[i].VendorId, TRUE);\r
         }\r
 \r
         if (pDevDesc->ProductIdOffset)\r
         {\r
             safe_strcpy(pDiskInfo[i].ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset);\r
-            TrimString(pDiskInfo[i].ProductId);\r
+            TrimString(pDiskInfo[i].ProductId, TRUE);\r
         }\r
 \r
         if (pDevDesc->ProductRevisionOffset)\r
         {\r
             safe_strcpy(pDiskInfo[i].ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset);\r
-            TrimString(pDiskInfo[i].ProductRev);\r
+            TrimString(pDiskInfo[i].ProductRev, TRUE);\r
         }\r
 \r
         if (pDevDesc->SerialNumberOffset)\r
         {\r
             safe_strcpy(pDiskInfo[i].SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset);\r
-            TrimString(pDiskInfo[i].SerialNumber);\r
+            TrimString(pDiskInfo[i].SerialNumber, TRUE);\r
         }\r
 \r
         free(pDevDesc);\r
@@ -1716,19 +1812,19 @@ static int UnattendVarExpand(const char *script, const char *tmpfile)
     }\r
     \r
     fopen_s(&fp, script, "r");\r
-       if (!fp)\r
-       {\r
+    if (!fp)\r
+    {\r
         free(pDiskInfo);\r
-               return 0;\r
-       }\r
+        return 0;\r
+    }\r
 \r
     fopen_s(&fout, tmpfile, "w+");\r
-       if (!fout)\r
-       {\r
-           fclose(fp);\r
+    if (!fout)\r
+    {\r
+        fclose(fp);\r
         free(pDiskInfo);\r
-               return 0;\r
-       }\r
+        return 0;\r
+    }\r
 \r
     szLine[0] = szLine[4095] = 0;\r
     \r
@@ -1979,12 +2075,12 @@ static int VentoyHook(ventoy_os_param *param)
     DWORD VtoyDiskNum;\r
     UINT32 DiskSig;\r
     UINT32 VtoySig;\r
-       DISK_EXTENT DiskExtent;\r
+    DISK_EXTENT DiskExtent;\r
     DISK_EXTENT VtoyDiskExtent;\r
-       UINT8 UUID[16];\r
-       CHAR IsoPath[MAX_PATH];\r
+    UINT8 UUID[16];\r
+    CHAR IsoPath[MAX_PATH];\r
 \r
-       Log("VentoyHook Path:<%s>", param->vtoy_img_path);\r
+    Log("VentoyHook Path:<%s>", param->vtoy_img_path);\r
 \r
     if (IsUTF8Encode(param->vtoy_img_path))\r
     {\r
@@ -2039,12 +2135,12 @@ static int VentoyHook(ventoy_os_param *param)
     }\r
 \r
     if (find == FALSE)\r
-       {\r
-               Log("Failed to find ISO file");\r
-               return 1;\r
-       }\r
+    {\r
+        Log("Failed to find ISO file");\r
+        return 1;\r
+    }\r
 \r
-       Log("Find ISO file <%s>", IsoPath);\r
+    Log("Find ISO file <%s>", IsoPath);\r
     \r
     //Find VtoyLetter in Vlnk Mode\r
     if (g_os_param_reserved[6] == 1)\r
@@ -2258,59 +2354,6 @@ static int ExtractWindowsDataFile(char *databuf)
     return len;\r
 }\r
 \r
-int VentoyJumpWimboot(INT argc, CHAR **argv, CHAR *LunchFile)\r
-{\r
-    int rc = 1;\r
-    char *buf = NULL;\r
-    DWORD size = 0;\r
-    DWORD Pos;\r
-\r
-       Log("VentoyJumpWimboot %dbit", g_system_bit);\r
-\r
-    sprintf_s(LunchFile, MAX_PATH, "X:\\setup.exe");\r
-\r
-    ReadWholeFile2Buf("wimboot.data", &buf, &size);\r
-    Log("wimboot.data size:%d", size);\r
-\r
-    memcpy(&g_os_param, buf, sizeof(ventoy_os_param));\r
-    memcpy(&g_windows_data, buf + sizeof(ventoy_os_param), sizeof(ventoy_windows_data));\r
-    ExtractWindowsDataFile(buf + sizeof(ventoy_os_param));\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
-    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 (buf)\r
-    {\r
-        free(buf);\r
-    }\r
-\r
-    return rc;\r
-}\r
-\r
 static int ventoy_check_create_directory(void)\r
 {\r
     if (IsDirExist("ventoy"))\r
@@ -2332,31 +2375,31 @@ static int ventoy_check_create_directory(void)
 \r
 int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)\r
 {\r
-       int rc = 1;\r
+    int rc = 1;\r
     int stat = 0;\r
     int exlen = 0;\r
-       DWORD Pos;\r
-       DWORD PeStart;\r
+    DWORD Pos;\r
+    DWORD PeStart;\r
     DWORD FileSize;\r
     DWORD LockStatus = 0;\r
-       BYTE *Buffer = NULL; \r
-       CHAR ExeFileName[MAX_PATH];\r
+    BYTE *Buffer = NULL; \r
+    CHAR ExeFileName[MAX_PATH];\r
 \r
-       sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]);\r
-       if (!IsFileExist("%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
+    sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]);\r
+    if (!IsFileExist("%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, IsFileExist("%s", ExeFileName) ? "YES" : "NO");\r
-       }\r
+        Log("File %s exist ? %s", ExeFileName, IsFileExist("%s", ExeFileName) ? "YES" : "NO");\r
+    }\r
 \r
-       if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize))\r
-       {\r
-               goto End;\r
-       }\r
-       \r
-       Log("VentoyJump %dbit", g_system_bit);\r
+    if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize))\r
+    {\r
+        goto End;\r
+    }\r
+    \r
+    Log("VentoyJump %dbit", g_system_bit);\r
 \r
     MUTEX_LOCK(g_vtoyins_mutex);\r
     stat = ventoy_check_create_directory();\r
@@ -2367,12 +2410,12 @@ int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
         goto End;\r
     }\r
 \r
-       for (PeStart = 0; PeStart < FileSize; PeStart += 16)\r
-       {\r
-               if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) && \r
+    for (PeStart = 0; PeStart < FileSize; PeStart += 16)\r
+    {\r
+        if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) && \r
             CheckPeHead(Buffer, FileSize, PeStart + sizeof(ventoy_os_param)))\r
-               {\r
-                       Log("Find os pararm at %u", PeStart);\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
@@ -2380,22 +2423,22 @@ int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
             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
+                Log("break here for debug .....");\r
+                goto End;\r
+            }\r
 \r
-                       // convert / to \\   \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
+            {\r
                 if (g_os_param.vtoy_img_path[Pos] == '/')\r
-                               {\r
+                {\r
                     g_os_param.vtoy_img_path[Pos] = '\\';\r
-                               }\r
-                       }\r
+                }\r
+            }\r
 \r
-                       PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data) + exlen;\r
-                       sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName));\r
+            PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data) + exlen;\r
+            sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName));\r
 \r
             MUTEX_LOCK(g_vtoyins_mutex);\r
             if (IsFileExist("%s", LunchFile))\r
@@ -2406,18 +2449,18 @@ int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
                 goto End;\r
             }\r
 \r
-                       SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart);\r
+            SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart);\r
             MUTEX_UNLOCK(g_vtoyins_mutex);\r
 \r
-                       break;\r
-               }\r
-       }\r
+            break;\r
+        }\r
+    }\r
 \r
-       if (PeStart >= FileSize)\r
-       {\r
-               Log("OS param not found");\r
-               goto End;\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
@@ -2430,128 +2473,112 @@ int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
 \r
 End:\r
 \r
-       if (Buffer)\r
-       {\r
-               free(Buffer);\r
-       }\r
+    if (Buffer)\r
+    {\r
+        free(Buffer);\r
+    }\r
 \r
-       return rc;\r
+    return rc;\r
 }\r
 \r
 \r
 int real_main(int argc, char **argv)\r
 {\r
-       int i = 0;\r
-       int rc = 0;\r
-    int wimboot = 0;\r
-       CHAR NewFile[MAX_PATH];\r
-       CHAR LunchFile[MAX_PATH];\r
-       CHAR CallParam[1024] = { 0 };\r
-       STARTUPINFOA Si;\r
-       PROCESS_INFORMATION Pi;\r
-\r
-       Log("#### real_main #### argc = %d", argc);\r
+    int i = 0;\r
+    int rc = 0;\r
+    CHAR NewFile[MAX_PATH];\r
+    CHAR LunchFile[MAX_PATH];\r
+    CHAR CallParam[1024] = { 0 };\r
+    STARTUPINFOA Si;\r
+    PROCESS_INFORMATION Pi;\r
+\r
+    Log("#### real_main #### argc = %d", argc);\r
     Log("program full path: <%s>", g_prog_full_path);\r
     Log("program dir: <%s>", g_prog_dir);\r
-    Log("program name:: <%s>", g_prog_name);\r
+    Log("program name: <%s>", g_prog_name);\r
 \r
     Log("argc = %d", argc);\r
-       for (i = 0; i < argc; i++)\r
-       {\r
-               Log("argv[%d]=<%s>", i, argv[i]);\r
-               if (i > 0)\r
-               {\r
-                       strcat_s(CallParam, sizeof(CallParam), " ");\r
-                       strcat_s(CallParam, sizeof(CallParam), argv[i]);\r
-               }\r
-       }\r
-\r
-       GetStartupInfoA(&Si);\r
-       memset(LunchFile, 0, sizeof(LunchFile));\r
-\r
-       if (strstr(argv[0], "vtoyjump.exe"))\r
-       {\r
-        wimboot = 1;\r
-        DeleteFileA(WINPESHL_INI);\r
-        IsFileExist(WINPESHL_INI);\r
-        rc = VentoyJumpWimboot(argc, argv, LunchFile);\r
-       }\r
-       else\r
-       {\r
-        rc = VentoyJump(argc, argv, LunchFile);\r
-       }\r
-\r
-       Log("LunchFile=<%s> CallParam=<%s>", LunchFile, CallParam);\r
-\r
-       if (_stricmp(g_prog_name, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name))\r
-       {\r
-               sprintf_s(NewFile, sizeof(NewFile), "%s_BACK.EXE", g_prog_full_path);\r
-               MoveFileA(g_prog_full_path, NewFile);\r
-               Log("Move <%s> to <%s>", g_prog_full_path, NewFile);\r
-\r
-               sprintf_s(NewFile, sizeof(NewFile), "ventoy\\%s", g_prog_name);\r
-               CopyFileA(NewFile, g_prog_full_path, TRUE);\r
-               Log("Copy <%s> to <%s>", NewFile, g_prog_full_path);\r
-\r
-               sprintf_s(LunchFile, sizeof(LunchFile), "%s", g_prog_full_path);\r
-               Log("Final lunchFile is <%s>", LunchFile);\r
-       }\r
-    else if (wimboot && IsFileExist(WINPESHL_INI))\r
-    {\r
-        sprintf_s(LunchFile, MAX_PATH, "X:\\Windows\\system32\\winpeshl.exe");\r
-        Log("winpeshl.ini updated, now recall winpeshl.exe");\r
+    for (i = 0; i < argc; i++)\r
+    {\r
+        Log("argv[%d]=<%s>", i, argv[i]);\r
+        if (i > 0)\r
+        {\r
+            strcat_s(CallParam, sizeof(CallParam), " ");\r
+            strcat_s(CallParam, sizeof(CallParam), argv[i]);\r
+        }\r
+    }\r
+\r
+    GetStartupInfoA(&Si);\r
+    memset(LunchFile, 0, sizeof(LunchFile));\r
+\r
+    rc = VentoyJump(argc, argv, LunchFile);\r
+\r
+    Log("LunchFile=<%s> CallParam=<%s>", LunchFile, CallParam);\r
+\r
+    if (_stricmp(g_prog_name, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name))\r
+    {\r
+        sprintf_s(NewFile, sizeof(NewFile), "%s_BACK.EXE", g_prog_full_path);\r
+        MoveFileA(g_prog_full_path, NewFile);\r
+        Log("Move <%s> to <%s>", g_prog_full_path, NewFile);\r
+\r
+        sprintf_s(NewFile, sizeof(NewFile), "ventoy\\%s", g_prog_name);\r
+        CopyFileA(NewFile, g_prog_full_path, TRUE);\r
+        Log("Copy <%s> to <%s>", NewFile, g_prog_full_path);\r
+\r
+        sprintf_s(LunchFile, sizeof(LunchFile), "%s", g_prog_full_path);\r
+        Log("Final lunchFile is <%s>", LunchFile);\r
     }\r
     else\r
     {\r
         Log("We don't need to recover original <%s>", g_prog_name);\r
     }\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
-               if (CallParam[0])\r
-               {\r
-                       strcat_s(LunchFile, sizeof(LunchFile), CallParam);\r
-               }\r
-               else if (NULL == strstr(LunchFile, "setup.exe"))\r
-               {\r
-                       Log("Not setup.exe, hide windows.");\r
-                       Si.dwFlags |= STARTF_USESHOWWINDOW;\r
-                       Si.wShowWindow = SW_HIDE;\r
-               }\r
-\r
-               Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed");\r
-       }\r
-\r
-       Log("Now launch <%s> ...", LunchFile);\r
-\r
-       if (g_os_param_reserved[0] == 4)\r
-       {\r
-               Log("Open cmd for debug ...");\r
-               sprintf_s(LunchFile, sizeof(LunchFile), "%s", "cmd.exe");\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
+        if (CallParam[0])\r
+        {\r
+            strcat_s(LunchFile, sizeof(LunchFile), CallParam);\r
+        }\r
+        else if (NULL == strstr(LunchFile, "setup.exe"))\r
+        {\r
+            Log("Not setup.exe, hide windows.");\r
+            Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+            Si.wShowWindow = SW_HIDE;\r
+        }\r
+\r
+        Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed");\r
+    }\r
+\r
+    Log("Now launch <%s> ...", LunchFile);\r
+\r
+    if (g_os_param_reserved[0] == 4)\r
+    {\r
+        Log("Open cmd for debug ...");\r
+        sprintf_s(LunchFile, sizeof(LunchFile), "%s", "cmd.exe");\r
+    }\r
 \r
     Log("Backup log at this point");\r
     CopyFileA(LOG_FILE, "X:\\Windows\\ventoy.backup", TRUE);\r
 \r
-       CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+    CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
 \r
-       for (i = 0; rc && i < 1800; i++)\r
-       {\r
-               Log("Ventoy hook failed, now wait and retry ...");\r
-               Sleep(1000);\r
-               rc = VentoyHook(&g_os_param);\r
-       }\r
+    for (i = 0; rc && i < 1800; i++)\r
+    {\r
+        Log("Ventoy hook failed, now wait and retry ...");\r
+        Sleep(1000);\r
+        rc = VentoyHook(&g_os_param);\r
+    }\r
 \r
-       Log("Wait process...");\r
-       WaitForSingleObject(Pi.hProcess, INFINITE);\r
+    Log("Wait process...");\r
+    WaitForSingleObject(Pi.hProcess, INFINITE);\r
 \r
-       Log("vtoyjump finished");\r
-       return 0;\r
+    Log("vtoyjump finished");\r
+    return 0;\r
 }\r
 \r
 static void VentoyToUpper(CHAR *str)\r
@@ -2563,39 +2590,80 @@ static void VentoyToUpper(CHAR *str)
     }\r
 }\r
 \r
+static int vtoy_remove_duplicate_file(char *File)\r
+{\r
+    CHAR szCmd[MAX_PATH];\r
+    CHAR NewFile[MAX_PATH];\r
+    STARTUPINFOA Si;\r
+    PROCESS_INFORMATION Pi;\r
+\r
+    Log("<1> Copy New file", File);\r
+    sprintf_s(NewFile, sizeof(NewFile), "%s_NEW", File);\r
+    CopyFileA(File, NewFile, FALSE);\r
+\r
+    Log("<2> Remove file <%s>", File);\r
+    GetStartupInfoA(&Si);\r
+    Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+    Si.wShowWindow = SW_HIDE;\r
+    sprintf_s(szCmd, sizeof(szCmd), "cmd.exe /c del /F /Q %s", File);\r
+    CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+    WaitForSingleObject(Pi.hProcess, INFINITE);\r
+\r
+    Log("<3> Copy back file <%s>", File);\r
+    MoveFileA(NewFile, File);\r
+\r
+    return 0;\r
+}\r
+\r
 int main(int argc, char **argv)\r
 {\r
-       int i;\r
-       STARTUPINFOA Si;\r
-       PROCESS_INFORMATION Pi;\r
-       CHAR CurDir[MAX_PATH];\r
+    int i;\r
+    STARTUPINFOA Si;\r
+    PROCESS_INFORMATION Pi;\r
+    CHAR CurDir[MAX_PATH];\r
     CHAR NewArgv0[MAX_PATH];\r
-       CHAR CallParam[1024] = { 0 };\r
+    CHAR CallParam[1024] = { 0 };\r
 \r
-       g_vtoylog_mutex = CreateMutexA(NULL, FALSE, "VTOYLOG_LOCK");\r
-       g_vtoyins_mutex = CreateMutexA(NULL, FALSE, "VTOYINS_LOCK");\r
+    g_vtoylog_mutex = CreateMutexA(NULL, FALSE, "VTOYLOG_LOCK");\r
+    g_vtoyins_mutex = CreateMutexA(NULL, FALSE, "VTOYINS_LOCK");\r
 \r
-       Log("######## VentoyJump %dbit ##########", g_system_bit);\r
+    Log("######## VentoyJump %dbit ##########", g_system_bit);\r
 \r
-       GetCurrentDirectoryA(sizeof(CurDir), CurDir);\r
-       Log("Current directory is <%s>", CurDir);\r
-       \r
-       GetModuleFileNameA(NULL, g_prog_full_path, MAX_PATH);\r
+    GetCurrentDirectoryA(sizeof(CurDir), CurDir);\r
+    Log("Current directory is <%s>", CurDir);\r
+    \r
+    GetModuleFileNameA(NULL, g_prog_full_path, MAX_PATH);\r
     split_path_name(g_prog_full_path, g_prog_dir, g_prog_name);\r
 \r
-       Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path, g_prog_dir, g_prog_name);\r
+    Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path, g_prog_dir, g_prog_name);\r
+\r
+    if (IsFileExist(WIMBOOT_FILE))\r
+    {\r
+        Log("This is wimboot mode ...");\r
+        g_wimboot_mode = TRUE;\r
+\r
+        if (!IsFileExist(WIMBOOT_DONE))\r
+        {\r
+            vtoy_remove_duplicate_file(g_prog_full_path);\r
+            SaveBuffer2File(WIMBOOT_DONE, g_prog_full_path, 1);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        Log("This is normal mode ...");\r
+    }\r
 \r
-       if (_stricmp(g_prog_name, "WinLogon.exe") == 0)\r
-       {\r
-               Log("This time is rejump back ...");\r
-               \r
-               strcpy_s(g_prog_full_path, sizeof(g_prog_full_path), argv[1]);\r
+    if (_stricmp(g_prog_name, "WinLogon.exe") == 0)\r
+    {\r
+        Log("This time is rejump back ...");\r
+        \r
+        strcpy_s(g_prog_full_path, sizeof(g_prog_full_path), argv[1]);\r
         split_path_name(g_prog_full_path, g_prog_dir, g_prog_name);\r
 \r
-               return real_main(argc - 1, argv + 1);\r
-       }\r
-       else if (_stricmp(g_prog_name, "PECMD.exe") == 0)\r
-       {\r
+        return real_main(argc - 1, argv + 1);\r
+    }\r
+    else if (_stricmp(g_prog_name, "PECMD.exe") == 0)\r
+    {\r
         strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_dir);\r
         VentoyToUpper(NewArgv0);\r
         \r
@@ -2613,32 +2681,31 @@ int main(int argc, char **argv)
 \r
             sprintf_s(CallParam, sizeof(CallParam), "ventoy\\WinLogon.exe %s", g_prog_full_path);\r
         }\r
-               \r
-               for (i = 1; i < argc; i++)\r
-               {\r
-                       strcat_s(CallParam, sizeof(CallParam), " ");\r
-                       strcat_s(CallParam, sizeof(CallParam), argv[i]);\r
-               }\r
-\r
-               Log("Now rejump to <%s> ...", CallParam);\r
-               GetStartupInfoA(&Si);\r
-               CreateProcessA(NULL, CallParam, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
-\r
-               Log("Wait rejump process...");\r
-               WaitForSingleObject(Pi.hProcess, INFINITE);\r
-               Log("rejump finished");\r
-               return 0;\r
-       }\r
-       else\r
-       {\r
-               Log("We don't need to rejump ...");\r
+        \r
+        for (i = 1; i < argc; i++)\r
+        {\r
+            strcat_s(CallParam, sizeof(CallParam), " ");\r
+            strcat_s(CallParam, sizeof(CallParam), argv[i]);\r
+        }\r
+\r
+        Log("Now rejump to <%s> ...", CallParam);\r
+        GetStartupInfoA(&Si);\r
+        CreateProcessA(NULL, CallParam, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+\r
+        Log("Wait rejump process...");\r
+        WaitForSingleObject(Pi.hProcess, INFINITE);\r
+        Log("rejump finished");\r
+        return 0;\r
+    }\r
+    else\r
+    {\r
+        Log("We don't need to rejump ...");\r
 \r
         ventoy_check_create_directory();\r
         strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_full_path);\r
         argv[0] = NewArgv0;\r
 \r
-               return real_main(argc, argv);\r
-       }\r
+        return real_main(argc, argv);\r
+    }\r
 }\r
 \r
-\r
index b19b334c1f2b353f335634c0b07294ad939549b2..768d7cc29f012e09c32e148e463868cff862cdbc 100644 (file)
@@ -164,6 +164,13 @@ typedef struct VarDiskInfo
     CHAR SerialNumber[128];\r
 }VarDiskInfo;\r
 \r
+typedef struct IsoId\r
+{\r
+    CHAR SystemId[64];\r
+    CHAR VolumeId[64];\r
+    CHAR PulisherId[256];\r
+    CHAR PreparerId[256];\r
+}IsoId;\r
 \r
 #define SAFE_CLOSE_HANDLE(handle) \\r
 {\\r