]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Ventoy2Disk/Ventoy2Disk/PhyDrive.c
a916d155a345dd7f78ca9bb3f0d4fb4bd6a69c9a
[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 <winternl.h>
24 #include <commctrl.h>
25 #include <initguid.h>
26 #include "resource.h"
27 #include "Language.h"
28 #include "Ventoy2Disk.h"
29 #include "fat_filelib.h"
30 #include "ff.h"
31 #include "DiskService.h"
32
33 static DWORD GetVentoyVolumeName(int PhyDrive, UINT64 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash)
34 {
35 size_t len;
36 BOOL bRet;
37 DWORD dwSize;
38 HANDLE hDrive;
39 HANDLE hVolume;
40 UINT64 PartOffset;
41 DWORD Status = ERROR_NOT_FOUND;
42 DISK_EXTENT *pExtents = NULL;
43 CHAR VolumeName[MAX_PATH] = { 0 };
44 VOLUME_DISK_EXTENTS DiskExtents;
45
46 PartOffset = 512ULL * StartSectorId;
47
48 Log("GetVentoyVolumeName PhyDrive %d SectorStart:%llu PartOffset:%llu", PhyDrive, (ULONGLONG)StartSectorId, (ULONGLONG)PartOffset);
49
50 hVolume = FindFirstVolumeA(VolumeName, sizeof(VolumeName));
51 if (hVolume == INVALID_HANDLE_VALUE)
52 {
53 return 1;
54 }
55
56 do {
57
58 len = strlen(VolumeName);
59 Log("Find volume:%s", VolumeName);
60
61 VolumeName[len - 1] = 0;
62
63 hDrive = CreateFileA(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
64 if (hDrive == INVALID_HANDLE_VALUE)
65 {
66 continue;
67 }
68
69 bRet = DeviceIoControl(hDrive,
70 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
71 NULL,
72 0,
73 &DiskExtents,
74 (DWORD)(sizeof(DiskExtents)),
75 (LPDWORD)&dwSize,
76 NULL);
77
78 Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet, LASTERR);
79 Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents.NumberOfDiskExtents, DiskExtents.Extents[0].DiskNumber);
80
81 if (bRet && DiskExtents.NumberOfDiskExtents == 1)
82 {
83 pExtents = DiskExtents.Extents;
84
85 Log("This volume DiskNumber:%u offset:%llu", pExtents->DiskNumber, (ULONGLONG)pExtents->StartingOffset.QuadPart);
86 if ((int)pExtents->DiskNumber == PhyDrive && pExtents->StartingOffset.QuadPart == PartOffset)
87 {
88 Log("This volume match");
89
90 if (!DelSlash)
91 {
92 VolumeName[len - 1] = '\\';
93 }
94
95 sprintf_s(NameBuf, BufLen, "%s", VolumeName);
96 Status = ERROR_SUCCESS;
97 CloseHandle(hDrive);
98 break;
99 }
100 }
101
102 CloseHandle(hDrive);
103 } while (FindNextVolumeA(hVolume, VolumeName, sizeof(VolumeName)));
104
105 FindVolumeClose(hVolume);
106
107 Log("GetVentoyVolumeName return %u", Status);
108 return Status;
109 }
110
111 static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length)
112 {
113 int n = 0;
114 DWORD DataSize = 0;
115 CHAR *Pos = NULL;
116 CHAR *StringBuf = NULL;
117
118 DataSize = GetLogicalDriveStringsA(0, NULL);
119 StringBuf = (CHAR *)malloc(DataSize + 1);
120 if (StringBuf == NULL)
121 {
122 return 1;
123 }
124
125 GetLogicalDriveStringsA(DataSize, StringBuf);
126
127 for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1)
128 {
129 if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0]))
130 {
131 Log("%C: is belong to phydrive%d", Pos[0], PhyDrive);
132 DriveLetters[n++] = Pos[0];
133 }
134 }
135
136 free(StringBuf);
137 return 0;
138 }
139
140 static HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare)
141 {
142 int i;
143 DWORD dwSize;
144 DWORD LastError;
145 UINT64 EndTime;
146 HANDLE hDrive = INVALID_HANDLE_VALUE;
147 CHAR PhyDrive[128];
148 CHAR DevPath[MAX_PATH] = { 0 };
149
150 safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", Drive);
151
152 if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath)))
153 {
154 Log("QueryDosDeviceA failed error:%u", GetLastError());
155 strcpy_s(DevPath, sizeof(DevPath), "???");
156 }
157 else
158 {
159 Log("QueryDosDeviceA success %s", DevPath);
160 }
161
162 for (i = 0; i < DRIVE_ACCESS_RETRIES; i++)
163 {
164 // Try without FILE_SHARE_WRITE (unless specifically requested) so that
165 // we won't be bothered by the OS or other apps when we set up our data.
166 // However this means we might have to wait for an access gap...
167 // We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is
168 // required for enumeration.
169 hDrive = CreateFileA(PhyDrive,
170 GENERIC_READ | (bWriteAccess ? GENERIC_WRITE : 0),
171 FILE_SHARE_READ | (bWriteShare ? FILE_SHARE_WRITE : 0),
172 NULL,
173 OPEN_EXISTING,
174 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
175 NULL);
176
177 LastError = GetLastError();
178 Log("[%d] CreateFileA %s code:%u %p", i, PhyDrive, LastError, hDrive);
179
180 if (hDrive != INVALID_HANDLE_VALUE)
181 {
182 break;
183 }
184
185 if ((LastError != ERROR_SHARING_VIOLATION) && (LastError != ERROR_ACCESS_DENIED))
186 {
187 break;
188 }
189
190 if (i == 0)
191 {
192 Log("Waiting for access on %s [%s]...", PhyDrive, DevPath);
193 }
194 else if (!bWriteShare && (i > DRIVE_ACCESS_RETRIES / 3))
195 {
196 // If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE...
197 Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");
198 bWriteShare = TRUE;
199
200 // Try to report the process that is locking the drive
201 // We also use bit 6 as a flag to indicate that SearchProcess was called.
202 //access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40;
203
204 }
205 Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
206 }
207
208 if (hDrive == INVALID_HANDLE_VALUE)
209 {
210 Log("Could not open %s %u", PhyDrive, LASTERR);
211 goto End;
212 }
213
214 if (bWriteAccess)
215 {
216 Log("Opened %s for %s write access", PhyDrive, bWriteShare ? "shared" : "exclusive");
217 }
218
219 if (bLockDrive)
220 {
221 if (DeviceIoControl(hDrive, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwSize, NULL))
222 {
223 Log("I/O boundary checks disabled");
224 }
225
226 EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT;
227
228 do {
229 if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL))
230 {
231 Log("FSCTL_LOCK_VOLUME success");
232 goto End;
233 }
234 Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
235 } while (GetTickCount64() < EndTime);
236
237 // If we reached this section, either we didn't manage to get a lock or the user cancelled
238 Log("Could not lock access to %s %u", PhyDrive, LASTERR);
239
240 // See if we can report the processes are accessing the drive
241 //if (!IS_ERROR(FormatStatus) && (access_mask == 0))
242 // access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE);
243 // Try to continue if the only access rights we saw were for read-only
244 //if ((access_mask & 0x07) != 0x01)
245 // safe_closehandle(hDrive);
246
247 CHECK_CLOSE_HANDLE(hDrive);
248 }
249
250 End:
251
252 if (hDrive == INVALID_HANDLE_VALUE)
253 {
254 Log("Can get handle of %s, maybe some process control it.", DevPath);
255 }
256
257 return hDrive;
258 }
259
260 int GetPhyDriveByLogicalDrive(int DriveLetter)
261 {
262 BOOL Ret;
263 DWORD dwSize;
264 HANDLE Handle;
265 VOLUME_DISK_EXTENTS DiskExtents;
266 CHAR PhyPath[128];
267
268 safe_sprintf(PhyPath, "\\\\.\\%C:", (CHAR)DriveLetter);
269
270 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
271 if (Handle == INVALID_HANDLE_VALUE)
272 {
273 Log("Could not open the disk<%s>, error:%u", PhyPath, LASTERR);
274 return -1;
275 }
276
277 Ret = DeviceIoControl(Handle,
278 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
279 NULL,
280 0,
281 &DiskExtents,
282 (DWORD)(sizeof(DiskExtents)),
283 (LPDWORD)&dwSize,
284 NULL);
285
286 if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
287 {
288 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, LASTERR);
289 CHECK_CLOSE_HANDLE(Handle);
290 return -1;
291 }
292 CHECK_CLOSE_HANDLE(Handle);
293
294 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
295 PhyPath,
296 DiskExtents.Extents[0].DiskNumber,
297 DiskExtents.Extents[0].StartingOffset.QuadPart,
298 DiskExtents.Extents[0].ExtentLength.QuadPart
299 );
300
301 return (int)DiskExtents.Extents[0].DiskNumber;
302 }
303
304 int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)
305 {
306 int i;
307 int Count;
308 int id;
309 int Letter = 'A';
310 BOOL bRet;
311 DWORD dwBytes;
312 DWORD DriveCount = 0;
313 HANDLE Handle = INVALID_HANDLE_VALUE;
314 CHAR PhyDrive[128];
315 PHY_DRIVE_INFO *CurDrive = pDriveList;
316 GET_LENGTH_INFORMATION LengthInfo;
317 STORAGE_PROPERTY_QUERY Query;
318 STORAGE_DESCRIPTOR_HEADER DevDescHeader;
319 STORAGE_DEVICE_DESCRIPTOR *pDevDesc;
320 int PhyDriveId[VENTOY_MAX_PHY_DRIVE];
321
322 Count = GetPhysicalDriveCount();
323
324 for (i = 0; i < Count && i < VENTOY_MAX_PHY_DRIVE; i++)
325 {
326 PhyDriveId[i] = i;
327 }
328
329 dwBytes = GetLogicalDrives();
330 Log("Logical Drives: 0x%x", dwBytes);
331 while (dwBytes)
332 {
333 if (dwBytes & 0x01)
334 {
335 id = GetPhyDriveByLogicalDrive(Letter);
336 Log("%C --> %d", Letter, id);
337 if (id >= 0)
338 {
339 for (i = 0; i < Count; i++)
340 {
341 if (PhyDriveId[i] == id)
342 {
343 break;
344 }
345 }
346
347 if (i >= Count)
348 {
349 Log("Add phy%d to list", i);
350 PhyDriveId[Count] = id;
351 Count++;
352 }
353 }
354 }
355
356 Letter++;
357 dwBytes >>= 1;
358 }
359
360 for (i = 0; i < Count && DriveCount < VENTOY_MAX_PHY_DRIVE; i++)
361 {
362 CHECK_CLOSE_HANDLE(Handle);
363
364 safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", PhyDriveId[i]);
365 Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
366 Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR);
367
368 if (Handle == INVALID_HANDLE_VALUE)
369 {
370 continue;
371 }
372
373 bRet = DeviceIoControl(Handle,
374 IOCTL_DISK_GET_LENGTH_INFO, NULL,
375 0,
376 &LengthInfo,
377 sizeof(LengthInfo),
378 &dwBytes,
379 NULL);
380 if (!bRet)
381 {
382 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR);
383 continue;
384 }
385
386 Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart);
387
388 Query.PropertyId = StorageDeviceProperty;
389 Query.QueryType = PropertyStandardQuery;
390
391 bRet = DeviceIoControl(Handle,
392 IOCTL_STORAGE_QUERY_PROPERTY,
393 &Query,
394 sizeof(Query),
395 &DevDescHeader,
396 sizeof(STORAGE_DESCRIPTOR_HEADER),
397 &dwBytes,
398 NULL);
399 if (!bRet)
400 {
401 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes);
402 continue;
403 }
404
405 if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))
406 {
407 Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size);
408 continue;
409 }
410
411 pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size);
412 if (!pDevDesc)
413 {
414 Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size);
415 continue;
416 }
417
418 bRet = DeviceIoControl(Handle,
419 IOCTL_STORAGE_QUERY_PROPERTY,
420 &Query,
421 sizeof(Query),
422 pDevDesc,
423 DevDescHeader.Size,
424 &dwBytes,
425 NULL);
426 if (!bRet)
427 {
428 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes);
429 free(pDevDesc);
430 continue;
431 }
432
433 CurDrive->PhyDrive = i;
434 CurDrive->SizeInBytes = LengthInfo.Length.QuadPart;
435 CurDrive->DeviceType = pDevDesc->DeviceType;
436 CurDrive->RemovableMedia = pDevDesc->RemovableMedia;
437 CurDrive->BusType = pDevDesc->BusType;
438
439 if (pDevDesc->VendorIdOffset)
440 {
441 safe_strcpy(CurDrive->VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset);
442 TrimString(CurDrive->VendorId);
443 }
444
445 if (pDevDesc->ProductIdOffset)
446 {
447 safe_strcpy(CurDrive->ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset);
448 TrimString(CurDrive->ProductId);
449 }
450
451 if (pDevDesc->ProductRevisionOffset)
452 {
453 safe_strcpy(CurDrive->ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset);
454 TrimString(CurDrive->ProductRev);
455 }
456
457 if (pDevDesc->SerialNumberOffset)
458 {
459 safe_strcpy(CurDrive->SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset);
460 TrimString(CurDrive->SerialNumber);
461 }
462
463 CurDrive++;
464 DriveCount++;
465
466 free(pDevDesc);
467
468 CHECK_CLOSE_HANDLE(Handle);
469 }
470
471 for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++)
472 {
473 Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
474 CurDrive->PhyDrive, GetBusTypeString(CurDrive->BusType), CurDrive->RemovableMedia,
475 GetHumanReadableGBSize(CurDrive->SizeInBytes), CurDrive->SizeInBytes,
476 CurDrive->VendorId, CurDrive->ProductId);
477 }
478
479 *pDriveCount = DriveCount;
480
481 return 0;
482 }
483
484
485 static HANDLE g_FatPhyDrive;
486 static UINT64 g_Part2StartSec;
487 static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen)
488 {
489 int rc = 1;
490 int size = 0;
491 char *buf = NULL;
492 void *flfile = NULL;
493
494 flfile = fl_fopen("/grub/grub.cfg", "rb");
495 if (flfile)
496 {
497 fl_fseek(flfile, 0, SEEK_END);
498 size = (int)fl_ftell(flfile);
499
500 fl_fseek(flfile, 0, SEEK_SET);
501
502 buf = (char *)malloc(size + 1);
503 if (buf)
504 {
505 fl_fread(buf, 1, size, flfile);
506 buf[size] = 0;
507
508 rc = 0;
509 sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf));
510 free(buf);
511 }
512
513 fl_fclose(flfile);
514 }
515
516 return rc;
517 }
518
519 static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
520 {
521 DWORD dwSize;
522 BOOL bRet;
523 DWORD ReadSize;
524 LARGE_INTEGER liCurrentPosition;
525
526 liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
527 liCurrentPosition.QuadPart *= 512;
528 SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
529
530 ReadSize = (DWORD)(SectorCount * 512);
531
532 bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
533 if (bRet == FALSE || dwSize != ReadSize)
534 {
535 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, LASTERR);
536 }
537
538 return 1;
539 }
540
541
542 int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen, BOOL *pSecureBoot)
543 {
544 int rc = 0;
545 HANDLE hDrive;
546 void *flfile;
547
548 hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE);
549 if (hDrive == INVALID_HANDLE_VALUE)
550 {
551 return 1;
552 }
553
554 g_FatPhyDrive = hDrive;
555 g_Part2StartSec = Part2StartSector;
556
557 Log("Parse FAT fs...");
558
559 fl_init();
560
561 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
562 {
563 Log("attach media success...");
564 rc = GetVentoyVersionFromFatFile(VerBuf, BufLen);
565 }
566 else
567 {
568 Log("attach media failed...");
569 rc = 1;
570 }
571
572 Log("GetVentoyVerInPhyDrive rc=%d...", rc);
573 if (rc == 0)
574 {
575 Log("VentoyVerInPhyDrive %d is <%s>...", pDriveInfo->PhyDrive, VerBuf);
576
577 flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
578 if (flfile)
579 {
580 *pSecureBoot = TRUE;
581 fl_fclose(flfile);
582 }
583 }
584
585 fl_shutdown();
586
587 CHECK_CLOSE_HANDLE(hDrive);
588
589 return rc;
590 }
591
592
593
594
595
596 static unsigned int g_disk_unxz_len = 0;
597 static BYTE *g_part_img_pos = NULL;
598 static BYTE *g_part_img_buf[VENTOY_EFI_PART_SIZE / SIZE_1MB];
599
600
601 static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
602 {
603 uint32 i;
604 uint32 offset;
605 BYTE *MbBuf = NULL;
606
607 for (i = 0; i < SectorCount; i++)
608 {
609 offset = (Sector + i) * 512;
610
611 if (g_part_img_buf[1] == NULL)
612 {
613 MbBuf = g_part_img_buf[0] + offset;
614 memcpy(Buffer + i * 512, MbBuf, 512);
615 }
616 else
617 {
618 MbBuf = g_part_img_buf[offset / SIZE_1MB];
619 memcpy(Buffer + i * 512, MbBuf + (offset % SIZE_1MB), 512);
620 }
621 }
622
623 return 1;
624 }
625
626
627 static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
628 {
629 uint32 i;
630 uint32 offset;
631 BYTE *MbBuf = NULL;
632
633 for (i = 0; i < SectorCount; i++)
634 {
635 offset = (Sector + i) * 512;
636
637 if (g_part_img_buf[1] == NULL)
638 {
639 MbBuf = g_part_img_buf[0] + offset;
640 memcpy(MbBuf, Buffer + i * 512, 512);
641 }
642 else
643 {
644 MbBuf = g_part_img_buf[offset / SIZE_1MB];
645 memcpy(MbBuf + (offset % SIZE_1MB), Buffer + i * 512, 512);
646 }
647 }
648
649 return 1;
650 }
651
652 int VentoyProcSecureBoot(BOOL SecureBoot)
653 {
654 int rc = 0;
655 int size;
656 char *filebuf = NULL;
657 void *file = NULL;
658
659 Log("VentoyProcSecureBoot %d ...", SecureBoot);
660
661 if (SecureBoot)
662 {
663 Log("Secure boot is enabled ...");
664 return 0;
665 }
666
667 fl_init();
668
669 if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite))
670 {
671 file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
672 Log("Open ventoy efi file %p ", file);
673 if (file)
674 {
675 fl_fseek(file, 0, SEEK_END);
676 size = (int)fl_ftell(file);
677 fl_fseek(file, 0, SEEK_SET);
678
679 Log("ventoy efi file size %d ...", size);
680
681 filebuf = (char *)malloc(size);
682 if (filebuf)
683 {
684 fl_fread(filebuf, 1, size, file);
685 }
686
687 fl_fclose(file);
688
689 Log("Now delete all efi files ...");
690 fl_remove("/EFI/BOOT/BOOTX64.EFI");
691 fl_remove("/EFI/BOOT/grubx64.efi");
692 fl_remove("/EFI/BOOT/grubx64_real.efi");
693 fl_remove("/EFI/BOOT/MokManager.efi");
694 fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
695
696 file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
697 Log("Open bootx64 efi file %p ", file);
698 if (file)
699 {
700 if (filebuf)
701 {
702 fl_fwrite(filebuf, 1, size, file);
703 }
704
705 fl_fflush(file);
706 fl_fclose(file);
707 }
708
709 if (filebuf)
710 {
711 free(filebuf);
712 }
713 }
714
715 file = fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");
716 Log("Open ventoy efi file %p ", file);
717 if (file)
718 {
719 fl_fseek(file, 0, SEEK_END);
720 size = (int)fl_ftell(file);
721 fl_fseek(file, 0, SEEK_SET);
722
723 Log("ventoy efi file size %d ...", size);
724
725 filebuf = (char *)malloc(size);
726 if (filebuf)
727 {
728 fl_fread(filebuf, 1, size, file);
729 }
730
731 fl_fclose(file);
732
733 Log("Now delete all efi files ...");
734 fl_remove("/EFI/BOOT/BOOTIA32.EFI");
735 fl_remove("/EFI/BOOT/grubia32.efi");
736 fl_remove("/EFI/BOOT/grubia32_real.efi");
737 fl_remove("/EFI/BOOT/mmia32.efi");
738
739 file = fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");
740 Log("Open bootia32 efi file %p ", file);
741 if (file)
742 {
743 if (filebuf)
744 {
745 fl_fwrite(filebuf, 1, size, file);
746 }
747
748 fl_fflush(file);
749 fl_fclose(file);
750 }
751
752 if (filebuf)
753 {
754 free(filebuf);
755 }
756 }
757
758 }
759 else
760 {
761 rc = 1;
762 }
763
764 fl_shutdown();
765
766 return rc;
767 }
768
769
770
771 static int disk_xz_flush(void *src, unsigned int size)
772 {
773 unsigned int i;
774 BYTE *buf = (BYTE *)src;
775
776 for (i = 0; i < size; i++)
777 {
778 *g_part_img_pos = *buf++;
779
780 g_disk_unxz_len++;
781 if ((g_disk_unxz_len % SIZE_1MB) == 0)
782 {
783 g_part_img_pos = g_part_img_buf[g_disk_unxz_len / SIZE_1MB];
784 }
785 else
786 {
787 g_part_img_pos++;
788 }
789 }
790
791 return (int)size;
792 }
793
794 static void unxz_error(char *x)
795 {
796 Log("%s", x);
797 }
798
799 static BOOL TryWritePart2(HANDLE hDrive, UINT64 StartSectorId)
800 {
801 BOOL bRet;
802 DWORD TrySize = 16 * 1024;
803 DWORD dwSize;
804 BYTE *Buffer = NULL;
805 unsigned char *data = NULL;
806 LARGE_INTEGER liCurrentPosition;
807
808 liCurrentPosition.QuadPart = StartSectorId * 512;
809 SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
810
811 Buffer = malloc(TrySize);
812
813 bRet = WriteFile(hDrive, Buffer, TrySize, &dwSize, NULL);
814
815 free(Buffer);
816
817 Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
818
819 if (bRet && dwSize == TrySize)
820 {
821 return TRUE;
822 }
823
824 return FALSE;
825 }
826
827 static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId)
828 {
829 int i;
830 int rc = 0;
831 int len = 0;
832 int writelen = 0;
833 int partwrite = 0;
834 int Pos = PT_WRITE_VENTOY_START;
835 DWORD dwSize = 0;
836 BOOL bRet;
837 unsigned char *data = NULL;
838 LARGE_INTEGER liCurrentPosition;
839 LARGE_INTEGER liNewPosition;
840 BYTE *CheckBuf = NULL;
841
842 Log("FormatPart2Fat %llu...", StartSectorId);
843
844 CheckBuf = malloc(SIZE_1MB);
845 if (!CheckBuf)
846 {
847 Log("Failed to malloc check buf");
848 return 1;
849 }
850
851 rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&data, &len);
852 if (rc)
853 {
854 Log("Failed to read img file %p %u", data, len);
855 free(CheckBuf);
856 return 1;
857 }
858
859 liCurrentPosition.QuadPart = StartSectorId * 512;
860 SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
861
862 memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
863
864 g_part_img_buf[0] = (BYTE *)malloc(VENTOY_EFI_PART_SIZE);
865 if (g_part_img_buf[0])
866 {
867 Log("Malloc whole img buffer success, now decompress ...");
868 unxz(data, len, NULL, NULL, g_part_img_buf[0], &writelen, unxz_error);
869
870 if (len == writelen)
871 {
872 Log("decompress finished success");
873
874 VentoyProcSecureBoot(g_SecureBoot);
875
876 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
877 {
878 dwSize = 0;
879 bRet = WriteFile(hDrive, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB, &dwSize, NULL);
880 Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
881
882 if (!bRet)
883 {
884 rc = 1;
885 goto End;
886 }
887
888 PROGRESS_BAR_SET_POS(Pos);
889 if (i % 2 == 0)
890 {
891 Pos++;
892 }
893 }
894
895 //Read and check the data
896 liCurrentPosition.QuadPart = StartSectorId * 512;
897 SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
898
899 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
900 {
901 bRet = ReadFile(hDrive, CheckBuf, SIZE_1MB, &dwSize, NULL);
902 Log("Read part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
903
904 if (!bRet || memcmp(CheckBuf, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB))
905 {
906 Log("### [Check Fail] The data write and read does not match");
907 rc = 1;
908 goto End;
909 }
910
911 PROGRESS_BAR_SET_POS(Pos);
912 if (i % 2 == 0)
913 {
914 Pos++;
915 }
916 }
917 }
918 else
919 {
920 rc = 1;
921 Log("decompress finished failed");
922 goto End;
923 }
924 }
925 else
926 {
927 Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE);
928
929 partwrite = 1;
930 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
931 {
932 g_part_img_buf[i] = (BYTE *)malloc(SIZE_1MB);
933 if (g_part_img_buf[i] == NULL)
934 {
935 rc = 1;
936 goto End;
937 }
938 }
939
940 Log("Malloc part img buffer success, now decompress ...");
941
942 g_part_img_pos = g_part_img_buf[0];
943
944 unxz(data, len, NULL, disk_xz_flush, NULL, NULL, unxz_error);
945
946 if (g_disk_unxz_len == VENTOY_EFI_PART_SIZE)
947 {
948 Log("decompress finished success");
949
950 VentoyProcSecureBoot(g_SecureBoot);
951
952 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
953 {
954 dwSize = 0;
955 bRet = WriteFile(hDrive, g_part_img_buf[i], SIZE_1MB, &dwSize, NULL);
956 Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
957
958 if (!bRet)
959 {
960 rc = 1;
961 goto End;
962 }
963
964 PROGRESS_BAR_SET_POS(Pos);
965 if (i % 2 == 0)
966 {
967 Pos++;
968 }
969 }
970
971 //Read and check the data
972 liCurrentPosition.QuadPart = StartSectorId * 512;
973 SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
974
975 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
976 {
977 bRet = ReadFile(hDrive, CheckBuf, SIZE_1MB, &dwSize, NULL);
978 Log("Read part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
979
980 if (!bRet || memcmp(CheckBuf, g_part_img_buf[i], SIZE_1MB))
981 {
982 Log("### [Check Fail] The data write and read does not match");
983 rc = 1;
984 goto End;
985 }
986
987 PROGRESS_BAR_SET_POS(Pos);
988 if (i % 2 == 0)
989 {
990 Pos++;
991 }
992 }
993 }
994 else
995 {
996 rc = 1;
997 Log("decompress finished failed");
998 goto End;
999 }
1000 }
1001
1002 End:
1003
1004 if (data) free(data);
1005 if (CheckBuf)free(CheckBuf);
1006
1007 if (partwrite)
1008 {
1009 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1010 {
1011 if (g_part_img_buf[i]) free(g_part_img_buf[i]);
1012 }
1013 }
1014 else
1015 {
1016 if (g_part_img_buf[0]) free(g_part_img_buf[0]);
1017 }
1018
1019 return rc;
1020 }
1021
1022 static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle)
1023 {
1024 int Len = 0;
1025 int readLen = 0;
1026 BOOL bRet;
1027 DWORD dwSize;
1028 BYTE *ImgBuf = NULL;
1029 BYTE *RawBuf = NULL;
1030
1031 Log("WriteGrubStage1ToPhyDrive ...");
1032
1033 RawBuf = (BYTE *)malloc(SIZE_1MB);
1034 if (!RawBuf)
1035 {
1036 return 1;
1037 }
1038
1039 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
1040 {
1041 Log("Failed to read stage1 img");
1042 free(RawBuf);
1043 return 1;
1044 }
1045
1046 unxz(ImgBuf, Len, NULL, NULL, RawBuf, &readLen, unxz_error);
1047
1048 if (PartStyle)
1049 {
1050 Log("Write GPT stage1 ...");
1051 RawBuf[500] = 35;//update blocklist
1052 SetFilePointer(hDrive, 512 * 34, NULL, FILE_BEGIN);
1053 bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512 * 34, &dwSize, NULL);
1054 }
1055 else
1056 {
1057 Log("Write MBR stage1 ...");
1058 SetFilePointer(hDrive, 512, NULL, FILE_BEGIN);
1059 bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512, &dwSize, NULL);
1060 }
1061
1062 Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet, dwSize, GetLastError());
1063
1064 free(RawBuf);
1065 free(ImgBuf);
1066 return 0;
1067 }
1068
1069
1070
1071 static int FormatPart1exFAT(UINT64 DiskSizeBytes)
1072 {
1073 MKFS_PARM Option;
1074 FRESULT Ret;
1075
1076 Option.fmt = FM_EXFAT;
1077 Option.n_fat = 1;
1078 Option.align = 8;
1079 Option.n_root = 1;
1080
1081 // < 32GB select 32KB as cluster size
1082 // > 32GB select 128KB as cluster size
1083 if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32)
1084 {
1085 Option.au_size = 32768;
1086 }
1087 else
1088 {
1089 Option.au_size = 131072;
1090 }
1091
1092 Log("Formatting Part1 exFAT ...");
1093
1094 Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
1095 if (FR_OK == Ret)
1096 {
1097 Log("Formatting Part1 exFAT success");
1098 return 0;
1099 }
1100 else
1101 {
1102 Log("Formatting Part1 exFAT failed");
1103 return 1;
1104 }
1105 }
1106
1107
1108
1109 int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter)
1110 {
1111 int i;
1112 int rc = 0;
1113 int state = 0;
1114 HANDLE hDrive;
1115 DWORD dwSize;
1116 BOOL bRet;
1117 CHAR MountDrive;
1118 CHAR DriveName[] = "?:\\";
1119 CHAR DriveLetters[MAX_PATH] = { 0 };
1120 LARGE_INTEGER liCurrentPosition;
1121 char *pTmpBuf = NULL;
1122 MBR_HEAD MBR;
1123
1124 *pDrvLetter = 0;
1125
1126 Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
1127 pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1128 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1129
1130 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1131
1132 Log("Lock disk for clean ............................. ");
1133
1134 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
1135 if (hDrive == INVALID_HANDLE_VALUE)
1136 {
1137 Log("Failed to open physical disk");
1138 return 1;
1139 }
1140
1141 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1142
1143 if (DriveLetters[0] == 0)
1144 {
1145 Log("No drive letter was assigned...");
1146 DriveName[0] = GetFirstUnusedDriveLetter();
1147 Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
1148 }
1149 else
1150 {
1151 // Unmount all mounted volumes that belong to this drive
1152 // Do it in reverse so that we always end on the first volume letter
1153 for (i = (int)strlen(DriveLetters); i > 0; i--)
1154 {
1155 DriveName[0] = DriveLetters[i - 1];
1156 bRet = DeleteVolumeMountPointA(DriveName);
1157 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
1158 }
1159 }
1160
1161 MountDrive = DriveName[0];
1162 Log("Will use '%C:' as volume mountpoint", DriveName[0]);
1163
1164 // It kind of blows, but we have to relinquish access to the physical drive
1165 // for VDS to be able to delete the partitions that reside on it...
1166 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
1167 CHECK_CLOSE_HANDLE(hDrive);
1168
1169 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
1170
1171 if (!VDS_DeleteAllPartitions(pPhyDrive->PhyDrive))
1172 {
1173 Log("Notice: Could not delete partitions: %u", GetLastError());
1174 }
1175
1176 Log("Deleting all partitions ......................... OK");
1177
1178 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
1179
1180 Log("Lock disk for write ............................. ");
1181 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
1182 if (hDrive == INVALID_HANDLE_VALUE)
1183 {
1184 Log("Failed to GetPhysicalHandle for write.");
1185 rc = 1;
1186 goto End;
1187 }
1188
1189 // clear first and last 2MB space
1190 pTmpBuf = malloc(SIZE_2MB);
1191 if (!pTmpBuf)
1192 {
1193 Log("Failed to alloc memory.");
1194 rc = 1;
1195 goto End;
1196 }
1197 memset(pTmpBuf, 0, SIZE_2MB);
1198
1199 SET_FILE_POS(512);
1200 bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB - 512, &dwSize, NULL);
1201 Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1202 if (!bRet)
1203 {
1204 rc = 1;
1205 goto End;
1206 }
1207
1208 SET_FILE_POS(pPhyDrive->SizeInBytes - SIZE_2MB);
1209 bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB, &dwSize, NULL);
1210 Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1211 if (!bRet)
1212 {
1213 rc = 1;
1214 goto End;
1215 }
1216
1217 SET_FILE_POS(0);
1218
1219 if (pPhyDrive->SizeInBytes > 2199023255552ULL)
1220 {
1221 VTOY_GPT_INFO *pGptInfo;
1222 VTOY_GPT_HDR BackupHead;
1223 LARGE_INTEGER liCurrentPosition;
1224
1225 pGptInfo = (VTOY_GPT_INFO *)pTmpBuf;
1226
1227 VentoyFillWholeGpt(pPhyDrive->SizeInBytes, pGptInfo);
1228
1229 SET_FILE_POS(pPhyDrive->SizeInBytes - 512);
1230 VentoyFillBackupGptHead(pGptInfo, &BackupHead);
1231 if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))
1232 {
1233 rc = 1;
1234 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1235 goto End;
1236 }
1237
1238 SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);
1239 if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))
1240 {
1241 rc = 1;
1242 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1243 goto End;
1244 }
1245
1246 SET_FILE_POS(0);
1247 if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))
1248 {
1249 rc = 1;
1250 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1251 goto End;
1252 }
1253
1254 Log("Write GPT Info OK ...");
1255 }
1256 else
1257 {
1258 bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
1259 Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1260 if (!bRet)
1261 {
1262 rc = 1;
1263 goto End;
1264 }
1265
1266 //clear boot code and partition table (reserved disk signature)
1267 memset(MBR.BootCode, 0, 440);
1268 memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl));
1269
1270 VentoyFillMBRLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl);
1271
1272 MBR.PartTbl[0].Active = 0x00; // bootable
1273 MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS
1274
1275 SET_FILE_POS(0);
1276 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
1277 Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1278 if (!bRet)
1279 {
1280 rc = 1;
1281 goto End;
1282 }
1283 }
1284
1285 Log("Clear Ventoy successfully finished");
1286
1287 //Refresh Drive Layout
1288 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
1289
1290 End:
1291
1292 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1293
1294 if (pTmpBuf)
1295 {
1296 free(pTmpBuf);
1297 }
1298
1299 if (rc == 0)
1300 {
1301 Log("Mounting Ventoy Partition ....................... ");
1302 Sleep(1000);
1303
1304 state = 0;
1305 memset(DriveLetters, 0, sizeof(DriveLetters));
1306 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1307 Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
1308
1309 for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
1310 {
1311 DriveName[0] = DriveLetters[i];
1312 Log("%s is ventoy part1, already mounted", DriveName);
1313 state = 1;
1314 }
1315
1316 if (state != 1)
1317 {
1318 Log("need to mount ventoy part1...");
1319 if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, 2048, DriveLetters, sizeof(DriveLetters), FALSE))
1320 {
1321 DriveName[0] = MountDrive;
1322 bRet = SetVolumeMountPointA(DriveName, DriveLetters);
1323 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
1324
1325 *pDrvLetter = MountDrive;
1326 }
1327 else
1328 {
1329 Log("Failed to find ventoy volume");
1330 }
1331 }
1332
1333 Log("OK\n");
1334 }
1335 else
1336 {
1337 FindProcessOccupyDisk(hDrive, pPhyDrive);
1338 }
1339
1340 CHECK_CLOSE_HANDLE(hDrive);
1341 return rc;
1342 }
1343
1344 int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
1345 {
1346 int i;
1347 int rc = 1;
1348 int Len = 0;
1349 int dataLen = 0;
1350 UINT size = 0;
1351 UINT segnum = 0;
1352 UINT32 chksum = 0;
1353 UINT64 data_offset = 0;
1354 UINT64 Part2StartSector = 0;
1355 UINT64 Part1StartSector = 0;
1356 UINT64 Part1SectorCount = 0;
1357 UINT8 *pData = NULL;
1358 UINT8 *pBkGptPartTbl = NULL;
1359 BYTE *ImgBuf = NULL;
1360 MBR_HEAD *pMBR = NULL;
1361 VTSI_FOOTER *pImgFooter = NULL;
1362 VTSI_SEGMENT *pSegment = NULL;
1363 VTOY_GPT_INFO *pGptInfo = NULL;
1364 VTOY_GPT_HDR *pBkGptHdr = NULL;
1365 FILE *fp = NULL;
1366
1367 Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",
1368 PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1369 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1370
1371 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1372
1373 size = SIZE_1MB + VENTOY_EFI_PART_SIZE + 33 * 512 + VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT) + sizeof(VTSI_FOOTER);
1374
1375 pData = (UINT8 *)malloc(size);
1376 if (!pData)
1377 {
1378 Log("malloc image buffer failed %d.", size);
1379 goto End;
1380 }
1381
1382 pImgFooter = (VTSI_FOOTER *)(pData + size - sizeof(VTSI_FOOTER));
1383 pSegment = (VTSI_SEGMENT *)((UINT8 *)pImgFooter - VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));
1384 memset(pImgFooter, 0, sizeof(VTSI_FOOTER));
1385 memset(pSegment, 0, VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));
1386
1387 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START);
1388
1389 Log("Writing Boot Image ............................. ");
1390 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
1391 {
1392 Log("Failed to read stage1 img");
1393 goto End;
1394 }
1395
1396 unxz(ImgBuf, Len, NULL, NULL, pData, &dataLen, unxz_error);
1397 SAFE_FREE(ImgBuf);
1398
1399 Log("decompress %s len:%d", VENTOY_FILE_STG1_IMG, dataLen);
1400
1401 if (PartStyle)
1402 {
1403 pData[500] = 35;//update blocklist
1404 memmove(pData + 34 * 512, pData, SIZE_1MB - 512 * 34);
1405 memset(pData, 0, 34 * 512);
1406
1407 pGptInfo = (VTOY_GPT_INFO *)pData;
1408 memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
1409 VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);
1410
1411 pBkGptPartTbl = pData + SIZE_1MB + VENTOY_EFI_PART_SIZE;
1412 memset(pBkGptPartTbl, 0, 33 * 512);
1413
1414 memcpy(pBkGptPartTbl, pGptInfo->PartTbl, 32 * 512);
1415 pBkGptHdr = (VTOY_GPT_HDR *)(pBkGptPartTbl + 32 * 512);
1416 VentoyFillBackupGptHead(pGptInfo, pBkGptHdr);
1417
1418 Part1StartSector = pGptInfo->PartTbl[0].StartLBA;
1419 Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;
1420 Part2StartSector = pGptInfo->PartTbl[1].StartLBA;
1421
1422 Log("Write GPT Info OK ...");
1423 }
1424 else
1425 {
1426 memmove(pData + 512, pData, SIZE_1MB - 512);
1427 memset(pData, 0, 512);
1428
1429 pMBR = (MBR_HEAD *)pData;
1430 VentoyFillMBR(pPhyDrive->SizeInBytes, pMBR, PartStyle);
1431 Part1StartSector = pMBR->PartTbl[0].StartSectorId;
1432 Part1SectorCount = pMBR->PartTbl[0].SectorCount;
1433 Part2StartSector = pMBR->PartTbl[1].StartSectorId;
1434
1435 Log("Write MBR OK ...");
1436 }
1437
1438 Log("Writing EFI part Image ............................. ");
1439 rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&ImgBuf, &Len);
1440 if (rc)
1441 {
1442 Log("Failed to read img file %p %u", ImgBuf, Len);
1443 goto End;
1444 }
1445
1446 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + 28);
1447 memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
1448 unxz(ImgBuf, Len, NULL, NULL, pData + SIZE_1MB, &dataLen, unxz_error);
1449 if (dataLen == Len)
1450 {
1451 Log("decompress finished success");
1452 g_part_img_buf[0] = pData + SIZE_1MB;
1453
1454 VentoyProcSecureBoot(g_SecureBoot);
1455 }
1456 else
1457 {
1458 Log("decompress finished failed");
1459 goto End;
1460 }
1461
1462 fopen_s(&fp, "VentoySparseImg.vtsi", "wb+");
1463 if (!fp)
1464 {
1465 Log("Failed to create Ventoy img file");
1466 goto End;
1467 }
1468
1469 Log("Writing stage1 data ............................. ");
1470
1471 fwrite(pData, 1, SIZE_1MB, fp);
1472
1473 pSegment[0].disk_start_sector = 0;
1474 pSegment[0].sector_num = SIZE_1MB / 512;
1475 pSegment[0].data_offset = data_offset;
1476 data_offset += pSegment[0].sector_num * 512;
1477
1478 disk_io_set_param(INVALID_HANDLE_VALUE, Part1StartSector + Part1SectorCount);// include the 2048 sector gap
1479 disk_io_set_imghook(fp, pSegment + 1, VTSI_IMG_MAX_SEG - 1, data_offset);
1480
1481 Log("Formatting part1 exFAT ...");
1482 if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
1483 {
1484 Log("FormatPart1exFAT failed.");
1485 disk_io_reset_imghook(&segnum, &data_offset);
1486 goto End;
1487 }
1488
1489 disk_io_reset_imghook(&segnum, &data_offset);
1490 segnum++;
1491
1492 Log("current segment number:%d dataoff:%ld", segnum, (long)data_offset);
1493
1494 //write data
1495 Log("Writing part2 data ............................. ");
1496 fwrite(pData + SIZE_1MB, 1, VENTOY_EFI_PART_SIZE, fp);
1497 pSegment[segnum].disk_start_sector = Part2StartSector;
1498 pSegment[segnum].sector_num = VENTOY_EFI_PART_SIZE / 512;
1499 pSegment[segnum].data_offset = data_offset;
1500 data_offset += pSegment[segnum].sector_num * 512;
1501 segnum++;
1502
1503 if (PartStyle)
1504 {
1505 Log("Writing backup gpt table ............................. ");
1506 fwrite(pBkGptPartTbl, 1, 33 * 512, fp);
1507 pSegment[segnum].disk_start_sector = pPhyDrive->SizeInBytes / 512 - 33;
1508 pSegment[segnum].sector_num = 33;
1509 pSegment[segnum].data_offset = data_offset;
1510 data_offset += pSegment[segnum].sector_num * 512;
1511 segnum++;
1512 }
1513
1514 Log("Writing segment metadata ............................. ");
1515
1516 for (i = 0; i < (int)segnum; i++)
1517 {
1518 Log("SEG[%d]: PhySector:%llu SectorNum:%llu DataOffset:%llu(sector:%llu)", i, pSegment[i].disk_start_sector, pSegment[i].sector_num,
1519 pSegment[i].data_offset, pSegment[i].data_offset / 512);
1520 }
1521
1522 dataLen = segnum * sizeof(VTSI_SEGMENT);
1523 fwrite(pSegment, 1, dataLen, fp);
1524
1525 if (dataLen % 512)
1526 {
1527 //pData + SIZE_1MB - 8192 is a temp data buffer with zero
1528 fwrite(pData + SIZE_1MB - 8192, 1, 512 - (dataLen % 512), fp);
1529 }
1530
1531 //Fill footer
1532 pImgFooter->magic = VTSI_IMG_MAGIC;
1533 pImgFooter->version = 1;
1534 pImgFooter->disk_size = pPhyDrive->SizeInBytes;
1535 memcpy(&pImgFooter->disk_signature, pPhyDrive->MBR.BootCode + 0x1b8, 4);
1536 pImgFooter->segment_num = segnum;
1537 pImgFooter->segment_offset = data_offset;
1538
1539 for (i = 0, chksum = 0; i < (int)(segnum * sizeof(VTSI_SEGMENT)); i++)
1540 {
1541 chksum += *((UINT8 *)pSegment + i);
1542 }
1543 pImgFooter->segment_chksum = ~chksum;
1544
1545 for (i = 0, chksum = 0; i < sizeof(VTSI_FOOTER); i++)
1546 {
1547 chksum += *((UINT8 *)pImgFooter + i);
1548 }
1549 pImgFooter->foot_chksum = ~chksum;
1550
1551 Log("Writing footer segnum(%u) segoffset(%llu) ......................", segnum, data_offset);
1552 Log("disk_size=%llu disk_signature=%lx segment_offset=%llu", pImgFooter->disk_size, pImgFooter->disk_signature, pImgFooter->segment_offset);
1553
1554 fwrite(pImgFooter, 1, sizeof(VTSI_FOOTER), fp);
1555 fclose(fp);
1556
1557 Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset + 512 + ((dataLen + 511) / 512 * 512));
1558
1559 rc = 0;
1560
1561 End:
1562
1563 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1564
1565 Log("retcode:%d\n", rc);
1566
1567 SAFE_FREE(pData);
1568 SAFE_FREE(ImgBuf);
1569
1570 return rc;
1571 }
1572
1573
1574 int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)
1575 {
1576 int i;
1577 int rc = 0;
1578 int state = 0;
1579 HANDLE hDrive;
1580 DWORD dwSize;
1581 BOOL bRet;
1582 CHAR MountDrive;
1583 CHAR DriveName[] = "?:\\";
1584 CHAR DriveLetters[MAX_PATH] = { 0 };
1585 MBR_HEAD MBR;
1586 VTOY_GPT_INFO *pGptInfo = NULL;
1587 UINT64 Part1StartSector = 0;
1588 UINT64 Part1SectorCount = 0;
1589 UINT64 Part2StartSector = 0;
1590
1591 Log("InstallVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId,
1592 PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1593 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1594
1595 if (PartStyle)
1596 {
1597 pGptInfo = malloc(sizeof(VTOY_GPT_INFO));
1598 memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
1599 }
1600
1601 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1602
1603 if (PartStyle)
1604 {
1605 VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);
1606 Part1StartSector = pGptInfo->PartTbl[0].StartLBA;
1607 Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;
1608 Part2StartSector = pGptInfo->PartTbl[1].StartLBA;
1609 }
1610 else
1611 {
1612 VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle);
1613 Part1StartSector = MBR.PartTbl[0].StartSectorId;
1614 Part1SectorCount = MBR.PartTbl[0].SectorCount;
1615 Part2StartSector = MBR.PartTbl[1].StartSectorId;
1616 }
1617
1618 Log("Lock disk for clean ............................. ");
1619
1620 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
1621 if (hDrive == INVALID_HANDLE_VALUE)
1622 {
1623 Log("Failed to open physical disk");
1624 free(pGptInfo);
1625 return 1;
1626 }
1627
1628 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1629
1630 if (DriveLetters[0] == 0)
1631 {
1632 Log("No drive letter was assigned...");
1633 DriveName[0] = GetFirstUnusedDriveLetter();
1634 Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
1635 }
1636 else
1637 {
1638 // Unmount all mounted volumes that belong to this drive
1639 // Do it in reverse so that we always end on the first volume letter
1640 for (i = (int)strlen(DriveLetters); i > 0; i--)
1641 {
1642 DriveName[0] = DriveLetters[i - 1];
1643 bRet = DeleteVolumeMountPointA(DriveName);
1644 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
1645 }
1646 }
1647
1648 MountDrive = DriveName[0];
1649 Log("Will use '%C:' as volume mountpoint", DriveName[0]);
1650
1651 // It kind of blows, but we have to relinquish access to the physical drive
1652 // for VDS to be able to delete the partitions that reside on it...
1653 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
1654 CHECK_CLOSE_HANDLE(hDrive);
1655
1656 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
1657
1658 if (!VDS_DeleteAllPartitions(pPhyDrive->PhyDrive))
1659 {
1660 Log("Notice: Could not delete partitions: %u", GetLastError());
1661 }
1662
1663 Log("Deleting all partitions ......................... OK");
1664
1665 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
1666
1667 Log("Lock disk for write ............................. ");
1668 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
1669 if (hDrive == INVALID_HANDLE_VALUE)
1670 {
1671 Log("Failed to GetPhysicalHandle for write.");
1672 rc = 1;
1673 goto End;
1674 }
1675
1676 //Refresh Drive Layout
1677 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
1678
1679 disk_io_set_param(hDrive, Part1StartSector + Part1SectorCount);// include the 2048 sector gap
1680
1681 PROGRESS_BAR_SET_POS(PT_FORMAT_PART1);
1682
1683 if (PartStyle == 1 && pPhyDrive->PartStyle == 0)
1684 {
1685 Log("Wait for format part1 ...");
1686 Sleep(1000 * 5);
1687 }
1688
1689 Log("Formatting part1 exFAT ...");
1690 if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
1691 {
1692 Log("FormatPart1exFAT failed.");
1693 rc = 1;
1694 goto End;
1695 }
1696
1697 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
1698 Log("Writing part2 FAT img ...");
1699
1700 if (0 != FormatPart2Fat(hDrive, Part2StartSector))
1701 {
1702 Log("FormatPart2Fat failed.");
1703 rc = 1;
1704 goto End;
1705 }
1706
1707 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);
1708 Log("Writing Boot Image ............................. ");
1709 if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0)
1710 {
1711 Log("WriteGrubStage1ToPhyDrive failed.");
1712 rc = 1;
1713 goto End;
1714 }
1715
1716 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);
1717 Log("Writing Partition Table ........................ ");
1718 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
1719
1720 if (PartStyle)
1721 {
1722 VTOY_GPT_HDR BackupHead;
1723 LARGE_INTEGER liCurrentPosition;
1724
1725 SET_FILE_POS(pPhyDrive->SizeInBytes - 512);
1726 VentoyFillBackupGptHead(pGptInfo, &BackupHead);
1727 if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))
1728 {
1729 rc = 1;
1730 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1731 goto End;
1732 }
1733
1734 SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);
1735 if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))
1736 {
1737 rc = 1;
1738 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1739 goto End;
1740 }
1741
1742 SET_FILE_POS(0);
1743 if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))
1744 {
1745 rc = 1;
1746 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1747 goto End;
1748 }
1749
1750 Log("Write GPT Info OK ...");
1751 memcpy(&(pPhyDrive->MBR), &(pGptInfo->MBR), 512);
1752 }
1753 else
1754 {
1755 if (!WriteFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL))
1756 {
1757 rc = 1;
1758 Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize, GetLastError());
1759 goto End;
1760 }
1761 Log("Write MBR OK ...");
1762 memcpy(&(pPhyDrive->MBR), &MBR, 512);
1763 }
1764
1765 //Refresh Drive Layout
1766 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
1767
1768 End:
1769
1770 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1771
1772 if (rc == 0)
1773 {
1774 Log("Mounting Ventoy Partition ....................... ");
1775 Sleep(1000);
1776
1777 state = 0;
1778 memset(DriveLetters, 0, sizeof(DriveLetters));
1779 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1780 Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
1781
1782 for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
1783 {
1784 DriveName[0] = DriveLetters[i];
1785 if (IsVentoyLogicalDrive(DriveName[0]))
1786 {
1787 Log("%s is ventoy part2, delete mountpoint", DriveName);
1788 DeleteVolumeMountPointA(DriveName);
1789 }
1790 else
1791 {
1792 Log("%s is ventoy part1, already mounted", DriveName);
1793 state = 1;
1794 }
1795 }
1796
1797 if (state != 1)
1798 {
1799 Log("need to mount ventoy part1...");
1800
1801 if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, Part1StartSector, DriveLetters, sizeof(DriveLetters), FALSE))
1802 {
1803 DriveName[0] = MountDrive;
1804 bRet = SetVolumeMountPointA(DriveName, DriveLetters);
1805 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
1806 }
1807 else
1808 {
1809 Log("Failed to find ventoy volume");
1810 }
1811 }
1812 Log("OK\n");
1813 }
1814 else
1815 {
1816 FindProcessOccupyDisk(hDrive, pPhyDrive);
1817 }
1818
1819 if (pGptInfo)
1820 {
1821 free(pGptInfo);
1822 }
1823
1824 CHECK_CLOSE_HANDLE(hDrive);
1825 return rc;
1826 }
1827
1828
1829 int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
1830 {
1831 int i;
1832 int rc = 0;
1833 int MaxRetry = 3;
1834 BOOL ForceMBR = FALSE;
1835 BOOL Esp2Basic = FALSE;
1836 HANDLE hVolume;
1837 HANDLE hDrive;
1838 DWORD Status;
1839 DWORD dwSize;
1840 BOOL bRet;
1841 CHAR DriveName[] = "?:\\";
1842 CHAR DriveLetters[MAX_PATH] = { 0 };
1843 UINT64 StartSector;
1844 UINT64 ReservedMB = 0;
1845 MBR_HEAD BootImg;
1846 MBR_HEAD MBR;
1847 VTOY_GPT_INFO *pGptInfo = NULL;
1848 UINT8 ReservedData[4096];
1849
1850 Log("UpdateVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId,
1851 pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1852 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1853
1854 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1855
1856 Log("Lock disk for umount ............................ ");
1857
1858 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
1859 if (hDrive == INVALID_HANDLE_VALUE)
1860 {
1861 Log("Failed to open physical disk");
1862 return 1;
1863 }
1864
1865 if (pPhyDrive->PartStyle)
1866 {
1867 pGptInfo = malloc(sizeof(VTOY_GPT_INFO));
1868 if (!pGptInfo)
1869 {
1870 return 1;
1871 }
1872
1873 memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
1874
1875 // Read GPT Info
1876 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
1877 ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL);
1878
1879 //MBR will be used to compare with local boot image
1880 memcpy(&MBR, &pGptInfo->MBR, sizeof(MBR_HEAD));
1881
1882 StartSector = pGptInfo->PartTbl[1].StartLBA;
1883 Log("GPT StartSector in PartTbl:%llu", (ULONGLONG)StartSector);
1884
1885 ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512) - 33) / 2048;
1886 Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);
1887 }
1888 else
1889 {
1890 // Read MBR
1891 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
1892 ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
1893
1894 StartSector = MBR.PartTbl[1].StartSectorId;
1895 Log("MBR StartSector in PartTbl:%llu", (ULONGLONG)StartSector);
1896
1897 ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512)) / 2048;
1898 Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);
1899 }
1900
1901 //Read Reserved Data
1902 SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);
1903 ReadFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);
1904
1905 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1906
1907 if (DriveLetters[0] == 0)
1908 {
1909 Log("No drive letter was assigned...");
1910 }
1911 else
1912 {
1913 // Unmount all mounted volumes that belong to this drive
1914 // Do it in reverse so that we always end on the first volume letter
1915 for (i = (int)strlen(DriveLetters); i > 0; i--)
1916 {
1917 DriveName[0] = DriveLetters[i - 1];
1918 if (IsVentoyLogicalDrive(DriveName[0]))
1919 {
1920 Log("%s is ventoy logical drive", DriveName);
1921 bRet = DeleteVolumeMountPointA(DriveName);
1922 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, LASTERR);
1923 break;
1924 }
1925 }
1926 }
1927
1928 // It kind of blows, but we have to relinquish access to the physical drive
1929 // for VDS to be able to delete the partitions that reside on it...
1930 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
1931 CHECK_CLOSE_HANDLE(hDrive);
1932
1933 if (pPhyDrive->PartStyle == 1)
1934 {
1935 Log("TryId=%d EFI GPT partition type is 0x%llx", TryId, pPhyDrive->Part2GPTAttr);
1936
1937 if ((TryId == 1 && (pPhyDrive->Part2GPTAttr >> 56) == 0xC0) || TryId == 2)
1938 {
1939 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
1940 Log("Change GPT partition type to ESP");
1941
1942 if (VDS_ChangeVtoyEFI2ESP(pPhyDrive->PhyDrive, StartSector * 512))
1943 {
1944 Esp2Basic = TRUE;
1945 Sleep(1000);
1946 }
1947 }
1948 }
1949
1950 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
1951
1952 Log("Lock disk for update ............................ ");
1953 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
1954 if (hDrive == INVALID_HANDLE_VALUE)
1955 {
1956 Log("Failed to GetPhysicalHandle for write.");
1957 rc = 1;
1958 goto End;
1959 }
1960
1961 PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME);
1962
1963 Log("Lock volume for update .......................... ");
1964 hVolume = INVALID_HANDLE_VALUE;
1965
1966 //If we change VTOYEFI to ESP, it can not have s volume name, so don't try to get it.
1967 if (Esp2Basic)
1968 {
1969 Status = ERROR_NOT_FOUND;
1970 }
1971 else
1972 {
1973 for (i = 0; i < MaxRetry; i++)
1974 {
1975 Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, StartSector, DriveLetters, sizeof(DriveLetters), TRUE);
1976 if (ERROR_SUCCESS == Status)
1977 {
1978 break;
1979 }
1980 else
1981 {
1982 Log("==== Volume not found, wait and retry %d... ====", i);
1983 Sleep(2);
1984 }
1985 }
1986 }
1987
1988 if (ERROR_SUCCESS == Status)
1989 {
1990 Log("Now lock and dismount volume <%s>", DriveLetters);
1991
1992 for (i = 0; i < MaxRetry; i++)
1993 {
1994 hVolume = CreateFileA(DriveLetters,
1995 GENERIC_READ | GENERIC_WRITE,
1996 FILE_SHARE_READ,
1997 NULL,
1998 OPEN_EXISTING,
1999 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
2000 NULL);
2001
2002 if (hVolume == INVALID_HANDLE_VALUE)
2003 {
2004 Log("Failed to create file volume, errcode:%u, wait and retry ...", LASTERR);
2005 Sleep(2000);
2006 }
2007 else
2008 {
2009 break;
2010 }
2011 }
2012
2013 if (hVolume == INVALID_HANDLE_VALUE)
2014 {
2015 Log("Failed to create file volume, errcode:%u", LASTERR);
2016 }
2017 else
2018 {
2019 bRet = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2020 Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
2021
2022 bRet = DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2023 Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet, LASTERR);
2024 }
2025 }
2026 else if (ERROR_NOT_FOUND == Status)
2027 {
2028 Log("Volume not found, maybe not supported");
2029 }
2030 else
2031 {
2032 rc = 1;
2033 goto End;
2034 }
2035
2036 if (!TryWritePart2(hDrive, StartSector))
2037 {
2038 if (pPhyDrive->PartStyle == 0)
2039 {
2040 ForceMBR = TRUE;
2041
2042 Log("Try write failed, now delete partition 2 for MBR...");
2043 CHECK_CLOSE_HANDLE(hDrive);
2044
2045 Log("Now delete partition 2...");
2046 VDS_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive);
2047
2048 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2049 if (hDrive == INVALID_HANDLE_VALUE)
2050 {
2051 Log("Failed to GetPhysicalHandle for write.");
2052 rc = 1;
2053 goto End;
2054 }
2055 }
2056 else
2057 {
2058 Log("TryWritePart2 failed ....");
2059 rc = 1;
2060 goto End;
2061 }
2062 }
2063
2064 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
2065
2066 Log("Write Ventoy to disk ............................ ");
2067 if (0 != FormatPart2Fat(hDrive, StartSector))
2068 {
2069 rc = 1;
2070 goto End;
2071 }
2072
2073 if (hVolume != INVALID_HANDLE_VALUE)
2074 {
2075 bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2076 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
2077 CHECK_CLOSE_HANDLE(hVolume);
2078 }
2079
2080 Log("Updating Boot Image ............................. ");
2081 if (WriteGrubStage1ToPhyDrive(hDrive, pPhyDrive->PartStyle) != 0)
2082 {
2083 rc = 1;
2084 goto End;
2085 }
2086
2087 //write reserved data
2088 SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);
2089 bRet = WriteFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);
2090 Log("Write resv data ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
2091
2092 // Boot Image
2093 VentoyGetLocalBootImg(&BootImg);
2094
2095 // Use Old UUID
2096 memcpy(BootImg.BootCode + 0x180, MBR.BootCode + 0x180, 16);
2097 if (pPhyDrive->PartStyle)
2098 {
2099 BootImg.BootCode[92] = 0x22;
2100 }
2101
2102 if (ForceMBR == FALSE && memcmp(BootImg.BootCode, MBR.BootCode, 440) == 0)
2103 {
2104 Log("Boot image has no difference, no need to write.");
2105 }
2106 else
2107 {
2108 Log("Boot image need to write %u.", ForceMBR);
2109
2110 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2111
2112 memcpy(MBR.BootCode, BootImg.BootCode, 440);
2113 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
2114 Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
2115 }
2116
2117 if (pPhyDrive->PartStyle == 0)
2118 {
2119 if (0x00 == MBR.PartTbl[0].Active && 0x80 == MBR.PartTbl[1].Active)
2120 {
2121 Log("Need to chage 1st partition active and 2nd partition inactive.");
2122
2123 MBR.PartTbl[0].Active = 0x80;
2124 MBR.PartTbl[1].Active = 0x00;
2125
2126 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2127 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
2128 Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
2129 }
2130 }
2131
2132 //Refresh Drive Layout
2133 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
2134
2135 End:
2136
2137 if (rc == 0)
2138 {
2139 Log("OK");
2140 }
2141 else
2142 {
2143 FindProcessOccupyDisk(hDrive, pPhyDrive);
2144 }
2145
2146 CHECK_CLOSE_HANDLE(hDrive);
2147
2148 if (Esp2Basic)
2149 {
2150 Log("Recover GPT partition type to basic");
2151 VDS_ChangeVtoyEFI2Basic(pPhyDrive->PhyDrive, StartSector * 512);
2152 }
2153
2154 if (pGptInfo)
2155 {
2156 free(pGptInfo);
2157 }
2158
2159 return rc;
2160 }
2161
2162