diff --git a/INSTALL/Ventoy2Disk.exe b/INSTALL/Ventoy2Disk.exe index 7fed29a8..505927dd 100644 Binary files a/INSTALL/Ventoy2Disk.exe and b/INSTALL/Ventoy2Disk.exe differ diff --git a/INSTALL/Ventoy2Disk_ARM.exe b/INSTALL/Ventoy2Disk_ARM.exe index 295864b3..83073e1d 100644 Binary files a/INSTALL/Ventoy2Disk_ARM.exe and b/INSTALL/Ventoy2Disk_ARM.exe differ diff --git a/INSTALL/Ventoy2Disk_ARM64.exe b/INSTALL/Ventoy2Disk_ARM64.exe index 8d68a228..ef820063 100644 Binary files a/INSTALL/Ventoy2Disk_ARM64.exe and b/INSTALL/Ventoy2Disk_ARM64.exe differ diff --git a/INSTALL/Ventoy2Disk_X64.exe b/INSTALL/Ventoy2Disk_X64.exe index ff71dd16..44fe8e4b 100644 Binary files a/INSTALL/Ventoy2Disk_X64.exe and b/INSTALL/Ventoy2Disk_X64.exe differ diff --git a/INSTALL/grub/grub.cfg b/INSTALL/grub/grub.cfg index 5cc8079e..064542ba 100644 --- a/INSTALL/grub/grub.cfg +++ b/INSTALL/grub/grub.cfg @@ -2397,7 +2397,7 @@ function mimg_common_menuentry { ############################################################# ############################################################# -set VENTOY_VERSION="1.0.85" +set VENTOY_VERSION="1.0.86" #ACPI not compatible with Window7/8, so disable by default set VTOY_PARAM_NO_ACPI=1 diff --git a/Ventoy2Disk/Ventoy2Disk/PartDialog.c b/Ventoy2Disk/Ventoy2Disk/PartDialog.c index 46450d1f..eb4aa0d9 100644 Binary files a/Ventoy2Disk/Ventoy2Disk/PartDialog.c and b/Ventoy2Disk/Ventoy2Disk/PartDialog.c differ diff --git a/Ventoy2Disk/Ventoy2Disk/Utility.c b/Ventoy2Disk/Ventoy2Disk/Utility.c index 80cd6baa..dc9464a8 100644 --- a/Ventoy2Disk/Ventoy2Disk/Utility.c +++ b/Ventoy2Disk/Ventoy2Disk/Utility.c @@ -56,21 +56,23 @@ void Log(const char *Fmt, ...) Sys.wMilliseconds); va_start(Arg, Fmt); - Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg); + Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len - 1, sizeof(szBuf)-Len-1, Fmt, Arg); va_end(Arg); - //printf("%s\n", szBuf); - -#if 1 - fopen_s(&File, VENTOY_FILE_LOG, "a+"); + if (g_CLI_Mode) + { + fopen_s(&File, VENTOY_CLI_LOG, "a+"); + } + else + { + fopen_s(&File, VENTOY_FILE_LOG, "a+"); + } if (File) { fwrite(szBuf, 1, Len, File); fwrite("\n", 1, 1, File); fclose(File); } -#endif - } const char* GUID2String(void *guid, char *buf, int len) diff --git a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c index 0e0fe67b..68520a06 100644 --- a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c +++ b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c @@ -76,7 +76,7 @@ int ParseCmdLineOption(LPSTR lpCmdLine) return 0; } -static BOOL IsVentoyPhyDrive(int PhyDrive, UINT64 SizeBytes, MBR_HEAD *pMBR, UINT64 *Part2StartSector, UINT64 *GptPart2Attr) +BOOL IsVentoyPhyDrive(int PhyDrive, UINT64 SizeBytes, MBR_HEAD *pMBR, UINT64 *Part2StartSector, UINT64 *GptPart2Attr) { int i; BOOL bRet; @@ -274,7 +274,7 @@ int GetVolumeClusterSize(char Drive) return 0; } -static int GetVentoyFsNameInPhyDrive(PHY_DRIVE_INFO* CurDrive) +int GetVentoyFsNameInPhyDrive(PHY_DRIVE_INFO* CurDrive) { int i = 0; UINT64 Offset; diff --git a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h index 84d98b59..1a0a453f 100644 --- a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h +++ b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h @@ -48,6 +48,11 @@ typedef enum VTOY_FS #define VENTOY_FILE_LOG "log.txt" #define VENTOY_FILE_VERSION "ventoy\\version" +#define VENTOY_CLI_LOG "cli_log.txt" +#define VENTOY_CLI_PERCENT "cli_percent.txt" +#define VENTOY_CLI_DONE "cli_done.txt" + + #define DRIVE_ACCESS_TIMEOUT 15000 // How long we should retry drive access (in ms) #define DRIVE_ACCESS_RETRIES 150 // How many times we should retry @@ -345,6 +350,8 @@ extern int __static_assert__[sizeof(VTSI_FOOTER) == 512 ? 1 : -1]; extern HWND g_DialogHwnd; +extern BOOL g_CLI_Mode; + #define SAFE_FREE(ptr) if (ptr) { free(ptr); (ptr) = NULL; } int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle); void disk_io_set_imghook(FILE *fp, VTSI_SEGMENT *segment, int maxseg, UINT64 data_offset); @@ -358,6 +365,11 @@ const char* GUID2String(void* guid, char* buf, int len); void VentoyStringToUpper(CHAR* str); BOOL AlertSuppressInit(void); void SetAlertPromptHookEnable(BOOL enable); +int VentoyCLIMain(int argc, char** argv); +BOOL IsVentoyPhyDrive(int PhyDrive, UINT64 SizeBytes, MBR_HEAD* pMBR, UINT64* Part2StartSector, UINT64* GptPart2Attr); +int GetVentoyFsNameInPhyDrive(PHY_DRIVE_INFO* CurDrive); +void CLISetReserveSpace(int MB); +void CLI_UpdatePercent(int Pos); #define VTSI_SUPPORT 1 diff --git a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj index 451dae83..e2df9e18 100644 --- a/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj +++ b/Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj @@ -367,6 +367,7 @@ + diff --git a/Ventoy2Disk/Ventoy2Disk/WinDialog.c b/Ventoy2Disk/Ventoy2Disk/WinDialog.c index 2e4a3692..40a8ab63 100644 Binary files a/Ventoy2Disk/Ventoy2Disk/WinDialog.c and b/Ventoy2Disk/Ventoy2Disk/WinDialog.c differ diff --git a/Ventoy2Disk/Ventoy2Disk/ventoy_cli.c b/Ventoy2Disk/Ventoy2Disk/ventoy_cli.c new file mode 100644 index 00000000..10c8ffe9 --- /dev/null +++ b/Ventoy2Disk/Ventoy2Disk/ventoy_cli.c @@ -0,0 +1,411 @@ +#include +#include +#include +#include +#include +#include "resource.h" +#include "Language.h" +#include "Ventoy2Disk.h" +#include "DiskService.h" +#include "VentoyJson.h" + +extern void CLISetReserveSpace(int MB); + +typedef struct CLI_CFG +{ + int op; + int PartStyle; + int ReserveMB; + BOOL USBCheck; +}CLI_CFG; + +BOOL g_CLI_Mode = FALSE; +static int g_CLI_OP; +static int g_CLI_PhyDrive; + +static int CLI_GetPhyDriveInfo(int PhyDrive, PHY_DRIVE_INFO* pInfo) +{ + BOOL bRet; + DWORD dwBytes; + HANDLE Handle = INVALID_HANDLE_VALUE; + CHAR PhyDrivePath[128]; + GET_LENGTH_INFORMATION LengthInfo; + STORAGE_PROPERTY_QUERY Query; + STORAGE_DESCRIPTOR_HEADER DevDescHeader; + STORAGE_DEVICE_DESCRIPTOR* pDevDesc; + + safe_sprintf(PhyDrivePath, "\\\\.\\PhysicalDrive%d", PhyDrive); + Handle = CreateFileA(PhyDrivePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + Log("Create file Handle:%p %s status:%u", Handle, PhyDrivePath, LASTERR); + + if (Handle == INVALID_HANDLE_VALUE) + { + return 1; + } + + 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); + return 1; + } + + Log("PHYSICALDRIVE%d size %llu bytes", PhyDrive, (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); + return 1; + } + + if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR)) + { + Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size); + return 1; + } + + pDevDesc = (STORAGE_DEVICE_DESCRIPTOR*)malloc(DevDescHeader.Size); + if (!pDevDesc) + { + Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size); + return 1; + } + + 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); + return 1; + } + + pInfo->PhyDrive = PhyDrive; + pInfo->SizeInBytes = LengthInfo.Length.QuadPart; + pInfo->DeviceType = pDevDesc->DeviceType; + pInfo->RemovableMedia = pDevDesc->RemovableMedia; + pInfo->BusType = pDevDesc->BusType; + + if (pDevDesc->VendorIdOffset) + { + safe_strcpy(pInfo->VendorId, (char*)pDevDesc + pDevDesc->VendorIdOffset); + TrimString(pInfo->VendorId); + } + + if (pDevDesc->ProductIdOffset) + { + safe_strcpy(pInfo->ProductId, (char*)pDevDesc + pDevDesc->ProductIdOffset); + TrimString(pInfo->ProductId); + } + + if (pDevDesc->ProductRevisionOffset) + { + safe_strcpy(pInfo->ProductRev, (char*)pDevDesc + pDevDesc->ProductRevisionOffset); + TrimString(pInfo->ProductRev); + } + + if (pDevDesc->SerialNumberOffset) + { + safe_strcpy(pInfo->SerialNumber, (char*)pDevDesc + pDevDesc->SerialNumberOffset); + TrimString(pInfo->SerialNumber); + } + + free(pDevDesc); + + CHECK_CLOSE_HANDLE(Handle); + + return 0; +} + +static int CLI_CheckParam(int argc, char** argv, PHY_DRIVE_INFO* pDrvInfo, CLI_CFG *pCfg) +{ + int i; + int op = -1; + char* opt = NULL; + int PhyDrive = -1; + int PartStyle = 0; + int ReserveMB = 0; + BOOL USBCheck = TRUE; + MBR_HEAD MBR; + UINT64 Part2GPTAttr = 0; + UINT64 Part2StartSector = 0; + + for (i = 0; i < argc; i++) + { + opt = argv[i]; + if (_stricmp(opt, "/I") == 0) + { + op = 0; + } + else if (_stricmp(opt, "/U") == 0) + { + op = 1; + } + else if (_stricmp(opt, "/GPT") == 0) + { + PartStyle = 1; + } + else if (_stricmp(opt, "/NoSB") == 0) + { + g_SecureBoot = FALSE; + } + else if (_stricmp(opt, "/NoUSBCheck") == 0) + { + USBCheck = FALSE; + } + else if (_strnicmp(opt, "/Drive:", 7) == 0) + { + Log("Get PhyDrive by logical drive %C:", opt[7]); + PhyDrive = GetPhyDriveByLogicalDrive(opt[7], NULL); + } + else if (_strnicmp(opt, "/PhyDrive:", 10) == 0) + { + PhyDrive = (int)strtol(opt + 10, NULL, 10); + } + else if (_strnicmp(opt, "/R:", 3) == 0) + { + ReserveMB = (int)strtol(opt + 3, NULL, 10); + } + } + + if (op < 0 || PhyDrive < 0) + { + Log("[ERROR] Invalid parameters %d %d", op, PhyDrive); + return 1; + } + + Log("Ventoy CLI %s PhyDrive:%d %s SecureBoot:%d ReserveSpace:%dMB USBCheck:%u", + op == 0 ? "install" : "update", + PhyDrive, PartStyle ? "GPT" : "MBR", + g_SecureBoot, ReserveMB, USBCheck + ); + + if (CLI_GetPhyDriveInfo(PhyDrive, pDrvInfo)) + { + Log("[ERROR] Failed to get phydrive%d info", PhyDrive); + return 1; + } + + Log("PhyDrive:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s", + pDrvInfo->PhyDrive, GetBusTypeString(pDrvInfo->BusType), pDrvInfo->RemovableMedia, + GetHumanReadableGBSize(pDrvInfo->SizeInBytes), pDrvInfo->SizeInBytes, + pDrvInfo->VendorId, pDrvInfo->ProductId); + + if (IsVentoyPhyDrive(PhyDrive, pDrvInfo->SizeInBytes, &MBR, &Part2StartSector, &Part2GPTAttr)) + { + memcpy(&(pDrvInfo->MBR), &MBR, sizeof(MBR)); + pDrvInfo->PartStyle = (MBR.PartTbl[0].FsFlag == 0xEE) ? 1 : 0; + pDrvInfo->Part2GPTAttr = Part2GPTAttr; + GetVentoyVerInPhyDrive(pDrvInfo, Part2StartSector, pDrvInfo->VentoyVersion, sizeof(pDrvInfo->VentoyVersion), &(pDrvInfo->SecureBootSupport)); + Log("PhyDrive %d is Ventoy Disk ver:%s SecureBoot:%u", pDrvInfo->PhyDrive, pDrvInfo->VentoyVersion, pDrvInfo->SecureBootSupport); + + GetVentoyFsNameInPhyDrive(pDrvInfo); + + if (pDrvInfo->VentoyVersion[0] == 0) + { + pDrvInfo->VentoyVersion[0] = '?'; + Log("Unknown Ventoy Version"); + } + } + + pCfg->op = op; + pCfg->PartStyle = PartStyle; + pCfg->ReserveMB = ReserveMB; + pCfg->USBCheck = USBCheck; + + return 0; +} + +static int Ventoy_CLI_Install(PHY_DRIVE_INFO* pDrvInfo, CLI_CFG *pCfg) +{ + int rc; + int TryId = 1; + + Log("Ventoy_CLI_Install start ..."); + + if (pCfg->ReserveMB > 0) + { + CLISetReserveSpace(pCfg->ReserveMB); + } + + rc = InstallVentoy2PhyDrive(pDrvInfo, pCfg->PartStyle, TryId++); + if (rc) + { + Log("This time install failed, clean disk by disk, wait 3s and retry..."); + DISK_CleanDisk(pDrvInfo->PhyDrive); + + Sleep(3000); + + Log("Now retry to install..."); + rc = InstallVentoy2PhyDrive(pDrvInfo, pCfg->PartStyle, TryId++); + + if (rc) + { + Log("This time install failed, clean disk by diskpart, wait 5s and retry..."); + DSPT_CleanDisk(pDrvInfo->PhyDrive); + + Sleep(5000); + + Log("Now retry to install..."); + rc = InstallVentoy2PhyDrive(pDrvInfo, pCfg->PartStyle, TryId++); + } + } + + Log("Ventoy_CLI_Install [%s]", rc == 0 ? "SUCCESS" : "FAILED"); + + return rc; +} + +static int Ventoy_CLI_Update(PHY_DRIVE_INFO* pDrvInfo, CLI_CFG* pCfg) +{ + int rc; + int TryId = 1; + + Log("Ventoy_CLI_Update start ..."); + + rc = UpdateVentoy2PhyDrive(pDrvInfo, TryId++); + if (rc) + { + Log("This time update failed, now wait and retry..."); + Sleep(4000); + + //Try2 + Log("Now retry to update..."); + rc = UpdateVentoy2PhyDrive(pDrvInfo, TryId++); + if (rc) + { + //Try3 + Sleep(1000); + Log("Now retry to update..."); + rc = UpdateVentoy2PhyDrive(pDrvInfo, TryId++); + if (rc) + { + //Try4 is dangerous ... + Sleep(3000); + Log("Now retry to update..."); + rc = UpdateVentoy2PhyDrive(pDrvInfo, TryId++); + } + } + } + + Log("Ventoy_CLI_Update [%s]", rc == 0 ? "SUCCESS" : "FAILED"); + + return rc; +} + +void CLI_UpdatePercent(int Pos) +{ + int Len; + FILE* File = NULL; + CHAR szBuf[128]; + + Len = (int)sprintf_s(szBuf, sizeof(szBuf), "%d", Pos * 100 / PT_FINISH); + fopen_s(&File, VENTOY_CLI_PERCENT, "w+"); + if (File) + { + fwrite(szBuf, 1, Len, File); + fwrite("\n", 1, 1, File); + fclose(File); + } +} + +static void CLI_WriteDoneFile(int ret) +{ + FILE* File = NULL; + + fopen_s(&File, VENTOY_CLI_DONE, "w+"); + if (File) + { + if (ret == 0) + { + fwrite("0\n", 1, 2, File); + } + else + { + fwrite("1\n", 1, 2, File); + } + fclose(File); + } +} + +/* + * Ventoy2Disk.exe VTOYCLI { /I | /U } { /Drive:F: | /PhyDrive:1 } /GPT /NoSB /R:4096 /NoUSBCheck + * + */ +int VentoyCLIMain(int argc, char** argv) +{ + int ret = 1; + PHY_DRIVE_INFO* pDrvInfo = NULL; + CLI_CFG CliCfg; + + DeleteFileA(VENTOY_CLI_PERCENT); + DeleteFileA(VENTOY_CLI_DONE); + + pDrvInfo = (PHY_DRIVE_INFO*)malloc(sizeof(PHY_DRIVE_INFO)); + if (!pDrvInfo) + { + goto end; + } + memset(pDrvInfo, 0, sizeof(PHY_DRIVE_INFO)); + + if (CLI_CheckParam(argc, argv, pDrvInfo, &CliCfg)) + { + goto end; + } + + //Check USB type for install + if (CliCfg.op == 0 && CliCfg.USBCheck) + { + if (pDrvInfo->BusType != BusTypeUsb) + { + Log("[ERROR] PhyDrive %d is NOT USB type", pDrvInfo->PhyDrive); + goto end; + } + } + + if (CliCfg.op == 0) + { + ret = Ventoy_CLI_Install(pDrvInfo, &CliCfg); + } + else + { + if (pDrvInfo->VentoyVersion[0] == 0) + { + Log("[ERROR] No Ventoy information detected in PhyDrive %d, so can not do update", pDrvInfo->PhyDrive); + goto end; + } + + ret = Ventoy_CLI_Update(pDrvInfo, &CliCfg); + } + +end: + CHECK_FREE(pDrvInfo); + + CLI_UpdatePercent(PT_FINISH); + CLI_WriteDoneFile(ret); + + return ret; +}