From e79dc57ebe8d1818fac798d90567915cc4609a13 Mon Sep 17 00:00:00 2001 From: longpanda Date: Fri, 16 Sep 2022 01:05:58 +0800 Subject: [PATCH] wimboot mode support Bob.Ombs.Modified.Win10PEx64 (#1842) --- .../grub-2.04/grub-core/ventoy/ventoy_cmd.c | 12 +- .../grub-core/ventoy/ventoy_windows.c | 165 +- GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h | 2 +- INSTALL/grub/grub.cfg | 213 ++- INSTALL/ventoy/vtoyjump32.exe | Bin 140288 -> 141312 bytes INSTALL/ventoy/vtoyjump64.exe | Bin 161792 -> 162304 bytes vtoyjump/vtoyjump/vtoyjump.c | 1555 +++++++++-------- vtoyjump/vtoyjump/vtoyjump.h | 7 + 8 files changed, 1118 insertions(+), 836 deletions(-) diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c index 562ede6c..e4f42750 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c @@ -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"); diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c index 987b04ac..2fc7f20a 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_windows.c @@ -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); - grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)param); + jump_align = ventoy_align(wim_data.jump_exe_len, 16); + param = wim_data.jump_bin_data; + + 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); } diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h index c140b925..f5357253 100644 --- a/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h +++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h @@ -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 */ diff --git a/INSTALL/grub/grub.cfg b/INSTALL/grub/grub.cfg index 487dae0d..a53de0a0 100644 --- a/INSTALL/grub/grub.cfg +++ b/INSTALL/grub/grub.cfg @@ -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 - - 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 - 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 "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 + 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 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 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 [ $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 + + 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 + fi + + 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 [ "$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 - 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 diff --git a/INSTALL/ventoy/vtoyjump32.exe b/INSTALL/ventoy/vtoyjump32.exe index d5deb3ac2324bda1a972f0d814b23e2d756e94c2..2cd7eff2644930ae94796c8458f04fb0eea150c5 100644 GIT binary patch delta 25077 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ಲ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 diff --git a/INSTALL/ventoy/vtoyjump64.exe b/INSTALL/ventoy/vtoyjump64.exe index 4d36cf67f9e0ab6a05954c7b914e9743a3e7b909..65a2fb1e738f46627260fe6809b0747fb63aab38 100644 GIT binary patch delta 40357 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 0; i--) - { - if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\') - { - return fullpath + i; - } - } - } + if (strstr(fullpath, ":")) + { + for (i = (int)strlen(fullpath); i > 0; i--) + { + if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\') + { + return fullpath + i; + } + } + } - return fullpath; + return fullpath; } static int split_path_name(char *fullpath, char *dir, char *name) @@ -92,27 +95,59 @@ static int split_path_name(char *fullpath, char *dir, char *name) return 0; } +static void TrimString(CHAR *String, BOOL TrimLeft) +{ + CHAR *Pos1 = String; + CHAR *Pos2 = String; + size_t Len = strlen(String); + + while (Len > 0) + { + if (String[Len - 1] != ' ' && String[Len - 1] != '\t') + { + break; + } + String[Len - 1] = 0; + Len--; + } + + if (TrimLeft) + { + while (*Pos1 == ' ' || *Pos1 == '\t') + { + Pos1++; + } + + while (*Pos1) + { + *Pos2++ = *Pos1++; + } + *Pos2++ = 0; + } + + return; +} void Log(const char *Fmt, ...) { - va_list Arg; - int Len = 0; - FILE *File = NULL; - SYSTEMTIME Sys; - char szBuf[1024]; + va_list Arg; + int Len = 0; + FILE *File = NULL; + SYSTEMTIME Sys; + char szBuf[1024]; DWORD LockStatus = 0; DWORD PID = GetCurrentProcessId(); - GetLocalTime(&Sys); - Len += sprintf_s(szBuf, sizeof(szBuf), - "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ", - Sys.wYear, Sys.wMonth, Sys.wDay, - Sys.wHour, Sys.wMinute, Sys.wSecond, + GetLocalTime(&Sys); + Len += sprintf_s(szBuf, sizeof(szBuf), + "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ", + Sys.wYear, Sys.wMonth, Sys.wDay, + Sys.wHour, Sys.wMinute, Sys.wSecond, Sys.wMilliseconds, PID); - va_start(Arg, Fmt); - Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg); - va_end(Arg); + va_start(Arg, Fmt); + Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg); + va_end(Arg); MUTEX_LOCK(g_vtoylog_mutex); @@ -130,140 +165,140 @@ void Log(const char *Fmt, ...) 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 }; + 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; - } - } + 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); + 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; - } + hServiceMgr = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hServiceMgr == NULL) + { + Log("OpenSCManager failed Error:%u", GetLastError()); + return 1; + } - Log("OpenSCManager OK"); + 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 = 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; - } - } + hService = OpenServiceA(hServiceMgr, name, SERVICE_ALL_ACCESS); + if (hService == NULL) + { + Log("OpenService failed %u", Status); + CloseServiceHandle(hServiceMgr); + return 1; + } + } - Log("CreateService imdisk OK"); + 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; - } - } + 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); + CloseServiceHandle(hService); + CloseServiceHandle(hServiceMgr); - Log("Load NT driver %s", rc ? "failed" : "success"); + Log("Load NT driver %s", rc ? "failed" : "success"); - return rc; + return rc; } static int ReadWholeFile2Buf(const char *Fullpath, void **Data, DWORD *Size) { - int rc = 1; - DWORD FileSize; - DWORD dwSize; - HANDLE Handle; - BYTE *Buffer = NULL; + int rc = 1; + DWORD FileSize; + DWORD dwSize; + HANDLE Handle; + BYTE *Buffer = NULL; - Log("ReadWholeFile2Buf <%s>", Fullpath); + 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; - } + 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); + FileSize = SetFilePointer(Handle, 0, NULL, FILE_END); - Buffer = malloc(FileSize); - if (!Buffer) - { - Log("Failed to alloc memory size:%u", FileSize); - goto 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; - } + 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; + *Data = Buffer; + *Size = FileSize; - Log("Success read file size:%u", FileSize); + Log("Success read file size:%u", FileSize); - rc = 0; + rc = 0; End: - SAFE_CLOSE_HANDLE(Handle); + SAFE_CLOSE_HANDLE(Handle); - return rc; + return rc; } static BOOL CheckPeHead(BYTE *Buffer, DWORD Size, DWORD Offset) { - UINT32 PeOffset; + UINT32 PeOffset; BYTE *Head = NULL; DWORD End; ventoy_windows_data *pdata = NULL; @@ -281,73 +316,73 @@ static BOOL CheckPeHead(BYTE *Buffer, DWORD Size, DWORD Offset) } } - if (Head[0] != 'M' || Head[1] != 'Z') - { - return FALSE; - } + if (Head[0] != 'M' || Head[1] != 'Z') + { + return FALSE; + } - PeOffset = *(UINT32 *)(Head + 60); - if (*(UINT32 *)(Head + PeOffset) != 0x00004550) - { - return FALSE; - } + PeOffset = *(UINT32 *)(Head + 60); + if (*(UINT32 *)(Head + PeOffset) != 0x00004550) + { + return FALSE; + } - return TRUE; + return TRUE; } static BOOL CheckOsParam(ventoy_os_param *param) { - UINT32 i; - BYTE Sum = 0; + UINT32 i; + BYTE Sum = 0; - if (memcmp(¶m->guid, &g_ventoy_guid, sizeof(ventoy_guid))) - { - return FALSE; - } + if (memcmp(¶m->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; - } + 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; - } + if (param->vtoy_img_location_addr % 4096) + { + return FALSE; + } - return TRUE; + return TRUE; } static int SaveBuffer2File(const char *Fullpath, void *Buffer, DWORD Length) { - int rc = 1; - DWORD dwSize; - HANDLE Handle; + int rc = 1; + DWORD dwSize; + HANDLE Handle; - Log("SaveBuffer2File <%s> len:%u", Fullpath, Length); + 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; - } + 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); + WriteFile(Handle, Buffer, Length, &dwSize, NULL); - rc = 0; + rc = 0; End: - SAFE_CLOSE_HANDLE(Handle); + SAFE_CLOSE_HANDLE(Handle); - return rc; + return rc; } static int IsUTF8Encode(const char *src) @@ -406,17 +441,17 @@ static BOOL IsDirExist(const char *Fmt, ...) static BOOL IsFileExist(const char *Fmt, ...) { - va_list Arg; - HANDLE hFile; - DWORD Attr; + va_list Arg; + HANDLE hFile; + DWORD Attr; BOOL bRet = FALSE; int UTF8 = 0; - CHAR FilePathA[MAX_PATH]; - WCHAR FilePathW[MAX_PATH]; + CHAR FilePathA[MAX_PATH]; + WCHAR FilePathW[MAX_PATH]; - va_start(Arg, Fmt); - vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg); - va_end(Arg); + va_start(Arg, Fmt); + vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg); + va_end(Arg); UTF8 = IsUTF8Encode(FilePathA); @@ -429,12 +464,12 @@ static BOOL IsFileExist(const char *Fmt, ...) { hFile = CreateFileA(FilePathA, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); } - if (INVALID_HANDLE_VALUE == hFile) - { + if (INVALID_HANDLE_VALUE == hFile) + { goto out; - } + } - CloseHandle(hFile); + CloseHandle(hFile); if (UTF8) { @@ -444,7 +479,7 @@ static BOOL IsFileExist(const char *Fmt, ...) { Attr = GetFileAttributesA(FilePathA); } - + if (Attr & FILE_ATTRIBUTE_DIRECTORY) { goto out; @@ -459,66 +494,66 @@ out: static int GetPhyDiskUUID(const char LogicalDrive, UINT8 *UUID, UINT32 *DiskSig, DISK_EXTENT *DiskExtent) { - BOOL Ret; - DWORD dwSize; - HANDLE Handle; - VOLUME_DISK_EXTENTS DiskExtents; - CHAR PhyPath[128]; - UINT8 SectorBuf[512]; + BOOL Ret; + DWORD dwSize; + HANDLE Handle; + VOLUME_DISK_EXTENTS DiskExtents; + CHAR PhyPath[128]; + UINT8 SectorBuf[512]; - Log("GetPhyDiskUUID %C", LogicalDrive); + 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; - } + 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); + 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(DISK_EXTENT)); Log("%C: is in PhysicalDrive%d Offset:%llu", LogicalDrive, DiskExtents.Extents[0].DiskNumber, (ULONGLONG)(DiskExtents.Extents[0].StartingOffset.QuadPart)); - 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; - } + 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); + 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); if (DiskSig) { memcpy(DiskSig, SectorBuf + 0x1B8, 4); } - CloseHandle(Handle); - return 0; + CloseHandle(Handle); + return 0; } static int VentoyMountAnywhere(HANDLE Handle) @@ -605,7 +640,7 @@ int VentoyMountY(HANDLE Handle) static BOOL VentoyAPINeedMountY(const char *IsoPath) { - (void)IsoPath; + (void)IsoPath; /* TBD */ return FALSE; @@ -628,7 +663,7 @@ static int VentoyAttachVirtualDisk(HANDLE Handle, const char *IsoPath) DriveYFree = 1; } - if (DriveYFree && VentoyAPINeedMountY(IsoPath)) + if (DriveYFree && VentoyAPINeedMountY(IsoPath)) { return VentoyMountY(Handle); } @@ -641,13 +676,13 @@ static int VentoyAttachVirtualDisk(HANDLE Handle, const char *IsoPath) int VentoyMountISOByAPI(const char *IsoPath) { int i; - HANDLE Handle; - DWORD Status; - WCHAR wFilePath[512] = { 0 }; - VIRTUAL_STORAGE_TYPE StorageType; - OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters; + HANDLE Handle; + DWORD Status; + WCHAR wFilePath[512] = { 0 }; + VIRTUAL_STORAGE_TYPE StorageType; + OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters; - Log("VentoyMountISOByAPI <%s>", IsoPath); + Log("VentoyMountISOByAPI <%s>", IsoPath); if (IsUTF8Encode(IsoPath)) { @@ -660,10 +695,10 @@ int VentoyMountISOByAPI(const char *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)); - - OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1; + memset(&StorageType, 0, sizeof(StorageType)); + memset(&OpenParameters, 0, sizeof(OpenParameters)); + + OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1; for (i = 0; i < 10; i++) { @@ -696,20 +731,20 @@ int VentoyMountISOByAPI(const char *IsoPath) return 1; } - Log("OpenVirtualDisk success"); + Log("OpenVirtualDisk success"); Status = VentoyAttachVirtualDisk(Handle, IsoPath); - if (Status != ERROR_SUCCESS) - { - Log("Failed to attach virtual disk ErrorCode:%u", Status); - CloseHandle(Handle); - return 1; - } + if (Status != ERROR_SUCCESS) + { + Log("Failed to attach virtual disk ErrorCode:%u", Status); + CloseHandle(Handle); + return 1; + } Log("VentoyAttachVirtualDisk success"); - CloseHandle(Handle); - return 0; + CloseHandle(Handle); + return 0; } @@ -718,282 +753,373 @@ 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; + int rc = 1; + int size = 0; + char *buf = NULL; + void *flfile = NULL; - Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile, DstFile); + 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); + 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); + buf = (char *)malloc(size); + if (buf) + { + fl_fread(buf, 1, size, flfile); - rc = 0; - SaveBuffer2File(DstFile, buf, size); - free(buf); - } + rc = 0; + SaveBuffer2File(DstFile, buf, size); + free(buf); + } - fl_fclose(flfile); - } + fl_fclose(flfile); + } - return rc; + return rc; } static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount) { - DWORD dwSize; - BOOL bRet; - DWORD ReadSize; - LARGE_INTEGER liCurrentPosition; + DWORD dwSize; + BOOL bRet; + DWORD ReadSize; + LARGE_INTEGER liCurrentPosition; - liCurrentPosition.QuadPart = Sector + g_Part2StartSec; - liCurrentPosition.QuadPart *= 512; - SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN); + liCurrentPosition.QuadPart = Sector + g_Part2StartSec; + liCurrentPosition.QuadPart *= 512; + SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN); - ReadSize = (DWORD)(SectorCount * 512); + 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", bRet, ReadSize, dwSize, GetLastError()); - } + bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL); + if (bRet == FALSE || dwSize != ReadSize) + { + Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u", bRet, ReadSize, dwSize, GetLastError()); + } - return 1; + return 1; } static BOOL Is2K10PE(void) { - BOOL bRet = FALSE; - FILE *fp = NULL; - CHAR szLine[1024]; + BOOL bRet = FALSE; + FILE *fp = NULL; + CHAR szLine[1024]; - fopen_s(&fp, "X:\\Windows\\System32\\PECMD.INI", "r"); - if (!fp) - { - return FALSE; - } + fopen_s(&fp, "X:\\Windows\\System32\\PECMD.INI", "r"); + if (!fp) + { + return FALSE; + } - memset(szLine, 0, sizeof(szLine)); - while (fgets(szLine, sizeof(szLine) - 1, fp)) - { - if (strstr(szLine, "2k10\\")) - { - bRet = TRUE; - break; - } - } + memset(szLine, 0, sizeof(szLine)); + while (fgets(szLine, sizeof(szLine) - 1, fp)) + { + if (strstr(szLine, "2k10\\")) + { + bRet = TRUE; + break; + } + } - fclose(fp); - return bRet; + fclose(fp); + return bRet; } static CHAR GetIMDiskMountLogicalDrive(void) { - CHAR Letter = 'Y'; - DWORD Drives; - DWORD Mask = 0x1000000; + CHAR Letter = 'Y'; + DWORD Drives; + DWORD Mask = 0x1000000; - // fixed use M as mountpoint for 2K10 PE - if (Is2K10PE()) - { - Log("Use M: for 2K10 PE"); - return 'M'; - } + // fixed use M as mountpoint for 2K10 PE + if (Is2K10PE()) + { + Log("Use M: for 2K10 PE"); + return 'M'; + } - Drives = GetLogicalDrives(); + Drives = GetLogicalDrives(); Log("Drives=0x%x", Drives); - while (Mask) - { - if ((Drives & Mask) == 0) - { - break; - } + while (Mask) + { + if ((Drives & Mask) == 0) + { + break; + } - Letter--; - Mask >>= 1; - } + Letter--; + Mask >>= 1; + } - return Letter; + return Letter; } UINT64 GetVentoyEfiPartStartSector(HANDLE hDrive) { - BOOL bRet; - DWORD dwSize; - MBR_HEAD MBR; - VTOY_GPT_INFO *pGpt = NULL; - UINT64 StartSector = 0; + BOOL bRet; + DWORD dwSize; + MBR_HEAD MBR; + VTOY_GPT_INFO *pGpt = NULL; + UINT64 StartSector = 0; - SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); + 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); + 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 ((!bRet) || (dwSize != sizeof(MBR))) + { + 0; + } - if (MBR.PartTbl[0].FsFlag == 0xEE) - { - Log("GPT partition style"); + if (MBR.PartTbl[0].FsFlag == 0xEE) + { + Log("GPT partition style"); - pGpt = malloc(sizeof(VTOY_GPT_INFO)); - if (!pGpt) - { - return 0; - } + 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; - } + 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; - } + StartSector = pGpt->PartTbl[1].StartLBA; + free(pGpt); + } + else + { + Log("MBR partition style"); + StartSector = MBR.PartTbl[1].StartSectorId; + } - Log("GetVentoyEfiPart StartSector: %llu", StartSector); - return StartSector; + Log("GetVentoyEfiPart StartSector: %llu", StartSector); + return StartSector; } static int VentoyRunImdisk(const char *IsoPath, const char *imdiskexe) { - CHAR Letter; - CHAR Cmdline[512]; - WCHAR CmdlineW[512]; - PROCESS_INFORMATION Pi; + CHAR Letter; + CHAR Cmdline[512]; + WCHAR CmdlineW[512]; + PROCESS_INFORMATION Pi; - Log("VentoyRunImdisk <%s> <%s>", IsoPath, imdiskexe); + Log("VentoyRunImdisk <%s> <%s>", IsoPath, imdiskexe); - Letter = GetIMDiskMountLogicalDrive(); - sprintf_s(Cmdline, sizeof(Cmdline), "%s -a -o ro -f \"%s\" -m %C:", imdiskexe, IsoPath, Letter); - Log("mount iso to %C: use imdisk cmd <%s>", Letter, Cmdline); + Letter = GetIMDiskMountLogicalDrive(); + sprintf_s(Cmdline, sizeof(Cmdline), "%s -a -o ro -f \"%s\" -m %C:", imdiskexe, IsoPath, Letter); + Log("mount iso to %C: use imdisk cmd <%s>", Letter, Cmdline); - if (IsUTF8Encode(IsoPath)) - { - STARTUPINFOW Si; - GetStartupInfoW(&Si); - Si.dwFlags |= STARTF_USESHOWWINDOW; - Si.wShowWindow = SW_HIDE; + if (IsUTF8Encode(IsoPath)) + { + STARTUPINFOW Si; + GetStartupInfoW(&Si); + Si.dwFlags |= STARTF_USESHOWWINDOW; + Si.wShowWindow = SW_HIDE; - Utf8ToUtf16(Cmdline, CmdlineW); - CreateProcessW(NULL, CmdlineW, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); + Utf8ToUtf16(Cmdline, CmdlineW); + CreateProcessW(NULL, CmdlineW, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); - Log("This is UTF8 encoding"); - } - else - { - STARTUPINFOA Si; - GetStartupInfoA(&Si); - Si.dwFlags |= STARTF_USESHOWWINDOW; - Si.wShowWindow = SW_HIDE; + Log("This is UTF8 encoding"); + } + else + { + STARTUPINFOA Si; + GetStartupInfoA(&Si); + Si.dwFlags |= STARTF_USESHOWWINDOW; + Si.wShowWindow = SW_HIDE; - CreateProcessA(NULL, Cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); + CreateProcessA(NULL, Cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); - Log("This is ANSI encoding"); - } + Log("This is ANSI encoding"); + } - Log("Wait for imdisk process ..."); - WaitForSingleObject(Pi.hProcess, INFINITE); - Log("imdisk process finished"); + Log("Wait for imdisk process ..."); + WaitForSingleObject(Pi.hProcess, INFINITE); + Log("imdisk process finished"); - return 0; + return 0; } int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive) { - int rc = 1; - BOOL bRet; - DWORD dwBytes; - HANDLE hDrive; - CHAR PhyPath[MAX_PATH]; - GET_LENGTH_INFORMATION LengthInfo; + int rc = 1; + BOOL bRet; + DWORD dwBytes; + HANDLE hDrive; + CHAR PhyPath[MAX_PATH]; + GET_LENGTH_INFORMATION LengthInfo; - Log("VentoyMountISOByImdisk %s", IsoPath); + Log("VentoyMountISOByImdisk %s", IsoPath); - if (IsFileExist("X:\\Windows\\System32\\imdisk.exe")) - { - Log("imdisk.exe exist, use it directly..."); - VentoyRunImdisk(IsoPath, "imdisk.exe"); - return 0; - } + if (IsFileExist("X:\\Windows\\System32\\imdisk.exe")) + { + Log("imdisk.exe exist, use it directly..."); + VentoyRunImdisk(IsoPath, "imdisk.exe"); + return 0; + } - sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", PhyDrive); + 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; - } + 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; - } + 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); + g_FatPhyDrive = hDrive; + g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive); - Log("Parse FAT fs..."); + Log("Parse FAT fs..."); - fl_init(); + fl_init(); - if (0 == fl_attach_media(VentoyFatDiskRead, NULL)) - { - if (g_system_bit == 64) - { - 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 (0 == fl_attach_media(VentoyFatDiskRead, NULL)) + { + if (g_system_bit == 64) + { + 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) - { - VentoyRunImdisk(IsoPath, "ventoy\\imdisk.exe"); - rc = 0; - } - } - fl_shutdown(); + if (LoadNtDriver(PhyPath) == 0) + { + VentoyRunImdisk(IsoPath, "ventoy\\imdisk.exe"); + rc = 0; + } + } + fl_shutdown(); End: - SAFE_CLOSE_HANDLE(hDrive); + SAFE_CLOSE_HANDLE(hDrive); - return rc; + return rc; +} + +static int GetIsoId(CONST CHAR *IsoPath, IsoId *ids) +{ + int i; + int n = 0; + HANDLE hFile; + DWORD dwSize = 0; + BOOL bRet[8]; + + hFile = CreateFileA(IsoPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + return 1; + } + + SetFilePointer(hFile, 2048 * 16 + 8, NULL, FILE_BEGIN); + bRet[n++] = ReadFile(hFile, ids->SystemId, 32, &dwSize, NULL); + + SetFilePointer(hFile, 2048 * 16 + 40, NULL, FILE_BEGIN); + bRet[n++] = ReadFile(hFile, ids->VolumeId, 32, &dwSize, NULL); + + SetFilePointer(hFile, 2048 * 16 + 318, NULL, FILE_BEGIN); + bRet[n++] = ReadFile(hFile, ids->PulisherId, 128, &dwSize, NULL); + + SetFilePointer(hFile, 2048 * 16 + 446, NULL, FILE_BEGIN); + bRet[n++] = ReadFile(hFile, ids->PreparerId, 128, &dwSize, NULL); + + CloseHandle(hFile); + + + for (i = 0; i < n; i++) + { + if (bRet[i] == FALSE) + { + return 1; + } + } + + + TrimString(ids->SystemId, FALSE); + TrimString(ids->VolumeId, FALSE); + TrimString(ids->PulisherId, FALSE); + TrimString(ids->PreparerId, FALSE); + + Log("ISO ID: System<%s> Volume<%s> Pulisher<%s> Preparer<%s>", + ids->SystemId, ids->VolumeId, ids->PulisherId, ids->PreparerId); + + return 0; +} + +static int CheckSkipMountIso(CONST CHAR *IsoPath) +{ + BOOL InRoot = FALSE; + int slashcnt = 0; + CONST CHAR *p = NULL; + IsoId ID; + + // C:\\xxx + for (p = IsoPath; *p; p++) + { + if (*p == '\\' || *p == '/') + { + slashcnt++; + } + } + + if (slashcnt == 2) + { + InRoot = TRUE; + } + + memset(&ID, 0, sizeof(ID)); + if (GetIsoId(IsoPath, &ID)) + { + return 0; + } + + //Bob.Ombs.Modified.Win10PEx64.iso will auto find ISO file in root, so we can skip the mount + if (InRoot && strcmp(ID.VolumeId, "Modified-Win10PEx64") == 0) + { + return 1; + } + + return 0; } static int MountIsoFile(CONST CHAR *IsoPath, DWORD PhyDrive) { + if (CheckSkipMountIso(IsoPath)) + { + Log("Skip mount ISO file for <%s>", IsoPath); + return 0; + } + if (IsWindows8OrGreater()) { Log("This is Windows 8 or latter..."); @@ -1196,7 +1322,7 @@ static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive) } g_FatPhyDrive = hDrive; - g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive); + g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive); Log("Parse FAT fs..."); @@ -1204,7 +1330,7 @@ static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive) if (0 == fl_attach_media(VentoyFatDiskRead, NULL)) { - if (g_system_bit == 64) + if (g_system_bit == 64) { CopyFileFromFatDisk("/ventoy/7z/64/7za.xz", "ventoy\\7za.xz"); } @@ -1301,10 +1427,10 @@ static int UnattendNeedVarExpand(const char *script) char szLine[4096]; fopen_s(&fp, script, "r"); - if (!fp) - { - return 0; - } + if (!fp) + { + return 0; + } szLine[0] = szLine[4095] = 0; @@ -1417,36 +1543,6 @@ static int ExpandSingleVar(VarDiskInfo *pDiskInfo, int DiskNum, const char *var, return 0; } -static void TrimString(CHAR *String) -{ - CHAR *Pos1 = String; - CHAR *Pos2 = String; - size_t Len = strlen(String); - - while (Len > 0) - { - if (String[Len - 1] != ' ' && String[Len - 1] != '\t') - { - break; - } - String[Len - 1] = 0; - Len--; - } - - while (*Pos1 == ' ' || *Pos1 == '\t') - { - Pos1++; - } - - while (*Pos1) - { - *Pos2++ = *Pos1++; - } - *Pos2++ = 0; - - return; -} - static int GetRegDwordValue(HKEY Key, LPCSTR SubKey, LPCSTR ValueName, DWORD *pValue) { HKEY hKey; @@ -1655,25 +1751,25 @@ static int EnumerateAllDisk(VarDiskInfo **ppDiskInfo, int *pDiskNum) if (pDevDesc->VendorIdOffset) { safe_strcpy(pDiskInfo[i].VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset); - TrimString(pDiskInfo[i].VendorId); + TrimString(pDiskInfo[i].VendorId, TRUE); } if (pDevDesc->ProductIdOffset) { safe_strcpy(pDiskInfo[i].ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset); - TrimString(pDiskInfo[i].ProductId); + TrimString(pDiskInfo[i].ProductId, TRUE); } if (pDevDesc->ProductRevisionOffset) { safe_strcpy(pDiskInfo[i].ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset); - TrimString(pDiskInfo[i].ProductRev); + TrimString(pDiskInfo[i].ProductRev, TRUE); } if (pDevDesc->SerialNumberOffset) { safe_strcpy(pDiskInfo[i].SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset); - TrimString(pDiskInfo[i].SerialNumber); + TrimString(pDiskInfo[i].SerialNumber, TRUE); } free(pDevDesc); @@ -1716,19 +1812,19 @@ static int UnattendVarExpand(const char *script, const char *tmpfile) } fopen_s(&fp, script, "r"); - if (!fp) - { + if (!fp) + { free(pDiskInfo); - return 0; - } + return 0; + } fopen_s(&fout, tmpfile, "w+"); - if (!fout) - { - fclose(fp); + if (!fout) + { + fclose(fp); free(pDiskInfo); - return 0; - } + return 0; + } szLine[0] = szLine[4095] = 0; @@ -1979,12 +2075,12 @@ static int VentoyHook(ventoy_os_param *param) DWORD VtoyDiskNum; UINT32 DiskSig; UINT32 VtoySig; - DISK_EXTENT DiskExtent; + DISK_EXTENT DiskExtent; DISK_EXTENT VtoyDiskExtent; - UINT8 UUID[16]; - CHAR IsoPath[MAX_PATH]; + UINT8 UUID[16]; + CHAR IsoPath[MAX_PATH]; - Log("VentoyHook Path:<%s>", param->vtoy_img_path); + Log("VentoyHook Path:<%s>", param->vtoy_img_path); if (IsUTF8Encode(param->vtoy_img_path)) { @@ -2039,12 +2135,12 @@ static int VentoyHook(ventoy_os_param *param) } if (find == FALSE) - { - Log("Failed to find ISO file"); - return 1; - } + { + Log("Failed to find ISO file"); + return 1; + } - Log("Find ISO file <%s>", IsoPath); + Log("Find ISO file <%s>", IsoPath); //Find VtoyLetter in Vlnk Mode if (g_os_param_reserved[6] == 1) @@ -2258,59 +2354,6 @@ static int ExtractWindowsDataFile(char *databuf) return len; } -int VentoyJumpWimboot(INT argc, CHAR **argv, CHAR *LunchFile) -{ - int rc = 1; - char *buf = NULL; - DWORD size = 0; - DWORD Pos; - - Log("VentoyJumpWimboot %dbit", g_system_bit); - - sprintf_s(LunchFile, MAX_PATH, "X:\\setup.exe"); - - ReadWholeFile2Buf("wimboot.data", &buf, &size); - Log("wimboot.data size:%d", size); - - memcpy(&g_os_param, buf, sizeof(ventoy_os_param)); - memcpy(&g_windows_data, buf + sizeof(ventoy_os_param), sizeof(ventoy_windows_data)); - ExtractWindowsDataFile(buf + sizeof(ventoy_os_param)); - 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] = '\\'; - } - } - - if (g_os_param_reserved[0] == 2) - { - Log("skip hook for debug ....."); - rc = 0; - goto End; - } - - rc = VentoyHook(&g_os_param); - -End: - - if (buf) - { - free(buf); - } - - return rc; -} - static int ventoy_check_create_directory(void) { if (IsDirExist("ventoy")) @@ -2332,31 +2375,31 @@ static int ventoy_check_create_directory(void) int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile) { - int rc = 1; + int rc = 1; int stat = 0; int exlen = 0; - DWORD Pos; - DWORD PeStart; + DWORD Pos; + DWORD PeStart; DWORD FileSize; DWORD LockStatus = 0; - BYTE *Buffer = NULL; - CHAR ExeFileName[MAX_PATH]; + BYTE *Buffer = NULL; + CHAR ExeFileName[MAX_PATH]; - sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]); - if (!IsFileExist("%s", ExeFileName)) - { - Log("File %s NOT exist, now try %s.exe", ExeFileName, ExeFileName); - sprintf_s(ExeFileName, sizeof(ExeFileName), "%s.exe", argv[0]); + sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]); + if (!IsFileExist("%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, IsFileExist("%s", ExeFileName) ? "YES" : "NO"); - } + Log("File %s exist ? %s", ExeFileName, IsFileExist("%s", ExeFileName) ? "YES" : "NO"); + } - if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize)) - { - goto End; - } - - Log("VentoyJump %dbit", g_system_bit); + if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize)) + { + goto End; + } + + Log("VentoyJump %dbit", g_system_bit); MUTEX_LOCK(g_vtoyins_mutex); stat = ventoy_check_create_directory(); @@ -2367,12 +2410,12 @@ int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile) goto End; } - for (PeStart = 0; PeStart < FileSize; PeStart += 16) - { - if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) && + for (PeStart = 0; PeStart < FileSize; PeStart += 16) + { + if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) && CheckPeHead(Buffer, FileSize, PeStart + sizeof(ventoy_os_param))) - { - Log("Find os pararm at %u", PeStart); + { + 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)); @@ -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)); if (g_os_param_reserved[0] == 1) - { - Log("break here for debug ....."); - goto End; - } + { + Log("break here for debug ....."); + goto End; + } - // convert / to \\ + // 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) + exlen; - sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName)); + PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data) + exlen; + sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName)); MUTEX_LOCK(g_vtoyins_mutex); if (IsFileExist("%s", LunchFile)) @@ -2406,18 +2449,18 @@ int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile) goto End; } - SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart); + SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart); MUTEX_UNLOCK(g_vtoyins_mutex); - break; - } - } + break; + } + } - if (PeStart >= FileSize) - { - Log("OS param not found"); - goto End; - } + if (PeStart >= FileSize) + { + Log("OS param not found"); + goto End; + } if (g_os_param_reserved[0] == 2) { @@ -2430,128 +2473,112 @@ int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile) End: - if (Buffer) - { - free(Buffer); - } + if (Buffer) + { + free(Buffer); + } - return rc; + return rc; } int real_main(int argc, char **argv) { - int i = 0; - int rc = 0; - int wimboot = 0; - CHAR NewFile[MAX_PATH]; - CHAR LunchFile[MAX_PATH]; - CHAR CallParam[1024] = { 0 }; - STARTUPINFOA Si; - PROCESS_INFORMATION Pi; + int i = 0; + int rc = 0; + CHAR NewFile[MAX_PATH]; + CHAR LunchFile[MAX_PATH]; + CHAR CallParam[1024] = { 0 }; + STARTUPINFOA Si; + PROCESS_INFORMATION Pi; - Log("#### real_main #### argc = %d", argc); + Log("#### real_main #### argc = %d", argc); Log("program full path: <%s>", g_prog_full_path); Log("program dir: <%s>", g_prog_dir); - Log("program name:: <%s>", g_prog_name); + Log("program name: <%s>", g_prog_name); Log("argc = %d", argc); - for (i = 0; i < argc; i++) - { - Log("argv[%d]=<%s>", i, argv[i]); - if (i > 0) - { - strcat_s(CallParam, sizeof(CallParam), " "); - strcat_s(CallParam, sizeof(CallParam), argv[i]); - } - } - - GetStartupInfoA(&Si); - memset(LunchFile, 0, sizeof(LunchFile)); - - if (strstr(argv[0], "vtoyjump.exe")) - { - wimboot = 1; - DeleteFileA(WINPESHL_INI); - IsFileExist(WINPESHL_INI); - rc = VentoyJumpWimboot(argc, argv, LunchFile); - } - else - { - rc = VentoyJump(argc, argv, LunchFile); - } - - Log("LunchFile=<%s> CallParam=<%s>", LunchFile, CallParam); - - if (_stricmp(g_prog_name, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name)) - { - sprintf_s(NewFile, sizeof(NewFile), "%s_BACK.EXE", g_prog_full_path); - MoveFileA(g_prog_full_path, NewFile); - Log("Move <%s> to <%s>", g_prog_full_path, NewFile); - - sprintf_s(NewFile, sizeof(NewFile), "ventoy\\%s", g_prog_name); - CopyFileA(NewFile, g_prog_full_path, TRUE); - Log("Copy <%s> to <%s>", NewFile, g_prog_full_path); - - sprintf_s(LunchFile, sizeof(LunchFile), "%s", g_prog_full_path); - Log("Final lunchFile is <%s>", LunchFile); - } - else if (wimboot && IsFileExist(WINPESHL_INI)) + for (i = 0; i < argc; i++) { - sprintf_s(LunchFile, MAX_PATH, "X:\\Windows\\system32\\winpeshl.exe"); - Log("winpeshl.ini updated, now recall winpeshl.exe"); + Log("argv[%d]=<%s>", i, argv[i]); + if (i > 0) + { + strcat_s(CallParam, sizeof(CallParam), " "); + strcat_s(CallParam, sizeof(CallParam), argv[i]); + } + } + + GetStartupInfoA(&Si); + memset(LunchFile, 0, sizeof(LunchFile)); + + rc = VentoyJump(argc, argv, LunchFile); + + Log("LunchFile=<%s> CallParam=<%s>", LunchFile, CallParam); + + if (_stricmp(g_prog_name, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name)) + { + sprintf_s(NewFile, sizeof(NewFile), "%s_BACK.EXE", g_prog_full_path); + MoveFileA(g_prog_full_path, NewFile); + Log("Move <%s> to <%s>", g_prog_full_path, NewFile); + + sprintf_s(NewFile, sizeof(NewFile), "ventoy\\%s", g_prog_name); + CopyFileA(NewFile, g_prog_full_path, TRUE); + Log("Copy <%s> to <%s>", NewFile, g_prog_full_path); + + sprintf_s(LunchFile, sizeof(LunchFile), "%s", g_prog_full_path); + Log("Final lunchFile is <%s>", LunchFile); } else { Log("We don't need to recover original <%s>", g_prog_name); } - if (g_os_param_reserved[0] == 3) - { - Log("Open log for debug ..."); - sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log"); - } - else - { - if (CallParam[0]) - { - strcat_s(LunchFile, sizeof(LunchFile), CallParam); - } - else if (NULL == strstr(LunchFile, "setup.exe")) - { - Log("Not setup.exe, hide windows."); - Si.dwFlags |= STARTF_USESHOWWINDOW; - Si.wShowWindow = SW_HIDE; - } + if (g_os_param_reserved[0] == 3) + { + Log("Open log for debug ..."); + sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log"); + } + else + { + if (CallParam[0]) + { + strcat_s(LunchFile, sizeof(LunchFile), CallParam); + } + else if (NULL == strstr(LunchFile, "setup.exe")) + { + Log("Not setup.exe, hide windows."); + Si.dwFlags |= STARTF_USESHOWWINDOW; + Si.wShowWindow = SW_HIDE; + } - Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed"); - } + Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed"); + } - Log("Now launch <%s> ...", LunchFile); + Log("Now launch <%s> ...", LunchFile); - if (g_os_param_reserved[0] == 4) - { - Log("Open cmd for debug ..."); - sprintf_s(LunchFile, sizeof(LunchFile), "%s", "cmd.exe"); - } + if (g_os_param_reserved[0] == 4) + { + Log("Open cmd for debug ..."); + sprintf_s(LunchFile, sizeof(LunchFile), "%s", "cmd.exe"); + } Log("Backup log at this point"); CopyFileA(LOG_FILE, "X:\\Windows\\ventoy.backup", TRUE); - CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); + CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); - for (i = 0; rc && i < 1800; i++) - { - Log("Ventoy hook failed, now wait and retry ..."); - Sleep(1000); - rc = VentoyHook(&g_os_param); - } + for (i = 0; rc && i < 1800; i++) + { + Log("Ventoy hook failed, now wait and retry ..."); + Sleep(1000); + rc = VentoyHook(&g_os_param); + } - Log("Wait process..."); - WaitForSingleObject(Pi.hProcess, INFINITE); + Log("Wait process..."); + WaitForSingleObject(Pi.hProcess, INFINITE); - Log("vtoyjump finished"); - return 0; + Log("vtoyjump finished"); + return 0; } static void VentoyToUpper(CHAR *str) @@ -2563,39 +2590,80 @@ static void VentoyToUpper(CHAR *str) } } +static int vtoy_remove_duplicate_file(char *File) +{ + CHAR szCmd[MAX_PATH]; + CHAR NewFile[MAX_PATH]; + STARTUPINFOA Si; + PROCESS_INFORMATION Pi; + + Log("<1> Copy New file", File); + sprintf_s(NewFile, sizeof(NewFile), "%s_NEW", File); + CopyFileA(File, NewFile, FALSE); + + Log("<2> Remove file <%s>", File); + GetStartupInfoA(&Si); + Si.dwFlags |= STARTF_USESHOWWINDOW; + Si.wShowWindow = SW_HIDE; + sprintf_s(szCmd, sizeof(szCmd), "cmd.exe /c del /F /Q %s", File); + CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); + WaitForSingleObject(Pi.hProcess, INFINITE); + + Log("<3> Copy back file <%s>", File); + MoveFileA(NewFile, File); + + return 0; +} + int main(int argc, char **argv) { - int i; - STARTUPINFOA Si; - PROCESS_INFORMATION Pi; - CHAR CurDir[MAX_PATH]; + int i; + STARTUPINFOA Si; + PROCESS_INFORMATION Pi; + CHAR CurDir[MAX_PATH]; CHAR NewArgv0[MAX_PATH]; - CHAR CallParam[1024] = { 0 }; + CHAR CallParam[1024] = { 0 }; - g_vtoylog_mutex = CreateMutexA(NULL, FALSE, "VTOYLOG_LOCK"); - g_vtoyins_mutex = CreateMutexA(NULL, FALSE, "VTOYINS_LOCK"); + g_vtoylog_mutex = CreateMutexA(NULL, FALSE, "VTOYLOG_LOCK"); + g_vtoyins_mutex = CreateMutexA(NULL, FALSE, "VTOYINS_LOCK"); - Log("######## VentoyJump %dbit ##########", g_system_bit); + Log("######## VentoyJump %dbit ##########", g_system_bit); - GetCurrentDirectoryA(sizeof(CurDir), CurDir); - Log("Current directory is <%s>", CurDir); - - GetModuleFileNameA(NULL, g_prog_full_path, MAX_PATH); + GetCurrentDirectoryA(sizeof(CurDir), CurDir); + Log("Current directory is <%s>", CurDir); + + GetModuleFileNameA(NULL, g_prog_full_path, MAX_PATH); split_path_name(g_prog_full_path, g_prog_dir, g_prog_name); - Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path, g_prog_dir, g_prog_name); + Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path, g_prog_dir, g_prog_name); - if (_stricmp(g_prog_name, "WinLogon.exe") == 0) - { - Log("This time is rejump back ..."); - - strcpy_s(g_prog_full_path, sizeof(g_prog_full_path), argv[1]); + if (IsFileExist(WIMBOOT_FILE)) + { + Log("This is wimboot mode ..."); + g_wimboot_mode = TRUE; + + if (!IsFileExist(WIMBOOT_DONE)) + { + vtoy_remove_duplicate_file(g_prog_full_path); + SaveBuffer2File(WIMBOOT_DONE, g_prog_full_path, 1); + } + } + else + { + Log("This is normal mode ..."); + } + + if (_stricmp(g_prog_name, "WinLogon.exe") == 0) + { + Log("This time is rejump back ..."); + + strcpy_s(g_prog_full_path, sizeof(g_prog_full_path), argv[1]); split_path_name(g_prog_full_path, g_prog_dir, g_prog_name); - return real_main(argc - 1, argv + 1); - } - else if (_stricmp(g_prog_name, "PECMD.exe") == 0) - { + return real_main(argc - 1, argv + 1); + } + else if (_stricmp(g_prog_name, "PECMD.exe") == 0) + { strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_dir); VentoyToUpper(NewArgv0); @@ -2613,32 +2681,31 @@ int main(int argc, char **argv) sprintf_s(CallParam, sizeof(CallParam), "ventoy\\WinLogon.exe %s", g_prog_full_path); } - - for (i = 1; i < argc; i++) - { - strcat_s(CallParam, sizeof(CallParam), " "); - strcat_s(CallParam, sizeof(CallParam), argv[i]); - } + + for (i = 1; i < argc; i++) + { + strcat_s(CallParam, sizeof(CallParam), " "); + strcat_s(CallParam, sizeof(CallParam), argv[i]); + } - Log("Now rejump to <%s> ...", CallParam); - GetStartupInfoA(&Si); - CreateProcessA(NULL, CallParam, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); + Log("Now rejump to <%s> ...", CallParam); + GetStartupInfoA(&Si); + CreateProcessA(NULL, CallParam, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); - Log("Wait rejump process..."); - WaitForSingleObject(Pi.hProcess, INFINITE); - Log("rejump finished"); - return 0; - } - else - { - Log("We don't need to rejump ..."); + Log("Wait rejump process..."); + WaitForSingleObject(Pi.hProcess, INFINITE); + Log("rejump finished"); + return 0; + } + else + { + Log("We don't need to rejump ..."); ventoy_check_create_directory(); strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_full_path); argv[0] = NewArgv0; - return real_main(argc, argv); - } + return real_main(argc, argv); + } } - diff --git a/vtoyjump/vtoyjump/vtoyjump.h b/vtoyjump/vtoyjump/vtoyjump.h index b19b334c..768d7cc2 100644 --- a/vtoyjump/vtoyjump/vtoyjump.h +++ b/vtoyjump/vtoyjump/vtoyjump.h @@ -164,6 +164,13 @@ typedef struct VarDiskInfo CHAR SerialNumber[128]; }VarDiskInfo; +typedef struct IsoId +{ + CHAR SystemId[64]; + CHAR VolumeId[64]; + CHAR PulisherId[256]; + CHAR PreparerId[256]; +}IsoId; #define SAFE_CLOSE_HANDLE(handle) \ {\