]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Ventoy2Disk/Ventoy2Disk/Ventoy2Disk.c
a3dfb776864a1278ffa9907f41dd074b0d1f40d8
[Ventoy.git] / Ventoy2Disk / Ventoy2Disk / Ventoy2Disk.c
1 /******************************************************************************
2 * Ventoy2Disk.c
3 *
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 */
20
21 #include <Windows.h>
22 #include "resource.h"
23 #include "Language.h"
24 #include "Ventoy2Disk.h"
25
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;
31
32 int ParseCmdLineOption(LPSTR lpCmdLine)
33 {
34 int i;
35 char cfgfile[MAX_PATH];
36
37 if (lpCmdLine && lpCmdLine[0])
38 {
39 Log("CmdLine:<%s>", lpCmdLine);
40 }
41
42 for (i = 0; i < __argc; i++)
43 {
44 if (strncmp(__argv[i], "-U", 2) == 0 ||
45 strncmp(__argv[i], "-u", 2) == 0)
46 {
47 g_FilterUSB = 0;
48 }
49 else if (strncmp(__argv[i], "-F", 2) == 0)
50 {
51 g_ForceOperation = 1;
52 }
53 }
54
55 GetCurrentDirectoryA(sizeof(cfgfile), cfgfile);
56 strcat_s(cfgfile, sizeof(cfgfile), "\\Ventoy2Disk.ini");
57
58 if (0 == GetPrivateProfileIntA("Filter", "USB", 1, cfgfile))
59 {
60 g_FilterUSB = 0;
61 }
62
63 if (1 == GetPrivateProfileIntA("Operation", "Force", 0, cfgfile))
64 {
65 g_ForceOperation = 1;
66 }
67
68 Log("Control Flag: %d %d %d", g_FilterRemovable, g_FilterUSB, g_ForceOperation);
69
70 return 0;
71 }
72
73 static BOOL IsVentoyPhyDrive(int PhyDrive, UINT64 SizeBytes)
74 {
75 int i;
76 BOOL bRet;
77 DWORD dwSize;
78 HANDLE hDrive;
79 MBR_HEAD MBR;
80 UINT32 PartStartSector;
81 UINT32 PartSectorCount;
82 CHAR PhyDrivePath[128];
83
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);
87
88 if (hDrive == INVALID_HANDLE_VALUE)
89 {
90 return FALSE;
91 }
92
93 bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
94 CHECK_CLOSE_HANDLE(hDrive);
95
96 Log("Read MBR Ret:%u Size:%u code:%u", bRet, dwSize, LASTERR);
97
98 if ((!bRet) || (dwSize != sizeof(MBR)))
99 {
100 return FALSE;
101 }
102
103 if (MBR.Byte55 != 0x55 || MBR.ByteAA != 0xAA)
104 {
105 Log("Byte55 ByteAA not match 0x%x 0x%x", MBR.Byte55, MBR.ByteAA);
106 return FALSE;
107 }
108
109 for (i = 0; i < 4; i++)
110 {
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);
122 }
123
124 if (MBR.PartTbl[2].SectorCount > 0 || MBR.PartTbl[3].SectorCount > 0)
125 {
126 Log("Part3 Part4 are not empty");
127 return FALSE;
128 }
129
130 PartStartSector = 2048;
131 PartSectorCount = (UINT32)((SizeBytes - VENTOY_EFI_PART_SIZE - SIZE_1MB) / 512);
132
133 if (MBR.PartTbl[0].FsFlag != 0x07 ||
134 MBR.PartTbl[0].StartSectorId != PartStartSector ||
135 MBR.PartTbl[0].SectorCount != PartSectorCount)
136 {
137 Log("Part1 not match %u %u", PartStartSector, PartSectorCount);
138 return FALSE;
139 }
140
141 PartStartSector = (UINT32)((SizeBytes - VENTOY_EFI_PART_SIZE) / 512);
142 PartSectorCount = VENTOY_EFI_PART_SIZE / 512;
143
144 if (MBR.PartTbl[1].Active != 0x80 ||
145 MBR.PartTbl[1].FsFlag != 0xEF ||
146 MBR.PartTbl[1].StartSectorId != PartStartSector ||
147 MBR.PartTbl[1].SectorCount != PartSectorCount)
148 {
149 Log("Part2 not match %u %u", PartStartSector, PartSectorCount);
150 return FALSE;
151 }
152
153 Log("PhysicalDrive%d is ventoy disk", PhyDrive);
154 return TRUE;
155 }
156
157
158 static int FilterPhysicalDrive(PHY_DRIVE_INFO *pDriveList, DWORD DriveCount)
159 {
160 DWORD i;
161 DWORD LogDrive;
162 int Letter = 'A';
163 int Id = 0;
164 int LetterCount = 0;
165 PHY_DRIVE_INFO *CurDrive;
166 int LogLetter[VENTOY_MAX_PHY_DRIVE];
167 int PhyDriveId[VENTOY_MAX_PHY_DRIVE];
168
169 for (LogDrive = GetLogicalDrives(); LogDrive > 0; LogDrive >>= 1)
170 {
171 if (LogDrive & 0x01)
172 {
173 LogLetter[LetterCount] = Letter;
174 PhyDriveId[LetterCount] = GetPhyDriveByLogicalDrive(Letter);
175
176 Log("Logical Drive:%C ===> PhyDrive:%d", LogLetter[LetterCount], PhyDriveId[LetterCount]);
177 LetterCount++;
178 }
179
180 Letter++;
181 }
182
183 for (i = 0; i < DriveCount; i++)
184 {
185 CurDrive = pDriveList + i;
186
187 CurDrive->Id = -1;
188 CurDrive->FirstDriveLetter = -1;
189
190 // Too big for MBR
191 if (CurDrive->SizeInBytes > 2199023255552ULL)
192 {
193 Log("<%s %s> is filtered for too big for MBR.", CurDrive->VendorId, CurDrive->ProductId);
194 continue;
195 }
196
197 if (g_FilterRemovable && (!CurDrive->RemovableMedia))
198 {
199 Log("<%s %s> is filtered for not removable.", CurDrive->VendorId, CurDrive->ProductId);
200 continue;
201 }
202
203 if (g_FilterUSB && CurDrive->BusType != BusTypeUsb)
204 {
205 Log("<%s %s> is filtered for not USB type.", CurDrive->VendorId, CurDrive->ProductId);
206 continue;
207 }
208
209 CurDrive->Id = Id++;
210
211 for (Letter = 0; Letter < LetterCount; Letter++)
212 {
213 if (PhyDriveId[Letter] == CurDrive->PhyDrive)
214 {
215 CurDrive->FirstDriveLetter = LogLetter[Letter];
216 break;
217 }
218 }
219
220 if (IsVentoyPhyDrive(CurDrive->PhyDrive, CurDrive->SizeInBytes))
221 {
222 GetVentoyVerInPhyDrive(CurDrive, CurDrive->VentoyVersion, sizeof(CurDrive->VentoyVersion));
223 }
224 }
225
226 // for safe
227 for (i = 0; i < DriveCount; i++)
228 {
229 CurDrive = pDriveList + i;
230 if (CurDrive->Id < 0)
231 {
232 CurDrive->PhyDrive = 0x00FFFFFF;
233 }
234 }
235
236 return Id;
237 }
238
239 PHY_DRIVE_INFO * GetPhyDriveInfoById(int Id)
240 {
241 DWORD i;
242 for (i = 0; i < g_PhyDriveCount; i++)
243 {
244 if (g_PhyDriveList[i].Id >= 0 && g_PhyDriveList[i].Id == Id)
245 {
246 return g_PhyDriveList + i;
247 }
248 }
249
250 return NULL;
251 }
252
253 int SortPhysicalDrive(PHY_DRIVE_INFO *pDriveList, DWORD DriveCount)
254 {
255 DWORD i, j;
256 PHY_DRIVE_INFO TmpDriveInfo;
257
258 for (i = 0; i < DriveCount; i++)
259 {
260 for (j = i + 1; j < DriveCount; j++)
261 {
262 if (pDriveList[i].BusType == BusTypeUsb && pDriveList[j].BusType == BusTypeUsb)
263 {
264 if (pDriveList[i].RemovableMedia == FALSE && pDriveList[j].RemovableMedia == TRUE)
265 {
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));
269 }
270 }
271 }
272 }
273
274 return 0;
275 }
276
277 int Ventoy2DiskInit(void)
278 {
279 g_PhyDriveList = (PHY_DRIVE_INFO *)malloc(sizeof(PHY_DRIVE_INFO)* VENTOY_MAX_PHY_DRIVE);
280 if (NULL == g_PhyDriveList)
281 {
282 Log("Failed to alloc phy drive memory");
283 return FALSE;
284 }
285 memset(g_PhyDriveList, 0, sizeof(PHY_DRIVE_INFO)* VENTOY_MAX_PHY_DRIVE);
286
287 GetAllPhysicalDriveInfo(g_PhyDriveList, &g_PhyDriveCount);
288
289 SortPhysicalDrive(g_PhyDriveList, g_PhyDriveCount);
290
291 FilterPhysicalDrive(g_PhyDriveList, g_PhyDriveCount);
292
293 return 0;
294 }
295
296 int Ventoy2DiskDestroy(void)
297 {
298 free(g_PhyDriveList);
299 return 0;
300 }