8 #include "Ventoy2Disk.h"
9 #include "DiskService.h"
10 #include "VentoyJson.h"
12 extern void CLISetReserveSpace(int MB
);
14 typedef struct CLI_CFG
24 BOOL g_CLI_Mode
= FALSE
;
26 static int g_CLI_PhyDrive
;
28 static PHY_DRIVE_INFO
* g_CLI_PhyDrvInfo
= NULL
;
30 static int CLI_GetPhyDriveInfo(int PhyDrive
, PHY_DRIVE_INFO
* pInfo
)
34 HANDLE Handle
= INVALID_HANDLE_VALUE
;
35 CHAR PhyDrivePath
[128];
36 GET_LENGTH_INFORMATION LengthInfo
;
37 STORAGE_PROPERTY_QUERY Query
;
38 STORAGE_DESCRIPTOR_HEADER DevDescHeader
;
39 STORAGE_DEVICE_DESCRIPTOR
* pDevDesc
;
40 STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment
;
42 safe_sprintf(PhyDrivePath
, "\\\\.\\PhysicalDrive%d", PhyDrive
);
43 Handle
= CreateFileA(PhyDrivePath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
44 Log("Create file Handle:%p %s status:%u", Handle
, PhyDrivePath
, LASTERR
);
46 if (Handle
== INVALID_HANDLE_VALUE
)
51 bRet
= DeviceIoControl(Handle
,
52 IOCTL_DISK_GET_LENGTH_INFO
, NULL
,
60 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR
);
64 Log("PHYSICALDRIVE%d size %llu bytes", PhyDrive
, (ULONGLONG
)LengthInfo
.Length
.QuadPart
);
66 Query
.PropertyId
= StorageDeviceProperty
;
67 Query
.QueryType
= PropertyStandardQuery
;
69 bRet
= DeviceIoControl(Handle
,
70 IOCTL_STORAGE_QUERY_PROPERTY
,
74 sizeof(STORAGE_DESCRIPTOR_HEADER
),
79 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR
, dwBytes
);
83 if (DevDescHeader
.Size
< sizeof(STORAGE_DEVICE_DESCRIPTOR
))
85 Log("Invalid DevDescHeader.Size:%u", DevDescHeader
.Size
);
89 pDevDesc
= (STORAGE_DEVICE_DESCRIPTOR
*)malloc(DevDescHeader
.Size
);
92 Log("failed to malloc error:%u len:%u", LASTERR
, DevDescHeader
.Size
);
96 bRet
= DeviceIoControl(Handle
,
97 IOCTL_STORAGE_QUERY_PROPERTY
,
106 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR
, dwBytes
);
112 memset(&Query
, 0, sizeof(STORAGE_PROPERTY_QUERY
));
113 Query
.PropertyId
= StorageAccessAlignmentProperty
;
114 Query
.QueryType
= PropertyStandardQuery
;
115 memset(&diskAlignment
, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
));
117 bRet
= DeviceIoControl(Handle
,
118 IOCTL_STORAGE_QUERY_PROPERTY
,
120 sizeof(STORAGE_PROPERTY_QUERY
),
122 sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
),
127 Log("DeviceIoControl3 error:%u dwBytes:%u", LASTERR
, dwBytes
);
131 pInfo
->PhyDrive
= PhyDrive
;
132 pInfo
->SizeInBytes
= LengthInfo
.Length
.QuadPart
;
133 pInfo
->DeviceType
= pDevDesc
->DeviceType
;
134 pInfo
->RemovableMedia
= pDevDesc
->RemovableMedia
;
135 pInfo
->BusType
= pDevDesc
->BusType
;
137 pInfo
->BytesPerLogicalSector
= diskAlignment
.BytesPerLogicalSector
;
138 pInfo
->BytesPerPhysicalSector
= diskAlignment
.BytesPerPhysicalSector
;
140 if (pDevDesc
->VendorIdOffset
)
142 safe_strcpy(pInfo
->VendorId
, (char*)pDevDesc
+ pDevDesc
->VendorIdOffset
);
143 TrimString(pInfo
->VendorId
);
146 if (pDevDesc
->ProductIdOffset
)
148 safe_strcpy(pInfo
->ProductId
, (char*)pDevDesc
+ pDevDesc
->ProductIdOffset
);
149 TrimString(pInfo
->ProductId
);
152 if (pDevDesc
->ProductRevisionOffset
)
154 safe_strcpy(pInfo
->ProductRev
, (char*)pDevDesc
+ pDevDesc
->ProductRevisionOffset
);
155 TrimString(pInfo
->ProductRev
);
158 if (pDevDesc
->SerialNumberOffset
)
160 safe_strcpy(pInfo
->SerialNumber
, (char*)pDevDesc
+ pDevDesc
->SerialNumberOffset
);
161 TrimString(pInfo
->SerialNumber
);
166 CHECK_CLOSE_HANDLE(Handle
);
171 static int CLI_CheckParam(int argc
, char** argv
, PHY_DRIVE_INFO
* pDrvInfo
, CLI_CFG
*pCfg
)
174 int fstype
= VTOY_FS_EXFAT
;
180 BOOL USBCheck
= TRUE
;
181 BOOL NonDest
= FALSE
;
183 UINT64 Part2GPTAttr
= 0;
184 UINT64 Part2StartSector
= 0;
186 for (i
= 0; i
< argc
; i
++)
189 if (_stricmp(opt
, "/I") == 0)
193 else if (_stricmp(opt
, "/U") == 0)
197 else if (_stricmp(opt
, "/GPT") == 0)
201 else if (_stricmp(opt
, "/NoSB") == 0)
203 g_SecureBoot
= FALSE
;
205 else if (_stricmp(opt
, "/NoUSBCheck") == 0)
209 else if (_stricmp(opt
, "/NonDest") == 0)
213 else if (_strnicmp(opt
, "/Drive:", 7) == 0)
215 Log("Get PhyDrive by logical drive %C:", opt
[7]);
216 PhyDrive
= GetPhyDriveByLogicalDrive(opt
[7], NULL
);
218 else if (_strnicmp(opt
, "/PhyDrive:", 10) == 0)
220 PhyDrive
= (int)strtol(opt
+ 10, NULL
, 10);
222 else if (_strnicmp(opt
, "/R:", 3) == 0)
224 ReserveMB
= (int)strtol(opt
+ 3, NULL
, 10);
226 else if (_strnicmp(opt
, "/FS:", 4) == 0)
228 if (_stricmp(opt
+ 4, "NTFS") == 0)
230 fstype
= VTOY_FS_NTFS
;
232 else if (_stricmp(opt
+ 4, "FAT32") == 0)
234 fstype
= VTOY_FS_FAT32
;
236 else if (_stricmp(opt
+ 4, "UDF") == 0)
238 fstype
= VTOY_FS_UDF
;
243 if (op
< 0 || PhyDrive
< 0)
245 Log("[ERROR] Invalid parameters %d %d", op
, PhyDrive
);
249 Log("Ventoy CLI %s PhyDrive:%d %s SecureBoot:%d ReserveSpace:%dMB USBCheck:%u FS:%s NonDest:%d",
250 op
== 0 ? "install" : "update",
251 PhyDrive
, PartStyle
? "GPT" : "MBR",
252 g_SecureBoot
, ReserveMB
, USBCheck
, GetVentoyFsFmtNameByTypeA(fstype
), NonDest
255 if (CLI_GetPhyDriveInfo(PhyDrive
, pDrvInfo
))
257 Log("[ERROR] Failed to get phydrive%d info", PhyDrive
);
261 Log("PhyDrive:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
262 pDrvInfo
->PhyDrive
, GetBusTypeString(pDrvInfo
->BusType
), pDrvInfo
->RemovableMedia
,
263 GetHumanReadableGBSize(pDrvInfo
->SizeInBytes
), pDrvInfo
->SizeInBytes
,
264 pDrvInfo
->VendorId
, pDrvInfo
->ProductId
);
266 if (IsVentoyPhyDrive(PhyDrive
, pDrvInfo
->SizeInBytes
, &MBR
, &Part2StartSector
, &Part2GPTAttr
))
268 memcpy(&(pDrvInfo
->MBR
), &MBR
, sizeof(MBR
));
269 pDrvInfo
->PartStyle
= (MBR
.PartTbl
[0].FsFlag
== 0xEE) ? 1 : 0;
270 pDrvInfo
->Part2GPTAttr
= Part2GPTAttr
;
271 GetVentoyVerInPhyDrive(pDrvInfo
, Part2StartSector
, pDrvInfo
->VentoyVersion
, sizeof(pDrvInfo
->VentoyVersion
), &(pDrvInfo
->SecureBootSupport
));
272 Log("PhyDrive %d is Ventoy Disk ver:%s SecureBoot:%u", pDrvInfo
->PhyDrive
, pDrvInfo
->VentoyVersion
, pDrvInfo
->SecureBootSupport
);
274 GetVentoyFsNameInPhyDrive(pDrvInfo
);
276 if (pDrvInfo
->VentoyVersion
[0] == 0)
278 pDrvInfo
->VentoyVersion
[0] = '?';
279 Log("Unknown Ventoy Version");
283 if (op
== 0 && NonDest
)
285 GetLettersBelongPhyDrive(PhyDrive
, pDrvInfo
->DriveLetters
, sizeof(pDrvInfo
->DriveLetters
));
289 pCfg
->PartStyle
= PartStyle
;
290 pCfg
->ReserveMB
= ReserveMB
;
291 pCfg
->USBCheck
= USBCheck
;
292 pCfg
->NonDest
= NonDest
;
293 pCfg
->fstype
= fstype
;
298 static int Ventoy_CLI_NonDestInstall(PHY_DRIVE_INFO
* pDrvInfo
, CLI_CFG
* pCfg
)
303 Log("Ventoy_CLI_NonDestInstall start ...");
305 if (pDrvInfo
->BytesPerLogicalSector
== 4096 && pDrvInfo
->BytesPerPhysicalSector
== 4096)
307 Log("Ventoy does not support 4k native disk.");
312 if (!PartResizePreCheck(NULL
))
314 Log("#### Part Resize PreCheck Failed ####");
319 rc
= PartitionResizeForVentoy(pDrvInfo
);
322 Log("Ventoy_CLI_NonDestInstall [%s]", rc
== 0 ? "SUCCESS" : "FAILED");
328 static int Ventoy_CLI_Install(PHY_DRIVE_INFO
* pDrvInfo
, CLI_CFG
*pCfg
)
333 Log("Ventoy_CLI_Install start ...");
335 if (pDrvInfo
->BytesPerLogicalSector
== 4096 && pDrvInfo
->BytesPerPhysicalSector
== 4096)
337 Log("Ventoy does not support 4k native disk.");
342 if (pCfg
->ReserveMB
> 0)
344 CLISetReserveSpace(pCfg
->ReserveMB
);
347 SetVentoyFsType(pCfg
->fstype
);
349 rc
= InstallVentoy2PhyDrive(pDrvInfo
, pCfg
->PartStyle
, TryId
++);
352 Log("This time install failed, clean disk by disk, wait 3s and retry...");
353 DISK_CleanDisk(pDrvInfo
->PhyDrive
);
357 Log("Now retry to install...");
358 rc
= InstallVentoy2PhyDrive(pDrvInfo
, pCfg
->PartStyle
, TryId
++);
362 Log("This time install failed, clean disk by diskpart, wait 5s and retry...");
363 DSPT_CleanDisk(pDrvInfo
->PhyDrive
);
367 Log("Now retry to install...");
368 rc
= InstallVentoy2PhyDrive(pDrvInfo
, pCfg
->PartStyle
, TryId
++);
372 SetVentoyFsType(VTOY_FS_EXFAT
);
375 Log("Ventoy_CLI_Install [%s]", rc
== 0 ? "SUCCESS" : "FAILED");
380 static int Ventoy_CLI_Update(PHY_DRIVE_INFO
* pDrvInfo
, CLI_CFG
* pCfg
)
385 Log("Ventoy_CLI_Update start ...");
387 rc
= UpdateVentoy2PhyDrive(pDrvInfo
, TryId
++);
390 Log("This time update failed, now wait and retry...");
394 Log("Now retry to update...");
395 rc
= UpdateVentoy2PhyDrive(pDrvInfo
, TryId
++);
400 Log("Now retry to update...");
401 rc
= UpdateVentoy2PhyDrive(pDrvInfo
, TryId
++);
404 //Try4 is dangerous ...
406 Log("Now retry to update...");
407 rc
= UpdateVentoy2PhyDrive(pDrvInfo
, TryId
++);
412 Log("Ventoy_CLI_Update [%s]", rc
== 0 ? "SUCCESS" : "FAILED");
417 void CLI_UpdatePercent(int Pos
)
423 Len
= (int)sprintf_s(szBuf
, sizeof(szBuf
), "%d", Pos
* 100 / PT_FINISH
);
424 fopen_s(&File
, VENTOY_CLI_PERCENT
, "w+");
427 fwrite(szBuf
, 1, Len
, File
);
428 fwrite("\n", 1, 1, File
);
433 static void CLI_WriteDoneFile(int ret
)
437 fopen_s(&File
, VENTOY_CLI_DONE
, "w+");
442 fwrite("0\n", 1, 2, File
);
446 fwrite("1\n", 1, 2, File
);
452 PHY_DRIVE_INFO
* CLI_PhyDrvInfo(void)
454 return g_CLI_PhyDrvInfo
;
458 * Ventoy2Disk.exe VTOYCLI { /I | /U } { /Drive:F: | /PhyDrive:1 } /GPT /NoSB /R:4096 /NoUSBCheck
461 int VentoyCLIMain(int argc
, char** argv
)
464 PHY_DRIVE_INFO
* pDrvInfo
= NULL
;
467 DeleteFileA(VENTOY_CLI_PERCENT
);
468 DeleteFileA(VENTOY_CLI_DONE
);
470 g_CLI_PhyDrvInfo
= pDrvInfo
= (PHY_DRIVE_INFO
*)malloc(sizeof(PHY_DRIVE_INFO
));
475 memset(pDrvInfo
, 0, sizeof(PHY_DRIVE_INFO
));
477 if (CLI_CheckParam(argc
, argv
, pDrvInfo
, &CliCfg
))
482 //Check USB type for install
483 if (CliCfg
.op
== 0 && CliCfg
.USBCheck
)
485 if (pDrvInfo
->BusType
!= BusTypeUsb
)
487 Log("[ERROR] PhyDrive %d is NOT USB type", pDrvInfo
->PhyDrive
);
496 ret
= Ventoy_CLI_NonDestInstall(pDrvInfo
, &CliCfg
);
501 SetAlertPromptHookEnable(TRUE
);
502 ret
= Ventoy_CLI_Install(pDrvInfo
, &CliCfg
);
507 if (pDrvInfo
->VentoyVersion
[0] == 0)
509 Log("[ERROR] No Ventoy information detected in PhyDrive %d, so can not do update", pDrvInfo
->PhyDrive
);
513 ret
= Ventoy_CLI_Update(pDrvInfo
, &CliCfg
);
517 CHECK_FREE(pDrvInfo
);
519 CLI_UpdatePercent(PT_FINISH
);
520 CLI_WriteDoneFile(ret
);