Commit 4fda20d8 authored by longpanda's avatar longpanda
Browse files

update

parent b32cf97f
...@@ -12,7 +12,7 @@ make install ...@@ -12,7 +12,7 @@ make install
PATH=$PATH:$VT_DIR/GRUB2/INSTALL/bin/:$VT_DIR/GRUB2/INSTALL/sbin/ PATH=$PATH:$VT_DIR/GRUB2/INSTALL/bin/:$VT_DIR/GRUB2/INSTALL/sbin/
net_modules_legacy="net tftp http" net_modules_legacy="net tftp http"
all_modules_legacy="date drivemap blocklist ntldr search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio lspci pci ext2 xfs ventoy chain read halt iso9660 linux16 test true sleep reboot echo videotest videoinfo videotest_checksum video_colors video_cirrus video_bochs vga vbe video_fb font video gettext extcmd terminal linux minicmd help configfile tr trig boot biosdisk disk ls tar squash4 password_pbkdf2 all_video png jpeg part_gpt part_msdos fat exfat ntfs loopback gzio normal udf gfxmenu gfxterm gfxterm_background gfxterm_menu" all_modules_legacy="date drivemap blocklist vga_text ntldr search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio lspci pci ext2 xfs ventoy chain read halt iso9660 linux16 test true sleep reboot echo videotest videoinfo videotest_checksum video_colors video_cirrus video_bochs vga vbe video_fb font video gettext extcmd terminal linux minicmd help configfile tr trig boot biosdisk disk ls tar squash4 password_pbkdf2 all_video png jpeg part_gpt part_msdos fat exfat ntfs loopback gzio normal udf gfxmenu gfxterm gfxterm_background gfxterm_menu"
net_modules_uefi="efinet net tftp http" net_modules_uefi="efinet net tftp http"
all_modules_uefi="blocklist ventoy test search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu" all_modules_uefi="blocklist ventoy test search at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio ext2 xfs read halt sleep serial terminfo png password_pbkdf2 gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback part_apple minicmd diskfilter linux relocator jpeg iso9660 udf hfsplus halt acpi mmap gfxmenu video_colors trig bitmap_scale gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo configfile normal terminal gettext chain priority_queue bufio datetime cat extcmd crypto gzio boot all_video efi_gop efi_uga video_bochs video_cirrus video video_fb gfxterm_background gfxterm_menu"
......
No preview for this file type
...@@ -23,6 +23,8 @@ sh buildlib.sh ...@@ -23,6 +23,8 @@ sh buildlib.sh
cd $VTOY_PATH/vtoyfat cd $VTOY_PATH/vtoyfat
sh build.sh || exit 1 sh build.sh || exit 1
cd $VTOY_PATH/vtoygpt
sh build.sh || exit 1
cd $VTOY_PATH/ExFAT cd $VTOY_PATH/ExFAT
sh buidlibfuse.sh || exit 1 sh buidlibfuse.sh || exit 1
......
...@@ -30,6 +30,29 @@ function ventoy_debug_pause { ...@@ -30,6 +30,29 @@ function ventoy_debug_pause {
fi fi
} }
function ventoy_cli_console {
if [ "$grub_platform" = "pc" ]; then
terminal_output vga_text
else
if [ "$vtoy_display_mode" != "CLI" ]; then
terminal_output console
fi
fi
}
function ventoy_gui_console {
if [ "$grub_platform" = "pc" ]; then
if [ "$vtoy_display_mode" = "CLI" ]; then
terminal_output console
else
terminal_output gfxterm
fi
else
if [ "$vtoy_display_mode" != "CLI" ]; then
terminal_output gfxterm
fi
fi
}
function ventoy_power { function ventoy_power {
configfile $prefix/power.cfg configfile $prefix/power.cfg
...@@ -186,7 +209,7 @@ function uefi_windows_menu_func { ...@@ -186,7 +209,7 @@ function uefi_windows_menu_func {
ventoy_debug_pause ventoy_debug_pause
if [ -n "$vtoy_chain_mem_addr" ]; then if [ -n "$vtoy_chain_mem_addr" ]; then
terminal_output console ventoy_cli_console
chainloader ${vtoy_path}/ventoy_x64.efi env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size} chainloader ${vtoy_path}/ventoy_x64.efi env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}
boot boot
else else
...@@ -262,7 +285,7 @@ function uefi_linux_menu_func { ...@@ -262,7 +285,7 @@ function uefi_linux_menu_func {
vt_linux_chain_data ${1}${chosen_path} vt_linux_chain_data ${1}${chosen_path}
if [ -n "$vtoy_chain_mem_addr" ]; then if [ -n "$vtoy_chain_mem_addr" ]; then
terminal_output console ventoy_cli_console
chainloader ${vtoy_path}/ventoy_x64.efi env_param=${env_param} isoefi=${LoadIsoEfiDriver} FirstTry=${FirstTryBootFile} ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size} chainloader ${vtoy_path}/ventoy_x64.efi env_param=${env_param} isoefi=${LoadIsoEfiDriver} FirstTry=${FirstTryBootFile} ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}
boot boot
else else
...@@ -327,7 +350,7 @@ function uefi_iso_menu_func { ...@@ -327,7 +350,7 @@ function uefi_iso_menu_func {
uefi_linux_menu_func $1 ${chosen_path} uefi_linux_menu_func $1 ${chosen_path}
fi fi
terminal_output gfxterm ventoy_gui_console
} }
function uefi_iso_memdisk { function uefi_iso_memdisk {
...@@ -336,11 +359,11 @@ function uefi_iso_memdisk { ...@@ -336,11 +359,11 @@ function uefi_iso_memdisk {
echo 'Loading ISO file to memory ...' echo 'Loading ISO file to memory ...'
vt_load_iso_to_mem ${1}${chosen_path} vtoy_iso_buf vt_load_iso_to_mem ${1}${chosen_path} vtoy_iso_buf
terminal_output console ventoy_cli_console
chainloader ${vtoy_path}/ventoy_x64.efi memdisk env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_iso_buf_addr}:size:${vtoy_iso_buf_size} chainloader ${vtoy_path}/ventoy_x64.efi memdisk env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_iso_buf_addr}:size:${vtoy_iso_buf_size}
boot boot
terminal_output gfxterm ventoy_gui_console
} }
...@@ -527,9 +550,9 @@ function wim_common_menuentry { ...@@ -527,9 +550,9 @@ function wim_common_menuentry {
if [ "$grub_platform" = "pc" ]; then if [ "$grub_platform" = "pc" ]; then
linux16 $vtoy_path/ipxe.krn ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size} linux16 $vtoy_path/ipxe.krn ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}
else else
terminal_output console ventoy_cli_console
chainloader ${vtoy_path}/ventoy_x64.efi env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size} chainloader ${vtoy_path}/ventoy_x64.efi env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size}
terminal_output gfxterm ventoy_gui_console
fi fi
boot boot
else else
...@@ -545,10 +568,10 @@ function wim_unsupport_menuentry { ...@@ -545,10 +568,10 @@ function wim_unsupport_menuentry {
function efi_common_menuentry { function efi_common_menuentry {
vt_chosen_img_path chosen_path vt_chosen_img_path chosen_path
terminal_output console ventoy_cli_console
chainloader ${iso_path}${chosen_path} chainloader ${iso_path}${chosen_path}
boot boot
terminal_output gfxterm ventoy_gui_console
} }
function efi_unsupport_menuentry { function efi_unsupport_menuentry {
......
...@@ -327,22 +327,28 @@ else ...@@ -327,22 +327,28 @@ else
SHORT_PART2=${PART2#/dev/} SHORT_PART2=${PART2#/dev/}
part2_start=$(cat /sys/class/block/$SHORT_PART2/start) part2_start=$(cat /sys/class/block/$SHORT_PART2/start)
dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=440 PART1_TYPE=$(dd if=$DISK bs=1 count=1 skip=450 status=none | ./tool/hexdump -n1 -e '1/1 "%02X"')
PART1_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=446 status=none | ./tool/hexdump -n1 -e '1/1 "%02X"') if [ "$PART1_TYPE" = "EE" ]; then
PART2_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=462 status=none | ./tool/hexdump -n1 -e '1/1 "%02X"') vtdebug "This is GPT partition style ..."
./tool/xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34
echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none
else
vtdebug "This is MBR partition style ..."
dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=440
vtdebug "PART1_ACTIVE=$PART1_ACTIVE PART2_ACTIVE=$PART2_ACTIVE" PART1_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=446 status=none | ./tool/hexdump -n1 -e '1/1 "%02X"')
if [ "$PART1_ACTIVE" = "00" ] && [ "$PART2_ACTIVE" = "80" ]; then PART2_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=462 status=none | ./tool/hexdump -n1 -e '1/1 "%02X"')
vtdebug "change 1st partition active, 2nd partition inactive ..."
echo -en '\x80' | dd of=$DISK conv=fsync bs=1 count=1 seek=446 status=none vtdebug "PART1_ACTIVE=$PART1_ACTIVE PART2_ACTIVE=$PART2_ACTIVE"
echo -en '\x00' | dd of=$DISK conv=fsync bs=1 count=1 seek=462 status=none if [ "$PART1_ACTIVE" = "00" ] && [ "$PART2_ACTIVE" = "80" ]; then
vtdebug "change 1st partition active, 2nd partition inactive ..."
echo -en '\x80' | dd of=$DISK conv=fsync bs=1 count=1 seek=446 status=none
echo -en '\x00' | dd of=$DISK conv=fsync bs=1 count=1 seek=462 status=none
fi
./tool/xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1
fi fi
./tool/xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1
./tool/xzcat ./ventoy/ventoy.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$VENTOY_SECTOR_NUM seek=$part2_start ./tool/xzcat ./ventoy/ventoy.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$VENTOY_SECTOR_NUM seek=$part2_start
sync sync
......
...@@ -345,11 +345,19 @@ format_ventoy_disk_gpt() { ...@@ -345,11 +345,19 @@ format_ventoy_disk_gpt() {
unit s \ unit s \
mkpart Ventoy ntfs $part1_start_sector $part1_end_sector \ mkpart Ventoy ntfs $part1_start_sector $part1_end_sector \
mkpart VTOYEFI fat16 $part2_start_sector $part2_end_sector \ mkpart VTOYEFI fat16 $part2_start_sector $part2_end_sector \
set 2 boot on \ set 2 msftdata on \
set 2 esp on \
set 2 hidden on \ set 2 hidden on \
quit quit
sync
if ventoy_is_linux64; then
vtoygpt=./tool/vtoygpt_64
else
vtoygpt=./tool/vtoygpt_32
fi
$vtoygpt -f $DISK
sync sync
udevadm trigger >/dev/null 2>&1 udevadm trigger >/dev/null 2>&1
......
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
/****************************************************************************** /******************************************************************************
* PhyDrive.c * PhyDrive.c
* *
* Copyright (c) 2020, longpanda <admin@ventoy.net> * Copyright (c) 2020, longpanda <admin@ventoy.net>
* Copyright (c) 2011-2020, Pete Batard <pete@akeo.ie> * Copyright (c) 2011-2020, Pete Batard <pete@akeo.ie>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the * published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version. * License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include <Windows.h> #include <Windows.h>
#include <winternl.h> #include <winternl.h>
#include <commctrl.h> #include <commctrl.h>
#include <initguid.h> #include <initguid.h>
#include <vds.h> #include <vds.h>
#include "resource.h" #include "resource.h"
#include "Language.h" #include "Language.h"
#include "Ventoy2Disk.h" #include "Ventoy2Disk.h"
#include "fat_filelib.h" #include "fat_filelib.h"
#include "ff.h" #include "ff.h"
/* /*
* Some code and functions in the file are copied from rufus. * Some code and functions in the file are copied from rufus.
* https://github.com/pbatard/rufus * https://github.com/pbatard/rufus
*/ */
#define VDS_SET_ERROR SetLastError #define VDS_SET_ERROR SetLastError
#define IVdsServiceLoader_LoadService(This, pwszMachineName, ppService) (This)->lpVtbl->LoadService(This, pwszMachineName, ppService) #define IVdsServiceLoader_LoadService(This, pwszMachineName, ppService) (This)->lpVtbl->LoadService(This, pwszMachineName, ppService)
#define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This) #define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This)
#define IVdsService_QueryProviders(This, masks, ppEnum) (This)->lpVtbl->QueryProviders(This, masks, ppEnum) #define IVdsService_QueryProviders(This, masks, ppEnum) (This)->lpVtbl->QueryProviders(This, masks, ppEnum)
#define IVdsService_WaitForServiceReady(This) ((This)->lpVtbl->WaitForServiceReady(This)) #define IVdsService_WaitForServiceReady(This) ((This)->lpVtbl->WaitForServiceReady(This))
#define IVdsService_CleanupObsoleteMountPoints(This) ((This)->lpVtbl->CleanupObsoleteMountPoints(This)) #define IVdsService_CleanupObsoleteMountPoints(This) ((This)->lpVtbl->CleanupObsoleteMountPoints(This))
#define IVdsService_Refresh(This) ((This)->lpVtbl->Refresh(This)) #define IVdsService_Refresh(This) ((This)->lpVtbl->Refresh(This))
#define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This)) #define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This))
#define IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject) #define IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
#define IVdsProvider_Release(This) (This)->lpVtbl->Release(This) #define IVdsProvider_Release(This) (This)->lpVtbl->Release(This)
#define IVdsSwProvider_QueryPacks(This, ppEnum) (This)->lpVtbl->QueryPacks(This, ppEnum) #define IVdsSwProvider_QueryPacks(This, ppEnum) (This)->lpVtbl->QueryPacks(This, ppEnum)
#define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This) #define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This)
#define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum) #define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum)
#define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties) #define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties)
#define IVdsDisk_Release(This) (This)->lpVtbl->Release(This) #define IVdsDisk_Release(This) (This)->lpVtbl->Release(This)
#define IVdsDisk_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject) #define IVdsDisk_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
#define IVdsAdvancedDisk_QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions) (This)->lpVtbl->QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions) #define IVdsAdvancedDisk_QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions) (This)->lpVtbl->QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions)
#define IVdsAdvancedDisk_DeletePartition(This, ullOffset, bForce, bForceProtected) (This)->lpVtbl->DeletePartition(This, ullOffset, bForce, bForceProtected) #define IVdsAdvancedDisk_DeletePartition(This, ullOffset, bForce, bForceProtected) (This)->lpVtbl->DeletePartition(This, ullOffset, bForce, bForceProtected)
#define IVdsAdvancedDisk_Clean(This, bForce, bForceOEM, bFullClean, ppAsync) (This)->lpVtbl->Clean(This, bForce, bForceOEM, bFullClean, ppAsync) #define IVdsAdvancedDisk_Clean(This, bForce, bForceOEM, bFullClean, ppAsync) (This)->lpVtbl->Clean(This, bForce, bForceOEM, bFullClean, ppAsync)
#define IVdsAdvancedDisk_Release(This) (This)->lpVtbl->Release(This) #define IVdsAdvancedDisk_Release(This) (This)->lpVtbl->Release(This)
#define IEnumVdsObject_Next(This, celt, ppObjectArray, pcFetched) (This)->lpVtbl->Next(This, celt, ppObjectArray, pcFetched) #define IEnumVdsObject_Next(This, celt, ppObjectArray, pcFetched) (This)->lpVtbl->Next(This, celt, ppObjectArray, pcFetched)
#define IVdsPack_QueryVolumes(This, ppEnum) (This)->lpVtbl->QueryVolumes(This, ppEnum) #define IVdsPack_QueryVolumes(This, ppEnum) (This)->lpVtbl->QueryVolumes(This, ppEnum)
#define IVdsVolume_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject) #define IVdsVolume_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
#define IVdsVolume_Release(This) (This)->lpVtbl->Release(This) #define IVdsVolume_Release(This) (This)->lpVtbl->Release(This)
#define IVdsVolumeMF3_QueryVolumeGuidPathnames(This, pwszPathArray, pulNumberOfPaths) (This)->lpVtbl->QueryVolumeGuidPathnames(This,pwszPathArray,pulNumberOfPaths) #define IVdsVolumeMF3_QueryVolumeGuidPathnames(This, pwszPathArray, pulNumberOfPaths) (This)->lpVtbl->QueryVolumeGuidPathnames(This,pwszPathArray,pulNumberOfPaths)
#define IVdsVolumeMF3_FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync) (This)->lpVtbl->FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync) #define IVdsVolumeMF3_FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync) (This)->lpVtbl->FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync)
#define IVdsVolumeMF3_Release(This) (This)->lpVtbl->Release(This) #define IVdsVolumeMF3_Release(This) (This)->lpVtbl->Release(This)
#define IVdsVolume_GetProperties(This, pVolumeProperties) (This)->lpVtbl->GetProperties(This,pVolumeProperties) #define IVdsVolume_GetProperties(This, pVolumeProperties) (This)->lpVtbl->GetProperties(This,pVolumeProperties)
#define IVdsAsync_Cancel(This) (This)->lpVtbl->Cancel(This) #define IVdsAsync_Cancel(This) (This)->lpVtbl->Cancel(This)
#define IVdsAsync_QueryStatus(This,pHrResult,pulPercentCompleted) (This)->lpVtbl->QueryStatus(This,pHrResult,pulPercentCompleted) #define IVdsAsync_QueryStatus(This,pHrResult,pulPercentCompleted) (This)->lpVtbl->QueryStatus(This,pHrResult,pulPercentCompleted)
#define IVdsAsync_Wait(This,pHrResult,pAsyncOut) (This)->lpVtbl->Wait(This,pHrResult,pAsyncOut) #define IVdsAsync_Wait(This,pHrResult,pAsyncOut) (This)->lpVtbl->Wait(This,pHrResult,pAsyncOut)
#define IVdsAsync_Release(This) (This)->lpVtbl->Release(This) #define IVdsAsync_Release(This) (This)->lpVtbl->Release(This)
#define IUnknown_QueryInterface(This, a, b) (This)->lpVtbl->QueryInterface(This,a,b) #define IUnknown_QueryInterface(This, a, b) (This)->lpVtbl->QueryInterface(This,a,b)
#define IUnknown_Release(This) (This)->lpVtbl->Release(This) #define IUnknown_Release(This) (This)->lpVtbl->Release(This)
/* /*
* Delete all the partitions from a disk, using VDS * Delete all the partitions from a disk, using VDS
* Mostly copied from https://social.msdn.microsoft.com/Forums/vstudio/en-US/b90482ae-4e44-4b08-8731-81915030b32a/createpartition-using-vds-interface-throw-error-enointerface-dcom?forum=vcgeneral * Mostly copied from https://social.msdn.microsoft.com/Forums/vstudio/en-US/b90482ae-4e44-4b08-8731-81915030b32a/createpartition-using-vds-interface-throw-error-enointerface-dcom?forum=vcgeneral
*/ */
BOOL DeletePartitions(DWORD DriveIndex, BOOL OnlyPart2) BOOL DeletePartitions(DWORD DriveIndex, BOOL OnlyPart2)
{ {
BOOL r = FALSE; BOOL r = FALSE;
HRESULT hr; HRESULT hr;
ULONG ulFetched; ULONG ulFetched;
wchar_t wPhysicalName[48]; wchar_t wPhysicalName[48];
IVdsServiceLoader *pLoader; IVdsServiceLoader *pLoader;
IVdsService *pService; IVdsService *pService;
IEnumVdsObject *pEnum; IEnumVdsObject *pEnum;
IUnknown *pUnk; IUnknown *pUnk;
swprintf_s(wPhysicalName, ARRAYSIZE(wPhysicalName), L"\\\\?\\PhysicalDrive%lu", DriveIndex); swprintf_s(wPhysicalName, ARRAYSIZE(wPhysicalName), L"\\\\?\\PhysicalDrive%lu", DriveIndex);
// Initialize COM // Initialize COM
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL); RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
// Create a VDS Loader Instance // Create a VDS Loader Instance
hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
&IID_IVdsServiceLoader, (void **)&pLoader); &IID_IVdsServiceLoader, (void **)&pLoader);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not create VDS Loader Instance: %u", LASTERR); Log("Could not create VDS Loader Instance: %u", LASTERR);
goto out; goto out;
} }
// Load the VDS Service // Load the VDS Service
hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService); hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService);
IVdsServiceLoader_Release(pLoader); IVdsServiceLoader_Release(pLoader);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not load VDS Service: %u", LASTERR); Log("Could not load VDS Service: %u", LASTERR);
goto out; goto out;
} }
// Wait for the Service to become ready if needed // Wait for the Service to become ready if needed
hr = IVdsService_WaitForServiceReady(pService); hr = IVdsService_WaitForServiceReady(pService);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("VDS Service is not ready: %u", LASTERR); Log("VDS Service is not ready: %u", LASTERR);
goto out; goto out;
} }
// Query the VDS Service Providers // Query the VDS Service Providers
hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum); hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not query VDS Service Providers: %u", LASTERR); Log("Could not query VDS Service Providers: %u", LASTERR);
goto out; goto out;
} }
while (IEnumVdsObject_Next(pEnum, 1, &pUnk, &ulFetched) == S_OK) { while (IEnumVdsObject_Next(pEnum, 1, &pUnk, &ulFetched) == S_OK) {
IVdsProvider *pProvider; IVdsProvider *pProvider;
IVdsSwProvider *pSwProvider; IVdsSwProvider *pSwProvider;
IEnumVdsObject *pEnumPack; IEnumVdsObject *pEnumPack;
IUnknown *pPackUnk; IUnknown *pPackUnk;
// Get VDS Provider // Get VDS Provider
hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider); hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider);
IUnknown_Release(pUnk); IUnknown_Release(pUnk);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not get VDS Provider: %u", LASTERR); Log("Could not get VDS Provider: %u", LASTERR);
goto out; goto out;
} }
// Get VDS Software Provider // Get VDS Software Provider
hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider); hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider);
IVdsProvider_Release(pProvider); IVdsProvider_Release(pProvider);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not get VDS Software Provider: %u", LASTERR); Log("Could not get VDS Software Provider: %u", LASTERR);
goto out; goto out;
} }
// Get VDS Software Provider Packs // Get VDS Software Provider Packs
hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack); hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack);
IVdsSwProvider_Release(pSwProvider); IVdsSwProvider_Release(pSwProvider);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not get VDS Software Provider Packs: %u", LASTERR); Log("Could not get VDS Software Provider Packs: %u", LASTERR);
goto out; goto out;
} }
// Enumerate Provider Packs // Enumerate Provider Packs
while (IEnumVdsObject_Next(pEnumPack, 1, &pPackUnk, &ulFetched) == S_OK) { while (IEnumVdsObject_Next(pEnumPack, 1, &pPackUnk, &ulFetched) == S_OK) {
IVdsPack *pPack; IVdsPack *pPack;
IEnumVdsObject *pEnumDisk; IEnumVdsObject *pEnumDisk;
IUnknown *pDiskUnk; IUnknown *pDiskUnk;
hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack); hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack);
IUnknown_Release(pPackUnk); IUnknown_Release(pPackUnk);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not query VDS Software Provider Pack: %u", LASTERR); Log("Could not query VDS Software Provider Pack: %u", LASTERR);
goto out; goto out;
} }
// Use the pack interface to access the disks // Use the pack interface to access the disks
hr = IVdsPack_QueryDisks(pPack, &pEnumDisk); hr = IVdsPack_QueryDisks(pPack, &pEnumDisk);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not query VDS disks: %u", LASTERR); Log("Could not query VDS disks: %u", LASTERR);
goto out; goto out;
} }
// List disks // List disks
while (IEnumVdsObject_Next(pEnumDisk, 1, &pDiskUnk, &ulFetched) == S_OK) { while (IEnumVdsObject_Next(pEnumDisk, 1, &pDiskUnk, &ulFetched) == S_OK) {
VDS_DISK_PROP diskprop; VDS_DISK_PROP diskprop;
VDS_PARTITION_PROP* prop_array; VDS_PARTITION_PROP* prop_array;
LONG i, prop_array_size; LONG i, prop_array_size;
IVdsDisk *pDisk; IVdsDisk *pDisk;
IVdsAdvancedDisk *pAdvancedDisk; IVdsAdvancedDisk *pAdvancedDisk;
// Get the disk interface. // Get the disk interface.
hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk); hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not query VDS Disk Interface: %u", LASTERR); Log("Could not query VDS Disk Interface: %u", LASTERR);
goto out; goto out;
} }
// Get the disk properties // Get the disk properties
hr = IVdsDisk_GetProperties(pDisk, &diskprop); hr = IVdsDisk_GetProperties(pDisk, &diskprop);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not query VDS Disk Properties: %u", LASTERR); Log("Could not query VDS Disk Properties: %u", LASTERR);
goto out; goto out;
} }
// Isolate the disk we want // Isolate the disk we want
if (_wcsicmp(wPhysicalName, diskprop.pwszName) != 0) { if (_wcsicmp(wPhysicalName, diskprop.pwszName) != 0) {
IVdsDisk_Release(pDisk); IVdsDisk_Release(pDisk);
continue; continue;
} }
// Instantiate the AdvanceDisk interface for our disk. // Instantiate the AdvanceDisk interface for our disk.
hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk); hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk);
IVdsDisk_Release(pDisk); IVdsDisk_Release(pDisk);
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not access VDS Advanced Disk interface: %u", LASTERR); Log("Could not access VDS Advanced Disk interface: %u", LASTERR);
goto out; goto out;
} }
// Query the partition data, so we can get the start offset, which we need for deletion // Query the partition data, so we can get the start offset, which we need for deletion
hr = IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk, &prop_array, &prop_array_size); hr = IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk, &prop_array, &prop_array_size);
if (hr == S_OK) { if (hr == S_OK) {
Log("Deleting ALL partition(s) from disk '%S':", diskprop.pwszName); Log("Deleting ALL partition(s) from disk '%S':", diskprop.pwszName);
// Now go through each partition // Now go through each partition
for (i = 0; i < prop_array_size; i++) { for (i = 0; i < prop_array_size; i++) {
Log("* Partition %d (offset: %lld, size: %llu)", prop_array[i].ulPartitionNumber, Log("* Partition %d (offset: %lld, size: %llu)", prop_array[i].ulPartitionNumber,
prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize); prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize);
if (OnlyPart2 && prop_array[i].ullOffset == 2048*512) if (OnlyPart2 && prop_array[i].ullOffset == 2048*512)
{ {
Log("Skip this partition..."); Log("Skip this partition...");
continue; continue;
} }
hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE); hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE);
if (hr != S_OK) { if (hr != S_OK) {
r = FALSE; r = FALSE;
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not delete partitions: %u", LASTERR); Log("Could not delete partitions: %u", LASTERR);
} }
} }
r = TRUE; r = TRUE;
} }
else { else {
Log("No partition to delete on disk '%S'", diskprop.pwszName); Log("No partition to delete on disk '%S'", diskprop.pwszName);
r = TRUE; r = TRUE;
} }
CoTaskMemFree(prop_array); CoTaskMemFree(prop_array);
#if 0 #if 0
// Issue a Clean while we're at it // Issue a Clean while we're at it
HRESULT hr2 = E_FAIL; HRESULT hr2 = E_FAIL;
ULONG completed; ULONG completed;
IVdsAsync* pAsync; IVdsAsync* pAsync;
hr = IVdsAdvancedDisk_Clean(pAdvancedDisk, TRUE, FALSE, FALSE, &pAsync); hr = IVdsAdvancedDisk_Clean(pAdvancedDisk, TRUE, FALSE, FALSE, &pAsync);
while (SUCCEEDED(hr)) { while (SUCCEEDED(hr)) {
if (IS_ERROR(FormatStatus)) { if (IS_ERROR(FormatStatus)) {
IVdsAsync_Cancel(pAsync); IVdsAsync_Cancel(pAsync);
break; break;
} }
hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed); hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
hr = hr2; hr = hr2;
if (hr == S_OK) if (hr == S_OK)
break; break;
if (hr == VDS_E_OPERATION_PENDING) if (hr == VDS_E_OPERATION_PENDING)
hr = S_OK; hr = S_OK;
} }
Sleep(500); Sleep(500);
} }
if (hr != S_OK) { if (hr != S_OK) {
VDS_SET_ERROR(hr); VDS_SET_ERROR(hr);
Log("Could not clean disk: %s", LASTERR); Log("Could not clean disk: %s", LASTERR);
} }
#endif #endif
IVdsAdvancedDisk_Release(pAdvancedDisk); IVdsAdvancedDisk_Release(pAdvancedDisk);
goto out; goto out;
} }
} }
} }
out: out:
return r; return r;
} }
static DWORD GetVentoyVolumeName(int PhyDrive, UINT32 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash) static DWORD GetVentoyVolumeName(int PhyDrive, UINT32 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash)
{ {
size_t len; size_t len;
BOOL bRet; BOOL bRet;
DWORD dwSize; DWORD dwSize;
HANDLE hDrive; HANDLE hDrive;
HANDLE hVolume; HANDLE hVolume;
UINT64 PartOffset; UINT64 PartOffset;
DWORD Status = ERROR_NOT_FOUND; DWORD Status = ERROR_NOT_FOUND;
DISK_EXTENT *pExtents = NULL; DISK_EXTENT *pExtents = NULL;
CHAR VolumeName[MAX_PATH] = { 0 }; CHAR VolumeName[MAX_PATH] = { 0 };
VOLUME_DISK_EXTENTS DiskExtents; VOLUME_DISK_EXTENTS DiskExtents;
PartOffset = 512ULL * StartSectorId; PartOffset = 512ULL * StartSectorId;
Log("GetVentoyVolumeName PhyDrive %d SectorStart:%u PartOffset:%llu", PhyDrive, StartSectorId, (ULONGLONG)PartOffset); Log("GetVentoyVolumeName PhyDrive %d SectorStart:%u PartOffset:%llu", PhyDrive, StartSectorId, (ULONGLONG)PartOffset);
hVolume = FindFirstVolumeA(VolumeName, sizeof(VolumeName)); hVolume = FindFirstVolumeA(VolumeName, sizeof(VolumeName));
if (hVolume == INVALID_HANDLE_VALUE) if (hVolume == INVALID_HANDLE_VALUE)
{ {
return 1; return 1;
} }
do { do {
len = strlen(VolumeName); len = strlen(VolumeName);
Log("Find volume:%s", VolumeName); Log("Find volume:%s", VolumeName);
VolumeName[len - 1] = 0; VolumeName[len - 1] = 0;
hDrive = CreateFileA(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); hDrive = CreateFileA(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDrive == INVALID_HANDLE_VALUE) if (hDrive == INVALID_HANDLE_VALUE)
{ {
continue; continue;
} }
bRet = DeviceIoControl(hDrive, bRet = DeviceIoControl(hDrive,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL, NULL,
0, 0,
&DiskExtents, &DiskExtents,
(DWORD)(sizeof(DiskExtents)), (DWORD)(sizeof(DiskExtents)),
(LPDWORD)&dwSize, (LPDWORD)&dwSize,
NULL); NULL);
Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet, LASTERR); Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet, LASTERR);
Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents.NumberOfDiskExtents, DiskExtents.Extents[0].DiskNumber); Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents.NumberOfDiskExtents, DiskExtents.Extents[0].DiskNumber);
if (bRet && DiskExtents.NumberOfDiskExtents == 1) if (bRet && DiskExtents.NumberOfDiskExtents == 1)
{ {
pExtents = DiskExtents.Extents; pExtents = DiskExtents.Extents;
Log("This volume DiskNumber:%u offset:%llu", pExtents->DiskNumber, (ULONGLONG)pExtents->StartingOffset.QuadPart); Log("This volume DiskNumber:%u offset:%llu", pExtents->DiskNumber, (ULONGLONG)pExtents->StartingOffset.QuadPart);
if ((int)pExtents->DiskNumber == PhyDrive && pExtents->StartingOffset.QuadPart == PartOffset) if ((int)pExtents->DiskNumber == PhyDrive && pExtents->StartingOffset.QuadPart == PartOffset)
{ {
Log("This volume match"); Log("This volume match");
if (!DelSlash) if (!DelSlash)
{ {
VolumeName[len - 1] = '\\'; VolumeName[len - 1] = '\\';
} }
sprintf_s(NameBuf, BufLen, "%s", VolumeName); sprintf_s(NameBuf, BufLen, "%s", VolumeName);
Status = ERROR_SUCCESS; Status = ERROR_SUCCESS;
CloseHandle(hDrive); CloseHandle(hDrive);
break; break;
} }
} }
CloseHandle(hDrive); CloseHandle(hDrive);
} while (FindNextVolumeA(hVolume, VolumeName, sizeof(VolumeName))); } while (FindNextVolumeA(hVolume, VolumeName, sizeof(VolumeName)));
FindVolumeClose(hVolume); FindVolumeClose(hVolume);
Log("GetVentoyVolumeName return %u", Status); Log("GetVentoyVolumeName return %u", Status);
return Status; return Status;
} }
static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length) static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length)
{ {
int n = 0; int n = 0;
DWORD DataSize = 0; DWORD DataSize = 0;
CHAR *Pos = NULL; CHAR *Pos = NULL;
CHAR *StringBuf = NULL; CHAR *StringBuf = NULL;
DataSize = GetLogicalDriveStringsA(0, NULL); DataSize = GetLogicalDriveStringsA(0, NULL);
StringBuf = (CHAR *)malloc(DataSize + 1); StringBuf = (CHAR *)malloc(DataSize + 1);
if (StringBuf == NULL) if (StringBuf == NULL)
{ {
return 1; return 1;
} }
GetLogicalDriveStringsA(DataSize, StringBuf); GetLogicalDriveStringsA(DataSize, StringBuf);
for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1) for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1)
{ {
if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0])) if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0]))
{ {
Log("%C: is belong to phydrive%d", Pos[0], PhyDrive); Log("%C: is belong to phydrive%d", Pos[0], PhyDrive);
DriveLetters[n++] = Pos[0]; DriveLetters[n++] = Pos[0];
} }
} }
free(StringBuf); free(StringBuf);
return 0; return 0;
} }
static HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare) static HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare)
{ {
int i; int i;
DWORD dwSize; DWORD dwSize;
DWORD LastError; DWORD LastError;
UINT64 EndTime; UINT64 EndTime;
HANDLE hDrive = INVALID_HANDLE_VALUE; HANDLE hDrive = INVALID_HANDLE_VALUE;
CHAR PhyDrive[128]; CHAR PhyDrive[128];
CHAR DevPath[MAX_PATH] = { 0 }; CHAR DevPath[MAX_PATH] = { 0 };
safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", Drive); safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", Drive);
if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath))) if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath)))
{ {
Log("QueryDosDeviceA failed error:%u", GetLastError()); Log("QueryDosDeviceA failed error:%u", GetLastError());
strcpy_s(DevPath, sizeof(DevPath), "???"); strcpy_s(DevPath, sizeof(DevPath), "???");
} }
else else
{ {
Log("QueryDosDeviceA success %s", DevPath); Log("QueryDosDeviceA success %s", DevPath);
} }
for (i = 0; i < DRIVE_ACCESS_RETRIES; i++) for (i = 0; i < DRIVE_ACCESS_RETRIES; i++)
{ {
// Try without FILE_SHARE_WRITE (unless specifically requested) so that // Try without FILE_SHARE_WRITE (unless specifically requested) so that
// we won't be bothered by the OS or other apps when we set up our data. // we won't be bothered by the OS or other apps when we set up our data.
// However this means we might have to wait for an access gap... // However this means we might have to wait for an access gap...
// We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is // We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is
// required for enumeration. // required for enumeration.
hDrive = CreateFileA(PhyDrive, hDrive = CreateFileA(PhyDrive,
GENERIC_READ | (bWriteAccess ? GENERIC_WRITE : 0), GENERIC_READ | (bWriteAccess ? GENERIC_WRITE : 0),
FILE_SHARE_READ | (bWriteShare ? FILE_SHARE_WRITE : 0), FILE_SHARE_READ | (bWriteShare ? FILE_SHARE_WRITE : 0),
NULL, NULL,
OPEN_EXISTING, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
NULL); NULL);
LastError = GetLastError(); LastError = GetLastError();
Log("[%d] CreateFileA %s code:%u %p", i, PhyDrive, LastError, hDrive); Log("[%d] CreateFileA %s code:%u %p", i, PhyDrive, LastError, hDrive);
if (hDrive != INVALID_HANDLE_VALUE) if (hDrive != INVALID_HANDLE_VALUE)
{ {
break; break;
} }
if ((LastError != ERROR_SHARING_VIOLATION) && (LastError != ERROR_ACCESS_DENIED)) if ((LastError != ERROR_SHARING_VIOLATION) && (LastError != ERROR_ACCESS_DENIED))
{ {
break; break;
} }
if (i == 0) if (i == 0)
{ {
Log("Waiting for access on %s [%s]...", PhyDrive, DevPath); Log("Waiting for access on %s [%s]...", PhyDrive, DevPath);
} }
else if (!bWriteShare && (i > DRIVE_ACCESS_RETRIES / 3)) else if (!bWriteShare && (i > DRIVE_ACCESS_RETRIES / 3))
{ {
// If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE... // If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE...
Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled..."); Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");
bWriteShare = TRUE; bWriteShare = TRUE;
// Try to report the process that is locking the drive // Try to report the process that is locking the drive
// We also use bit 6 as a flag to indicate that SearchProcess was called. // We also use bit 6 as a flag to indicate that SearchProcess was called.
//access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40; //access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40;
} }
Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES); Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
} }
if (hDrive == INVALID_HANDLE_VALUE) if (hDrive == INVALID_HANDLE_VALUE)
{ {
Log("Could not open %s %u", PhyDrive, LASTERR); Log("Could not open %s %u", PhyDrive, LASTERR);
goto End; goto End;
} }
if (bWriteAccess) if (bWriteAccess)
{ {
Log("Opened %s for %s write access", PhyDrive, bWriteShare ? "shared" : "exclusive"); Log("Opened %s for %s write access", PhyDrive, bWriteShare ? "shared" : "exclusive");
} }
if (bLockDrive) if (bLockDrive)
{ {
if (DeviceIoControl(hDrive, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwSize, NULL)) if (DeviceIoControl(hDrive, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwSize, NULL))
{ {
Log("I/O boundary checks disabled"); Log("I/O boundary checks disabled");
} }
EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT; EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT;
do { do {
if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL)) if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL))
{ {
Log("FSCTL_LOCK_VOLUME success"); Log("FSCTL_LOCK_VOLUME success");
goto End; goto End;
} }
Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES); Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
} while (GetTickCount64() < EndTime); } while (GetTickCount64() < EndTime);
// If we reached this section, either we didn't manage to get a lock or the user cancelled // If we reached this section, either we didn't manage to get a lock or the user cancelled
Log("Could not lock access to %s %u", PhyDrive, LASTERR); Log("Could not lock access to %s %u", PhyDrive, LASTERR);
// See if we can report the processes are accessing the drive // See if we can report the processes are accessing the drive
//if (!IS_ERROR(FormatStatus) && (access_mask == 0)) //if (!IS_ERROR(FormatStatus) && (access_mask == 0))
// access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE); // access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE);
// Try to continue if the only access rights we saw were for read-only // Try to continue if the only access rights we saw were for read-only
//if ((access_mask & 0x07) != 0x01) //if ((access_mask & 0x07) != 0x01)
// safe_closehandle(hDrive); // safe_closehandle(hDrive);
CHECK_CLOSE_HANDLE(hDrive); CHECK_CLOSE_HANDLE(hDrive);
} }
End: End:
if (hDrive == INVALID_HANDLE_VALUE) if (hDrive == INVALID_HANDLE_VALUE)
{ {
Log("Can get handle of %s, maybe some process control it.", DevPath); Log("Can get handle of %s, maybe some process control it.", DevPath);
} }
return hDrive; return hDrive;
} }
int GetPhyDriveByLogicalDrive(int DriveLetter) int GetPhyDriveByLogicalDrive(int DriveLetter)
{ {
BOOL Ret; BOOL Ret;
DWORD dwSize; DWORD dwSize;
HANDLE Handle; HANDLE Handle;
VOLUME_DISK_EXTENTS DiskExtents; VOLUME_DISK_EXTENTS DiskExtents;
CHAR PhyPath[128]; CHAR PhyPath[128];
safe_sprintf(PhyPath, "\\\\.\\%C:", (CHAR)DriveLetter); safe_sprintf(PhyPath, "\\\\.\\%C:", (CHAR)DriveLetter);
Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if (Handle == INVALID_HANDLE_VALUE) if (Handle == INVALID_HANDLE_VALUE)
{ {
Log("Could not open the disk<%s>, error:%u", PhyPath, LASTERR); Log("Could not open the disk<%s>, error:%u", PhyPath, LASTERR);
return -1; return -1;
} }
Ret = DeviceIoControl(Handle, Ret = DeviceIoControl(Handle,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL, NULL,
0, 0,
&DiskExtents, &DiskExtents,
(DWORD)(sizeof(DiskExtents)), (DWORD)(sizeof(DiskExtents)),
(LPDWORD)&dwSize, (LPDWORD)&dwSize,
NULL); NULL);
if (!Ret || DiskExtents.NumberOfDiskExtents == 0) if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
{ {
Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, LASTERR); Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, LASTERR);
CHECK_CLOSE_HANDLE(Handle); CHECK_CLOSE_HANDLE(Handle);
return -1; return -1;
} }
CHECK_CLOSE_HANDLE(Handle); CHECK_CLOSE_HANDLE(Handle);
Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu", Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
PhyPath, PhyPath,
DiskExtents.Extents[0].DiskNumber, DiskExtents.Extents[0].DiskNumber,
DiskExtents.Extents[0].StartingOffset.QuadPart, DiskExtents.Extents[0].StartingOffset.QuadPart,
DiskExtents.Extents[0].ExtentLength.QuadPart DiskExtents.Extents[0].ExtentLength.QuadPart
); );
return (int)DiskExtents.Extents[0].DiskNumber; return (int)DiskExtents.Extents[0].DiskNumber;
} }
int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount) int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)
{ {
int i; int i;
int Count; int Count;
int id; int id;
int Letter = 'A'; int Letter = 'A';
BOOL bRet; BOOL bRet;
DWORD dwBytes; DWORD dwBytes;
DWORD DriveCount = 0; DWORD DriveCount = 0;
HANDLE Handle = INVALID_HANDLE_VALUE; HANDLE Handle = INVALID_HANDLE_VALUE;
CHAR PhyDrive[128]; CHAR PhyDrive[128];
PHY_DRIVE_INFO *CurDrive = pDriveList; PHY_DRIVE_INFO *CurDrive = pDriveList;
GET_LENGTH_INFORMATION LengthInfo; GET_LENGTH_INFORMATION LengthInfo;
STORAGE_PROPERTY_QUERY Query; STORAGE_PROPERTY_QUERY Query;
STORAGE_DESCRIPTOR_HEADER DevDescHeader; STORAGE_DESCRIPTOR_HEADER DevDescHeader;
STORAGE_DEVICE_DESCRIPTOR *pDevDesc; STORAGE_DEVICE_DESCRIPTOR *pDevDesc;
int PhyDriveId[VENTOY_MAX_PHY_DRIVE]; int PhyDriveId[VENTOY_MAX_PHY_DRIVE];
Count = GetPhysicalDriveCount(); Count = GetPhysicalDriveCount();
for (i = 0; i < Count && i < VENTOY_MAX_PHY_DRIVE; i++) for (i = 0; i < Count && i < VENTOY_MAX_PHY_DRIVE; i++)
{ {
PhyDriveId[i] = i; PhyDriveId[i] = i;
} }
dwBytes = GetLogicalDrives(); dwBytes = GetLogicalDrives();
Log("Logical Drives: 0x%x", dwBytes); Log("Logical Drives: 0x%x", dwBytes);
while (dwBytes) while (dwBytes)
{ {
if (dwBytes & 0x01) if (dwBytes & 0x01)
{ {
id = GetPhyDriveByLogicalDrive(Letter); id = GetPhyDriveByLogicalDrive(Letter);
Log("%C --> %d", Letter, id); Log("%C --> %d", Letter, id);
if (id >= 0) if (id >= 0)
{ {
for (i = 0; i < Count; i++) for (i = 0; i < Count; i++)
{ {
if (PhyDriveId[i] == id) if (PhyDriveId[i] == id)
{ {
break; break;
} }
} }
if (i >= Count) if (i >= Count)
{ {
Log("Add phy%d to list", i); Log("Add phy%d to list", i);
PhyDriveId[Count] = id; PhyDriveId[Count] = id;
Count++; Count++;
} }
} }
} }
Letter++; Letter++;
dwBytes >>= 1; dwBytes >>= 1;
} }
for (i = 0; i < Count && DriveCount < VENTOY_MAX_PHY_DRIVE; i++) for (i = 0; i < Count && DriveCount < VENTOY_MAX_PHY_DRIVE; i++)
{ {
CHECK_CLOSE_HANDLE(Handle); CHECK_CLOSE_HANDLE(Handle);
safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", PhyDriveId[i]); safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", PhyDriveId[i]);
Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR); Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR);
if (Handle == INVALID_HANDLE_VALUE) if (Handle == INVALID_HANDLE_VALUE)
{ {
continue; continue;
} }
bRet = DeviceIoControl(Handle, bRet = DeviceIoControl(Handle,
IOCTL_DISK_GET_LENGTH_INFO, NULL, IOCTL_DISK_GET_LENGTH_INFO, NULL,
0, 0,
&LengthInfo, &LengthInfo,
sizeof(LengthInfo), sizeof(LengthInfo),
&dwBytes, &dwBytes,
NULL); NULL);
if (!bRet) if (!bRet)
{ {
Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR); Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR);
continue; continue;
} }
Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart); Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart);
Query.PropertyId = StorageDeviceProperty; Query.PropertyId = StorageDeviceProperty;
Query.QueryType = PropertyStandardQuery; Query.QueryType = PropertyStandardQuery;
bRet = DeviceIoControl(Handle, bRet = DeviceIoControl(Handle,
IOCTL_STORAGE_QUERY_PROPERTY, IOCTL_STORAGE_QUERY_PROPERTY,
&Query, &Query,
sizeof(Query), sizeof(Query),
&DevDescHeader, &DevDescHeader,
sizeof(STORAGE_DESCRIPTOR_HEADER), sizeof(STORAGE_DESCRIPTOR_HEADER),
&dwBytes, &dwBytes,
NULL); NULL);
if (!bRet) if (!bRet)
{ {
Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes); Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes);
continue; continue;
} }
if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR)) if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))
{ {
Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size); Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size);
continue; continue;
} }
pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size); pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size);
if (!pDevDesc) if (!pDevDesc)
{ {
Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size); Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size);
continue; continue;
} }
bRet = DeviceIoControl(Handle, bRet = DeviceIoControl(Handle,
IOCTL_STORAGE_QUERY_PROPERTY, IOCTL_STORAGE_QUERY_PROPERTY,
&Query, &Query,
sizeof(Query), sizeof(Query),
pDevDesc, pDevDesc,
DevDescHeader.Size, DevDescHeader.Size,
&dwBytes, &dwBytes,
NULL); NULL);
if (!bRet) if (!bRet)
{ {
Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes); Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes);
free(pDevDesc); free(pDevDesc);
continue; continue;
} }
CurDrive->PhyDrive = i; CurDrive->PhyDrive = i;
CurDrive->SizeInBytes = LengthInfo.Length.QuadPart; CurDrive->SizeInBytes = LengthInfo.Length.QuadPart;
CurDrive->DeviceType = pDevDesc->DeviceType; CurDrive->DeviceType = pDevDesc->DeviceType;
CurDrive->RemovableMedia = pDevDesc->RemovableMedia; CurDrive->RemovableMedia = pDevDesc->RemovableMedia;
CurDrive->BusType = pDevDesc->BusType; CurDrive->BusType = pDevDesc->BusType;
if (pDevDesc->VendorIdOffset) if (pDevDesc->VendorIdOffset)
{ {
safe_strcpy(CurDrive->VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset); safe_strcpy(CurDrive->VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset);
TrimString(CurDrive->VendorId); TrimString(CurDrive->VendorId);
} }
if (pDevDesc->ProductIdOffset) if (pDevDesc->ProductIdOffset)
{ {
safe_strcpy(CurDrive->ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset); safe_strcpy(CurDrive->ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset);
TrimString(CurDrive->ProductId); TrimString(CurDrive->ProductId);
} }
if (pDevDesc->ProductRevisionOffset) if (pDevDesc->ProductRevisionOffset)
{ {
safe_strcpy(CurDrive->ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset); safe_strcpy(CurDrive->ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset);
TrimString(CurDrive->ProductRev); TrimString(CurDrive->ProductRev);
} }
if (pDevDesc->SerialNumberOffset) if (pDevDesc->SerialNumberOffset)
{ {
safe_strcpy(CurDrive->SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset); safe_strcpy(CurDrive->SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset);
TrimString(CurDrive->SerialNumber); TrimString(CurDrive->SerialNumber);
} }
CurDrive++; CurDrive++;
DriveCount++; DriveCount++;
free(pDevDesc); free(pDevDesc);
CHECK_CLOSE_HANDLE(Handle); CHECK_CLOSE_HANDLE(Handle);
} }
for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++) for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++)
{ {
Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s", Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
CurDrive->PhyDrive, GetBusTypeString(CurDrive->BusType), CurDrive->RemovableMedia, CurDrive->PhyDrive, GetBusTypeString(CurDrive->BusType), CurDrive->RemovableMedia,
GetHumanReadableGBSize(CurDrive->SizeInBytes), CurDrive->SizeInBytes, GetHumanReadableGBSize(CurDrive->SizeInBytes), CurDrive->SizeInBytes,
CurDrive->VendorId, CurDrive->ProductId); CurDrive->VendorId, CurDrive->ProductId);
} }
*pDriveCount = DriveCount; *pDriveCount = DriveCount;
return 0; return 0;
} }
static HANDLE g_FatPhyDrive; static HANDLE g_FatPhyDrive;
static UINT64 g_Part2StartSec; static UINT64 g_Part2StartSec;
static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen) static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen)
{ {
int rc = 1; int rc = 1;
int size = 0; int size = 0;
char *buf = NULL; char *buf = NULL;
void *flfile = NULL; void *flfile = NULL;
flfile = fl_fopen("/grub/grub.cfg", "rb"); flfile = fl_fopen("/grub/grub.cfg", "rb");
if (flfile) if (flfile)
{ {
fl_fseek(flfile, 0, SEEK_END); fl_fseek(flfile, 0, SEEK_END);
size = (int)fl_ftell(flfile); size = (int)fl_ftell(flfile);
fl_fseek(flfile, 0, SEEK_SET); fl_fseek(flfile, 0, SEEK_SET);
buf = (char *)malloc(size + 1); buf = (char *)malloc(size + 1);
if (buf) if (buf)
{ {
fl_fread(buf, 1, size, flfile); fl_fread(buf, 1, size, flfile);
buf[size] = 0; buf[size] = 0;
rc = 0; rc = 0;
sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf)); sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf));
free(buf); free(buf);
} }
fl_fclose(flfile); fl_fclose(flfile);
} }
return rc; return rc;
} }
static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount) static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
{ {
DWORD dwSize; DWORD dwSize;
BOOL bRet; BOOL bRet;
DWORD ReadSize; DWORD ReadSize;
LARGE_INTEGER liCurrentPosition; LARGE_INTEGER liCurrentPosition;
liCurrentPosition.QuadPart = Sector + g_Part2StartSec; liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
liCurrentPosition.QuadPart *= 512; liCurrentPosition.QuadPart *= 512;
SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN); SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
ReadSize = (DWORD)(SectorCount * 512); ReadSize = (DWORD)(SectorCount * 512);
bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL); bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
if (bRet == FALSE || dwSize != ReadSize) if (bRet == FALSE || dwSize != ReadSize)
{ {
Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, LASTERR); Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, LASTERR);
} }
return 1; return 1;
} }
int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen) int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen)
{ {
int rc = 0; int rc = 0;
HANDLE hDrive; HANDLE hDrive;
hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE); hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE);
if (hDrive == INVALID_HANDLE_VALUE) if (hDrive == INVALID_HANDLE_VALUE)
{ {
return 1; return 1;
} }
g_FatPhyDrive = hDrive; g_FatPhyDrive = hDrive;
g_Part2StartSec = Part2StartSector; g_Part2StartSec = Part2StartSector;
Log("Parse FAT fs..."); Log("Parse FAT fs...");
fl_init(); fl_init();
if (0 == fl_attach_media(VentoyFatDiskRead, NULL)) if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
{ {
rc = GetVentoyVersionFromFatFile(VerBuf, BufLen); rc = GetVentoyVersionFromFatFile(VerBuf, BufLen);
} }
else else
{ {
rc = 1; rc = 1;
} }
fl_shutdown(); fl_shutdown();
CHECK_CLOSE_HANDLE(hDrive); CHECK_CLOSE_HANDLE(hDrive);
return rc; return rc;
} }
static unsigned int g_disk_unxz_len = 0; static unsigned int g_disk_unxz_len = 0;
static BYTE *g_part_img_pos = NULL; static BYTE *g_part_img_pos = NULL;
static BYTE *g_part_img_buf[VENTOY_EFI_PART_SIZE / SIZE_1MB]; static BYTE *g_part_img_buf[VENTOY_EFI_PART_SIZE / SIZE_1MB];
static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount) static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
{ {
uint32 i; uint32 i;
uint32 offset; uint32 offset;
BYTE *MbBuf = NULL; BYTE *MbBuf = NULL;
for (i = 0; i < SectorCount; i++) for (i = 0; i < SectorCount; i++)
{ {
offset = (Sector + i) * 512; offset = (Sector + i) * 512;
if (g_part_img_buf[1] == NULL) if (g_part_img_buf[1] == NULL)
{ {
MbBuf = g_part_img_buf[0] + offset; MbBuf = g_part_img_buf[0] + offset;
memcpy(Buffer + i * 512, MbBuf, 512); memcpy(Buffer + i * 512, MbBuf, 512);
} }
else else
{ {
MbBuf = g_part_img_buf[offset / SIZE_1MB]; MbBuf = g_part_img_buf[offset / SIZE_1MB];
memcpy(Buffer + i * 512, MbBuf + (offset % SIZE_1MB), 512); memcpy(Buffer + i * 512, MbBuf + (offset % SIZE_1MB), 512);
} }
} }
return 1; return 1;
} }
static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount) static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
{ {
uint32 i; uint32 i;
uint32 offset; uint32 offset;
BYTE *MbBuf = NULL; BYTE *MbBuf = NULL;
for (i = 0; i < SectorCount; i++) for (i = 0; i < SectorCount; i++)
{ {
offset = (Sector + i) * 512; offset = (Sector + i) * 512;
if (g_part_img_buf[1] == NULL) if (g_part_img_buf[1] == NULL)
{ {
MbBuf = g_part_img_buf[0] + offset; MbBuf = g_part_img_buf[0] + offset;
memcpy(MbBuf, Buffer + i * 512, 512); memcpy(MbBuf, Buffer + i * 512, 512);
} }
else else
{ {
MbBuf = g_part_img_buf[offset / SIZE_1MB]; MbBuf = g_part_img_buf[offset / SIZE_1MB];
memcpy(MbBuf + (offset % SIZE_1MB), Buffer + i * 512, 512); memcpy(MbBuf + (offset % SIZE_1MB), Buffer + i * 512, 512);
} }
} }
return 1; return 1;
} }
int VentoyProcSecureBoot(BOOL SecureBoot) int VentoyProcSecureBoot(BOOL SecureBoot)
{ {
int rc = 0; int rc = 0;
int size; int size;
char *filebuf = NULL; char *filebuf = NULL;
void *file = NULL; void *file = NULL;
Log("VentoyProcSecureBoot %d ...", SecureBoot); Log("VentoyProcSecureBoot %d ...", SecureBoot);
if (SecureBoot) if (SecureBoot)
{ {
Log("Secure boot is enabled ..."); Log("Secure boot is enabled ...");
return 0; return 0;
} }
fl_init(); fl_init();
if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite)) if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite))
{ {
file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb"); file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
Log("Open ventoy efi file %p ", file); Log("Open ventoy efi file %p ", file);
if (file) if (file)
{ {
fl_fseek(file, 0, SEEK_END); fl_fseek(file, 0, SEEK_END);
size = (int)fl_ftell(file); size = (int)fl_ftell(file);
fl_fseek(file, 0, SEEK_SET); fl_fseek(file, 0, SEEK_SET);
Log("ventoy efi file size %d ...", size); Log("ventoy efi file size %d ...", size);
filebuf = (char *)malloc(size); filebuf = (char *)malloc(size);
if (filebuf) if (filebuf)
{ {
fl_fread(filebuf, 1, size, file); fl_fread(filebuf, 1, size, file);
} }
fl_fclose(file); fl_fclose(file);
Log("Now delete all efi files ..."); Log("Now delete all efi files ...");
fl_remove("/EFI/BOOT/BOOTX64.EFI"); fl_remove("/EFI/BOOT/BOOTX64.EFI");
fl_remove("/EFI/BOOT/grubx64.efi"); fl_remove("/EFI/BOOT/grubx64.efi");
fl_remove("/EFI/BOOT/grubx64_real.efi"); fl_remove("/EFI/BOOT/grubx64_real.efi");
fl_remove("/EFI/BOOT/MokManager.efi"); fl_remove("/EFI/BOOT/MokManager.efi");
fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
Log("Open bootx64 efi file %p ", file); file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
if (file) Log("Open bootx64 efi file %p ", file);
{ if (file)
if (filebuf) {
{ if (filebuf)
fl_fwrite(filebuf, 1, size, file); {
} fl_fwrite(filebuf, 1, size, file);
}
fl_fflush(file);
fl_fclose(file); fl_fflush(file);
} fl_fclose(file);
}
if (filebuf)
{ if (filebuf)
free(filebuf); {
} free(filebuf);
} }
} }
else }
{ else
rc = 1; {
} rc = 1;
}
fl_shutdown();
fl_shutdown();
return rc;
} return rc;
}
static int disk_xz_flush(void *src, unsigned int size)
{ static int disk_xz_flush(void *src, unsigned int size)
unsigned int i; {
BYTE *buf = (BYTE *)src; unsigned int i;
BYTE *buf = (BYTE *)src;
for (i = 0; i < size; i++)
{ for (i = 0; i < size; i++)
*g_part_img_pos = *buf++; {
*g_part_img_pos = *buf++;
g_disk_unxz_len++;
if ((g_disk_unxz_len % SIZE_1MB) == 0) g_disk_unxz_len++;
{ if ((g_disk_unxz_len % SIZE_1MB) == 0)
g_part_img_pos = g_part_img_buf[g_disk_unxz_len / SIZE_1MB]; {
} g_part_img_pos = g_part_img_buf[g_disk_unxz_len / SIZE_1MB];
else }
{ else
g_part_img_pos++; {
} g_part_img_pos++;
} }
}
return (int)size;
} return (int)size;
}
static void unxz_error(char *x)
{ static void unxz_error(char *x)
Log("%s", x); {
} Log("%s", x);
}
static BOOL TryWritePart2(HANDLE hDrive, UINT64 StartSectorId)
{ static BOOL TryWritePart2(HANDLE hDrive, UINT64 StartSectorId)
BOOL bRet; {
DWORD TrySize = 16 * 1024; BOOL bRet;
DWORD dwSize; DWORD TrySize = 16 * 1024;
BYTE *Buffer = NULL; DWORD dwSize;
unsigned char *data = NULL; BYTE *Buffer = NULL;
LARGE_INTEGER liCurrentPosition; unsigned char *data = NULL;
LARGE_INTEGER liCurrentPosition;
liCurrentPosition.QuadPart = StartSectorId * 512;
SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN); liCurrentPosition.QuadPart = StartSectorId * 512;
SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
Buffer = malloc(TrySize);
Buffer = malloc(TrySize);
bRet = WriteFile(hDrive, Buffer, TrySize, &dwSize, NULL);
bRet = WriteFile(hDrive, Buffer, TrySize, &dwSize, NULL);
free(Buffer);
free(Buffer);
Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
if (bRet && dwSize == TrySize)
{ if (bRet && dwSize == TrySize)
return TRUE; {
} return TRUE;
}
return FALSE;
} return FALSE;
}
static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId)
{ static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId)
int i; {
int rc = 0; int i;
int len = 0; int rc = 0;
int writelen = 0; int len = 0;
int partwrite = 0; int writelen = 0;
DWORD dwSize = 0; int partwrite = 0;
BOOL bRet; DWORD dwSize = 0;
unsigned char *data = NULL; BOOL bRet;
LARGE_INTEGER liCurrentPosition; unsigned char *data = NULL;
LARGE_INTEGER liNewPosition; LARGE_INTEGER liCurrentPosition;
LARGE_INTEGER liNewPosition;
Log("FormatPart2Fat %llu...", StartSectorId);
Log("FormatPart2Fat %llu...", StartSectorId);
rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&data, &len);
if (rc) rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&data, &len);
{ if (rc)
Log("Failed to read img file %p %u", data, len); {
return 1; Log("Failed to read img file %p %u", data, len);
} return 1;
}
liCurrentPosition.QuadPart = StartSectorId * 512;
SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN); liCurrentPosition.QuadPart = StartSectorId * 512;
SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
Log("Set file pointer: %llu New pointer:%llu", liCurrentPosition.QuadPart, liNewPosition.QuadPart);
Log("Set file pointer: %llu New pointer:%llu", liCurrentPosition.QuadPart, liNewPosition.QuadPart);
memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
g_part_img_buf[0] = (BYTE *)malloc(VENTOY_EFI_PART_SIZE);
if (g_part_img_buf[0]) g_part_img_buf[0] = (BYTE *)malloc(VENTOY_EFI_PART_SIZE);
{ if (g_part_img_buf[0])
Log("Malloc whole img buffer success, now decompress ..."); {
unxz(data, len, NULL, NULL, g_part_img_buf[0], &writelen, unxz_error); Log("Malloc whole img buffer success, now decompress ...");
unxz(data, len, NULL, NULL, g_part_img_buf[0], &writelen, unxz_error);
if (len == writelen)
{ if (len == writelen)
Log("decompress finished success"); {
Log("decompress finished success");
VentoyProcSecureBoot(g_SecureBoot);
VentoyProcSecureBoot(g_SecureBoot);
for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
{ for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
dwSize = 0; {
bRet = WriteFile(hDrive, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB, &dwSize, NULL); dwSize = 0;
Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR); bRet = WriteFile(hDrive, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB, &dwSize, NULL);
Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
if (!bRet)
{ if (!bRet)
rc = 1; {
goto End; rc = 1;
} goto End;
}
PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i);
} PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i);
} }
else }
{ else
rc = 1; {
Log("decompress finished failed"); rc = 1;
goto End; Log("decompress finished failed");
} goto End;
} }
else }
{ else
Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE); {
Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE);
partwrite = 1;
for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++) partwrite = 1;
{ for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
g_part_img_buf[i] = (BYTE *)malloc(SIZE_1MB); {
if (g_part_img_buf[i] == NULL) g_part_img_buf[i] = (BYTE *)malloc(SIZE_1MB);
{ if (g_part_img_buf[i] == NULL)
rc = 1; {
goto End; rc = 1;
} goto End;
} }
}
Log("Malloc part img buffer success, now decompress ...");
Log("Malloc part img buffer success, now decompress ...");
g_part_img_pos = g_part_img_buf[0];
g_part_img_pos = g_part_img_buf[0];
unxz(data, len, NULL, disk_xz_flush, NULL, NULL, unxz_error);
unxz(data, len, NULL, disk_xz_flush, NULL, NULL, unxz_error);
if (g_disk_unxz_len == VENTOY_EFI_PART_SIZE)
{ if (g_disk_unxz_len == VENTOY_EFI_PART_SIZE)
Log("decompress finished success"); {
Log("decompress finished success");
VentoyProcSecureBoot(g_SecureBoot);
VentoyProcSecureBoot(g_SecureBoot);
for (int i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
{ for (int i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
dwSize = 0; {
bRet = WriteFile(hDrive, g_part_img_buf[i], SIZE_1MB, &dwSize, NULL); dwSize = 0;
Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR); bRet = WriteFile(hDrive, g_part_img_buf[i], SIZE_1MB, &dwSize, NULL);
Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
if (!bRet)
{ if (!bRet)
rc = 1; {
goto End; rc = 1;
} goto End;
}
PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i);
} PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i);
} }
else }
{ else
rc = 1; {
Log("decompress finished failed"); rc = 1;
goto End; Log("decompress finished failed");
} goto End;
} }
}
End:
End:
if (data) free(data);
if (data) free(data);
if (partwrite)
{ if (partwrite)
for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++) {
{ for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
if (g_part_img_buf[i]) free(g_part_img_buf[i]); {
} if (g_part_img_buf[i]) free(g_part_img_buf[i]);
} }
else }
{ else
if (g_part_img_buf[0]) free(g_part_img_buf[0]); {
} if (g_part_img_buf[0]) free(g_part_img_buf[0]);
}
return rc;
} return rc;
}
static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle)
{ static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle)
int Len = 0; {
int readLen = 0; int Len = 0;
BOOL bRet; int readLen = 0;
DWORD dwSize; BOOL bRet;
BYTE *ImgBuf = NULL; DWORD dwSize;
BYTE *RawBuf = NULL; BYTE *ImgBuf = NULL;
BYTE *RawBuf = NULL;
Log("WriteGrubStage1ToPhyDrive ...");
Log("WriteGrubStage1ToPhyDrive ...");
RawBuf = (BYTE *)malloc(SIZE_1MB);
if (!RawBuf) RawBuf = (BYTE *)malloc(SIZE_1MB);
{ if (!RawBuf)
return 1; {
} return 1;
}
if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
{ if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
Log("Failed to read stage1 img"); {
free(RawBuf); Log("Failed to read stage1 img");
return 1; free(RawBuf);
} return 1;
}
unxz(ImgBuf, Len, NULL, NULL, RawBuf, &readLen, unxz_error);
unxz(ImgBuf, Len, NULL, NULL, RawBuf, &readLen, unxz_error);
if (PartStyle)
{ if (PartStyle)
Log("Write GPT stage1 ..."); {
RawBuf[500] = 35;//update blocklist Log("Write GPT stage1 ...");
SetFilePointer(hDrive, 512 * 34, NULL, FILE_BEGIN); RawBuf[500] = 35;//update blocklist
bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512 * 34, &dwSize, NULL); SetFilePointer(hDrive, 512 * 34, NULL, FILE_BEGIN);
} bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512 * 34, &dwSize, NULL);
else }
{ else
Log("Write MBR stage1 ..."); {
SetFilePointer(hDrive, 512, NULL, FILE_BEGIN); Log("Write MBR stage1 ...");
bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512, &dwSize, NULL); SetFilePointer(hDrive, 512, NULL, FILE_BEGIN);
} bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512, &dwSize, NULL);
}
Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet, dwSize, GetLastError());
Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet, dwSize, GetLastError());
free(RawBuf);
free(ImgBuf); free(RawBuf);
return 0; free(ImgBuf);
} return 0;
}
static int FormatPart1exFAT(UINT64 DiskSizeBytes)
{ static int FormatPart1exFAT(UINT64 DiskSizeBytes)
MKFS_PARM Option; {
FRESULT Ret; MKFS_PARM Option;
FATFS fs; FRESULT Ret;
FATFS fs;
Option.fmt = FM_EXFAT;
Option.n_fat = 1; Option.fmt = FM_EXFAT;
Option.align = 8; Option.n_fat = 1;
Option.n_root = 1; Option.align = 8;
Option.n_root = 1;
// < 32GB select 32KB as cluster size
// > 32GB select 128KB as cluster size // < 32GB select 32KB as cluster size
if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32) // > 32GB select 128KB as cluster size
{ if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32)
Option.au_size = 32768; {
} Option.au_size = 32768;
else }
{ else
Option.au_size = 131072; {
} Option.au_size = 131072;
}
Log("Formatting Part1 exFAT ...");
Log("Formatting Part1 exFAT ...");
Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
if (FR_OK == Ret)
{ if (FR_OK == Ret)
Log("Formatting Part1 exFAT success"); {
Log("Formatting Part1 exFAT success");
Ret = f_mount(&fs, TEXT("0:"), 1);
Log("mount part %d", Ret); Ret = f_mount(&fs, TEXT("0:"), 1);
Log("mount part %d", Ret);
if (FR_OK == Ret)
{ if (FR_OK == Ret)
Ret = f_setlabel(TEXT("Ventoy")); {
Log("f_setlabel %d", Ret); Ret = f_setlabel(TEXT("Ventoy"));
Log("f_setlabel %d", Ret);
Ret = f_mount(0, TEXT("0:"), 1);
Log("umount part %d", Ret); Ret = f_mount(0, TEXT("0:"), 1);
return 0; Log("umount part %d", Ret);
} return 0;
else }
{ else
Log("mount exfat failed %d", Ret); {
return 1; Log("mount exfat failed %d", Ret);
} return 1;
} }
else }
{ else
Log("Formatting Part1 exFAT failed"); {
return 1; Log("Formatting Part1 exFAT failed");
} return 1;
} }
}
int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter)
{ int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter)
int i; {
int rc = 0; int i;
int state = 0; int rc = 0;
HANDLE hDrive; int state = 0;
DWORD dwSize; HANDLE hDrive;
BOOL bRet; DWORD dwSize;
CHAR MountDrive; BOOL bRet;
CHAR DriveName[] = "?:\\"; CHAR MountDrive;
CHAR DriveLetters[MAX_PATH] = { 0 }; CHAR DriveName[] = "?:\\";
LARGE_INTEGER liCurrentPosition; CHAR DriveLetters[MAX_PATH] = { 0 };
char *pTmpBuf = NULL; LARGE_INTEGER liCurrentPosition;
MBR_HEAD MBR; char *pTmpBuf = NULL;
MBR_HEAD MBR;
*pDrvLetter = 0;
*pDrvLetter = 0;
Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
Log("Lock disk for clean ............................. ");
Log("Lock disk for clean ............................. ");
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
if (hDrive == INVALID_HANDLE_VALUE) hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
{ if (hDrive == INVALID_HANDLE_VALUE)
Log("Failed to open physical disk"); {
return 1; Log("Failed to open physical disk");
} return 1;
}
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
if (DriveLetters[0] == 0)
{ if (DriveLetters[0] == 0)
Log("No drive letter was assigned..."); {
DriveName[0] = GetFirstUnusedDriveLetter(); Log("No drive letter was assigned...");
Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]); DriveName[0] = GetFirstUnusedDriveLetter();
} Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
else }
{ else
// Unmount all mounted volumes that belong to this drive {
// Do it in reverse so that we always end on the first volume letter // Unmount all mounted volumes that belong to this drive
for (i = (int)strlen(DriveLetters); i > 0; i--) // Do it in reverse so that we always end on the first volume letter
{ for (i = (int)strlen(DriveLetters); i > 0; i--)
DriveName[0] = DriveLetters[i - 1]; {
bRet = DeleteVolumeMountPointA(DriveName); DriveName[0] = DriveLetters[i - 1];
Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError()); bRet = DeleteVolumeMountPointA(DriveName);
} Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
} }
}
MountDrive = DriveName[0];
Log("Will use '%C:' as volume mountpoint", DriveName[0]); MountDrive = DriveName[0];
Log("Will use '%C:' as volume mountpoint", DriveName[0]);
// It kind of blows, but we have to relinquish access to the physical drive
// for VDS to be able to delete the partitions that reside on it... // It kind of blows, but we have to relinquish access to the physical drive
DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); // for VDS to be able to delete the partitions that reside on it...
CHECK_CLOSE_HANDLE(hDrive); DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
CHECK_CLOSE_HANDLE(hDrive);
PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE))
{ if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE))
Log("Notice: Could not delete partitions: %u", GetLastError()); {
} Log("Notice: Could not delete partitions: %u", GetLastError());
}
Log("Deleting all partitions ......................... OK");
Log("Deleting all partitions ......................... OK");
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
Log("Lock disk for write ............................. ");
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); Log("Lock disk for write ............................. ");
if (hDrive == INVALID_HANDLE_VALUE) hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
{ if (hDrive == INVALID_HANDLE_VALUE)
Log("Failed to GetPhysicalHandle for write."); {
rc = 1; Log("Failed to GetPhysicalHandle for write.");
goto End; rc = 1;
} goto End;
}
// clear first and last 1MB space
pTmpBuf = malloc(SIZE_1MB); // clear first and last 1MB space
if (!pTmpBuf) pTmpBuf = malloc(SIZE_1MB);
{ if (!pTmpBuf)
Log("Failed to alloc memory."); {
rc = 1; Log("Failed to alloc memory.");
goto End; rc = 1;
} goto End;
memset(pTmpBuf, 0, SIZE_1MB); }
memset(pTmpBuf, 0, SIZE_1MB);
SET_FILE_POS(512);
bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB - 512, &dwSize, NULL); SET_FILE_POS(512);
Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR); bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB - 512, &dwSize, NULL);
if (!bRet) Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
{ if (!bRet)
rc = 1; {
goto End; rc = 1;
} goto End;
}
SET_FILE_POS(SIZE_1MB);
bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB, &dwSize, NULL); SET_FILE_POS(SIZE_1MB);
Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR); bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB, &dwSize, NULL);
if (!bRet) Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
{ if (!bRet)
rc = 1; {
goto End; rc = 1;
} goto End;
}
SET_FILE_POS(0);
bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL); SET_FILE_POS(0);
Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR); bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
if (!bRet) Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
{ if (!bRet)
rc = 1; {
goto End; rc = 1;
} goto End;
}
//clear boot code and partition table (reserved disk signature)
memset(MBR.BootCode, 0, 440); //clear boot code and partition table (reserved disk signature)
memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl)); memset(MBR.BootCode, 0, 440);
memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl));
VentoyFillLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl);
VentoyFillLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl);
MBR.PartTbl[0].Active = 0x00; // bootable
MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS MBR.PartTbl[0].Active = 0x00; // bootable
MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS
SET_FILE_POS(0);
bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL); SET_FILE_POS(0);
Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR); bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
if (!bRet) Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
{ if (!bRet)
rc = 1; {
goto End; rc = 1;
} goto End;
}
Log("Clear Ventoy successfully finished");
Log("Clear Ventoy successfully finished");
//Refresh Drive Layout
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); //Refresh Drive Layout
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
End:
End:
PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
if (pTmpBuf)
{ if (pTmpBuf)
free(pTmpBuf); {
} free(pTmpBuf);
}
if (rc == 0)
{ if (rc == 0)
Log("Mounting Ventoy Partition ....................... "); {
Sleep(1000); Log("Mounting Ventoy Partition ....................... ");
Sleep(1000);
state = 0;
memset(DriveLetters, 0, sizeof(DriveLetters)); state = 0;
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); memset(DriveLetters, 0, sizeof(DriveLetters));
Log("Logical drive letter after write ventoy: <%s>", DriveLetters); GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
{ for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
DriveName[0] = DriveLetters[i]; {
Log("%s is ventoy part1, already mounted", DriveName); DriveName[0] = DriveLetters[i];
state = 1; Log("%s is ventoy part1, already mounted", DriveName);
} state = 1;
}
if (state != 1)
{ if (state != 1)
Log("need to mount ventoy part1..."); {
if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE)) Log("need to mount ventoy part1...");
{ if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE))
DriveName[0] = MountDrive; {
bRet = SetVolumeMountPointA(DriveName, DriveLetters); DriveName[0] = MountDrive;
Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError()); bRet = SetVolumeMountPointA(DriveName, DriveLetters);
Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
*pDrvLetter = MountDrive;
} *pDrvLetter = MountDrive;
else }
{ else
Log("Failed to find ventoy volume"); {
} Log("Failed to find ventoy volume");
} }
}
Log("OK\n");
} Log("OK\n");
else }
{ else
FindProcessOccupyDisk(hDrive, pPhyDrive); {
} FindProcessOccupyDisk(hDrive, pPhyDrive);
}
CHECK_CLOSE_HANDLE(hDrive);
return rc; CHECK_CLOSE_HANDLE(hDrive);
} return rc;
}
int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
{ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
int i; {
int rc = 0; int i;
int state = 0; int rc = 0;
HANDLE hDrive; int state = 0;
DWORD dwSize; HANDLE hDrive;
BOOL bRet; DWORD dwSize;
CHAR MountDrive; BOOL bRet;
CHAR DriveName[] = "?:\\"; CHAR MountDrive;
CHAR DriveLetters[MAX_PATH] = { 0 }; CHAR DriveName[] = "?:\\";
MBR_HEAD MBR; CHAR DriveLetters[MAX_PATH] = { 0 };
VTOY_GPT_INFO *pGptInfo = NULL; MBR_HEAD MBR;
VTOY_GPT_INFO *pGptInfo = NULL;
Log("InstallVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>",
PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, Log("InstallVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>",
GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
if (PartStyle)
{ if (PartStyle)
pGptInfo = malloc(sizeof(VTOY_GPT_INFO)); {
memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO)); pGptInfo = malloc(sizeof(VTOY_GPT_INFO));
} memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
}
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle);//also used to format 1st partition in GPT mode
if (PartStyle) VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle);//also used to format 1st partition in GPT mode
{ if (PartStyle)
VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo); {
} VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);
}
Log("Lock disk for clean ............................. ");
Log("Lock disk for clean ............................. ");
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
if (hDrive == INVALID_HANDLE_VALUE) hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
{ if (hDrive == INVALID_HANDLE_VALUE)
Log("Failed to open physical disk"); {
free(pGptInfo); Log("Failed to open physical disk");
return 1; free(pGptInfo);
} return 1;
}
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
if (DriveLetters[0] == 0)
{ if (DriveLetters[0] == 0)
Log("No drive letter was assigned..."); {
DriveName[0] = GetFirstUnusedDriveLetter(); Log("No drive letter was assigned...");
Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]); DriveName[0] = GetFirstUnusedDriveLetter();
} Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
else }
{ else
// Unmount all mounted volumes that belong to this drive {
// Do it in reverse so that we always end on the first volume letter // Unmount all mounted volumes that belong to this drive
for (i = (int)strlen(DriveLetters); i > 0; i--) // Do it in reverse so that we always end on the first volume letter
{ for (i = (int)strlen(DriveLetters); i > 0; i--)
DriveName[0] = DriveLetters[i - 1]; {
bRet = DeleteVolumeMountPointA(DriveName); DriveName[0] = DriveLetters[i - 1];
Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError()); bRet = DeleteVolumeMountPointA(DriveName);
} Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
} }
}
MountDrive = DriveName[0];
Log("Will use '%C:' as volume mountpoint", DriveName[0]); MountDrive = DriveName[0];
Log("Will use '%C:' as volume mountpoint", DriveName[0]);
// It kind of blows, but we have to relinquish access to the physical drive
// for VDS to be able to delete the partitions that reside on it... // It kind of blows, but we have to relinquish access to the physical drive
DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); // for VDS to be able to delete the partitions that reside on it...
CHECK_CLOSE_HANDLE(hDrive); DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
CHECK_CLOSE_HANDLE(hDrive);
PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE))
{ if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE))
Log("Notice: Could not delete partitions: %u", GetLastError()); {
} Log("Notice: Could not delete partitions: %u", GetLastError());
}
Log("Deleting all partitions ......................... OK");
Log("Deleting all partitions ......................... OK");
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
Log("Lock disk for write ............................. ");
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); Log("Lock disk for write ............................. ");
if (hDrive == INVALID_HANDLE_VALUE) hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
{ if (hDrive == INVALID_HANDLE_VALUE)
Log("Failed to GetPhysicalHandle for write."); {
rc = 1; Log("Failed to GetPhysicalHandle for write.");
goto End; rc = 1;
} goto End;
}
//Refresh Drive Layout
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); //Refresh Drive Layout
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
disk_io_set_param(hDrive, MBR.PartTbl[0].StartSectorId + MBR.PartTbl[0].SectorCount);
disk_io_set_param(hDrive, MBR.PartTbl[0].StartSectorId + MBR.PartTbl[0].SectorCount);
PROGRESS_BAR_SET_POS(PT_FORMAT_PART1);
PROGRESS_BAR_SET_POS(PT_FORMAT_PART1);
Log("Formatting part1 exFAT ...");
if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes)) if (PartStyle == 1 && pPhyDrive->PartStyle == 0)
{ {
Log("FormatPart1exFAT failed."); Log("Wait for format part1 ...");
rc = 1; Sleep(1000 * 5);
goto End; }
}
Log("Formatting part1 exFAT ...");
PROGRESS_BAR_SET_POS(PT_FORMAT_PART2); if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
Log("Writing part2 FAT img ..."); {
if (0 != FormatPart2Fat(hDrive, MBR.PartTbl[1].StartSectorId)) Log("FormatPart1exFAT failed.");
{ rc = 1;
Log("FormatPart2Fat failed."); goto End;
rc = 1; }
goto End;
} PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
Log("Writing part2 FAT img ...");
PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG); if (0 != FormatPart2Fat(hDrive, MBR.PartTbl[1].StartSectorId))
Log("Writting Boot Image ............................. "); {
if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0) Log("FormatPart2Fat failed.");
{ rc = 1;
Log("WriteGrubStage1ToPhyDrive failed."); goto End;
rc = 1; }
goto End;
} PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);
Log("Writting Boot Image ............................. ");
PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE); if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0)
Log("Writting Partition Table ........................ "); {
SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); Log("WriteGrubStage1ToPhyDrive failed.");
rc = 1;
if (PartStyle) goto End;
{ }
VTOY_GPT_HDR BackupHead;
LARGE_INTEGER liCurrentPosition; PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);
Log("Writting Partition Table ........................ ");
SET_FILE_POS(pPhyDrive->SizeInBytes - 512); SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
VentoyFillBackupGptHead(pGptInfo, &BackupHead);
if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL)) if (PartStyle)
{ {
rc = 1; VTOY_GPT_HDR BackupHead;
Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError()); LARGE_INTEGER liCurrentPosition;
goto End;
} SET_FILE_POS(pPhyDrive->SizeInBytes - 512);
VentoyFillBackupGptHead(pGptInfo, &BackupHead);
SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33); if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))
if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL)) {
{ rc = 1;
rc = 1; Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError()); goto End;
goto End; }
}
SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);
SET_FILE_POS(0); if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))
if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL)) {
{ rc = 1;
rc = 1; Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError()); goto End;
goto End; }
}
SET_FILE_POS(0);
Log("Write GPT Info OK ..."); if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))
} {
else rc = 1;
{ Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
if (!WriteFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL)) goto End;
{ }
rc = 1;
Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize, GetLastError()); Log("Write GPT Info OK ...");
goto End; }
} else
Log("Write MBR OK ..."); {
} if (!WriteFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL))
{
rc = 1;
//Refresh Drive Layout Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize, GetLastError());
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); goto End;
}
End: Log("Write MBR OK ...");
}
PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
if (rc == 0) //Refresh Drive Layout
{ DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
Log("Mounting Ventoy Partition ....................... ");
Sleep(1000); End:
state = 0; PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
memset(DriveLetters, 0, sizeof(DriveLetters));
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); if (rc == 0)
Log("Logical drive letter after write ventoy: <%s>", DriveLetters); {
Log("Mounting Ventoy Partition ....................... ");
for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++) Sleep(1000);
{
DriveName[0] = DriveLetters[i]; state = 0;
if (IsVentoyLogicalDrive(DriveName[0])) memset(DriveLetters, 0, sizeof(DriveLetters));
{ GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
Log("%s is ventoy part2, delete mountpoint", DriveName); Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
DeleteVolumeMountPointA(DriveName);
} for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
else {
{ DriveName[0] = DriveLetters[i];
Log("%s is ventoy part1, already mounted", DriveName); if (IsVentoyLogicalDrive(DriveName[0]))
state = 1; {
} Log("%s is ventoy part2, delete mountpoint", DriveName);
} DeleteVolumeMountPointA(DriveName);
}
if (state != 1) else
{ {
Log("need to mount ventoy part1..."); Log("%s is ventoy part1, already mounted", DriveName);
if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE)) state = 1;
{ }
DriveName[0] = MountDrive; }
bRet = SetVolumeMountPointA(DriveName, DriveLetters);
Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError()); if (state != 1)
} {
else Log("need to mount ventoy part1...");
{ if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE))
Log("Failed to find ventoy volume"); {
} DriveName[0] = MountDrive;
} bRet = SetVolumeMountPointA(DriveName, DriveLetters);
Log("OK\n"); Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
} }
else else
{ {
FindProcessOccupyDisk(hDrive, pPhyDrive); Log("Failed to find ventoy volume");
} }
}
if (pGptInfo) Log("OK\n");
{ }
free(pGptInfo); else
} {
FindProcessOccupyDisk(hDrive, pPhyDrive);
CHECK_CLOSE_HANDLE(hDrive); }
return rc;
} if (pGptInfo)
{
int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive) free(pGptInfo);
{ }
int i;
int rc = 0; CHECK_CLOSE_HANDLE(hDrive);
BOOL ForceMBR = FALSE; return rc;
HANDLE hVolume; }
HANDLE hDrive;
DWORD Status; int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
DWORD dwSize; {
BOOL bRet; int i;
CHAR DriveName[] = "?:\\"; int rc = 0;
CHAR DriveLetters[MAX_PATH] = { 0 }; BOOL ForceMBR = FALSE;
UINT64 StartSector; HANDLE hVolume;
UINT64 ReservedMB = 0; HANDLE hDrive;
MBR_HEAD BootImg; DWORD Status;
MBR_HEAD MBR; DWORD dwSize;
VTOY_GPT_INFO *pGptInfo = NULL; BOOL bRet;
CHAR DriveName[] = "?:\\";
Log("UpdateVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>", CHAR DriveLetters[MAX_PATH] = { 0 };
pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, UINT64 StartSector;
GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); UINT64 ReservedMB = 0;
MBR_HEAD BootImg;
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); MBR_HEAD MBR;
VTOY_GPT_INFO *pGptInfo = NULL;
Log("Lock disk for umount ............................ ");
Log("UpdateVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>",
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE); pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
if (hDrive == INVALID_HANDLE_VALUE) GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
{
Log("Failed to open physical disk"); PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
return 1;
} Log("Lock disk for umount ............................ ");
if (pPhyDrive->PartStyle) hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
{ if (hDrive == INVALID_HANDLE_VALUE)
pGptInfo = malloc(sizeof(VTOY_GPT_INFO)); {
if (!pGptInfo) Log("Failed to open physical disk");
{ return 1;
return 1; }
}
if (pPhyDrive->PartStyle)
memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO)); {
pGptInfo = malloc(sizeof(VTOY_GPT_INFO));
// Read GPT Info if (!pGptInfo)
SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); {
ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL); return 1;
}
StartSector = pGptInfo->PartTbl[1].StartLBA;
Log("GPT StartSector in PartTbl:%llu", (ULONGLONG)StartSector); memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512) - 33) / 2048; // Read GPT Info
Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB); SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
} ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL);
else
{ //MBR will be used to compare with local boot image
// Read MBR memcpy(&MBR, &pGptInfo->MBR, sizeof(MBR_HEAD));
SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL); StartSector = pGptInfo->PartTbl[1].StartLBA;
Log("GPT StartSector in PartTbl:%llu", (ULONGLONG)StartSector);
StartSector = MBR.PartTbl[1].StartSectorId;
Log("MBR StartSector in PartTbl:%llu", (ULONGLONG)StartSector); ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512) - 33) / 2048;
Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);
ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512)) / 2048; }
Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB); else
} {
// Read MBR
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
if (DriveLetters[0] == 0)
{ StartSector = MBR.PartTbl[1].StartSectorId;
Log("No drive letter was assigned..."); Log("MBR StartSector in PartTbl:%llu", (ULONGLONG)StartSector);
}
else ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512)) / 2048;
{ Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);
// Unmount all mounted volumes that belong to this drive }
// Do it in reverse so that we always end on the first volume letter
for (i = (int)strlen(DriveLetters); i > 0; i--) GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
{
DriveName[0] = DriveLetters[i - 1]; if (DriveLetters[0] == 0)
if (IsVentoyLogicalDrive(DriveName[0])) {
{ Log("No drive letter was assigned...");
Log("%s is ventoy logical drive", DriveName); }
bRet = DeleteVolumeMountPointA(DriveName); else
Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, LASTERR); {
break; // Unmount all mounted volumes that belong to this drive
} // Do it in reverse so that we always end on the first volume letter
} for (i = (int)strlen(DriveLetters); i > 0; i--)
} {
DriveName[0] = DriveLetters[i - 1];
// It kind of blows, but we have to relinquish access to the physical drive if (IsVentoyLogicalDrive(DriveName[0]))
// for VDS to be able to delete the partitions that reside on it... {
DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); Log("%s is ventoy logical drive", DriveName);
CHECK_CLOSE_HANDLE(hDrive); bRet = DeleteVolumeMountPointA(DriveName);
Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, LASTERR);
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE); break;
}
Log("Lock disk for update ............................ "); }
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); }
if (hDrive == INVALID_HANDLE_VALUE)
{ // It kind of blows, but we have to relinquish access to the physical drive
Log("Failed to GetPhysicalHandle for write."); // for VDS to be able to delete the partitions that reside on it...
rc = 1; DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
goto End; CHECK_CLOSE_HANDLE(hDrive);
}
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME);
Log("Lock disk for update ............................ ");
Log("Lock volume for update .......................... "); hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
hVolume = INVALID_HANDLE_VALUE; if (hDrive == INVALID_HANDLE_VALUE)
Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[1].StartSectorId, DriveLetters, sizeof(DriveLetters), TRUE); {
if (ERROR_SUCCESS == Status) Log("Failed to GetPhysicalHandle for write.");
{ rc = 1;
Log("Now lock and dismount volume <%s>", DriveLetters); goto End;
hVolume = CreateFileA(DriveLetters, }
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME);
NULL,
OPEN_EXISTING, Log("Lock volume for update .......................... ");
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, hVolume = INVALID_HANDLE_VALUE;
NULL); Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[1].StartSectorId, DriveLetters, sizeof(DriveLetters), TRUE);
if (ERROR_SUCCESS == Status)
if (hVolume == INVALID_HANDLE_VALUE) {
{ Log("Now lock and dismount volume <%s>", DriveLetters);
Log("Failed to create file volume, errcode:%u", LASTERR); hVolume = CreateFileA(DriveLetters,
rc = 1; GENERIC_READ | GENERIC_WRITE,
goto End; FILE_SHARE_READ,
} NULL,
OPEN_EXISTING,
bRet = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet, LASTERR); NULL);
bRet = DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); if (hVolume == INVALID_HANDLE_VALUE)
Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet, LASTERR); {
} Log("Failed to create file volume, errcode:%u", LASTERR);
else if (ERROR_NOT_FOUND == Status) rc = 1;
{ goto End;
Log("Volume not found, maybe not supported"); }
}
else bRet = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
{ Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
rc = 1;
goto End; bRet = DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
} Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet, LASTERR);
}
else if (ERROR_NOT_FOUND == Status)
if (!TryWritePart2(hDrive, StartSector)) {
{ Log("Volume not found, maybe not supported");
ForceMBR = TRUE; }
Log("Try write failed, now delete partition 2..."); else
{
CHECK_CLOSE_HANDLE(hDrive); rc = 1;
goto End;
Log("Now delete partition 2..."); }
DeletePartitions(pPhyDrive->PhyDrive, TRUE);
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); if (!TryWritePart2(hDrive, StartSector))
if (hDrive == INVALID_HANDLE_VALUE) {
{ ForceMBR = TRUE;
Log("Failed to GetPhysicalHandle for write."); Log("Try write failed, now delete partition 2...");
rc = 1;
goto End; CHECK_CLOSE_HANDLE(hDrive);
}
} Log("Now delete partition 2...");
DeletePartitions(pPhyDrive->PhyDrive, TRUE);
PROGRESS_BAR_SET_POS(PT_FORMAT_PART2); hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
if (hDrive == INVALID_HANDLE_VALUE)
Log("Write Ventoy to disk ............................ "); {
if (0 != FormatPart2Fat(hDrive, StartSector)) Log("Failed to GetPhysicalHandle for write.");
{ rc = 1;
rc = 1; goto End;
goto End; }
} }
if (hVolume != INVALID_HANDLE_VALUE)
{ PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR); Log("Write Ventoy to disk ............................ ");
CHECK_CLOSE_HANDLE(hVolume); if (0 != FormatPart2Fat(hDrive, StartSector))
} {
rc = 1;
Log("Updating Boot Image ............................. "); goto End;
if (WriteGrubStage1ToPhyDrive(hDrive, pPhyDrive->PartStyle) != 0) }
{
rc = 1; if (hVolume != INVALID_HANDLE_VALUE)
goto End; {
} bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
// Boot Image CHECK_CLOSE_HANDLE(hVolume);
VentoyGetLocalBootImg(&BootImg); }
// Use Old UUID Log("Updating Boot Image ............................. ");
memcpy(BootImg.BootCode + 0x180, MBR.BootCode + 0x180, 16); if (WriteGrubStage1ToPhyDrive(hDrive, pPhyDrive->PartStyle) != 0)
if (pPhyDrive->PartStyle) {
{ rc = 1;
BootImg.BootCode[92] = 0x22; goto End;
} }
if (ForceMBR == FALSE && memcmp(BootImg.BootCode, MBR.BootCode, 440) == 0) // Boot Image
{ VentoyGetLocalBootImg(&BootImg);
Log("Boot image has no difference, no need to write.");
} // Use Old UUID
else memcpy(BootImg.BootCode + 0x180, MBR.BootCode + 0x180, 16);
{ if (pPhyDrive->PartStyle)
Log("Boot image need to write %u.", ForceMBR); {
BootImg.BootCode[92] = 0x22;
SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); }
memcpy(MBR.BootCode, BootImg.BootCode, 440); if (ForceMBR == FALSE && memcmp(BootImg.BootCode, MBR.BootCode, 440) == 0)
bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL); {
Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR); Log("Boot image has no difference, no need to write.");
} }
else
if (pPhyDrive->PartStyle == 0) {
{ Log("Boot image need to write %u.", ForceMBR);
if (0x00 == MBR.PartTbl[0].Active && 0x80 == MBR.PartTbl[1].Active)
{ SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
Log("Need to chage 1st partition active and 2nd partition inactive.");
memcpy(MBR.BootCode, BootImg.BootCode, 440);
MBR.PartTbl[0].Active = 0x80; bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
MBR.PartTbl[1].Active = 0x00; Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
}
SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL); if (pPhyDrive->PartStyle == 0)
Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR); {
} if (0x00 == MBR.PartTbl[0].Active && 0x80 == MBR.PartTbl[1].Active)
} {
Log("Need to chage 1st partition active and 2nd partition inactive.");
//Refresh Drive Layout
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); MBR.PartTbl[0].Active = 0x80;
MBR.PartTbl[1].Active = 0x00;
End:
SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
if (rc == 0) bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
{ Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
Log("OK"); }
} }
else
{ //Refresh Drive Layout
FindProcessOccupyDisk(hDrive, pPhyDrive); DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
}
End:
CHECK_CLOSE_HANDLE(hDrive);
if (rc == 0)
if (pGptInfo) {
{ Log("OK");
free(pGptInfo); }
} else
{
return rc; FindProcessOccupyDisk(hDrive, pPhyDrive);
} }
CHECK_CLOSE_HANDLE(hDrive);
if (pGptInfo)
{
free(pGptInfo);
}
return rc;
}
/****************************************************************************** /******************************************************************************
* Utility.c * Utility.c
* *
* Copyright (c) 2020, longpanda <admin@ventoy.net> * Copyright (c) 2020, longpanda <admin@ventoy.net>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the * published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version. * License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include <Windows.h> #include <Windows.h>
#include "Ventoy2Disk.h" #include "Ventoy2Disk.h"
void Log(const char *Fmt, ...) void Log(const char *Fmt, ...)
{ {
va_list Arg; va_list Arg;
int Len = 0; int Len = 0;
FILE *File = NULL; FILE *File = NULL;
SYSTEMTIME Sys; SYSTEMTIME Sys;
char szBuf[1024]; char szBuf[1024];
GetLocalTime(&Sys); GetLocalTime(&Sys);
Len += safe_sprintf(szBuf, Len += safe_sprintf(szBuf,
"[%4d/%02d/%02d %02d:%02d:%02d.%03d] ", "[%4d/%02d/%02d %02d:%02d:%02d.%03d] ",
Sys.wYear, Sys.wMonth, Sys.wDay, Sys.wYear, Sys.wMonth, Sys.wDay,
Sys.wHour, Sys.wMinute, Sys.wSecond, Sys.wHour, Sys.wMinute, Sys.wSecond,
Sys.wMilliseconds); Sys.wMilliseconds);
va_start(Arg, Fmt); va_start(Arg, Fmt);
Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg); Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);
va_end(Arg); va_end(Arg);
//printf("%s\n", szBuf); //printf("%s\n", szBuf);
#if 1 #if 1
fopen_s(&File, VENTOY_FILE_LOG, "a+"); fopen_s(&File, VENTOY_FILE_LOG, "a+");
if (File) if (File)
{ {
fwrite(szBuf, 1, Len, File); fwrite(szBuf, 1, Len, File);
fwrite("\n", 1, 1, File); fwrite("\n", 1, 1, File);
fclose(File); fclose(File);
} }
#endif #endif
} }
BOOL IsPathExist(BOOL Dir, const char *Fmt, ...) BOOL IsPathExist(BOOL Dir, const char *Fmt, ...)
{ {
va_list Arg; va_list Arg;
HANDLE hFile; HANDLE hFile;
DWORD Attr; DWORD Attr;
CHAR FilePath[MAX_PATH]; CHAR FilePath[MAX_PATH];
va_start(Arg, Fmt); va_start(Arg, Fmt);
vsnprintf_s(FilePath, sizeof(FilePath), sizeof(FilePath), Fmt, Arg); vsnprintf_s(FilePath, sizeof(FilePath), sizeof(FilePath), Fmt, Arg);
va_end(Arg); va_end(Arg);
hFile = CreateFileA(FilePath, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); hFile = CreateFileA(FilePath, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (INVALID_HANDLE_VALUE == hFile) if (INVALID_HANDLE_VALUE == hFile)
{ {
return FALSE; return FALSE;
} }
CloseHandle(hFile); CloseHandle(hFile);
Attr = GetFileAttributesA(FilePath); Attr = GetFileAttributesA(FilePath);
if (Dir) if (Dir)
{ {
if ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0) if ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
{ {
return FALSE; return FALSE;
} }
} }
else else
{ {
if (Attr & FILE_ATTRIBUTE_DIRECTORY) if (Attr & FILE_ATTRIBUTE_DIRECTORY)
{ {
return FALSE; return FALSE;
} }
} }
return TRUE; return TRUE;
} }
int ReadWholeFileToBuf(const CHAR *FileName, int ExtLen, void **Bufer, int *BufLen) int ReadWholeFileToBuf(const CHAR *FileName, int ExtLen, void **Bufer, int *BufLen)
{ {
int FileSize; int FileSize;
FILE *File = NULL; FILE *File = NULL;
void *Data = NULL; void *Data = NULL;
fopen_s(&File, FileName, "rb"); fopen_s(&File, FileName, "rb");
if (File == NULL) if (File == NULL)
{ {
Log("Failed to open file %s", FileName); Log("Failed to open file %s", FileName);
return 1; return 1;
} }
fseek(File, 0, SEEK_END); fseek(File, 0, SEEK_END);
FileSize = (int)ftell(File); FileSize = (int)ftell(File);
Data = malloc(FileSize + ExtLen); Data = malloc(FileSize + ExtLen);
if (!Data) if (!Data)
{ {
fclose(File); fclose(File);
return 1; return 1;
} }
fseek(File, 0, SEEK_SET); fseek(File, 0, SEEK_SET);
fread(Data, 1, FileSize, File); fread(Data, 1, FileSize, File);
fclose(File); fclose(File);
*Bufer = Data; *Bufer = Data;
*BufLen = FileSize; *BufLen = FileSize;
return 0; return 0;
} }
const CHAR* GetLocalVentoyVersion(void) const CHAR* GetLocalVentoyVersion(void)
{ {
int rc; int rc;
int FileSize; int FileSize;
CHAR *Pos = NULL; CHAR *Pos = NULL;
CHAR *Buf = NULL; CHAR *Buf = NULL;
static CHAR LocalVersion[64] = { 0 }; static CHAR LocalVersion[64] = { 0 };
if (LocalVersion[0] == 0) if (LocalVersion[0] == 0)
{ {
rc = ReadWholeFileToBuf(VENTOY_FILE_VERSION, 1, (void **)&Buf, &FileSize); rc = ReadWholeFileToBuf(VENTOY_FILE_VERSION, 1, (void **)&Buf, &FileSize);
if (rc) if (rc)
{ {
return ""; return "";
} }
Buf[FileSize] = 0; Buf[FileSize] = 0;
for (Pos = Buf; *Pos; Pos++) for (Pos = Buf; *Pos; Pos++)
{ {
if (*Pos == '\r' || *Pos == '\n') if (*Pos == '\r' || *Pos == '\n')
{ {
*Pos = 0; *Pos = 0;
break; break;
} }
} }
safe_sprintf(LocalVersion, "%s", Buf); safe_sprintf(LocalVersion, "%s", Buf);
free(Buf); free(Buf);
} }
return LocalVersion; return LocalVersion;
} }
const CHAR* ParseVentoyVersionFromString(CHAR *Buf) const CHAR* ParseVentoyVersionFromString(CHAR *Buf)
{ {
CHAR *Pos = NULL; CHAR *Pos = NULL;
CHAR *End = NULL; CHAR *End = NULL;
static CHAR LocalVersion[64] = { 0 }; static CHAR LocalVersion[64] = { 0 };
Pos = strstr(Buf, "VENTOY_VERSION="); Pos = strstr(Buf, "VENTOY_VERSION=");
if (Pos) if (Pos)
{ {
Pos += strlen("VENTOY_VERSION="); Pos += strlen("VENTOY_VERSION=");
if (*Pos == '"') if (*Pos == '"')
{ {
Pos++; Pos++;
} }
End = Pos; End = Pos;
while (*End != 0 && *End != '"' && *End != '\r' && *End != '\n') while (*End != 0 && *End != '"' && *End != '\r' && *End != '\n')
{ {
End++; End++;
} }
*End = 0; *End = 0;
safe_sprintf(LocalVersion, "%s", Pos); safe_sprintf(LocalVersion, "%s", Pos);
return LocalVersion; return LocalVersion;
} }
return ""; return "";
} }
BOOL IsWow64(void) BOOL IsWow64(void)
{ {
typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process; LPFN_ISWOW64PROCESS fnIsWow64Process;
BOOL bIsWow64 = FALSE; BOOL bIsWow64 = FALSE;
fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process"); fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process");
if (NULL != fnIsWow64Process) if (NULL != fnIsWow64Process)
{ {
fnIsWow64Process(GetCurrentProcess(), &bIsWow64); fnIsWow64Process(GetCurrentProcess(), &bIsWow64);
} }
return bIsWow64; return bIsWow64;
} }
void DumpWindowsVersion(void) void DumpWindowsVersion(void)
{ {
int Bit; int Bit;
BOOL WsVer; BOOL WsVer;
DWORD Major, Minor; DWORD Major, Minor;
ULONGLONG MajorEqual, MinorEqual; ULONGLONG MajorEqual, MinorEqual;
OSVERSIONINFOEXA Ver1, Ver2; OSVERSIONINFOEXA Ver1, Ver2;
const CHAR *Ver = NULL; const CHAR *Ver = NULL;
CHAR WinVer[256] = { 0 }; CHAR WinVer[256] = { 0 };
memset(&Ver1, 0, sizeof(Ver1)); memset(&Ver1, 0, sizeof(Ver1));
memset(&Ver2, 0, sizeof(Ver2)); memset(&Ver2, 0, sizeof(Ver2));
Ver1.dwOSVersionInfoSize = sizeof(Ver1); Ver1.dwOSVersionInfoSize = sizeof(Ver1);
// suppress the C4996 warning for GetVersionExA // suppress the C4996 warning for GetVersionExA
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4996) #pragma warning(disable:4996)
if (!GetVersionExA((OSVERSIONINFOA *)&Ver1)) if (!GetVersionExA((OSVERSIONINFOA *)&Ver1))
{ {
memset(&Ver1, 0, sizeof(Ver1)); memset(&Ver1, 0, sizeof(Ver1));
Ver1.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); Ver1.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
if (!GetVersionExA((OSVERSIONINFOA *)&Ver1)) if (!GetVersionExA((OSVERSIONINFOA *)&Ver1))
{ {
return; return;
} }
} }
#pragma warning(pop) #pragma warning(pop)
if (Ver1.dwPlatformId == VER_PLATFORM_WIN32_NT) if (Ver1.dwPlatformId == VER_PLATFORM_WIN32_NT)
{ {
if (Ver1.dwMajorVersion > 6 || (Ver1.dwMajorVersion == 6 && Ver1.dwMinorVersion >= 2)) if (Ver1.dwMajorVersion > 6 || (Ver1.dwMajorVersion == 6 && Ver1.dwMinorVersion >= 2))
{ {
// GetVersionEx() has problem on some Windows version // GetVersionEx() has problem on some Windows version
MajorEqual = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); MajorEqual = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
for (Major = Ver1.dwMajorVersion; Major <= 9; Major++) for (Major = Ver1.dwMajorVersion; Major <= 9; Major++)
{ {
memset(&Ver2, 0, sizeof(Ver2)); memset(&Ver2, 0, sizeof(Ver2));
Ver2.dwOSVersionInfoSize = sizeof(Ver2); Ver2.dwOSVersionInfoSize = sizeof(Ver2);
Ver2.dwMajorVersion = Major; Ver2.dwMajorVersion = Major;
if (!VerifyVersionInfoA(&Ver2, VER_MAJORVERSION, MajorEqual)) if (!VerifyVersionInfoA(&Ver2, VER_MAJORVERSION, MajorEqual))
{ {
continue; continue;
} }
if (Ver1.dwMajorVersion < Major) if (Ver1.dwMajorVersion < Major)
{ {
Ver1.dwMajorVersion = Major; Ver1.dwMajorVersion = Major;
Ver1.dwMinorVersion = 0; Ver1.dwMinorVersion = 0;
} }
MinorEqual = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); MinorEqual = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
for (Minor = Ver1.dwMinorVersion; Minor <= 9; Minor++) for (Minor = Ver1.dwMinorVersion; Minor <= 9; Minor++)
{ {
memset(&Ver2, 0, sizeof(Ver2)); memset(&Ver2, 0, sizeof(Ver2));
Ver2.dwOSVersionInfoSize = sizeof(Ver2); Ver2.dwOSVersionInfoSize = sizeof(Ver2);
Ver2.dwMinorVersion = Minor; Ver2.dwMinorVersion = Minor;
if (!VerifyVersionInfoA(&Ver2, VER_MINORVERSION, MinorEqual)) if (!VerifyVersionInfoA(&Ver2, VER_MINORVERSION, MinorEqual))
{ {
continue; continue;
} }
Ver1.dwMinorVersion = Minor; Ver1.dwMinorVersion = Minor;
break; break;
} }
break; break;
} }
} }
if (Ver1.dwMajorVersion <= 0xF && Ver1.dwMinorVersion <= 0xF) if (Ver1.dwMajorVersion <= 0xF && Ver1.dwMinorVersion <= 0xF)
{ {
WsVer = (Ver1.wProductType <= VER_NT_WORKSTATION); WsVer = (Ver1.wProductType <= VER_NT_WORKSTATION);
switch ((Ver1.dwMajorVersion << 4) | Ver2.dwMinorVersion) switch ((Ver1.dwMajorVersion << 4) | Ver2.dwMinorVersion)
{ {
case 0x51: case 0x51:
{ {
Ver = "XP"; Ver = "XP";
break; break;
} }
case 0x52: case 0x52:
{ {
Ver = GetSystemMetrics(89) ? "Server 2003 R2" : "Server 2003"; Ver = GetSystemMetrics(89) ? "Server 2003 R2" : "Server 2003";
break; break;
} }
case 0x60: case 0x60:
{ {
Ver = WsVer ? "Vista" : "Server 2008"; Ver = WsVer ? "Vista" : "Server 2008";
break; break;
} }
case 0x61: case 0x61:
{ {
Ver = WsVer ? "7" : "Server 2008 R2"; Ver = WsVer ? "7" : "Server 2008 R2";
break; break;
} }
case 0x62: case 0x62:
{ {
Ver = WsVer ? "8" : "Server 2012"; Ver = WsVer ? "8" : "Server 2012";
break; break;
} }
case 0x63: case 0x63:
{ {
Ver = WsVer ? "8.1" : "Server 2012 R2"; Ver = WsVer ? "8.1" : "Server 2012 R2";
break; break;
} }
case 0x64: case 0x64:
{ {
Ver = WsVer ? "10 (Preview 1)" : "Server 10 (Preview 1)"; Ver = WsVer ? "10 (Preview 1)" : "Server 10 (Preview 1)";
break; break;
} }
case 0xA0: case 0xA0:
{ {
Ver = WsVer ? "10" : ((Ver1.dwBuildNumber > 15000) ? "Server 2019" : "Server 2016"); Ver = WsVer ? "10" : ((Ver1.dwBuildNumber > 15000) ? "Server 2019" : "Server 2016");
break; break;
} }
default: default:
{ {
Ver = "10 or later"; Ver = "10 or later";
break; break;
} }
} }
} }
} }
Bit = IsWow64() ? 64 : 32; Bit = IsWow64() ? 64 : 32;
if (Ver1.wServicePackMinor) if (Ver1.wServicePackMinor)
{ {
safe_sprintf(WinVer, "Windows %s SP%u.%u %d-bit", Ver, Ver1.wServicePackMajor, Ver1.wServicePackMinor, Bit); safe_sprintf(WinVer, "Windows %s SP%u.%u %d-bit", Ver, Ver1.wServicePackMajor, Ver1.wServicePackMinor, Bit);
} }
else if (Ver1.wServicePackMajor) else if (Ver1.wServicePackMajor)
{ {
safe_sprintf(WinVer, "Windows %s SP%u %d-bit", Ver, Ver1.wServicePackMajor, Bit); safe_sprintf(WinVer, "Windows %s SP%u %d-bit", Ver, Ver1.wServicePackMajor, Bit);
} }
else else
{ {
safe_sprintf(WinVer, "Windows %s %d-bit", Ver, Bit); safe_sprintf(WinVer, "Windows %s %d-bit", Ver, Bit);
} }
if (((Ver1.dwMajorVersion << 4) | Ver2.dwMinorVersion) >= 0x62) if (((Ver1.dwMajorVersion << 4) | Ver2.dwMinorVersion) >= 0x62)
{ {
Log("Windows Version : %s (Build %u)", WinVer, Ver1.dwBuildNumber); Log("Windows Version : %s (Build %u)", WinVer, Ver1.dwBuildNumber);
} }
else else
{ {
Log("Windows Version : %s", WinVer); Log("Windows Version : %s", WinVer);
} }
return; return;
} }
BOOL IsVentoyLogicalDrive(CHAR DriveLetter) BOOL IsVentoyLogicalDrive(CHAR DriveLetter)
{ {
int i; int i;
CONST CHAR *Files[] = CONST CHAR *Files[] =
{ {
"EFI\\BOOT\\BOOTX64.EFI", "EFI\\BOOT\\BOOTX64.EFI",
"grub\\themes\\ventoy\\theme.txt", "grub\\themes\\ventoy\\theme.txt",
"ventoy\\ventoy.cpio", "ventoy\\ventoy.cpio",
}; };
for (i = 0; i < sizeof(Files) / sizeof(Files[0]); i++) for (i = 0; i < sizeof(Files) / sizeof(Files[0]); i++)
{ {
if (!IsFileExist("%C:\\%s", DriveLetter, Files[i])) if (!IsFileExist("%C:\\%s", DriveLetter, Files[i]))
{ {
return FALSE; return FALSE;
} }
} }
return TRUE; return TRUE;
} }
int VentoyFillLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table) int VentoyFillLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table)
{ {
BYTE Head; BYTE Head;
BYTE Sector; BYTE Sector;
BYTE nSector = 63; BYTE nSector = 63;
BYTE nHead = 8; BYTE nHead = 8;
UINT32 Cylinder; UINT32 Cylinder;
UINT32 EndSectorId; UINT32 EndSectorId;
while (nHead != 0 && (DiskSizeInBytes / 512 / nSector / nHead) > 1024) while (nHead != 0 && (DiskSizeInBytes / 512 / nSector / nHead) > 1024)
{ {
nHead = (BYTE)nHead * 2; nHead = (BYTE)nHead * 2;
} }
if (nHead == 0) if (nHead == 0)
{ {
nHead = 255; nHead = 255;
} }
Cylinder = StartSectorId / nSector / nHead; Cylinder = StartSectorId / nSector / nHead;
Head = StartSectorId / nSector % nHead; Head = StartSectorId / nSector % nHead;
Sector = StartSectorId % nSector + 1; Sector = StartSectorId % nSector + 1;
Table->StartHead = Head; Table->StartHead = Head;
Table->StartSector = Sector; Table->StartSector = Sector;
Table->StartCylinder = Cylinder; Table->StartCylinder = Cylinder;
EndSectorId = StartSectorId + SectorCount - 1; EndSectorId = StartSectorId + SectorCount - 1;
Cylinder = EndSectorId / nSector / nHead; Cylinder = EndSectorId / nSector / nHead;
Head = EndSectorId / nSector % nHead; Head = EndSectorId / nSector % nHead;
Sector = EndSectorId % nSector + 1; Sector = EndSectorId % nSector + 1;
Table->EndHead = Head; Table->EndHead = Head;
Table->EndSector = Sector; Table->EndSector = Sector;
Table->EndCylinder = Cylinder; Table->EndCylinder = Cylinder;
Table->StartSectorId = StartSectorId; Table->StartSectorId = StartSectorId;
Table->SectorCount = SectorCount; Table->SectorCount = SectorCount;
return 0; return 0;
} }
int VentoyFillMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR, int PartStyle) int VentoyFillMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR, int PartStyle)
{ {
GUID Guid; GUID Guid;
int ReservedValue; int ReservedValue;
UINT32 DiskSignature; UINT32 DiskSignature;
UINT32 DiskSectorCount; UINT32 DiskSectorCount;
UINT32 PartSectorCount; UINT32 PartSectorCount;
UINT32 PartStartSector; UINT32 PartStartSector;
UINT32 ReservedSector; UINT32 ReservedSector;
VentoyGetLocalBootImg(pMBR); VentoyGetLocalBootImg(pMBR);
CoCreateGuid(&Guid); CoCreateGuid(&Guid);
memcpy(&DiskSignature, &Guid, sizeof(UINT32)); memcpy(&DiskSignature, &Guid, sizeof(UINT32));
Log("Disk signature: 0x%08x", DiskSignature); Log("Disk signature: 0x%08x", DiskSignature);
*((UINT32 *)(pMBR->BootCode + 0x1B8)) = DiskSignature; *((UINT32 *)(pMBR->BootCode + 0x1B8)) = DiskSignature;
if (DiskSizeBytes / 512 > 0xFFFFFFFF) if (DiskSizeBytes / 512 > 0xFFFFFFFF)
{ {
DiskSectorCount = 0xFFFFFFFF; DiskSectorCount = 0xFFFFFFFF;
} }
else else
{ {
DiskSectorCount = (UINT32)(DiskSizeBytes / 512); DiskSectorCount = (UINT32)(DiskSizeBytes / 512);
} }
ReservedValue = GetReservedSpaceInMB(); ReservedValue = GetReservedSpaceInMB();
if (ReservedValue <= 0) if (ReservedValue <= 0)
{ {
ReservedSector = 0; ReservedSector = 0;
} }
else else
{ {
ReservedSector = (UINT32)(ReservedValue * 2048); ReservedSector = (UINT32)(ReservedValue * 2048);
} }
if (PartStyle) if (PartStyle)
{ {
ReservedSector += 33; // backup GPT part table ReservedSector += 33; // backup GPT part table
} }
Log("ReservedSector: %u", ReservedSector); Log("ReservedSector: %u", ReservedSector);
//Part1 //Part1
PartStartSector = VENTOY_PART1_START_SECTOR; PartStartSector = VENTOY_PART1_START_SECTOR;
PartSectorCount = DiskSectorCount - ReservedSector - VENTOY_EFI_PART_SIZE / 512 - PartStartSector; PartSectorCount = DiskSectorCount - ReservedSector - VENTOY_EFI_PART_SIZE / 512 - PartStartSector;
VentoyFillLocation(DiskSizeBytes, PartStartSector, PartSectorCount, pMBR->PartTbl); VentoyFillLocation(DiskSizeBytes, PartStartSector, PartSectorCount, pMBR->PartTbl);
pMBR->PartTbl[0].Active = 0x80; // bootable pMBR->PartTbl[0].Active = 0x80; // bootable
pMBR->PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS pMBR->PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS
//Part2 //Part2
PartStartSector += PartSectorCount; PartStartSector += PartSectorCount;
PartSectorCount = VENTOY_EFI_PART_SIZE / 512; PartSectorCount = VENTOY_EFI_PART_SIZE / 512;
VentoyFillLocation(DiskSizeBytes, PartStartSector, PartSectorCount, pMBR->PartTbl + 1); VentoyFillLocation(DiskSizeBytes, PartStartSector, PartSectorCount, pMBR->PartTbl + 1);
pMBR->PartTbl[1].Active = 0x00; pMBR->PartTbl[1].Active = 0x00;
pMBR->PartTbl[1].FsFlag = 0xEF; // EFI System Partition pMBR->PartTbl[1].FsFlag = 0xEF; // EFI System Partition
pMBR->Byte55 = 0x55; pMBR->Byte55 = 0x55;
pMBR->ByteAA = 0xAA; pMBR->ByteAA = 0xAA;
return 0; return 0;
} }
static int VentoyFillProtectMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR) static int VentoyFillProtectMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR)
{ {
GUID Guid; GUID Guid;
UINT32 DiskSignature; UINT32 DiskSignature;
UINT64 DiskSectorCount; UINT64 DiskSectorCount;
VentoyGetLocalBootImg(pMBR); VentoyGetLocalBootImg(pMBR);
CoCreateGuid(&Guid); CoCreateGuid(&Guid);
memcpy(&DiskSignature, &Guid, sizeof(UINT32)); memcpy(&DiskSignature, &Guid, sizeof(UINT32));
Log("Disk signature: 0x%08x", DiskSignature); Log("Disk signature: 0x%08x", DiskSignature);
*((UINT32 *)(pMBR->BootCode + 0x1B8)) = DiskSignature; *((UINT32 *)(pMBR->BootCode + 0x1B8)) = DiskSignature;
DiskSectorCount = DiskSizeBytes / 512 - 1; DiskSectorCount = DiskSizeBytes / 512 - 1;
if (DiskSectorCount > 0xFFFFFFFF) if (DiskSectorCount > 0xFFFFFFFF)
{ {
DiskSectorCount = 0xFFFFFFFF; DiskSectorCount = 0xFFFFFFFF;
} }
memset(pMBR->PartTbl, 0, sizeof(pMBR->PartTbl)); memset(pMBR->PartTbl, 0, sizeof(pMBR->PartTbl));
pMBR->PartTbl[0].Active = 0x00; pMBR->PartTbl[0].Active = 0x00;
pMBR->PartTbl[0].FsFlag = 0xee; // EE pMBR->PartTbl[0].FsFlag = 0xee; // EE
pMBR->PartTbl[0].StartHead = 0; pMBR->PartTbl[0].StartHead = 0;
pMBR->PartTbl[0].StartSector = 1; pMBR->PartTbl[0].StartSector = 1;
pMBR->PartTbl[0].StartCylinder = 0; pMBR->PartTbl[0].StartCylinder = 0;
pMBR->PartTbl[0].EndHead = 254; pMBR->PartTbl[0].EndHead = 254;
pMBR->PartTbl[0].EndSector = 63; pMBR->PartTbl[0].EndSector = 63;
pMBR->PartTbl[0].EndCylinder = 1023; pMBR->PartTbl[0].EndCylinder = 1023;
pMBR->PartTbl[0].StartSectorId = 1; pMBR->PartTbl[0].StartSectorId = 1;
pMBR->PartTbl[0].SectorCount = (UINT32)DiskSectorCount; pMBR->PartTbl[0].SectorCount = (UINT32)DiskSectorCount;
pMBR->Byte55 = 0x55; pMBR->Byte55 = 0x55;
pMBR->ByteAA = 0xAA; pMBR->ByteAA = 0xAA;
pMBR->BootCode[92] = 0x22; pMBR->BootCode[92] = 0x22;
return 0; return 0;
} }
int VentoyFillGpt(UINT64 DiskSizeBytes, VTOY_GPT_INFO *pInfo) int VentoyFillGpt(UINT64 DiskSizeBytes, VTOY_GPT_INFO *pInfo)
{ {
INT64 ReservedValue = 0; INT64 ReservedValue = 0;
UINT64 ReservedSector = 33; UINT64 ReservedSector = 33;
UINT64 Part1SectorCount = 0; UINT64 Part1SectorCount = 0;
UINT64 DiskSectorCount = DiskSizeBytes / 512; UINT64 DiskSectorCount = DiskSizeBytes / 512;
VTOY_GPT_HDR *Head = &pInfo->Head; VTOY_GPT_HDR *Head = &pInfo->Head;
VTOY_GPT_PART_TBL *Table = pInfo->PartTbl; VTOY_GPT_PART_TBL *Table = pInfo->PartTbl;
static GUID WindowsDataPartType = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } }; static GUID WindowsDataPartType = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };
static GUID EspPartType = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } }; static GUID EspPartType = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };
//static GUID BiosGrubPartType = { 0x21686148, 0x6449, 0x6e6f, { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } }; static GUID BiosGrubPartType = { 0x21686148, 0x6449, 0x6e6f, { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } };
VentoyFillProtectMBR(DiskSizeBytes, &pInfo->MBR); VentoyFillProtectMBR(DiskSizeBytes, &pInfo->MBR);
ReservedValue = GetReservedSpaceInMB(); ReservedValue = GetReservedSpaceInMB();
if (ReservedValue > 0) if (ReservedValue > 0)
{ {
ReservedSector += ReservedValue * 2048; ReservedSector += ReservedValue * 2048;
} }
Part1SectorCount = DiskSectorCount - ReservedSector - (VENTOY_EFI_PART_SIZE / 512) - 2048; Part1SectorCount = DiskSectorCount - ReservedSector - (VENTOY_EFI_PART_SIZE / 512) - 2048;
memcpy(Head->Signature, "EFI PART", 8); memcpy(Head->Signature, "EFI PART", 8);
Head->Version[2] = 0x01; Head->Version[2] = 0x01;
Head->Length = 92; Head->Length = 92;
Head->Crc = 0; Head->Crc = 0;
Head->EfiStartLBA = 1; Head->EfiStartLBA = 1;
Head->EfiBackupLBA = DiskSectorCount - 1; Head->EfiBackupLBA = DiskSectorCount - 1;
Head->PartAreaStartLBA = 34; Head->PartAreaStartLBA = 34;
Head->PartAreaEndLBA = DiskSectorCount - 34; Head->PartAreaEndLBA = DiskSectorCount - 34;
CoCreateGuid(&Head->DiskGuid); CoCreateGuid(&Head->DiskGuid);
Head->PartTblStartLBA = 2; Head->PartTblStartLBA = 2;
Head->PartTblTotNum = 128; Head->PartTblTotNum = 128;
Head->PartTblEntryLen = 128; Head->PartTblEntryLen = 128;
memcpy(&(Table[0].PartType), &WindowsDataPartType, sizeof(GUID)); memcpy(&(Table[0].PartType), &WindowsDataPartType, sizeof(GUID));
CoCreateGuid(&(Table[0].PartGuid)); CoCreateGuid(&(Table[0].PartGuid));
Table[0].StartLBA = 2048; Table[0].StartLBA = 2048;
Table[0].LastLBA = 2048 + Part1SectorCount - 1; Table[0].LastLBA = 2048 + Part1SectorCount - 1;
Table[0].Attr = 0; Table[0].Attr = 0;
memcpy(Table[0].Name, L"Ventoy", 6 * 2); memcpy(Table[0].Name, L"Ventoy", 6 * 2);
memcpy(&(Table[1].PartType), &EspPartType, sizeof(GUID)); // to fix windows issue
CoCreateGuid(&(Table[1].PartGuid)); //memcpy(&(Table[1].PartType), &EspPartType, sizeof(GUID));
Table[1].StartLBA = Table[0].LastLBA + 1; memcpy(&(Table[1].PartType), &WindowsDataPartType, sizeof(GUID));
Table[1].LastLBA = Table[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1; CoCreateGuid(&(Table[1].PartGuid));
Table[1].Attr = 1; Table[1].StartLBA = Table[0].LastLBA + 1;
memcpy(Table[1].Name, L"VTOYEFI", 7 * 2); Table[1].LastLBA = Table[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1;
Table[1].Attr = 0xC000000000000001ULL;
#if 0 memcpy(Table[1].Name, L"VTOYEFI", 7 * 2);
memcpy(&(Table[2].PartType), &BiosGrubPartType, sizeof(GUID));
CoCreateGuid(&(Table[2].PartGuid)); #if 0
Table[2].StartLBA = 34; memcpy(&(Table[2].PartType), &BiosGrubPartType, sizeof(GUID));
Table[2].LastLBA = 2047; CoCreateGuid(&(Table[2].PartGuid));
Table[2].Attr = 0; Table[2].StartLBA = 34;
#endif Table[2].LastLBA = 2047;
Table[2].Attr = 0;
//Update CRC #endif
Head->PartTblCrc = VentoyCrc32(Table, sizeof(pInfo->PartTbl));
Head->Crc = VentoyCrc32(Head, Head->Length); //Update CRC
Head->PartTblCrc = VentoyCrc32(Table, sizeof(pInfo->PartTbl));
return 0; Head->Crc = VentoyCrc32(Head, Head->Length);
}
return 0;
int VentoyFillBackupGptHead(VTOY_GPT_INFO *pInfo, VTOY_GPT_HDR *pHead) }
{
UINT64 LBA; int VentoyFillBackupGptHead(VTOY_GPT_INFO *pInfo, VTOY_GPT_HDR *pHead)
UINT64 BackupLBA; {
UINT64 LBA;
memcpy(pHead, &pInfo->Head, sizeof(VTOY_GPT_HDR)); UINT64 BackupLBA;
LBA = pHead->EfiStartLBA; memcpy(pHead, &pInfo->Head, sizeof(VTOY_GPT_HDR));
BackupLBA = pHead->EfiBackupLBA;
LBA = pHead->EfiStartLBA;
pHead->EfiStartLBA = BackupLBA; BackupLBA = pHead->EfiBackupLBA;
pHead->EfiBackupLBA = LBA;
pHead->PartTblStartLBA = BackupLBA + 1 - 33; pHead->EfiStartLBA = BackupLBA;
pHead->EfiBackupLBA = LBA;
pHead->Crc = 0; pHead->PartTblStartLBA = BackupLBA + 1 - 33;
pHead->Crc = VentoyCrc32(pHead, pHead->Length);
pHead->Crc = 0;
return 0; pHead->Crc = VentoyCrc32(pHead, pHead->Length);
}
return 0;
CHAR GetFirstUnusedDriveLetter(void) }
{
CHAR Letter = 'D'; CHAR GetFirstUnusedDriveLetter(void)
DWORD Drives = GetLogicalDrives(); {
CHAR Letter = 'D';
Drives >>= 3; DWORD Drives = GetLogicalDrives();
while (Drives & 0x1)
{ Drives >>= 3;
Letter++; while (Drives & 0x1)
Drives >>= 1; {
} Letter++;
Drives >>= 1;
return Letter; }
}
return Letter;
const CHAR * GetBusTypeString(STORAGE_BUS_TYPE Type) }
{
switch (Type) const CHAR * GetBusTypeString(STORAGE_BUS_TYPE Type)
{ {
case BusTypeUnknown: return "unknown"; switch (Type)
case BusTypeScsi: return "SCSI"; {
case BusTypeAtapi: return "Atapi"; case BusTypeUnknown: return "unknown";
case BusTypeAta: return "ATA"; case BusTypeScsi: return "SCSI";
case BusType1394: return "1394"; case BusTypeAtapi: return "Atapi";
case BusTypeSsa: return "SSA"; case BusTypeAta: return "ATA";
case BusTypeFibre: return "Fibre"; case BusType1394: return "1394";
case BusTypeUsb: return "USB"; case BusTypeSsa: return "SSA";
case BusTypeRAID: return "RAID"; case BusTypeFibre: return "Fibre";
case BusTypeiScsi: return "iSCSI"; case BusTypeUsb: return "USB";
case BusTypeSas: return "SAS"; case BusTypeRAID: return "RAID";
case BusTypeSata: return "SATA"; case BusTypeiScsi: return "iSCSI";
case BusTypeSd: return "SD"; case BusTypeSas: return "SAS";
case BusTypeMmc: return "MMC"; case BusTypeSata: return "SATA";
case BusTypeVirtual: return "Virtual"; case BusTypeSd: return "SD";
case BusTypeFileBackedVirtual: return "FileBackedVirtual"; case BusTypeMmc: return "MMC";
case BusTypeSpaces: return "Spaces"; case BusTypeVirtual: return "Virtual";
case BusTypeNvme: return "Nvme"; case BusTypeFileBackedVirtual: return "FileBackedVirtual";
} case BusTypeSpaces: return "Spaces";
return "unknown"; case BusTypeNvme: return "Nvme";
} }
return "unknown";
int VentoyGetLocalBootImg(MBR_HEAD *pMBR) }
{
int Len = 0; int VentoyGetLocalBootImg(MBR_HEAD *pMBR)
BYTE *ImgBuf = NULL; {
static int Loaded = 0; int Len = 0;
static MBR_HEAD MBR; BYTE *ImgBuf = NULL;
static int Loaded = 0;
if (Loaded) static MBR_HEAD MBR;
{
memcpy(pMBR, &MBR, 512); if (Loaded)
return 0; {
} memcpy(pMBR, &MBR, 512);
return 0;
if (0 == ReadWholeFileToBuf(VENTOY_FILE_BOOT_IMG, 0, (void **)&ImgBuf, &Len)) }
{
Log("Copy boot img success"); if (0 == ReadWholeFileToBuf(VENTOY_FILE_BOOT_IMG, 0, (void **)&ImgBuf, &Len))
memcpy(pMBR, ImgBuf, 512); {
free(ImgBuf); Log("Copy boot img success");
memcpy(pMBR, ImgBuf, 512);
CoCreateGuid((GUID *)(pMBR->BootCode + 0x180)); free(ImgBuf);
memcpy(&MBR, pMBR, 512); CoCreateGuid((GUID *)(pMBR->BootCode + 0x180));
Loaded = 1;
memcpy(&MBR, pMBR, 512);
return 0; Loaded = 1;
}
else return 0;
{ }
Log("Copy boot img failed"); else
return 1; {
} Log("Copy boot img failed");
} return 1;
}
int GetHumanReadableGBSize(UINT64 SizeBytes) }
{
int i; int GetHumanReadableGBSize(UINT64 SizeBytes)
int Pow2 = 1; {
double Delta; int i;
double GB = SizeBytes * 1.0 / 1000 / 1000 / 1000; int Pow2 = 1;
double Delta;
for (i = 0; i < 12; i++) double GB = SizeBytes * 1.0 / 1000 / 1000 / 1000;
{
if (Pow2 > GB) for (i = 0; i < 12; i++)
{ {
Delta = (Pow2 - GB) / Pow2; if (Pow2 > GB)
} {
else Delta = (Pow2 - GB) / Pow2;
{ }
Delta = (GB - Pow2) / Pow2; else
} {
Delta = (GB - Pow2) / Pow2;
if (Delta < 0.05) }
{
return Pow2; if (Delta < 0.05)
} {
return Pow2;
Pow2 <<= 1; }
}
Pow2 <<= 1;
return (int)GB; }
}
return (int)GB;
void TrimString(CHAR *String) }
{
CHAR *Pos1 = String; void TrimString(CHAR *String)
CHAR *Pos2 = String; {
size_t Len = strlen(String); CHAR *Pos1 = String;
CHAR *Pos2 = String;
while (Len > 0) size_t Len = strlen(String);
{
if (String[Len - 1] != ' ' && String[Len - 1] != '\t') while (Len > 0)
{ {
break; if (String[Len - 1] != ' ' && String[Len - 1] != '\t')
} {
String[Len - 1] = 0; break;
Len--; }
} String[Len - 1] = 0;
Len--;
while (*Pos1 == ' ' || *Pos1 == '\t') }
{
Pos1++; while (*Pos1 == ' ' || *Pos1 == '\t')
} {
Pos1++;
while (*Pos1) }
{
*Pos2++ = *Pos1++; while (*Pos1)
} {
*Pos2++ = 0; *Pos2++ = *Pos1++;
}
return; *Pos2++ = 0;
}
return;
int GetRegDwordValue(HKEY Key, LPCSTR SubKey, LPCSTR ValueName, DWORD *pValue) }
{
HKEY hKey; int GetRegDwordValue(HKEY Key, LPCSTR SubKey, LPCSTR ValueName, DWORD *pValue)
DWORD Type; {
DWORD Size; HKEY hKey;
LSTATUS lRet; DWORD Type;
DWORD Value; DWORD Size;
LSTATUS lRet;
lRet = RegOpenKeyExA(Key, SubKey, 0, KEY_QUERY_VALUE, &hKey); DWORD Value;
Log("RegOpenKeyExA <%s> Ret:%ld", SubKey, lRet);
lRet = RegOpenKeyExA(Key, SubKey, 0, KEY_QUERY_VALUE, &hKey);
if (ERROR_SUCCESS == lRet) Log("RegOpenKeyExA <%s> Ret:%ld", SubKey, lRet);
{
Size = sizeof(Value); if (ERROR_SUCCESS == lRet)
lRet = RegQueryValueExA(hKey, ValueName, NULL, &Type, (LPBYTE)&Value, &Size); {
Log("RegQueryValueExA <%s> ret:%u Size:%u Value:%u", ValueName, lRet, Size, Value); Size = sizeof(Value);
lRet = RegQueryValueExA(hKey, ValueName, NULL, &Type, (LPBYTE)&Value, &Size);
*pValue = Value; Log("RegQueryValueExA <%s> ret:%u Size:%u Value:%u", ValueName, lRet, Size, Value);
RegCloseKey(hKey);
*pValue = Value;
return 0; RegCloseKey(hKey);
}
else return 0;
{ }
return 1; else
} {
} return 1;
}
int GetPhysicalDriveCount(void) }
{
DWORD Value; int GetPhysicalDriveCount(void)
int Count = 0; {
DWORD Value;
if (GetRegDwordValue(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", "Count", &Value) == 0) int Count = 0;
{
Count = (int)Value; if (GetRegDwordValue(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", "Count", &Value) == 0)
} {
Count = (int)Value;
Log("GetPhysicalDriveCount: %d", Count); }
return Count;
} Log("GetPhysicalDriveCount: %d", Count);
return Count;
}
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
#!/bin/bash
rm -f vtoytool/00/*
/opt/diet64/bin/diet -Os gcc -D_FILE_OFFSET_BITS=64 vtoygpt.c crc32.c -o vtoygpt_64
/opt/diet32/bin/diet -Os gcc -D_FILE_OFFSET_BITS=64 -m32 vtoygpt.c crc32.c -o vtoygpt_32
#gcc -D_FILE_OFFSET_BITS=64 -static -Wall vtoygpt.c -o vtoytool_64
#gcc -D_FILE_OFFSET_BITS=64 -Wall -m32 vtoygpt.c -o vtoytool_32
if [ -e vtoygpt_64 ] && [ -e vtoygpt_32 ]; then
echo -e '\n############### SUCCESS ###############\n'
mv vtoygpt_64 ../INSTALL/tool/
mv vtoygpt_32 ../INSTALL/tool/
else
echo -e '\n############### FAILED ################\n'
exit 1
fi
/******************************************************************************
* vtoygpt.c ---- ventoy gpt util
*
* Copyright (c) 2020, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <dirent.h>
#define VOID void
#define CHAR char
#define UINT64 unsigned long long
#define UINT32 unsigned int
#define UINT16 unsigned short
#define CHAR16 unsigned short
#define UINT8 unsigned char
UINT32 g_crc_table[256] = {
0x00000000,
0x77073096,
0xEE0E612C,
0x990951BA,
0x076DC419,
0x706AF48F,
0xE963A535,
0x9E6495A3,
0x0EDB8832,
0x79DCB8A4,
0xE0D5E91E,
0x97D2D988,
0x09B64C2B,
0x7EB17CBD,
0xE7B82D07,
0x90BF1D91,
0x1DB71064,
0x6AB020F2,
0xF3B97148,
0x84BE41DE,
0x1ADAD47D,
0x6DDDE4EB,
0xF4D4B551,
0x83D385C7,
0x136C9856,
0x646BA8C0,
0xFD62F97A,
0x8A65C9EC,
0x14015C4F,
0x63066CD9,
0xFA0F3D63,
0x8D080DF5,
0x3B6E20C8,
0x4C69105E,
0xD56041E4,
0xA2677172,
0x3C03E4D1,
0x4B04D447,
0xD20D85FD,
0xA50AB56B,
0x35B5A8FA,
0x42B2986C,
0xDBBBC9D6,
0xACBCF940,
0x32D86CE3,
0x45DF5C75,
0xDCD60DCF,
0xABD13D59,
0x26D930AC,
0x51DE003A,
0xC8D75180,
0xBFD06116,
0x21B4F4B5,
0x56B3C423,
0xCFBA9599,
0xB8BDA50F,
0x2802B89E,
0x5F058808,
0xC60CD9B2,
0xB10BE924,
0x2F6F7C87,
0x58684C11,
0xC1611DAB,
0xB6662D3D,
0x76DC4190,
0x01DB7106,
0x98D220BC,
0xEFD5102A,
0x71B18589,
0x06B6B51F,
0x9FBFE4A5,
0xE8B8D433,
0x7807C9A2,
0x0F00F934,
0x9609A88E,
0xE10E9818,
0x7F6A0DBB,
0x086D3D2D,
0x91646C97,
0xE6635C01,
0x6B6B51F4,
0x1C6C6162,
0x856530D8,
0xF262004E,
0x6C0695ED,
0x1B01A57B,
0x8208F4C1,
0xF50FC457,
0x65B0D9C6,
0x12B7E950,
0x8BBEB8EA,
0xFCB9887C,
0x62DD1DDF,
0x15DA2D49,
0x8CD37CF3,
0xFBD44C65,
0x4DB26158,
0x3AB551CE,
0xA3BC0074,
0xD4BB30E2,
0x4ADFA541,
0x3DD895D7,
0xA4D1C46D,
0xD3D6F4FB,
0x4369E96A,
0x346ED9FC,
0xAD678846,
0xDA60B8D0,
0x44042D73,
0x33031DE5,
0xAA0A4C5F,
0xDD0D7CC9,
0x5005713C,
0x270241AA,
0xBE0B1010,
0xC90C2086,
0x5768B525,
0x206F85B3,
0xB966D409,
0xCE61E49F,
0x5EDEF90E,
0x29D9C998,
0xB0D09822,
0xC7D7A8B4,
0x59B33D17,
0x2EB40D81,
0xB7BD5C3B,
0xC0BA6CAD,
0xEDB88320,
0x9ABFB3B6,
0x03B6E20C,
0x74B1D29A,
0xEAD54739,
0x9DD277AF,
0x04DB2615,
0x73DC1683,
0xE3630B12,
0x94643B84,
0x0D6D6A3E,
0x7A6A5AA8,
0xE40ECF0B,
0x9309FF9D,
0x0A00AE27,
0x7D079EB1,
0xF00F9344,
0x8708A3D2,
0x1E01F268,
0x6906C2FE,
0xF762575D,
0x806567CB,
0x196C3671,
0x6E6B06E7,
0xFED41B76,
0x89D32BE0,
0x10DA7A5A,
0x67DD4ACC,
0xF9B9DF6F,
0x8EBEEFF9,
0x17B7BE43,
0x60B08ED5,
0xD6D6A3E8,
0xA1D1937E,
0x38D8C2C4,
0x4FDFF252,
0xD1BB67F1,
0xA6BC5767,
0x3FB506DD,
0x48B2364B,
0xD80D2BDA,
0xAF0A1B4C,
0x36034AF6,
0x41047A60,
0xDF60EFC3,
0xA867DF55,
0x316E8EEF,
0x4669BE79,
0xCB61B38C,
0xBC66831A,
0x256FD2A0,
0x5268E236,
0xCC0C7795,
0xBB0B4703,
0x220216B9,
0x5505262F,
0xC5BA3BBE,
0xB2BD0B28,
0x2BB45A92,
0x5CB36A04,
0xC2D7FFA7,
0xB5D0CF31,
0x2CD99E8B,
0x5BDEAE1D,
0x9B64C2B0,
0xEC63F226,
0x756AA39C,
0x026D930A,
0x9C0906A9,
0xEB0E363F,
0x72076785,
0x05005713,
0x95BF4A82,
0xE2B87A14,
0x7BB12BAE,
0x0CB61B38,
0x92D28E9B,
0xE5D5BE0D,
0x7CDCEFB7,
0x0BDBDF21,
0x86D3D2D4,
0xF1D4E242,
0x68DDB3F8,
0x1FDA836E,
0x81BE16CD,
0xF6B9265B,
0x6FB077E1,
0x18B74777,
0x88085AE6,
0xFF0F6A70,
0x66063BCA,
0x11010B5C,
0x8F659EFF,
0xF862AE69,
0x616BFFD3,
0x166CCF45,
0xA00AE278,
0xD70DD2EE,
0x4E048354,
0x3903B3C2,
0xA7672661,
0xD06016F7,
0x4969474D,
0x3E6E77DB,
0xAED16A4A,
0xD9D65ADC,
0x40DF0B66,
0x37D83BF0,
0xA9BCAE53,
0xDEBB9EC5,
0x47B2CF7F,
0x30B5FFE9,
0xBDBDF21C,
0xCABAC28A,
0x53B39330,
0x24B4A3A6,
0xBAD03605,
0xCDD70693,
0x54DE5729,
0x23D967BF,
0xB3667A2E,
0xC4614AB8,
0x5D681B02,
0x2A6F2B94,
0xB40BBE37,
0xC30C8EA1,
0x5A05DF1B,
0x2D02EF8D
};
UINT32 VtoyCrc32(VOID *Buffer, UINT32 Length)
{
UINT32 i;
UINT8 *Ptr = Buffer;
UINT32 Crc = 0xFFFFFFFF;
for (i = 0; i < Length; i++, Ptr++)
{
Crc = (Crc >> 8) ^ g_crc_table[(UINT8) Crc ^ *Ptr];
}
return Crc ^ 0xffffffff;
}
/******************************************************************************
* vtoygpt.c ---- ventoy gpt util
*
* Copyright (c) 2020, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <dirent.h>
#define VOID void
#define CHAR char
#define UINT64 unsigned long long
#define UINT32 unsigned int
#define UINT16 unsigned short
#define CHAR16 unsigned short
#define UINT8 unsigned char
UINT32 VtoyCrc32(VOID *Buffer, UINT32 Length);
#define COMPILE_ASSERT(expr) extern char __compile_assert[(expr) ? 1 : -1]
#pragma pack(1)
typedef struct PART_TABLE
{
UINT8 Active;
UINT8 StartHead;
UINT16 StartSector : 6;
UINT16 StartCylinder : 10;
UINT8 FsFlag;
UINT8 EndHead;
UINT16 EndSector : 6;
UINT16 EndCylinder : 10;
UINT32 StartSectorId;
UINT32 SectorCount;
}PART_TABLE;
typedef struct MBR_HEAD
{
UINT8 BootCode[446];
PART_TABLE PartTbl[4];
UINT8 Byte55;
UINT8 ByteAA;
}MBR_HEAD;
typedef struct GUID
{
UINT32 data1;
UINT16 data2;
UINT16 data3;
UINT8 data4[8];
}GUID;
typedef struct VTOY_GPT_HDR
{
CHAR Signature[8]; /* EFI PART */
UINT8 Version[4];
UINT32 Length;
UINT32 Crc;
UINT8 Reserved1[4];
UINT64 EfiStartLBA;
UINT64 EfiBackupLBA;
UINT64 PartAreaStartLBA;
UINT64 PartAreaEndLBA;
GUID DiskGuid;
UINT64 PartTblStartLBA;
UINT32 PartTblTotNum;
UINT32 PartTblEntryLen;
UINT32 PartTblCrc;
UINT8 Reserved2[420];
}VTOY_GPT_HDR;
COMPILE_ASSERT(sizeof(VTOY_GPT_HDR) == 512);
typedef struct VTOY_GPT_PART_TBL
{
GUID PartType;
GUID PartGuid;
UINT64 StartLBA;
UINT64 LastLBA;
UINT64 Attr;
CHAR16 Name[36];
}VTOY_GPT_PART_TBL;
COMPILE_ASSERT(sizeof(VTOY_GPT_PART_TBL) == 128);
typedef struct VTOY_GPT_INFO
{
MBR_HEAD MBR;
VTOY_GPT_HDR Head;
VTOY_GPT_PART_TBL PartTbl[128];
}VTOY_GPT_INFO;
typedef struct VTOY_BK_GPT_INFO
{
VTOY_GPT_PART_TBL PartTbl[128];
VTOY_GPT_HDR Head;
}VTOY_BK_GPT_INFO;
COMPILE_ASSERT(sizeof(VTOY_GPT_INFO) == 512 * 34);
COMPILE_ASSERT(sizeof(VTOY_BK_GPT_INFO) == 512 * 33);
#pragma pack()
void DumpGuid(const char *prefix, GUID *guid)
{
printf("%s: %08x-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n",
prefix,
guid->data1, guid->data2, guid->data3,
guid->data4[0], guid->data4[1], guid->data4[2], guid->data4[3],
guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]
);
}
void DumpHead(VTOY_GPT_HDR *pHead)
{
UINT32 CrcRead;
UINT32 CrcCalc;
printf("Signature:<%s>\n", pHead->Signature);
printf("Version:<%02x %02x %02x %02x>\n", pHead->Version[0], pHead->Version[1], pHead->Version[2], pHead->Version[3]);
printf("Length:%u\n", pHead->Length);
printf("Crc:0x%08x\n", pHead->Crc);
printf("EfiStartLBA:%lu\n", pHead->EfiStartLBA);
printf("EfiBackupLBA:%lu\n", pHead->EfiBackupLBA);
printf("PartAreaStartLBA:%lu\n", pHead->PartAreaStartLBA);
printf("PartAreaEndLBA:%lu\n", pHead->PartAreaEndLBA);
DumpGuid("DiskGuid", &pHead->DiskGuid);
printf("PartTblStartLBA:%lu\n", pHead->PartTblStartLBA);
printf("PartTblTotNum:%u\n", pHead->PartTblTotNum);
printf("PartTblEntryLen:%u\n", pHead->PartTblEntryLen);
printf("PartTblCrc:0x%08x\n", pHead->PartTblCrc);
CrcRead = pHead->Crc;
pHead->Crc = 0;
CrcCalc = VtoyCrc32(pHead, pHead->Length);
if (CrcCalc != CrcRead)
{
printf("Head CRC Check Failed\n");
}
else
{
printf("Head CRC Check SUCCESS [%x] [%x]\n", CrcCalc, CrcRead);
}
CrcRead = pHead->PartTblCrc;
CrcCalc = VtoyCrc32(pHead + 1, pHead->PartTblEntryLen * pHead->PartTblTotNum);
if (CrcCalc != CrcRead)
{
printf("Part Table CRC Check Failed\n");
}
else
{
printf("Part Table CRC Check SUCCESS [%x] [%x]\n", CrcCalc, CrcRead);
}
}
void DumpPartTable(VTOY_GPT_PART_TBL *Tbl)
{
int i;
DumpGuid("PartType", &Tbl->PartType);
DumpGuid("PartGuid", &Tbl->PartGuid);
printf("StartLBA:%lu\n", Tbl->StartLBA);
printf("LastLBA:%lu\n", Tbl->LastLBA);
printf("Attr:0x%lx\n", Tbl->Attr);
printf("Name:");
for (i = 0; i < 36 && Tbl->Name[i]; i++)
{
printf("%c", (CHAR)(Tbl->Name[i]));
}
printf("\n");
}
void DumpMBR(MBR_HEAD *pMBR)
{
int i;
for (i = 0; i < 4; i++)
{
printf("=========== Partition Table %d ============\n", i + 1);
printf("PartTbl.Active = 0x%x\n", pMBR->PartTbl[i].Active);
printf("PartTbl.FsFlag = 0x%x\n", pMBR->PartTbl[i].FsFlag);
printf("PartTbl.StartSectorId = %u\n", pMBR->PartTbl[i].StartSectorId);
printf("PartTbl.SectorCount = %u\n", pMBR->PartTbl[i].SectorCount);
printf("PartTbl.StartHead = %u\n", pMBR->PartTbl[i].StartHead);
printf("PartTbl.StartSector = %u\n", pMBR->PartTbl[i].StartSector);
printf("PartTbl.StartCylinder = %u\n", pMBR->PartTbl[i].StartCylinder);
printf("PartTbl.EndHead = %u\n", pMBR->PartTbl[i].EndHead);
printf("PartTbl.EndSector = %u\n", pMBR->PartTbl[i].EndSector);
printf("PartTbl.EndCylinder = %u\n", pMBR->PartTbl[i].EndCylinder);
}
}
int DumpGptInfo(VTOY_GPT_INFO *pGptInfo)
{
int i;
DumpMBR(&pGptInfo->MBR);
DumpHead(&pGptInfo->Head);
for (i = 0; i < 128; i++)
{
if (pGptInfo->PartTbl[i].StartLBA == 0)
{
break;
}
printf("=====Part %d=====\n", i);
DumpPartTable(pGptInfo->PartTbl + i);
}
return 0;
}
#define VENTOY_EFI_PART_ATTR 0xC000000000000001ULL
int main(int argc, const char **argv)
{
int i;
int fd;
UINT64 DiskSize;
CHAR16 *Name = NULL;
VTOY_GPT_INFO *pMainGptInfo = NULL;
VTOY_BK_GPT_INFO *pBackGptInfo = NULL;
if (argc != 3)
{
printf("usage: vtoygpt -f /dev/sdb\n");
return 1;
}
fd = open(argv[2], O_RDWR);
if (fd < 0)
{
printf("Failed to open %s\n", argv[2]);
return 1;
}
pMainGptInfo = malloc(sizeof(VTOY_GPT_INFO));
pBackGptInfo = malloc(sizeof(VTOY_BK_GPT_INFO));
if (NULL == pMainGptInfo || NULL == pBackGptInfo)
{
close(fd);
return 1;
}
read(fd, pMainGptInfo, sizeof(VTOY_GPT_INFO));
if (argv[1][0] == '-' && argv[1][1] == 'd')
{
DumpGptInfo(pMainGptInfo);
}
else
{
DiskSize = lseek(fd, 0, SEEK_END);
lseek(fd, DiskSize - 33 * 512, SEEK_SET);
read(fd, pBackGptInfo, sizeof(VTOY_BK_GPT_INFO));
Name = pMainGptInfo->PartTbl[1].Name;
if (Name[0] == 'V' && Name[1] == 'T' && Name[2] == 'O' && Name[3] == 'Y')
{
pMainGptInfo->PartTbl[1].Attr = VENTOY_EFI_PART_ATTR;
pMainGptInfo->Head.PartTblCrc = VtoyCrc32(pMainGptInfo->PartTbl, sizeof(pMainGptInfo->PartTbl));
pMainGptInfo->Head.Crc = 0;
pMainGptInfo->Head.Crc = VtoyCrc32(&pMainGptInfo->Head, pMainGptInfo->Head.Length);
pBackGptInfo->PartTbl[1].Attr = VENTOY_EFI_PART_ATTR;
pBackGptInfo->Head.PartTblCrc = VtoyCrc32(pBackGptInfo->PartTbl, sizeof(pBackGptInfo->PartTbl));
pBackGptInfo->Head.Crc = 0;
pBackGptInfo->Head.Crc = VtoyCrc32(&pBackGptInfo->Head, pBackGptInfo->Head.Length);
lseek(fd, 512, SEEK_SET);
write(fd, (UINT8 *)pMainGptInfo + 512, sizeof(VTOY_GPT_INFO) - 512);
lseek(fd, DiskSize - 33 * 512, SEEK_SET);
write(fd, pBackGptInfo, sizeof(VTOY_BK_GPT_INFO));
fsync(fd);
}
}
free(pMainGptInfo);
free(pBackGptInfo);
close(fd);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment