]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Ventoy2Disk/Ventoy2Disk/PhyDrive.c
d64916e5989771d09ec108151331ea28217b6c58
[Ventoy.git] / Ventoy2Disk / Ventoy2Disk / PhyDrive.c
1 /******************************************************************************
2 * PhyDrive.c
3 *
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 * Copyright (c) 2011-2020, Pete Batard <pete@akeo.ie>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 #include <Windows.h>
23 #include <time.h>
24 #include <winternl.h>
25 #include <commctrl.h>
26 #include <initguid.h>
27 #include "resource.h"
28 #include "Language.h"
29 #include "Ventoy2Disk.h"
30 #include "fat_filelib.h"
31 #include "ff.h"
32 #include "DiskService.h"
33
34 static int g_backup_bin_index = 0;
35
36
37 static BOOL WriteDataToPhyDisk(HANDLE hDrive, UINT64 Offset, VOID *buffer, DWORD len)
38 {
39 BOOL bRet;
40 DWORD dwSize = 0;
41 LARGE_INTEGER liCurPosition;
42 LARGE_INTEGER liNewPosition;
43
44 liCurPosition.QuadPart = (LONGLONG)Offset;
45 liNewPosition.QuadPart = 0;
46 if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||
47 liNewPosition.QuadPart != liCurPosition.QuadPart)
48 {
49 Log("SetFilePointerEx Failed %u", LASTERR);
50 return FALSE;
51 }
52
53 bRet = WriteFile(hDrive, buffer, len, &dwSize, NULL);
54 if (bRet == FALSE || dwSize != len)
55 {
56 Log("Write file error %u %u", dwSize, LASTERR);
57 return FALSE;
58 }
59
60 return TRUE;
61 }
62
63
64 static DWORD GetVentoyVolumeName(int PhyDrive, UINT64 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash)
65 {
66 size_t len;
67 BOOL bRet;
68 DWORD dwSize;
69 HANDLE hDrive;
70 HANDLE hVolume;
71 UINT64 PartOffset;
72 DWORD Status = ERROR_NOT_FOUND;
73 DISK_EXTENT *pExtents = NULL;
74 CHAR VolumeName[MAX_PATH] = { 0 };
75 VOLUME_DISK_EXTENTS DiskExtents;
76
77 PartOffset = 512ULL * StartSectorId;
78
79 Log("GetVentoyVolumeName PhyDrive %d SectorStart:%llu PartOffset:%llu", PhyDrive, (ULONGLONG)StartSectorId, (ULONGLONG)PartOffset);
80
81 hVolume = FindFirstVolumeA(VolumeName, sizeof(VolumeName));
82 if (hVolume == INVALID_HANDLE_VALUE)
83 {
84 return 1;
85 }
86
87 do {
88
89 len = strlen(VolumeName);
90 Log("Find volume:%s", VolumeName);
91
92 VolumeName[len - 1] = 0;
93
94 hDrive = CreateFileA(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
95 if (hDrive == INVALID_HANDLE_VALUE)
96 {
97 continue;
98 }
99
100 bRet = DeviceIoControl(hDrive,
101 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
102 NULL,
103 0,
104 &DiskExtents,
105 (DWORD)(sizeof(DiskExtents)),
106 (LPDWORD)&dwSize,
107 NULL);
108
109 Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet, LASTERR);
110 Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents.NumberOfDiskExtents, DiskExtents.Extents[0].DiskNumber);
111
112 if (bRet && DiskExtents.NumberOfDiskExtents == 1)
113 {
114 pExtents = DiskExtents.Extents;
115
116 Log("This volume DiskNumber:%u offset:%llu", pExtents->DiskNumber, (ULONGLONG)pExtents->StartingOffset.QuadPart);
117 if ((int)pExtents->DiskNumber == PhyDrive && pExtents->StartingOffset.QuadPart == PartOffset)
118 {
119 Log("This volume match");
120
121 if (!DelSlash)
122 {
123 VolumeName[len - 1] = '\\';
124 }
125
126 sprintf_s(NameBuf, BufLen, "%s", VolumeName);
127 Status = ERROR_SUCCESS;
128 CloseHandle(hDrive);
129 break;
130 }
131 }
132
133 CloseHandle(hDrive);
134 } while (FindNextVolumeA(hVolume, VolumeName, sizeof(VolumeName)));
135
136 FindVolumeClose(hVolume);
137
138 Log("GetVentoyVolumeName return %u", Status);
139 return Status;
140 }
141
142 int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length)
143 {
144 int n = 0;
145 DWORD DataSize = 0;
146 CHAR *Pos = NULL;
147 CHAR *StringBuf = NULL;
148
149 DataSize = GetLogicalDriveStringsA(0, NULL);
150 StringBuf = (CHAR *)malloc(DataSize + 1);
151 if (StringBuf == NULL)
152 {
153 return 1;
154 }
155
156 GetLogicalDriveStringsA(DataSize, StringBuf);
157
158 for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1)
159 {
160 if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0], NULL))
161 {
162 Log("%C: is belong to phydrive%d", Pos[0], PhyDrive);
163 DriveLetters[n++] = Pos[0];
164 }
165 }
166
167 free(StringBuf);
168 return 0;
169 }
170
171 HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare)
172 {
173 int i;
174 DWORD dwSize;
175 DWORD LastError;
176 UINT64 EndTime;
177 HANDLE hDrive = INVALID_HANDLE_VALUE;
178 CHAR PhyDrive[128];
179 CHAR DevPath[MAX_PATH] = { 0 };
180
181 safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", Drive);
182
183 if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath)))
184 {
185 Log("QueryDosDeviceA failed error:%u", GetLastError());
186 strcpy_s(DevPath, sizeof(DevPath), "???");
187 }
188 else
189 {
190 Log("QueryDosDeviceA success %s", DevPath);
191 }
192
193 for (i = 0; i < DRIVE_ACCESS_RETRIES; i++)
194 {
195 // Try without FILE_SHARE_WRITE (unless specifically requested) so that
196 // we won't be bothered by the OS or other apps when we set up our data.
197 // However this means we might have to wait for an access gap...
198 // We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is
199 // required for enumeration.
200 hDrive = CreateFileA(PhyDrive,
201 GENERIC_READ | (bWriteAccess ? GENERIC_WRITE : 0),
202 FILE_SHARE_READ | (bWriteShare ? FILE_SHARE_WRITE : 0),
203 NULL,
204 OPEN_EXISTING,
205 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
206 NULL);
207
208 LastError = GetLastError();
209 Log("[%d] CreateFileA %s code:%u %p", i, PhyDrive, LastError, hDrive);
210
211 if (hDrive != INVALID_HANDLE_VALUE)
212 {
213 break;
214 }
215
216 if ((LastError != ERROR_SHARING_VIOLATION) && (LastError != ERROR_ACCESS_DENIED))
217 {
218 break;
219 }
220
221 if (i == 0)
222 {
223 Log("Waiting for access on %s [%s]...", PhyDrive, DevPath);
224 }
225 else if (!bWriteShare && (i > DRIVE_ACCESS_RETRIES / 3))
226 {
227 // If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE...
228 Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");
229 bWriteShare = TRUE;
230
231 // Try to report the process that is locking the drive
232 // We also use bit 6 as a flag to indicate that SearchProcess was called.
233 //access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40;
234
235 }
236 Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
237 }
238
239 if (hDrive == INVALID_HANDLE_VALUE)
240 {
241 Log("Could not open %s %u", PhyDrive, LASTERR);
242 goto End;
243 }
244
245 if (bWriteAccess)
246 {
247 Log("Opened %s for %s write access", PhyDrive, bWriteShare ? "shared" : "exclusive");
248 }
249
250 if (bLockDrive)
251 {
252 if (DeviceIoControl(hDrive, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwSize, NULL))
253 {
254 Log("I/O boundary checks disabled");
255 }
256
257 EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT;
258
259 do {
260 if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL))
261 {
262 Log("FSCTL_LOCK_VOLUME success");
263 goto End;
264 }
265 Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
266 } while (GetTickCount64() < EndTime);
267
268 // If we reached this section, either we didn't manage to get a lock or the user cancelled
269 Log("Could not lock access to %s %u", PhyDrive, LASTERR);
270
271 // See if we can report the processes are accessing the drive
272 //if (!IS_ERROR(FormatStatus) && (access_mask == 0))
273 // access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE);
274 // Try to continue if the only access rights we saw were for read-only
275 //if ((access_mask & 0x07) != 0x01)
276 // safe_closehandle(hDrive);
277
278 CHECK_CLOSE_HANDLE(hDrive);
279 }
280
281 End:
282
283 if (hDrive == INVALID_HANDLE_VALUE)
284 {
285 Log("Can get handle of %s, maybe some process control it.", DevPath);
286 }
287
288 return hDrive;
289 }
290
291 int GetPhyDriveByLogicalDrive(int DriveLetter, UINT64 *Offset)
292 {
293 BOOL Ret = FALSE;
294 DWORD dwSize = 0;
295 HANDLE Handle = INVALID_HANDLE_VALUE;
296 VOLUME_DISK_EXTENTS DiskExtents;
297 CHAR PhyPath[128];
298
299 safe_sprintf(PhyPath, "\\\\.\\%C:", (CHAR)DriveLetter);
300
301 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
302 if (Handle == INVALID_HANDLE_VALUE)
303 {
304 Log("Could not open the disk<%s>, error:%u", PhyPath, LASTERR);
305 return -1;
306 }
307
308 memset(&DiskExtents, 0, sizeof(DiskExtents));
309 Ret = DeviceIoControl(Handle,
310 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
311 NULL,
312 0,
313 &DiskExtents,
314 (DWORD)(sizeof(DiskExtents)),
315 (LPDWORD)&dwSize,
316 NULL);
317
318 if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
319 {
320 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, LASTERR);
321 CHECK_CLOSE_HANDLE(Handle);
322 return -1;
323 }
324 CHECK_CLOSE_HANDLE(Handle);
325
326 Log("LogicalDrive:%s PhyDrive:%d Num:%d Offset:%llu ExtentLength:%llu",
327 PhyPath,
328 DiskExtents.Extents[0].DiskNumber,
329 DiskExtents.NumberOfDiskExtents,
330 DiskExtents.Extents[0].StartingOffset.QuadPart,
331 DiskExtents.Extents[0].ExtentLength.QuadPart
332 );
333
334 if (Offset)
335 {
336 *Offset = (UINT64)(DiskExtents.Extents[0].StartingOffset.QuadPart);
337 }
338
339 return (int)DiskExtents.Extents[0].DiskNumber;
340 }
341
342 int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)
343 {
344 int i;
345 int Count;
346 int id;
347 int Letter = 'A';
348 BOOL bRet;
349 DWORD dwBytes;
350 DWORD DriveCount = 0;
351 HANDLE Handle = INVALID_HANDLE_VALUE;
352 CHAR PhyDrive[128];
353 PHY_DRIVE_INFO *CurDrive = pDriveList;
354 GET_LENGTH_INFORMATION LengthInfo;
355 STORAGE_PROPERTY_QUERY Query;
356 STORAGE_DESCRIPTOR_HEADER DevDescHeader;
357 STORAGE_DEVICE_DESCRIPTOR *pDevDesc;
358 STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment;
359 int PhyDriveId[VENTOY_MAX_PHY_DRIVE];
360
361 Count = GetPhysicalDriveCount();
362
363 for (i = 0; i < Count && i < VENTOY_MAX_PHY_DRIVE; i++)
364 {
365 PhyDriveId[i] = i;
366 }
367
368 dwBytes = GetLogicalDrives();
369 Log("Logical Drives: 0x%x", dwBytes);
370 while (dwBytes)
371 {
372 if (dwBytes & 0x01)
373 {
374 id = GetPhyDriveByLogicalDrive(Letter, NULL);
375 Log("%C --> %d", Letter, id);
376 if (id >= 0)
377 {
378 for (i = 0; i < Count; i++)
379 {
380 if (PhyDriveId[i] == id)
381 {
382 break;
383 }
384 }
385
386 if (i >= Count)
387 {
388 Log("Add phy%d to list", i);
389 PhyDriveId[Count] = id;
390 Count++;
391 }
392 }
393 }
394
395 Letter++;
396 dwBytes >>= 1;
397 }
398
399 for (i = 0; i < Count && DriveCount < VENTOY_MAX_PHY_DRIVE; i++)
400 {
401 CHECK_CLOSE_HANDLE(Handle);
402
403 safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", PhyDriveId[i]);
404 Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
405 Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR);
406
407 if (Handle == INVALID_HANDLE_VALUE)
408 {
409 continue;
410 }
411
412 bRet = DeviceIoControl(Handle,
413 IOCTL_DISK_GET_LENGTH_INFO, NULL,
414 0,
415 &LengthInfo,
416 sizeof(LengthInfo),
417 &dwBytes,
418 NULL);
419 if (!bRet)
420 {
421 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR);
422 continue;
423 }
424
425 Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart);
426
427 Query.PropertyId = StorageDeviceProperty;
428 Query.QueryType = PropertyStandardQuery;
429
430 bRet = DeviceIoControl(Handle,
431 IOCTL_STORAGE_QUERY_PROPERTY,
432 &Query,
433 sizeof(Query),
434 &DevDescHeader,
435 sizeof(STORAGE_DESCRIPTOR_HEADER),
436 &dwBytes,
437 NULL);
438 if (!bRet)
439 {
440 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes);
441 continue;
442 }
443
444 if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))
445 {
446 Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size);
447 continue;
448 }
449
450 pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size);
451 if (!pDevDesc)
452 {
453 Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size);
454 continue;
455 }
456
457 bRet = DeviceIoControl(Handle,
458 IOCTL_STORAGE_QUERY_PROPERTY,
459 &Query,
460 sizeof(Query),
461 pDevDesc,
462 DevDescHeader.Size,
463 &dwBytes,
464 NULL);
465 if (!bRet)
466 {
467 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes);
468 free(pDevDesc);
469 continue;
470 }
471
472
473
474 memset(&Query, 0, sizeof(STORAGE_PROPERTY_QUERY));
475 Query.PropertyId = StorageAccessAlignmentProperty;
476 Query.QueryType = PropertyStandardQuery;
477 memset(&diskAlignment, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR));
478
479 bRet = DeviceIoControl(Handle,
480 IOCTL_STORAGE_QUERY_PROPERTY,
481 &Query,
482 sizeof(STORAGE_PROPERTY_QUERY),
483 &diskAlignment,
484 sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
485 &dwBytes,
486 NULL);
487 if (!bRet)
488 {
489 Log("DeviceIoControl3 error:%u dwBytes:%u", LASTERR, dwBytes);
490 }
491
492 CurDrive->PhyDrive = i;
493 CurDrive->SizeInBytes = LengthInfo.Length.QuadPart;
494 CurDrive->DeviceType = pDevDesc->DeviceType;
495 CurDrive->RemovableMedia = pDevDesc->RemovableMedia;
496 CurDrive->BusType = pDevDesc->BusType;
497
498 CurDrive->BytesPerLogicalSector = diskAlignment.BytesPerLogicalSector;
499 CurDrive->BytesPerPhysicalSector = diskAlignment.BytesPerPhysicalSector;
500
501 if (pDevDesc->VendorIdOffset)
502 {
503 safe_strcpy(CurDrive->VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset);
504 TrimString(CurDrive->VendorId);
505 }
506
507 if (pDevDesc->ProductIdOffset)
508 {
509 safe_strcpy(CurDrive->ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset);
510 TrimString(CurDrive->ProductId);
511 }
512
513 if (pDevDesc->ProductRevisionOffset)
514 {
515 safe_strcpy(CurDrive->ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset);
516 TrimString(CurDrive->ProductRev);
517 }
518
519 if (pDevDesc->SerialNumberOffset)
520 {
521 safe_strcpy(CurDrive->SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset);
522 TrimString(CurDrive->SerialNumber);
523 }
524
525 CurDrive++;
526 DriveCount++;
527
528 free(pDevDesc);
529
530 CHECK_CLOSE_HANDLE(Handle);
531 }
532
533 for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++)
534 {
535 Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Sector:%u/%u Name:%s %s",
536 CurDrive->PhyDrive, GetBusTypeString(CurDrive->BusType), CurDrive->RemovableMedia,
537 GetHumanReadableGBSize(CurDrive->SizeInBytes), CurDrive->SizeInBytes,
538 CurDrive->BytesPerLogicalSector, CurDrive->BytesPerPhysicalSector,
539 CurDrive->VendorId, CurDrive->ProductId);
540 }
541
542 *pDriveCount = DriveCount;
543
544 return 0;
545 }
546
547 BOOL VentoyPhydriveMatch(PHY_DRIVE_INFO* pPhyDrive)
548 {
549 BOOL bRet = FALSE;
550 DWORD dwBytes;
551 HANDLE Handle = INVALID_HANDLE_VALUE;
552 CHAR PhyDrive[128];
553 GET_LENGTH_INFORMATION LengthInfo;
554 STORAGE_PROPERTY_QUERY Query;
555 STORAGE_DESCRIPTOR_HEADER DevDescHeader;
556 STORAGE_DEVICE_DESCRIPTOR* pDevDesc = NULL;
557 STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment;
558 CHAR VendorId[128] = { 0 };
559 CHAR ProductId[128] = { 0 };
560 CHAR ProductRev[128] = { 0 };
561 CHAR SerialNumber[128] = { 0 };
562
563
564 safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", pPhyDrive->PhyDrive);
565 Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
566 if (Handle == INVALID_HANDLE_VALUE)
567 {
568 Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR);
569 return FALSE;
570 }
571
572 bRet = DeviceIoControl(Handle,
573 IOCTL_DISK_GET_LENGTH_INFO, NULL,
574 0,
575 &LengthInfo,
576 sizeof(LengthInfo),
577 &dwBytes,
578 NULL);
579 if (!bRet)
580 {
581 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR);
582 return FALSE;
583 }
584
585 if (pPhyDrive->SizeInBytes != (ULONGLONG)LengthInfo.Length.QuadPart)
586 {
587 Log("PHYSICALDRIVE%d size not match %llu %llu", pPhyDrive->PhyDrive, (ULONGLONG)LengthInfo.Length.QuadPart,
588 (ULONGLONG)pPhyDrive->SizeInBytes);
589 CHECK_CLOSE_HANDLE(Handle);
590 return FALSE;
591 }
592
593 Query.PropertyId = StorageDeviceProperty;
594 Query.QueryType = PropertyStandardQuery;
595
596 bRet = DeviceIoControl(Handle,
597 IOCTL_STORAGE_QUERY_PROPERTY,
598 &Query,
599 sizeof(Query),
600 &DevDescHeader,
601 sizeof(STORAGE_DESCRIPTOR_HEADER),
602 &dwBytes,
603 NULL);
604 if (!bRet)
605 {
606 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes);
607 CHECK_CLOSE_HANDLE(Handle);
608 return FALSE;
609 }
610
611 if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))
612 {
613 Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size);
614 CHECK_CLOSE_HANDLE(Handle);
615 return FALSE;
616 }
617
618 pDevDesc = (STORAGE_DEVICE_DESCRIPTOR*)malloc(DevDescHeader.Size);
619 if (!pDevDesc)
620 {
621 Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size);
622 CHECK_CLOSE_HANDLE(Handle);
623 return FALSE;
624 }
625
626 bRet = DeviceIoControl(Handle,
627 IOCTL_STORAGE_QUERY_PROPERTY,
628 &Query,
629 sizeof(Query),
630 pDevDesc,
631 DevDescHeader.Size,
632 &dwBytes,
633 NULL);
634 if (!bRet)
635 {
636 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes);
637 free(pDevDesc);
638 goto out;
639 }
640
641
642
643 memset(&Query, 0, sizeof(STORAGE_PROPERTY_QUERY));
644 Query.PropertyId = StorageAccessAlignmentProperty;
645 Query.QueryType = PropertyStandardQuery;
646 memset(&diskAlignment, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR));
647
648 bRet = DeviceIoControl(Handle,
649 IOCTL_STORAGE_QUERY_PROPERTY,
650 &Query,
651 sizeof(STORAGE_PROPERTY_QUERY),
652 &diskAlignment,
653 sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
654 &dwBytes,
655 NULL);
656 if (!bRet)
657 {
658 Log("DeviceIoControl3 error:%u dwBytes:%u", LASTERR, dwBytes);
659 }
660
661 if (pPhyDrive->DeviceType != pDevDesc->DeviceType ||
662 pPhyDrive->RemovableMedia != pDevDesc->RemovableMedia ||
663 pPhyDrive->BusType != pDevDesc->BusType ||
664 pPhyDrive->BytesPerLogicalSector != diskAlignment.BytesPerLogicalSector ||
665 pPhyDrive->BytesPerPhysicalSector != diskAlignment.BytesPerPhysicalSector
666 )
667 {
668 Log("Some properties not match DeviceType[%u %u] Removable[%u %u] BusType[%u %u] LogSec[%u %u] PhySec[%u %u]",
669 pPhyDrive->DeviceType, pDevDesc->DeviceType,
670 pPhyDrive->RemovableMedia, pDevDesc->RemovableMedia,
671 pPhyDrive->BusType, pDevDesc->BusType,
672 pPhyDrive->BytesPerLogicalSector, diskAlignment.BytesPerLogicalSector,
673 pPhyDrive->BytesPerPhysicalSector, diskAlignment.BytesPerPhysicalSector
674 );
675 goto out;
676 }
677
678 if (pDevDesc->VendorIdOffset)
679 {
680 safe_strcpy(VendorId, (char*)pDevDesc + pDevDesc->VendorIdOffset);
681 TrimString(VendorId);
682
683 if (strcmp(pPhyDrive->VendorId, VendorId))
684 {
685 Log("VendorId not match <%s %s>", pPhyDrive->VendorId, VendorId);
686 goto out;
687 }
688 }
689
690 if (pDevDesc->ProductIdOffset)
691 {
692 safe_strcpy(ProductId, (char*)pDevDesc + pDevDesc->ProductIdOffset);
693 TrimString(ProductId);
694
695 if (strcmp(pPhyDrive->ProductId, ProductId))
696 {
697 Log("ProductId not match <%s %s>", pPhyDrive->ProductId, ProductId);
698 goto out;
699 }
700 }
701
702 if (pDevDesc->ProductRevisionOffset)
703 {
704 safe_strcpy(ProductRev, (char*)pDevDesc + pDevDesc->ProductRevisionOffset);
705 TrimString(ProductRev);
706
707 if (strcmp(pPhyDrive->ProductRev, ProductRev))
708 {
709 Log("ProductRev not match <%s %s>", pPhyDrive->ProductRev, ProductRev);
710 goto out;
711 }
712 }
713
714 if (pDevDesc->SerialNumberOffset)
715 {
716 safe_strcpy(SerialNumber, (char*)pDevDesc + pDevDesc->SerialNumberOffset);
717 TrimString(SerialNumber);
718
719 if (strcmp(pPhyDrive->SerialNumber, SerialNumber))
720 {
721 Log("ProductRev not match <%s %s>", pPhyDrive->SerialNumber, SerialNumber);
722 goto out;
723 }
724 }
725
726 Log("PhyDrive%d ALL match, now continue", pPhyDrive->PhyDrive);
727
728 bRet = TRUE;
729
730 out:
731 if (pDevDesc)
732 {
733 free(pDevDesc);
734 }
735
736 CHECK_CLOSE_HANDLE(Handle);
737
738 return bRet;
739 }
740
741 static HANDLE g_FatPhyDrive;
742 static UINT64 g_Part2StartSec;
743 static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen)
744 {
745 int rc = 1;
746 int size = 0;
747 char *buf = NULL;
748 void *flfile = NULL;
749
750 flfile = fl_fopen("/grub/grub.cfg", "rb");
751 if (flfile)
752 {
753 fl_fseek(flfile, 0, SEEK_END);
754 size = (int)fl_ftell(flfile);
755
756 fl_fseek(flfile, 0, SEEK_SET);
757
758 buf = (char *)malloc(size + 1);
759 if (buf)
760 {
761 fl_fread(buf, 1, size, flfile);
762 buf[size] = 0;
763
764 rc = 0;
765 sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf));
766 free(buf);
767 }
768
769 fl_fclose(flfile);
770 }
771
772 return rc;
773 }
774
775 static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
776 {
777 DWORD dwSize;
778 BOOL bRet;
779 DWORD ReadSize;
780 LARGE_INTEGER liCurrentPosition;
781
782 liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
783 liCurrentPosition.QuadPart *= 512;
784 SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
785
786 ReadSize = (DWORD)(SectorCount * 512);
787
788 bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
789 if (bRet == FALSE || dwSize != ReadSize)
790 {
791 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, LASTERR);
792 }
793
794 return 1;
795 }
796
797
798 int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen, BOOL *pSecureBoot)
799 {
800 int rc = 0;
801 HANDLE hDrive;
802 void *flfile;
803
804 hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE);
805 if (hDrive == INVALID_HANDLE_VALUE)
806 {
807 return 1;
808 }
809
810 g_FatPhyDrive = hDrive;
811 g_Part2StartSec = Part2StartSector;
812
813 Log("Parse FAT fs...");
814
815 fl_init();
816
817 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
818 {
819 Log("attach media success...");
820 rc = GetVentoyVersionFromFatFile(VerBuf, BufLen);
821 }
822 else
823 {
824 Log("attach media failed...");
825 rc = 1;
826 }
827
828 Log("GetVentoyVerInPhyDrive rc=%d...", rc);
829 if (rc == 0)
830 {
831 Log("VentoyVerInPhyDrive %d is <%s>...", pDriveInfo->PhyDrive, VerBuf);
832
833 flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
834 if (flfile)
835 {
836 *pSecureBoot = TRUE;
837 fl_fclose(flfile);
838 }
839 }
840
841 fl_shutdown();
842
843 CHECK_CLOSE_HANDLE(hDrive);
844
845 return rc;
846 }
847
848
849
850
851
852 static unsigned int g_disk_unxz_len = 0;
853 static BYTE *g_part_img_pos = NULL;
854 static BYTE *g_part_img_buf[VENTOY_EFI_PART_SIZE / SIZE_1MB];
855
856
857 static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
858 {
859 uint32 i;
860 uint32 offset;
861 BYTE *MbBuf = NULL;
862
863 for (i = 0; i < SectorCount; i++)
864 {
865 offset = (Sector + i) * 512;
866
867 if (g_part_img_buf[1] == NULL)
868 {
869 MbBuf = g_part_img_buf[0] + offset;
870 memcpy(Buffer + i * 512, MbBuf, 512);
871 }
872 else
873 {
874 MbBuf = g_part_img_buf[offset / SIZE_1MB];
875 memcpy(Buffer + i * 512, MbBuf + (offset % SIZE_1MB), 512);
876 }
877 }
878
879 return 1;
880 }
881
882
883 static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
884 {
885 uint32 i;
886 uint32 offset;
887 BYTE *MbBuf = NULL;
888
889 for (i = 0; i < SectorCount; i++)
890 {
891 offset = (Sector + i) * 512;
892
893 if (g_part_img_buf[1] == NULL)
894 {
895 MbBuf = g_part_img_buf[0] + offset;
896 memcpy(MbBuf, Buffer + i * 512, 512);
897 }
898 else
899 {
900 MbBuf = g_part_img_buf[offset / SIZE_1MB];
901 memcpy(MbBuf + (offset % SIZE_1MB), Buffer + i * 512, 512);
902 }
903 }
904
905 return 1;
906 }
907
908 int VentoyProcSecureBoot(BOOL SecureBoot)
909 {
910 int rc = 0;
911 int size;
912 char *filebuf = NULL;
913 void *file = NULL;
914
915 Log("VentoyProcSecureBoot %d ...", SecureBoot);
916
917 if (SecureBoot)
918 {
919 Log("Secure boot is enabled ...");
920 return 0;
921 }
922
923 fl_init();
924
925 if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite))
926 {
927 file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
928 Log("Open ventoy efi file %p ", file);
929 if (file)
930 {
931 fl_fseek(file, 0, SEEK_END);
932 size = (int)fl_ftell(file);
933 fl_fseek(file, 0, SEEK_SET);
934
935 Log("ventoy efi file size %d ...", size);
936
937 filebuf = (char *)malloc(size);
938 if (filebuf)
939 {
940 fl_fread(filebuf, 1, size, file);
941 }
942
943 fl_fclose(file);
944
945 Log("Now delete all efi files ...");
946 fl_remove("/EFI/BOOT/BOOTX64.EFI");
947 fl_remove("/EFI/BOOT/grubx64.efi");
948 fl_remove("/EFI/BOOT/grubx64_real.efi");
949 fl_remove("/EFI/BOOT/MokManager.efi");
950 fl_remove("/EFI/BOOT/mmx64.efi");
951 fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
952 fl_remove("/EFI/BOOT/grub.efi");
953
954 file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
955 Log("Open bootx64 efi file %p ", file);
956 if (file)
957 {
958 if (filebuf)
959 {
960 fl_fwrite(filebuf, 1, size, file);
961 }
962
963 fl_fflush(file);
964 fl_fclose(file);
965 }
966
967 if (filebuf)
968 {
969 free(filebuf);
970 }
971 }
972
973 file = fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");
974 Log("Open ventoy efi file %p ", file);
975 if (file)
976 {
977 fl_fseek(file, 0, SEEK_END);
978 size = (int)fl_ftell(file);
979 fl_fseek(file, 0, SEEK_SET);
980
981 Log("ventoy efi file size %d ...", size);
982
983 filebuf = (char *)malloc(size);
984 if (filebuf)
985 {
986 fl_fread(filebuf, 1, size, file);
987 }
988
989 fl_fclose(file);
990
991 Log("Now delete all efi files ...");
992 fl_remove("/EFI/BOOT/BOOTIA32.EFI");
993 fl_remove("/EFI/BOOT/grubia32.efi");
994 fl_remove("/EFI/BOOT/grubia32_real.efi");
995 fl_remove("/EFI/BOOT/mmia32.efi");
996
997 file = fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");
998 Log("Open bootia32 efi file %p ", file);
999 if (file)
1000 {
1001 if (filebuf)
1002 {
1003 fl_fwrite(filebuf, 1, size, file);
1004 }
1005
1006 fl_fflush(file);
1007 fl_fclose(file);
1008 }
1009
1010 if (filebuf)
1011 {
1012 free(filebuf);
1013 }
1014 }
1015
1016 }
1017 else
1018 {
1019 rc = 1;
1020 }
1021
1022 fl_shutdown();
1023
1024 return rc;
1025 }
1026
1027
1028
1029 static int disk_xz_flush(void *src, unsigned int size)
1030 {
1031 unsigned int i;
1032 BYTE *buf = (BYTE *)src;
1033
1034 for (i = 0; i < size; i++)
1035 {
1036 *g_part_img_pos = *buf++;
1037
1038 g_disk_unxz_len++;
1039 if ((g_disk_unxz_len % SIZE_1MB) == 0)
1040 {
1041 g_part_img_pos = g_part_img_buf[g_disk_unxz_len / SIZE_1MB];
1042 }
1043 else
1044 {
1045 g_part_img_pos++;
1046 }
1047 }
1048
1049 return (int)size;
1050 }
1051
1052 static void unxz_error(char *x)
1053 {
1054 Log("%s", x);
1055 }
1056
1057 static BOOL TryWritePart2(HANDLE hDrive, UINT64 StartSectorId)
1058 {
1059 BOOL bRet;
1060 DWORD TrySize = 16 * 1024;
1061 DWORD dwSize;
1062 BYTE *Buffer = NULL;
1063 unsigned char *data = NULL;
1064 LARGE_INTEGER liCurrentPosition;
1065
1066 liCurrentPosition.QuadPart = StartSectorId * 512;
1067 SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
1068
1069 Buffer = malloc(TrySize);
1070
1071 bRet = WriteFile(hDrive, Buffer, TrySize, &dwSize, NULL);
1072
1073 free(Buffer);
1074
1075 Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
1076
1077 if (bRet && dwSize == TrySize)
1078 {
1079 return TRUE;
1080 }
1081
1082 return FALSE;
1083 }
1084
1085 static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId)
1086 {
1087 int i;
1088 int rc = 0;
1089 int len = 0;
1090 int writelen = 0;
1091 int partwrite = 0;
1092 int Pos = PT_WRITE_VENTOY_START;
1093 DWORD dwSize = 0;
1094 BOOL bRet;
1095 unsigned char *data = NULL;
1096 LARGE_INTEGER liCurrentPosition;
1097 LARGE_INTEGER liNewPosition;
1098 BYTE *CheckBuf = NULL;
1099
1100 Log("FormatPart2Fat %llu...", (ULONGLONG)StartSectorId);
1101
1102 CheckBuf = malloc(SIZE_1MB);
1103 if (!CheckBuf)
1104 {
1105 Log("Failed to malloc check buf");
1106 return 1;
1107 }
1108
1109 rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&data, &len);
1110 if (rc)
1111 {
1112 Log("Failed to read img file %p %u", data, len);
1113 free(CheckBuf);
1114 return 1;
1115 }
1116
1117 liCurrentPosition.QuadPart = StartSectorId * 512;
1118 SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
1119
1120 memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
1121
1122 g_part_img_buf[0] = (BYTE *)malloc(VENTOY_EFI_PART_SIZE);
1123 if (g_part_img_buf[0])
1124 {
1125 Log("Malloc whole img buffer success, now decompress ...");
1126 unxz(data, len, NULL, NULL, g_part_img_buf[0], &writelen, unxz_error);
1127
1128 if (len == writelen)
1129 {
1130 Log("decompress finished success");
1131
1132 VentoyProcSecureBoot(g_SecureBoot);
1133
1134 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1135 {
1136 dwSize = 0;
1137 bRet = WriteFile(hDrive, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB, &dwSize, NULL);
1138 Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
1139
1140 if (!bRet)
1141 {
1142 rc = 1;
1143 goto End;
1144 }
1145
1146 PROGRESS_BAR_SET_POS(Pos);
1147 if (i % 2 == 0)
1148 {
1149 Pos++;
1150 }
1151 }
1152
1153 //Read and check the data
1154 liCurrentPosition.QuadPart = StartSectorId * 512;
1155 SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
1156
1157 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1158 {
1159 bRet = ReadFile(hDrive, CheckBuf, SIZE_1MB, &dwSize, NULL);
1160 Log("Read part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
1161
1162 if (!bRet || memcmp(CheckBuf, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB))
1163 {
1164 Log("### [Check Fail] The data write and read does not match");
1165 rc = 1;
1166 goto End;
1167 }
1168
1169 PROGRESS_BAR_SET_POS(Pos);
1170 if (i % 2 == 0)
1171 {
1172 Pos++;
1173 }
1174 }
1175 }
1176 else
1177 {
1178 rc = 1;
1179 Log("decompress finished failed");
1180 goto End;
1181 }
1182 }
1183 else
1184 {
1185 Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE);
1186
1187 partwrite = 1;
1188 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1189 {
1190 g_part_img_buf[i] = (BYTE *)malloc(SIZE_1MB);
1191 if (g_part_img_buf[i] == NULL)
1192 {
1193 rc = 1;
1194 goto End;
1195 }
1196 }
1197
1198 Log("Malloc part img buffer success, now decompress ...");
1199
1200 g_part_img_pos = g_part_img_buf[0];
1201
1202 unxz(data, len, NULL, disk_xz_flush, NULL, NULL, unxz_error);
1203
1204 if (g_disk_unxz_len == VENTOY_EFI_PART_SIZE)
1205 {
1206 Log("decompress finished success");
1207
1208 VentoyProcSecureBoot(g_SecureBoot);
1209
1210 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1211 {
1212 dwSize = 0;
1213 bRet = WriteFile(hDrive, g_part_img_buf[i], SIZE_1MB, &dwSize, NULL);
1214 Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
1215
1216 if (!bRet)
1217 {
1218 rc = 1;
1219 goto End;
1220 }
1221
1222 PROGRESS_BAR_SET_POS(Pos);
1223 if (i % 2 == 0)
1224 {
1225 Pos++;
1226 }
1227 }
1228
1229 //Read and check the data
1230 liCurrentPosition.QuadPart = StartSectorId * 512;
1231 SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
1232
1233 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1234 {
1235 bRet = ReadFile(hDrive, CheckBuf, SIZE_1MB, &dwSize, NULL);
1236 Log("Read part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
1237
1238 if (!bRet || memcmp(CheckBuf, g_part_img_buf[i], SIZE_1MB))
1239 {
1240 Log("### [Check Fail] The data write and read does not match");
1241 rc = 1;
1242 goto End;
1243 }
1244
1245 PROGRESS_BAR_SET_POS(Pos);
1246 if (i % 2 == 0)
1247 {
1248 Pos++;
1249 }
1250 }
1251 }
1252 else
1253 {
1254 rc = 1;
1255 Log("decompress finished failed");
1256 goto End;
1257 }
1258 }
1259
1260 End:
1261
1262 if (data) free(data);
1263 if (CheckBuf)free(CheckBuf);
1264
1265 if (partwrite)
1266 {
1267 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1268 {
1269 if (g_part_img_buf[i]) free(g_part_img_buf[i]);
1270 }
1271 }
1272 else
1273 {
1274 if (g_part_img_buf[0]) free(g_part_img_buf[0]);
1275 }
1276
1277 return rc;
1278 }
1279
1280 static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle)
1281 {
1282 int Len = 0;
1283 int readLen = 0;
1284 BOOL bRet;
1285 DWORD dwSize;
1286 BYTE *ImgBuf = NULL;
1287 BYTE *RawBuf = NULL;
1288
1289 Log("WriteGrubStage1ToPhyDrive ...");
1290
1291 RawBuf = (BYTE *)malloc(SIZE_1MB);
1292 if (!RawBuf)
1293 {
1294 return 1;
1295 }
1296
1297 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
1298 {
1299 Log("Failed to read stage1 img");
1300 free(RawBuf);
1301 return 1;
1302 }
1303
1304 unxz(ImgBuf, Len, NULL, NULL, RawBuf, &readLen, unxz_error);
1305
1306 if (PartStyle)
1307 {
1308 Log("Write GPT stage1 ...");
1309 RawBuf[500] = 35;//update blocklist
1310 SetFilePointer(hDrive, 512 * 34, NULL, FILE_BEGIN);
1311 bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512 * 34, &dwSize, NULL);
1312 }
1313 else
1314 {
1315 Log("Write MBR stage1 ...");
1316 SetFilePointer(hDrive, 512, NULL, FILE_BEGIN);
1317 bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512, &dwSize, NULL);
1318 }
1319
1320 Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet, dwSize, GetLastError());
1321
1322 free(RawBuf);
1323 free(ImgBuf);
1324 return 0;
1325 }
1326
1327
1328 static int FormatPart1LargeFAT32(UINT64 DiskSizeBytes, int CluserSize)
1329 {
1330 MKFS_PARM Option;
1331 FRESULT Ret;
1332 FATFS FS;
1333
1334 Option.fmt = FM_FAT32;
1335 Option.n_fat = 1;
1336 Option.align = 8;
1337 Option.n_root = 1;
1338
1339 if (CluserSize == 0)
1340 {
1341 // < 32GB select 32KB as cluster size
1342 // > 32GB select 128KB as cluster size
1343 if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32)
1344 {
1345 Option.au_size = 32768;
1346 }
1347 else
1348 {
1349 Option.au_size = 131072;
1350 }
1351 }
1352 else
1353 {
1354 Option.au_size = CluserSize;
1355 }
1356
1357 Log("Formatting Part1 large FAT32 ClusterSize:%u(%uKB) ...", CluserSize, CluserSize / 1024);
1358
1359 disk_io_reset_write_error();
1360
1361 Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
1362 if (FR_OK == Ret)
1363 {
1364 if (disk_io_is_write_error())
1365 {
1366 Log("Formatting Part1 large FAT32 failed, write error.");
1367 return 1;
1368 }
1369
1370 Log("Formatting Part1 large FAT32 success, now set label");
1371
1372 Ret = f_mount(&FS, TEXT("0:"), 1);
1373 if (FR_OK == Ret)
1374 {
1375 Log("f_mount SUCCESS");
1376 Ret = f_setlabel(TEXT("0:Ventoy"));
1377 if (FR_OK == Ret)
1378 {
1379 Log("f_setlabel SUCCESS");
1380 Ret = f_unmount(TEXT("0:"));
1381 Log("f_unmount %d %s", Ret, (FR_OK == Ret) ? "SUCCESS" : "FAILED");
1382 }
1383 else
1384 {
1385 Log("f_setlabel failed %d", Ret);
1386 }
1387 }
1388 else
1389 {
1390 Log("f_mount failed %d", Ret);
1391 }
1392
1393 return 0;
1394 }
1395 else
1396 {
1397 Log("Formatting Part1 large FAT32 failed");
1398 return 1;
1399 }
1400 }
1401
1402 static int FormatPart1exFAT(UINT64 DiskSizeBytes)
1403 {
1404 MKFS_PARM Option;
1405 FRESULT Ret;
1406
1407 Option.fmt = FM_EXFAT;
1408 Option.n_fat = 1;
1409 Option.align = 8;
1410 Option.n_root = 1;
1411
1412 // < 32GB select 32KB as cluster size
1413 // > 32GB select 128KB as cluster size
1414 if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32)
1415 {
1416 Option.au_size = 32768;
1417 }
1418 else
1419 {
1420 Option.au_size = 131072;
1421 }
1422
1423 Log("Formatting Part1 exFAT ...");
1424
1425 disk_io_reset_write_error();
1426
1427 Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
1428 if (FR_OK == Ret)
1429 {
1430 if (disk_io_is_write_error())
1431 {
1432 Log("Formatting Part1 exFAT failed, write error.");
1433 return 1;
1434 }
1435
1436 Log("Formatting Part1 exFAT success");
1437 return 0;
1438 }
1439 else
1440 {
1441 Log("Formatting Part1 exFAT failed");
1442 return 1;
1443 }
1444 }
1445
1446 static int ZeroPart1FileSystem(HANDLE hDrive, UINT64 Part2StartSector)
1447 {
1448 int i;
1449 DWORD dwSize = 0;
1450 LARGE_INTEGER liCurPos;
1451 LARGE_INTEGER liNewPos;
1452 CHAR TmpBuffer[1024] = { 0 };
1453
1454 liCurPos.QuadPart = VENTOY_PART1_START_SECTOR * 512;
1455 liNewPos.QuadPart = 0;
1456 if (0 == SetFilePointerEx(hDrive, liCurPos, &liNewPos, FILE_BEGIN) ||
1457 liNewPos.QuadPart != liCurPos.QuadPart)
1458 {
1459 Log("SetFilePointerEx Failed %u %llu %llu", LASTERR, (ULONGLONG)liCurPos.QuadPart, (ULONGLONG)liNewPos.QuadPart);
1460 return 1;
1461 }
1462
1463 for (i = 0; i < 1024; i++)
1464 {
1465 WriteFile(hDrive, TmpBuffer, 1024, &dwSize, NULL);
1466 }
1467
1468 liCurPos.QuadPart = (Part2StartSector * 512) - (1024 * 1024);
1469 liNewPos.QuadPart = 0;
1470 if (0 == SetFilePointerEx(hDrive, liCurPos, &liNewPos, FILE_BEGIN) ||
1471 liNewPos.QuadPart != liCurPos.QuadPart)
1472 {
1473 Log("SetFilePointerEx Failed %u %llu %llu", LASTERR, (ULONGLONG)liCurPos.QuadPart, (ULONGLONG)liNewPos.QuadPart);
1474 return 1;
1475 }
1476
1477 for (i = 0; i < 1024; i++)
1478 {
1479 WriteFile(hDrive, TmpBuffer, 1024, &dwSize, NULL);
1480 }
1481
1482 Log("Zero Part1 SUCCESS");
1483 return 0;
1484 }
1485
1486 int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter)
1487 {
1488 int i;
1489 int rc = 0;
1490 int state = 0;
1491 HANDLE hDrive;
1492 DWORD dwSize;
1493 BOOL bRet;
1494 CHAR MountDrive;
1495 CHAR DriveName[] = "?:\\";
1496 CHAR DriveLetters[MAX_PATH] = { 0 };
1497 LARGE_INTEGER liCurrentPosition;
1498 char *pTmpBuf = NULL;
1499 MBR_HEAD MBR;
1500
1501 *pDrvLetter = 0;
1502
1503 Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
1504 pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1505 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1506
1507 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1508
1509 Log("Lock disk for clean ............................. ");
1510
1511 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
1512 if (hDrive == INVALID_HANDLE_VALUE)
1513 {
1514 Log("Failed to open physical disk");
1515 return 1;
1516 }
1517
1518 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1519
1520 if (DriveLetters[0] == 0)
1521 {
1522 Log("No drive letter was assigned...");
1523 DriveName[0] = GetFirstUnusedDriveLetter();
1524 Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
1525 }
1526 else
1527 {
1528 // Unmount all mounted volumes that belong to this drive
1529 // Do it in reverse so that we always end on the first volume letter
1530 for (i = (int)strlen(DriveLetters); i > 0; i--)
1531 {
1532 DriveName[0] = DriveLetters[i - 1];
1533 bRet = DeleteVolumeMountPointA(DriveName);
1534 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
1535 }
1536 }
1537
1538 MountDrive = DriveName[0];
1539 Log("Will use '%C:' as volume mountpoint", DriveName[0]);
1540
1541 // It kind of blows, but we have to relinquish access to the physical drive
1542 // for VDS to be able to delete the partitions that reside on it...
1543 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
1544 CHECK_CLOSE_HANDLE(hDrive);
1545
1546 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
1547
1548 if (!VDS_DeleteAllPartitions(pPhyDrive->PhyDrive))
1549 {
1550 Log("Notice: Could not delete partitions: %u", GetLastError());
1551 }
1552
1553 Log("Deleting all partitions ......................... OK");
1554
1555 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
1556
1557 Log("Lock disk for write ............................. ");
1558 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
1559 if (hDrive == INVALID_HANDLE_VALUE)
1560 {
1561 Log("Failed to GetPhysicalHandle for write.");
1562 rc = 1;
1563 goto End;
1564 }
1565
1566 // clear first and last 2MB space
1567 pTmpBuf = malloc(SIZE_2MB);
1568 if (!pTmpBuf)
1569 {
1570 Log("Failed to alloc memory.");
1571 rc = 1;
1572 goto End;
1573 }
1574 memset(pTmpBuf, 0, SIZE_2MB);
1575
1576 SET_FILE_POS(512);
1577 bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB - 512, &dwSize, NULL);
1578 Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1579 if (!bRet)
1580 {
1581 rc = 1;
1582 goto End;
1583 }
1584
1585 SET_FILE_POS(pPhyDrive->SizeInBytes - SIZE_2MB);
1586 bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB, &dwSize, NULL);
1587 Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1588 if (!bRet)
1589 {
1590 rc = 1;
1591 goto End;
1592 }
1593
1594 SET_FILE_POS(0);
1595
1596 if (pPhyDrive->SizeInBytes > 2199023255552ULL)
1597 {
1598 VTOY_GPT_INFO *pGptInfo;
1599 VTOY_GPT_HDR BackupHead;
1600 LARGE_INTEGER liCurrentPosition;
1601
1602 pGptInfo = (VTOY_GPT_INFO *)pTmpBuf;
1603
1604 VentoyFillWholeGpt(pPhyDrive->SizeInBytes, pGptInfo);
1605
1606 SET_FILE_POS(pPhyDrive->SizeInBytes - 512);
1607 VentoyFillBackupGptHead(pGptInfo, &BackupHead);
1608 if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))
1609 {
1610 rc = 1;
1611 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1612 goto End;
1613 }
1614
1615 SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);
1616 if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))
1617 {
1618 rc = 1;
1619 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1620 goto End;
1621 }
1622
1623 SET_FILE_POS(0);
1624 if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))
1625 {
1626 rc = 1;
1627 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1628 goto End;
1629 }
1630
1631 Log("Write GPT Info OK ...");
1632 }
1633 else
1634 {
1635 bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
1636 Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1637 if (!bRet)
1638 {
1639 rc = 1;
1640 goto End;
1641 }
1642
1643 //clear boot code and partition table (reserved disk signature)
1644 memset(MBR.BootCode, 0, 440);
1645 memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl));
1646
1647 VentoyFillMBRLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl);
1648
1649 MBR.PartTbl[0].Active = 0x00; // bootable
1650 MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS
1651
1652 SET_FILE_POS(0);
1653 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
1654 Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1655 if (!bRet)
1656 {
1657 rc = 1;
1658 goto End;
1659 }
1660 }
1661
1662 Log("Clear Ventoy successfully finished");
1663
1664 //Refresh Drive Layout
1665 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
1666
1667 End:
1668
1669 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1670 PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH);
1671
1672 if (pTmpBuf)
1673 {
1674 free(pTmpBuf);
1675 }
1676
1677 if (rc == 0)
1678 {
1679 Log("Mounting Ventoy Partition ....................... ");
1680 Sleep(1000);
1681
1682 state = 0;
1683 memset(DriveLetters, 0, sizeof(DriveLetters));
1684 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1685 Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
1686
1687 for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
1688 {
1689 DriveName[0] = DriveLetters[i];
1690 Log("%s is ventoy part1, already mounted", DriveName);
1691 state = 1;
1692 }
1693
1694 if (state != 1)
1695 {
1696 Log("need to mount ventoy part1...");
1697 if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, 2048, DriveLetters, sizeof(DriveLetters), FALSE))
1698 {
1699 DriveName[0] = MountDrive;
1700 bRet = SetVolumeMountPointA(DriveName, DriveLetters);
1701 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
1702
1703 *pDrvLetter = MountDrive;
1704 }
1705 else
1706 {
1707 Log("Failed to find ventoy volume");
1708 }
1709 }
1710
1711 Log("OK\n");
1712 }
1713 else
1714 {
1715 FindProcessOccupyDisk(hDrive, pPhyDrive);
1716 }
1717
1718 CHECK_CLOSE_HANDLE(hDrive);
1719 return rc;
1720 }
1721
1722 int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
1723 {
1724 int i;
1725 int rc = 1;
1726 int Len = 0;
1727 int dataLen = 0;
1728 UINT size = 0;
1729 UINT segnum = 0;
1730 UINT32 chksum = 0;
1731 UINT64 data_offset = 0;
1732 UINT64 Part2StartSector = 0;
1733 UINT64 Part1StartSector = 0;
1734 UINT64 Part1SectorCount = 0;
1735 UINT8 *pData = NULL;
1736 UINT8 *pBkGptPartTbl = NULL;
1737 BYTE *ImgBuf = NULL;
1738 MBR_HEAD *pMBR = NULL;
1739 VTSI_FOOTER *pImgFooter = NULL;
1740 VTSI_SEGMENT *pSegment = NULL;
1741 VTOY_GPT_INFO *pGptInfo = NULL;
1742 VTOY_GPT_HDR *pBkGptHdr = NULL;
1743 FILE *fp = NULL;
1744
1745 Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",
1746 PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1747 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1748
1749 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1750
1751 size = SIZE_1MB + VENTOY_EFI_PART_SIZE + 33 * 512 + VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT) + sizeof(VTSI_FOOTER);
1752
1753 pData = (UINT8 *)malloc(size);
1754 if (!pData)
1755 {
1756 Log("malloc image buffer failed %d.", size);
1757 goto End;
1758 }
1759
1760 pImgFooter = (VTSI_FOOTER *)(pData + size - sizeof(VTSI_FOOTER));
1761 pSegment = (VTSI_SEGMENT *)((UINT8 *)pImgFooter - VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));
1762 memset(pImgFooter, 0, sizeof(VTSI_FOOTER));
1763 memset(pSegment, 0, VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));
1764
1765 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START);
1766
1767 Log("Writing Boot Image ............................. ");
1768 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
1769 {
1770 Log("Failed to read stage1 img");
1771 goto End;
1772 }
1773
1774 unxz(ImgBuf, Len, NULL, NULL, pData, &dataLen, unxz_error);
1775 SAFE_FREE(ImgBuf);
1776
1777 Log("decompress %s len:%d", VENTOY_FILE_STG1_IMG, dataLen);
1778
1779 if (PartStyle)
1780 {
1781 pData[500] = 35;//update blocklist
1782 memmove(pData + 34 * 512, pData, SIZE_1MB - 512 * 34);
1783 memset(pData, 0, 34 * 512);
1784
1785 pGptInfo = (VTOY_GPT_INFO *)pData;
1786 memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
1787 VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);
1788
1789 pBkGptPartTbl = pData + SIZE_1MB + VENTOY_EFI_PART_SIZE;
1790 memset(pBkGptPartTbl, 0, 33 * 512);
1791
1792 memcpy(pBkGptPartTbl, pGptInfo->PartTbl, 32 * 512);
1793 pBkGptHdr = (VTOY_GPT_HDR *)(pBkGptPartTbl + 32 * 512);
1794 VentoyFillBackupGptHead(pGptInfo, pBkGptHdr);
1795
1796 Part1StartSector = pGptInfo->PartTbl[0].StartLBA;
1797 Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;
1798 Part2StartSector = pGptInfo->PartTbl[1].StartLBA;
1799
1800 Log("Write GPT Info OK ...");
1801 }
1802 else
1803 {
1804 memmove(pData + 512, pData, SIZE_1MB - 512);
1805 memset(pData, 0, 512);
1806
1807 pMBR = (MBR_HEAD *)pData;
1808 VentoyFillMBR(pPhyDrive->SizeInBytes, pMBR, PartStyle, 0x07);
1809 Part1StartSector = pMBR->PartTbl[0].StartSectorId;
1810 Part1SectorCount = pMBR->PartTbl[0].SectorCount;
1811 Part2StartSector = pMBR->PartTbl[1].StartSectorId;
1812
1813 Log("Write MBR OK ...");
1814 }
1815
1816 Log("Writing EFI part Image ............................. ");
1817 rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&ImgBuf, &Len);
1818 if (rc)
1819 {
1820 Log("Failed to read img file %p %u", ImgBuf, Len);
1821 goto End;
1822 }
1823
1824 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + 28);
1825 memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
1826 unxz(ImgBuf, Len, NULL, NULL, pData + SIZE_1MB, &dataLen, unxz_error);
1827 if (dataLen == Len)
1828 {
1829 Log("decompress finished success");
1830 g_part_img_buf[0] = pData + SIZE_1MB;
1831
1832 VentoyProcSecureBoot(g_SecureBoot);
1833 }
1834 else
1835 {
1836 Log("decompress finished failed");
1837 goto End;
1838 }
1839
1840 fopen_s(&fp, "VentoySparseImg.vtsi", "wb+");
1841 if (!fp)
1842 {
1843 Log("Failed to create Ventoy img file");
1844 goto End;
1845 }
1846
1847 Log("Writing stage1 data ............................. ");
1848
1849 fwrite(pData, 1, SIZE_1MB, fp);
1850
1851 pSegment[0].disk_start_sector = 0;
1852 pSegment[0].sector_num = SIZE_1MB / 512;
1853 pSegment[0].data_offset = data_offset;
1854 data_offset += pSegment[0].sector_num * 512;
1855
1856 disk_io_set_param(INVALID_HANDLE_VALUE, Part1StartSector + Part1SectorCount);// include the 2048 sector gap
1857 disk_io_set_imghook(fp, pSegment + 1, VTSI_IMG_MAX_SEG - 1, data_offset);
1858
1859 Log("Formatting part1 exFAT ...");
1860 if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
1861 {
1862 Log("FormatPart1exFAT failed.");
1863 disk_io_reset_imghook(&segnum, &data_offset);
1864 goto End;
1865 }
1866
1867 disk_io_reset_imghook(&segnum, &data_offset);
1868 segnum++;
1869
1870 Log("current segment number:%d dataoff:%ld", segnum, (long)data_offset);
1871
1872 //write data
1873 Log("Writing part2 data ............................. ");
1874 fwrite(pData + SIZE_1MB, 1, VENTOY_EFI_PART_SIZE, fp);
1875 pSegment[segnum].disk_start_sector = Part2StartSector;
1876 pSegment[segnum].sector_num = VENTOY_EFI_PART_SIZE / 512;
1877 pSegment[segnum].data_offset = data_offset;
1878 data_offset += pSegment[segnum].sector_num * 512;
1879 segnum++;
1880
1881 if (PartStyle)
1882 {
1883 Log("Writing backup gpt table ............................. ");
1884 fwrite(pBkGptPartTbl, 1, 33 * 512, fp);
1885 pSegment[segnum].disk_start_sector = pPhyDrive->SizeInBytes / 512 - 33;
1886 pSegment[segnum].sector_num = 33;
1887 pSegment[segnum].data_offset = data_offset;
1888 data_offset += pSegment[segnum].sector_num * 512;
1889 segnum++;
1890 }
1891
1892 Log("Writing segment metadata ............................. ");
1893
1894 for (i = 0; i < (int)segnum; i++)
1895 {
1896 Log("SEG[%d]: PhySector:%llu SectorNum:%llu DataOffset:%llu(sector:%llu)", i, pSegment[i].disk_start_sector, pSegment[i].sector_num,
1897 pSegment[i].data_offset, pSegment[i].data_offset / 512);
1898 }
1899
1900 dataLen = segnum * sizeof(VTSI_SEGMENT);
1901 fwrite(pSegment, 1, dataLen, fp);
1902
1903 if (dataLen % 512)
1904 {
1905 //pData + SIZE_1MB - 8192 is a temp data buffer with zero
1906 fwrite(pData + SIZE_1MB - 8192, 1, 512 - (dataLen % 512), fp);
1907 }
1908
1909 //Fill footer
1910 pImgFooter->magic = VTSI_IMG_MAGIC;
1911 pImgFooter->version = 1;
1912 pImgFooter->disk_size = pPhyDrive->SizeInBytes;
1913 memcpy(&pImgFooter->disk_signature, pPhyDrive->MBR.BootCode + 0x1b8, 4);
1914 pImgFooter->segment_num = segnum;
1915 pImgFooter->segment_offset = data_offset;
1916
1917 for (i = 0, chksum = 0; i < (int)(segnum * sizeof(VTSI_SEGMENT)); i++)
1918 {
1919 chksum += *((UINT8 *)pSegment + i);
1920 }
1921 pImgFooter->segment_chksum = ~chksum;
1922
1923 for (i = 0, chksum = 0; i < sizeof(VTSI_FOOTER); i++)
1924 {
1925 chksum += *((UINT8 *)pImgFooter + i);
1926 }
1927 pImgFooter->foot_chksum = ~chksum;
1928
1929 Log("Writing footer segnum(%u) segoffset(%llu) ......................", segnum, data_offset);
1930 Log("disk_size=%llu disk_signature=%lx segment_offset=%llu", pImgFooter->disk_size, pImgFooter->disk_signature, pImgFooter->segment_offset);
1931
1932 fwrite(pImgFooter, 1, sizeof(VTSI_FOOTER), fp);
1933 fclose(fp);
1934
1935 Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset + 512 + ((dataLen + 511) / 512 * 512));
1936
1937 rc = 0;
1938
1939 End:
1940
1941 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1942 PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH);
1943
1944 Log("retcode:%d\n", rc);
1945
1946 SAFE_FREE(pData);
1947 SAFE_FREE(ImgBuf);
1948
1949 return rc;
1950 }
1951
1952
1953 int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)
1954 {
1955 int i;
1956 int rc = 0;
1957 int state = 0;
1958 BOOL ReformatOK;
1959 HANDLE hDrive;
1960 DWORD dwSize;
1961 BOOL bRet;
1962 CHAR MountDrive;
1963 CHAR DriveName[] = "?:\\";
1964 CHAR DriveLetters[MAX_PATH] = { 0 };
1965 MBR_HEAD MBR;
1966 VTOY_GPT_INFO *pGptInfo = NULL;
1967 UINT64 Part1StartSector = 0;
1968 UINT64 Part1SectorCount = 0;
1969 UINT64 Part2StartSector = 0;
1970 BOOL LargeFAT32 = FALSE;
1971 BOOL DefaultExFAT = FALSE;
1972 UINT8 FsFlag = 0x07;
1973
1974 Log("#####################################################");
1975 Log("InstallVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId,
1976 PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1977 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1978 Log("#####################################################");
1979
1980 if (PartStyle)
1981 {
1982 pGptInfo = malloc(sizeof(VTOY_GPT_INFO));
1983 memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
1984 }
1985
1986 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1987
1988 if (PartStyle)
1989 {
1990 VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);
1991 Part1StartSector = pGptInfo->PartTbl[0].StartLBA;
1992 Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;
1993 Part2StartSector = pGptInfo->PartTbl[1].StartLBA;
1994 }
1995 else
1996 {
1997 if (GetVentoyFsType() == VTOY_FS_FAT32)
1998 {
1999 FsFlag = 0x0C;
2000 }
2001
2002 VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle, FsFlag);
2003 Part1StartSector = MBR.PartTbl[0].StartSectorId;
2004 Part1SectorCount = MBR.PartTbl[0].SectorCount;
2005 Part2StartSector = MBR.PartTbl[1].StartSectorId;
2006 }
2007
2008 Log("Lock disk for clean ............................. ");
2009
2010 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
2011 if (hDrive == INVALID_HANDLE_VALUE)
2012 {
2013 Log("Failed to open physical disk");
2014 free(pGptInfo);
2015 return 1;
2016 }
2017
2018 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
2019
2020 if (DriveLetters[0] == 0)
2021 {
2022 Log("No drive letter was assigned...");
2023 DriveName[0] = GetFirstUnusedDriveLetter();
2024 Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
2025 }
2026 else
2027 {
2028 // Unmount all mounted volumes that belong to this drive
2029 // Do it in reverse so that we always end on the first volume letter
2030 for (i = (int)strlen(DriveLetters); i > 0; i--)
2031 {
2032 DriveName[0] = DriveLetters[i - 1];
2033 bRet = DeleteVolumeMountPointA(DriveName);
2034 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
2035 }
2036 }
2037
2038 MountDrive = DriveName[0];
2039 Log("Will use '%C:' as volume mountpoint", DriveName[0]);
2040
2041 // It kind of blows, but we have to relinquish access to the physical drive
2042 // for VDS to be able to delete the partitions that reside on it...
2043 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2044 CHECK_CLOSE_HANDLE(hDrive);
2045
2046 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
2047
2048 if (!VDS_DeleteAllPartitions(pPhyDrive->PhyDrive))
2049 {
2050 Log("Notice: Could not delete partitions: 0x%x, but we continue.", GetLastError());
2051 }
2052
2053 Log("Deleting all partitions ......................... OK");
2054
2055 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
2056
2057 Log("Lock disk for write ............................. ");
2058 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2059 if (hDrive == INVALID_HANDLE_VALUE)
2060 {
2061 Log("Failed to GetPhysicalHandle for write.");
2062 rc = 1;
2063 goto End;
2064 }
2065
2066 //Refresh Drive Layout
2067 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
2068
2069 disk_io_set_param(hDrive, Part1StartSector + Part1SectorCount);// include the 2048 sector gap
2070
2071 PROGRESS_BAR_SET_POS(PT_FORMAT_PART1);
2072
2073 if (PartStyle == 1 && pPhyDrive->PartStyle == 0)
2074 {
2075 Log("Wait for format part1 ...");
2076 Sleep(1000 * 5);
2077 }
2078
2079 if (GetVentoyFsType() == VTOY_FS_FAT32 && (Part1SectorCount * 512 >= FAT32_MAX_LIMIT))
2080 {
2081 Log("Formatting part1 large FAT32 ...");
2082 LargeFAT32 = TRUE;
2083 if (0 != FormatPart1LargeFAT32(pPhyDrive->SizeInBytes, GetClusterSize()))
2084 {
2085 Log("FormatPart1LargeFAT32 failed.");
2086 rc = 1;
2087 goto End;
2088 }
2089 }
2090 else if (GetVentoyFsType() == VTOY_FS_EXFAT && GetClusterSize() == 0)
2091 {
2092 Log("Formatting part1 exFAT ...");
2093 DefaultExFAT = TRUE;
2094 if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
2095 {
2096 Log("FormatPart1exFAT failed.");
2097 rc = 1;
2098 goto End;
2099 }
2100 }
2101 else
2102 {
2103 Log("Zero part1 file system ...");
2104 if (0 != ZeroPart1FileSystem(hDrive, Part2StartSector))
2105 {
2106 Log("ZeroPart1FileSystem failed.");
2107 rc = 1;
2108 goto End;
2109 }
2110 }
2111
2112 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
2113 Log("Writing part2 FAT img ...");
2114
2115 if (0 != FormatPart2Fat(hDrive, Part2StartSector))
2116 {
2117 Log("FormatPart2Fat failed.");
2118 rc = 1;
2119 goto End;
2120 }
2121
2122 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);
2123 Log("Writing Boot Image ............................. ");
2124 if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0)
2125 {
2126 Log("WriteGrubStage1ToPhyDrive failed.");
2127 rc = 1;
2128 goto End;
2129 }
2130
2131 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);
2132 Log("Writing Partition Table ........................ ");
2133 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2134
2135 if (PartStyle)
2136 {
2137 VTOY_GPT_HDR BackupHead;
2138 LARGE_INTEGER liCurrentPosition;
2139
2140 SET_FILE_POS(pPhyDrive->SizeInBytes - 512);
2141 VentoyFillBackupGptHead(pGptInfo, &BackupHead);
2142 if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))
2143 {
2144 rc = 1;
2145 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
2146 goto End;
2147 }
2148
2149 SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);
2150 if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))
2151 {
2152 rc = 1;
2153 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
2154 goto End;
2155 }
2156
2157 SET_FILE_POS(0);
2158 if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))
2159 {
2160 rc = 1;
2161 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
2162 goto End;
2163 }
2164
2165 Log("Write GPT Info OK ...");
2166 memcpy(&(pPhyDrive->MBR), &(pGptInfo->MBR), 512);
2167 }
2168 else
2169 {
2170 if (!WriteFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL))
2171 {
2172 rc = 1;
2173 Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize, GetLastError());
2174 goto End;
2175 }
2176 Log("Write MBR OK ...");
2177 memcpy(&(pPhyDrive->MBR), &MBR, 512);
2178 }
2179
2180 //Refresh Drive Layout
2181 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
2182
2183 End:
2184
2185 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
2186
2187 if (rc == 0)
2188 {
2189 Log("Mounting Ventoy Partition ....................... ");
2190 Sleep(1000);
2191
2192 state = 0;
2193 memset(DriveLetters, 0, sizeof(DriveLetters));
2194 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
2195 Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
2196
2197 for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
2198 {
2199 DriveName[0] = DriveLetters[i];
2200 if (IsVentoyLogicalDrive(DriveName[0]))
2201 {
2202 Log("%s is ventoy part2, delete mountpoint", DriveName);
2203 DeleteVolumeMountPointA(DriveName);
2204 }
2205 else
2206 {
2207 Log("%s is ventoy part1, already mounted", DriveName);
2208 MountDrive = DriveName[0];
2209 state = 1;
2210 }
2211 }
2212
2213 if (state != 1)
2214 {
2215 Log("need to mount ventoy part1...");
2216
2217 if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, Part1StartSector, DriveLetters, sizeof(DriveLetters), FALSE))
2218 {
2219 DriveName[0] = MountDrive;
2220 bRet = SetVolumeMountPointA(DriveName, DriveLetters);
2221 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
2222
2223 if (bRet)
2224 {
2225 state = 1;
2226 }
2227 }
2228 else
2229 {
2230 Log("Failed to find ventoy volume");
2231 }
2232 }
2233
2234 // close handle, or it will deny reformat
2235 Log("Close handle ...");
2236 CHECK_CLOSE_HANDLE(hDrive);
2237
2238 ReformatOK = TRUE;
2239
2240 if (state)
2241 {
2242 if (LargeFAT32)
2243 {
2244 Log("No need to reformat for large FAT32");
2245 pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);
2246 }
2247 else if (DefaultExFAT)
2248 {
2249 Log("No need to reformat for default exfat");
2250 pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);
2251 }
2252 else
2253 {
2254 bRet = DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512);
2255 for (i = 0; bRet == FALSE && i < 2; i++)
2256 {
2257 Log("Wait and retry reformat ...");
2258 Sleep(1000);
2259 bRet = DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512);
2260 }
2261
2262 if (bRet)
2263 {
2264 Log("Reformat %C:\\ to %s SUCCESS", MountDrive, GetVentoyFsName());
2265 pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);
2266
2267 if ((GetVentoyFsType() != VTOY_FS_UDF) && (pPhyDrive->VentoyFsClusterSize < 2048))
2268 {
2269 for (i = 0; i < 10; i++)
2270 {
2271 Log("### Invalid cluster size %d ###", pPhyDrive->VentoyFsClusterSize);
2272 }
2273 }
2274 }
2275 else
2276 {
2277 ReformatOK = FALSE;
2278 Log("Reformat %C:\\ to %s FAILED", MountDrive, GetVentoyFsName());
2279 }
2280 }
2281 }
2282 else
2283 {
2284 Log("Can not reformat %s to %s", DriveName, GetVentoyFsName());
2285 }
2286
2287 if (!ReformatOK)
2288 {
2289 Log("Format to exfat with built-in algorithm");
2290
2291 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2292 if (hDrive == INVALID_HANDLE_VALUE)
2293 {
2294 Log("Failed to GetPhysicalHandle for write.");
2295 }
2296 else
2297 {
2298 if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
2299 {
2300 Log("FormatPart1exFAT SUCCESS.");
2301 }
2302 else
2303 {
2304 Log("FormatPart1exFAT FAILED.");
2305 }
2306
2307 CHECK_CLOSE_HANDLE(hDrive);
2308 }
2309 }
2310
2311 Log("OK\n");
2312 }
2313 else
2314 {
2315 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
2316
2317 FindProcessOccupyDisk(hDrive, pPhyDrive);
2318
2319 if (!VDS_IsLastAvaliable())
2320 {
2321 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2322 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2323 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2324 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2325 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2326 }
2327
2328 CHECK_CLOSE_HANDLE(hDrive);
2329 }
2330
2331 if (pGptInfo)
2332 {
2333 free(pGptInfo);
2334 }
2335
2336 return rc;
2337 }
2338
2339
2340 int PartitionResizeForVentoy(PHY_DRIVE_INFO *pPhyDrive)
2341 {
2342 int i, j;
2343 int rc = 1;
2344 int PhyDrive;
2345 int PartStyle;
2346 UINT64 RecudeBytes;
2347 GUID Guid;
2348 MBR_HEAD MBR;
2349 VTOY_GPT_INFO *pGPT;
2350 MBR_HEAD *pMBR;
2351 DWORD dwSize = 0;
2352 VTOY_GPT_HDR BackupHead;
2353 HANDLE hDrive = INVALID_HANDLE_VALUE;
2354 GUID ZeroGuid = { 0 };
2355 static GUID WindowsDataPartType = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };
2356 static GUID EspPartType = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };
2357 static GUID BiosGrubPartType = { 0x21686148, 0x6449, 0x6e6f, { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } };
2358
2359 Log("#####################################################");
2360 Log("PartitionResizeForVentoy PhyDrive%d <<%s %s %dGB>>",
2361 pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
2362 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
2363 Log("#####################################################");
2364
2365 pGPT = &(pPhyDrive->Gpt);
2366 pMBR = &(pPhyDrive->Gpt.MBR);
2367 Log("Disksize:%llu Part2Start:%llu", pPhyDrive->SizeInBytes, pPhyDrive->ResizePart2StartSector * 512);
2368
2369 if (pMBR->PartTbl[0].FsFlag == 0xEE && memcmp(pGPT->Head.Signature, "EFI PART", 8) == 0)
2370 {
2371 PartStyle = 1;
2372 }
2373 else
2374 {
2375 PartStyle = 0;
2376 }
2377
2378 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
2379
2380 RecudeBytes = VENTOY_EFI_PART_SIZE;
2381
2382 if (pPhyDrive->ResizeNoShrink == FALSE)
2383 {
2384 Log("Need to shrink the volume");
2385 if (DISK_ShrinkVolume(pPhyDrive->PhyDrive, pPhyDrive->ResizeVolumeGuid, pPhyDrive->Part1DriveLetter, pPhyDrive->ResizeOldPart1Size, RecudeBytes))
2386 {
2387 Log("Shrink volume success, now check again");
2388
2389 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2390 if (hDrive == INVALID_HANDLE_VALUE)
2391 {
2392 Log("Failed to GetPhysicalHandle for update.");
2393 goto End;
2394 }
2395
2396 //Refresh Drive Layout
2397 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
2398
2399 CHECK_CLOSE_HANDLE(hDrive);
2400
2401
2402 if (PartResizePreCheck(NULL) && pPhyDrive->ResizeNoShrink)
2403 {
2404 Log("Recheck after Shrink volume success");
2405 Log("After shrink Disksize:%llu Part2Start:%llu", pPhyDrive->SizeInBytes, pPhyDrive->ResizePart2StartSector * 512);
2406 }
2407 else
2408 {
2409 Log("Recheck after Shrink volume failed %u", pPhyDrive->ResizeNoShrink);
2410 goto End;
2411 }
2412 }
2413 else
2414 {
2415 Log("Shrink volume failed");
2416 goto End;
2417 }
2418 }
2419
2420
2421 //Now try write data
2422 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2423 if (hDrive == INVALID_HANDLE_VALUE)
2424 {
2425 Log("Failed to GetPhysicalHandle for update.");
2426 goto End;
2427 }
2428
2429
2430 //Write partition 2 data
2431 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
2432 if (0 != FormatPart2Fat(hDrive, pPhyDrive->ResizePart2StartSector))
2433 {
2434 Log("FormatPart2Fat failed.");
2435 goto End;
2436 }
2437
2438 //Write grub stage2 gap
2439 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);
2440 Log("Writing Boot Image ............................. ");
2441 if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0)
2442 {
2443 Log("WriteGrubStage1ToPhyDrive failed.");
2444 goto End;
2445 }
2446
2447
2448 //Write partition table
2449 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);
2450 Log("Writing partition table ............................. ");
2451
2452 VentoyGetLocalBootImg(&MBR);
2453 CoCreateGuid(&Guid);
2454 memcpy(MBR.BootCode + 0x180, &Guid, 16);
2455 memcpy(pMBR->BootCode, MBR.BootCode, 440);
2456
2457 if (PartStyle == 0)
2458 {
2459 for (i = 1; i < 4; i++)
2460 {
2461 if (pMBR->PartTbl[i].SectorCount == 0)
2462 {
2463 break;
2464 }
2465 }
2466
2467 if (i >= 4)
2468 {
2469 Log("Can not find MBR free partition table");
2470 goto End;
2471 }
2472
2473 for (j = i - 1; j > 0; j--)
2474 {
2475 Log("Move MBR partition table %d --> %d", j + 1, j + 2);
2476 memcpy(pMBR->PartTbl + (j + 1), pMBR->PartTbl + j, sizeof(PART_TABLE));
2477 }
2478
2479 memset(pMBR->PartTbl + 1, 0, sizeof(PART_TABLE));
2480 VentoyFillMBRLocation(pPhyDrive->SizeInBytes, (UINT32)pPhyDrive->ResizePart2StartSector, VENTOY_EFI_PART_SIZE / 512, pMBR->PartTbl + 1);
2481 pMBR->PartTbl[0].Active = 0x80; // bootable
2482 pMBR->PartTbl[1].Active = 0x00;
2483 pMBR->PartTbl[1].FsFlag = 0xEF; // EFI System Partition
2484
2485 if (!WriteDataToPhyDisk(hDrive, 0, pMBR, 512))
2486 {
2487 Log("Legacy BIOS write MBR failed");
2488 goto End;
2489 }
2490 }
2491 else
2492 {
2493 for (i = 1; i < 128; i++)
2494 {
2495 if (memcmp(&(pGPT->PartTbl[i].PartGuid), &ZeroGuid, sizeof(GUID)) == 0)
2496 {
2497 break;
2498 }
2499 }
2500
2501 if (i >= 128)
2502 {
2503 Log("Can not find GPT free partition table");
2504 goto End;
2505 }
2506
2507 for (j = i - 1; j > 0; j--)
2508 {
2509 Log("Move GPT partition table %d --> %d", j + 1, j + 2);
2510 memcpy(pGPT->PartTbl + (j + 1), pGPT->PartTbl + j, sizeof(VTOY_GPT_PART_TBL));
2511 }
2512
2513
2514 pMBR->BootCode[92] = 0x22;
2515
2516 // to fix windows issue
2517 memset(pGPT->PartTbl + 1, 0, sizeof(VTOY_GPT_PART_TBL));
2518 memcpy(&(pGPT->PartTbl[1].PartType), &WindowsDataPartType, sizeof(GUID));
2519 CoCreateGuid(&(pGPT->PartTbl[1].PartGuid));
2520
2521 pGPT->PartTbl[1].StartLBA = pGPT->PartTbl[0].LastLBA + 1;
2522 pGPT->PartTbl[1].LastLBA = pGPT->PartTbl[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1;
2523 pGPT->PartTbl[1].Attr = 0xC000000000000001ULL;
2524 memcpy(pGPT->PartTbl[1].Name, L"VTOYEFI", 7 * 2);
2525
2526 //Update CRC
2527 pGPT->Head.PartTblCrc = VentoyCrc32(pGPT->PartTbl, sizeof(pGPT->PartTbl));
2528 pGPT->Head.Crc = 0;
2529 pGPT->Head.Crc = VentoyCrc32(&(pGPT->Head), pGPT->Head.Length);
2530
2531 Log("pGPT->Head.EfiStartLBA=%llu", (ULONGLONG)pGPT->Head.EfiStartLBA);
2532 Log("pGPT->Head.EfiBackupLBA=%llu", (ULONGLONG)pGPT->Head.EfiBackupLBA);
2533
2534 VentoyFillBackupGptHead(pGPT, &BackupHead);
2535 if (!WriteDataToPhyDisk(hDrive, pGPT->Head.EfiBackupLBA * 512, &BackupHead, 512))
2536 {
2537 Log("UEFI write backup head failed");
2538 goto End;
2539 }
2540
2541 if (!WriteDataToPhyDisk(hDrive, (pGPT->Head.EfiBackupLBA - 32) * 512, pGPT->PartTbl, 512 * 32))
2542 {
2543 Log("UEFI write backup partition table failed");
2544 goto End;
2545 }
2546
2547 if (!WriteDataToPhyDisk(hDrive, 0, pGPT, 512 * 34))
2548 {
2549 Log("UEFI write MBR & Main partition table failed");
2550 goto End;
2551 }
2552 }
2553
2554
2555
2556 //Refresh Drive Layout
2557 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
2558
2559 //We must close handle here, because it will block the refresh bellow
2560 CHECK_CLOSE_HANDLE(hDrive);
2561
2562 Sleep(2000);
2563
2564 if (g_CLI_Mode)
2565 {
2566 Log("### Ventoy non-destructive CLI installation successfully finished.");
2567 }
2568 else
2569 {
2570 //Refresh disk list
2571 PhyDrive = pPhyDrive->PhyDrive;
2572
2573 Log("#### Now Refresh PhyDrive ####");
2574 Ventoy2DiskDestroy();
2575 Ventoy2DiskInit();
2576
2577 pPhyDrive = GetPhyDriveInfoByPhyDrive(PhyDrive);
2578 if (pPhyDrive)
2579 {
2580 if (pPhyDrive->VentoyVersion[0] == 0)
2581 {
2582 Log("After process the Ventoy version is still invalid");
2583 goto End;
2584 }
2585
2586 Log("### Ventoy non-destructive installation successfully finished <%s>", pPhyDrive->VentoyVersion);
2587 }
2588 else
2589 {
2590 Log("### Ventoy non-destructive installation successfully finished <not found>");
2591 }
2592
2593 InitComboxCtrl(g_DialogHwnd, PhyDrive);
2594 }
2595
2596 rc = 0;
2597
2598 End:
2599 CHECK_CLOSE_HANDLE(hDrive);
2600 return rc;
2601 }
2602
2603
2604 static BOOL DiskCheckWriteAccess(HANDLE hDrive)
2605 {
2606 DWORD dwSize;
2607 BOOL ret = FALSE;
2608 BOOL bRet = FALSE;
2609 BYTE Buffer[512];
2610 LARGE_INTEGER liCurPosition;
2611 LARGE_INTEGER liNewPosition;
2612
2613 liCurPosition.QuadPart = 2039 * 512;
2614 liNewPosition.QuadPart = 0;
2615 if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||
2616 liNewPosition.QuadPart != liCurPosition.QuadPart)
2617 {
2618 Log("SetFilePointer1 Failed %u", LASTERR);
2619 goto out;
2620 }
2621
2622
2623 dwSize = 0;
2624 ret = ReadFile(hDrive, Buffer, 512, &dwSize, NULL);
2625 if ((!ret) || (dwSize != 512))
2626 {
2627 Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR);
2628 goto out;
2629 }
2630
2631
2632 liCurPosition.QuadPart = 2039 * 512;
2633 liNewPosition.QuadPart = 0;
2634 if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||
2635 liNewPosition.QuadPart != liCurPosition.QuadPart)
2636 {
2637 Log("SetFilePointer2 Failed %u", LASTERR);
2638 goto out;
2639 }
2640
2641 dwSize = 0;
2642 ret = WriteFile(hDrive, Buffer, 512, &dwSize, NULL);
2643 if ((!ret) || dwSize != 512)
2644 {
2645 Log("Failed to write %d %u %u", ret, dwSize, LASTERR);
2646 goto out;
2647 }
2648
2649 bRet = TRUE;
2650
2651 out:
2652
2653 return bRet;
2654 }
2655
2656 static BOOL BackupDataBeforeCleanDisk(int PhyDrive, UINT64 DiskSize, BYTE **pBackup)
2657 {
2658 DWORD dwSize;
2659 DWORD dwStatus;
2660 BOOL Return = FALSE;
2661 BOOL ret = FALSE;
2662 BYTE *backup = NULL;
2663 UINT64 offset;
2664 HANDLE hDrive = INVALID_HANDLE_VALUE;
2665 LARGE_INTEGER liCurPosition;
2666 LARGE_INTEGER liNewPosition;
2667 VTOY_GPT_INFO *pGPT = NULL;
2668
2669 Log("BackupDataBeforeCleanDisk %d", PhyDrive);
2670
2671 // step1: check write access
2672 hDrive = GetPhysicalHandle(PhyDrive, TRUE, TRUE, FALSE);
2673 if (hDrive == INVALID_HANDLE_VALUE)
2674 {
2675 Log("Failed to GetPhysicalHandle for write.");
2676 goto out;
2677 }
2678
2679 if (DiskCheckWriteAccess(hDrive))
2680 {
2681 Log("DiskCheckWriteAccess success");
2682 CHECK_CLOSE_HANDLE(hDrive);
2683 }
2684 else
2685 {
2686 Log("DiskCheckWriteAccess failed");
2687 goto out;
2688 }
2689
2690 //step2 backup 4MB data
2691 backup = malloc(SIZE_1MB * 4);
2692 if (!backup)
2693 {
2694 goto out;
2695 }
2696
2697 hDrive = GetPhysicalHandle(PhyDrive, FALSE, FALSE, FALSE);
2698 if (hDrive == INVALID_HANDLE_VALUE)
2699 {
2700 goto out;
2701 }
2702
2703 //read first 2MB
2704 dwStatus = SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2705 if (dwStatus != 0)
2706 {
2707 goto out;
2708 }
2709
2710 dwSize = 0;
2711 ret = ReadFile(hDrive, backup, SIZE_2MB, &dwSize, NULL);
2712 if ((!ret) || (dwSize != SIZE_2MB))
2713 {
2714 Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR);
2715 goto out;
2716 }
2717
2718 pGPT = (VTOY_GPT_INFO *)backup;
2719 offset = pGPT->Head.EfiBackupLBA * 512;
2720 if (offset >= (DiskSize - SIZE_2MB) && offset < DiskSize)
2721 {
2722 Log("EFI partition table check success");
2723 }
2724 else
2725 {
2726 Log("Backup EFI LBA not in last 2MB range: %llu", pGPT->Head.EfiBackupLBA);
2727 goto out;
2728 }
2729
2730 //read last 2MB
2731 liCurPosition.QuadPart = DiskSize - SIZE_2MB;
2732 liNewPosition.QuadPart = 0;
2733 if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||
2734 liNewPosition.QuadPart != liCurPosition.QuadPart)
2735 {
2736 goto out;
2737 }
2738
2739 dwSize = 0;
2740 ret = ReadFile(hDrive, backup + SIZE_2MB, SIZE_2MB, &dwSize, NULL);
2741 if ((!ret) || (dwSize != SIZE_2MB))
2742 {
2743 Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR);
2744 goto out;
2745 }
2746
2747 *pBackup = backup;
2748 backup = NULL; //For don't free later
2749 Return = TRUE;
2750
2751 out:
2752 CHECK_CLOSE_HANDLE(hDrive);
2753 if (backup)
2754 free(backup);
2755
2756 return Return;
2757 }
2758
2759
2760 static BOOL WriteBackupDataToDisk(HANDLE hDrive, UINT64 Offset, BYTE *Data, DWORD Length)
2761 {
2762 DWORD dwSize = 0;
2763 BOOL ret = FALSE;
2764 LARGE_INTEGER liCurPosition;
2765 LARGE_INTEGER liNewPosition;
2766
2767 Log("WriteBackupDataToDisk %llu %p %u", Offset, Data, Length);
2768
2769 liCurPosition.QuadPart = Offset;
2770 liNewPosition.QuadPart = 0;
2771 if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||
2772 liNewPosition.QuadPart != liCurPosition.QuadPart)
2773 {
2774 return FALSE;
2775 }
2776
2777 ret = WriteFile(hDrive, Data, Length, &dwSize, NULL);
2778 if ((!ret) || dwSize != Length)
2779 {
2780 Log("Failed to write %d %u %u", ret, dwSize, LASTERR);
2781 return FALSE;
2782 }
2783
2784 Log("WriteBackupDataToDisk %llu %p %u success", Offset, Data, Length);
2785 return TRUE;
2786 }
2787
2788
2789 int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
2790 {
2791 int i;
2792 int rc = 0;
2793 int MaxRetry = 4;
2794 BOOL ForceMBR = FALSE;
2795 BOOL Esp2Basic = FALSE;
2796 BOOL ChangeAttr = FALSE;
2797 BOOL CleanDisk = FALSE;
2798 BOOL DelEFI = FALSE;
2799 BOOL bWriteBack = TRUE;
2800 HANDLE hVolume;
2801 HANDLE hDrive;
2802 DWORD Status;
2803 DWORD dwSize;
2804 BOOL bRet;
2805 CHAR DriveName[] = "?:\\";
2806 CHAR DriveLetters[MAX_PATH] = { 0 };
2807 CHAR BackBinFile[MAX_PATH];
2808 UINT64 StartSector;
2809 UINT64 ReservedMB = 0;
2810 MBR_HEAD BootImg;
2811 MBR_HEAD MBR;
2812 BYTE *pBackup = NULL;
2813 VTOY_GPT_INFO *pGptInfo = NULL;
2814 VTOY_GPT_INFO *pGptBkup = NULL;
2815 UINT8 ReservedData[4096];
2816
2817 Log("#####################################################");
2818 Log("UpdateVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId,
2819 pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
2820 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
2821 Log("#####################################################");
2822
2823 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
2824
2825 Log("Lock disk for umount ............................ ");
2826
2827 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
2828 if (hDrive == INVALID_HANDLE_VALUE)
2829 {
2830 Log("Failed to open physical disk");
2831 return 1;
2832 }
2833
2834 if (pPhyDrive->PartStyle)
2835 {
2836 pGptInfo = malloc(2 * sizeof(VTOY_GPT_INFO));
2837 if (!pGptInfo)
2838 {
2839 return 1;
2840 }
2841
2842 memset(pGptInfo, 0, 2 * sizeof(VTOY_GPT_INFO));
2843 pGptBkup = pGptInfo + 1;
2844
2845 // Read GPT Info
2846 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2847 ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL);
2848 memcpy(pGptBkup, pGptInfo, sizeof(VTOY_GPT_INFO));
2849
2850 //MBR will be used to compare with local boot image
2851 memcpy(&MBR, &pGptInfo->MBR, sizeof(MBR_HEAD));
2852
2853 StartSector = pGptInfo->PartTbl[1].StartLBA;
2854 Log("GPT StartSector in PartTbl:%llu", (ULONGLONG)StartSector);
2855
2856 ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512) - 33) / 2048;
2857 Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);
2858 }
2859 else
2860 {
2861 // Read MBR
2862 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2863 ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
2864
2865 StartSector = MBR.PartTbl[1].StartSectorId;
2866 Log("MBR StartSector in PartTbl:%llu", (ULONGLONG)StartSector);
2867
2868 ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512)) / 2048;
2869 Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);
2870 }
2871
2872 //Read Reserved Data
2873 SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);
2874 ReadFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);
2875
2876 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
2877
2878 if (DriveLetters[0] == 0)
2879 {
2880 Log("No drive letter was assigned...");
2881 }
2882 else
2883 {
2884 // Unmount all mounted volumes that belong to this drive
2885 // Do it in reverse so that we always end on the first volume letter
2886 for (i = (int)strlen(DriveLetters); i > 0; i--)
2887 {
2888 DriveName[0] = DriveLetters[i - 1];
2889 if (IsVentoyLogicalDrive(DriveName[0]))
2890 {
2891 Log("%s is ventoy logical drive", DriveName);
2892 bRet = DeleteVolumeMountPointA(DriveName);
2893 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, LASTERR);
2894 break;
2895 }
2896 }
2897 }
2898
2899 // It kind of blows, but we have to relinquish access to the physical drive
2900 // for VDS to be able to delete the partitions that reside on it...
2901 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2902 CHECK_CLOSE_HANDLE(hDrive);
2903
2904 if (pPhyDrive->PartStyle == 1)
2905 {
2906 Log("TryId=%d EFI GPT partition type is 0x%llx", TryId, pPhyDrive->Part2GPTAttr);
2907 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
2908
2909 if (TryId == 1)
2910 {
2911 Log("Change GPT partition type to ESP");
2912 if (DISK_ChangeVtoyEFI2ESP(pPhyDrive->PhyDrive, StartSector * 512ULL))
2913 {
2914 Esp2Basic = TRUE;
2915 Sleep(3000);
2916 }
2917 }
2918 else if (TryId == 2)
2919 {
2920 Log("Change GPT partition attribute");
2921 if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, 0x8000000000000001))
2922 {
2923 ChangeAttr = TRUE;
2924 Sleep(2000);
2925 }
2926 }
2927 else if (TryId == 3)
2928 {
2929 DISK_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive, StartSector * 512ULL);
2930 DelEFI = TRUE;
2931 }
2932 else if (TryId == 4)
2933 {
2934 Log("Clean disk GPT partition table");
2935 if (BackupDataBeforeCleanDisk(pPhyDrive->PhyDrive, pPhyDrive->SizeInBytes, &pBackup))
2936 {
2937 sprintf_s(BackBinFile, sizeof(BackBinFile), ".\\ventoy\\phydrive%d_%u_%d.bin",
2938 pPhyDrive->PhyDrive, GetCurrentProcessId(), g_backup_bin_index++);
2939 SaveBufToFile(BackBinFile, pBackup, 4 * SIZE_1MB);
2940 Log("Save backup data to %s", BackBinFile);
2941
2942 Log("Success to backup data before clean");
2943 CleanDisk = TRUE;
2944 DISK_CleanDisk(pPhyDrive->PhyDrive);
2945 Sleep(3000);
2946 }
2947 else
2948 {
2949 Log("Failed to backup data before clean");
2950 }
2951 }
2952 }
2953
2954 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
2955
2956 Log("Lock disk for update ............................ ");
2957 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2958 if (hDrive == INVALID_HANDLE_VALUE)
2959 {
2960 Log("Failed to GetPhysicalHandle for write.");
2961 rc = 1;
2962 goto End;
2963 }
2964
2965 PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME);
2966
2967 Log("Lock volume for update .......................... ");
2968 hVolume = INVALID_HANDLE_VALUE;
2969
2970 //If we change VTOYEFI to ESP, it can not have s volume name, so don't try to get it.
2971 if (CleanDisk)
2972 {
2973 //writeback the last 2MB
2974 if (!WriteBackupDataToDisk(hDrive, pPhyDrive->SizeInBytes - SIZE_2MB, pBackup + SIZE_2MB, SIZE_2MB))
2975 {
2976 bWriteBack = FALSE;
2977 }
2978
2979 //write the first 2MB except parttable
2980 if (!WriteBackupDataToDisk(hDrive, 34 * 512, pBackup + 34 * 512, SIZE_2MB - 34 * 512))
2981 {
2982 bWriteBack = FALSE;
2983 }
2984
2985 Status = ERROR_NOT_FOUND;
2986 }
2987 else if (DelEFI)
2988 {
2989 Status = ERROR_NOT_FOUND;
2990 }
2991 else if (Esp2Basic)
2992 {
2993 Status = ERROR_NOT_FOUND;
2994 }
2995 else
2996 {
2997 for (i = 0; i < MaxRetry; i++)
2998 {
2999 Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, StartSector, DriveLetters, sizeof(DriveLetters), TRUE);
3000 if (ERROR_SUCCESS == Status)
3001 {
3002 break;
3003 }
3004 else
3005 {
3006 Log("==== Volume not found, wait and retry %d... ====", i);
3007 Sleep(2);
3008 }
3009 }
3010 }
3011
3012 if (ERROR_SUCCESS == Status)
3013 {
3014 Log("Now lock and dismount volume <%s>", DriveLetters);
3015
3016 for (i = 0; i < MaxRetry; i++)
3017 {
3018 hVolume = CreateFileA(DriveLetters,
3019 GENERIC_READ | GENERIC_WRITE,
3020 FILE_SHARE_READ,
3021 NULL,
3022 OPEN_EXISTING,
3023 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
3024 NULL);
3025
3026 if (hVolume == INVALID_HANDLE_VALUE)
3027 {
3028 Log("Failed to create file volume, errcode:%u, wait and retry ...", LASTERR);
3029 Sleep(2000);
3030 }
3031 else
3032 {
3033 break;
3034 }
3035 }
3036
3037 if (hVolume == INVALID_HANDLE_VALUE)
3038 {
3039 Log("Failed to create file volume, errcode:%u", LASTERR);
3040 }
3041 else
3042 {
3043 bRet = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
3044 Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
3045
3046 bRet = DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
3047 Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet, LASTERR);
3048 }
3049 }
3050 else if (ERROR_NOT_FOUND == Status)
3051 {
3052 Log("Volume not found, maybe not supported");
3053 }
3054 else
3055 {
3056 rc = 1;
3057 goto End;
3058 }
3059
3060 bRet = TryWritePart2(hDrive, StartSector);
3061 if (FALSE == bRet && Esp2Basic)
3062 {
3063 Log("TryWritePart2 agagin ...");
3064 Sleep(3000);
3065 bRet = TryWritePart2(hDrive, StartSector);
3066 }
3067
3068 if (!bRet)
3069 {
3070 if (pPhyDrive->PartStyle == 0)
3071 {
3072 if (DiskCheckWriteAccess(hDrive))
3073 {
3074 Log("MBR DiskCheckWriteAccess success");
3075
3076 ForceMBR = TRUE;
3077
3078 Log("Try write failed, now delete partition 2 for MBR...");
3079 CHECK_CLOSE_HANDLE(hDrive);
3080
3081 Log("Now delete partition 2...");
3082 DISK_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive, StartSector * 512ULL);
3083
3084 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
3085 if (hDrive == INVALID_HANDLE_VALUE)
3086 {
3087 Log("Failed to GetPhysicalHandle for write.");
3088 rc = 1;
3089 goto End;
3090 }
3091 }
3092 else
3093 {
3094 Log("MBR DiskCheckWriteAccess failed");
3095 }
3096 }
3097 else
3098 {
3099 Log("TryWritePart2 failed ....");
3100 rc = 1;
3101 goto End;
3102 }
3103 }
3104
3105 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
3106
3107 Log("Write Ventoy to disk ............................ ");
3108 if (0 != FormatPart2Fat(hDrive, StartSector))
3109 {
3110 rc = 1;
3111 goto End;
3112 }
3113
3114 if (hVolume != INVALID_HANDLE_VALUE)
3115 {
3116 bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
3117 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
3118 CHECK_CLOSE_HANDLE(hVolume);
3119 }
3120
3121 Log("Updating Boot Image ............................. ");
3122 if (WriteGrubStage1ToPhyDrive(hDrive, pPhyDrive->PartStyle) != 0)
3123 {
3124 rc = 1;
3125 goto End;
3126 }
3127
3128 //write reserved data
3129 SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);
3130 bRet = WriteFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);
3131 Log("Write resv data ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
3132
3133 // Boot Image
3134 VentoyGetLocalBootImg(&BootImg);
3135
3136 // Use Old UUID
3137 memcpy(BootImg.BootCode + 0x180, MBR.BootCode + 0x180, 16);
3138 if (pPhyDrive->PartStyle)
3139 {
3140 BootImg.BootCode[92] = 0x22;
3141 }
3142
3143 if (ForceMBR == FALSE && memcmp(BootImg.BootCode, MBR.BootCode, 440) == 0)
3144 {
3145 Log("Boot image has no difference, no need to write.");
3146 }
3147 else
3148 {
3149 Log("Boot image need to write %u.", ForceMBR);
3150
3151 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
3152
3153 memcpy(MBR.BootCode, BootImg.BootCode, 440);
3154 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
3155 Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
3156 }
3157
3158 if (pPhyDrive->PartStyle == 0)
3159 {
3160 if (0x00 == MBR.PartTbl[0].Active && 0x80 == MBR.PartTbl[1].Active)
3161 {
3162 Log("Need to chage 1st partition active and 2nd partition inactive.");
3163
3164 MBR.PartTbl[0].Active = 0x80;
3165 MBR.PartTbl[1].Active = 0x00;
3166
3167 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
3168 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
3169 Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
3170 }
3171 }
3172
3173 if (CleanDisk)
3174 {
3175 if (!WriteBackupDataToDisk(hDrive, 0, pBackup, 34 * 512))
3176 {
3177 bWriteBack = FALSE;
3178 }
3179
3180 free(pBackup);
3181
3182 if (bWriteBack)
3183 {
3184 Log("Write backup data success, now delete %s", BackBinFile);
3185 DeleteFileA(BackBinFile);
3186 }
3187 else
3188 {
3189 Log("Write backup data failed");
3190 }
3191
3192 Sleep(1000);
3193 }
3194 else if (DelEFI)
3195 {
3196 VTOY_GPT_HDR BackupHdr;
3197
3198 VentoyFillBackupGptHead(pGptBkup, &BackupHdr);
3199 if (!WriteBackupDataToDisk(hDrive, 512 * pGptBkup->Head.EfiBackupLBA, (BYTE*)(&BackupHdr), 512))
3200 {
3201 bWriteBack = FALSE;
3202 }
3203
3204 if (!WriteBackupDataToDisk(hDrive, 512 * (pGptBkup->Head.EfiBackupLBA - 32), (BYTE*)(pGptBkup->PartTbl), 32 * 512))
3205 {
3206 bWriteBack = FALSE;
3207 }
3208
3209 if (!WriteBackupDataToDisk(hDrive, 512, (BYTE*)pGptBkup + 512, 33 * 512))
3210 {
3211 bWriteBack = FALSE;
3212 }
3213
3214 if (bWriteBack)
3215 {
3216 Log("Write backup partition table success");
3217 }
3218 else
3219 {
3220 Log("Write backup partition table failed");
3221 }
3222
3223 Sleep(1000);
3224 }
3225
3226 //Refresh Drive Layout
3227 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
3228
3229 End:
3230
3231 if (hVolume != INVALID_HANDLE_VALUE)
3232 {
3233 bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
3234 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
3235 CHECK_CLOSE_HANDLE(hVolume);
3236 }
3237
3238 if (rc == 0)
3239 {
3240 Log("OK");
3241 }
3242 else
3243 {
3244 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
3245 FindProcessOccupyDisk(hDrive, pPhyDrive);
3246 }
3247
3248 CHECK_CLOSE_HANDLE(hDrive);
3249
3250 if (Esp2Basic)
3251 {
3252 Log("Recover GPT partition type to basic");
3253 DISK_ChangeVtoyEFI2Basic(pPhyDrive->PhyDrive, StartSector * 512);
3254 }
3255
3256 if (pPhyDrive->PartStyle == 1)
3257 {
3258 if (ChangeAttr || ((pPhyDrive->Part2GPTAttr >> 56) != 0xC0))
3259 {
3260 Log("Change EFI partition attr %u <0x%llx> to <0x%llx>", ChangeAttr, pPhyDrive->Part2GPTAttr, 0xC000000000000001ULL);
3261 if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, 0xC000000000000001ULL))
3262 {
3263 Log("Change EFI partition attr success");
3264 pPhyDrive->Part2GPTAttr = 0xC000000000000001ULL;
3265 }
3266 else
3267 {
3268 Log("Change EFI partition attr failed");
3269 }
3270 }
3271 }
3272
3273 if (pGptInfo)
3274 {
3275 free(pGptInfo);
3276 }
3277
3278 return rc;
3279 }
3280
3281