1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 * Copyright (c) 2011-2020, Pete Batard <pete@akeo.ie>
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.
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.
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/>.
29 #include "Ventoy2Disk.h"
30 #include "fat_filelib.h"
32 #include "DiskService.h"
34 static int g_backup_bin_index
= 0;
36 static DWORD
GetVentoyVolumeName(int PhyDrive
, UINT64 StartSectorId
, CHAR
*NameBuf
, UINT32 BufLen
, BOOL DelSlash
)
44 DWORD Status
= ERROR_NOT_FOUND
;
45 DISK_EXTENT
*pExtents
= NULL
;
46 CHAR VolumeName
[MAX_PATH
] = { 0 };
47 VOLUME_DISK_EXTENTS DiskExtents
;
49 PartOffset
= 512ULL * StartSectorId
;
51 Log("GetVentoyVolumeName PhyDrive %d SectorStart:%llu PartOffset:%llu", PhyDrive
, (ULONGLONG
)StartSectorId
, (ULONGLONG
)PartOffset
);
53 hVolume
= FindFirstVolumeA(VolumeName
, sizeof(VolumeName
));
54 if (hVolume
== INVALID_HANDLE_VALUE
)
61 len
= strlen(VolumeName
);
62 Log("Find volume:%s", VolumeName
);
64 VolumeName
[len
- 1] = 0;
66 hDrive
= CreateFileA(VolumeName
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
67 if (hDrive
== INVALID_HANDLE_VALUE
)
72 bRet
= DeviceIoControl(hDrive
,
73 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
77 (DWORD
)(sizeof(DiskExtents
)),
81 Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet
, LASTERR
);
82 Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents
.NumberOfDiskExtents
, DiskExtents
.Extents
[0].DiskNumber
);
84 if (bRet
&& DiskExtents
.NumberOfDiskExtents
== 1)
86 pExtents
= DiskExtents
.Extents
;
88 Log("This volume DiskNumber:%u offset:%llu", pExtents
->DiskNumber
, (ULONGLONG
)pExtents
->StartingOffset
.QuadPart
);
89 if ((int)pExtents
->DiskNumber
== PhyDrive
&& pExtents
->StartingOffset
.QuadPart
== PartOffset
)
91 Log("This volume match");
95 VolumeName
[len
- 1] = '\\';
98 sprintf_s(NameBuf
, BufLen
, "%s", VolumeName
);
99 Status
= ERROR_SUCCESS
;
106 } while (FindNextVolumeA(hVolume
, VolumeName
, sizeof(VolumeName
)));
108 FindVolumeClose(hVolume
);
110 Log("GetVentoyVolumeName return %u", Status
);
114 static int GetLettersBelongPhyDrive(int PhyDrive
, char *DriveLetters
, size_t Length
)
119 CHAR
*StringBuf
= NULL
;
121 DataSize
= GetLogicalDriveStringsA(0, NULL
);
122 StringBuf
= (CHAR
*)malloc(DataSize
+ 1);
123 if (StringBuf
== NULL
)
128 GetLogicalDriveStringsA(DataSize
, StringBuf
);
130 for (Pos
= StringBuf
; *Pos
; Pos
+= strlen(Pos
) + 1)
132 if (n
< (int)Length
&& PhyDrive
== GetPhyDriveByLogicalDrive(Pos
[0]))
134 Log("%C: is belong to phydrive%d", Pos
[0], PhyDrive
);
135 DriveLetters
[n
++] = Pos
[0];
143 static HANDLE
GetPhysicalHandle(int Drive
, BOOLEAN bLockDrive
, BOOLEAN bWriteAccess
, BOOLEAN bWriteShare
)
149 HANDLE hDrive
= INVALID_HANDLE_VALUE
;
151 CHAR DevPath
[MAX_PATH
] = { 0 };
153 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", Drive
);
155 if (0 == QueryDosDeviceA(PhyDrive
+ 4, DevPath
, sizeof(DevPath
)))
157 Log("QueryDosDeviceA failed error:%u", GetLastError());
158 strcpy_s(DevPath
, sizeof(DevPath
), "???");
162 Log("QueryDosDeviceA success %s", DevPath
);
165 for (i
= 0; i
< DRIVE_ACCESS_RETRIES
; i
++)
167 // Try without FILE_SHARE_WRITE (unless specifically requested) so that
168 // we won't be bothered by the OS or other apps when we set up our data.
169 // However this means we might have to wait for an access gap...
170 // We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is
171 // required for enumeration.
172 hDrive
= CreateFileA(PhyDrive
,
173 GENERIC_READ
| (bWriteAccess
? GENERIC_WRITE
: 0),
174 FILE_SHARE_READ
| (bWriteShare
? FILE_SHARE_WRITE
: 0),
177 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_NO_BUFFERING
| FILE_FLAG_WRITE_THROUGH
,
180 LastError
= GetLastError();
181 Log("[%d] CreateFileA %s code:%u %p", i
, PhyDrive
, LastError
, hDrive
);
183 if (hDrive
!= INVALID_HANDLE_VALUE
)
188 if ((LastError
!= ERROR_SHARING_VIOLATION
) && (LastError
!= ERROR_ACCESS_DENIED
))
195 Log("Waiting for access on %s [%s]...", PhyDrive
, DevPath
);
197 else if (!bWriteShare
&& (i
> DRIVE_ACCESS_RETRIES
/ 3))
199 // If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE...
200 Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");
203 // Try to report the process that is locking the drive
204 // We also use bit 6 as a flag to indicate that SearchProcess was called.
205 //access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40;
208 Sleep(DRIVE_ACCESS_TIMEOUT
/ DRIVE_ACCESS_RETRIES
);
211 if (hDrive
== INVALID_HANDLE_VALUE
)
213 Log("Could not open %s %u", PhyDrive
, LASTERR
);
219 Log("Opened %s for %s write access", PhyDrive
, bWriteShare
? "shared" : "exclusive");
224 if (DeviceIoControl(hDrive
, FSCTL_ALLOW_EXTENDED_DASD_IO
, NULL
, 0, NULL
, 0, &dwSize
, NULL
))
226 Log("I/O boundary checks disabled");
229 EndTime
= GetTickCount64() + DRIVE_ACCESS_TIMEOUT
;
232 if (DeviceIoControl(hDrive
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
))
234 Log("FSCTL_LOCK_VOLUME success");
237 Sleep(DRIVE_ACCESS_TIMEOUT
/ DRIVE_ACCESS_RETRIES
);
238 } while (GetTickCount64() < EndTime
);
240 // If we reached this section, either we didn't manage to get a lock or the user cancelled
241 Log("Could not lock access to %s %u", PhyDrive
, LASTERR
);
243 // See if we can report the processes are accessing the drive
244 //if (!IS_ERROR(FormatStatus) && (access_mask == 0))
245 // access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE);
246 // Try to continue if the only access rights we saw were for read-only
247 //if ((access_mask & 0x07) != 0x01)
248 // safe_closehandle(hDrive);
250 CHECK_CLOSE_HANDLE(hDrive
);
255 if (hDrive
== INVALID_HANDLE_VALUE
)
257 Log("Can get handle of %s, maybe some process control it.", DevPath
);
263 int GetPhyDriveByLogicalDrive(int DriveLetter
)
268 VOLUME_DISK_EXTENTS DiskExtents
;
271 safe_sprintf(PhyPath
, "\\\\.\\%C:", (CHAR
)DriveLetter
);
273 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
274 if (Handle
== INVALID_HANDLE_VALUE
)
276 Log("Could not open the disk<%s>, error:%u", PhyPath
, LASTERR
);
280 Ret
= DeviceIoControl(Handle
,
281 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
285 (DWORD
)(sizeof(DiskExtents
)),
289 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
291 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath
, LASTERR
);
292 CHECK_CLOSE_HANDLE(Handle
);
295 CHECK_CLOSE_HANDLE(Handle
);
297 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
299 DiskExtents
.Extents
[0].DiskNumber
,
300 DiskExtents
.Extents
[0].StartingOffset
.QuadPart
,
301 DiskExtents
.Extents
[0].ExtentLength
.QuadPart
304 return (int)DiskExtents
.Extents
[0].DiskNumber
;
307 int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO
*pDriveList
, DWORD
*pDriveCount
)
315 DWORD DriveCount
= 0;
316 HANDLE Handle
= INVALID_HANDLE_VALUE
;
318 PHY_DRIVE_INFO
*CurDrive
= pDriveList
;
319 GET_LENGTH_INFORMATION LengthInfo
;
320 STORAGE_PROPERTY_QUERY Query
;
321 STORAGE_DESCRIPTOR_HEADER DevDescHeader
;
322 STORAGE_DEVICE_DESCRIPTOR
*pDevDesc
;
323 int PhyDriveId
[VENTOY_MAX_PHY_DRIVE
];
325 Count
= GetPhysicalDriveCount();
327 for (i
= 0; i
< Count
&& i
< VENTOY_MAX_PHY_DRIVE
; i
++)
332 dwBytes
= GetLogicalDrives();
333 Log("Logical Drives: 0x%x", dwBytes
);
338 id
= GetPhyDriveByLogicalDrive(Letter
);
339 Log("%C --> %d", Letter
, id
);
342 for (i
= 0; i
< Count
; i
++)
344 if (PhyDriveId
[i
] == id
)
352 Log("Add phy%d to list", i
);
353 PhyDriveId
[Count
] = id
;
363 for (i
= 0; i
< Count
&& DriveCount
< VENTOY_MAX_PHY_DRIVE
; i
++)
365 CHECK_CLOSE_HANDLE(Handle
);
367 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", PhyDriveId
[i
]);
368 Handle
= CreateFileA(PhyDrive
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
369 Log("Create file Handle:%p %s status:%u", Handle
, PhyDrive
, LASTERR
);
371 if (Handle
== INVALID_HANDLE_VALUE
)
376 bRet
= DeviceIoControl(Handle
,
377 IOCTL_DISK_GET_LENGTH_INFO
, NULL
,
385 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR
);
389 Log("PHYSICALDRIVE%d size %llu bytes", i
, (ULONGLONG
)LengthInfo
.Length
.QuadPart
);
391 Query
.PropertyId
= StorageDeviceProperty
;
392 Query
.QueryType
= PropertyStandardQuery
;
394 bRet
= DeviceIoControl(Handle
,
395 IOCTL_STORAGE_QUERY_PROPERTY
,
399 sizeof(STORAGE_DESCRIPTOR_HEADER
),
404 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR
, dwBytes
);
408 if (DevDescHeader
.Size
< sizeof(STORAGE_DEVICE_DESCRIPTOR
))
410 Log("Invalid DevDescHeader.Size:%u", DevDescHeader
.Size
);
414 pDevDesc
= (STORAGE_DEVICE_DESCRIPTOR
*)malloc(DevDescHeader
.Size
);
417 Log("failed to malloc error:%u len:%u", LASTERR
, DevDescHeader
.Size
);
421 bRet
= DeviceIoControl(Handle
,
422 IOCTL_STORAGE_QUERY_PROPERTY
,
431 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR
, dwBytes
);
436 CurDrive
->PhyDrive
= i
;
437 CurDrive
->SizeInBytes
= LengthInfo
.Length
.QuadPart
;
438 CurDrive
->DeviceType
= pDevDesc
->DeviceType
;
439 CurDrive
->RemovableMedia
= pDevDesc
->RemovableMedia
;
440 CurDrive
->BusType
= pDevDesc
->BusType
;
442 if (pDevDesc
->VendorIdOffset
)
444 safe_strcpy(CurDrive
->VendorId
, (char *)pDevDesc
+ pDevDesc
->VendorIdOffset
);
445 TrimString(CurDrive
->VendorId
);
448 if (pDevDesc
->ProductIdOffset
)
450 safe_strcpy(CurDrive
->ProductId
, (char *)pDevDesc
+ pDevDesc
->ProductIdOffset
);
451 TrimString(CurDrive
->ProductId
);
454 if (pDevDesc
->ProductRevisionOffset
)
456 safe_strcpy(CurDrive
->ProductRev
, (char *)pDevDesc
+ pDevDesc
->ProductRevisionOffset
);
457 TrimString(CurDrive
->ProductRev
);
460 if (pDevDesc
->SerialNumberOffset
)
462 safe_strcpy(CurDrive
->SerialNumber
, (char *)pDevDesc
+ pDevDesc
->SerialNumberOffset
);
463 TrimString(CurDrive
->SerialNumber
);
471 CHECK_CLOSE_HANDLE(Handle
);
474 for (i
= 0, CurDrive
= pDriveList
; i
< (int)DriveCount
; i
++, CurDrive
++)
476 Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
477 CurDrive
->PhyDrive
, GetBusTypeString(CurDrive
->BusType
), CurDrive
->RemovableMedia
,
478 GetHumanReadableGBSize(CurDrive
->SizeInBytes
), CurDrive
->SizeInBytes
,
479 CurDrive
->VendorId
, CurDrive
->ProductId
);
482 *pDriveCount
= DriveCount
;
488 static HANDLE g_FatPhyDrive
;
489 static UINT64 g_Part2StartSec
;
490 static int GetVentoyVersionFromFatFile(CHAR
*VerBuf
, size_t BufLen
)
497 flfile
= fl_fopen("/grub/grub.cfg", "rb");
500 fl_fseek(flfile
, 0, SEEK_END
);
501 size
= (int)fl_ftell(flfile
);
503 fl_fseek(flfile
, 0, SEEK_SET
);
505 buf
= (char *)malloc(size
+ 1);
508 fl_fread(buf
, 1, size
, flfile
);
512 sprintf_s(VerBuf
, BufLen
, "%s", ParseVentoyVersionFromString(buf
));
522 static int VentoyFatDiskRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
527 LARGE_INTEGER liCurrentPosition
;
529 liCurrentPosition
.QuadPart
= Sector
+ g_Part2StartSec
;
530 liCurrentPosition
.QuadPart
*= 512;
531 SetFilePointerEx(g_FatPhyDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
533 ReadSize
= (DWORD
)(SectorCount
* 512);
535 bRet
= ReadFile(g_FatPhyDrive
, Buffer
, ReadSize
, &dwSize
, NULL
);
536 if (bRet
== FALSE
|| dwSize
!= ReadSize
)
538 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet
, ReadSize
, dwSize
, LASTERR
);
545 int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO
*pDriveInfo
, UINT64 Part2StartSector
, CHAR
*VerBuf
, size_t BufLen
, BOOL
*pSecureBoot
)
551 hDrive
= GetPhysicalHandle(pDriveInfo
->PhyDrive
, FALSE
, FALSE
, FALSE
);
552 if (hDrive
== INVALID_HANDLE_VALUE
)
557 g_FatPhyDrive
= hDrive
;
558 g_Part2StartSec
= Part2StartSector
;
560 Log("Parse FAT fs...");
564 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
566 Log("attach media success...");
567 rc
= GetVentoyVersionFromFatFile(VerBuf
, BufLen
);
571 Log("attach media failed...");
575 Log("GetVentoyVerInPhyDrive rc=%d...", rc
);
578 Log("VentoyVerInPhyDrive %d is <%s>...", pDriveInfo
->PhyDrive
, VerBuf
);
580 flfile
= fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
590 CHECK_CLOSE_HANDLE(hDrive
);
599 static unsigned int g_disk_unxz_len
= 0;
600 static BYTE
*g_part_img_pos
= NULL
;
601 static BYTE
*g_part_img_buf
[VENTOY_EFI_PART_SIZE
/ SIZE_1MB
];
604 static int VentoyFatMemRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
610 for (i
= 0; i
< SectorCount
; i
++)
612 offset
= (Sector
+ i
) * 512;
614 if (g_part_img_buf
[1] == NULL
)
616 MbBuf
= g_part_img_buf
[0] + offset
;
617 memcpy(Buffer
+ i
* 512, MbBuf
, 512);
621 MbBuf
= g_part_img_buf
[offset
/ SIZE_1MB
];
622 memcpy(Buffer
+ i
* 512, MbBuf
+ (offset
% SIZE_1MB
), 512);
630 static int VentoyFatMemWrite(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
636 for (i
= 0; i
< SectorCount
; i
++)
638 offset
= (Sector
+ i
) * 512;
640 if (g_part_img_buf
[1] == NULL
)
642 MbBuf
= g_part_img_buf
[0] + offset
;
643 memcpy(MbBuf
, Buffer
+ i
* 512, 512);
647 MbBuf
= g_part_img_buf
[offset
/ SIZE_1MB
];
648 memcpy(MbBuf
+ (offset
% SIZE_1MB
), Buffer
+ i
* 512, 512);
655 int VentoyProcSecureBoot(BOOL SecureBoot
)
659 char *filebuf
= NULL
;
662 Log("VentoyProcSecureBoot %d ...", SecureBoot
);
666 Log("Secure boot is enabled ...");
672 if (0 == fl_attach_media(VentoyFatMemRead
, VentoyFatMemWrite
))
674 file
= fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
675 Log("Open ventoy efi file %p ", file
);
678 fl_fseek(file
, 0, SEEK_END
);
679 size
= (int)fl_ftell(file
);
680 fl_fseek(file
, 0, SEEK_SET
);
682 Log("ventoy efi file size %d ...", size
);
684 filebuf
= (char *)malloc(size
);
687 fl_fread(filebuf
, 1, size
, file
);
692 Log("Now delete all efi files ...");
693 fl_remove("/EFI/BOOT/BOOTX64.EFI");
694 fl_remove("/EFI/BOOT/grubx64.efi");
695 fl_remove("/EFI/BOOT/grubx64_real.efi");
696 fl_remove("/EFI/BOOT/MokManager.efi");
697 fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
699 file
= fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
700 Log("Open bootx64 efi file %p ", file
);
705 fl_fwrite(filebuf
, 1, size
, file
);
718 file
= fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");
719 Log("Open ventoy efi file %p ", file
);
722 fl_fseek(file
, 0, SEEK_END
);
723 size
= (int)fl_ftell(file
);
724 fl_fseek(file
, 0, SEEK_SET
);
726 Log("ventoy efi file size %d ...", size
);
728 filebuf
= (char *)malloc(size
);
731 fl_fread(filebuf
, 1, size
, file
);
736 Log("Now delete all efi files ...");
737 fl_remove("/EFI/BOOT/BOOTIA32.EFI");
738 fl_remove("/EFI/BOOT/grubia32.efi");
739 fl_remove("/EFI/BOOT/grubia32_real.efi");
740 fl_remove("/EFI/BOOT/mmia32.efi");
742 file
= fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");
743 Log("Open bootia32 efi file %p ", file
);
748 fl_fwrite(filebuf
, 1, size
, file
);
774 static int disk_xz_flush(void *src
, unsigned int size
)
777 BYTE
*buf
= (BYTE
*)src
;
779 for (i
= 0; i
< size
; i
++)
781 *g_part_img_pos
= *buf
++;
784 if ((g_disk_unxz_len
% SIZE_1MB
) == 0)
786 g_part_img_pos
= g_part_img_buf
[g_disk_unxz_len
/ SIZE_1MB
];
797 static void unxz_error(char *x
)
802 static BOOL
TryWritePart2(HANDLE hDrive
, UINT64 StartSectorId
)
805 DWORD TrySize
= 16 * 1024;
808 unsigned char *data
= NULL
;
809 LARGE_INTEGER liCurrentPosition
;
811 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
812 SetFilePointerEx(hDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
814 Buffer
= malloc(TrySize
);
816 bRet
= WriteFile(hDrive
, Buffer
, TrySize
, &dwSize
, NULL
);
820 Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
822 if (bRet
&& dwSize
== TrySize
)
830 static int FormatPart2Fat(HANDLE hDrive
, UINT64 StartSectorId
)
837 int Pos
= PT_WRITE_VENTOY_START
;
840 unsigned char *data
= NULL
;
841 LARGE_INTEGER liCurrentPosition
;
842 LARGE_INTEGER liNewPosition
;
843 BYTE
*CheckBuf
= NULL
;
845 Log("FormatPart2Fat %llu...", StartSectorId
);
847 CheckBuf
= malloc(SIZE_1MB
);
850 Log("Failed to malloc check buf");
854 rc
= ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG
, 0, (void **)&data
, &len
);
857 Log("Failed to read img file %p %u", data
, len
);
862 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
863 SetFilePointerEx(hDrive
, liCurrentPosition
, &liNewPosition
, FILE_BEGIN
);
865 memset(g_part_img_buf
, 0, sizeof(g_part_img_buf
));
867 g_part_img_buf
[0] = (BYTE
*)malloc(VENTOY_EFI_PART_SIZE
);
868 if (g_part_img_buf
[0])
870 Log("Malloc whole img buffer success, now decompress ...");
871 unxz(data
, len
, NULL
, NULL
, g_part_img_buf
[0], &writelen
, unxz_error
);
875 Log("decompress finished success");
877 VentoyProcSecureBoot(g_SecureBoot
);
879 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
882 bRet
= WriteFile(hDrive
, g_part_img_buf
[0] + i
* SIZE_1MB
, SIZE_1MB
, &dwSize
, NULL
);
883 Log("Write part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
891 PROGRESS_BAR_SET_POS(Pos
);
898 //Read and check the data
899 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
900 SetFilePointerEx(hDrive
, liCurrentPosition
, &liNewPosition
, FILE_BEGIN
);
902 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
904 bRet
= ReadFile(hDrive
, CheckBuf
, SIZE_1MB
, &dwSize
, NULL
);
905 Log("Read part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
907 if (!bRet
|| memcmp(CheckBuf
, g_part_img_buf
[0] + i
* SIZE_1MB
, SIZE_1MB
))
909 Log("### [Check Fail] The data write and read does not match");
914 PROGRESS_BAR_SET_POS(Pos
);
924 Log("decompress finished failed");
930 Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE
);
933 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
935 g_part_img_buf
[i
] = (BYTE
*)malloc(SIZE_1MB
);
936 if (g_part_img_buf
[i
] == NULL
)
943 Log("Malloc part img buffer success, now decompress ...");
945 g_part_img_pos
= g_part_img_buf
[0];
947 unxz(data
, len
, NULL
, disk_xz_flush
, NULL
, NULL
, unxz_error
);
949 if (g_disk_unxz_len
== VENTOY_EFI_PART_SIZE
)
951 Log("decompress finished success");
953 VentoyProcSecureBoot(g_SecureBoot
);
955 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
958 bRet
= WriteFile(hDrive
, g_part_img_buf
[i
], SIZE_1MB
, &dwSize
, NULL
);
959 Log("Write part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
967 PROGRESS_BAR_SET_POS(Pos
);
974 //Read and check the data
975 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
976 SetFilePointerEx(hDrive
, liCurrentPosition
, &liNewPosition
, FILE_BEGIN
);
978 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
980 bRet
= ReadFile(hDrive
, CheckBuf
, SIZE_1MB
, &dwSize
, NULL
);
981 Log("Read part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
983 if (!bRet
|| memcmp(CheckBuf
, g_part_img_buf
[i
], SIZE_1MB
))
985 Log("### [Check Fail] The data write and read does not match");
990 PROGRESS_BAR_SET_POS(Pos
);
1000 Log("decompress finished failed");
1007 if (data
) free(data
);
1008 if (CheckBuf
)free(CheckBuf
);
1012 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1014 if (g_part_img_buf
[i
]) free(g_part_img_buf
[i
]);
1019 if (g_part_img_buf
[0]) free(g_part_img_buf
[0]);
1025 static int WriteGrubStage1ToPhyDrive(HANDLE hDrive
, int PartStyle
)
1031 BYTE
*ImgBuf
= NULL
;
1032 BYTE
*RawBuf
= NULL
;
1034 Log("WriteGrubStage1ToPhyDrive ...");
1036 RawBuf
= (BYTE
*)malloc(SIZE_1MB
);
1042 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG
, 0, (void **)&ImgBuf
, &Len
))
1044 Log("Failed to read stage1 img");
1049 unxz(ImgBuf
, Len
, NULL
, NULL
, RawBuf
, &readLen
, unxz_error
);
1053 Log("Write GPT stage1 ...");
1054 RawBuf
[500] = 35;//update blocklist
1055 SetFilePointer(hDrive
, 512 * 34, NULL
, FILE_BEGIN
);
1056 bRet
= WriteFile(hDrive
, RawBuf
, SIZE_1MB
- 512 * 34, &dwSize
, NULL
);
1060 Log("Write MBR stage1 ...");
1061 SetFilePointer(hDrive
, 512, NULL
, FILE_BEGIN
);
1062 bRet
= WriteFile(hDrive
, RawBuf
, SIZE_1MB
- 512, &dwSize
, NULL
);
1065 Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet
, dwSize
, GetLastError());
1074 static int FormatPart1exFAT(UINT64 DiskSizeBytes
)
1079 Option
.fmt
= FM_EXFAT
;
1084 // < 32GB select 32KB as cluster size
1085 // > 32GB select 128KB as cluster size
1086 if (DiskSizeBytes
/ 1024 / 1024 / 1024 <= 32)
1088 Option
.au_size
= 32768;
1092 Option
.au_size
= 131072;
1095 Log("Formatting Part1 exFAT ...");
1097 Ret
= f_mkfs(TEXT("0:"), &Option
, 0, 8 * 1024 * 1024);
1100 Log("Formatting Part1 exFAT success");
1105 Log("Formatting Part1 exFAT failed");
1112 int ClearVentoyFromPhyDrive(HWND hWnd
, PHY_DRIVE_INFO
*pPhyDrive
, char *pDrvLetter
)
1121 CHAR DriveName
[] = "?:\\";
1122 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1123 LARGE_INTEGER liCurrentPosition
;
1124 char *pTmpBuf
= NULL
;
1129 Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
1130 pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1131 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1133 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1135 Log("Lock disk for clean ............................. ");
1137 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1138 if (hDrive
== INVALID_HANDLE_VALUE
)
1140 Log("Failed to open physical disk");
1144 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1146 if (DriveLetters
[0] == 0)
1148 Log("No drive letter was assigned...");
1149 DriveName
[0] = GetFirstUnusedDriveLetter();
1150 Log("GetFirstUnusedDriveLetter %C: ...", DriveName
[0]);
1154 // Unmount all mounted volumes that belong to this drive
1155 // Do it in reverse so that we always end on the first volume letter
1156 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
1158 DriveName
[0] = DriveLetters
[i
- 1];
1159 bRet
= DeleteVolumeMountPointA(DriveName
);
1160 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, GetLastError());
1164 MountDrive
= DriveName
[0];
1165 Log("Will use '%C:' as volume mountpoint", DriveName
[0]);
1167 // It kind of blows, but we have to relinquish access to the physical drive
1168 // for VDS to be able to delete the partitions that reside on it...
1169 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1170 CHECK_CLOSE_HANDLE(hDrive
);
1172 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
1174 if (!VDS_DeleteAllPartitions(pPhyDrive
->PhyDrive
))
1176 Log("Notice: Could not delete partitions: %u", GetLastError());
1179 Log("Deleting all partitions ......................... OK");
1181 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
1183 Log("Lock disk for write ............................. ");
1184 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1185 if (hDrive
== INVALID_HANDLE_VALUE
)
1187 Log("Failed to GetPhysicalHandle for write.");
1192 // clear first and last 2MB space
1193 pTmpBuf
= malloc(SIZE_2MB
);
1196 Log("Failed to alloc memory.");
1200 memset(pTmpBuf
, 0, SIZE_2MB
);
1203 bRet
= WriteFile(hDrive
, pTmpBuf
, SIZE_2MB
- 512, &dwSize
, NULL
);
1204 Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1211 SET_FILE_POS(pPhyDrive
->SizeInBytes
- SIZE_2MB
);
1212 bRet
= WriteFile(hDrive
, pTmpBuf
, SIZE_2MB
, &dwSize
, NULL
);
1213 Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1222 if (pPhyDrive
->SizeInBytes
> 2199023255552ULL)
1224 VTOY_GPT_INFO
*pGptInfo
;
1225 VTOY_GPT_HDR BackupHead
;
1226 LARGE_INTEGER liCurrentPosition
;
1228 pGptInfo
= (VTOY_GPT_INFO
*)pTmpBuf
;
1230 VentoyFillWholeGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1232 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512);
1233 VentoyFillBackupGptHead(pGptInfo
, &BackupHead
);
1234 if (!WriteFile(hDrive
, &BackupHead
, sizeof(VTOY_GPT_HDR
), &dwSize
, NULL
))
1237 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1241 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512 * 33);
1242 if (!WriteFile(hDrive
, pGptInfo
->PartTbl
, sizeof(pGptInfo
->PartTbl
), &dwSize
, NULL
))
1245 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1250 if (!WriteFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
))
1253 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1257 Log("Write GPT Info OK ...");
1261 bRet
= ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
1262 Log("Read MBR ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1269 //clear boot code and partition table (reserved disk signature)
1270 memset(MBR
.BootCode
, 0, 440);
1271 memset(MBR
.PartTbl
, 0, sizeof(MBR
.PartTbl
));
1273 VentoyFillMBRLocation(pPhyDrive
->SizeInBytes
, 2048, (UINT32
)(pPhyDrive
->SizeInBytes
/ 512 - 2048), MBR
.PartTbl
);
1275 MBR
.PartTbl
[0].Active
= 0x00; // bootable
1276 MBR
.PartTbl
[0].FsFlag
= 0x07; // exFAT/NTFS/HPFS
1279 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
1280 Log("Write MBR ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1288 Log("Clear Ventoy successfully finished");
1290 //Refresh Drive Layout
1291 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1295 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1304 Log("Mounting Ventoy Partition ....................... ");
1308 memset(DriveLetters
, 0, sizeof(DriveLetters
));
1309 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1310 Log("Logical drive letter after write ventoy: <%s>", DriveLetters
);
1312 for (i
= 0; i
< sizeof(DriveLetters
) && DriveLetters
[i
]; i
++)
1314 DriveName
[0] = DriveLetters
[i
];
1315 Log("%s is ventoy part1, already mounted", DriveName
);
1321 Log("need to mount ventoy part1...");
1322 if (0 == GetVentoyVolumeName(pPhyDrive
->PhyDrive
, 2048, DriveLetters
, sizeof(DriveLetters
), FALSE
))
1324 DriveName
[0] = MountDrive
;
1325 bRet
= SetVolumeMountPointA(DriveName
, DriveLetters
);
1326 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName
, DriveLetters
, bRet
, GetLastError());
1328 *pDrvLetter
= MountDrive
;
1332 Log("Failed to find ventoy volume");
1340 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
1343 CHECK_CLOSE_HANDLE(hDrive
);
1347 int InstallVentoy2FileImage(PHY_DRIVE_INFO
*pPhyDrive
, int PartStyle
)
1356 UINT64 data_offset
= 0;
1357 UINT64 Part2StartSector
= 0;
1358 UINT64 Part1StartSector
= 0;
1359 UINT64 Part1SectorCount
= 0;
1360 UINT8
*pData
= NULL
;
1361 UINT8
*pBkGptPartTbl
= NULL
;
1362 BYTE
*ImgBuf
= NULL
;
1363 MBR_HEAD
*pMBR
= NULL
;
1364 VTSI_FOOTER
*pImgFooter
= NULL
;
1365 VTSI_SEGMENT
*pSegment
= NULL
;
1366 VTOY_GPT_INFO
*pGptInfo
= NULL
;
1367 VTOY_GPT_HDR
*pBkGptHdr
= NULL
;
1370 Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",
1371 PartStyle
? "GPT" : "MBR", pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1372 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1374 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1376 size
= SIZE_1MB
+ VENTOY_EFI_PART_SIZE
+ 33 * 512 + VTSI_IMG_MAX_SEG
* sizeof(VTSI_SEGMENT
) + sizeof(VTSI_FOOTER
);
1378 pData
= (UINT8
*)malloc(size
);
1381 Log("malloc image buffer failed %d.", size
);
1385 pImgFooter
= (VTSI_FOOTER
*)(pData
+ size
- sizeof(VTSI_FOOTER
));
1386 pSegment
= (VTSI_SEGMENT
*)((UINT8
*)pImgFooter
- VTSI_IMG_MAX_SEG
* sizeof(VTSI_SEGMENT
));
1387 memset(pImgFooter
, 0, sizeof(VTSI_FOOTER
));
1388 memset(pSegment
, 0, VTSI_IMG_MAX_SEG
* sizeof(VTSI_SEGMENT
));
1390 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
);
1392 Log("Writing Boot Image ............................. ");
1393 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG
, 0, (void **)&ImgBuf
, &Len
))
1395 Log("Failed to read stage1 img");
1399 unxz(ImgBuf
, Len
, NULL
, NULL
, pData
, &dataLen
, unxz_error
);
1402 Log("decompress %s len:%d", VENTOY_FILE_STG1_IMG
, dataLen
);
1406 pData
[500] = 35;//update blocklist
1407 memmove(pData
+ 34 * 512, pData
, SIZE_1MB
- 512 * 34);
1408 memset(pData
, 0, 34 * 512);
1410 pGptInfo
= (VTOY_GPT_INFO
*)pData
;
1411 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
1412 VentoyFillGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1414 pBkGptPartTbl
= pData
+ SIZE_1MB
+ VENTOY_EFI_PART_SIZE
;
1415 memset(pBkGptPartTbl
, 0, 33 * 512);
1417 memcpy(pBkGptPartTbl
, pGptInfo
->PartTbl
, 32 * 512);
1418 pBkGptHdr
= (VTOY_GPT_HDR
*)(pBkGptPartTbl
+ 32 * 512);
1419 VentoyFillBackupGptHead(pGptInfo
, pBkGptHdr
);
1421 Part1StartSector
= pGptInfo
->PartTbl
[0].StartLBA
;
1422 Part1SectorCount
= pGptInfo
->PartTbl
[0].LastLBA
- Part1StartSector
+ 1;
1423 Part2StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
1425 Log("Write GPT Info OK ...");
1429 memmove(pData
+ 512, pData
, SIZE_1MB
- 512);
1430 memset(pData
, 0, 512);
1432 pMBR
= (MBR_HEAD
*)pData
;
1433 VentoyFillMBR(pPhyDrive
->SizeInBytes
, pMBR
, PartStyle
);
1434 Part1StartSector
= pMBR
->PartTbl
[0].StartSectorId
;
1435 Part1SectorCount
= pMBR
->PartTbl
[0].SectorCount
;
1436 Part2StartSector
= pMBR
->PartTbl
[1].StartSectorId
;
1438 Log("Write MBR OK ...");
1441 Log("Writing EFI part Image ............................. ");
1442 rc
= ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG
, 0, (void **)&ImgBuf
, &Len
);
1445 Log("Failed to read img file %p %u", ImgBuf
, Len
);
1449 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
+ 28);
1450 memset(g_part_img_buf
, 0, sizeof(g_part_img_buf
));
1451 unxz(ImgBuf
, Len
, NULL
, NULL
, pData
+ SIZE_1MB
, &dataLen
, unxz_error
);
1454 Log("decompress finished success");
1455 g_part_img_buf
[0] = pData
+ SIZE_1MB
;
1457 VentoyProcSecureBoot(g_SecureBoot
);
1461 Log("decompress finished failed");
1465 fopen_s(&fp
, "VentoySparseImg.vtsi", "wb+");
1468 Log("Failed to create Ventoy img file");
1472 Log("Writing stage1 data ............................. ");
1474 fwrite(pData
, 1, SIZE_1MB
, fp
);
1476 pSegment
[0].disk_start_sector
= 0;
1477 pSegment
[0].sector_num
= SIZE_1MB
/ 512;
1478 pSegment
[0].data_offset
= data_offset
;
1479 data_offset
+= pSegment
[0].sector_num
* 512;
1481 disk_io_set_param(INVALID_HANDLE_VALUE
, Part1StartSector
+ Part1SectorCount
);// include the 2048 sector gap
1482 disk_io_set_imghook(fp
, pSegment
+ 1, VTSI_IMG_MAX_SEG
- 1, data_offset
);
1484 Log("Formatting part1 exFAT ...");
1485 if (0 != FormatPart1exFAT(pPhyDrive
->SizeInBytes
))
1487 Log("FormatPart1exFAT failed.");
1488 disk_io_reset_imghook(&segnum
, &data_offset
);
1492 disk_io_reset_imghook(&segnum
, &data_offset
);
1495 Log("current segment number:%d dataoff:%ld", segnum
, (long)data_offset
);
1498 Log("Writing part2 data ............................. ");
1499 fwrite(pData
+ SIZE_1MB
, 1, VENTOY_EFI_PART_SIZE
, fp
);
1500 pSegment
[segnum
].disk_start_sector
= Part2StartSector
;
1501 pSegment
[segnum
].sector_num
= VENTOY_EFI_PART_SIZE
/ 512;
1502 pSegment
[segnum
].data_offset
= data_offset
;
1503 data_offset
+= pSegment
[segnum
].sector_num
* 512;
1508 Log("Writing backup gpt table ............................. ");
1509 fwrite(pBkGptPartTbl
, 1, 33 * 512, fp
);
1510 pSegment
[segnum
].disk_start_sector
= pPhyDrive
->SizeInBytes
/ 512 - 33;
1511 pSegment
[segnum
].sector_num
= 33;
1512 pSegment
[segnum
].data_offset
= data_offset
;
1513 data_offset
+= pSegment
[segnum
].sector_num
* 512;
1517 Log("Writing segment metadata ............................. ");
1519 for (i
= 0; i
< (int)segnum
; i
++)
1521 Log("SEG[%d]: PhySector:%llu SectorNum:%llu DataOffset:%llu(sector:%llu)", i
, pSegment
[i
].disk_start_sector
, pSegment
[i
].sector_num
,
1522 pSegment
[i
].data_offset
, pSegment
[i
].data_offset
/ 512);
1525 dataLen
= segnum
* sizeof(VTSI_SEGMENT
);
1526 fwrite(pSegment
, 1, dataLen
, fp
);
1530 //pData + SIZE_1MB - 8192 is a temp data buffer with zero
1531 fwrite(pData
+ SIZE_1MB
- 8192, 1, 512 - (dataLen
% 512), fp
);
1535 pImgFooter
->magic
= VTSI_IMG_MAGIC
;
1536 pImgFooter
->version
= 1;
1537 pImgFooter
->disk_size
= pPhyDrive
->SizeInBytes
;
1538 memcpy(&pImgFooter
->disk_signature
, pPhyDrive
->MBR
.BootCode
+ 0x1b8, 4);
1539 pImgFooter
->segment_num
= segnum
;
1540 pImgFooter
->segment_offset
= data_offset
;
1542 for (i
= 0, chksum
= 0; i
< (int)(segnum
* sizeof(VTSI_SEGMENT
)); i
++)
1544 chksum
+= *((UINT8
*)pSegment
+ i
);
1546 pImgFooter
->segment_chksum
= ~chksum
;
1548 for (i
= 0, chksum
= 0; i
< sizeof(VTSI_FOOTER
); i
++)
1550 chksum
+= *((UINT8
*)pImgFooter
+ i
);
1552 pImgFooter
->foot_chksum
= ~chksum
;
1554 Log("Writing footer segnum(%u) segoffset(%llu) ......................", segnum
, data_offset
);
1555 Log("disk_size=%llu disk_signature=%lx segment_offset=%llu", pImgFooter
->disk_size
, pImgFooter
->disk_signature
, pImgFooter
->segment_offset
);
1557 fwrite(pImgFooter
, 1, sizeof(VTSI_FOOTER
), fp
);
1560 Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset
+ 512 + ((dataLen
+ 511) / 512 * 512));
1566 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1568 Log("retcode:%d\n", rc
);
1577 int InstallVentoy2PhyDrive(PHY_DRIVE_INFO
*pPhyDrive
, int PartStyle
, int TryId
)
1586 CHAR DriveName
[] = "?:\\";
1587 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1589 VTOY_GPT_INFO
*pGptInfo
= NULL
;
1590 UINT64 Part1StartSector
= 0;
1591 UINT64 Part1SectorCount
= 0;
1592 UINT64 Part2StartSector
= 0;
1594 Log("InstallVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId
,
1595 PartStyle
? "GPT" : "MBR", pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1596 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1600 pGptInfo
= malloc(sizeof(VTOY_GPT_INFO
));
1601 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
1604 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1608 VentoyFillGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1609 Part1StartSector
= pGptInfo
->PartTbl
[0].StartLBA
;
1610 Part1SectorCount
= pGptInfo
->PartTbl
[0].LastLBA
- Part1StartSector
+ 1;
1611 Part2StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
1615 VentoyFillMBR(pPhyDrive
->SizeInBytes
, &MBR
, PartStyle
);
1616 Part1StartSector
= MBR
.PartTbl
[0].StartSectorId
;
1617 Part1SectorCount
= MBR
.PartTbl
[0].SectorCount
;
1618 Part2StartSector
= MBR
.PartTbl
[1].StartSectorId
;
1621 Log("Lock disk for clean ............................. ");
1623 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1624 if (hDrive
== INVALID_HANDLE_VALUE
)
1626 Log("Failed to open physical disk");
1631 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1633 if (DriveLetters
[0] == 0)
1635 Log("No drive letter was assigned...");
1636 DriveName
[0] = GetFirstUnusedDriveLetter();
1637 Log("GetFirstUnusedDriveLetter %C: ...", DriveName
[0]);
1641 // Unmount all mounted volumes that belong to this drive
1642 // Do it in reverse so that we always end on the first volume letter
1643 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
1645 DriveName
[0] = DriveLetters
[i
- 1];
1646 bRet
= DeleteVolumeMountPointA(DriveName
);
1647 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, GetLastError());
1651 MountDrive
= DriveName
[0];
1652 Log("Will use '%C:' as volume mountpoint", DriveName
[0]);
1654 // It kind of blows, but we have to relinquish access to the physical drive
1655 // for VDS to be able to delete the partitions that reside on it...
1656 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1657 CHECK_CLOSE_HANDLE(hDrive
);
1659 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
1661 if (!VDS_DeleteAllPartitions(pPhyDrive
->PhyDrive
))
1663 Log("Notice: Could not delete partitions: 0x%x", GetLastError());
1668 Log("Deleting all partitions ......................... OK");
1670 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
1672 Log("Lock disk for write ............................. ");
1673 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1674 if (hDrive
== INVALID_HANDLE_VALUE
)
1676 Log("Failed to GetPhysicalHandle for write.");
1681 //Refresh Drive Layout
1682 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1684 disk_io_set_param(hDrive
, Part1StartSector
+ Part1SectorCount
);// include the 2048 sector gap
1686 PROGRESS_BAR_SET_POS(PT_FORMAT_PART1
);
1688 if (PartStyle
== 1 && pPhyDrive
->PartStyle
== 0)
1690 Log("Wait for format part1 ...");
1694 Log("Formatting part1 exFAT ...");
1695 if (0 != FormatPart1exFAT(pPhyDrive
->SizeInBytes
))
1697 Log("FormatPart1exFAT failed.");
1702 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
1703 Log("Writing part2 FAT img ...");
1705 if (0 != FormatPart2Fat(hDrive
, Part2StartSector
))
1707 Log("FormatPart2Fat failed.");
1712 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG
);
1713 Log("Writing Boot Image ............................. ");
1714 if (WriteGrubStage1ToPhyDrive(hDrive
, PartStyle
) != 0)
1716 Log("WriteGrubStage1ToPhyDrive failed.");
1721 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE
);
1722 Log("Writing Partition Table ........................ ");
1723 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
1727 VTOY_GPT_HDR BackupHead
;
1728 LARGE_INTEGER liCurrentPosition
;
1730 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512);
1731 VentoyFillBackupGptHead(pGptInfo
, &BackupHead
);
1732 if (!WriteFile(hDrive
, &BackupHead
, sizeof(VTOY_GPT_HDR
), &dwSize
, NULL
))
1735 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1739 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512 * 33);
1740 if (!WriteFile(hDrive
, pGptInfo
->PartTbl
, sizeof(pGptInfo
->PartTbl
), &dwSize
, NULL
))
1743 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1748 if (!WriteFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
))
1751 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1755 Log("Write GPT Info OK ...");
1756 memcpy(&(pPhyDrive
->MBR
), &(pGptInfo
->MBR
), 512);
1760 if (!WriteFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
))
1763 Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize
, GetLastError());
1766 Log("Write MBR OK ...");
1767 memcpy(&(pPhyDrive
->MBR
), &MBR
, 512);
1770 //Refresh Drive Layout
1771 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1775 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1779 Log("Mounting Ventoy Partition ....................... ");
1783 memset(DriveLetters
, 0, sizeof(DriveLetters
));
1784 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1785 Log("Logical drive letter after write ventoy: <%s>", DriveLetters
);
1787 for (i
= 0; i
< sizeof(DriveLetters
) && DriveLetters
[i
]; i
++)
1789 DriveName
[0] = DriveLetters
[i
];
1790 if (IsVentoyLogicalDrive(DriveName
[0]))
1792 Log("%s is ventoy part2, delete mountpoint", DriveName
);
1793 DeleteVolumeMountPointA(DriveName
);
1797 Log("%s is ventoy part1, already mounted", DriveName
);
1804 Log("need to mount ventoy part1...");
1806 if (0 == GetVentoyVolumeName(pPhyDrive
->PhyDrive
, Part1StartSector
, DriveLetters
, sizeof(DriveLetters
), FALSE
))
1808 DriveName
[0] = MountDrive
;
1809 bRet
= SetVolumeMountPointA(DriveName
, DriveLetters
);
1810 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName
, DriveLetters
, bRet
, GetLastError());
1814 Log("Failed to find ventoy volume");
1821 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
1829 CHECK_CLOSE_HANDLE(hDrive
);
1833 static BOOL
BackupDataBeforeCleanDisk(int PhyDrive
, UINT64 DiskSize
, BYTE
**pBackup
)
1837 BOOL Return
= FALSE
;
1839 BYTE
*backup
= NULL
;
1840 HANDLE hDrive
= INVALID_HANDLE_VALUE
;
1841 LARGE_INTEGER liCurPosition
;
1842 LARGE_INTEGER liNewPosition
;
1844 Log("BackupDataBeforeCleanDisk %d", PhyDrive
);
1846 backup
= malloc(SIZE_1MB
* 4);
1852 hDrive
= GetPhysicalHandle(PhyDrive
, FALSE
, FALSE
, FALSE
);
1853 if (hDrive
== INVALID_HANDLE_VALUE
)
1859 dwStatus
= SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
1866 ret
= ReadFile(hDrive
, backup
, SIZE_2MB
, &dwSize
, NULL
);
1867 if ((!ret
) || (dwSize
!= SIZE_2MB
))
1869 Log("Failed to read %d %u 0x%x", ret
, dwSize
, LASTERR
);
1874 liCurPosition
.QuadPart
= DiskSize
- SIZE_2MB
;
1875 liNewPosition
.QuadPart
= 0;
1876 if (0 == SetFilePointerEx(hDrive
, liCurPosition
, &liNewPosition
, FILE_BEGIN
) ||
1877 liNewPosition
.QuadPart
!= liCurPosition
.QuadPart
)
1883 ret
= ReadFile(hDrive
, backup
+ SIZE_2MB
, SIZE_2MB
, &dwSize
, NULL
);
1884 if ((!ret
) || (dwSize
!= SIZE_2MB
))
1886 Log("Failed to read %d %u 0x%x", ret
, dwSize
, LASTERR
);
1891 backup
= NULL
; //For don't free later
1895 CHECK_CLOSE_HANDLE(hDrive
);
1903 static BOOL
WriteBackupDataToDisk(HANDLE hDrive
, UINT64 Offset
, BYTE
*Data
, DWORD Length
)
1907 LARGE_INTEGER liCurPosition
;
1908 LARGE_INTEGER liNewPosition
;
1910 Log("WriteBackupDataToDisk %llu %p %u", Offset
, Data
, Length
);
1912 liCurPosition
.QuadPart
= Offset
;
1913 liNewPosition
.QuadPart
= 0;
1914 if (0 == SetFilePointerEx(hDrive
, liCurPosition
, &liNewPosition
, FILE_BEGIN
) ||
1915 liNewPosition
.QuadPart
!= liCurPosition
.QuadPart
)
1920 ret
= WriteFile(hDrive
, Data
, Length
, &dwSize
, NULL
);
1921 if ((!ret
) || dwSize
!= Length
)
1923 Log("Failed to write %d %u %u", ret
, dwSize
, LASTERR
);
1927 Log("WriteBackupDataToDisk %llu %p %u success", Offset
, Data
, Length
);
1932 int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO
*pPhyDrive
, int TryId
)
1937 BOOL ForceMBR
= FALSE
;
1938 BOOL Esp2Basic
= FALSE
;
1939 BOOL ChangeAttr
= FALSE
;
1940 BOOL CleanDisk
= FALSE
;
1941 BOOL bWriteBack
= TRUE
;
1947 CHAR DriveName
[] = "?:\\";
1948 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1949 CHAR BackBinFile
[MAX_PATH
];
1951 UINT64 ReservedMB
= 0;
1954 BYTE
*pBackup
= NULL
;
1955 VTOY_GPT_INFO
*pGptInfo
= NULL
;
1956 UINT8 ReservedData
[4096];
1958 Log("UpdateVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId
,
1959 pPhyDrive
->PartStyle
? "GPT" : "MBR", pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1960 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1962 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1964 Log("Lock disk for umount ............................ ");
1966 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1967 if (hDrive
== INVALID_HANDLE_VALUE
)
1969 Log("Failed to open physical disk");
1973 if (pPhyDrive
->PartStyle
)
1975 pGptInfo
= malloc(sizeof(VTOY_GPT_INFO
));
1981 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
1984 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
1985 ReadFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
);
1987 //MBR will be used to compare with local boot image
1988 memcpy(&MBR
, &pGptInfo
->MBR
, sizeof(MBR_HEAD
));
1990 StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
1991 Log("GPT StartSector in PartTbl:%llu", (ULONGLONG
)StartSector
);
1993 ReservedMB
= (pPhyDrive
->SizeInBytes
/ 512 - (StartSector
+ VENTOY_EFI_PART_SIZE
/ 512) - 33) / 2048;
1994 Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG
)ReservedMB
);
1999 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2000 ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
2002 StartSector
= MBR
.PartTbl
[1].StartSectorId
;
2003 Log("MBR StartSector in PartTbl:%llu", (ULONGLONG
)StartSector
);
2005 ReservedMB
= (pPhyDrive
->SizeInBytes
/ 512 - (StartSector
+ VENTOY_EFI_PART_SIZE
/ 512)) / 2048;
2006 Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG
)ReservedMB
);
2009 //Read Reserved Data
2010 SetFilePointer(hDrive
, 512 * 2040, NULL
, FILE_BEGIN
);
2011 ReadFile(hDrive
, ReservedData
, sizeof(ReservedData
), &dwSize
, NULL
);
2013 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
2015 if (DriveLetters
[0] == 0)
2017 Log("No drive letter was assigned...");
2021 // Unmount all mounted volumes that belong to this drive
2022 // Do it in reverse so that we always end on the first volume letter
2023 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
2025 DriveName
[0] = DriveLetters
[i
- 1];
2026 if (IsVentoyLogicalDrive(DriveName
[0]))
2028 Log("%s is ventoy logical drive", DriveName
);
2029 bRet
= DeleteVolumeMountPointA(DriveName
);
2030 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, LASTERR
);
2036 // It kind of blows, but we have to relinquish access to the physical drive
2037 // for VDS to be able to delete the partitions that reside on it...
2038 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2039 CHECK_CLOSE_HANDLE(hDrive
);
2041 if (pPhyDrive
->PartStyle
== 1)
2043 Log("TryId=%d EFI GPT partition type is 0x%llx", TryId
, pPhyDrive
->Part2GPTAttr
);
2044 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
2048 Log("Change GPT partition type to ESP");
2049 if (VDS_ChangeVtoyEFI2ESP(pPhyDrive
->PhyDrive
, StartSector
* 512))
2055 else if (TryId
== 2)
2057 Log("Change GPT partition attribute");
2058 if (VDS_ChangeVtoyEFIAttr(pPhyDrive
->PhyDrive
, 0x8000000000000001))
2064 else if (TryId
== 3)
2066 Log("Clean disk GPT partition table");
2067 if (BackupDataBeforeCleanDisk(pPhyDrive
->PhyDrive
, pPhyDrive
->SizeInBytes
, &pBackup
))
2069 sprintf_s(BackBinFile
, sizeof(BackBinFile
), ".\\ventoy\\phydrive%d_%u_%d.bin",
2070 pPhyDrive
->PhyDrive
, GetCurrentProcessId(), g_backup_bin_index
++);
2071 SaveBufToFile(BackBinFile
, pBackup
, 4 * SIZE_1MB
);
2072 Log("Save backup data to %s", BackBinFile
);
2074 Log("Success to backup data before clean");
2076 if (!VDS_CleanDisk(pPhyDrive
->PhyDrive
))
2079 DSPT_CleanDisk(pPhyDrive
->PhyDrive
);
2085 Log("Failed to backup data before clean");
2090 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
2092 Log("Lock disk for update ............................ ");
2093 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
2094 if (hDrive
== INVALID_HANDLE_VALUE
)
2096 Log("Failed to GetPhysicalHandle for write.");
2101 PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME
);
2103 Log("Lock volume for update .......................... ");
2104 hVolume
= INVALID_HANDLE_VALUE
;
2106 //If we change VTOYEFI to ESP, it can not have s volume name, so don't try to get it.
2109 //writeback the last 2MB
2110 if (!WriteBackupDataToDisk(hDrive
, pPhyDrive
->SizeInBytes
- SIZE_2MB
, pBackup
+ SIZE_2MB
, SIZE_2MB
))
2114 Status
= ERROR_NOT_FOUND
;
2118 Status
= ERROR_NOT_FOUND
;
2122 for (i
= 0; i
< MaxRetry
; i
++)
2124 Status
= GetVentoyVolumeName(pPhyDrive
->PhyDrive
, StartSector
, DriveLetters
, sizeof(DriveLetters
), TRUE
);
2125 if (ERROR_SUCCESS
== Status
)
2131 Log("==== Volume not found, wait and retry %d... ====", i
);
2137 if (ERROR_SUCCESS
== Status
)
2139 Log("Now lock and dismount volume <%s>", DriveLetters
);
2141 for (i
= 0; i
< MaxRetry
; i
++)
2143 hVolume
= CreateFileA(DriveLetters
,
2144 GENERIC_READ
| GENERIC_WRITE
,
2148 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_NO_BUFFERING
| FILE_FLAG_WRITE_THROUGH
,
2151 if (hVolume
== INVALID_HANDLE_VALUE
)
2153 Log("Failed to create file volume, errcode:%u, wait and retry ...", LASTERR
);
2162 if (hVolume
== INVALID_HANDLE_VALUE
)
2164 Log("Failed to create file volume, errcode:%u", LASTERR
);
2168 bRet
= DeviceIoControl(hVolume
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2169 Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
2171 bRet
= DeviceIoControl(hVolume
, FSCTL_DISMOUNT_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2172 Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
2175 else if (ERROR_NOT_FOUND
== Status
)
2177 Log("Volume not found, maybe not supported");
2185 bRet
= TryWritePart2(hDrive
, StartSector
);
2186 if (FALSE
== bRet
&& Esp2Basic
)
2188 Log("TryWritePart2 agagin ...");
2190 bRet
= TryWritePart2(hDrive
, StartSector
);
2195 if (pPhyDrive
->PartStyle
== 0)
2199 Log("Try write failed, now delete partition 2 for MBR...");
2200 CHECK_CLOSE_HANDLE(hDrive
);
2202 Log("Now delete partition 2...");
2203 VDS_DeleteVtoyEFIPartition(pPhyDrive
->PhyDrive
);
2205 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
2206 if (hDrive
== INVALID_HANDLE_VALUE
)
2208 Log("Failed to GetPhysicalHandle for write.");
2215 Log("TryWritePart2 failed ....");
2221 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
2223 Log("Write Ventoy to disk ............................ ");
2224 if (0 != FormatPart2Fat(hDrive
, StartSector
))
2230 if (hVolume
!= INVALID_HANDLE_VALUE
)
2232 bRet
= DeviceIoControl(hVolume
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2233 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
2234 CHECK_CLOSE_HANDLE(hVolume
);
2237 Log("Updating Boot Image ............................. ");
2238 if (WriteGrubStage1ToPhyDrive(hDrive
, pPhyDrive
->PartStyle
) != 0)
2244 //write reserved data
2245 SetFilePointer(hDrive
, 512 * 2040, NULL
, FILE_BEGIN
);
2246 bRet
= WriteFile(hDrive
, ReservedData
, sizeof(ReservedData
), &dwSize
, NULL
);
2247 Log("Write resv data ret:%u dwSize:%u Error:%u", bRet
, dwSize
, LASTERR
);
2250 VentoyGetLocalBootImg(&BootImg
);
2253 memcpy(BootImg
.BootCode
+ 0x180, MBR
.BootCode
+ 0x180, 16);
2254 if (pPhyDrive
->PartStyle
)
2256 BootImg
.BootCode
[92] = 0x22;
2259 if (ForceMBR
== FALSE
&& memcmp(BootImg
.BootCode
, MBR
.BootCode
, 440) == 0)
2261 Log("Boot image has no difference, no need to write.");
2265 Log("Boot image need to write %u.", ForceMBR
);
2267 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2269 memcpy(MBR
.BootCode
, BootImg
.BootCode
, 440);
2270 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
2271 Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet
, dwSize
, LASTERR
);
2274 if (pPhyDrive
->PartStyle
== 0)
2276 if (0x00 == MBR
.PartTbl
[0].Active
&& 0x80 == MBR
.PartTbl
[1].Active
)
2278 Log("Need to chage 1st partition active and 2nd partition inactive.");
2280 MBR
.PartTbl
[0].Active
= 0x80;
2281 MBR
.PartTbl
[1].Active
= 0x00;
2283 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2284 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
2285 Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet
, dwSize
, LASTERR
);
2291 if (!WriteBackupDataToDisk(hDrive
, 4 * 512, pBackup
+ 4 * 512, SIZE_2MB
- 4 * 512))
2296 if (!WriteBackupDataToDisk(hDrive
, 0, pBackup
, 4 * 512))
2305 Log("Write success, now delete %s", BackBinFile
);
2306 DeleteFileA(BackBinFile
);
2310 //Refresh Drive Layout
2311 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2321 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
2324 CHECK_CLOSE_HANDLE(hDrive
);
2328 Log("Recover GPT partition type to basic");
2329 VDS_ChangeVtoyEFI2Basic(pPhyDrive
->PhyDrive
, StartSector
* 512);
2332 if (pPhyDrive
->PartStyle
== 1)
2334 if (ChangeAttr
|| ((pPhyDrive
->Part2GPTAttr
>> 56) != 0xC0))
2336 Log("Change EFI partition attr %u <0x%llx> to <0x%llx>", ChangeAttr
, pPhyDrive
->Part2GPTAttr
, 0xC000000000000001ULL
);
2337 if (VDS_ChangeVtoyEFIAttr(pPhyDrive
->PhyDrive
, 0xC000000000000001ULL
))
2339 Log("Change EFI partition attr success");
2340 pPhyDrive
->Part2GPTAttr
= 0xC000000000000001ULL
;
2344 Log("Change EFI partition attr failed");