1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #include "Ventoy2Disk.h"
26 PHY_DRIVE_INFO
*g_PhyDriveList
= NULL
;
27 DWORD g_PhyDriveCount
= 0;
28 static int g_FilterRemovable
= 0;
29 static int g_FilterUSB
= 1;
30 int g_ForceOperation
= 1;
32 int ParseCmdLineOption(LPSTR lpCmdLine
)
35 char cfgfile
[MAX_PATH
];
37 if (lpCmdLine
&& lpCmdLine
[0])
39 Log("CmdLine:<%s>", lpCmdLine
);
42 for (i
= 0; i
< __argc
; i
++)
44 if (strncmp(__argv
[i
], "-U", 2) == 0 ||
45 strncmp(__argv
[i
], "-u", 2) == 0)
49 else if (strncmp(__argv
[i
], "-F", 2) == 0)
55 GetCurrentDirectoryA(sizeof(cfgfile
), cfgfile
);
56 strcat_s(cfgfile
, sizeof(cfgfile
), "\\Ventoy2Disk.ini");
58 if (0 == GetPrivateProfileIntA("Filter", "USB", 1, cfgfile
))
63 if (1 == GetPrivateProfileIntA("Operation", "Force", 0, cfgfile
))
68 Log("Control Flag: %d %d %d", g_FilterRemovable
, g_FilterUSB
, g_ForceOperation
);
73 static BOOL
IsVentoyPhyDrive(int PhyDrive
, UINT64 SizeBytes
, MBR_HEAD
*pMBR
)
80 UINT32 PartStartSector
;
81 UINT32 PartSectorCount
;
82 CHAR PhyDrivePath
[128];
84 safe_sprintf(PhyDrivePath
, "\\\\.\\PhysicalDrive%d", PhyDrive
);
85 hDrive
= CreateFileA(PhyDrivePath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
86 Log("Create file Handle:%p %s status:%u", hDrive
, PhyDrivePath
, LASTERR
);
88 if (hDrive
== INVALID_HANDLE_VALUE
)
93 bRet
= ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
94 CHECK_CLOSE_HANDLE(hDrive
);
96 Log("Read MBR Ret:%u Size:%u code:%u", bRet
, dwSize
, LASTERR
);
98 if ((!bRet
) || (dwSize
!= sizeof(MBR
)))
103 if (MBR
.Byte55
!= 0x55 || MBR
.ByteAA
!= 0xAA)
105 Log("Byte55 ByteAA not match 0x%x 0x%x", MBR
.Byte55
, MBR
.ByteAA
);
109 for (i
= 0; i
< 4; i
++)
111 Log("=========== Partition Table %d ============", i
+ 1);
112 Log("PartTbl.Active = 0x%x", MBR
.PartTbl
[i
].Active
);
113 Log("PartTbl.FsFlag = 0x%x", MBR
.PartTbl
[i
].FsFlag
);
114 Log("PartTbl.StartSectorId = %u", MBR
.PartTbl
[i
].StartSectorId
);
115 Log("PartTbl.SectorCount = %u", MBR
.PartTbl
[i
].SectorCount
);
116 Log("PartTbl.StartHead = %u", MBR
.PartTbl
[i
].StartHead
);
117 Log("PartTbl.StartSector = %u", MBR
.PartTbl
[i
].StartSector
);
118 Log("PartTbl.StartCylinder = %u", MBR
.PartTbl
[i
].StartCylinder
);
119 Log("PartTbl.EndHead = %u", MBR
.PartTbl
[i
].EndHead
);
120 Log("PartTbl.EndSector = %u", MBR
.PartTbl
[i
].EndSector
);
121 Log("PartTbl.EndCylinder = %u", MBR
.PartTbl
[i
].EndCylinder
);
125 if (MBR
.PartTbl
[0].StartSectorId
!= 2048)
127 Log("Part1 not match %u", MBR
.PartTbl
[0].StartSectorId
);
131 PartStartSector
= MBR
.PartTbl
[0].StartSectorId
+ MBR
.PartTbl
[0].SectorCount
;
132 PartSectorCount
= VENTOY_EFI_PART_SIZE
/ 512;
134 if (MBR
.PartTbl
[1].FsFlag
!= 0xEF ||
135 MBR
.PartTbl
[1].StartSectorId
!= PartStartSector
||
136 MBR
.PartTbl
[1].SectorCount
!= PartSectorCount
)
138 Log("Part2 not match [0x%x 0x%x] [%u %u] [%u %u]",
139 MBR
.PartTbl
[1].FsFlag
, 0xEF,
140 MBR
.PartTbl
[1].StartSectorId
, PartStartSector
,
141 MBR
.PartTbl
[1].SectorCount
, PartSectorCount
);
145 if (MBR
.PartTbl
[0].Active
!= 0x80 && MBR
.PartTbl
[1].Active
!= 0x80)
147 Log("Part1 and Part2 are both NOT active 0x%x 0x%x", MBR
.PartTbl
[0].Active
, MBR
.PartTbl
[1].Active
);
151 memcpy(pMBR
, &MBR
, sizeof(MBR_HEAD
));
152 Log("PhysicalDrive%d is ventoy disk", PhyDrive
);
157 static int FilterPhysicalDrive(PHY_DRIVE_INFO
*pDriveList
, DWORD DriveCount
)
164 PHY_DRIVE_INFO
*CurDrive
;
166 int LogLetter
[VENTOY_MAX_PHY_DRIVE
];
167 int PhyDriveId
[VENTOY_MAX_PHY_DRIVE
];
169 for (LogDrive
= GetLogicalDrives(); LogDrive
> 0; LogDrive
>>= 1)
173 LogLetter
[LetterCount
] = Letter
;
174 PhyDriveId
[LetterCount
] = GetPhyDriveByLogicalDrive(Letter
);
176 Log("Logical Drive:%C ===> PhyDrive:%d", LogLetter
[LetterCount
], PhyDriveId
[LetterCount
]);
183 for (i
= 0; i
< DriveCount
; i
++)
185 CurDrive
= pDriveList
+ i
;
188 CurDrive
->FirstDriveLetter
= -1;
191 if (CurDrive
->SizeInBytes
> 2199023255552ULL)
193 Log("<%s %s> is filtered for too big for MBR.", CurDrive
->VendorId
, CurDrive
->ProductId
);
197 if (g_FilterRemovable
&& (!CurDrive
->RemovableMedia
))
199 Log("<%s %s> is filtered for not removable.", CurDrive
->VendorId
, CurDrive
->ProductId
);
203 if (g_FilterUSB
&& CurDrive
->BusType
!= BusTypeUsb
)
205 Log("<%s %s> is filtered for not USB type.", CurDrive
->VendorId
, CurDrive
->ProductId
);
211 for (Letter
= 0; Letter
< LetterCount
; Letter
++)
213 if (PhyDriveId
[Letter
] == CurDrive
->PhyDrive
)
215 CurDrive
->FirstDriveLetter
= LogLetter
[Letter
];
220 if (IsVentoyPhyDrive(CurDrive
->PhyDrive
, CurDrive
->SizeInBytes
, &MBR
))
222 GetVentoyVerInPhyDrive(CurDrive
, &MBR
, CurDrive
->VentoyVersion
, sizeof(CurDrive
->VentoyVersion
));
227 for (i
= 0; i
< DriveCount
; i
++)
229 CurDrive
= pDriveList
+ i
;
230 if (CurDrive
->Id
< 0)
232 CurDrive
->PhyDrive
= 0x00FFFFFF;
239 PHY_DRIVE_INFO
* GetPhyDriveInfoById(int Id
)
242 for (i
= 0; i
< g_PhyDriveCount
; i
++)
244 if (g_PhyDriveList
[i
].Id
>= 0 && g_PhyDriveList
[i
].Id
== Id
)
246 return g_PhyDriveList
+ i
;
253 int SortPhysicalDrive(PHY_DRIVE_INFO
*pDriveList
, DWORD DriveCount
)
256 PHY_DRIVE_INFO TmpDriveInfo
;
258 for (i
= 0; i
< DriveCount
; i
++)
260 for (j
= i
+ 1; j
< DriveCount
; j
++)
262 if (pDriveList
[i
].BusType
== BusTypeUsb
&& pDriveList
[j
].BusType
== BusTypeUsb
)
264 if (pDriveList
[i
].RemovableMedia
== FALSE
&& pDriveList
[j
].RemovableMedia
== TRUE
)
266 memcpy(&TmpDriveInfo
, pDriveList
+ i
, sizeof(PHY_DRIVE_INFO
));
267 memcpy(pDriveList
+ i
, pDriveList
+ j
, sizeof(PHY_DRIVE_INFO
));
268 memcpy(pDriveList
+ j
, &TmpDriveInfo
, sizeof(PHY_DRIVE_INFO
));
277 int Ventoy2DiskInit(void)
279 g_PhyDriveList
= (PHY_DRIVE_INFO
*)malloc(sizeof(PHY_DRIVE_INFO
)* VENTOY_MAX_PHY_DRIVE
);
280 if (NULL
== g_PhyDriveList
)
282 Log("Failed to alloc phy drive memory");
285 memset(g_PhyDriveList
, 0, sizeof(PHY_DRIVE_INFO
)* VENTOY_MAX_PHY_DRIVE
);
287 GetAllPhysicalDriveInfo(g_PhyDriveList
, &g_PhyDriveCount
);
289 SortPhysicalDrive(g_PhyDriveList
, g_PhyDriveCount
);
291 FilterPhysicalDrive(g_PhyDriveList
, g_PhyDriveCount
);
296 int Ventoy2DiskDestroy(void)
298 free(g_PhyDriveList
);