diff --git a/GRUB2/MOD_SRC/grub-2.04/install.sh b/GRUB2/MOD_SRC/grub-2.04/install.sh index 8d9ba4cb..19cffe56 100644 --- a/GRUB2/MOD_SRC/grub-2.04/install.sh +++ b/GRUB2/MOD_SRC/grub-2.04/install.sh @@ -12,7 +12,7 @@ make install PATH=$PATH:$VT_DIR/GRUB2/INSTALL/bin/:$VT_DIR/GRUB2/INSTALL/sbin/ 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" 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" diff --git a/INSTALL/Ventoy2Disk.exe b/INSTALL/Ventoy2Disk.exe index 09511244..5c4f5ae9 100644 Binary files a/INSTALL/Ventoy2Disk.exe and b/INSTALL/Ventoy2Disk.exe differ diff --git a/INSTALL/all_in_one.sh b/INSTALL/all_in_one.sh index 89484e7c..660b63be 100644 --- a/INSTALL/all_in_one.sh +++ b/INSTALL/all_in_one.sh @@ -23,6 +23,8 @@ sh buildlib.sh cd $VTOY_PATH/vtoyfat sh build.sh || exit 1 +cd $VTOY_PATH/vtoygpt +sh build.sh || exit 1 cd $VTOY_PATH/ExFAT sh buidlibfuse.sh || exit 1 diff --git a/INSTALL/grub/grub.cfg b/INSTALL/grub/grub.cfg index 52e8a6b7..6b94d74a 100644 --- a/INSTALL/grub/grub.cfg +++ b/INSTALL/grub/grub.cfg @@ -30,6 +30,29 @@ function ventoy_debug_pause { 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 { configfile $prefix/power.cfg @@ -186,7 +209,7 @@ function uefi_windows_menu_func { ventoy_debug_pause 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} boot else @@ -262,7 +285,7 @@ function uefi_linux_menu_func { vt_linux_chain_data ${1}${chosen_path} 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} boot else @@ -327,7 +350,7 @@ function uefi_iso_menu_func { uefi_linux_menu_func $1 ${chosen_path} fi - terminal_output gfxterm + ventoy_gui_console } function uefi_iso_memdisk { @@ -336,11 +359,11 @@ function uefi_iso_memdisk { echo 'Loading ISO file to memory ...' 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} boot - terminal_output gfxterm + ventoy_gui_console } @@ -527,9 +550,9 @@ function wim_common_menuentry { if [ "$grub_platform" = "pc" ]; then linux16 $vtoy_path/ipxe.krn ${vtdebug_flag} mem:${vtoy_chain_mem_addr}:size:${vtoy_chain_mem_size} 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} - terminal_output gfxterm + ventoy_gui_console fi boot else @@ -545,10 +568,10 @@ function wim_unsupport_menuentry { function efi_common_menuentry { vt_chosen_img_path chosen_path - terminal_output console + ventoy_cli_console chainloader ${iso_path}${chosen_path} boot - terminal_output gfxterm + ventoy_gui_console } function efi_unsupport_menuentry { diff --git a/INSTALL/tool/VentoyWorker.sh b/INSTALL/tool/VentoyWorker.sh index 099b2d55..2fe07e6a 100644 --- a/INSTALL/tool/VentoyWorker.sh +++ b/INSTALL/tool/VentoyWorker.sh @@ -327,22 +327,28 @@ else SHORT_PART2=${PART2#/dev/} 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"') - PART2_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=462 status=none | ./tool/hexdump -n1 -e '1/1 "%02X"') + if [ "$PART1_TYPE" = "EE" ]; then + 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" - 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 + PART1_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=446 status=none | ./tool/hexdump -n1 -e '1/1 "%02X"') + PART2_ACTIVE=$(dd if=$DISK bs=1 count=1 skip=462 status=none | ./tool/hexdump -n1 -e '1/1 "%02X"') + + vtdebug "PART1_ACTIVE=$PART1_ACTIVE PART2_ACTIVE=$PART2_ACTIVE" + 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 - - ./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 sync diff --git a/INSTALL/tool/ventoy_lib.sh b/INSTALL/tool/ventoy_lib.sh index 9e4d45d8..915deaa6 100644 --- a/INSTALL/tool/ventoy_lib.sh +++ b/INSTALL/tool/ventoy_lib.sh @@ -345,11 +345,19 @@ format_ventoy_disk_gpt() { unit s \ mkpart Ventoy ntfs $part1_start_sector $part1_end_sector \ mkpart VTOYEFI fat16 $part2_start_sector $part2_end_sector \ - set 2 boot on \ - set 2 esp on \ + set 2 msftdata on \ set 2 hidden on \ quit + + sync + + if ventoy_is_linux64; then + vtoygpt=./tool/vtoygpt_64 + else + vtoygpt=./tool/vtoygpt_32 + fi + $vtoygpt -f $DISK sync udevadm trigger >/dev/null 2>&1 diff --git a/INSTALL/tool/vtoygpt_32 b/INSTALL/tool/vtoygpt_32 new file mode 100644 index 00000000..127f080c Binary files /dev/null and b/INSTALL/tool/vtoygpt_32 differ diff --git a/INSTALL/tool/vtoygpt_64 b/INSTALL/tool/vtoygpt_64 new file mode 100644 index 00000000..068aaf6e Binary files /dev/null and b/INSTALL/tool/vtoygpt_64 differ diff --git a/Ventoy2Disk/Ventoy2Disk/PartDialog.c b/Ventoy2Disk/Ventoy2Disk/PartDialog.c index b5f737c0..2b30c746 100644 Binary files a/Ventoy2Disk/Ventoy2Disk/PartDialog.c and b/Ventoy2Disk/Ventoy2Disk/PartDialog.c differ diff --git a/Ventoy2Disk/Ventoy2Disk/PhyDrive.c b/Ventoy2Disk/Ventoy2Disk/PhyDrive.c index 572aeb87..1cd00544 100644 --- a/Ventoy2Disk/Ventoy2Disk/PhyDrive.c +++ b/Ventoy2Disk/Ventoy2Disk/PhyDrive.c @@ -1,1942 +1,1952 @@ -/****************************************************************************** - * PhyDrive.c - * - * Copyright (c) 2020, longpanda - * Copyright (c) 2011-2020, Pete Batard - * - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include "resource.h" -#include "Language.h" -#include "Ventoy2Disk.h" -#include "fat_filelib.h" -#include "ff.h" - -/* - * Some code and functions in the file are copied from rufus. - * https://github.com/pbatard/rufus - */ -#define VDS_SET_ERROR SetLastError -#define IVdsServiceLoader_LoadService(This, pwszMachineName, ppService) (This)->lpVtbl->LoadService(This, pwszMachineName, ppService) -#define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This) -#define IVdsService_QueryProviders(This, masks, ppEnum) (This)->lpVtbl->QueryProviders(This, masks, ppEnum) -#define IVdsService_WaitForServiceReady(This) ((This)->lpVtbl->WaitForServiceReady(This)) -#define IVdsService_CleanupObsoleteMountPoints(This) ((This)->lpVtbl->CleanupObsoleteMountPoints(This)) -#define IVdsService_Refresh(This) ((This)->lpVtbl->Refresh(This)) -#define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This)) -#define IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject) -#define IVdsProvider_Release(This) (This)->lpVtbl->Release(This) -#define IVdsSwProvider_QueryPacks(This, ppEnum) (This)->lpVtbl->QueryPacks(This, ppEnum) -#define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This) -#define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum) -#define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties) -#define IVdsDisk_Release(This) (This)->lpVtbl->Release(This) -#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_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_Release(This) (This)->lpVtbl->Release(This) -#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 IVdsVolume_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject) -#define IVdsVolume_Release(This) (This)->lpVtbl->Release(This) -#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_Release(This) (This)->lpVtbl->Release(This) -#define IVdsVolume_GetProperties(This, pVolumeProperties) (This)->lpVtbl->GetProperties(This,pVolumeProperties) -#define IVdsAsync_Cancel(This) (This)->lpVtbl->Cancel(This) -#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_Release(This) (This)->lpVtbl->Release(This) - -#define IUnknown_QueryInterface(This, a, b) (This)->lpVtbl->QueryInterface(This,a,b) -#define IUnknown_Release(This) (This)->lpVtbl->Release(This) - -/* -* 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 -*/ -BOOL DeletePartitions(DWORD DriveIndex, BOOL OnlyPart2) -{ - BOOL r = FALSE; - HRESULT hr; - ULONG ulFetched; - wchar_t wPhysicalName[48]; - IVdsServiceLoader *pLoader; - IVdsService *pService; - IEnumVdsObject *pEnum; - IUnknown *pUnk; - - swprintf_s(wPhysicalName, ARRAYSIZE(wPhysicalName), L"\\\\?\\PhysicalDrive%lu", DriveIndex); - - // Initialize COM - CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, - RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL); - - // Create a VDS Loader Instance - hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, - &IID_IVdsServiceLoader, (void **)&pLoader); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not create VDS Loader Instance: %u", LASTERR); - goto out; - } - - // Load the VDS Service - hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService); - IVdsServiceLoader_Release(pLoader); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not load VDS Service: %u", LASTERR); - goto out; - } - - // Wait for the Service to become ready if needed - hr = IVdsService_WaitForServiceReady(pService); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("VDS Service is not ready: %u", LASTERR); - goto out; - } - - // Query the VDS Service Providers - hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not query VDS Service Providers: %u", LASTERR); - goto out; - } - - while (IEnumVdsObject_Next(pEnum, 1, &pUnk, &ulFetched) == S_OK) { - IVdsProvider *pProvider; - IVdsSwProvider *pSwProvider; - IEnumVdsObject *pEnumPack; - IUnknown *pPackUnk; - - // Get VDS Provider - hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider); - IUnknown_Release(pUnk); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not get VDS Provider: %u", LASTERR); - goto out; - } - - // Get VDS Software Provider - hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider); - IVdsProvider_Release(pProvider); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not get VDS Software Provider: %u", LASTERR); - goto out; - } - - // Get VDS Software Provider Packs - hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack); - IVdsSwProvider_Release(pSwProvider); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not get VDS Software Provider Packs: %u", LASTERR); - goto out; - } - - // Enumerate Provider Packs - while (IEnumVdsObject_Next(pEnumPack, 1, &pPackUnk, &ulFetched) == S_OK) { - IVdsPack *pPack; - IEnumVdsObject *pEnumDisk; - IUnknown *pDiskUnk; - - hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack); - IUnknown_Release(pPackUnk); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not query VDS Software Provider Pack: %u", LASTERR); - goto out; - } - - // Use the pack interface to access the disks - hr = IVdsPack_QueryDisks(pPack, &pEnumDisk); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not query VDS disks: %u", LASTERR); - goto out; - } - - // List disks - while (IEnumVdsObject_Next(pEnumDisk, 1, &pDiskUnk, &ulFetched) == S_OK) { - VDS_DISK_PROP diskprop; - VDS_PARTITION_PROP* prop_array; - LONG i, prop_array_size; - IVdsDisk *pDisk; - IVdsAdvancedDisk *pAdvancedDisk; - - // Get the disk interface. - hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not query VDS Disk Interface: %u", LASTERR); - goto out; - } - - // Get the disk properties - hr = IVdsDisk_GetProperties(pDisk, &diskprop); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not query VDS Disk Properties: %u", LASTERR); - goto out; - } - - // Isolate the disk we want - if (_wcsicmp(wPhysicalName, diskprop.pwszName) != 0) { - IVdsDisk_Release(pDisk); - continue; - } - - // Instantiate the AdvanceDisk interface for our disk. - hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk); - IVdsDisk_Release(pDisk); - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not access VDS Advanced Disk interface: %u", LASTERR); - goto out; - } - - // 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); - if (hr == S_OK) { - Log("Deleting ALL partition(s) from disk '%S':", diskprop.pwszName); - // Now go through each partition - for (i = 0; i < prop_array_size; i++) { - - Log("* Partition %d (offset: %lld, size: %llu)", prop_array[i].ulPartitionNumber, - prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize); - - if (OnlyPart2 && prop_array[i].ullOffset == 2048*512) - { - Log("Skip this partition..."); - continue; - } - - - hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE); - if (hr != S_OK) { - r = FALSE; - VDS_SET_ERROR(hr); - Log("Could not delete partitions: %u", LASTERR); - } - } - r = TRUE; - } - else { - Log("No partition to delete on disk '%S'", diskprop.pwszName); - r = TRUE; - } - CoTaskMemFree(prop_array); - -#if 0 - // Issue a Clean while we're at it - HRESULT hr2 = E_FAIL; - ULONG completed; - IVdsAsync* pAsync; - hr = IVdsAdvancedDisk_Clean(pAdvancedDisk, TRUE, FALSE, FALSE, &pAsync); - while (SUCCEEDED(hr)) { - if (IS_ERROR(FormatStatus)) { - IVdsAsync_Cancel(pAsync); - break; - } - hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed); - if (SUCCEEDED(hr)) { - hr = hr2; - if (hr == S_OK) - break; - if (hr == VDS_E_OPERATION_PENDING) - hr = S_OK; - } - Sleep(500); - } - if (hr != S_OK) { - VDS_SET_ERROR(hr); - Log("Could not clean disk: %s", LASTERR); - } -#endif - IVdsAdvancedDisk_Release(pAdvancedDisk); - goto out; - } - } - } - -out: - return r; -} - - -static DWORD GetVentoyVolumeName(int PhyDrive, UINT32 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash) -{ - size_t len; - BOOL bRet; - DWORD dwSize; - HANDLE hDrive; - HANDLE hVolume; - UINT64 PartOffset; - DWORD Status = ERROR_NOT_FOUND; - DISK_EXTENT *pExtents = NULL; - CHAR VolumeName[MAX_PATH] = { 0 }; - VOLUME_DISK_EXTENTS DiskExtents; - - PartOffset = 512ULL * StartSectorId; - - Log("GetVentoyVolumeName PhyDrive %d SectorStart:%u PartOffset:%llu", PhyDrive, StartSectorId, (ULONGLONG)PartOffset); - - hVolume = FindFirstVolumeA(VolumeName, sizeof(VolumeName)); - if (hVolume == INVALID_HANDLE_VALUE) - { - return 1; - } - - do { - - len = strlen(VolumeName); - Log("Find volume:%s", VolumeName); - - VolumeName[len - 1] = 0; - - hDrive = CreateFileA(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hDrive == INVALID_HANDLE_VALUE) - { - continue; - } - - bRet = DeviceIoControl(hDrive, - IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, - NULL, - 0, - &DiskExtents, - (DWORD)(sizeof(DiskExtents)), - (LPDWORD)&dwSize, - NULL); - - Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet, LASTERR); - Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents.NumberOfDiskExtents, DiskExtents.Extents[0].DiskNumber); - - if (bRet && DiskExtents.NumberOfDiskExtents == 1) - { - pExtents = DiskExtents.Extents; - - Log("This volume DiskNumber:%u offset:%llu", pExtents->DiskNumber, (ULONGLONG)pExtents->StartingOffset.QuadPart); - if ((int)pExtents->DiskNumber == PhyDrive && pExtents->StartingOffset.QuadPart == PartOffset) - { - Log("This volume match"); - - if (!DelSlash) - { - VolumeName[len - 1] = '\\'; - } - - sprintf_s(NameBuf, BufLen, "%s", VolumeName); - Status = ERROR_SUCCESS; - CloseHandle(hDrive); - break; - } - } - - CloseHandle(hDrive); - } while (FindNextVolumeA(hVolume, VolumeName, sizeof(VolumeName))); - - FindVolumeClose(hVolume); - - Log("GetVentoyVolumeName return %u", Status); - return Status; -} - -static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length) -{ - int n = 0; - DWORD DataSize = 0; - CHAR *Pos = NULL; - CHAR *StringBuf = NULL; - - DataSize = GetLogicalDriveStringsA(0, NULL); - StringBuf = (CHAR *)malloc(DataSize + 1); - if (StringBuf == NULL) - { - return 1; - } - - GetLogicalDriveStringsA(DataSize, StringBuf); - - for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1) - { - if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0])) - { - Log("%C: is belong to phydrive%d", Pos[0], PhyDrive); - DriveLetters[n++] = Pos[0]; - } - } - - free(StringBuf); - return 0; -} - -static HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare) -{ - int i; - DWORD dwSize; - DWORD LastError; - UINT64 EndTime; - HANDLE hDrive = INVALID_HANDLE_VALUE; - CHAR PhyDrive[128]; - CHAR DevPath[MAX_PATH] = { 0 }; - - safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", Drive); - - if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath))) - { - Log("QueryDosDeviceA failed error:%u", GetLastError()); - strcpy_s(DevPath, sizeof(DevPath), "???"); - } - else - { - Log("QueryDosDeviceA success %s", DevPath); - } - - for (i = 0; i < DRIVE_ACCESS_RETRIES; i++) - { - // 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. - // 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 - // required for enumeration. - hDrive = CreateFileA(PhyDrive, - GENERIC_READ | (bWriteAccess ? GENERIC_WRITE : 0), - FILE_SHARE_READ | (bWriteShare ? FILE_SHARE_WRITE : 0), - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, - NULL); - - LastError = GetLastError(); - Log("[%d] CreateFileA %s code:%u %p", i, PhyDrive, LastError, hDrive); - - if (hDrive != INVALID_HANDLE_VALUE) - { - break; - } - - if ((LastError != ERROR_SHARING_VIOLATION) && (LastError != ERROR_ACCESS_DENIED)) - { - break; - } - - if (i == 0) - { - Log("Waiting for access on %s [%s]...", PhyDrive, DevPath); - } - 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... - Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled..."); - bWriteShare = TRUE; - - // Try to report the process that is locking the drive - // 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; - - } - Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES); - } - - if (hDrive == INVALID_HANDLE_VALUE) - { - Log("Could not open %s %u", PhyDrive, LASTERR); - goto End; - } - - if (bWriteAccess) - { - Log("Opened %s for %s write access", PhyDrive, bWriteShare ? "shared" : "exclusive"); - } - - if (bLockDrive) - { - if (DeviceIoControl(hDrive, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwSize, NULL)) - { - Log("I/O boundary checks disabled"); - } - - EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT; - - do { - if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL)) - { - Log("FSCTL_LOCK_VOLUME success"); - goto End; - } - Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES); - } while (GetTickCount64() < EndTime); - - // 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); - - // See if we can report the processes are accessing the drive - //if (!IS_ERROR(FormatStatus) && (access_mask == 0)) - // access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE); - // Try to continue if the only access rights we saw were for read-only - //if ((access_mask & 0x07) != 0x01) - // safe_closehandle(hDrive); - - CHECK_CLOSE_HANDLE(hDrive); - } - -End: - - if (hDrive == INVALID_HANDLE_VALUE) - { - Log("Can get handle of %s, maybe some process control it.", DevPath); - } - - return hDrive; -} - -int GetPhyDriveByLogicalDrive(int DriveLetter) -{ - BOOL Ret; - DWORD dwSize; - HANDLE Handle; - VOLUME_DISK_EXTENTS DiskExtents; - CHAR PhyPath[128]; - - safe_sprintf(PhyPath, "\\\\.\\%C:", (CHAR)DriveLetter); - - Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); - if (Handle == INVALID_HANDLE_VALUE) - { - Log("Could not open the disk<%s>, error:%u", PhyPath, LASTERR); - return -1; - } - - Ret = DeviceIoControl(Handle, - IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, - NULL, - 0, - &DiskExtents, - (DWORD)(sizeof(DiskExtents)), - (LPDWORD)&dwSize, - NULL); - - if (!Ret || DiskExtents.NumberOfDiskExtents == 0) - { - Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, LASTERR); - CHECK_CLOSE_HANDLE(Handle); - return -1; - } - CHECK_CLOSE_HANDLE(Handle); - - Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu", - PhyPath, - DiskExtents.Extents[0].DiskNumber, - DiskExtents.Extents[0].StartingOffset.QuadPart, - DiskExtents.Extents[0].ExtentLength.QuadPart - ); - - return (int)DiskExtents.Extents[0].DiskNumber; -} - -int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount) -{ - int i; - int Count; - int id; - int Letter = 'A'; - BOOL bRet; - DWORD dwBytes; - DWORD DriveCount = 0; - HANDLE Handle = INVALID_HANDLE_VALUE; - CHAR PhyDrive[128]; - PHY_DRIVE_INFO *CurDrive = pDriveList; - GET_LENGTH_INFORMATION LengthInfo; - STORAGE_PROPERTY_QUERY Query; - STORAGE_DESCRIPTOR_HEADER DevDescHeader; - STORAGE_DEVICE_DESCRIPTOR *pDevDesc; - int PhyDriveId[VENTOY_MAX_PHY_DRIVE]; - - Count = GetPhysicalDriveCount(); - - for (i = 0; i < Count && i < VENTOY_MAX_PHY_DRIVE; i++) - { - PhyDriveId[i] = i; - } - - dwBytes = GetLogicalDrives(); - Log("Logical Drives: 0x%x", dwBytes); - while (dwBytes) - { - if (dwBytes & 0x01) - { - id = GetPhyDriveByLogicalDrive(Letter); - Log("%C --> %d", Letter, id); - if (id >= 0) - { - for (i = 0; i < Count; i++) - { - if (PhyDriveId[i] == id) - { - break; - } - } - - if (i >= Count) - { - Log("Add phy%d to list", i); - PhyDriveId[Count] = id; - Count++; - } - } - } - - Letter++; - dwBytes >>= 1; - } - - for (i = 0; i < Count && DriveCount < VENTOY_MAX_PHY_DRIVE; i++) - { - CHECK_CLOSE_HANDLE(Handle); - - safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", PhyDriveId[i]); - Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR); - - if (Handle == INVALID_HANDLE_VALUE) - { - continue; - } - - bRet = DeviceIoControl(Handle, - IOCTL_DISK_GET_LENGTH_INFO, NULL, - 0, - &LengthInfo, - sizeof(LengthInfo), - &dwBytes, - NULL); - if (!bRet) - { - Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR); - continue; - } - - Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart); - - Query.PropertyId = StorageDeviceProperty; - Query.QueryType = PropertyStandardQuery; - - bRet = DeviceIoControl(Handle, - IOCTL_STORAGE_QUERY_PROPERTY, - &Query, - sizeof(Query), - &DevDescHeader, - sizeof(STORAGE_DESCRIPTOR_HEADER), - &dwBytes, - NULL); - if (!bRet) - { - Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes); - continue; - } - - if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR)) - { - Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size); - continue; - } - - pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size); - if (!pDevDesc) - { - Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size); - continue; - } - - bRet = DeviceIoControl(Handle, - IOCTL_STORAGE_QUERY_PROPERTY, - &Query, - sizeof(Query), - pDevDesc, - DevDescHeader.Size, - &dwBytes, - NULL); - if (!bRet) - { - Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes); - free(pDevDesc); - continue; - } - - CurDrive->PhyDrive = i; - CurDrive->SizeInBytes = LengthInfo.Length.QuadPart; - CurDrive->DeviceType = pDevDesc->DeviceType; - CurDrive->RemovableMedia = pDevDesc->RemovableMedia; - CurDrive->BusType = pDevDesc->BusType; - - if (pDevDesc->VendorIdOffset) - { - safe_strcpy(CurDrive->VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset); - TrimString(CurDrive->VendorId); - } - - if (pDevDesc->ProductIdOffset) - { - safe_strcpy(CurDrive->ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset); - TrimString(CurDrive->ProductId); - } - - if (pDevDesc->ProductRevisionOffset) - { - safe_strcpy(CurDrive->ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset); - TrimString(CurDrive->ProductRev); - } - - if (pDevDesc->SerialNumberOffset) - { - safe_strcpy(CurDrive->SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset); - TrimString(CurDrive->SerialNumber); - } - - CurDrive++; - DriveCount++; - - free(pDevDesc); - - CHECK_CLOSE_HANDLE(Handle); - } - - for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++) - { - Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s", - CurDrive->PhyDrive, GetBusTypeString(CurDrive->BusType), CurDrive->RemovableMedia, - GetHumanReadableGBSize(CurDrive->SizeInBytes), CurDrive->SizeInBytes, - CurDrive->VendorId, CurDrive->ProductId); - } - - *pDriveCount = DriveCount; - - return 0; -} - - -static HANDLE g_FatPhyDrive; -static UINT64 g_Part2StartSec; -static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen) -{ - int rc = 1; - int size = 0; - char *buf = NULL; - void *flfile = NULL; - - flfile = fl_fopen("/grub/grub.cfg", "rb"); - if (flfile) - { - fl_fseek(flfile, 0, SEEK_END); - size = (int)fl_ftell(flfile); - - fl_fseek(flfile, 0, SEEK_SET); - - buf = (char *)malloc(size + 1); - if (buf) - { - fl_fread(buf, 1, size, flfile); - buf[size] = 0; - - rc = 0; - sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf)); - free(buf); - } - - fl_fclose(flfile); - } - - return rc; -} - -static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount) -{ - DWORD dwSize; - BOOL bRet; - DWORD ReadSize; - LARGE_INTEGER liCurrentPosition; - - liCurrentPosition.QuadPart = Sector + g_Part2StartSec; - liCurrentPosition.QuadPart *= 512; - SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN); - - ReadSize = (DWORD)(SectorCount * 512); - - bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL); - if (bRet == FALSE || dwSize != ReadSize) - { - Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, LASTERR); - } - - return 1; -} - - -int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen) -{ - int rc = 0; - HANDLE hDrive; - - hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE); - if (hDrive == INVALID_HANDLE_VALUE) - { - return 1; - } - - g_FatPhyDrive = hDrive; - g_Part2StartSec = Part2StartSector; - - Log("Parse FAT fs..."); - - fl_init(); - - if (0 == fl_attach_media(VentoyFatDiskRead, NULL)) - { - rc = GetVentoyVersionFromFatFile(VerBuf, BufLen); - } - else - { - rc = 1; - } - - fl_shutdown(); - - CHECK_CLOSE_HANDLE(hDrive); - - return rc; -} - - - - - -static unsigned int g_disk_unxz_len = 0; -static BYTE *g_part_img_pos = NULL; -static BYTE *g_part_img_buf[VENTOY_EFI_PART_SIZE / SIZE_1MB]; - - -static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount) -{ - uint32 i; - uint32 offset; - BYTE *MbBuf = NULL; - - for (i = 0; i < SectorCount; i++) - { - offset = (Sector + i) * 512; - - if (g_part_img_buf[1] == NULL) - { - MbBuf = g_part_img_buf[0] + offset; - memcpy(Buffer + i * 512, MbBuf, 512); - } - else - { - MbBuf = g_part_img_buf[offset / SIZE_1MB]; - memcpy(Buffer + i * 512, MbBuf + (offset % SIZE_1MB), 512); - } - } - - return 1; -} - - -static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount) -{ - uint32 i; - uint32 offset; - BYTE *MbBuf = NULL; - - for (i = 0; i < SectorCount; i++) - { - offset = (Sector + i) * 512; - - if (g_part_img_buf[1] == NULL) - { - MbBuf = g_part_img_buf[0] + offset; - memcpy(MbBuf, Buffer + i * 512, 512); - } - else - { - MbBuf = g_part_img_buf[offset / SIZE_1MB]; - memcpy(MbBuf + (offset % SIZE_1MB), Buffer + i * 512, 512); - } - } - - return 1; -} - -int VentoyProcSecureBoot(BOOL SecureBoot) -{ - int rc = 0; - int size; - char *filebuf = NULL; - void *file = NULL; - - Log("VentoyProcSecureBoot %d ...", SecureBoot); - - if (SecureBoot) - { - Log("Secure boot is enabled ..."); - return 0; - } - - fl_init(); - - if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite)) - { - file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb"); - Log("Open ventoy efi file %p ", file); - if (file) - { - fl_fseek(file, 0, SEEK_END); - size = (int)fl_ftell(file); - fl_fseek(file, 0, SEEK_SET); - - Log("ventoy efi file size %d ...", size); - - filebuf = (char *)malloc(size); - if (filebuf) - { - fl_fread(filebuf, 1, size, file); - } - - fl_fclose(file); - - Log("Now delete all efi files ..."); - fl_remove("/EFI/BOOT/BOOTX64.EFI"); - fl_remove("/EFI/BOOT/grubx64.efi"); - fl_remove("/EFI/BOOT/grubx64_real.efi"); - fl_remove("/EFI/BOOT/MokManager.efi"); - - file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb"); - Log("Open bootx64 efi file %p ", file); - if (file) - { - if (filebuf) - { - fl_fwrite(filebuf, 1, size, file); - } - - fl_fflush(file); - fl_fclose(file); - } - - if (filebuf) - { - free(filebuf); - } - } - } - else - { - rc = 1; - } - - fl_shutdown(); - - return rc; -} - - - -static int disk_xz_flush(void *src, unsigned int size) -{ - unsigned int i; - BYTE *buf = (BYTE *)src; - - for (i = 0; i < size; i++) - { - *g_part_img_pos = *buf++; - - 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]; - } - else - { - g_part_img_pos++; - } - } - - return (int)size; -} - -static void unxz_error(char *x) -{ - Log("%s", x); -} - -static BOOL TryWritePart2(HANDLE hDrive, UINT64 StartSectorId) -{ - BOOL bRet; - DWORD TrySize = 16 * 1024; - DWORD dwSize; - BYTE *Buffer = NULL; - unsigned char *data = NULL; - LARGE_INTEGER liCurrentPosition; - - liCurrentPosition.QuadPart = StartSectorId * 512; - SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN); - - Buffer = malloc(TrySize); - - bRet = WriteFile(hDrive, Buffer, TrySize, &dwSize, NULL); - - free(Buffer); - - Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR); - - if (bRet && dwSize == TrySize) - { - return TRUE; - } - - return FALSE; -} - -static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId) -{ - int i; - int rc = 0; - int len = 0; - int writelen = 0; - int partwrite = 0; - DWORD dwSize = 0; - BOOL bRet; - unsigned char *data = NULL; - LARGE_INTEGER liCurrentPosition; - LARGE_INTEGER liNewPosition; - - Log("FormatPart2Fat %llu...", StartSectorId); - - rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&data, &len); - if (rc) - { - Log("Failed to read img file %p %u", data, len); - return 1; - } - - liCurrentPosition.QuadPart = StartSectorId * 512; - SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN); - - Log("Set file pointer: %llu New pointer:%llu", liCurrentPosition.QuadPart, liNewPosition.QuadPart); - - 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]) - { - Log("Malloc whole img buffer success, now decompress ..."); - unxz(data, len, NULL, NULL, g_part_img_buf[0], &writelen, unxz_error); - - if (len == writelen) - { - Log("decompress finished success"); - - VentoyProcSecureBoot(g_SecureBoot); - - 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); - Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR); - - if (!bRet) - { - rc = 1; - goto End; - } - - PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i); - } - } - else - { - rc = 1; - Log("decompress finished failed"); - goto End; - } - } - else - { - 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++) - { - g_part_img_buf[i] = (BYTE *)malloc(SIZE_1MB); - if (g_part_img_buf[i] == NULL) - { - rc = 1; - goto End; - } - } - - Log("Malloc part img buffer success, now decompress ..."); - - g_part_img_pos = g_part_img_buf[0]; - - unxz(data, len, NULL, disk_xz_flush, NULL, NULL, unxz_error); - - if (g_disk_unxz_len == VENTOY_EFI_PART_SIZE) - { - Log("decompress finished success"); - - VentoyProcSecureBoot(g_SecureBoot); - - 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); - Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR); - - if (!bRet) - { - rc = 1; - goto End; - } - - PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i); - } - } - else - { - rc = 1; - Log("decompress finished failed"); - goto End; - } - } - -End: - - if (data) free(data); - - if (partwrite) - { - for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++) - { - if (g_part_img_buf[i]) free(g_part_img_buf[i]); - } - } - else - { - if (g_part_img_buf[0]) free(g_part_img_buf[0]); - } - - return rc; -} - -static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle) -{ - int Len = 0; - int readLen = 0; - BOOL bRet; - DWORD dwSize; - BYTE *ImgBuf = NULL; - BYTE *RawBuf = NULL; - - Log("WriteGrubStage1ToPhyDrive ..."); - - RawBuf = (BYTE *)malloc(SIZE_1MB); - if (!RawBuf) - { - return 1; - } - - if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len)) - { - Log("Failed to read stage1 img"); - free(RawBuf); - return 1; - } - - unxz(ImgBuf, Len, NULL, NULL, RawBuf, &readLen, unxz_error); - - if (PartStyle) - { - Log("Write GPT stage1 ..."); - RawBuf[500] = 35;//update blocklist - SetFilePointer(hDrive, 512 * 34, NULL, FILE_BEGIN); - bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512 * 34, &dwSize, NULL); - } - else - { - Log("Write MBR stage1 ..."); - 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()); - - free(RawBuf); - free(ImgBuf); - return 0; -} - - - -static int FormatPart1exFAT(UINT64 DiskSizeBytes) -{ - MKFS_PARM Option; - FRESULT Ret; - FATFS fs; - - Option.fmt = FM_EXFAT; - Option.n_fat = 1; - Option.align = 8; - Option.n_root = 1; - - // < 32GB select 32KB as cluster size - // > 32GB select 128KB as cluster size - if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32) - { - Option.au_size = 32768; - } - else - { - Option.au_size = 131072; - } - - Log("Formatting Part1 exFAT ..."); - - Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024); - - if (FR_OK == Ret) - { - Log("Formatting Part1 exFAT success"); - - Ret = f_mount(&fs, TEXT("0:"), 1); - Log("mount part %d", Ret); - - if (FR_OK == Ret) - { - Ret = f_setlabel(TEXT("Ventoy")); - Log("f_setlabel %d", Ret); - - Ret = f_mount(0, TEXT("0:"), 1); - Log("umount part %d", Ret); - return 0; - } - else - { - Log("mount exfat failed %d", Ret); - return 1; - } - } - else - { - Log("Formatting Part1 exFAT failed"); - return 1; - } -} - - - -int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter) -{ - int i; - int rc = 0; - int state = 0; - HANDLE hDrive; - DWORD dwSize; - BOOL bRet; - CHAR MountDrive; - CHAR DriveName[] = "?:\\"; - CHAR DriveLetters[MAX_PATH] = { 0 }; - LARGE_INTEGER liCurrentPosition; - char *pTmpBuf = NULL; - MBR_HEAD MBR; - - *pDrvLetter = 0; - - Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>", - pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, - GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); - - PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); - - Log("Lock disk for clean ............................. "); - - hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE); - if (hDrive == INVALID_HANDLE_VALUE) - { - Log("Failed to open physical disk"); - return 1; - } - - GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); - - if (DriveLetters[0] == 0) - { - Log("No drive letter was assigned..."); - DriveName[0] = GetFirstUnusedDriveLetter(); - Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]); - } - else - { - // Unmount all mounted volumes that belong to this drive - // Do it in reverse so that we always end on the first volume letter - for (i = (int)strlen(DriveLetters); i > 0; i--) - { - DriveName[0] = DriveLetters[i - 1]; - bRet = DeleteVolumeMountPointA(DriveName); - Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError()); - } - } - - MountDrive = DriveName[0]; - Log("Will use '%C:' as volume mountpoint", DriveName[0]); - - // It kind of blows, but we have to relinquish access to the physical drive - // for VDS to be able to delete the partitions that reside on it... - DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); - CHECK_CLOSE_HANDLE(hDrive); - - PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART); - - if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE)) - { - Log("Notice: Could not delete partitions: %u", GetLastError()); - } - - Log("Deleting all partitions ......................... OK"); - - PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE); - - Log("Lock disk for write ............................. "); - hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); - if (hDrive == INVALID_HANDLE_VALUE) - { - Log("Failed to GetPhysicalHandle for write."); - rc = 1; - goto End; - } - - // clear first and last 1MB space - pTmpBuf = malloc(SIZE_1MB); - if (!pTmpBuf) - { - Log("Failed to alloc memory."); - rc = 1; - goto End; - } - memset(pTmpBuf, 0, SIZE_1MB); - - SET_FILE_POS(512); - bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB - 512, &dwSize, NULL); - Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR); - if (!bRet) - { - rc = 1; - goto End; - } - - SET_FILE_POS(SIZE_1MB); - bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB, &dwSize, NULL); - Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR); - if (!bRet) - { - rc = 1; - goto End; - } - - SET_FILE_POS(0); - bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL); - Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR); - if (!bRet) - { - rc = 1; - goto End; - } - - //clear boot code and partition table (reserved disk signature) - memset(MBR.BootCode, 0, 440); - memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl)); - - VentoyFillLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl); - - MBR.PartTbl[0].Active = 0x00; // bootable - MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS - - SET_FILE_POS(0); - bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL); - Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR); - if (!bRet) - { - rc = 1; - goto End; - } - - Log("Clear Ventoy successfully finished"); - - //Refresh Drive Layout - DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); - -End: - - PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME); - - if (pTmpBuf) - { - free(pTmpBuf); - } - - if (rc == 0) - { - Log("Mounting Ventoy Partition ....................... "); - Sleep(1000); - - state = 0; - memset(DriveLetters, 0, sizeof(DriveLetters)); - GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); - Log("Logical drive letter after write ventoy: <%s>", DriveLetters); - - for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++) - { - DriveName[0] = DriveLetters[i]; - Log("%s is ventoy part1, already mounted", DriveName); - state = 1; - } - - if (state != 1) - { - Log("need to mount ventoy part1..."); - if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE)) - { - DriveName[0] = MountDrive; - bRet = SetVolumeMountPointA(DriveName, DriveLetters); - Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError()); - - *pDrvLetter = MountDrive; - } - else - { - Log("Failed to find ventoy volume"); - } - } - - Log("OK\n"); - } - else - { - FindProcessOccupyDisk(hDrive, pPhyDrive); - } - - CHECK_CLOSE_HANDLE(hDrive); - return rc; -} - -int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle) -{ - int i; - int rc = 0; - int state = 0; - HANDLE hDrive; - DWORD dwSize; - BOOL bRet; - CHAR MountDrive; - CHAR DriveName[] = "?:\\"; - CHAR DriveLetters[MAX_PATH] = { 0 }; - 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, - GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); - - if (PartStyle) - { - pGptInfo = malloc(sizeof(VTOY_GPT_INFO)); - memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO)); - } - - PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); - - VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle);//also used to format 1st partition in GPT mode - if (PartStyle) - { - VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo); - } - - Log("Lock disk for clean ............................. "); - - hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE); - if (hDrive == INVALID_HANDLE_VALUE) - { - Log("Failed to open physical disk"); - free(pGptInfo); - return 1; - } - - GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); - - if (DriveLetters[0] == 0) - { - Log("No drive letter was assigned..."); - DriveName[0] = GetFirstUnusedDriveLetter(); - Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]); - } - else - { - // Unmount all mounted volumes that belong to this drive - // Do it in reverse so that we always end on the first volume letter - for (i = (int)strlen(DriveLetters); i > 0; i--) - { - DriveName[0] = DriveLetters[i - 1]; - bRet = DeleteVolumeMountPointA(DriveName); - Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError()); - } - } - - MountDrive = DriveName[0]; - Log("Will use '%C:' as volume mountpoint", DriveName[0]); - - // It kind of blows, but we have to relinquish access to the physical drive - // for VDS to be able to delete the partitions that reside on it... - DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); - CHECK_CLOSE_HANDLE(hDrive); - - PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART); - - if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE)) - { - Log("Notice: Could not delete partitions: %u", GetLastError()); - } - - Log("Deleting all partitions ......................... OK"); - - PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE); - - Log("Lock disk for write ............................. "); - hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); - if (hDrive == INVALID_HANDLE_VALUE) - { - Log("Failed to GetPhysicalHandle for write."); - rc = 1; - goto End; - } - - //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); - - PROGRESS_BAR_SET_POS(PT_FORMAT_PART1); - - Log("Formatting part1 exFAT ..."); - if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes)) - { - Log("FormatPart1exFAT failed."); - rc = 1; - goto End; - } - - PROGRESS_BAR_SET_POS(PT_FORMAT_PART2); - Log("Writing part2 FAT img ..."); - if (0 != FormatPart2Fat(hDrive, MBR.PartTbl[1].StartSectorId)) - { - Log("FormatPart2Fat failed."); - rc = 1; - goto End; - } - - PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG); - Log("Writting Boot Image ............................. "); - if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0) - { - Log("WriteGrubStage1ToPhyDrive failed."); - rc = 1; - goto End; - } - - PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE); - Log("Writting Partition Table ........................ "); - SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); - - if (PartStyle) - { - VTOY_GPT_HDR BackupHead; - LARGE_INTEGER liCurrentPosition; - - SET_FILE_POS(pPhyDrive->SizeInBytes - 512); - VentoyFillBackupGptHead(pGptInfo, &BackupHead); - if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL)) - { - rc = 1; - Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError()); - goto End; - } - - SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33); - if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL)) - { - rc = 1; - Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError()); - goto End; - } - - SET_FILE_POS(0); - if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL)) - { - rc = 1; - Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError()); - goto End; - } - - Log("Write GPT Info OK ..."); - } - else - { - if (!WriteFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL)) - { - rc = 1; - Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize, GetLastError()); - goto End; - } - Log("Write MBR OK ..."); - } - - - //Refresh Drive Layout - DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); - -End: - - PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME); - - if (rc == 0) - { - Log("Mounting Ventoy Partition ....................... "); - Sleep(1000); - - state = 0; - memset(DriveLetters, 0, sizeof(DriveLetters)); - GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); - Log("Logical drive letter after write ventoy: <%s>", DriveLetters); - - for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++) - { - DriveName[0] = DriveLetters[i]; - if (IsVentoyLogicalDrive(DriveName[0])) - { - Log("%s is ventoy part2, delete mountpoint", DriveName); - DeleteVolumeMountPointA(DriveName); - } - else - { - Log("%s is ventoy part1, already mounted", DriveName); - state = 1; - } - } - - if (state != 1) - { - Log("need to mount ventoy part1..."); - if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE)) - { - DriveName[0] = MountDrive; - bRet = SetVolumeMountPointA(DriveName, DriveLetters); - Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError()); - } - else - { - Log("Failed to find ventoy volume"); - } - } - Log("OK\n"); - } - else - { - FindProcessOccupyDisk(hDrive, pPhyDrive); - } - - if (pGptInfo) - { - free(pGptInfo); - } - - CHECK_CLOSE_HANDLE(hDrive); - return rc; -} - -int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive) -{ - int i; - int rc = 0; - BOOL ForceMBR = FALSE; - HANDLE hVolume; - HANDLE hDrive; - DWORD Status; - DWORD dwSize; - BOOL bRet; - CHAR DriveName[] = "?:\\"; - CHAR DriveLetters[MAX_PATH] = { 0 }; - UINT64 StartSector; - UINT64 ReservedMB = 0; - MBR_HEAD BootImg; - MBR_HEAD MBR; - VTOY_GPT_INFO *pGptInfo = NULL; - - Log("UpdateVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>", - pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, - GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); - - PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); - - Log("Lock disk for umount ............................ "); - - hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE); - if (hDrive == INVALID_HANDLE_VALUE) - { - Log("Failed to open physical disk"); - return 1; - } - - if (pPhyDrive->PartStyle) - { - pGptInfo = malloc(sizeof(VTOY_GPT_INFO)); - if (!pGptInfo) - { - return 1; - } - - memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO)); - - // Read GPT Info - SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); - ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL); - - StartSector = pGptInfo->PartTbl[1].StartLBA; - Log("GPT 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); - } - else - { - // Read MBR - SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); - ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL); - - StartSector = MBR.PartTbl[1].StartSectorId; - Log("MBR StartSector in PartTbl:%llu", (ULONGLONG)StartSector); - - ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512)) / 2048; - Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB); - } - - GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); - - if (DriveLetters[0] == 0) - { - Log("No drive letter was assigned..."); - } - else - { - // Unmount all mounted volumes that belong to this drive - // Do it in reverse so that we always end on the first volume letter - for (i = (int)strlen(DriveLetters); i > 0; i--) - { - DriveName[0] = DriveLetters[i - 1]; - if (IsVentoyLogicalDrive(DriveName[0])) - { - Log("%s is ventoy logical drive", DriveName); - bRet = DeleteVolumeMountPointA(DriveName); - Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, LASTERR); - break; - } - } - } - - // It kind of blows, but we have to relinquish access to the physical drive - // for VDS to be able to delete the partitions that reside on it... - DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); - CHECK_CLOSE_HANDLE(hDrive); - - PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE); - - Log("Lock disk for update ............................ "); - hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); - if (hDrive == INVALID_HANDLE_VALUE) - { - Log("Failed to GetPhysicalHandle for write."); - rc = 1; - goto End; - } - - PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME); - - Log("Lock volume for update .......................... "); - hVolume = INVALID_HANDLE_VALUE; - Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[1].StartSectorId, DriveLetters, sizeof(DriveLetters), TRUE); - if (ERROR_SUCCESS == Status) - { - Log("Now lock and dismount volume <%s>", DriveLetters); - hVolume = CreateFileA(DriveLetters, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, - NULL); - - if (hVolume == INVALID_HANDLE_VALUE) - { - Log("Failed to create file volume, errcode:%u", LASTERR); - rc = 1; - goto End; - } - - bRet = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); - Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet, LASTERR); - - 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) - { - Log("Volume not found, maybe not supported"); - } - else - { - rc = 1; - goto End; - } - - - if (!TryWritePart2(hDrive, StartSector)) - { - ForceMBR = TRUE; - Log("Try write failed, now delete partition 2..."); - - CHECK_CLOSE_HANDLE(hDrive); - - Log("Now delete partition 2..."); - DeletePartitions(pPhyDrive->PhyDrive, TRUE); - - hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); - if (hDrive == INVALID_HANDLE_VALUE) - { - Log("Failed to GetPhysicalHandle for write."); - rc = 1; - goto End; - } - } - - - PROGRESS_BAR_SET_POS(PT_FORMAT_PART2); - - Log("Write Ventoy to disk ............................ "); - if (0 != FormatPart2Fat(hDrive, StartSector)) - { - rc = 1; - goto End; - } - - if (hVolume != INVALID_HANDLE_VALUE) - { - bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); - Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR); - CHECK_CLOSE_HANDLE(hVolume); - } - - Log("Updating Boot Image ............................. "); - if (WriteGrubStage1ToPhyDrive(hDrive, pPhyDrive->PartStyle) != 0) - { - rc = 1; - goto End; - } - - // Boot Image - VentoyGetLocalBootImg(&BootImg); - - // Use Old UUID - memcpy(BootImg.BootCode + 0x180, MBR.BootCode + 0x180, 16); - if (pPhyDrive->PartStyle) - { - BootImg.BootCode[92] = 0x22; - } - - if (ForceMBR == FALSE && memcmp(BootImg.BootCode, MBR.BootCode, 440) == 0) - { - Log("Boot image has no difference, no need to write."); - } - else - { - Log("Boot image need to write %u.", ForceMBR); - - SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); - - memcpy(MBR.BootCode, BootImg.BootCode, 440); - bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL); - Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR); - } - - if (pPhyDrive->PartStyle == 0) - { - if (0x00 == MBR.PartTbl[0].Active && 0x80 == MBR.PartTbl[1].Active) - { - Log("Need to chage 1st partition active and 2nd partition inactive."); - - MBR.PartTbl[0].Active = 0x80; - MBR.PartTbl[1].Active = 0x00; - - SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); - bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL); - Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR); - } - } - - //Refresh Drive Layout - DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); - -End: - - if (rc == 0) - { - Log("OK"); - } - else - { - FindProcessOccupyDisk(hDrive, pPhyDrive); - } - - CHECK_CLOSE_HANDLE(hDrive); - - if (pGptInfo) - { - free(pGptInfo); - } - - return rc; -} - - +/****************************************************************************** + * PhyDrive.c + * + * Copyright (c) 2020, longpanda + * Copyright (c) 2011-2020, Pete Batard + * + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include "resource.h" +#include "Language.h" +#include "Ventoy2Disk.h" +#include "fat_filelib.h" +#include "ff.h" + +/* + * Some code and functions in the file are copied from rufus. + * https://github.com/pbatard/rufus + */ +#define VDS_SET_ERROR SetLastError +#define IVdsServiceLoader_LoadService(This, pwszMachineName, ppService) (This)->lpVtbl->LoadService(This, pwszMachineName, ppService) +#define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This) +#define IVdsService_QueryProviders(This, masks, ppEnum) (This)->lpVtbl->QueryProviders(This, masks, ppEnum) +#define IVdsService_WaitForServiceReady(This) ((This)->lpVtbl->WaitForServiceReady(This)) +#define IVdsService_CleanupObsoleteMountPoints(This) ((This)->lpVtbl->CleanupObsoleteMountPoints(This)) +#define IVdsService_Refresh(This) ((This)->lpVtbl->Refresh(This)) +#define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This)) +#define IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject) +#define IVdsProvider_Release(This) (This)->lpVtbl->Release(This) +#define IVdsSwProvider_QueryPacks(This, ppEnum) (This)->lpVtbl->QueryPacks(This, ppEnum) +#define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This) +#define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum) +#define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties) +#define IVdsDisk_Release(This) (This)->lpVtbl->Release(This) +#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_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_Release(This) (This)->lpVtbl->Release(This) +#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 IVdsVolume_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject) +#define IVdsVolume_Release(This) (This)->lpVtbl->Release(This) +#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_Release(This) (This)->lpVtbl->Release(This) +#define IVdsVolume_GetProperties(This, pVolumeProperties) (This)->lpVtbl->GetProperties(This,pVolumeProperties) +#define IVdsAsync_Cancel(This) (This)->lpVtbl->Cancel(This) +#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_Release(This) (This)->lpVtbl->Release(This) + +#define IUnknown_QueryInterface(This, a, b) (This)->lpVtbl->QueryInterface(This,a,b) +#define IUnknown_Release(This) (This)->lpVtbl->Release(This) + +/* +* 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 +*/ +BOOL DeletePartitions(DWORD DriveIndex, BOOL OnlyPart2) +{ + BOOL r = FALSE; + HRESULT hr; + ULONG ulFetched; + wchar_t wPhysicalName[48]; + IVdsServiceLoader *pLoader; + IVdsService *pService; + IEnumVdsObject *pEnum; + IUnknown *pUnk; + + swprintf_s(wPhysicalName, ARRAYSIZE(wPhysicalName), L"\\\\?\\PhysicalDrive%lu", DriveIndex); + + // Initialize COM + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, + RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL); + + // Create a VDS Loader Instance + hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, + &IID_IVdsServiceLoader, (void **)&pLoader); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not create VDS Loader Instance: %u", LASTERR); + goto out; + } + + // Load the VDS Service + hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService); + IVdsServiceLoader_Release(pLoader); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not load VDS Service: %u", LASTERR); + goto out; + } + + // Wait for the Service to become ready if needed + hr = IVdsService_WaitForServiceReady(pService); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("VDS Service is not ready: %u", LASTERR); + goto out; + } + + // Query the VDS Service Providers + hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not query VDS Service Providers: %u", LASTERR); + goto out; + } + + while (IEnumVdsObject_Next(pEnum, 1, &pUnk, &ulFetched) == S_OK) { + IVdsProvider *pProvider; + IVdsSwProvider *pSwProvider; + IEnumVdsObject *pEnumPack; + IUnknown *pPackUnk; + + // Get VDS Provider + hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider); + IUnknown_Release(pUnk); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not get VDS Provider: %u", LASTERR); + goto out; + } + + // Get VDS Software Provider + hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider); + IVdsProvider_Release(pProvider); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not get VDS Software Provider: %u", LASTERR); + goto out; + } + + // Get VDS Software Provider Packs + hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack); + IVdsSwProvider_Release(pSwProvider); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not get VDS Software Provider Packs: %u", LASTERR); + goto out; + } + + // Enumerate Provider Packs + while (IEnumVdsObject_Next(pEnumPack, 1, &pPackUnk, &ulFetched) == S_OK) { + IVdsPack *pPack; + IEnumVdsObject *pEnumDisk; + IUnknown *pDiskUnk; + + hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack); + IUnknown_Release(pPackUnk); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not query VDS Software Provider Pack: %u", LASTERR); + goto out; + } + + // Use the pack interface to access the disks + hr = IVdsPack_QueryDisks(pPack, &pEnumDisk); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not query VDS disks: %u", LASTERR); + goto out; + } + + // List disks + while (IEnumVdsObject_Next(pEnumDisk, 1, &pDiskUnk, &ulFetched) == S_OK) { + VDS_DISK_PROP diskprop; + VDS_PARTITION_PROP* prop_array; + LONG i, prop_array_size; + IVdsDisk *pDisk; + IVdsAdvancedDisk *pAdvancedDisk; + + // Get the disk interface. + hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not query VDS Disk Interface: %u", LASTERR); + goto out; + } + + // Get the disk properties + hr = IVdsDisk_GetProperties(pDisk, &diskprop); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not query VDS Disk Properties: %u", LASTERR); + goto out; + } + + // Isolate the disk we want + if (_wcsicmp(wPhysicalName, diskprop.pwszName) != 0) { + IVdsDisk_Release(pDisk); + continue; + } + + // Instantiate the AdvanceDisk interface for our disk. + hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk); + IVdsDisk_Release(pDisk); + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not access VDS Advanced Disk interface: %u", LASTERR); + goto out; + } + + // 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); + if (hr == S_OK) { + Log("Deleting ALL partition(s) from disk '%S':", diskprop.pwszName); + // Now go through each partition + for (i = 0; i < prop_array_size; i++) { + + Log("* Partition %d (offset: %lld, size: %llu)", prop_array[i].ulPartitionNumber, + prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize); + + if (OnlyPart2 && prop_array[i].ullOffset == 2048*512) + { + Log("Skip this partition..."); + continue; + } + + + hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE); + if (hr != S_OK) { + r = FALSE; + VDS_SET_ERROR(hr); + Log("Could not delete partitions: %u", LASTERR); + } + } + r = TRUE; + } + else { + Log("No partition to delete on disk '%S'", diskprop.pwszName); + r = TRUE; + } + CoTaskMemFree(prop_array); + +#if 0 + // Issue a Clean while we're at it + HRESULT hr2 = E_FAIL; + ULONG completed; + IVdsAsync* pAsync; + hr = IVdsAdvancedDisk_Clean(pAdvancedDisk, TRUE, FALSE, FALSE, &pAsync); + while (SUCCEEDED(hr)) { + if (IS_ERROR(FormatStatus)) { + IVdsAsync_Cancel(pAsync); + break; + } + hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed); + if (SUCCEEDED(hr)) { + hr = hr2; + if (hr == S_OK) + break; + if (hr == VDS_E_OPERATION_PENDING) + hr = S_OK; + } + Sleep(500); + } + if (hr != S_OK) { + VDS_SET_ERROR(hr); + Log("Could not clean disk: %s", LASTERR); + } +#endif + IVdsAdvancedDisk_Release(pAdvancedDisk); + goto out; + } + } + } + +out: + return r; +} + + +static DWORD GetVentoyVolumeName(int PhyDrive, UINT32 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash) +{ + size_t len; + BOOL bRet; + DWORD dwSize; + HANDLE hDrive; + HANDLE hVolume; + UINT64 PartOffset; + DWORD Status = ERROR_NOT_FOUND; + DISK_EXTENT *pExtents = NULL; + CHAR VolumeName[MAX_PATH] = { 0 }; + VOLUME_DISK_EXTENTS DiskExtents; + + PartOffset = 512ULL * StartSectorId; + + Log("GetVentoyVolumeName PhyDrive %d SectorStart:%u PartOffset:%llu", PhyDrive, StartSectorId, (ULONGLONG)PartOffset); + + hVolume = FindFirstVolumeA(VolumeName, sizeof(VolumeName)); + if (hVolume == INVALID_HANDLE_VALUE) + { + return 1; + } + + do { + + len = strlen(VolumeName); + Log("Find volume:%s", VolumeName); + + VolumeName[len - 1] = 0; + + hDrive = CreateFileA(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hDrive == INVALID_HANDLE_VALUE) + { + continue; + } + + bRet = DeviceIoControl(hDrive, + IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, + NULL, + 0, + &DiskExtents, + (DWORD)(sizeof(DiskExtents)), + (LPDWORD)&dwSize, + NULL); + + Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet, LASTERR); + Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents.NumberOfDiskExtents, DiskExtents.Extents[0].DiskNumber); + + if (bRet && DiskExtents.NumberOfDiskExtents == 1) + { + pExtents = DiskExtents.Extents; + + Log("This volume DiskNumber:%u offset:%llu", pExtents->DiskNumber, (ULONGLONG)pExtents->StartingOffset.QuadPart); + if ((int)pExtents->DiskNumber == PhyDrive && pExtents->StartingOffset.QuadPart == PartOffset) + { + Log("This volume match"); + + if (!DelSlash) + { + VolumeName[len - 1] = '\\'; + } + + sprintf_s(NameBuf, BufLen, "%s", VolumeName); + Status = ERROR_SUCCESS; + CloseHandle(hDrive); + break; + } + } + + CloseHandle(hDrive); + } while (FindNextVolumeA(hVolume, VolumeName, sizeof(VolumeName))); + + FindVolumeClose(hVolume); + + Log("GetVentoyVolumeName return %u", Status); + return Status; +} + +static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length) +{ + int n = 0; + DWORD DataSize = 0; + CHAR *Pos = NULL; + CHAR *StringBuf = NULL; + + DataSize = GetLogicalDriveStringsA(0, NULL); + StringBuf = (CHAR *)malloc(DataSize + 1); + if (StringBuf == NULL) + { + return 1; + } + + GetLogicalDriveStringsA(DataSize, StringBuf); + + for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1) + { + if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0])) + { + Log("%C: is belong to phydrive%d", Pos[0], PhyDrive); + DriveLetters[n++] = Pos[0]; + } + } + + free(StringBuf); + return 0; +} + +static HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare) +{ + int i; + DWORD dwSize; + DWORD LastError; + UINT64 EndTime; + HANDLE hDrive = INVALID_HANDLE_VALUE; + CHAR PhyDrive[128]; + CHAR DevPath[MAX_PATH] = { 0 }; + + safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", Drive); + + if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath))) + { + Log("QueryDosDeviceA failed error:%u", GetLastError()); + strcpy_s(DevPath, sizeof(DevPath), "???"); + } + else + { + Log("QueryDosDeviceA success %s", DevPath); + } + + for (i = 0; i < DRIVE_ACCESS_RETRIES; i++) + { + // 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. + // 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 + // required for enumeration. + hDrive = CreateFileA(PhyDrive, + GENERIC_READ | (bWriteAccess ? GENERIC_WRITE : 0), + FILE_SHARE_READ | (bWriteShare ? FILE_SHARE_WRITE : 0), + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, + NULL); + + LastError = GetLastError(); + Log("[%d] CreateFileA %s code:%u %p", i, PhyDrive, LastError, hDrive); + + if (hDrive != INVALID_HANDLE_VALUE) + { + break; + } + + if ((LastError != ERROR_SHARING_VIOLATION) && (LastError != ERROR_ACCESS_DENIED)) + { + break; + } + + if (i == 0) + { + Log("Waiting for access on %s [%s]...", PhyDrive, DevPath); + } + 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... + Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled..."); + bWriteShare = TRUE; + + // Try to report the process that is locking the drive + // 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; + + } + Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES); + } + + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Could not open %s %u", PhyDrive, LASTERR); + goto End; + } + + if (bWriteAccess) + { + Log("Opened %s for %s write access", PhyDrive, bWriteShare ? "shared" : "exclusive"); + } + + if (bLockDrive) + { + if (DeviceIoControl(hDrive, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwSize, NULL)) + { + Log("I/O boundary checks disabled"); + } + + EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT; + + do { + if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL)) + { + Log("FSCTL_LOCK_VOLUME success"); + goto End; + } + Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES); + } while (GetTickCount64() < EndTime); + + // 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); + + // See if we can report the processes are accessing the drive + //if (!IS_ERROR(FormatStatus) && (access_mask == 0)) + // access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE); + // Try to continue if the only access rights we saw were for read-only + //if ((access_mask & 0x07) != 0x01) + // safe_closehandle(hDrive); + + CHECK_CLOSE_HANDLE(hDrive); + } + +End: + + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Can get handle of %s, maybe some process control it.", DevPath); + } + + return hDrive; +} + +int GetPhyDriveByLogicalDrive(int DriveLetter) +{ + BOOL Ret; + DWORD dwSize; + HANDLE Handle; + VOLUME_DISK_EXTENTS DiskExtents; + CHAR PhyPath[128]; + + safe_sprintf(PhyPath, "\\\\.\\%C:", (CHAR)DriveLetter); + + Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + if (Handle == INVALID_HANDLE_VALUE) + { + Log("Could not open the disk<%s>, error:%u", PhyPath, LASTERR); + return -1; + } + + Ret = DeviceIoControl(Handle, + IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, + NULL, + 0, + &DiskExtents, + (DWORD)(sizeof(DiskExtents)), + (LPDWORD)&dwSize, + NULL); + + if (!Ret || DiskExtents.NumberOfDiskExtents == 0) + { + Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, LASTERR); + CHECK_CLOSE_HANDLE(Handle); + return -1; + } + CHECK_CLOSE_HANDLE(Handle); + + Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu", + PhyPath, + DiskExtents.Extents[0].DiskNumber, + DiskExtents.Extents[0].StartingOffset.QuadPart, + DiskExtents.Extents[0].ExtentLength.QuadPart + ); + + return (int)DiskExtents.Extents[0].DiskNumber; +} + +int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount) +{ + int i; + int Count; + int id; + int Letter = 'A'; + BOOL bRet; + DWORD dwBytes; + DWORD DriveCount = 0; + HANDLE Handle = INVALID_HANDLE_VALUE; + CHAR PhyDrive[128]; + PHY_DRIVE_INFO *CurDrive = pDriveList; + GET_LENGTH_INFORMATION LengthInfo; + STORAGE_PROPERTY_QUERY Query; + STORAGE_DESCRIPTOR_HEADER DevDescHeader; + STORAGE_DEVICE_DESCRIPTOR *pDevDesc; + int PhyDriveId[VENTOY_MAX_PHY_DRIVE]; + + Count = GetPhysicalDriveCount(); + + for (i = 0; i < Count && i < VENTOY_MAX_PHY_DRIVE; i++) + { + PhyDriveId[i] = i; + } + + dwBytes = GetLogicalDrives(); + Log("Logical Drives: 0x%x", dwBytes); + while (dwBytes) + { + if (dwBytes & 0x01) + { + id = GetPhyDriveByLogicalDrive(Letter); + Log("%C --> %d", Letter, id); + if (id >= 0) + { + for (i = 0; i < Count; i++) + { + if (PhyDriveId[i] == id) + { + break; + } + } + + if (i >= Count) + { + Log("Add phy%d to list", i); + PhyDriveId[Count] = id; + Count++; + } + } + } + + Letter++; + dwBytes >>= 1; + } + + for (i = 0; i < Count && DriveCount < VENTOY_MAX_PHY_DRIVE; i++) + { + CHECK_CLOSE_HANDLE(Handle); + + safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", PhyDriveId[i]); + Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR); + + if (Handle == INVALID_HANDLE_VALUE) + { + continue; + } + + bRet = DeviceIoControl(Handle, + IOCTL_DISK_GET_LENGTH_INFO, NULL, + 0, + &LengthInfo, + sizeof(LengthInfo), + &dwBytes, + NULL); + if (!bRet) + { + Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR); + continue; + } + + Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart); + + Query.PropertyId = StorageDeviceProperty; + Query.QueryType = PropertyStandardQuery; + + bRet = DeviceIoControl(Handle, + IOCTL_STORAGE_QUERY_PROPERTY, + &Query, + sizeof(Query), + &DevDescHeader, + sizeof(STORAGE_DESCRIPTOR_HEADER), + &dwBytes, + NULL); + if (!bRet) + { + Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes); + continue; + } + + if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR)) + { + Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size); + continue; + } + + pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size); + if (!pDevDesc) + { + Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size); + continue; + } + + bRet = DeviceIoControl(Handle, + IOCTL_STORAGE_QUERY_PROPERTY, + &Query, + sizeof(Query), + pDevDesc, + DevDescHeader.Size, + &dwBytes, + NULL); + if (!bRet) + { + Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes); + free(pDevDesc); + continue; + } + + CurDrive->PhyDrive = i; + CurDrive->SizeInBytes = LengthInfo.Length.QuadPart; + CurDrive->DeviceType = pDevDesc->DeviceType; + CurDrive->RemovableMedia = pDevDesc->RemovableMedia; + CurDrive->BusType = pDevDesc->BusType; + + if (pDevDesc->VendorIdOffset) + { + safe_strcpy(CurDrive->VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset); + TrimString(CurDrive->VendorId); + } + + if (pDevDesc->ProductIdOffset) + { + safe_strcpy(CurDrive->ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset); + TrimString(CurDrive->ProductId); + } + + if (pDevDesc->ProductRevisionOffset) + { + safe_strcpy(CurDrive->ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset); + TrimString(CurDrive->ProductRev); + } + + if (pDevDesc->SerialNumberOffset) + { + safe_strcpy(CurDrive->SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset); + TrimString(CurDrive->SerialNumber); + } + + CurDrive++; + DriveCount++; + + free(pDevDesc); + + CHECK_CLOSE_HANDLE(Handle); + } + + for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++) + { + Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s", + CurDrive->PhyDrive, GetBusTypeString(CurDrive->BusType), CurDrive->RemovableMedia, + GetHumanReadableGBSize(CurDrive->SizeInBytes), CurDrive->SizeInBytes, + CurDrive->VendorId, CurDrive->ProductId); + } + + *pDriveCount = DriveCount; + + return 0; +} + + +static HANDLE g_FatPhyDrive; +static UINT64 g_Part2StartSec; +static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen) +{ + int rc = 1; + int size = 0; + char *buf = NULL; + void *flfile = NULL; + + flfile = fl_fopen("/grub/grub.cfg", "rb"); + if (flfile) + { + fl_fseek(flfile, 0, SEEK_END); + size = (int)fl_ftell(flfile); + + fl_fseek(flfile, 0, SEEK_SET); + + buf = (char *)malloc(size + 1); + if (buf) + { + fl_fread(buf, 1, size, flfile); + buf[size] = 0; + + rc = 0; + sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf)); + free(buf); + } + + fl_fclose(flfile); + } + + return rc; +} + +static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount) +{ + DWORD dwSize; + BOOL bRet; + DWORD ReadSize; + LARGE_INTEGER liCurrentPosition; + + liCurrentPosition.QuadPart = Sector + g_Part2StartSec; + liCurrentPosition.QuadPart *= 512; + SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN); + + ReadSize = (DWORD)(SectorCount * 512); + + bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL); + if (bRet == FALSE || dwSize != ReadSize) + { + Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, LASTERR); + } + + return 1; +} + + +int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen) +{ + int rc = 0; + HANDLE hDrive; + + hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + return 1; + } + + g_FatPhyDrive = hDrive; + g_Part2StartSec = Part2StartSector; + + Log("Parse FAT fs..."); + + fl_init(); + + if (0 == fl_attach_media(VentoyFatDiskRead, NULL)) + { + rc = GetVentoyVersionFromFatFile(VerBuf, BufLen); + } + else + { + rc = 1; + } + + fl_shutdown(); + + CHECK_CLOSE_HANDLE(hDrive); + + return rc; +} + + + + + +static unsigned int g_disk_unxz_len = 0; +static BYTE *g_part_img_pos = NULL; +static BYTE *g_part_img_buf[VENTOY_EFI_PART_SIZE / SIZE_1MB]; + + +static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount) +{ + uint32 i; + uint32 offset; + BYTE *MbBuf = NULL; + + for (i = 0; i < SectorCount; i++) + { + offset = (Sector + i) * 512; + + if (g_part_img_buf[1] == NULL) + { + MbBuf = g_part_img_buf[0] + offset; + memcpy(Buffer + i * 512, MbBuf, 512); + } + else + { + MbBuf = g_part_img_buf[offset / SIZE_1MB]; + memcpy(Buffer + i * 512, MbBuf + (offset % SIZE_1MB), 512); + } + } + + return 1; +} + + +static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount) +{ + uint32 i; + uint32 offset; + BYTE *MbBuf = NULL; + + for (i = 0; i < SectorCount; i++) + { + offset = (Sector + i) * 512; + + if (g_part_img_buf[1] == NULL) + { + MbBuf = g_part_img_buf[0] + offset; + memcpy(MbBuf, Buffer + i * 512, 512); + } + else + { + MbBuf = g_part_img_buf[offset / SIZE_1MB]; + memcpy(MbBuf + (offset % SIZE_1MB), Buffer + i * 512, 512); + } + } + + return 1; +} + +int VentoyProcSecureBoot(BOOL SecureBoot) +{ + int rc = 0; + int size; + char *filebuf = NULL; + void *file = NULL; + + Log("VentoyProcSecureBoot %d ...", SecureBoot); + + if (SecureBoot) + { + Log("Secure boot is enabled ..."); + return 0; + } + + fl_init(); + + if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite)) + { + file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb"); + Log("Open ventoy efi file %p ", file); + if (file) + { + fl_fseek(file, 0, SEEK_END); + size = (int)fl_ftell(file); + fl_fseek(file, 0, SEEK_SET); + + Log("ventoy efi file size %d ...", size); + + filebuf = (char *)malloc(size); + if (filebuf) + { + fl_fread(filebuf, 1, size, file); + } + + fl_fclose(file); + + Log("Now delete all efi files ..."); + fl_remove("/EFI/BOOT/BOOTX64.EFI"); + fl_remove("/EFI/BOOT/grubx64.efi"); + fl_remove("/EFI/BOOT/grubx64_real.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); + if (file) + { + if (filebuf) + { + fl_fwrite(filebuf, 1, size, file); + } + + fl_fflush(file); + fl_fclose(file); + } + + if (filebuf) + { + free(filebuf); + } + } + } + else + { + rc = 1; + } + + fl_shutdown(); + + return rc; +} + + + +static int disk_xz_flush(void *src, unsigned int size) +{ + unsigned int i; + BYTE *buf = (BYTE *)src; + + for (i = 0; i < size; i++) + { + *g_part_img_pos = *buf++; + + 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]; + } + else + { + g_part_img_pos++; + } + } + + return (int)size; +} + +static void unxz_error(char *x) +{ + Log("%s", x); +} + +static BOOL TryWritePart2(HANDLE hDrive, UINT64 StartSectorId) +{ + BOOL bRet; + DWORD TrySize = 16 * 1024; + DWORD dwSize; + BYTE *Buffer = NULL; + unsigned char *data = NULL; + LARGE_INTEGER liCurrentPosition; + + liCurrentPosition.QuadPart = StartSectorId * 512; + SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN); + + Buffer = malloc(TrySize); + + bRet = WriteFile(hDrive, Buffer, TrySize, &dwSize, NULL); + + free(Buffer); + + Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR); + + if (bRet && dwSize == TrySize) + { + return TRUE; + } + + return FALSE; +} + +static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId) +{ + int i; + int rc = 0; + int len = 0; + int writelen = 0; + int partwrite = 0; + DWORD dwSize = 0; + BOOL bRet; + unsigned char *data = NULL; + LARGE_INTEGER liCurrentPosition; + LARGE_INTEGER liNewPosition; + + Log("FormatPart2Fat %llu...", StartSectorId); + + rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&data, &len); + if (rc) + { + Log("Failed to read img file %p %u", data, len); + return 1; + } + + liCurrentPosition.QuadPart = StartSectorId * 512; + SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN); + + Log("Set file pointer: %llu New pointer:%llu", liCurrentPosition.QuadPart, liNewPosition.QuadPart); + + 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]) + { + Log("Malloc whole img buffer success, now decompress ..."); + unxz(data, len, NULL, NULL, g_part_img_buf[0], &writelen, unxz_error); + + if (len == writelen) + { + Log("decompress finished success"); + + VentoyProcSecureBoot(g_SecureBoot); + + 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); + Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR); + + if (!bRet) + { + rc = 1; + goto End; + } + + PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i); + } + } + else + { + rc = 1; + Log("decompress finished failed"); + goto End; + } + } + else + { + 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++) + { + g_part_img_buf[i] = (BYTE *)malloc(SIZE_1MB); + if (g_part_img_buf[i] == NULL) + { + rc = 1; + goto End; + } + } + + Log("Malloc part img buffer success, now decompress ..."); + + g_part_img_pos = g_part_img_buf[0]; + + unxz(data, len, NULL, disk_xz_flush, NULL, NULL, unxz_error); + + if (g_disk_unxz_len == VENTOY_EFI_PART_SIZE) + { + Log("decompress finished success"); + + VentoyProcSecureBoot(g_SecureBoot); + + 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); + Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR); + + if (!bRet) + { + rc = 1; + goto End; + } + + PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i); + } + } + else + { + rc = 1; + Log("decompress finished failed"); + goto End; + } + } + +End: + + if (data) free(data); + + if (partwrite) + { + for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++) + { + if (g_part_img_buf[i]) free(g_part_img_buf[i]); + } + } + else + { + if (g_part_img_buf[0]) free(g_part_img_buf[0]); + } + + return rc; +} + +static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle) +{ + int Len = 0; + int readLen = 0; + BOOL bRet; + DWORD dwSize; + BYTE *ImgBuf = NULL; + BYTE *RawBuf = NULL; + + Log("WriteGrubStage1ToPhyDrive ..."); + + RawBuf = (BYTE *)malloc(SIZE_1MB); + if (!RawBuf) + { + return 1; + } + + if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len)) + { + Log("Failed to read stage1 img"); + free(RawBuf); + return 1; + } + + unxz(ImgBuf, Len, NULL, NULL, RawBuf, &readLen, unxz_error); + + if (PartStyle) + { + Log("Write GPT stage1 ..."); + RawBuf[500] = 35;//update blocklist + SetFilePointer(hDrive, 512 * 34, NULL, FILE_BEGIN); + bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512 * 34, &dwSize, NULL); + } + else + { + Log("Write MBR stage1 ..."); + 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()); + + free(RawBuf); + free(ImgBuf); + return 0; +} + + + +static int FormatPart1exFAT(UINT64 DiskSizeBytes) +{ + MKFS_PARM Option; + FRESULT Ret; + FATFS fs; + + Option.fmt = FM_EXFAT; + Option.n_fat = 1; + Option.align = 8; + Option.n_root = 1; + + // < 32GB select 32KB as cluster size + // > 32GB select 128KB as cluster size + if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32) + { + Option.au_size = 32768; + } + else + { + Option.au_size = 131072; + } + + Log("Formatting Part1 exFAT ..."); + + Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024); + + if (FR_OK == Ret) + { + Log("Formatting Part1 exFAT success"); + + Ret = f_mount(&fs, TEXT("0:"), 1); + Log("mount part %d", Ret); + + if (FR_OK == Ret) + { + Ret = f_setlabel(TEXT("Ventoy")); + Log("f_setlabel %d", Ret); + + Ret = f_mount(0, TEXT("0:"), 1); + Log("umount part %d", Ret); + return 0; + } + else + { + Log("mount exfat failed %d", Ret); + return 1; + } + } + else + { + Log("Formatting Part1 exFAT failed"); + return 1; + } +} + + + +int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter) +{ + int i; + int rc = 0; + int state = 0; + HANDLE hDrive; + DWORD dwSize; + BOOL bRet; + CHAR MountDrive; + CHAR DriveName[] = "?:\\"; + CHAR DriveLetters[MAX_PATH] = { 0 }; + LARGE_INTEGER liCurrentPosition; + char *pTmpBuf = NULL; + MBR_HEAD MBR; + + *pDrvLetter = 0; + + Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>", + pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, + GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); + + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); + + Log("Lock disk for clean ............................. "); + + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to open physical disk"); + return 1; + } + + GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); + + if (DriveLetters[0] == 0) + { + Log("No drive letter was assigned..."); + DriveName[0] = GetFirstUnusedDriveLetter(); + Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]); + } + else + { + // Unmount all mounted volumes that belong to this drive + // Do it in reverse so that we always end on the first volume letter + for (i = (int)strlen(DriveLetters); i > 0; i--) + { + DriveName[0] = DriveLetters[i - 1]; + bRet = DeleteVolumeMountPointA(DriveName); + Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError()); + } + } + + MountDrive = DriveName[0]; + Log("Will use '%C:' as volume mountpoint", DriveName[0]); + + // It kind of blows, but we have to relinquish access to the physical drive + // for VDS to be able to delete the partitions that reside on it... + DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); + CHECK_CLOSE_HANDLE(hDrive); + + PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART); + + if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE)) + { + Log("Notice: Could not delete partitions: %u", GetLastError()); + } + + Log("Deleting all partitions ......................... OK"); + + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE); + + Log("Lock disk for write ............................. "); + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to GetPhysicalHandle for write."); + rc = 1; + goto End; + } + + // clear first and last 1MB space + pTmpBuf = malloc(SIZE_1MB); + if (!pTmpBuf) + { + Log("Failed to alloc memory."); + rc = 1; + goto End; + } + memset(pTmpBuf, 0, SIZE_1MB); + + SET_FILE_POS(512); + bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB - 512, &dwSize, NULL); + Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR); + if (!bRet) + { + rc = 1; + goto End; + } + + SET_FILE_POS(SIZE_1MB); + bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB, &dwSize, NULL); + Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR); + if (!bRet) + { + rc = 1; + goto End; + } + + SET_FILE_POS(0); + bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL); + Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR); + if (!bRet) + { + rc = 1; + goto End; + } + + //clear boot code and partition table (reserved disk signature) + memset(MBR.BootCode, 0, 440); + memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl)); + + VentoyFillLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl); + + MBR.PartTbl[0].Active = 0x00; // bootable + MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS + + SET_FILE_POS(0); + bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL); + Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR); + if (!bRet) + { + rc = 1; + goto End; + } + + Log("Clear Ventoy successfully finished"); + + //Refresh Drive Layout + DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); + +End: + + PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME); + + if (pTmpBuf) + { + free(pTmpBuf); + } + + if (rc == 0) + { + Log("Mounting Ventoy Partition ....................... "); + Sleep(1000); + + state = 0; + memset(DriveLetters, 0, sizeof(DriveLetters)); + GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); + Log("Logical drive letter after write ventoy: <%s>", DriveLetters); + + for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++) + { + DriveName[0] = DriveLetters[i]; + Log("%s is ventoy part1, already mounted", DriveName); + state = 1; + } + + if (state != 1) + { + Log("need to mount ventoy part1..."); + if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE)) + { + DriveName[0] = MountDrive; + bRet = SetVolumeMountPointA(DriveName, DriveLetters); + Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError()); + + *pDrvLetter = MountDrive; + } + else + { + Log("Failed to find ventoy volume"); + } + } + + Log("OK\n"); + } + else + { + FindProcessOccupyDisk(hDrive, pPhyDrive); + } + + CHECK_CLOSE_HANDLE(hDrive); + return rc; +} + +int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle) +{ + int i; + int rc = 0; + int state = 0; + HANDLE hDrive; + DWORD dwSize; + BOOL bRet; + CHAR MountDrive; + CHAR DriveName[] = "?:\\"; + CHAR DriveLetters[MAX_PATH] = { 0 }; + 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, + GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); + + if (PartStyle) + { + pGptInfo = malloc(sizeof(VTOY_GPT_INFO)); + memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO)); + } + + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); + + VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle);//also used to format 1st partition in GPT mode + if (PartStyle) + { + VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo); + } + + Log("Lock disk for clean ............................. "); + + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to open physical disk"); + free(pGptInfo); + return 1; + } + + GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); + + if (DriveLetters[0] == 0) + { + Log("No drive letter was assigned..."); + DriveName[0] = GetFirstUnusedDriveLetter(); + Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]); + } + else + { + // Unmount all mounted volumes that belong to this drive + // Do it in reverse so that we always end on the first volume letter + for (i = (int)strlen(DriveLetters); i > 0; i--) + { + DriveName[0] = DriveLetters[i - 1]; + bRet = DeleteVolumeMountPointA(DriveName); + Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError()); + } + } + + MountDrive = DriveName[0]; + Log("Will use '%C:' as volume mountpoint", DriveName[0]); + + // It kind of blows, but we have to relinquish access to the physical drive + // for VDS to be able to delete the partitions that reside on it... + DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); + CHECK_CLOSE_HANDLE(hDrive); + + PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART); + + if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE)) + { + Log("Notice: Could not delete partitions: %u", GetLastError()); + } + + Log("Deleting all partitions ......................... OK"); + + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE); + + Log("Lock disk for write ............................. "); + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to GetPhysicalHandle for write."); + rc = 1; + goto End; + } + + //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); + + PROGRESS_BAR_SET_POS(PT_FORMAT_PART1); + + if (PartStyle == 1 && pPhyDrive->PartStyle == 0) + { + Log("Wait for format part1 ..."); + Sleep(1000 * 5); + } + + Log("Formatting part1 exFAT ..."); + if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes)) + { + Log("FormatPart1exFAT failed."); + rc = 1; + goto End; + } + + PROGRESS_BAR_SET_POS(PT_FORMAT_PART2); + Log("Writing part2 FAT img ..."); + if (0 != FormatPart2Fat(hDrive, MBR.PartTbl[1].StartSectorId)) + { + Log("FormatPart2Fat failed."); + rc = 1; + goto End; + } + + PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG); + Log("Writting Boot Image ............................. "); + if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0) + { + Log("WriteGrubStage1ToPhyDrive failed."); + rc = 1; + goto End; + } + + PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE); + Log("Writting Partition Table ........................ "); + SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); + + if (PartStyle) + { + VTOY_GPT_HDR BackupHead; + LARGE_INTEGER liCurrentPosition; + + SET_FILE_POS(pPhyDrive->SizeInBytes - 512); + VentoyFillBackupGptHead(pGptInfo, &BackupHead); + if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL)) + { + rc = 1; + Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError()); + goto End; + } + + SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33); + if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL)) + { + rc = 1; + Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError()); + goto End; + } + + SET_FILE_POS(0); + if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL)) + { + rc = 1; + Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError()); + goto End; + } + + Log("Write GPT Info OK ..."); + } + else + { + if (!WriteFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL)) + { + rc = 1; + Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize, GetLastError()); + goto End; + } + Log("Write MBR OK ..."); + } + + + //Refresh Drive Layout + DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); + +End: + + PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME); + + if (rc == 0) + { + Log("Mounting Ventoy Partition ....................... "); + Sleep(1000); + + state = 0; + memset(DriveLetters, 0, sizeof(DriveLetters)); + GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); + Log("Logical drive letter after write ventoy: <%s>", DriveLetters); + + for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++) + { + DriveName[0] = DriveLetters[i]; + if (IsVentoyLogicalDrive(DriveName[0])) + { + Log("%s is ventoy part2, delete mountpoint", DriveName); + DeleteVolumeMountPointA(DriveName); + } + else + { + Log("%s is ventoy part1, already mounted", DriveName); + state = 1; + } + } + + if (state != 1) + { + Log("need to mount ventoy part1..."); + if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE)) + { + DriveName[0] = MountDrive; + bRet = SetVolumeMountPointA(DriveName, DriveLetters); + Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError()); + } + else + { + Log("Failed to find ventoy volume"); + } + } + Log("OK\n"); + } + else + { + FindProcessOccupyDisk(hDrive, pPhyDrive); + } + + if (pGptInfo) + { + free(pGptInfo); + } + + CHECK_CLOSE_HANDLE(hDrive); + return rc; +} + +int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive) +{ + int i; + int rc = 0; + BOOL ForceMBR = FALSE; + HANDLE hVolume; + HANDLE hDrive; + DWORD Status; + DWORD dwSize; + BOOL bRet; + CHAR DriveName[] = "?:\\"; + CHAR DriveLetters[MAX_PATH] = { 0 }; + UINT64 StartSector; + UINT64 ReservedMB = 0; + MBR_HEAD BootImg; + MBR_HEAD MBR; + VTOY_GPT_INFO *pGptInfo = NULL; + + Log("UpdateVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>", + pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, + GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); + + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); + + Log("Lock disk for umount ............................ "); + + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to open physical disk"); + return 1; + } + + if (pPhyDrive->PartStyle) + { + pGptInfo = malloc(sizeof(VTOY_GPT_INFO)); + if (!pGptInfo) + { + return 1; + } + + memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO)); + + // Read GPT Info + SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); + ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL); + + //MBR will be used to compare with local boot image + memcpy(&MBR, &pGptInfo->MBR, sizeof(MBR_HEAD)); + + StartSector = pGptInfo->PartTbl[1].StartLBA; + Log("GPT 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); + } + else + { + // Read MBR + SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); + ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL); + + StartSector = MBR.PartTbl[1].StartSectorId; + Log("MBR StartSector in PartTbl:%llu", (ULONGLONG)StartSector); + + ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512)) / 2048; + Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB); + } + + GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters)); + + if (DriveLetters[0] == 0) + { + Log("No drive letter was assigned..."); + } + else + { + // Unmount all mounted volumes that belong to this drive + // Do it in reverse so that we always end on the first volume letter + for (i = (int)strlen(DriveLetters); i > 0; i--) + { + DriveName[0] = DriveLetters[i - 1]; + if (IsVentoyLogicalDrive(DriveName[0])) + { + Log("%s is ventoy logical drive", DriveName); + bRet = DeleteVolumeMountPointA(DriveName); + Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, LASTERR); + break; + } + } + } + + // It kind of blows, but we have to relinquish access to the physical drive + // for VDS to be able to delete the partitions that reside on it... + DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); + CHECK_CLOSE_HANDLE(hDrive); + + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE); + + Log("Lock disk for update ............................ "); + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to GetPhysicalHandle for write."); + rc = 1; + goto End; + } + + PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME); + + Log("Lock volume for update .......................... "); + hVolume = INVALID_HANDLE_VALUE; + Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[1].StartSectorId, DriveLetters, sizeof(DriveLetters), TRUE); + if (ERROR_SUCCESS == Status) + { + Log("Now lock and dismount volume <%s>", DriveLetters); + hVolume = CreateFileA(DriveLetters, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, + NULL); + + if (hVolume == INVALID_HANDLE_VALUE) + { + Log("Failed to create file volume, errcode:%u", LASTERR); + rc = 1; + goto End; + } + + bRet = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); + Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet, LASTERR); + + 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) + { + Log("Volume not found, maybe not supported"); + } + else + { + rc = 1; + goto End; + } + + + if (!TryWritePart2(hDrive, StartSector)) + { + ForceMBR = TRUE; + Log("Try write failed, now delete partition 2..."); + + CHECK_CLOSE_HANDLE(hDrive); + + Log("Now delete partition 2..."); + DeletePartitions(pPhyDrive->PhyDrive, TRUE); + + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to GetPhysicalHandle for write."); + rc = 1; + goto End; + } + } + + + PROGRESS_BAR_SET_POS(PT_FORMAT_PART2); + + Log("Write Ventoy to disk ............................ "); + if (0 != FormatPart2Fat(hDrive, StartSector)) + { + rc = 1; + goto End; + } + + if (hVolume != INVALID_HANDLE_VALUE) + { + bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); + Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR); + CHECK_CLOSE_HANDLE(hVolume); + } + + Log("Updating Boot Image ............................. "); + if (WriteGrubStage1ToPhyDrive(hDrive, pPhyDrive->PartStyle) != 0) + { + rc = 1; + goto End; + } + + // Boot Image + VentoyGetLocalBootImg(&BootImg); + + // Use Old UUID + memcpy(BootImg.BootCode + 0x180, MBR.BootCode + 0x180, 16); + if (pPhyDrive->PartStyle) + { + BootImg.BootCode[92] = 0x22; + } + + if (ForceMBR == FALSE && memcmp(BootImg.BootCode, MBR.BootCode, 440) == 0) + { + Log("Boot image has no difference, no need to write."); + } + else + { + Log("Boot image need to write %u.", ForceMBR); + + SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); + + memcpy(MBR.BootCode, BootImg.BootCode, 440); + bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL); + Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR); + } + + if (pPhyDrive->PartStyle == 0) + { + if (0x00 == MBR.PartTbl[0].Active && 0x80 == MBR.PartTbl[1].Active) + { + Log("Need to chage 1st partition active and 2nd partition inactive."); + + MBR.PartTbl[0].Active = 0x80; + MBR.PartTbl[1].Active = 0x00; + + SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); + bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL); + Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR); + } + } + + //Refresh Drive Layout + DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); + +End: + + if (rc == 0) + { + Log("OK"); + } + else + { + FindProcessOccupyDisk(hDrive, pPhyDrive); + } + + CHECK_CLOSE_HANDLE(hDrive); + + if (pGptInfo) + { + free(pGptInfo); + } + + return rc; +} + + diff --git a/Ventoy2Disk/Ventoy2Disk/Utility.c b/Ventoy2Disk/Ventoy2Disk/Utility.c index 586d2368..2b9327f1 100644 --- a/Ventoy2Disk/Ventoy2Disk/Utility.c +++ b/Ventoy2Disk/Ventoy2Disk/Utility.c @@ -1,803 +1,805 @@ -/****************************************************************************** - * Utility.c - * - * Copyright (c) 2020, longpanda - * - * 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 . - * - */ -#include -#include "Ventoy2Disk.h" - -void Log(const char *Fmt, ...) -{ - va_list Arg; - int Len = 0; - FILE *File = NULL; - SYSTEMTIME Sys; - char szBuf[1024]; - - GetLocalTime(&Sys); - Len += safe_sprintf(szBuf, - "[%4d/%02d/%02d %02d:%02d:%02d.%03d] ", - Sys.wYear, Sys.wMonth, Sys.wDay, - Sys.wHour, Sys.wMinute, Sys.wSecond, - Sys.wMilliseconds); - - va_start(Arg, Fmt); - Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg); - va_end(Arg); - - //printf("%s\n", szBuf); - -#if 1 - fopen_s(&File, VENTOY_FILE_LOG, "a+"); - if (File) - { - fwrite(szBuf, 1, Len, File); - fwrite("\n", 1, 1, File); - fclose(File); - } -#endif - -} - -BOOL IsPathExist(BOOL Dir, const char *Fmt, ...) -{ - va_list Arg; - HANDLE hFile; - DWORD Attr; - CHAR FilePath[MAX_PATH]; - - va_start(Arg, Fmt); - vsnprintf_s(FilePath, sizeof(FilePath), sizeof(FilePath), Fmt, Arg); - va_end(Arg); - - hFile = CreateFileA(FilePath, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); - if (INVALID_HANDLE_VALUE == hFile) - { - return FALSE; - } - - CloseHandle(hFile); - - Attr = GetFileAttributesA(FilePath); - - if (Dir) - { - if ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0) - { - return FALSE; - } - } - else - { - if (Attr & FILE_ATTRIBUTE_DIRECTORY) - { - return FALSE; - } - } - - return TRUE; -} - - -int ReadWholeFileToBuf(const CHAR *FileName, int ExtLen, void **Bufer, int *BufLen) -{ - int FileSize; - FILE *File = NULL; - void *Data = NULL; - - fopen_s(&File, FileName, "rb"); - if (File == NULL) - { - Log("Failed to open file %s", FileName); - return 1; - } - - fseek(File, 0, SEEK_END); - FileSize = (int)ftell(File); - - Data = malloc(FileSize + ExtLen); - if (!Data) - { - fclose(File); - return 1; - } - - fseek(File, 0, SEEK_SET); - fread(Data, 1, FileSize, File); - - fclose(File); - - *Bufer = Data; - *BufLen = FileSize; - - return 0; -} - -const CHAR* GetLocalVentoyVersion(void) -{ - int rc; - int FileSize; - CHAR *Pos = NULL; - CHAR *Buf = NULL; - static CHAR LocalVersion[64] = { 0 }; - - if (LocalVersion[0] == 0) - { - rc = ReadWholeFileToBuf(VENTOY_FILE_VERSION, 1, (void **)&Buf, &FileSize); - if (rc) - { - return ""; - } - Buf[FileSize] = 0; - - for (Pos = Buf; *Pos; Pos++) - { - if (*Pos == '\r' || *Pos == '\n') - { - *Pos = 0; - break; - } - } - - safe_sprintf(LocalVersion, "%s", Buf); - free(Buf); - } - - return LocalVersion; -} - -const CHAR* ParseVentoyVersionFromString(CHAR *Buf) -{ - CHAR *Pos = NULL; - CHAR *End = NULL; - static CHAR LocalVersion[64] = { 0 }; - - Pos = strstr(Buf, "VENTOY_VERSION="); - if (Pos) - { - Pos += strlen("VENTOY_VERSION="); - if (*Pos == '"') - { - Pos++; - } - - End = Pos; - while (*End != 0 && *End != '"' && *End != '\r' && *End != '\n') - { - End++; - } - - *End = 0; - - safe_sprintf(LocalVersion, "%s", Pos); - return LocalVersion; - } - - return ""; -} - -BOOL IsWow64(void) -{ - typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); - LPFN_ISWOW64PROCESS fnIsWow64Process; - BOOL bIsWow64 = FALSE; - - fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process"); - if (NULL != fnIsWow64Process) - { - fnIsWow64Process(GetCurrentProcess(), &bIsWow64); - } - - return bIsWow64; -} - -void DumpWindowsVersion(void) -{ - int Bit; - BOOL WsVer; - DWORD Major, Minor; - ULONGLONG MajorEqual, MinorEqual; - OSVERSIONINFOEXA Ver1, Ver2; - const CHAR *Ver = NULL; - CHAR WinVer[256] = { 0 }; - - memset(&Ver1, 0, sizeof(Ver1)); - memset(&Ver2, 0, sizeof(Ver2)); - - Ver1.dwOSVersionInfoSize = sizeof(Ver1); - - // suppress the C4996 warning for GetVersionExA - #pragma warning(push) - #pragma warning(disable:4996) - if (!GetVersionExA((OSVERSIONINFOA *)&Ver1)) - { - memset(&Ver1, 0, sizeof(Ver1)); - Ver1.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); - if (!GetVersionExA((OSVERSIONINFOA *)&Ver1)) - { - return; - } - } - #pragma warning(pop) - - if (Ver1.dwPlatformId == VER_PLATFORM_WIN32_NT) - { - if (Ver1.dwMajorVersion > 6 || (Ver1.dwMajorVersion == 6 && Ver1.dwMinorVersion >= 2)) - { - // GetVersionEx() has problem on some Windows version - - MajorEqual = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); - for (Major = Ver1.dwMajorVersion; Major <= 9; Major++) - { - memset(&Ver2, 0, sizeof(Ver2)); - Ver2.dwOSVersionInfoSize = sizeof(Ver2); - Ver2.dwMajorVersion = Major; - - if (!VerifyVersionInfoA(&Ver2, VER_MAJORVERSION, MajorEqual)) - { - continue; - } - - if (Ver1.dwMajorVersion < Major) - { - Ver1.dwMajorVersion = Major; - Ver1.dwMinorVersion = 0; - } - - MinorEqual = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); - for (Minor = Ver1.dwMinorVersion; Minor <= 9; Minor++) - { - memset(&Ver2, 0, sizeof(Ver2)); - - Ver2.dwOSVersionInfoSize = sizeof(Ver2); - Ver2.dwMinorVersion = Minor; - - if (!VerifyVersionInfoA(&Ver2, VER_MINORVERSION, MinorEqual)) - { - continue; - } - - Ver1.dwMinorVersion = Minor; - break; - } - - break; - } - } - - if (Ver1.dwMajorVersion <= 0xF && Ver1.dwMinorVersion <= 0xF) - { - WsVer = (Ver1.wProductType <= VER_NT_WORKSTATION); - switch ((Ver1.dwMajorVersion << 4) | Ver2.dwMinorVersion) - { - case 0x51: - { - Ver = "XP"; - break; - } - case 0x52: - { - Ver = GetSystemMetrics(89) ? "Server 2003 R2" : "Server 2003"; - break; - } - case 0x60: - { - Ver = WsVer ? "Vista" : "Server 2008"; - break; - } - case 0x61: - { - Ver = WsVer ? "7" : "Server 2008 R2"; - break; - } - case 0x62: - { - Ver = WsVer ? "8" : "Server 2012"; - break; - } - case 0x63: - { - Ver = WsVer ? "8.1" : "Server 2012 R2"; - break; - } - case 0x64: - { - Ver = WsVer ? "10 (Preview 1)" : "Server 10 (Preview 1)"; - break; - } - case 0xA0: - { - Ver = WsVer ? "10" : ((Ver1.dwBuildNumber > 15000) ? "Server 2019" : "Server 2016"); - break; - } - default: - { - Ver = "10 or later"; - break; - } - } - } - } - - Bit = IsWow64() ? 64 : 32; - - if (Ver1.wServicePackMinor) - { - safe_sprintf(WinVer, "Windows %s SP%u.%u %d-bit", Ver, Ver1.wServicePackMajor, Ver1.wServicePackMinor, Bit); - } - else if (Ver1.wServicePackMajor) - { - safe_sprintf(WinVer, "Windows %s SP%u %d-bit", Ver, Ver1.wServicePackMajor, Bit); - } - else - { - safe_sprintf(WinVer, "Windows %s %d-bit", Ver, Bit); - } - - if (((Ver1.dwMajorVersion << 4) | Ver2.dwMinorVersion) >= 0x62) - { - Log("Windows Version : %s (Build %u)", WinVer, Ver1.dwBuildNumber); - } - else - { - Log("Windows Version : %s", WinVer); - } - - return; -} - -BOOL IsVentoyLogicalDrive(CHAR DriveLetter) -{ - int i; - CONST CHAR *Files[] = - { - "EFI\\BOOT\\BOOTX64.EFI", - "grub\\themes\\ventoy\\theme.txt", - "ventoy\\ventoy.cpio", - }; - - for (i = 0; i < sizeof(Files) / sizeof(Files[0]); i++) - { - if (!IsFileExist("%C:\\%s", DriveLetter, Files[i])) - { - return FALSE; - } - } - - return TRUE; -} - - -int VentoyFillLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table) -{ - BYTE Head; - BYTE Sector; - BYTE nSector = 63; - BYTE nHead = 8; - UINT32 Cylinder; - UINT32 EndSectorId; - - while (nHead != 0 && (DiskSizeInBytes / 512 / nSector / nHead) > 1024) - { - nHead = (BYTE)nHead * 2; - } - - if (nHead == 0) - { - nHead = 255; - } - - Cylinder = StartSectorId / nSector / nHead; - Head = StartSectorId / nSector % nHead; - Sector = StartSectorId % nSector + 1; - - Table->StartHead = Head; - Table->StartSector = Sector; - Table->StartCylinder = Cylinder; - - EndSectorId = StartSectorId + SectorCount - 1; - Cylinder = EndSectorId / nSector / nHead; - Head = EndSectorId / nSector % nHead; - Sector = EndSectorId % nSector + 1; - - Table->EndHead = Head; - Table->EndSector = Sector; - Table->EndCylinder = Cylinder; - - Table->StartSectorId = StartSectorId; - Table->SectorCount = SectorCount; - - return 0; -} - -int VentoyFillMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR, int PartStyle) -{ - GUID Guid; - int ReservedValue; - UINT32 DiskSignature; - UINT32 DiskSectorCount; - UINT32 PartSectorCount; - UINT32 PartStartSector; - UINT32 ReservedSector; - - VentoyGetLocalBootImg(pMBR); - - CoCreateGuid(&Guid); - - memcpy(&DiskSignature, &Guid, sizeof(UINT32)); - - Log("Disk signature: 0x%08x", DiskSignature); - - *((UINT32 *)(pMBR->BootCode + 0x1B8)) = DiskSignature; - - if (DiskSizeBytes / 512 > 0xFFFFFFFF) - { - DiskSectorCount = 0xFFFFFFFF; - } - else - { - DiskSectorCount = (UINT32)(DiskSizeBytes / 512); - } - - ReservedValue = GetReservedSpaceInMB(); - if (ReservedValue <= 0) - { - ReservedSector = 0; - } - else - { - ReservedSector = (UINT32)(ReservedValue * 2048); - } - - if (PartStyle) - { - ReservedSector += 33; // backup GPT part table - } - - Log("ReservedSector: %u", ReservedSector); - - //Part1 - PartStartSector = VENTOY_PART1_START_SECTOR; - PartSectorCount = DiskSectorCount - ReservedSector - VENTOY_EFI_PART_SIZE / 512 - PartStartSector; - VentoyFillLocation(DiskSizeBytes, PartStartSector, PartSectorCount, pMBR->PartTbl); - - pMBR->PartTbl[0].Active = 0x80; // bootable - pMBR->PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS - - //Part2 - PartStartSector += PartSectorCount; - PartSectorCount = VENTOY_EFI_PART_SIZE / 512; - VentoyFillLocation(DiskSizeBytes, PartStartSector, PartSectorCount, pMBR->PartTbl + 1); - - pMBR->PartTbl[1].Active = 0x00; - pMBR->PartTbl[1].FsFlag = 0xEF; // EFI System Partition - - pMBR->Byte55 = 0x55; - pMBR->ByteAA = 0xAA; - - return 0; -} - - -static int VentoyFillProtectMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR) -{ - GUID Guid; - UINT32 DiskSignature; - UINT64 DiskSectorCount; - - VentoyGetLocalBootImg(pMBR); - - CoCreateGuid(&Guid); - - memcpy(&DiskSignature, &Guid, sizeof(UINT32)); - - Log("Disk signature: 0x%08x", DiskSignature); - - *((UINT32 *)(pMBR->BootCode + 0x1B8)) = DiskSignature; - - DiskSectorCount = DiskSizeBytes / 512 - 1; - if (DiskSectorCount > 0xFFFFFFFF) - { - DiskSectorCount = 0xFFFFFFFF; - } - - memset(pMBR->PartTbl, 0, sizeof(pMBR->PartTbl)); - - pMBR->PartTbl[0].Active = 0x00; - pMBR->PartTbl[0].FsFlag = 0xee; // EE - - pMBR->PartTbl[0].StartHead = 0; - pMBR->PartTbl[0].StartSector = 1; - pMBR->PartTbl[0].StartCylinder = 0; - pMBR->PartTbl[0].EndHead = 254; - pMBR->PartTbl[0].EndSector = 63; - pMBR->PartTbl[0].EndCylinder = 1023; - - pMBR->PartTbl[0].StartSectorId = 1; - pMBR->PartTbl[0].SectorCount = (UINT32)DiskSectorCount; - - pMBR->Byte55 = 0x55; - pMBR->ByteAA = 0xAA; - - pMBR->BootCode[92] = 0x22; - - return 0; -} - - -int VentoyFillGpt(UINT64 DiskSizeBytes, VTOY_GPT_INFO *pInfo) -{ - INT64 ReservedValue = 0; - UINT64 ReservedSector = 33; - UINT64 Part1SectorCount = 0; - UINT64 DiskSectorCount = DiskSizeBytes / 512; - VTOY_GPT_HDR *Head = &pInfo->Head; - VTOY_GPT_PART_TBL *Table = pInfo->PartTbl; - 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 BiosGrubPartType = { 0x21686148, 0x6449, 0x6e6f, { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } }; - - VentoyFillProtectMBR(DiskSizeBytes, &pInfo->MBR); - - ReservedValue = GetReservedSpaceInMB(); - if (ReservedValue > 0) - { - ReservedSector += ReservedValue * 2048; - } - - Part1SectorCount = DiskSectorCount - ReservedSector - (VENTOY_EFI_PART_SIZE / 512) - 2048; - - memcpy(Head->Signature, "EFI PART", 8); - Head->Version[2] = 0x01; - Head->Length = 92; - Head->Crc = 0; - Head->EfiStartLBA = 1; - Head->EfiBackupLBA = DiskSectorCount - 1; - Head->PartAreaStartLBA = 34; - Head->PartAreaEndLBA = DiskSectorCount - 34; - CoCreateGuid(&Head->DiskGuid); - Head->PartTblStartLBA = 2; - Head->PartTblTotNum = 128; - Head->PartTblEntryLen = 128; - - - memcpy(&(Table[0].PartType), &WindowsDataPartType, sizeof(GUID)); - CoCreateGuid(&(Table[0].PartGuid)); - Table[0].StartLBA = 2048; - Table[0].LastLBA = 2048 + Part1SectorCount - 1; - Table[0].Attr = 0; - memcpy(Table[0].Name, L"Ventoy", 6 * 2); - - memcpy(&(Table[1].PartType), &EspPartType, sizeof(GUID)); - CoCreateGuid(&(Table[1].PartGuid)); - Table[1].StartLBA = Table[0].LastLBA + 1; - Table[1].LastLBA = Table[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1; - Table[1].Attr = 1; - memcpy(Table[1].Name, L"VTOYEFI", 7 * 2); - -#if 0 - memcpy(&(Table[2].PartType), &BiosGrubPartType, sizeof(GUID)); - CoCreateGuid(&(Table[2].PartGuid)); - Table[2].StartLBA = 34; - Table[2].LastLBA = 2047; - Table[2].Attr = 0; -#endif - - //Update CRC - Head->PartTblCrc = VentoyCrc32(Table, sizeof(pInfo->PartTbl)); - Head->Crc = VentoyCrc32(Head, Head->Length); - - return 0; -} - -int VentoyFillBackupGptHead(VTOY_GPT_INFO *pInfo, VTOY_GPT_HDR *pHead) -{ - UINT64 LBA; - UINT64 BackupLBA; - - memcpy(pHead, &pInfo->Head, sizeof(VTOY_GPT_HDR)); - - LBA = pHead->EfiStartLBA; - BackupLBA = pHead->EfiBackupLBA; - - pHead->EfiStartLBA = BackupLBA; - pHead->EfiBackupLBA = LBA; - pHead->PartTblStartLBA = BackupLBA + 1 - 33; - - pHead->Crc = 0; - pHead->Crc = VentoyCrc32(pHead, pHead->Length); - - return 0; -} - -CHAR GetFirstUnusedDriveLetter(void) -{ - CHAR Letter = 'D'; - DWORD Drives = GetLogicalDrives(); - - Drives >>= 3; - while (Drives & 0x1) - { - Letter++; - Drives >>= 1; - } - - return Letter; -} - -const CHAR * GetBusTypeString(STORAGE_BUS_TYPE Type) -{ - switch (Type) - { - case BusTypeUnknown: return "unknown"; - case BusTypeScsi: return "SCSI"; - case BusTypeAtapi: return "Atapi"; - case BusTypeAta: return "ATA"; - case BusType1394: return "1394"; - case BusTypeSsa: return "SSA"; - case BusTypeFibre: return "Fibre"; - case BusTypeUsb: return "USB"; - case BusTypeRAID: return "RAID"; - case BusTypeiScsi: return "iSCSI"; - case BusTypeSas: return "SAS"; - case BusTypeSata: return "SATA"; - case BusTypeSd: return "SD"; - case BusTypeMmc: return "MMC"; - case BusTypeVirtual: return "Virtual"; - case BusTypeFileBackedVirtual: return "FileBackedVirtual"; - case BusTypeSpaces: return "Spaces"; - case BusTypeNvme: return "Nvme"; - } - return "unknown"; -} - -int VentoyGetLocalBootImg(MBR_HEAD *pMBR) -{ - int Len = 0; - BYTE *ImgBuf = NULL; - static int Loaded = 0; - static MBR_HEAD MBR; - - if (Loaded) - { - memcpy(pMBR, &MBR, 512); - return 0; - } - - if (0 == ReadWholeFileToBuf(VENTOY_FILE_BOOT_IMG, 0, (void **)&ImgBuf, &Len)) - { - Log("Copy boot img success"); - memcpy(pMBR, ImgBuf, 512); - free(ImgBuf); - - CoCreateGuid((GUID *)(pMBR->BootCode + 0x180)); - - memcpy(&MBR, pMBR, 512); - Loaded = 1; - - return 0; - } - else - { - Log("Copy boot img failed"); - return 1; - } -} - -int GetHumanReadableGBSize(UINT64 SizeBytes) -{ - int i; - int Pow2 = 1; - double Delta; - double GB = SizeBytes * 1.0 / 1000 / 1000 / 1000; - - for (i = 0; i < 12; i++) - { - if (Pow2 > GB) - { - Delta = (Pow2 - GB) / Pow2; - } - else - { - Delta = (GB - Pow2) / Pow2; - } - - if (Delta < 0.05) - { - return Pow2; - } - - Pow2 <<= 1; - } - - return (int)GB; -} - -void TrimString(CHAR *String) -{ - CHAR *Pos1 = String; - CHAR *Pos2 = String; - size_t Len = strlen(String); - - while (Len > 0) - { - if (String[Len - 1] != ' ' && String[Len - 1] != '\t') - { - break; - } - String[Len - 1] = 0; - Len--; - } - - while (*Pos1 == ' ' || *Pos1 == '\t') - { - Pos1++; - } - - while (*Pos1) - { - *Pos2++ = *Pos1++; - } - *Pos2++ = 0; - - return; -} - -int GetRegDwordValue(HKEY Key, LPCSTR SubKey, LPCSTR ValueName, DWORD *pValue) -{ - HKEY hKey; - DWORD Type; - DWORD Size; - LSTATUS lRet; - DWORD Value; - - lRet = RegOpenKeyExA(Key, SubKey, 0, KEY_QUERY_VALUE, &hKey); - Log("RegOpenKeyExA <%s> Ret:%ld", SubKey, lRet); - - if (ERROR_SUCCESS == lRet) - { - Size = sizeof(Value); - lRet = RegQueryValueExA(hKey, ValueName, NULL, &Type, (LPBYTE)&Value, &Size); - Log("RegQueryValueExA <%s> ret:%u Size:%u Value:%u", ValueName, lRet, Size, Value); - - *pValue = Value; - RegCloseKey(hKey); - - return 0; - } - else - { - return 1; - } -} - -int GetPhysicalDriveCount(void) -{ - DWORD Value; - int Count = 0; - - if (GetRegDwordValue(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", "Count", &Value) == 0) - { - Count = (int)Value; - } - - Log("GetPhysicalDriveCount: %d", Count); - return Count; -} - - - +/****************************************************************************** + * Utility.c + * + * Copyright (c) 2020, longpanda + * + * 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 . + * + */ +#include +#include "Ventoy2Disk.h" + +void Log(const char *Fmt, ...) +{ + va_list Arg; + int Len = 0; + FILE *File = NULL; + SYSTEMTIME Sys; + char szBuf[1024]; + + GetLocalTime(&Sys); + Len += safe_sprintf(szBuf, + "[%4d/%02d/%02d %02d:%02d:%02d.%03d] ", + Sys.wYear, Sys.wMonth, Sys.wDay, + Sys.wHour, Sys.wMinute, Sys.wSecond, + Sys.wMilliseconds); + + va_start(Arg, Fmt); + Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg); + va_end(Arg); + + //printf("%s\n", szBuf); + +#if 1 + fopen_s(&File, VENTOY_FILE_LOG, "a+"); + if (File) + { + fwrite(szBuf, 1, Len, File); + fwrite("\n", 1, 1, File); + fclose(File); + } +#endif + +} + +BOOL IsPathExist(BOOL Dir, const char *Fmt, ...) +{ + va_list Arg; + HANDLE hFile; + DWORD Attr; + CHAR FilePath[MAX_PATH]; + + va_start(Arg, Fmt); + vsnprintf_s(FilePath, sizeof(FilePath), sizeof(FilePath), Fmt, Arg); + va_end(Arg); + + hFile = CreateFileA(FilePath, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if (INVALID_HANDLE_VALUE == hFile) + { + return FALSE; + } + + CloseHandle(hFile); + + Attr = GetFileAttributesA(FilePath); + + if (Dir) + { + if ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0) + { + return FALSE; + } + } + else + { + if (Attr & FILE_ATTRIBUTE_DIRECTORY) + { + return FALSE; + } + } + + return TRUE; +} + + +int ReadWholeFileToBuf(const CHAR *FileName, int ExtLen, void **Bufer, int *BufLen) +{ + int FileSize; + FILE *File = NULL; + void *Data = NULL; + + fopen_s(&File, FileName, "rb"); + if (File == NULL) + { + Log("Failed to open file %s", FileName); + return 1; + } + + fseek(File, 0, SEEK_END); + FileSize = (int)ftell(File); + + Data = malloc(FileSize + ExtLen); + if (!Data) + { + fclose(File); + return 1; + } + + fseek(File, 0, SEEK_SET); + fread(Data, 1, FileSize, File); + + fclose(File); + + *Bufer = Data; + *BufLen = FileSize; + + return 0; +} + +const CHAR* GetLocalVentoyVersion(void) +{ + int rc; + int FileSize; + CHAR *Pos = NULL; + CHAR *Buf = NULL; + static CHAR LocalVersion[64] = { 0 }; + + if (LocalVersion[0] == 0) + { + rc = ReadWholeFileToBuf(VENTOY_FILE_VERSION, 1, (void **)&Buf, &FileSize); + if (rc) + { + return ""; + } + Buf[FileSize] = 0; + + for (Pos = Buf; *Pos; Pos++) + { + if (*Pos == '\r' || *Pos == '\n') + { + *Pos = 0; + break; + } + } + + safe_sprintf(LocalVersion, "%s", Buf); + free(Buf); + } + + return LocalVersion; +} + +const CHAR* ParseVentoyVersionFromString(CHAR *Buf) +{ + CHAR *Pos = NULL; + CHAR *End = NULL; + static CHAR LocalVersion[64] = { 0 }; + + Pos = strstr(Buf, "VENTOY_VERSION="); + if (Pos) + { + Pos += strlen("VENTOY_VERSION="); + if (*Pos == '"') + { + Pos++; + } + + End = Pos; + while (*End != 0 && *End != '"' && *End != '\r' && *End != '\n') + { + End++; + } + + *End = 0; + + safe_sprintf(LocalVersion, "%s", Pos); + return LocalVersion; + } + + return ""; +} + +BOOL IsWow64(void) +{ + typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); + LPFN_ISWOW64PROCESS fnIsWow64Process; + BOOL bIsWow64 = FALSE; + + fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process"); + if (NULL != fnIsWow64Process) + { + fnIsWow64Process(GetCurrentProcess(), &bIsWow64); + } + + return bIsWow64; +} + +void DumpWindowsVersion(void) +{ + int Bit; + BOOL WsVer; + DWORD Major, Minor; + ULONGLONG MajorEqual, MinorEqual; + OSVERSIONINFOEXA Ver1, Ver2; + const CHAR *Ver = NULL; + CHAR WinVer[256] = { 0 }; + + memset(&Ver1, 0, sizeof(Ver1)); + memset(&Ver2, 0, sizeof(Ver2)); + + Ver1.dwOSVersionInfoSize = sizeof(Ver1); + + // suppress the C4996 warning for GetVersionExA + #pragma warning(push) + #pragma warning(disable:4996) + if (!GetVersionExA((OSVERSIONINFOA *)&Ver1)) + { + memset(&Ver1, 0, sizeof(Ver1)); + Ver1.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); + if (!GetVersionExA((OSVERSIONINFOA *)&Ver1)) + { + return; + } + } + #pragma warning(pop) + + if (Ver1.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + if (Ver1.dwMajorVersion > 6 || (Ver1.dwMajorVersion == 6 && Ver1.dwMinorVersion >= 2)) + { + // GetVersionEx() has problem on some Windows version + + MajorEqual = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); + for (Major = Ver1.dwMajorVersion; Major <= 9; Major++) + { + memset(&Ver2, 0, sizeof(Ver2)); + Ver2.dwOSVersionInfoSize = sizeof(Ver2); + Ver2.dwMajorVersion = Major; + + if (!VerifyVersionInfoA(&Ver2, VER_MAJORVERSION, MajorEqual)) + { + continue; + } + + if (Ver1.dwMajorVersion < Major) + { + Ver1.dwMajorVersion = Major; + Ver1.dwMinorVersion = 0; + } + + MinorEqual = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); + for (Minor = Ver1.dwMinorVersion; Minor <= 9; Minor++) + { + memset(&Ver2, 0, sizeof(Ver2)); + + Ver2.dwOSVersionInfoSize = sizeof(Ver2); + Ver2.dwMinorVersion = Minor; + + if (!VerifyVersionInfoA(&Ver2, VER_MINORVERSION, MinorEqual)) + { + continue; + } + + Ver1.dwMinorVersion = Minor; + break; + } + + break; + } + } + + if (Ver1.dwMajorVersion <= 0xF && Ver1.dwMinorVersion <= 0xF) + { + WsVer = (Ver1.wProductType <= VER_NT_WORKSTATION); + switch ((Ver1.dwMajorVersion << 4) | Ver2.dwMinorVersion) + { + case 0x51: + { + Ver = "XP"; + break; + } + case 0x52: + { + Ver = GetSystemMetrics(89) ? "Server 2003 R2" : "Server 2003"; + break; + } + case 0x60: + { + Ver = WsVer ? "Vista" : "Server 2008"; + break; + } + case 0x61: + { + Ver = WsVer ? "7" : "Server 2008 R2"; + break; + } + case 0x62: + { + Ver = WsVer ? "8" : "Server 2012"; + break; + } + case 0x63: + { + Ver = WsVer ? "8.1" : "Server 2012 R2"; + break; + } + case 0x64: + { + Ver = WsVer ? "10 (Preview 1)" : "Server 10 (Preview 1)"; + break; + } + case 0xA0: + { + Ver = WsVer ? "10" : ((Ver1.dwBuildNumber > 15000) ? "Server 2019" : "Server 2016"); + break; + } + default: + { + Ver = "10 or later"; + break; + } + } + } + } + + Bit = IsWow64() ? 64 : 32; + + if (Ver1.wServicePackMinor) + { + safe_sprintf(WinVer, "Windows %s SP%u.%u %d-bit", Ver, Ver1.wServicePackMajor, Ver1.wServicePackMinor, Bit); + } + else if (Ver1.wServicePackMajor) + { + safe_sprintf(WinVer, "Windows %s SP%u %d-bit", Ver, Ver1.wServicePackMajor, Bit); + } + else + { + safe_sprintf(WinVer, "Windows %s %d-bit", Ver, Bit); + } + + if (((Ver1.dwMajorVersion << 4) | Ver2.dwMinorVersion) >= 0x62) + { + Log("Windows Version : %s (Build %u)", WinVer, Ver1.dwBuildNumber); + } + else + { + Log("Windows Version : %s", WinVer); + } + + return; +} + +BOOL IsVentoyLogicalDrive(CHAR DriveLetter) +{ + int i; + CONST CHAR *Files[] = + { + "EFI\\BOOT\\BOOTX64.EFI", + "grub\\themes\\ventoy\\theme.txt", + "ventoy\\ventoy.cpio", + }; + + for (i = 0; i < sizeof(Files) / sizeof(Files[0]); i++) + { + if (!IsFileExist("%C:\\%s", DriveLetter, Files[i])) + { + return FALSE; + } + } + + return TRUE; +} + + +int VentoyFillLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table) +{ + BYTE Head; + BYTE Sector; + BYTE nSector = 63; + BYTE nHead = 8; + UINT32 Cylinder; + UINT32 EndSectorId; + + while (nHead != 0 && (DiskSizeInBytes / 512 / nSector / nHead) > 1024) + { + nHead = (BYTE)nHead * 2; + } + + if (nHead == 0) + { + nHead = 255; + } + + Cylinder = StartSectorId / nSector / nHead; + Head = StartSectorId / nSector % nHead; + Sector = StartSectorId % nSector + 1; + + Table->StartHead = Head; + Table->StartSector = Sector; + Table->StartCylinder = Cylinder; + + EndSectorId = StartSectorId + SectorCount - 1; + Cylinder = EndSectorId / nSector / nHead; + Head = EndSectorId / nSector % nHead; + Sector = EndSectorId % nSector + 1; + + Table->EndHead = Head; + Table->EndSector = Sector; + Table->EndCylinder = Cylinder; + + Table->StartSectorId = StartSectorId; + Table->SectorCount = SectorCount; + + return 0; +} + +int VentoyFillMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR, int PartStyle) +{ + GUID Guid; + int ReservedValue; + UINT32 DiskSignature; + UINT32 DiskSectorCount; + UINT32 PartSectorCount; + UINT32 PartStartSector; + UINT32 ReservedSector; + + VentoyGetLocalBootImg(pMBR); + + CoCreateGuid(&Guid); + + memcpy(&DiskSignature, &Guid, sizeof(UINT32)); + + Log("Disk signature: 0x%08x", DiskSignature); + + *((UINT32 *)(pMBR->BootCode + 0x1B8)) = DiskSignature; + + if (DiskSizeBytes / 512 > 0xFFFFFFFF) + { + DiskSectorCount = 0xFFFFFFFF; + } + else + { + DiskSectorCount = (UINT32)(DiskSizeBytes / 512); + } + + ReservedValue = GetReservedSpaceInMB(); + if (ReservedValue <= 0) + { + ReservedSector = 0; + } + else + { + ReservedSector = (UINT32)(ReservedValue * 2048); + } + + if (PartStyle) + { + ReservedSector += 33; // backup GPT part table + } + + Log("ReservedSector: %u", ReservedSector); + + //Part1 + PartStartSector = VENTOY_PART1_START_SECTOR; + PartSectorCount = DiskSectorCount - ReservedSector - VENTOY_EFI_PART_SIZE / 512 - PartStartSector; + VentoyFillLocation(DiskSizeBytes, PartStartSector, PartSectorCount, pMBR->PartTbl); + + pMBR->PartTbl[0].Active = 0x80; // bootable + pMBR->PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS + + //Part2 + PartStartSector += PartSectorCount; + PartSectorCount = VENTOY_EFI_PART_SIZE / 512; + VentoyFillLocation(DiskSizeBytes, PartStartSector, PartSectorCount, pMBR->PartTbl + 1); + + pMBR->PartTbl[1].Active = 0x00; + pMBR->PartTbl[1].FsFlag = 0xEF; // EFI System Partition + + pMBR->Byte55 = 0x55; + pMBR->ByteAA = 0xAA; + + return 0; +} + + +static int VentoyFillProtectMBR(UINT64 DiskSizeBytes, MBR_HEAD *pMBR) +{ + GUID Guid; + UINT32 DiskSignature; + UINT64 DiskSectorCount; + + VentoyGetLocalBootImg(pMBR); + + CoCreateGuid(&Guid); + + memcpy(&DiskSignature, &Guid, sizeof(UINT32)); + + Log("Disk signature: 0x%08x", DiskSignature); + + *((UINT32 *)(pMBR->BootCode + 0x1B8)) = DiskSignature; + + DiskSectorCount = DiskSizeBytes / 512 - 1; + if (DiskSectorCount > 0xFFFFFFFF) + { + DiskSectorCount = 0xFFFFFFFF; + } + + memset(pMBR->PartTbl, 0, sizeof(pMBR->PartTbl)); + + pMBR->PartTbl[0].Active = 0x00; + pMBR->PartTbl[0].FsFlag = 0xee; // EE + + pMBR->PartTbl[0].StartHead = 0; + pMBR->PartTbl[0].StartSector = 1; + pMBR->PartTbl[0].StartCylinder = 0; + pMBR->PartTbl[0].EndHead = 254; + pMBR->PartTbl[0].EndSector = 63; + pMBR->PartTbl[0].EndCylinder = 1023; + + pMBR->PartTbl[0].StartSectorId = 1; + pMBR->PartTbl[0].SectorCount = (UINT32)DiskSectorCount; + + pMBR->Byte55 = 0x55; + pMBR->ByteAA = 0xAA; + + pMBR->BootCode[92] = 0x22; + + return 0; +} + + +int VentoyFillGpt(UINT64 DiskSizeBytes, VTOY_GPT_INFO *pInfo) +{ + INT64 ReservedValue = 0; + UINT64 ReservedSector = 33; + UINT64 Part1SectorCount = 0; + UINT64 DiskSectorCount = DiskSizeBytes / 512; + VTOY_GPT_HDR *Head = &pInfo->Head; + VTOY_GPT_PART_TBL *Table = pInfo->PartTbl; + 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 BiosGrubPartType = { 0x21686148, 0x6449, 0x6e6f, { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } }; + + VentoyFillProtectMBR(DiskSizeBytes, &pInfo->MBR); + + ReservedValue = GetReservedSpaceInMB(); + if (ReservedValue > 0) + { + ReservedSector += ReservedValue * 2048; + } + + Part1SectorCount = DiskSectorCount - ReservedSector - (VENTOY_EFI_PART_SIZE / 512) - 2048; + + memcpy(Head->Signature, "EFI PART", 8); + Head->Version[2] = 0x01; + Head->Length = 92; + Head->Crc = 0; + Head->EfiStartLBA = 1; + Head->EfiBackupLBA = DiskSectorCount - 1; + Head->PartAreaStartLBA = 34; + Head->PartAreaEndLBA = DiskSectorCount - 34; + CoCreateGuid(&Head->DiskGuid); + Head->PartTblStartLBA = 2; + Head->PartTblTotNum = 128; + Head->PartTblEntryLen = 128; + + + memcpy(&(Table[0].PartType), &WindowsDataPartType, sizeof(GUID)); + CoCreateGuid(&(Table[0].PartGuid)); + Table[0].StartLBA = 2048; + Table[0].LastLBA = 2048 + Part1SectorCount - 1; + Table[0].Attr = 0; + memcpy(Table[0].Name, L"Ventoy", 6 * 2); + + // to fix windows issue + //memcpy(&(Table[1].PartType), &EspPartType, sizeof(GUID)); + memcpy(&(Table[1].PartType), &WindowsDataPartType, sizeof(GUID)); + CoCreateGuid(&(Table[1].PartGuid)); + Table[1].StartLBA = Table[0].LastLBA + 1; + Table[1].LastLBA = Table[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1; + Table[1].Attr = 0xC000000000000001ULL; + memcpy(Table[1].Name, L"VTOYEFI", 7 * 2); + +#if 0 + memcpy(&(Table[2].PartType), &BiosGrubPartType, sizeof(GUID)); + CoCreateGuid(&(Table[2].PartGuid)); + Table[2].StartLBA = 34; + Table[2].LastLBA = 2047; + Table[2].Attr = 0; +#endif + + //Update CRC + Head->PartTblCrc = VentoyCrc32(Table, sizeof(pInfo->PartTbl)); + Head->Crc = VentoyCrc32(Head, Head->Length); + + return 0; +} + +int VentoyFillBackupGptHead(VTOY_GPT_INFO *pInfo, VTOY_GPT_HDR *pHead) +{ + UINT64 LBA; + UINT64 BackupLBA; + + memcpy(pHead, &pInfo->Head, sizeof(VTOY_GPT_HDR)); + + LBA = pHead->EfiStartLBA; + BackupLBA = pHead->EfiBackupLBA; + + pHead->EfiStartLBA = BackupLBA; + pHead->EfiBackupLBA = LBA; + pHead->PartTblStartLBA = BackupLBA + 1 - 33; + + pHead->Crc = 0; + pHead->Crc = VentoyCrc32(pHead, pHead->Length); + + return 0; +} + +CHAR GetFirstUnusedDriveLetter(void) +{ + CHAR Letter = 'D'; + DWORD Drives = GetLogicalDrives(); + + Drives >>= 3; + while (Drives & 0x1) + { + Letter++; + Drives >>= 1; + } + + return Letter; +} + +const CHAR * GetBusTypeString(STORAGE_BUS_TYPE Type) +{ + switch (Type) + { + case BusTypeUnknown: return "unknown"; + case BusTypeScsi: return "SCSI"; + case BusTypeAtapi: return "Atapi"; + case BusTypeAta: return "ATA"; + case BusType1394: return "1394"; + case BusTypeSsa: return "SSA"; + case BusTypeFibre: return "Fibre"; + case BusTypeUsb: return "USB"; + case BusTypeRAID: return "RAID"; + case BusTypeiScsi: return "iSCSI"; + case BusTypeSas: return "SAS"; + case BusTypeSata: return "SATA"; + case BusTypeSd: return "SD"; + case BusTypeMmc: return "MMC"; + case BusTypeVirtual: return "Virtual"; + case BusTypeFileBackedVirtual: return "FileBackedVirtual"; + case BusTypeSpaces: return "Spaces"; + case BusTypeNvme: return "Nvme"; + } + return "unknown"; +} + +int VentoyGetLocalBootImg(MBR_HEAD *pMBR) +{ + int Len = 0; + BYTE *ImgBuf = NULL; + static int Loaded = 0; + static MBR_HEAD MBR; + + if (Loaded) + { + memcpy(pMBR, &MBR, 512); + return 0; + } + + if (0 == ReadWholeFileToBuf(VENTOY_FILE_BOOT_IMG, 0, (void **)&ImgBuf, &Len)) + { + Log("Copy boot img success"); + memcpy(pMBR, ImgBuf, 512); + free(ImgBuf); + + CoCreateGuid((GUID *)(pMBR->BootCode + 0x180)); + + memcpy(&MBR, pMBR, 512); + Loaded = 1; + + return 0; + } + else + { + Log("Copy boot img failed"); + return 1; + } +} + +int GetHumanReadableGBSize(UINT64 SizeBytes) +{ + int i; + int Pow2 = 1; + double Delta; + double GB = SizeBytes * 1.0 / 1000 / 1000 / 1000; + + for (i = 0; i < 12; i++) + { + if (Pow2 > GB) + { + Delta = (Pow2 - GB) / Pow2; + } + else + { + Delta = (GB - Pow2) / Pow2; + } + + if (Delta < 0.05) + { + return Pow2; + } + + Pow2 <<= 1; + } + + return (int)GB; +} + +void TrimString(CHAR *String) +{ + CHAR *Pos1 = String; + CHAR *Pos2 = String; + size_t Len = strlen(String); + + while (Len > 0) + { + if (String[Len - 1] != ' ' && String[Len - 1] != '\t') + { + break; + } + String[Len - 1] = 0; + Len--; + } + + while (*Pos1 == ' ' || *Pos1 == '\t') + { + Pos1++; + } + + while (*Pos1) + { + *Pos2++ = *Pos1++; + } + *Pos2++ = 0; + + return; +} + +int GetRegDwordValue(HKEY Key, LPCSTR SubKey, LPCSTR ValueName, DWORD *pValue) +{ + HKEY hKey; + DWORD Type; + DWORD Size; + LSTATUS lRet; + DWORD Value; + + lRet = RegOpenKeyExA(Key, SubKey, 0, KEY_QUERY_VALUE, &hKey); + Log("RegOpenKeyExA <%s> Ret:%ld", SubKey, lRet); + + if (ERROR_SUCCESS == lRet) + { + Size = sizeof(Value); + lRet = RegQueryValueExA(hKey, ValueName, NULL, &Type, (LPBYTE)&Value, &Size); + Log("RegQueryValueExA <%s> ret:%u Size:%u Value:%u", ValueName, lRet, Size, Value); + + *pValue = Value; + RegCloseKey(hKey); + + return 0; + } + else + { + return 1; + } +} + +int GetPhysicalDriveCount(void) +{ + DWORD Value; + int Count = 0; + + if (GetRegDwordValue(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", "Count", &Value) == 0) + { + Count = (int)Value; + } + + Log("GetPhysicalDriveCount: %d", Count); + return Count; +} + + + diff --git a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.rc b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.rc index 03a4a003..b8d9b67f 100644 Binary files a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.rc and b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.rc differ diff --git a/Ventoy2Disk/Ventoy2Disk/WinDialog.c b/Ventoy2Disk/Ventoy2Disk/WinDialog.c index 814ba277..b72d22f4 100644 Binary files a/Ventoy2Disk/Ventoy2Disk/WinDialog.c and b/Ventoy2Disk/Ventoy2Disk/WinDialog.c differ diff --git a/vtoygpt/build.sh b/vtoygpt/build.sh new file mode 100644 index 00000000..a8c3f7ed --- /dev/null +++ b/vtoygpt/build.sh @@ -0,0 +1,19 @@ +#!/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 + diff --git a/vtoygpt/crc32.c b/vtoygpt/crc32.c new file mode 100644 index 00000000..354372b8 --- /dev/null +++ b/vtoygpt/crc32.c @@ -0,0 +1,315 @@ +/****************************************************************************** + * vtoygpt.c ---- ventoy gpt util + * + * Copyright (c) 2020, longpanda + * + * 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 . + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} + diff --git a/vtoygpt/vtoygpt.c b/vtoygpt/vtoygpt.c new file mode 100644 index 00000000..705f750d --- /dev/null +++ b/vtoygpt/vtoygpt.c @@ -0,0 +1,320 @@ +/****************************************************************************** + * vtoygpt.c ---- ventoy gpt util + * + * Copyright (c) 2020, longpanda + * + * 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 . + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} +