]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Ventoy2Disk/Ventoy2Disk/PhyDrive.c
1. Add new options for Windows CLI mode.
[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
548 static HANDLE g_FatPhyDrive;
549 static UINT64 g_Part2StartSec;
550 static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen)
551 {
552 int rc = 1;
553 int size = 0;
554 char *buf = NULL;
555 void *flfile = NULL;
556
557 flfile = fl_fopen("/grub/grub.cfg", "rb");
558 if (flfile)
559 {
560 fl_fseek(flfile, 0, SEEK_END);
561 size = (int)fl_ftell(flfile);
562
563 fl_fseek(flfile, 0, SEEK_SET);
564
565 buf = (char *)malloc(size + 1);
566 if (buf)
567 {
568 fl_fread(buf, 1, size, flfile);
569 buf[size] = 0;
570
571 rc = 0;
572 sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf));
573 free(buf);
574 }
575
576 fl_fclose(flfile);
577 }
578
579 return rc;
580 }
581
582 static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
583 {
584 DWORD dwSize;
585 BOOL bRet;
586 DWORD ReadSize;
587 LARGE_INTEGER liCurrentPosition;
588
589 liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
590 liCurrentPosition.QuadPart *= 512;
591 SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
592
593 ReadSize = (DWORD)(SectorCount * 512);
594
595 bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
596 if (bRet == FALSE || dwSize != ReadSize)
597 {
598 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, LASTERR);
599 }
600
601 return 1;
602 }
603
604
605 int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen, BOOL *pSecureBoot)
606 {
607 int rc = 0;
608 HANDLE hDrive;
609 void *flfile;
610
611 hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE);
612 if (hDrive == INVALID_HANDLE_VALUE)
613 {
614 return 1;
615 }
616
617 g_FatPhyDrive = hDrive;
618 g_Part2StartSec = Part2StartSector;
619
620 Log("Parse FAT fs...");
621
622 fl_init();
623
624 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
625 {
626 Log("attach media success...");
627 rc = GetVentoyVersionFromFatFile(VerBuf, BufLen);
628 }
629 else
630 {
631 Log("attach media failed...");
632 rc = 1;
633 }
634
635 Log("GetVentoyVerInPhyDrive rc=%d...", rc);
636 if (rc == 0)
637 {
638 Log("VentoyVerInPhyDrive %d is <%s>...", pDriveInfo->PhyDrive, VerBuf);
639
640 flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
641 if (flfile)
642 {
643 *pSecureBoot = TRUE;
644 fl_fclose(flfile);
645 }
646 }
647
648 fl_shutdown();
649
650 CHECK_CLOSE_HANDLE(hDrive);
651
652 return rc;
653 }
654
655
656
657
658
659 static unsigned int g_disk_unxz_len = 0;
660 static BYTE *g_part_img_pos = NULL;
661 static BYTE *g_part_img_buf[VENTOY_EFI_PART_SIZE / SIZE_1MB];
662
663
664 static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
665 {
666 uint32 i;
667 uint32 offset;
668 BYTE *MbBuf = NULL;
669
670 for (i = 0; i < SectorCount; i++)
671 {
672 offset = (Sector + i) * 512;
673
674 if (g_part_img_buf[1] == NULL)
675 {
676 MbBuf = g_part_img_buf[0] + offset;
677 memcpy(Buffer + i * 512, MbBuf, 512);
678 }
679 else
680 {
681 MbBuf = g_part_img_buf[offset / SIZE_1MB];
682 memcpy(Buffer + i * 512, MbBuf + (offset % SIZE_1MB), 512);
683 }
684 }
685
686 return 1;
687 }
688
689
690 static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
691 {
692 uint32 i;
693 uint32 offset;
694 BYTE *MbBuf = NULL;
695
696 for (i = 0; i < SectorCount; i++)
697 {
698 offset = (Sector + i) * 512;
699
700 if (g_part_img_buf[1] == NULL)
701 {
702 MbBuf = g_part_img_buf[0] + offset;
703 memcpy(MbBuf, Buffer + i * 512, 512);
704 }
705 else
706 {
707 MbBuf = g_part_img_buf[offset / SIZE_1MB];
708 memcpy(MbBuf + (offset % SIZE_1MB), Buffer + i * 512, 512);
709 }
710 }
711
712 return 1;
713 }
714
715 int VentoyProcSecureBoot(BOOL SecureBoot)
716 {
717 int rc = 0;
718 int size;
719 char *filebuf = NULL;
720 void *file = NULL;
721
722 Log("VentoyProcSecureBoot %d ...", SecureBoot);
723
724 if (SecureBoot)
725 {
726 Log("Secure boot is enabled ...");
727 return 0;
728 }
729
730 fl_init();
731
732 if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite))
733 {
734 file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
735 Log("Open ventoy efi file %p ", file);
736 if (file)
737 {
738 fl_fseek(file, 0, SEEK_END);
739 size = (int)fl_ftell(file);
740 fl_fseek(file, 0, SEEK_SET);
741
742 Log("ventoy efi file size %d ...", size);
743
744 filebuf = (char *)malloc(size);
745 if (filebuf)
746 {
747 fl_fread(filebuf, 1, size, file);
748 }
749
750 fl_fclose(file);
751
752 Log("Now delete all efi files ...");
753 fl_remove("/EFI/BOOT/BOOTX64.EFI");
754 fl_remove("/EFI/BOOT/grubx64.efi");
755 fl_remove("/EFI/BOOT/grubx64_real.efi");
756 fl_remove("/EFI/BOOT/MokManager.efi");
757 fl_remove("/EFI/BOOT/mmx64.efi");
758 fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
759 fl_remove("/EFI/BOOT/grub.efi");
760
761 file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
762 Log("Open bootx64 efi file %p ", file);
763 if (file)
764 {
765 if (filebuf)
766 {
767 fl_fwrite(filebuf, 1, size, file);
768 }
769
770 fl_fflush(file);
771 fl_fclose(file);
772 }
773
774 if (filebuf)
775 {
776 free(filebuf);
777 }
778 }
779
780 file = fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");
781 Log("Open ventoy efi file %p ", file);
782 if (file)
783 {
784 fl_fseek(file, 0, SEEK_END);
785 size = (int)fl_ftell(file);
786 fl_fseek(file, 0, SEEK_SET);
787
788 Log("ventoy efi file size %d ...", size);
789
790 filebuf = (char *)malloc(size);
791 if (filebuf)
792 {
793 fl_fread(filebuf, 1, size, file);
794 }
795
796 fl_fclose(file);
797
798 Log("Now delete all efi files ...");
799 fl_remove("/EFI/BOOT/BOOTIA32.EFI");
800 fl_remove("/EFI/BOOT/grubia32.efi");
801 fl_remove("/EFI/BOOT/grubia32_real.efi");
802 fl_remove("/EFI/BOOT/mmia32.efi");
803
804 file = fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");
805 Log("Open bootia32 efi file %p ", file);
806 if (file)
807 {
808 if (filebuf)
809 {
810 fl_fwrite(filebuf, 1, size, file);
811 }
812
813 fl_fflush(file);
814 fl_fclose(file);
815 }
816
817 if (filebuf)
818 {
819 free(filebuf);
820 }
821 }
822
823 }
824 else
825 {
826 rc = 1;
827 }
828
829 fl_shutdown();
830
831 return rc;
832 }
833
834
835
836 static int disk_xz_flush(void *src, unsigned int size)
837 {
838 unsigned int i;
839 BYTE *buf = (BYTE *)src;
840
841 for (i = 0; i < size; i++)
842 {
843 *g_part_img_pos = *buf++;
844
845 g_disk_unxz_len++;
846 if ((g_disk_unxz_len % SIZE_1MB) == 0)
847 {
848 g_part_img_pos = g_part_img_buf[g_disk_unxz_len / SIZE_1MB];
849 }
850 else
851 {
852 g_part_img_pos++;
853 }
854 }
855
856 return (int)size;
857 }
858
859 static void unxz_error(char *x)
860 {
861 Log("%s", x);
862 }
863
864 static BOOL TryWritePart2(HANDLE hDrive, UINT64 StartSectorId)
865 {
866 BOOL bRet;
867 DWORD TrySize = 16 * 1024;
868 DWORD dwSize;
869 BYTE *Buffer = NULL;
870 unsigned char *data = NULL;
871 LARGE_INTEGER liCurrentPosition;
872
873 liCurrentPosition.QuadPart = StartSectorId * 512;
874 SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
875
876 Buffer = malloc(TrySize);
877
878 bRet = WriteFile(hDrive, Buffer, TrySize, &dwSize, NULL);
879
880 free(Buffer);
881
882 Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
883
884 if (bRet && dwSize == TrySize)
885 {
886 return TRUE;
887 }
888
889 return FALSE;
890 }
891
892 static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId)
893 {
894 int i;
895 int rc = 0;
896 int len = 0;
897 int writelen = 0;
898 int partwrite = 0;
899 int Pos = PT_WRITE_VENTOY_START;
900 DWORD dwSize = 0;
901 BOOL bRet;
902 unsigned char *data = NULL;
903 LARGE_INTEGER liCurrentPosition;
904 LARGE_INTEGER liNewPosition;
905 BYTE *CheckBuf = NULL;
906
907 Log("FormatPart2Fat %llu...", (ULONGLONG)StartSectorId);
908
909 CheckBuf = malloc(SIZE_1MB);
910 if (!CheckBuf)
911 {
912 Log("Failed to malloc check buf");
913 return 1;
914 }
915
916 rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&data, &len);
917 if (rc)
918 {
919 Log("Failed to read img file %p %u", data, len);
920 free(CheckBuf);
921 return 1;
922 }
923
924 liCurrentPosition.QuadPart = StartSectorId * 512;
925 SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
926
927 memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
928
929 g_part_img_buf[0] = (BYTE *)malloc(VENTOY_EFI_PART_SIZE);
930 if (g_part_img_buf[0])
931 {
932 Log("Malloc whole img buffer success, now decompress ...");
933 unxz(data, len, NULL, NULL, g_part_img_buf[0], &writelen, unxz_error);
934
935 if (len == writelen)
936 {
937 Log("decompress finished success");
938
939 VentoyProcSecureBoot(g_SecureBoot);
940
941 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
942 {
943 dwSize = 0;
944 bRet = WriteFile(hDrive, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB, &dwSize, NULL);
945 Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
946
947 if (!bRet)
948 {
949 rc = 1;
950 goto End;
951 }
952
953 PROGRESS_BAR_SET_POS(Pos);
954 if (i % 2 == 0)
955 {
956 Pos++;
957 }
958 }
959
960 //Read and check the data
961 liCurrentPosition.QuadPart = StartSectorId * 512;
962 SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
963
964 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
965 {
966 bRet = ReadFile(hDrive, CheckBuf, SIZE_1MB, &dwSize, NULL);
967 Log("Read part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
968
969 if (!bRet || memcmp(CheckBuf, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB))
970 {
971 Log("### [Check Fail] The data write and read does not match");
972 rc = 1;
973 goto End;
974 }
975
976 PROGRESS_BAR_SET_POS(Pos);
977 if (i % 2 == 0)
978 {
979 Pos++;
980 }
981 }
982 }
983 else
984 {
985 rc = 1;
986 Log("decompress finished failed");
987 goto End;
988 }
989 }
990 else
991 {
992 Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE);
993
994 partwrite = 1;
995 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
996 {
997 g_part_img_buf[i] = (BYTE *)malloc(SIZE_1MB);
998 if (g_part_img_buf[i] == NULL)
999 {
1000 rc = 1;
1001 goto End;
1002 }
1003 }
1004
1005 Log("Malloc part img buffer success, now decompress ...");
1006
1007 g_part_img_pos = g_part_img_buf[0];
1008
1009 unxz(data, len, NULL, disk_xz_flush, NULL, NULL, unxz_error);
1010
1011 if (g_disk_unxz_len == VENTOY_EFI_PART_SIZE)
1012 {
1013 Log("decompress finished success");
1014
1015 VentoyProcSecureBoot(g_SecureBoot);
1016
1017 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1018 {
1019 dwSize = 0;
1020 bRet = WriteFile(hDrive, g_part_img_buf[i], SIZE_1MB, &dwSize, NULL);
1021 Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
1022
1023 if (!bRet)
1024 {
1025 rc = 1;
1026 goto End;
1027 }
1028
1029 PROGRESS_BAR_SET_POS(Pos);
1030 if (i % 2 == 0)
1031 {
1032 Pos++;
1033 }
1034 }
1035
1036 //Read and check the data
1037 liCurrentPosition.QuadPart = StartSectorId * 512;
1038 SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
1039
1040 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1041 {
1042 bRet = ReadFile(hDrive, CheckBuf, SIZE_1MB, &dwSize, NULL);
1043 Log("Read part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
1044
1045 if (!bRet || memcmp(CheckBuf, g_part_img_buf[i], SIZE_1MB))
1046 {
1047 Log("### [Check Fail] The data write and read does not match");
1048 rc = 1;
1049 goto End;
1050 }
1051
1052 PROGRESS_BAR_SET_POS(Pos);
1053 if (i % 2 == 0)
1054 {
1055 Pos++;
1056 }
1057 }
1058 }
1059 else
1060 {
1061 rc = 1;
1062 Log("decompress finished failed");
1063 goto End;
1064 }
1065 }
1066
1067 End:
1068
1069 if (data) free(data);
1070 if (CheckBuf)free(CheckBuf);
1071
1072 if (partwrite)
1073 {
1074 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1075 {
1076 if (g_part_img_buf[i]) free(g_part_img_buf[i]);
1077 }
1078 }
1079 else
1080 {
1081 if (g_part_img_buf[0]) free(g_part_img_buf[0]);
1082 }
1083
1084 return rc;
1085 }
1086
1087 static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle)
1088 {
1089 int Len = 0;
1090 int readLen = 0;
1091 BOOL bRet;
1092 DWORD dwSize;
1093 BYTE *ImgBuf = NULL;
1094 BYTE *RawBuf = NULL;
1095
1096 Log("WriteGrubStage1ToPhyDrive ...");
1097
1098 RawBuf = (BYTE *)malloc(SIZE_1MB);
1099 if (!RawBuf)
1100 {
1101 return 1;
1102 }
1103
1104 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
1105 {
1106 Log("Failed to read stage1 img");
1107 free(RawBuf);
1108 return 1;
1109 }
1110
1111 unxz(ImgBuf, Len, NULL, NULL, RawBuf, &readLen, unxz_error);
1112
1113 if (PartStyle)
1114 {
1115 Log("Write GPT stage1 ...");
1116 RawBuf[500] = 35;//update blocklist
1117 SetFilePointer(hDrive, 512 * 34, NULL, FILE_BEGIN);
1118 bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512 * 34, &dwSize, NULL);
1119 }
1120 else
1121 {
1122 Log("Write MBR stage1 ...");
1123 SetFilePointer(hDrive, 512, NULL, FILE_BEGIN);
1124 bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512, &dwSize, NULL);
1125 }
1126
1127 Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet, dwSize, GetLastError());
1128
1129 free(RawBuf);
1130 free(ImgBuf);
1131 return 0;
1132 }
1133
1134
1135 static int FormatPart1LargeFAT32(UINT64 DiskSizeBytes, int CluserSize)
1136 {
1137 MKFS_PARM Option;
1138 FRESULT Ret;
1139 FATFS FS;
1140
1141 Option.fmt = FM_FAT32;
1142 Option.n_fat = 1;
1143 Option.align = 8;
1144 Option.n_root = 1;
1145
1146 if (CluserSize == 0)
1147 {
1148 // < 32GB select 32KB as cluster size
1149 // > 32GB select 128KB as cluster size
1150 if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32)
1151 {
1152 Option.au_size = 32768;
1153 }
1154 else
1155 {
1156 Option.au_size = 131072;
1157 }
1158 }
1159 else
1160 {
1161 Option.au_size = CluserSize;
1162 }
1163
1164 Log("Formatting Part1 large FAT32 ClusterSize:%u(%uKB) ...", CluserSize, CluserSize / 1024);
1165
1166 disk_io_reset_write_error();
1167
1168 Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
1169 if (FR_OK == Ret)
1170 {
1171 if (disk_io_is_write_error())
1172 {
1173 Log("Formatting Part1 large FAT32 failed, write error.");
1174 return 1;
1175 }
1176
1177 Log("Formatting Part1 large FAT32 success, now set label");
1178
1179 Ret = f_mount(&FS, TEXT("0:"), 1);
1180 if (FR_OK == Ret)
1181 {
1182 Log("f_mount SUCCESS");
1183 Ret = f_setlabel(TEXT("0:Ventoy"));
1184 if (FR_OK == Ret)
1185 {
1186 Log("f_setlabel SUCCESS");
1187 Ret = f_unmount(TEXT("0:"));
1188 Log("f_unmount %d %s", Ret, (FR_OK == Ret) ? "SUCCESS" : "FAILED");
1189 }
1190 else
1191 {
1192 Log("f_setlabel failed %d", Ret);
1193 }
1194 }
1195 else
1196 {
1197 Log("f_mount failed %d", Ret);
1198 }
1199
1200 return 0;
1201 }
1202 else
1203 {
1204 Log("Formatting Part1 large FAT32 failed");
1205 return 1;
1206 }
1207 }
1208
1209 static int FormatPart1exFAT(UINT64 DiskSizeBytes)
1210 {
1211 MKFS_PARM Option;
1212 FRESULT Ret;
1213
1214 Option.fmt = FM_EXFAT;
1215 Option.n_fat = 1;
1216 Option.align = 8;
1217 Option.n_root = 1;
1218
1219 // < 32GB select 32KB as cluster size
1220 // > 32GB select 128KB as cluster size
1221 if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32)
1222 {
1223 Option.au_size = 32768;
1224 }
1225 else
1226 {
1227 Option.au_size = 131072;
1228 }
1229
1230 Log("Formatting Part1 exFAT ...");
1231
1232 disk_io_reset_write_error();
1233
1234 Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
1235 if (FR_OK == Ret)
1236 {
1237 if (disk_io_is_write_error())
1238 {
1239 Log("Formatting Part1 exFAT failed, write error.");
1240 return 1;
1241 }
1242
1243 Log("Formatting Part1 exFAT success");
1244 return 0;
1245 }
1246 else
1247 {
1248 Log("Formatting Part1 exFAT failed");
1249 return 1;
1250 }
1251 }
1252
1253 static int ZeroPart1FileSystem(HANDLE hDrive, UINT64 Part2StartSector)
1254 {
1255 int i;
1256 DWORD dwSize = 0;
1257 LARGE_INTEGER liCurPos;
1258 LARGE_INTEGER liNewPos;
1259 CHAR TmpBuffer[1024] = { 0 };
1260
1261 liCurPos.QuadPart = VENTOY_PART1_START_SECTOR * 512;
1262 liNewPos.QuadPart = 0;
1263 if (0 == SetFilePointerEx(hDrive, liCurPos, &liNewPos, FILE_BEGIN) ||
1264 liNewPos.QuadPart != liCurPos.QuadPart)
1265 {
1266 Log("SetFilePointerEx Failed %u %llu %llu", LASTERR, (ULONGLONG)liCurPos.QuadPart, (ULONGLONG)liNewPos.QuadPart);
1267 return 1;
1268 }
1269
1270 for (i = 0; i < 1024; i++)
1271 {
1272 WriteFile(hDrive, TmpBuffer, 1024, &dwSize, NULL);
1273 }
1274
1275 liCurPos.QuadPart = (Part2StartSector * 512) - (1024 * 1024);
1276 liNewPos.QuadPart = 0;
1277 if (0 == SetFilePointerEx(hDrive, liCurPos, &liNewPos, FILE_BEGIN) ||
1278 liNewPos.QuadPart != liCurPos.QuadPart)
1279 {
1280 Log("SetFilePointerEx Failed %u %llu %llu", LASTERR, (ULONGLONG)liCurPos.QuadPart, (ULONGLONG)liNewPos.QuadPart);
1281 return 1;
1282 }
1283
1284 for (i = 0; i < 1024; i++)
1285 {
1286 WriteFile(hDrive, TmpBuffer, 1024, &dwSize, NULL);
1287 }
1288
1289 Log("Zero Part1 SUCCESS");
1290 return 0;
1291 }
1292
1293 int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter)
1294 {
1295 int i;
1296 int rc = 0;
1297 int state = 0;
1298 HANDLE hDrive;
1299 DWORD dwSize;
1300 BOOL bRet;
1301 CHAR MountDrive;
1302 CHAR DriveName[] = "?:\\";
1303 CHAR DriveLetters[MAX_PATH] = { 0 };
1304 LARGE_INTEGER liCurrentPosition;
1305 char *pTmpBuf = NULL;
1306 MBR_HEAD MBR;
1307
1308 *pDrvLetter = 0;
1309
1310 Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
1311 pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1312 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1313
1314 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1315
1316 Log("Lock disk for clean ............................. ");
1317
1318 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
1319 if (hDrive == INVALID_HANDLE_VALUE)
1320 {
1321 Log("Failed to open physical disk");
1322 return 1;
1323 }
1324
1325 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1326
1327 if (DriveLetters[0] == 0)
1328 {
1329 Log("No drive letter was assigned...");
1330 DriveName[0] = GetFirstUnusedDriveLetter();
1331 Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
1332 }
1333 else
1334 {
1335 // Unmount all mounted volumes that belong to this drive
1336 // Do it in reverse so that we always end on the first volume letter
1337 for (i = (int)strlen(DriveLetters); i > 0; i--)
1338 {
1339 DriveName[0] = DriveLetters[i - 1];
1340 bRet = DeleteVolumeMountPointA(DriveName);
1341 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
1342 }
1343 }
1344
1345 MountDrive = DriveName[0];
1346 Log("Will use '%C:' as volume mountpoint", DriveName[0]);
1347
1348 // It kind of blows, but we have to relinquish access to the physical drive
1349 // for VDS to be able to delete the partitions that reside on it...
1350 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
1351 CHECK_CLOSE_HANDLE(hDrive);
1352
1353 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
1354
1355 if (!VDS_DeleteAllPartitions(pPhyDrive->PhyDrive))
1356 {
1357 Log("Notice: Could not delete partitions: %u", GetLastError());
1358 }
1359
1360 Log("Deleting all partitions ......................... OK");
1361
1362 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
1363
1364 Log("Lock disk for write ............................. ");
1365 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
1366 if (hDrive == INVALID_HANDLE_VALUE)
1367 {
1368 Log("Failed to GetPhysicalHandle for write.");
1369 rc = 1;
1370 goto End;
1371 }
1372
1373 // clear first and last 2MB space
1374 pTmpBuf = malloc(SIZE_2MB);
1375 if (!pTmpBuf)
1376 {
1377 Log("Failed to alloc memory.");
1378 rc = 1;
1379 goto End;
1380 }
1381 memset(pTmpBuf, 0, SIZE_2MB);
1382
1383 SET_FILE_POS(512);
1384 bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB - 512, &dwSize, NULL);
1385 Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1386 if (!bRet)
1387 {
1388 rc = 1;
1389 goto End;
1390 }
1391
1392 SET_FILE_POS(pPhyDrive->SizeInBytes - SIZE_2MB);
1393 bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB, &dwSize, NULL);
1394 Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1395 if (!bRet)
1396 {
1397 rc = 1;
1398 goto End;
1399 }
1400
1401 SET_FILE_POS(0);
1402
1403 if (pPhyDrive->SizeInBytes > 2199023255552ULL)
1404 {
1405 VTOY_GPT_INFO *pGptInfo;
1406 VTOY_GPT_HDR BackupHead;
1407 LARGE_INTEGER liCurrentPosition;
1408
1409 pGptInfo = (VTOY_GPT_INFO *)pTmpBuf;
1410
1411 VentoyFillWholeGpt(pPhyDrive->SizeInBytes, pGptInfo);
1412
1413 SET_FILE_POS(pPhyDrive->SizeInBytes - 512);
1414 VentoyFillBackupGptHead(pGptInfo, &BackupHead);
1415 if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))
1416 {
1417 rc = 1;
1418 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1419 goto End;
1420 }
1421
1422 SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);
1423 if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))
1424 {
1425 rc = 1;
1426 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1427 goto End;
1428 }
1429
1430 SET_FILE_POS(0);
1431 if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))
1432 {
1433 rc = 1;
1434 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1435 goto End;
1436 }
1437
1438 Log("Write GPT Info OK ...");
1439 }
1440 else
1441 {
1442 bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
1443 Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1444 if (!bRet)
1445 {
1446 rc = 1;
1447 goto End;
1448 }
1449
1450 //clear boot code and partition table (reserved disk signature)
1451 memset(MBR.BootCode, 0, 440);
1452 memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl));
1453
1454 VentoyFillMBRLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl);
1455
1456 MBR.PartTbl[0].Active = 0x00; // bootable
1457 MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS
1458
1459 SET_FILE_POS(0);
1460 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
1461 Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1462 if (!bRet)
1463 {
1464 rc = 1;
1465 goto End;
1466 }
1467 }
1468
1469 Log("Clear Ventoy successfully finished");
1470
1471 //Refresh Drive Layout
1472 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
1473
1474 End:
1475
1476 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1477 PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH);
1478
1479 if (pTmpBuf)
1480 {
1481 free(pTmpBuf);
1482 }
1483
1484 if (rc == 0)
1485 {
1486 Log("Mounting Ventoy Partition ....................... ");
1487 Sleep(1000);
1488
1489 state = 0;
1490 memset(DriveLetters, 0, sizeof(DriveLetters));
1491 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1492 Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
1493
1494 for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
1495 {
1496 DriveName[0] = DriveLetters[i];
1497 Log("%s is ventoy part1, already mounted", DriveName);
1498 state = 1;
1499 }
1500
1501 if (state != 1)
1502 {
1503 Log("need to mount ventoy part1...");
1504 if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, 2048, DriveLetters, sizeof(DriveLetters), FALSE))
1505 {
1506 DriveName[0] = MountDrive;
1507 bRet = SetVolumeMountPointA(DriveName, DriveLetters);
1508 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
1509
1510 *pDrvLetter = MountDrive;
1511 }
1512 else
1513 {
1514 Log("Failed to find ventoy volume");
1515 }
1516 }
1517
1518 Log("OK\n");
1519 }
1520 else
1521 {
1522 FindProcessOccupyDisk(hDrive, pPhyDrive);
1523 }
1524
1525 CHECK_CLOSE_HANDLE(hDrive);
1526 return rc;
1527 }
1528
1529 int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
1530 {
1531 int i;
1532 int rc = 1;
1533 int Len = 0;
1534 int dataLen = 0;
1535 UINT size = 0;
1536 UINT segnum = 0;
1537 UINT32 chksum = 0;
1538 UINT64 data_offset = 0;
1539 UINT64 Part2StartSector = 0;
1540 UINT64 Part1StartSector = 0;
1541 UINT64 Part1SectorCount = 0;
1542 UINT8 *pData = NULL;
1543 UINT8 *pBkGptPartTbl = NULL;
1544 BYTE *ImgBuf = NULL;
1545 MBR_HEAD *pMBR = NULL;
1546 VTSI_FOOTER *pImgFooter = NULL;
1547 VTSI_SEGMENT *pSegment = NULL;
1548 VTOY_GPT_INFO *pGptInfo = NULL;
1549 VTOY_GPT_HDR *pBkGptHdr = NULL;
1550 FILE *fp = NULL;
1551
1552 Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",
1553 PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1554 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1555
1556 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1557
1558 size = SIZE_1MB + VENTOY_EFI_PART_SIZE + 33 * 512 + VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT) + sizeof(VTSI_FOOTER);
1559
1560 pData = (UINT8 *)malloc(size);
1561 if (!pData)
1562 {
1563 Log("malloc image buffer failed %d.", size);
1564 goto End;
1565 }
1566
1567 pImgFooter = (VTSI_FOOTER *)(pData + size - sizeof(VTSI_FOOTER));
1568 pSegment = (VTSI_SEGMENT *)((UINT8 *)pImgFooter - VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));
1569 memset(pImgFooter, 0, sizeof(VTSI_FOOTER));
1570 memset(pSegment, 0, VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));
1571
1572 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START);
1573
1574 Log("Writing Boot Image ............................. ");
1575 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
1576 {
1577 Log("Failed to read stage1 img");
1578 goto End;
1579 }
1580
1581 unxz(ImgBuf, Len, NULL, NULL, pData, &dataLen, unxz_error);
1582 SAFE_FREE(ImgBuf);
1583
1584 Log("decompress %s len:%d", VENTOY_FILE_STG1_IMG, dataLen);
1585
1586 if (PartStyle)
1587 {
1588 pData[500] = 35;//update blocklist
1589 memmove(pData + 34 * 512, pData, SIZE_1MB - 512 * 34);
1590 memset(pData, 0, 34 * 512);
1591
1592 pGptInfo = (VTOY_GPT_INFO *)pData;
1593 memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
1594 VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);
1595
1596 pBkGptPartTbl = pData + SIZE_1MB + VENTOY_EFI_PART_SIZE;
1597 memset(pBkGptPartTbl, 0, 33 * 512);
1598
1599 memcpy(pBkGptPartTbl, pGptInfo->PartTbl, 32 * 512);
1600 pBkGptHdr = (VTOY_GPT_HDR *)(pBkGptPartTbl + 32 * 512);
1601 VentoyFillBackupGptHead(pGptInfo, pBkGptHdr);
1602
1603 Part1StartSector = pGptInfo->PartTbl[0].StartLBA;
1604 Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;
1605 Part2StartSector = pGptInfo->PartTbl[1].StartLBA;
1606
1607 Log("Write GPT Info OK ...");
1608 }
1609 else
1610 {
1611 memmove(pData + 512, pData, SIZE_1MB - 512);
1612 memset(pData, 0, 512);
1613
1614 pMBR = (MBR_HEAD *)pData;
1615 VentoyFillMBR(pPhyDrive->SizeInBytes, pMBR, PartStyle, 0x07);
1616 Part1StartSector = pMBR->PartTbl[0].StartSectorId;
1617 Part1SectorCount = pMBR->PartTbl[0].SectorCount;
1618 Part2StartSector = pMBR->PartTbl[1].StartSectorId;
1619
1620 Log("Write MBR OK ...");
1621 }
1622
1623 Log("Writing EFI part Image ............................. ");
1624 rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&ImgBuf, &Len);
1625 if (rc)
1626 {
1627 Log("Failed to read img file %p %u", ImgBuf, Len);
1628 goto End;
1629 }
1630
1631 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + 28);
1632 memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
1633 unxz(ImgBuf, Len, NULL, NULL, pData + SIZE_1MB, &dataLen, unxz_error);
1634 if (dataLen == Len)
1635 {
1636 Log("decompress finished success");
1637 g_part_img_buf[0] = pData + SIZE_1MB;
1638
1639 VentoyProcSecureBoot(g_SecureBoot);
1640 }
1641 else
1642 {
1643 Log("decompress finished failed");
1644 goto End;
1645 }
1646
1647 fopen_s(&fp, "VentoySparseImg.vtsi", "wb+");
1648 if (!fp)
1649 {
1650 Log("Failed to create Ventoy img file");
1651 goto End;
1652 }
1653
1654 Log("Writing stage1 data ............................. ");
1655
1656 fwrite(pData, 1, SIZE_1MB, fp);
1657
1658 pSegment[0].disk_start_sector = 0;
1659 pSegment[0].sector_num = SIZE_1MB / 512;
1660 pSegment[0].data_offset = data_offset;
1661 data_offset += pSegment[0].sector_num * 512;
1662
1663 disk_io_set_param(INVALID_HANDLE_VALUE, Part1StartSector + Part1SectorCount);// include the 2048 sector gap
1664 disk_io_set_imghook(fp, pSegment + 1, VTSI_IMG_MAX_SEG - 1, data_offset);
1665
1666 Log("Formatting part1 exFAT ...");
1667 if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
1668 {
1669 Log("FormatPart1exFAT failed.");
1670 disk_io_reset_imghook(&segnum, &data_offset);
1671 goto End;
1672 }
1673
1674 disk_io_reset_imghook(&segnum, &data_offset);
1675 segnum++;
1676
1677 Log("current segment number:%d dataoff:%ld", segnum, (long)data_offset);
1678
1679 //write data
1680 Log("Writing part2 data ............................. ");
1681 fwrite(pData + SIZE_1MB, 1, VENTOY_EFI_PART_SIZE, fp);
1682 pSegment[segnum].disk_start_sector = Part2StartSector;
1683 pSegment[segnum].sector_num = VENTOY_EFI_PART_SIZE / 512;
1684 pSegment[segnum].data_offset = data_offset;
1685 data_offset += pSegment[segnum].sector_num * 512;
1686 segnum++;
1687
1688 if (PartStyle)
1689 {
1690 Log("Writing backup gpt table ............................. ");
1691 fwrite(pBkGptPartTbl, 1, 33 * 512, fp);
1692 pSegment[segnum].disk_start_sector = pPhyDrive->SizeInBytes / 512 - 33;
1693 pSegment[segnum].sector_num = 33;
1694 pSegment[segnum].data_offset = data_offset;
1695 data_offset += pSegment[segnum].sector_num * 512;
1696 segnum++;
1697 }
1698
1699 Log("Writing segment metadata ............................. ");
1700
1701 for (i = 0; i < (int)segnum; i++)
1702 {
1703 Log("SEG[%d]: PhySector:%llu SectorNum:%llu DataOffset:%llu(sector:%llu)", i, pSegment[i].disk_start_sector, pSegment[i].sector_num,
1704 pSegment[i].data_offset, pSegment[i].data_offset / 512);
1705 }
1706
1707 dataLen = segnum * sizeof(VTSI_SEGMENT);
1708 fwrite(pSegment, 1, dataLen, fp);
1709
1710 if (dataLen % 512)
1711 {
1712 //pData + SIZE_1MB - 8192 is a temp data buffer with zero
1713 fwrite(pData + SIZE_1MB - 8192, 1, 512 - (dataLen % 512), fp);
1714 }
1715
1716 //Fill footer
1717 pImgFooter->magic = VTSI_IMG_MAGIC;
1718 pImgFooter->version = 1;
1719 pImgFooter->disk_size = pPhyDrive->SizeInBytes;
1720 memcpy(&pImgFooter->disk_signature, pPhyDrive->MBR.BootCode + 0x1b8, 4);
1721 pImgFooter->segment_num = segnum;
1722 pImgFooter->segment_offset = data_offset;
1723
1724 for (i = 0, chksum = 0; i < (int)(segnum * sizeof(VTSI_SEGMENT)); i++)
1725 {
1726 chksum += *((UINT8 *)pSegment + i);
1727 }
1728 pImgFooter->segment_chksum = ~chksum;
1729
1730 for (i = 0, chksum = 0; i < sizeof(VTSI_FOOTER); i++)
1731 {
1732 chksum += *((UINT8 *)pImgFooter + i);
1733 }
1734 pImgFooter->foot_chksum = ~chksum;
1735
1736 Log("Writing footer segnum(%u) segoffset(%llu) ......................", segnum, data_offset);
1737 Log("disk_size=%llu disk_signature=%lx segment_offset=%llu", pImgFooter->disk_size, pImgFooter->disk_signature, pImgFooter->segment_offset);
1738
1739 fwrite(pImgFooter, 1, sizeof(VTSI_FOOTER), fp);
1740 fclose(fp);
1741
1742 Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset + 512 + ((dataLen + 511) / 512 * 512));
1743
1744 rc = 0;
1745
1746 End:
1747
1748 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1749 PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH);
1750
1751 Log("retcode:%d\n", rc);
1752
1753 SAFE_FREE(pData);
1754 SAFE_FREE(ImgBuf);
1755
1756 return rc;
1757 }
1758
1759
1760 int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)
1761 {
1762 int i;
1763 int rc = 0;
1764 int state = 0;
1765 BOOL ReformatOK;
1766 HANDLE hDrive;
1767 DWORD dwSize;
1768 BOOL bRet;
1769 CHAR MountDrive;
1770 CHAR DriveName[] = "?:\\";
1771 CHAR DriveLetters[MAX_PATH] = { 0 };
1772 MBR_HEAD MBR;
1773 VTOY_GPT_INFO *pGptInfo = NULL;
1774 UINT64 Part1StartSector = 0;
1775 UINT64 Part1SectorCount = 0;
1776 UINT64 Part2StartSector = 0;
1777 BOOL LargeFAT32 = FALSE;
1778 BOOL DefaultExFAT = FALSE;
1779 UINT8 FsFlag = 0x07;
1780
1781 Log("#####################################################");
1782 Log("InstallVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId,
1783 PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1784 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1785 Log("#####################################################");
1786
1787 if (PartStyle)
1788 {
1789 pGptInfo = malloc(sizeof(VTOY_GPT_INFO));
1790 memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
1791 }
1792
1793 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1794
1795 if (PartStyle)
1796 {
1797 VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);
1798 Part1StartSector = pGptInfo->PartTbl[0].StartLBA;
1799 Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;
1800 Part2StartSector = pGptInfo->PartTbl[1].StartLBA;
1801 }
1802 else
1803 {
1804 if (GetVentoyFsType() == VTOY_FS_FAT32)
1805 {
1806 FsFlag = 0x0C;
1807 }
1808
1809 VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle, FsFlag);
1810 Part1StartSector = MBR.PartTbl[0].StartSectorId;
1811 Part1SectorCount = MBR.PartTbl[0].SectorCount;
1812 Part2StartSector = MBR.PartTbl[1].StartSectorId;
1813 }
1814
1815 Log("Lock disk for clean ............................. ");
1816
1817 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
1818 if (hDrive == INVALID_HANDLE_VALUE)
1819 {
1820 Log("Failed to open physical disk");
1821 free(pGptInfo);
1822 return 1;
1823 }
1824
1825 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1826
1827 if (DriveLetters[0] == 0)
1828 {
1829 Log("No drive letter was assigned...");
1830 DriveName[0] = GetFirstUnusedDriveLetter();
1831 Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
1832 }
1833 else
1834 {
1835 // Unmount all mounted volumes that belong to this drive
1836 // Do it in reverse so that we always end on the first volume letter
1837 for (i = (int)strlen(DriveLetters); i > 0; i--)
1838 {
1839 DriveName[0] = DriveLetters[i - 1];
1840 bRet = DeleteVolumeMountPointA(DriveName);
1841 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
1842 }
1843 }
1844
1845 MountDrive = DriveName[0];
1846 Log("Will use '%C:' as volume mountpoint", DriveName[0]);
1847
1848 // It kind of blows, but we have to relinquish access to the physical drive
1849 // for VDS to be able to delete the partitions that reside on it...
1850 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
1851 CHECK_CLOSE_HANDLE(hDrive);
1852
1853 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
1854
1855 if (!VDS_DeleteAllPartitions(pPhyDrive->PhyDrive))
1856 {
1857 Log("Notice: Could not delete partitions: 0x%x, but we continue.", GetLastError());
1858 }
1859
1860 Log("Deleting all partitions ......................... OK");
1861
1862 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
1863
1864 Log("Lock disk for write ............................. ");
1865 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
1866 if (hDrive == INVALID_HANDLE_VALUE)
1867 {
1868 Log("Failed to GetPhysicalHandle for write.");
1869 rc = 1;
1870 goto End;
1871 }
1872
1873 //Refresh Drive Layout
1874 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
1875
1876 disk_io_set_param(hDrive, Part1StartSector + Part1SectorCount);// include the 2048 sector gap
1877
1878 PROGRESS_BAR_SET_POS(PT_FORMAT_PART1);
1879
1880 if (PartStyle == 1 && pPhyDrive->PartStyle == 0)
1881 {
1882 Log("Wait for format part1 ...");
1883 Sleep(1000 * 5);
1884 }
1885
1886 if (GetVentoyFsType() == VTOY_FS_FAT32 && (Part1SectorCount * 512 >= FAT32_MAX_LIMIT))
1887 {
1888 Log("Formatting part1 large FAT32 ...");
1889 LargeFAT32 = TRUE;
1890 if (0 != FormatPart1LargeFAT32(pPhyDrive->SizeInBytes, GetClusterSize()))
1891 {
1892 Log("FormatPart1LargeFAT32 failed.");
1893 rc = 1;
1894 goto End;
1895 }
1896 }
1897 else if (GetVentoyFsType() == VTOY_FS_EXFAT && GetClusterSize() == 0)
1898 {
1899 Log("Formatting part1 exFAT ...");
1900 DefaultExFAT = TRUE;
1901 if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
1902 {
1903 Log("FormatPart1exFAT failed.");
1904 rc = 1;
1905 goto End;
1906 }
1907 }
1908 else
1909 {
1910 Log("Zero part1 file system ...");
1911 if (0 != ZeroPart1FileSystem(hDrive, Part2StartSector))
1912 {
1913 Log("ZeroPart1FileSystem failed.");
1914 rc = 1;
1915 goto End;
1916 }
1917 }
1918
1919 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
1920 Log("Writing part2 FAT img ...");
1921
1922 if (0 != FormatPart2Fat(hDrive, Part2StartSector))
1923 {
1924 Log("FormatPart2Fat failed.");
1925 rc = 1;
1926 goto End;
1927 }
1928
1929 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);
1930 Log("Writing Boot Image ............................. ");
1931 if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0)
1932 {
1933 Log("WriteGrubStage1ToPhyDrive failed.");
1934 rc = 1;
1935 goto End;
1936 }
1937
1938 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);
1939 Log("Writing Partition Table ........................ ");
1940 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
1941
1942 if (PartStyle)
1943 {
1944 VTOY_GPT_HDR BackupHead;
1945 LARGE_INTEGER liCurrentPosition;
1946
1947 SET_FILE_POS(pPhyDrive->SizeInBytes - 512);
1948 VentoyFillBackupGptHead(pGptInfo, &BackupHead);
1949 if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))
1950 {
1951 rc = 1;
1952 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1953 goto End;
1954 }
1955
1956 SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);
1957 if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))
1958 {
1959 rc = 1;
1960 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1961 goto End;
1962 }
1963
1964 SET_FILE_POS(0);
1965 if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))
1966 {
1967 rc = 1;
1968 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1969 goto End;
1970 }
1971
1972 Log("Write GPT Info OK ...");
1973 memcpy(&(pPhyDrive->MBR), &(pGptInfo->MBR), 512);
1974 }
1975 else
1976 {
1977 if (!WriteFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL))
1978 {
1979 rc = 1;
1980 Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize, GetLastError());
1981 goto End;
1982 }
1983 Log("Write MBR OK ...");
1984 memcpy(&(pPhyDrive->MBR), &MBR, 512);
1985 }
1986
1987 //Refresh Drive Layout
1988 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
1989
1990 End:
1991
1992 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1993
1994 if (rc == 0)
1995 {
1996 Log("Mounting Ventoy Partition ....................... ");
1997 Sleep(1000);
1998
1999 state = 0;
2000 memset(DriveLetters, 0, sizeof(DriveLetters));
2001 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
2002 Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
2003
2004 for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
2005 {
2006 DriveName[0] = DriveLetters[i];
2007 if (IsVentoyLogicalDrive(DriveName[0]))
2008 {
2009 Log("%s is ventoy part2, delete mountpoint", DriveName);
2010 DeleteVolumeMountPointA(DriveName);
2011 }
2012 else
2013 {
2014 Log("%s is ventoy part1, already mounted", DriveName);
2015 MountDrive = DriveName[0];
2016 state = 1;
2017 }
2018 }
2019
2020 if (state != 1)
2021 {
2022 Log("need to mount ventoy part1...");
2023
2024 if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, Part1StartSector, DriveLetters, sizeof(DriveLetters), FALSE))
2025 {
2026 DriveName[0] = MountDrive;
2027 bRet = SetVolumeMountPointA(DriveName, DriveLetters);
2028 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
2029
2030 if (bRet)
2031 {
2032 state = 1;
2033 }
2034 }
2035 else
2036 {
2037 Log("Failed to find ventoy volume");
2038 }
2039 }
2040
2041 // close handle, or it will deny reformat
2042 Log("Close handle ...");
2043 CHECK_CLOSE_HANDLE(hDrive);
2044
2045 ReformatOK = TRUE;
2046
2047 if (state)
2048 {
2049 if (LargeFAT32)
2050 {
2051 Log("No need to reformat for large FAT32");
2052 pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);
2053 }
2054 else if (DefaultExFAT)
2055 {
2056 Log("No need to reformat for default exfat");
2057 pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);
2058 }
2059 else
2060 {
2061 bRet = DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512);
2062 for (i = 0; bRet == FALSE && i < 2; i++)
2063 {
2064 Log("Wait and retry reformat ...");
2065 Sleep(1000);
2066 bRet = DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512);
2067 }
2068
2069 if (bRet)
2070 {
2071 Log("Reformat %C:\\ to %s SUCCESS", MountDrive, GetVentoyFsName());
2072 pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);
2073
2074 if ((GetVentoyFsType() != VTOY_FS_UDF) && (pPhyDrive->VentoyFsClusterSize < 2048))
2075 {
2076 for (i = 0; i < 10; i++)
2077 {
2078 Log("### Invalid cluster size %d ###", pPhyDrive->VentoyFsClusterSize);
2079 }
2080 }
2081 }
2082 else
2083 {
2084 ReformatOK = FALSE;
2085 Log("Reformat %C:\\ to %s FAILED", MountDrive, GetVentoyFsName());
2086 }
2087 }
2088 }
2089 else
2090 {
2091 Log("Can not reformat %s to %s", DriveName, GetVentoyFsName());
2092 }
2093
2094 if (!ReformatOK)
2095 {
2096 Log("Format to exfat with built-in algorithm");
2097
2098 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2099 if (hDrive == INVALID_HANDLE_VALUE)
2100 {
2101 Log("Failed to GetPhysicalHandle for write.");
2102 }
2103 else
2104 {
2105 if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
2106 {
2107 Log("FormatPart1exFAT SUCCESS.");
2108 }
2109 else
2110 {
2111 Log("FormatPart1exFAT FAILED.");
2112 }
2113
2114 CHECK_CLOSE_HANDLE(hDrive);
2115 }
2116 }
2117
2118 Log("OK\n");
2119 }
2120 else
2121 {
2122 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
2123
2124 FindProcessOccupyDisk(hDrive, pPhyDrive);
2125
2126 if (!VDS_IsLastAvaliable())
2127 {
2128 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2129 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2130 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2131 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2132 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2133 }
2134
2135 CHECK_CLOSE_HANDLE(hDrive);
2136 }
2137
2138 if (pGptInfo)
2139 {
2140 free(pGptInfo);
2141 }
2142
2143 return rc;
2144 }
2145
2146
2147 int PartitionResizeForVentoy(PHY_DRIVE_INFO *pPhyDrive)
2148 {
2149 int i, j;
2150 int rc = 1;
2151 int PhyDrive;
2152 int PartStyle;
2153 INT64 ReservedValue;
2154 UINT64 RecudeBytes;
2155 GUID Guid;
2156 MBR_HEAD MBR;
2157 VTOY_GPT_INFO *pGPT;
2158 MBR_HEAD *pMBR;
2159 DWORD dwSize = 0;
2160 VTOY_GPT_HDR BackupHead;
2161 HANDLE hDrive = INVALID_HANDLE_VALUE;
2162 GUID ZeroGuid = { 0 };
2163 static GUID WindowsDataPartType = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };
2164 static GUID EspPartType = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };
2165 static GUID BiosGrubPartType = { 0x21686148, 0x6449, 0x6e6f, { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } };
2166
2167 Log("#####################################################");
2168 Log("PartitionResizeForVentoy PhyDrive%d <<%s %s %dGB>>",
2169 pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
2170 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
2171 Log("#####################################################");
2172
2173 pGPT = &(pPhyDrive->Gpt);
2174 pMBR = &(pPhyDrive->Gpt.MBR);
2175 Log("Disksize:%llu Part2Start:%llu", pPhyDrive->SizeInBytes, pPhyDrive->ResizePart2StartSector * 512);
2176
2177 if (pMBR->PartTbl[0].FsFlag == 0xEE && memcmp(pGPT->Head.Signature, "EFI PART", 8) == 0)
2178 {
2179 PartStyle = 1;
2180 }
2181 else
2182 {
2183 PartStyle = 0;
2184 }
2185
2186 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
2187
2188 RecudeBytes = VENTOY_EFI_PART_SIZE;
2189 ReservedValue = GetReservedSpaceInMB();
2190 if (ReservedValue > 0)
2191 {
2192 Log("Reduce add reserved space %lldMB", (LONGLONG)ReservedValue);
2193 RecudeBytes += (UINT64)(ReservedValue * SIZE_1MB);
2194 }
2195
2196
2197 if (pPhyDrive->ResizeNoShrink == FALSE)
2198 {
2199 Log("Need to shrink the volume");
2200 if (DISK_ShrinkVolume(pPhyDrive->PhyDrive, pPhyDrive->ResizeVolumeGuid, pPhyDrive->Part1DriveLetter, pPhyDrive->ResizeOldPart1Size, RecudeBytes))
2201 {
2202 Log("Shrink volume success, now check again");
2203
2204 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2205 if (hDrive == INVALID_HANDLE_VALUE)
2206 {
2207 Log("Failed to GetPhysicalHandle for update.");
2208 goto End;
2209 }
2210
2211 //Refresh Drive Layout
2212 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
2213
2214 CHECK_CLOSE_HANDLE(hDrive);
2215
2216
2217 if (PartResizePreCheck(NULL) && pPhyDrive->ResizeNoShrink)
2218 {
2219 Log("Recheck after Shrink volume success");
2220 Log("After shrink Disksize:%llu Part2Start:%llu", pPhyDrive->SizeInBytes, pPhyDrive->ResizePart2StartSector * 512);
2221 }
2222 else
2223 {
2224 Log("Recheck after Shrink volume failed %u", pPhyDrive->ResizeNoShrink);
2225 goto End;
2226 }
2227 }
2228 else
2229 {
2230 Log("Shrink volume failed");
2231 goto End;
2232 }
2233 }
2234
2235
2236 //Now try write data
2237 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2238 if (hDrive == INVALID_HANDLE_VALUE)
2239 {
2240 Log("Failed to GetPhysicalHandle for update.");
2241 goto End;
2242 }
2243
2244
2245 //Write partition 2 data
2246 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
2247 if (0 != FormatPart2Fat(hDrive, pPhyDrive->ResizePart2StartSector))
2248 {
2249 Log("FormatPart2Fat failed.");
2250 goto End;
2251 }
2252
2253 //Write grub stage2 gap
2254 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);
2255 Log("Writing Boot Image ............................. ");
2256 if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0)
2257 {
2258 Log("WriteGrubStage1ToPhyDrive failed.");
2259 goto End;
2260 }
2261
2262
2263 //Write partition table
2264 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);
2265 Log("Writing partition table ............................. ");
2266
2267 VentoyGetLocalBootImg(&MBR);
2268 CoCreateGuid(&Guid);
2269 memcpy(MBR.BootCode + 0x180, &Guid, 16);
2270 memcpy(pMBR->BootCode, MBR.BootCode, 440);
2271
2272 if (PartStyle == 0)
2273 {
2274 for (i = 1; i < 4; i++)
2275 {
2276 if (pMBR->PartTbl[i].SectorCount == 0)
2277 {
2278 break;
2279 }
2280 }
2281
2282 if (i >= 4)
2283 {
2284 Log("Can not find MBR free partition table");
2285 goto End;
2286 }
2287
2288 for (j = i - 1; j > 0; j--)
2289 {
2290 Log("Move MBR partition table %d --> %d", j + 1, j + 2);
2291 memcpy(pMBR->PartTbl + (j + 1), pMBR->PartTbl + j, sizeof(PART_TABLE));
2292 }
2293
2294 memset(pMBR->PartTbl + 1, 0, sizeof(PART_TABLE));
2295 VentoyFillMBRLocation(pPhyDrive->SizeInBytes, (UINT32)pPhyDrive->ResizePart2StartSector, VENTOY_EFI_PART_SIZE / 512, pMBR->PartTbl + 1);
2296 pMBR->PartTbl[0].Active = 0x80; // bootable
2297 pMBR->PartTbl[1].Active = 0x00;
2298 pMBR->PartTbl[1].FsFlag = 0xEF; // EFI System Partition
2299
2300 if (!WriteDataToPhyDisk(hDrive, 0, pMBR, 512))
2301 {
2302 Log("Legacy BIOS write MBR failed");
2303 goto End;
2304 }
2305 }
2306 else
2307 {
2308 for (i = 1; i < 128; i++)
2309 {
2310 if (memcmp(&(pGPT->PartTbl[i].PartGuid), &ZeroGuid, sizeof(GUID)) == 0)
2311 {
2312 break;
2313 }
2314 }
2315
2316 if (i >= 128)
2317 {
2318 Log("Can not find GPT free partition table");
2319 goto End;
2320 }
2321
2322 for (j = i - 1; j > 0; j--)
2323 {
2324 Log("Move GPT partition table %d --> %d", j + 1, j + 2);
2325 memcpy(pGPT->PartTbl + (j + 1), pGPT->PartTbl + j, sizeof(VTOY_GPT_PART_TBL));
2326 }
2327
2328
2329 pMBR->BootCode[92] = 0x22;
2330
2331 // to fix windows issue
2332 memset(pGPT->PartTbl + 1, 0, sizeof(VTOY_GPT_PART_TBL));
2333 memcpy(&(pGPT->PartTbl[1].PartType), &WindowsDataPartType, sizeof(GUID));
2334 CoCreateGuid(&(pGPT->PartTbl[1].PartGuid));
2335
2336 pGPT->PartTbl[1].StartLBA = pGPT->PartTbl[0].LastLBA + 1;
2337 pGPT->PartTbl[1].LastLBA = pGPT->PartTbl[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1;
2338 pGPT->PartTbl[1].Attr = 0xC000000000000001ULL;
2339 memcpy(pGPT->PartTbl[1].Name, L"VTOYEFI", 7 * 2);
2340
2341 //Update CRC
2342 pGPT->Head.PartTblCrc = VentoyCrc32(pGPT->PartTbl, sizeof(pGPT->PartTbl));
2343 pGPT->Head.Crc = 0;
2344 pGPT->Head.Crc = VentoyCrc32(&(pGPT->Head), pGPT->Head.Length);
2345
2346 Log("pGPT->Head.EfiStartLBA=%llu", (ULONGLONG)pGPT->Head.EfiStartLBA);
2347 Log("pGPT->Head.EfiBackupLBA=%llu", (ULONGLONG)pGPT->Head.EfiBackupLBA);
2348
2349 VentoyFillBackupGptHead(pGPT, &BackupHead);
2350 if (!WriteDataToPhyDisk(hDrive, pGPT->Head.EfiBackupLBA * 512, &BackupHead, 512))
2351 {
2352 Log("UEFI write backup head failed");
2353 goto End;
2354 }
2355
2356 if (!WriteDataToPhyDisk(hDrive, (pGPT->Head.EfiBackupLBA - 32) * 512, pGPT->PartTbl, 512 * 32))
2357 {
2358 Log("UEFI write backup partition table failed");
2359 goto End;
2360 }
2361
2362 if (!WriteDataToPhyDisk(hDrive, 0, pGPT, 512 * 34))
2363 {
2364 Log("UEFI write MBR & Main partition table failed");
2365 goto End;
2366 }
2367 }
2368
2369
2370
2371 //Refresh Drive Layout
2372 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
2373
2374 //We must close handle here, because it will block the refresh bellow
2375 CHECK_CLOSE_HANDLE(hDrive);
2376
2377 Sleep(2000);
2378
2379 if (g_CLI_Mode)
2380 {
2381 Log("### Ventoy non-destructive CLI installation successfully finished.");
2382 }
2383 else
2384 {
2385 //Refresh disk list
2386 PhyDrive = pPhyDrive->PhyDrive;
2387
2388 Log("#### Now Refresh PhyDrive ####");
2389 Ventoy2DiskDestroy();
2390 Ventoy2DiskInit();
2391
2392 pPhyDrive = GetPhyDriveInfoByPhyDrive(PhyDrive);
2393 if (pPhyDrive)
2394 {
2395 if (pPhyDrive->VentoyVersion[0] == 0)
2396 {
2397 Log("After process the Ventoy version is still invalid");
2398 goto End;
2399 }
2400
2401 Log("### Ventoy non-destructive installation successfully finished <%s>", pPhyDrive->VentoyVersion);
2402 }
2403 else
2404 {
2405 Log("### Ventoy non-destructive installation successfully finished <not found>");
2406 }
2407
2408 InitComboxCtrl(g_DialogHwnd, PhyDrive);
2409 }
2410
2411 rc = 0;
2412
2413 End:
2414 CHECK_CLOSE_HANDLE(hDrive);
2415 return rc;
2416 }
2417
2418
2419 static BOOL DiskCheckWriteAccess(HANDLE hDrive)
2420 {
2421 DWORD dwSize;
2422 BOOL ret = FALSE;
2423 BOOL bRet = FALSE;
2424 BYTE Buffer[512];
2425 LARGE_INTEGER liCurPosition;
2426 LARGE_INTEGER liNewPosition;
2427
2428 liCurPosition.QuadPart = 2039 * 512;
2429 liNewPosition.QuadPart = 0;
2430 if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||
2431 liNewPosition.QuadPart != liCurPosition.QuadPart)
2432 {
2433 Log("SetFilePointer1 Failed %u", LASTERR);
2434 goto out;
2435 }
2436
2437
2438 dwSize = 0;
2439 ret = ReadFile(hDrive, Buffer, 512, &dwSize, NULL);
2440 if ((!ret) || (dwSize != 512))
2441 {
2442 Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR);
2443 goto out;
2444 }
2445
2446
2447 liCurPosition.QuadPart = 2039 * 512;
2448 liNewPosition.QuadPart = 0;
2449 if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||
2450 liNewPosition.QuadPart != liCurPosition.QuadPart)
2451 {
2452 Log("SetFilePointer2 Failed %u", LASTERR);
2453 goto out;
2454 }
2455
2456 dwSize = 0;
2457 ret = WriteFile(hDrive, Buffer, 512, &dwSize, NULL);
2458 if ((!ret) || dwSize != 512)
2459 {
2460 Log("Failed to write %d %u %u", ret, dwSize, LASTERR);
2461 goto out;
2462 }
2463
2464 bRet = TRUE;
2465
2466 out:
2467
2468 return bRet;
2469 }
2470
2471 static BOOL BackupDataBeforeCleanDisk(int PhyDrive, UINT64 DiskSize, BYTE **pBackup)
2472 {
2473 DWORD dwSize;
2474 DWORD dwStatus;
2475 BOOL Return = FALSE;
2476 BOOL ret = FALSE;
2477 BYTE *backup = NULL;
2478 UINT64 offset;
2479 HANDLE hDrive = INVALID_HANDLE_VALUE;
2480 LARGE_INTEGER liCurPosition;
2481 LARGE_INTEGER liNewPosition;
2482 VTOY_GPT_INFO *pGPT = NULL;
2483
2484 Log("BackupDataBeforeCleanDisk %d", PhyDrive);
2485
2486 // step1: check write access
2487 hDrive = GetPhysicalHandle(PhyDrive, TRUE, TRUE, FALSE);
2488 if (hDrive == INVALID_HANDLE_VALUE)
2489 {
2490 Log("Failed to GetPhysicalHandle for write.");
2491 goto out;
2492 }
2493
2494 if (DiskCheckWriteAccess(hDrive))
2495 {
2496 Log("DiskCheckWriteAccess success");
2497 CHECK_CLOSE_HANDLE(hDrive);
2498 }
2499 else
2500 {
2501 Log("DiskCheckWriteAccess failed");
2502 goto out;
2503 }
2504
2505 //step2 backup 4MB data
2506 backup = malloc(SIZE_1MB * 4);
2507 if (!backup)
2508 {
2509 goto out;
2510 }
2511
2512 hDrive = GetPhysicalHandle(PhyDrive, FALSE, FALSE, FALSE);
2513 if (hDrive == INVALID_HANDLE_VALUE)
2514 {
2515 goto out;
2516 }
2517
2518 //read first 2MB
2519 dwStatus = SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2520 if (dwStatus != 0)
2521 {
2522 goto out;
2523 }
2524
2525 dwSize = 0;
2526 ret = ReadFile(hDrive, backup, SIZE_2MB, &dwSize, NULL);
2527 if ((!ret) || (dwSize != SIZE_2MB))
2528 {
2529 Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR);
2530 goto out;
2531 }
2532
2533 pGPT = (VTOY_GPT_INFO *)backup;
2534 offset = pGPT->Head.EfiBackupLBA * 512;
2535 if (offset >= (DiskSize - SIZE_2MB) && offset < DiskSize)
2536 {
2537 Log("EFI partition table check success");
2538 }
2539 else
2540 {
2541 Log("Backup EFI LBA not in last 2MB range: %llu", pGPT->Head.EfiBackupLBA);
2542 goto out;
2543 }
2544
2545 //read last 2MB
2546 liCurPosition.QuadPart = DiskSize - SIZE_2MB;
2547 liNewPosition.QuadPart = 0;
2548 if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||
2549 liNewPosition.QuadPart != liCurPosition.QuadPart)
2550 {
2551 goto out;
2552 }
2553
2554 dwSize = 0;
2555 ret = ReadFile(hDrive, backup + SIZE_2MB, SIZE_2MB, &dwSize, NULL);
2556 if ((!ret) || (dwSize != SIZE_2MB))
2557 {
2558 Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR);
2559 goto out;
2560 }
2561
2562 *pBackup = backup;
2563 backup = NULL; //For don't free later
2564 Return = TRUE;
2565
2566 out:
2567 CHECK_CLOSE_HANDLE(hDrive);
2568 if (backup)
2569 free(backup);
2570
2571 return Return;
2572 }
2573
2574
2575 static BOOL WriteBackupDataToDisk(HANDLE hDrive, UINT64 Offset, BYTE *Data, DWORD Length)
2576 {
2577 DWORD dwSize = 0;
2578 BOOL ret = FALSE;
2579 LARGE_INTEGER liCurPosition;
2580 LARGE_INTEGER liNewPosition;
2581
2582 Log("WriteBackupDataToDisk %llu %p %u", Offset, Data, Length);
2583
2584 liCurPosition.QuadPart = Offset;
2585 liNewPosition.QuadPart = 0;
2586 if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||
2587 liNewPosition.QuadPart != liCurPosition.QuadPart)
2588 {
2589 return FALSE;
2590 }
2591
2592 ret = WriteFile(hDrive, Data, Length, &dwSize, NULL);
2593 if ((!ret) || dwSize != Length)
2594 {
2595 Log("Failed to write %d %u %u", ret, dwSize, LASTERR);
2596 return FALSE;
2597 }
2598
2599 Log("WriteBackupDataToDisk %llu %p %u success", Offset, Data, Length);
2600 return TRUE;
2601 }
2602
2603
2604 int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
2605 {
2606 int i;
2607 int rc = 0;
2608 int MaxRetry = 4;
2609 BOOL ForceMBR = FALSE;
2610 BOOL Esp2Basic = FALSE;
2611 BOOL ChangeAttr = FALSE;
2612 BOOL CleanDisk = FALSE;
2613 BOOL DelEFI = FALSE;
2614 BOOL bWriteBack = TRUE;
2615 HANDLE hVolume;
2616 HANDLE hDrive;
2617 DWORD Status;
2618 DWORD dwSize;
2619 BOOL bRet;
2620 CHAR DriveName[] = "?:\\";
2621 CHAR DriveLetters[MAX_PATH] = { 0 };
2622 CHAR BackBinFile[MAX_PATH];
2623 UINT64 StartSector;
2624 UINT64 ReservedMB = 0;
2625 MBR_HEAD BootImg;
2626 MBR_HEAD MBR;
2627 BYTE *pBackup = NULL;
2628 VTOY_GPT_INFO *pGptInfo = NULL;
2629 VTOY_GPT_INFO *pGptBkup = NULL;
2630 UINT8 ReservedData[4096];
2631
2632 Log("#####################################################");
2633 Log("UpdateVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId,
2634 pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
2635 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
2636 Log("#####################################################");
2637
2638 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
2639
2640 Log("Lock disk for umount ............................ ");
2641
2642 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
2643 if (hDrive == INVALID_HANDLE_VALUE)
2644 {
2645 Log("Failed to open physical disk");
2646 return 1;
2647 }
2648
2649 if (pPhyDrive->PartStyle)
2650 {
2651 pGptInfo = malloc(2 * sizeof(VTOY_GPT_INFO));
2652 if (!pGptInfo)
2653 {
2654 return 1;
2655 }
2656
2657 memset(pGptInfo, 0, 2 * sizeof(VTOY_GPT_INFO));
2658 pGptBkup = pGptInfo + 1;
2659
2660 // Read GPT Info
2661 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2662 ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL);
2663 memcpy(pGptBkup, pGptInfo, sizeof(VTOY_GPT_INFO));
2664
2665 //MBR will be used to compare with local boot image
2666 memcpy(&MBR, &pGptInfo->MBR, sizeof(MBR_HEAD));
2667
2668 StartSector = pGptInfo->PartTbl[1].StartLBA;
2669 Log("GPT StartSector in PartTbl:%llu", (ULONGLONG)StartSector);
2670
2671 ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512) - 33) / 2048;
2672 Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);
2673 }
2674 else
2675 {
2676 // Read MBR
2677 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2678 ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
2679
2680 StartSector = MBR.PartTbl[1].StartSectorId;
2681 Log("MBR StartSector in PartTbl:%llu", (ULONGLONG)StartSector);
2682
2683 ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512)) / 2048;
2684 Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);
2685 }
2686
2687 //Read Reserved Data
2688 SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);
2689 ReadFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);
2690
2691 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
2692
2693 if (DriveLetters[0] == 0)
2694 {
2695 Log("No drive letter was assigned...");
2696 }
2697 else
2698 {
2699 // Unmount all mounted volumes that belong to this drive
2700 // Do it in reverse so that we always end on the first volume letter
2701 for (i = (int)strlen(DriveLetters); i > 0; i--)
2702 {
2703 DriveName[0] = DriveLetters[i - 1];
2704 if (IsVentoyLogicalDrive(DriveName[0]))
2705 {
2706 Log("%s is ventoy logical drive", DriveName);
2707 bRet = DeleteVolumeMountPointA(DriveName);
2708 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, LASTERR);
2709 break;
2710 }
2711 }
2712 }
2713
2714 // It kind of blows, but we have to relinquish access to the physical drive
2715 // for VDS to be able to delete the partitions that reside on it...
2716 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2717 CHECK_CLOSE_HANDLE(hDrive);
2718
2719 if (pPhyDrive->PartStyle == 1)
2720 {
2721 Log("TryId=%d EFI GPT partition type is 0x%llx", TryId, pPhyDrive->Part2GPTAttr);
2722 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
2723
2724 if (TryId == 1)
2725 {
2726 Log("Change GPT partition type to ESP");
2727 if (DISK_ChangeVtoyEFI2ESP(pPhyDrive->PhyDrive, StartSector * 512ULL))
2728 {
2729 Esp2Basic = TRUE;
2730 Sleep(3000);
2731 }
2732 }
2733 else if (TryId == 2)
2734 {
2735 Log("Change GPT partition attribute");
2736 if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, 0x8000000000000001))
2737 {
2738 ChangeAttr = TRUE;
2739 Sleep(2000);
2740 }
2741 }
2742 else if (TryId == 3)
2743 {
2744 DISK_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive, StartSector * 512ULL);
2745 DelEFI = TRUE;
2746 }
2747 else if (TryId == 4)
2748 {
2749 Log("Clean disk GPT partition table");
2750 if (BackupDataBeforeCleanDisk(pPhyDrive->PhyDrive, pPhyDrive->SizeInBytes, &pBackup))
2751 {
2752 sprintf_s(BackBinFile, sizeof(BackBinFile), ".\\ventoy\\phydrive%d_%u_%d.bin",
2753 pPhyDrive->PhyDrive, GetCurrentProcessId(), g_backup_bin_index++);
2754 SaveBufToFile(BackBinFile, pBackup, 4 * SIZE_1MB);
2755 Log("Save backup data to %s", BackBinFile);
2756
2757 Log("Success to backup data before clean");
2758 CleanDisk = TRUE;
2759 DISK_CleanDisk(pPhyDrive->PhyDrive);
2760 Sleep(3000);
2761 }
2762 else
2763 {
2764 Log("Failed to backup data before clean");
2765 }
2766 }
2767 }
2768
2769 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
2770
2771 Log("Lock disk for update ............................ ");
2772 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2773 if (hDrive == INVALID_HANDLE_VALUE)
2774 {
2775 Log("Failed to GetPhysicalHandle for write.");
2776 rc = 1;
2777 goto End;
2778 }
2779
2780 PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME);
2781
2782 Log("Lock volume for update .......................... ");
2783 hVolume = INVALID_HANDLE_VALUE;
2784
2785 //If we change VTOYEFI to ESP, it can not have s volume name, so don't try to get it.
2786 if (CleanDisk)
2787 {
2788 //writeback the last 2MB
2789 if (!WriteBackupDataToDisk(hDrive, pPhyDrive->SizeInBytes - SIZE_2MB, pBackup + SIZE_2MB, SIZE_2MB))
2790 {
2791 bWriteBack = FALSE;
2792 }
2793
2794 //write the first 2MB except parttable
2795 if (!WriteBackupDataToDisk(hDrive, 34 * 512, pBackup + 34 * 512, SIZE_2MB - 34 * 512))
2796 {
2797 bWriteBack = FALSE;
2798 }
2799
2800 Status = ERROR_NOT_FOUND;
2801 }
2802 else if (DelEFI)
2803 {
2804 Status = ERROR_NOT_FOUND;
2805 }
2806 else if (Esp2Basic)
2807 {
2808 Status = ERROR_NOT_FOUND;
2809 }
2810 else
2811 {
2812 for (i = 0; i < MaxRetry; i++)
2813 {
2814 Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, StartSector, DriveLetters, sizeof(DriveLetters), TRUE);
2815 if (ERROR_SUCCESS == Status)
2816 {
2817 break;
2818 }
2819 else
2820 {
2821 Log("==== Volume not found, wait and retry %d... ====", i);
2822 Sleep(2);
2823 }
2824 }
2825 }
2826
2827 if (ERROR_SUCCESS == Status)
2828 {
2829 Log("Now lock and dismount volume <%s>", DriveLetters);
2830
2831 for (i = 0; i < MaxRetry; i++)
2832 {
2833 hVolume = CreateFileA(DriveLetters,
2834 GENERIC_READ | GENERIC_WRITE,
2835 FILE_SHARE_READ,
2836 NULL,
2837 OPEN_EXISTING,
2838 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
2839 NULL);
2840
2841 if (hVolume == INVALID_HANDLE_VALUE)
2842 {
2843 Log("Failed to create file volume, errcode:%u, wait and retry ...", LASTERR);
2844 Sleep(2000);
2845 }
2846 else
2847 {
2848 break;
2849 }
2850 }
2851
2852 if (hVolume == INVALID_HANDLE_VALUE)
2853 {
2854 Log("Failed to create file volume, errcode:%u", LASTERR);
2855 }
2856 else
2857 {
2858 bRet = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2859 Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
2860
2861 bRet = DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2862 Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet, LASTERR);
2863 }
2864 }
2865 else if (ERROR_NOT_FOUND == Status)
2866 {
2867 Log("Volume not found, maybe not supported");
2868 }
2869 else
2870 {
2871 rc = 1;
2872 goto End;
2873 }
2874
2875 bRet = TryWritePart2(hDrive, StartSector);
2876 if (FALSE == bRet && Esp2Basic)
2877 {
2878 Log("TryWritePart2 agagin ...");
2879 Sleep(3000);
2880 bRet = TryWritePart2(hDrive, StartSector);
2881 }
2882
2883 if (!bRet)
2884 {
2885 if (pPhyDrive->PartStyle == 0)
2886 {
2887 if (DiskCheckWriteAccess(hDrive))
2888 {
2889 Log("MBR DiskCheckWriteAccess success");
2890
2891 ForceMBR = TRUE;
2892
2893 Log("Try write failed, now delete partition 2 for MBR...");
2894 CHECK_CLOSE_HANDLE(hDrive);
2895
2896 Log("Now delete partition 2...");
2897 DISK_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive, StartSector * 512ULL);
2898
2899 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2900 if (hDrive == INVALID_HANDLE_VALUE)
2901 {
2902 Log("Failed to GetPhysicalHandle for write.");
2903 rc = 1;
2904 goto End;
2905 }
2906 }
2907 else
2908 {
2909 Log("MBR DiskCheckWriteAccess failed");
2910 }
2911 }
2912 else
2913 {
2914 Log("TryWritePart2 failed ....");
2915 rc = 1;
2916 goto End;
2917 }
2918 }
2919
2920 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
2921
2922 Log("Write Ventoy to disk ............................ ");
2923 if (0 != FormatPart2Fat(hDrive, StartSector))
2924 {
2925 rc = 1;
2926 goto End;
2927 }
2928
2929 if (hVolume != INVALID_HANDLE_VALUE)
2930 {
2931 bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2932 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
2933 CHECK_CLOSE_HANDLE(hVolume);
2934 }
2935
2936 Log("Updating Boot Image ............................. ");
2937 if (WriteGrubStage1ToPhyDrive(hDrive, pPhyDrive->PartStyle) != 0)
2938 {
2939 rc = 1;
2940 goto End;
2941 }
2942
2943 //write reserved data
2944 SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);
2945 bRet = WriteFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);
2946 Log("Write resv data ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
2947
2948 // Boot Image
2949 VentoyGetLocalBootImg(&BootImg);
2950
2951 // Use Old UUID
2952 memcpy(BootImg.BootCode + 0x180, MBR.BootCode + 0x180, 16);
2953 if (pPhyDrive->PartStyle)
2954 {
2955 BootImg.BootCode[92] = 0x22;
2956 }
2957
2958 if (ForceMBR == FALSE && memcmp(BootImg.BootCode, MBR.BootCode, 440) == 0)
2959 {
2960 Log("Boot image has no difference, no need to write.");
2961 }
2962 else
2963 {
2964 Log("Boot image need to write %u.", ForceMBR);
2965
2966 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2967
2968 memcpy(MBR.BootCode, BootImg.BootCode, 440);
2969 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
2970 Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
2971 }
2972
2973 if (pPhyDrive->PartStyle == 0)
2974 {
2975 if (0x00 == MBR.PartTbl[0].Active && 0x80 == MBR.PartTbl[1].Active)
2976 {
2977 Log("Need to chage 1st partition active and 2nd partition inactive.");
2978
2979 MBR.PartTbl[0].Active = 0x80;
2980 MBR.PartTbl[1].Active = 0x00;
2981
2982 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2983 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
2984 Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
2985 }
2986 }
2987
2988 if (CleanDisk)
2989 {
2990 if (!WriteBackupDataToDisk(hDrive, 0, pBackup, 34 * 512))
2991 {
2992 bWriteBack = FALSE;
2993 }
2994
2995 free(pBackup);
2996
2997 if (bWriteBack)
2998 {
2999 Log("Write backup data success, now delete %s", BackBinFile);
3000 DeleteFileA(BackBinFile);
3001 }
3002 else
3003 {
3004 Log("Write backup data failed");
3005 }
3006
3007 Sleep(1000);
3008 }
3009 else if (DelEFI)
3010 {
3011 VTOY_GPT_HDR BackupHdr;
3012
3013 VentoyFillBackupGptHead(pGptBkup, &BackupHdr);
3014 if (!WriteBackupDataToDisk(hDrive, 512 * pGptBkup->Head.EfiBackupLBA, (BYTE*)(&BackupHdr), 512))
3015 {
3016 bWriteBack = FALSE;
3017 }
3018
3019 if (!WriteBackupDataToDisk(hDrive, 512 * (pGptBkup->Head.EfiBackupLBA - 32), (BYTE*)(pGptBkup->PartTbl), 32 * 512))
3020 {
3021 bWriteBack = FALSE;
3022 }
3023
3024 if (!WriteBackupDataToDisk(hDrive, 512, (BYTE*)pGptBkup + 512, 33 * 512))
3025 {
3026 bWriteBack = FALSE;
3027 }
3028
3029 if (bWriteBack)
3030 {
3031 Log("Write backup partition table success");
3032 }
3033 else
3034 {
3035 Log("Write backup partition table failed");
3036 }
3037
3038 Sleep(1000);
3039 }
3040
3041 //Refresh Drive Layout
3042 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
3043
3044 End:
3045
3046 if (hVolume != INVALID_HANDLE_VALUE)
3047 {
3048 bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
3049 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
3050 CHECK_CLOSE_HANDLE(hVolume);
3051 }
3052
3053 if (rc == 0)
3054 {
3055 Log("OK");
3056 }
3057 else
3058 {
3059 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
3060 FindProcessOccupyDisk(hDrive, pPhyDrive);
3061 }
3062
3063 CHECK_CLOSE_HANDLE(hDrive);
3064
3065 if (Esp2Basic)
3066 {
3067 Log("Recover GPT partition type to basic");
3068 DISK_ChangeVtoyEFI2Basic(pPhyDrive->PhyDrive, StartSector * 512);
3069 }
3070
3071 if (pPhyDrive->PartStyle == 1)
3072 {
3073 if (ChangeAttr || ((pPhyDrive->Part2GPTAttr >> 56) != 0xC0))
3074 {
3075 Log("Change EFI partition attr %u <0x%llx> to <0x%llx>", ChangeAttr, pPhyDrive->Part2GPTAttr, 0xC000000000000001ULL);
3076 if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, 0xC000000000000001ULL))
3077 {
3078 Log("Change EFI partition attr success");
3079 pPhyDrive->Part2GPTAttr = 0xC000000000000001ULL;
3080 }
3081 else
3082 {
3083 Log("Change EFI partition attr failed");
3084 }
3085 }
3086 }
3087
3088 if (pGptInfo)
3089 {
3090 free(pGptInfo);
3091 }
3092
3093 return rc;
3094 }
3095
3096