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
;
239 if (op
< 0 || PhyDrive
< 0)
241 Log("[ERROR] Invalid parameters %d %d", op
, PhyDrive
);
245 Log("Ventoy CLI %s PhyDrive:%d %s SecureBoot:%d ReserveSpace:%dMB USBCheck:%u FS:%s NonDest:%d",
246 op
== 0 ? "install" : "update",
247 PhyDrive
, PartStyle
? "GPT" : "MBR",
248 g_SecureBoot
, ReserveMB
, USBCheck
, GetVentoyFsFmtNameByTypeA(fstype
), NonDest
251 if (CLI_GetPhyDriveInfo(PhyDrive
, pDrvInfo
))
253 Log("[ERROR] Failed to get phydrive%d info", PhyDrive
);
257 Log("PhyDrive:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
258 pDrvInfo
->PhyDrive
, GetBusTypeString(pDrvInfo
->BusType
), pDrvInfo
->RemovableMedia
,
259 GetHumanReadableGBSize(pDrvInfo
->SizeInBytes
), pDrvInfo
->SizeInBytes
,
260 pDrvInfo
->VendorId
, pDrvInfo
->ProductId
);
262 if (IsVentoyPhyDrive(PhyDrive
, pDrvInfo
->SizeInBytes
, &MBR
, &Part2StartSector
, &Part2GPTAttr
))
264 memcpy(&(pDrvInfo
->MBR
), &MBR
, sizeof(MBR
));
265 pDrvInfo
->PartStyle
= (MBR
.PartTbl
[0].FsFlag
== 0xEE) ? 1 : 0;
266 pDrvInfo
->Part2GPTAttr
= Part2GPTAttr
;
267 GetVentoyVerInPhyDrive(pDrvInfo
, Part2StartSector
, pDrvInfo
->VentoyVersion
, sizeof(pDrvInfo
->VentoyVersion
), &(pDrvInfo
->SecureBootSupport
));
268 Log("PhyDrive %d is Ventoy Disk ver:%s SecureBoot:%u", pDrvInfo
->PhyDrive
, pDrvInfo
->VentoyVersion
, pDrvInfo
->SecureBootSupport
);
270 GetVentoyFsNameInPhyDrive(pDrvInfo
);
272 if (pDrvInfo
->VentoyVersion
[0] == 0)
274 pDrvInfo
->VentoyVersion
[0] = '?';
275 Log("Unknown Ventoy Version");
279 if (op
== 0 && NonDest
)
281 GetLettersBelongPhyDrive(PhyDrive
, pDrvInfo
->DriveLetters
, sizeof(pDrvInfo
->DriveLetters
));
285 pCfg
->PartStyle
= PartStyle
;
286 pCfg
->ReserveMB
= ReserveMB
;
287 pCfg
->USBCheck
= USBCheck
;
288 pCfg
->NonDest
= NonDest
;
289 pCfg
->fstype
= fstype
;
294 static int Ventoy_CLI_NonDestInstall(PHY_DRIVE_INFO
* pDrvInfo
, CLI_CFG
* pCfg
)
299 Log("Ventoy_CLI_NonDestInstall start ...");
301 if (pDrvInfo
->BytesPerLogicalSector
== 4096 && pDrvInfo
->BytesPerPhysicalSector
== 4096)
303 Log("Ventoy does not support 4k native disk.");
308 if (!PartResizePreCheck(NULL
))
310 Log("#### Part Resize PreCheck Failed ####");
315 rc
= PartitionResizeForVentoy(pDrvInfo
);
318 Log("Ventoy_CLI_NonDestInstall [%s]", rc
== 0 ? "SUCCESS" : "FAILED");
324 static int Ventoy_CLI_Install(PHY_DRIVE_INFO
* pDrvInfo
, CLI_CFG
*pCfg
)
329 Log("Ventoy_CLI_Install start ...");
331 if (pDrvInfo
->BytesPerLogicalSector
== 4096 && pDrvInfo
->BytesPerPhysicalSector
== 4096)
333 Log("Ventoy does not support 4k native disk.");
338 if (pCfg
->ReserveMB
> 0)
340 CLISetReserveSpace(pCfg
->ReserveMB
);
343 SetVentoyFsType(pCfg
->fstype
);
345 rc
= InstallVentoy2PhyDrive(pDrvInfo
, pCfg
->PartStyle
, TryId
++);
348 Log("This time install failed, clean disk by disk, wait 3s and retry...");
349 DISK_CleanDisk(pDrvInfo
->PhyDrive
);
353 Log("Now retry to install...");
354 rc
= InstallVentoy2PhyDrive(pDrvInfo
, pCfg
->PartStyle
, TryId
++);
358 Log("This time install failed, clean disk by diskpart, wait 5s and retry...");
359 DSPT_CleanDisk(pDrvInfo
->PhyDrive
);
363 Log("Now retry to install...");
364 rc
= InstallVentoy2PhyDrive(pDrvInfo
, pCfg
->PartStyle
, TryId
++);
368 SetVentoyFsType(VTOY_FS_EXFAT
);
371 Log("Ventoy_CLI_Install [%s]", rc
== 0 ? "SUCCESS" : "FAILED");
376 static int Ventoy_CLI_Update(PHY_DRIVE_INFO
* pDrvInfo
, CLI_CFG
* pCfg
)
381 Log("Ventoy_CLI_Update start ...");
383 rc
= UpdateVentoy2PhyDrive(pDrvInfo
, TryId
++);
386 Log("This time update failed, now wait and retry...");
390 Log("Now retry to update...");
391 rc
= UpdateVentoy2PhyDrive(pDrvInfo
, TryId
++);
396 Log("Now retry to update...");
397 rc
= UpdateVentoy2PhyDrive(pDrvInfo
, TryId
++);
400 //Try4 is dangerous ...
402 Log("Now retry to update...");
403 rc
= UpdateVentoy2PhyDrive(pDrvInfo
, TryId
++);
408 Log("Ventoy_CLI_Update [%s]", rc
== 0 ? "SUCCESS" : "FAILED");
413 void CLI_UpdatePercent(int Pos
)
419 Len
= (int)sprintf_s(szBuf
, sizeof(szBuf
), "%d", Pos
* 100 / PT_FINISH
);
420 fopen_s(&File
, VENTOY_CLI_PERCENT
, "w+");
423 fwrite(szBuf
, 1, Len
, File
);
424 fwrite("\n", 1, 1, File
);
429 static void CLI_WriteDoneFile(int ret
)
433 fopen_s(&File
, VENTOY_CLI_DONE
, "w+");
438 fwrite("0\n", 1, 2, File
);
442 fwrite("1\n", 1, 2, File
);
448 PHY_DRIVE_INFO
* CLI_PhyDrvInfo(void)
450 return g_CLI_PhyDrvInfo
;
454 * Ventoy2Disk.exe VTOYCLI { /I | /U } { /Drive:F: | /PhyDrive:1 } /GPT /NoSB /R:4096 /NoUSBCheck
457 int VentoyCLIMain(int argc
, char** argv
)
460 PHY_DRIVE_INFO
* pDrvInfo
= NULL
;
463 DeleteFileA(VENTOY_CLI_PERCENT
);
464 DeleteFileA(VENTOY_CLI_DONE
);
466 g_CLI_PhyDrvInfo
= pDrvInfo
= (PHY_DRIVE_INFO
*)malloc(sizeof(PHY_DRIVE_INFO
));
471 memset(pDrvInfo
, 0, sizeof(PHY_DRIVE_INFO
));
473 if (CLI_CheckParam(argc
, argv
, pDrvInfo
, &CliCfg
))
478 //Check USB type for install
479 if (CliCfg
.op
== 0 && CliCfg
.USBCheck
)
481 if (pDrvInfo
->BusType
!= BusTypeUsb
)
483 Log("[ERROR] PhyDrive %d is NOT USB type", pDrvInfo
->PhyDrive
);
492 ret
= Ventoy_CLI_NonDestInstall(pDrvInfo
, &CliCfg
);
497 SetAlertPromptHookEnable(TRUE
);
498 ret
= Ventoy_CLI_Install(pDrvInfo
, &CliCfg
);
503 if (pDrvInfo
->VentoyVersion
[0] == 0)
505 Log("[ERROR] No Ventoy information detected in PhyDrive %d, so can not do update", pDrvInfo
->PhyDrive
);
509 ret
= Ventoy_CLI_Update(pDrvInfo
, &CliCfg
);
513 CHECK_FREE(pDrvInfo
);
515 CLI_UpdatePercent(PT_FINISH
);
516 CLI_WriteDoneFile(ret
);