]> glassweightruler.freedombox.rocks Git - Ventoy.git/commitdiff
1.0.86 release v1.0.86
authorlongpanda <admin@ventoy.net>
Sat, 24 Dec 2022 13:19:31 +0000 (21:19 +0800)
committerlongpanda <admin@ventoy.net>
Sat, 24 Dec 2022 13:19:31 +0000 (21:19 +0800)
12 files changed:
INSTALL/Ventoy2Disk.exe
INSTALL/Ventoy2Disk_ARM.exe
INSTALL/Ventoy2Disk_ARM64.exe
INSTALL/Ventoy2Disk_X64.exe
INSTALL/grub/grub.cfg
Ventoy2Disk/Ventoy2Disk/PartDialog.c
Ventoy2Disk/Ventoy2Disk/Utility.c
Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c
Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.h
Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.vcxproj
Ventoy2Disk/Ventoy2Disk/WinDialog.c
Ventoy2Disk/Ventoy2Disk/ventoy_cli.c [new file with mode: 0644]

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