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/>.
28 #include "Ventoy2Disk.h"
29 #include "fat_filelib.h"
31 #include "DiskService.h"
33 static DWORD
GetVentoyVolumeName(int PhyDrive
, UINT64 StartSectorId
, CHAR
*NameBuf
, UINT32 BufLen
, BOOL DelSlash
)
41 DWORD Status
= ERROR_NOT_FOUND
;
42 DISK_EXTENT
*pExtents
= NULL
;
43 CHAR VolumeName
[MAX_PATH
] = { 0 };
44 VOLUME_DISK_EXTENTS DiskExtents
;
46 PartOffset
= 512ULL * StartSectorId
;
48 Log("GetVentoyVolumeName PhyDrive %d SectorStart:%llu PartOffset:%llu", PhyDrive
, (ULONGLONG
)StartSectorId
, (ULONGLONG
)PartOffset
);
50 hVolume
= FindFirstVolumeA(VolumeName
, sizeof(VolumeName
));
51 if (hVolume
== INVALID_HANDLE_VALUE
)
58 len
= strlen(VolumeName
);
59 Log("Find volume:%s", VolumeName
);
61 VolumeName
[len
- 1] = 0;
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
)
69 bRet
= DeviceIoControl(hDrive
,
70 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
74 (DWORD
)(sizeof(DiskExtents
)),
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
);
81 if (bRet
&& DiskExtents
.NumberOfDiskExtents
== 1)
83 pExtents
= DiskExtents
.Extents
;
85 Log("This volume DiskNumber:%u offset:%llu", pExtents
->DiskNumber
, (ULONGLONG
)pExtents
->StartingOffset
.QuadPart
);
86 if ((int)pExtents
->DiskNumber
== PhyDrive
&& pExtents
->StartingOffset
.QuadPart
== PartOffset
)
88 Log("This volume match");
92 VolumeName
[len
- 1] = '\\';
95 sprintf_s(NameBuf
, BufLen
, "%s", VolumeName
);
96 Status
= ERROR_SUCCESS
;
103 } while (FindNextVolumeA(hVolume
, VolumeName
, sizeof(VolumeName
)));
105 FindVolumeClose(hVolume
);
107 Log("GetVentoyVolumeName return %u", Status
);
111 static int GetLettersBelongPhyDrive(int PhyDrive
, char *DriveLetters
, size_t Length
)
116 CHAR
*StringBuf
= NULL
;
118 DataSize
= GetLogicalDriveStringsA(0, NULL
);
119 StringBuf
= (CHAR
*)malloc(DataSize
+ 1);
120 if (StringBuf
== NULL
)
125 GetLogicalDriveStringsA(DataSize
, StringBuf
);
127 for (Pos
= StringBuf
; *Pos
; Pos
+= strlen(Pos
) + 1)
129 if (n
< (int)Length
&& PhyDrive
== GetPhyDriveByLogicalDrive(Pos
[0]))
131 Log("%C: is belong to phydrive%d", Pos
[0], PhyDrive
);
132 DriveLetters
[n
++] = Pos
[0];
140 static HANDLE
GetPhysicalHandle(int Drive
, BOOLEAN bLockDrive
, BOOLEAN bWriteAccess
, BOOLEAN bWriteShare
)
146 HANDLE hDrive
= INVALID_HANDLE_VALUE
;
148 CHAR DevPath
[MAX_PATH
] = { 0 };
150 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", Drive
);
152 if (0 == QueryDosDeviceA(PhyDrive
+ 4, DevPath
, sizeof(DevPath
)))
154 Log("QueryDosDeviceA failed error:%u", GetLastError());
155 strcpy_s(DevPath
, sizeof(DevPath
), "???");
159 Log("QueryDosDeviceA success %s", DevPath
);
162 for (i
= 0; i
< DRIVE_ACCESS_RETRIES
; i
++)
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),
174 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_NO_BUFFERING
| FILE_FLAG_WRITE_THROUGH
,
177 LastError
= GetLastError();
178 Log("[%d] CreateFileA %s code:%u %p", i
, PhyDrive
, LastError
, hDrive
);
180 if (hDrive
!= INVALID_HANDLE_VALUE
)
185 if ((LastError
!= ERROR_SHARING_VIOLATION
) && (LastError
!= ERROR_ACCESS_DENIED
))
192 Log("Waiting for access on %s [%s]...", PhyDrive
, DevPath
);
194 else if (!bWriteShare
&& (i
> DRIVE_ACCESS_RETRIES
/ 3))
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...");
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;
205 Sleep(DRIVE_ACCESS_TIMEOUT
/ DRIVE_ACCESS_RETRIES
);
208 if (hDrive
== INVALID_HANDLE_VALUE
)
210 Log("Could not open %s %u", PhyDrive
, LASTERR
);
216 Log("Opened %s for %s write access", PhyDrive
, bWriteShare
? "shared" : "exclusive");
221 if (DeviceIoControl(hDrive
, FSCTL_ALLOW_EXTENDED_DASD_IO
, NULL
, 0, NULL
, 0, &dwSize
, NULL
))
223 Log("I/O boundary checks disabled");
226 EndTime
= GetTickCount64() + DRIVE_ACCESS_TIMEOUT
;
229 if (DeviceIoControl(hDrive
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
))
231 Log("FSCTL_LOCK_VOLUME success");
234 Sleep(DRIVE_ACCESS_TIMEOUT
/ DRIVE_ACCESS_RETRIES
);
235 } while (GetTickCount64() < EndTime
);
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
);
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);
247 CHECK_CLOSE_HANDLE(hDrive
);
252 if (hDrive
== INVALID_HANDLE_VALUE
)
254 Log("Can get handle of %s, maybe some process control it.", DevPath
);
260 int GetPhyDriveByLogicalDrive(int DriveLetter
)
265 VOLUME_DISK_EXTENTS DiskExtents
;
268 safe_sprintf(PhyPath
, "\\\\.\\%C:", (CHAR
)DriveLetter
);
270 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
271 if (Handle
== INVALID_HANDLE_VALUE
)
273 Log("Could not open the disk<%s>, error:%u", PhyPath
, LASTERR
);
277 Ret
= DeviceIoControl(Handle
,
278 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
282 (DWORD
)(sizeof(DiskExtents
)),
286 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
288 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath
, LASTERR
);
289 CHECK_CLOSE_HANDLE(Handle
);
292 CHECK_CLOSE_HANDLE(Handle
);
294 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
296 DiskExtents
.Extents
[0].DiskNumber
,
297 DiskExtents
.Extents
[0].StartingOffset
.QuadPart
,
298 DiskExtents
.Extents
[0].ExtentLength
.QuadPart
301 return (int)DiskExtents
.Extents
[0].DiskNumber
;
304 int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO
*pDriveList
, DWORD
*pDriveCount
)
312 DWORD DriveCount
= 0;
313 HANDLE Handle
= INVALID_HANDLE_VALUE
;
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
];
322 Count
= GetPhysicalDriveCount();
324 for (i
= 0; i
< Count
&& i
< VENTOY_MAX_PHY_DRIVE
; i
++)
329 dwBytes
= GetLogicalDrives();
330 Log("Logical Drives: 0x%x", dwBytes
);
335 id
= GetPhyDriveByLogicalDrive(Letter
);
336 Log("%C --> %d", Letter
, id
);
339 for (i
= 0; i
< Count
; i
++)
341 if (PhyDriveId
[i
] == id
)
349 Log("Add phy%d to list", i
);
350 PhyDriveId
[Count
] = id
;
360 for (i
= 0; i
< Count
&& DriveCount
< VENTOY_MAX_PHY_DRIVE
; i
++)
362 CHECK_CLOSE_HANDLE(Handle
);
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
);
368 if (Handle
== INVALID_HANDLE_VALUE
)
373 bRet
= DeviceIoControl(Handle
,
374 IOCTL_DISK_GET_LENGTH_INFO
, NULL
,
382 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR
);
386 Log("PHYSICALDRIVE%d size %llu bytes", i
, (ULONGLONG
)LengthInfo
.Length
.QuadPart
);
388 Query
.PropertyId
= StorageDeviceProperty
;
389 Query
.QueryType
= PropertyStandardQuery
;
391 bRet
= DeviceIoControl(Handle
,
392 IOCTL_STORAGE_QUERY_PROPERTY
,
396 sizeof(STORAGE_DESCRIPTOR_HEADER
),
401 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR
, dwBytes
);
405 if (DevDescHeader
.Size
< sizeof(STORAGE_DEVICE_DESCRIPTOR
))
407 Log("Invalid DevDescHeader.Size:%u", DevDescHeader
.Size
);
411 pDevDesc
= (STORAGE_DEVICE_DESCRIPTOR
*)malloc(DevDescHeader
.Size
);
414 Log("failed to malloc error:%u len:%u", LASTERR
, DevDescHeader
.Size
);
418 bRet
= DeviceIoControl(Handle
,
419 IOCTL_STORAGE_QUERY_PROPERTY
,
428 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR
, dwBytes
);
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
;
439 if (pDevDesc
->VendorIdOffset
)
441 safe_strcpy(CurDrive
->VendorId
, (char *)pDevDesc
+ pDevDesc
->VendorIdOffset
);
442 TrimString(CurDrive
->VendorId
);
445 if (pDevDesc
->ProductIdOffset
)
447 safe_strcpy(CurDrive
->ProductId
, (char *)pDevDesc
+ pDevDesc
->ProductIdOffset
);
448 TrimString(CurDrive
->ProductId
);
451 if (pDevDesc
->ProductRevisionOffset
)
453 safe_strcpy(CurDrive
->ProductRev
, (char *)pDevDesc
+ pDevDesc
->ProductRevisionOffset
);
454 TrimString(CurDrive
->ProductRev
);
457 if (pDevDesc
->SerialNumberOffset
)
459 safe_strcpy(CurDrive
->SerialNumber
, (char *)pDevDesc
+ pDevDesc
->SerialNumberOffset
);
460 TrimString(CurDrive
->SerialNumber
);
468 CHECK_CLOSE_HANDLE(Handle
);
471 for (i
= 0, CurDrive
= pDriveList
; i
< (int)DriveCount
; i
++, CurDrive
++)
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
);
479 *pDriveCount
= DriveCount
;
485 static HANDLE g_FatPhyDrive
;
486 static UINT64 g_Part2StartSec
;
487 static int GetVentoyVersionFromFatFile(CHAR
*VerBuf
, size_t BufLen
)
494 flfile
= fl_fopen("/grub/grub.cfg", "rb");
497 fl_fseek(flfile
, 0, SEEK_END
);
498 size
= (int)fl_ftell(flfile
);
500 fl_fseek(flfile
, 0, SEEK_SET
);
502 buf
= (char *)malloc(size
+ 1);
505 fl_fread(buf
, 1, size
, flfile
);
509 sprintf_s(VerBuf
, BufLen
, "%s", ParseVentoyVersionFromString(buf
));
519 static int VentoyFatDiskRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
524 LARGE_INTEGER liCurrentPosition
;
526 liCurrentPosition
.QuadPart
= Sector
+ g_Part2StartSec
;
527 liCurrentPosition
.QuadPart
*= 512;
528 SetFilePointerEx(g_FatPhyDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
530 ReadSize
= (DWORD
)(SectorCount
* 512);
532 bRet
= ReadFile(g_FatPhyDrive
, Buffer
, ReadSize
, &dwSize
, NULL
);
533 if (bRet
== FALSE
|| dwSize
!= ReadSize
)
535 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet
, ReadSize
, dwSize
, LASTERR
);
542 int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO
*pDriveInfo
, UINT64 Part2StartSector
, CHAR
*VerBuf
, size_t BufLen
, BOOL
*pSecureBoot
)
548 hDrive
= GetPhysicalHandle(pDriveInfo
->PhyDrive
, FALSE
, FALSE
, FALSE
);
549 if (hDrive
== INVALID_HANDLE_VALUE
)
554 g_FatPhyDrive
= hDrive
;
555 g_Part2StartSec
= Part2StartSector
;
557 Log("Parse FAT fs...");
561 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
563 Log("attach media success...");
564 rc
= GetVentoyVersionFromFatFile(VerBuf
, BufLen
);
568 Log("attach media failed...");
572 Log("GetVentoyVerInPhyDrive rc=%d...", rc
);
575 Log("VentoyVerInPhyDrive %d is <%s>...", pDriveInfo
->PhyDrive
, VerBuf
);
577 flfile
= fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
587 CHECK_CLOSE_HANDLE(hDrive
);
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
];
601 static int VentoyFatMemRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
607 for (i
= 0; i
< SectorCount
; i
++)
609 offset
= (Sector
+ i
) * 512;
611 if (g_part_img_buf
[1] == NULL
)
613 MbBuf
= g_part_img_buf
[0] + offset
;
614 memcpy(Buffer
+ i
* 512, MbBuf
, 512);
618 MbBuf
= g_part_img_buf
[offset
/ SIZE_1MB
];
619 memcpy(Buffer
+ i
* 512, MbBuf
+ (offset
% SIZE_1MB
), 512);
627 static int VentoyFatMemWrite(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
633 for (i
= 0; i
< SectorCount
; i
++)
635 offset
= (Sector
+ i
) * 512;
637 if (g_part_img_buf
[1] == NULL
)
639 MbBuf
= g_part_img_buf
[0] + offset
;
640 memcpy(MbBuf
, Buffer
+ i
* 512, 512);
644 MbBuf
= g_part_img_buf
[offset
/ SIZE_1MB
];
645 memcpy(MbBuf
+ (offset
% SIZE_1MB
), Buffer
+ i
* 512, 512);
652 int VentoyProcSecureBoot(BOOL SecureBoot
)
656 char *filebuf
= NULL
;
659 Log("VentoyProcSecureBoot %d ...", SecureBoot
);
663 Log("Secure boot is enabled ...");
669 if (0 == fl_attach_media(VentoyFatMemRead
, VentoyFatMemWrite
))
671 file
= fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
672 Log("Open ventoy efi file %p ", file
);
675 fl_fseek(file
, 0, SEEK_END
);
676 size
= (int)fl_ftell(file
);
677 fl_fseek(file
, 0, SEEK_SET
);
679 Log("ventoy efi file size %d ...", size
);
681 filebuf
= (char *)malloc(size
);
684 fl_fread(filebuf
, 1, size
, file
);
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");
696 file
= fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
697 Log("Open bootx64 efi file %p ", file
);
702 fl_fwrite(filebuf
, 1, size
, file
);
715 file
= fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");
716 Log("Open ventoy efi file %p ", file
);
719 fl_fseek(file
, 0, SEEK_END
);
720 size
= (int)fl_ftell(file
);
721 fl_fseek(file
, 0, SEEK_SET
);
723 Log("ventoy efi file size %d ...", size
);
725 filebuf
= (char *)malloc(size
);
728 fl_fread(filebuf
, 1, size
, file
);
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");
739 file
= fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");
740 Log("Open bootia32 efi file %p ", file
);
745 fl_fwrite(filebuf
, 1, size
, file
);
771 static int disk_xz_flush(void *src
, unsigned int size
)
774 BYTE
*buf
= (BYTE
*)src
;
776 for (i
= 0; i
< size
; i
++)
778 *g_part_img_pos
= *buf
++;
781 if ((g_disk_unxz_len
% SIZE_1MB
) == 0)
783 g_part_img_pos
= g_part_img_buf
[g_disk_unxz_len
/ SIZE_1MB
];
794 static void unxz_error(char *x
)
799 static BOOL
TryWritePart2(HANDLE hDrive
, UINT64 StartSectorId
)
802 DWORD TrySize
= 16 * 1024;
805 unsigned char *data
= NULL
;
806 LARGE_INTEGER liCurrentPosition
;
808 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
809 SetFilePointerEx(hDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
811 Buffer
= malloc(TrySize
);
813 bRet
= WriteFile(hDrive
, Buffer
, TrySize
, &dwSize
, NULL
);
817 Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
819 if (bRet
&& dwSize
== TrySize
)
827 static int FormatPart2Fat(HANDLE hDrive
, UINT64 StartSectorId
)
834 int Pos
= PT_WRITE_VENTOY_START
;
837 unsigned char *data
= NULL
;
838 LARGE_INTEGER liCurrentPosition
;
839 LARGE_INTEGER liNewPosition
;
840 BYTE
*CheckBuf
= NULL
;
842 Log("FormatPart2Fat %llu...", StartSectorId
);
844 CheckBuf
= malloc(SIZE_1MB
);
847 Log("Failed to malloc check buf");
851 rc
= ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG
, 0, (void **)&data
, &len
);
854 Log("Failed to read img file %p %u", data
, len
);
859 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
860 SetFilePointerEx(hDrive
, liCurrentPosition
, &liNewPosition
, FILE_BEGIN
);
862 memset(g_part_img_buf
, 0, sizeof(g_part_img_buf
));
864 g_part_img_buf
[0] = (BYTE
*)malloc(VENTOY_EFI_PART_SIZE
);
865 if (g_part_img_buf
[0])
867 Log("Malloc whole img buffer success, now decompress ...");
868 unxz(data
, len
, NULL
, NULL
, g_part_img_buf
[0], &writelen
, unxz_error
);
872 Log("decompress finished success");
874 VentoyProcSecureBoot(g_SecureBoot
);
876 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
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
);
888 PROGRESS_BAR_SET_POS(Pos
);
895 //Read and check the data
896 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
897 SetFilePointerEx(hDrive
, liCurrentPosition
, &liNewPosition
, FILE_BEGIN
);
899 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
901 bRet
= ReadFile(hDrive
, CheckBuf
, SIZE_1MB
, &dwSize
, NULL
);
902 Log("Read part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
904 if (!bRet
|| memcmp(CheckBuf
, g_part_img_buf
[0] + i
* SIZE_1MB
, SIZE_1MB
))
906 Log("### [Check Fail] The data write and read does not match");
911 PROGRESS_BAR_SET_POS(Pos
);
921 Log("decompress finished failed");
927 Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE
);
930 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
932 g_part_img_buf
[i
] = (BYTE
*)malloc(SIZE_1MB
);
933 if (g_part_img_buf
[i
] == NULL
)
940 Log("Malloc part img buffer success, now decompress ...");
942 g_part_img_pos
= g_part_img_buf
[0];
944 unxz(data
, len
, NULL
, disk_xz_flush
, NULL
, NULL
, unxz_error
);
946 if (g_disk_unxz_len
== VENTOY_EFI_PART_SIZE
)
948 Log("decompress finished success");
950 VentoyProcSecureBoot(g_SecureBoot
);
952 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
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
);
964 PROGRESS_BAR_SET_POS(Pos
);
971 //Read and check the data
972 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
973 SetFilePointerEx(hDrive
, liCurrentPosition
, &liNewPosition
, FILE_BEGIN
);
975 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
977 bRet
= ReadFile(hDrive
, CheckBuf
, SIZE_1MB
, &dwSize
, NULL
);
978 Log("Read part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
980 if (!bRet
|| memcmp(CheckBuf
, g_part_img_buf
[i
], SIZE_1MB
))
982 Log("### [Check Fail] The data write and read does not match");
987 PROGRESS_BAR_SET_POS(Pos
);
997 Log("decompress finished failed");
1004 if (data
) free(data
);
1005 if (CheckBuf
)free(CheckBuf
);
1009 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1011 if (g_part_img_buf
[i
]) free(g_part_img_buf
[i
]);
1016 if (g_part_img_buf
[0]) free(g_part_img_buf
[0]);
1022 static int WriteGrubStage1ToPhyDrive(HANDLE hDrive
, int PartStyle
)
1028 BYTE
*ImgBuf
= NULL
;
1029 BYTE
*RawBuf
= NULL
;
1031 Log("WriteGrubStage1ToPhyDrive ...");
1033 RawBuf
= (BYTE
*)malloc(SIZE_1MB
);
1039 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG
, 0, (void **)&ImgBuf
, &Len
))
1041 Log("Failed to read stage1 img");
1046 unxz(ImgBuf
, Len
, NULL
, NULL
, RawBuf
, &readLen
, unxz_error
);
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
);
1057 Log("Write MBR stage1 ...");
1058 SetFilePointer(hDrive
, 512, NULL
, FILE_BEGIN
);
1059 bRet
= WriteFile(hDrive
, RawBuf
, SIZE_1MB
- 512, &dwSize
, NULL
);
1062 Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet
, dwSize
, GetLastError());
1071 static int FormatPart1exFAT(UINT64 DiskSizeBytes
)
1076 Option
.fmt
= FM_EXFAT
;
1081 // < 32GB select 32KB as cluster size
1082 // > 32GB select 128KB as cluster size
1083 if (DiskSizeBytes
/ 1024 / 1024 / 1024 <= 32)
1085 Option
.au_size
= 32768;
1089 Option
.au_size
= 131072;
1092 Log("Formatting Part1 exFAT ...");
1094 Ret
= f_mkfs(TEXT("0:"), &Option
, 0, 8 * 1024 * 1024);
1097 Log("Formatting Part1 exFAT success");
1102 Log("Formatting Part1 exFAT failed");
1109 int ClearVentoyFromPhyDrive(HWND hWnd
, PHY_DRIVE_INFO
*pPhyDrive
, char *pDrvLetter
)
1118 CHAR DriveName
[] = "?:\\";
1119 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1120 LARGE_INTEGER liCurrentPosition
;
1121 char *pTmpBuf
= NULL
;
1126 Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
1127 pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1128 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1130 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1132 Log("Lock disk for clean ............................. ");
1134 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1135 if (hDrive
== INVALID_HANDLE_VALUE
)
1137 Log("Failed to open physical disk");
1141 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1143 if (DriveLetters
[0] == 0)
1145 Log("No drive letter was assigned...");
1146 DriveName
[0] = GetFirstUnusedDriveLetter();
1147 Log("GetFirstUnusedDriveLetter %C: ...", DriveName
[0]);
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
--)
1155 DriveName
[0] = DriveLetters
[i
- 1];
1156 bRet
= DeleteVolumeMountPointA(DriveName
);
1157 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, GetLastError());
1161 MountDrive
= DriveName
[0];
1162 Log("Will use '%C:' as volume mountpoint", DriveName
[0]);
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
);
1169 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
1171 if (!VDS_DeleteAllPartitions(pPhyDrive
->PhyDrive
))
1173 Log("Notice: Could not delete partitions: %u", GetLastError());
1176 Log("Deleting all partitions ......................... OK");
1178 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
1180 Log("Lock disk for write ............................. ");
1181 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1182 if (hDrive
== INVALID_HANDLE_VALUE
)
1184 Log("Failed to GetPhysicalHandle for write.");
1189 // clear first and last 2MB space
1190 pTmpBuf
= malloc(SIZE_2MB
);
1193 Log("Failed to alloc memory.");
1197 memset(pTmpBuf
, 0, SIZE_2MB
);
1200 bRet
= WriteFile(hDrive
, pTmpBuf
, SIZE_2MB
- 512, &dwSize
, NULL
);
1201 Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
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
);
1219 if (pPhyDrive
->SizeInBytes
> 2199023255552ULL)
1221 VTOY_GPT_INFO
*pGptInfo
;
1222 VTOY_GPT_HDR BackupHead
;
1223 LARGE_INTEGER liCurrentPosition
;
1225 pGptInfo
= (VTOY_GPT_INFO
*)pTmpBuf
;
1227 VentoyFillWholeGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1229 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512);
1230 VentoyFillBackupGptHead(pGptInfo
, &BackupHead
);
1231 if (!WriteFile(hDrive
, &BackupHead
, sizeof(VTOY_GPT_HDR
), &dwSize
, NULL
))
1234 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1238 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512 * 33);
1239 if (!WriteFile(hDrive
, pGptInfo
->PartTbl
, sizeof(pGptInfo
->PartTbl
), &dwSize
, NULL
))
1242 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1247 if (!WriteFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
))
1250 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1254 Log("Write GPT Info OK ...");
1258 bRet
= ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
1259 Log("Read MBR ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1266 //clear boot code and partition table (reserved disk signature)
1267 memset(MBR
.BootCode
, 0, 440);
1268 memset(MBR
.PartTbl
, 0, sizeof(MBR
.PartTbl
));
1270 VentoyFillMBRLocation(pPhyDrive
->SizeInBytes
, 2048, (UINT32
)(pPhyDrive
->SizeInBytes
/ 512 - 2048), MBR
.PartTbl
);
1272 MBR
.PartTbl
[0].Active
= 0x00; // bootable
1273 MBR
.PartTbl
[0].FsFlag
= 0x07; // exFAT/NTFS/HPFS
1276 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
1277 Log("Write MBR ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1285 Log("Clear Ventoy successfully finished");
1287 //Refresh Drive Layout
1288 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1292 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1301 Log("Mounting Ventoy Partition ....................... ");
1305 memset(DriveLetters
, 0, sizeof(DriveLetters
));
1306 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1307 Log("Logical drive letter after write ventoy: <%s>", DriveLetters
);
1309 for (i
= 0; i
< sizeof(DriveLetters
) && DriveLetters
[i
]; i
++)
1311 DriveName
[0] = DriveLetters
[i
];
1312 Log("%s is ventoy part1, already mounted", DriveName
);
1318 Log("need to mount ventoy part1...");
1319 if (0 == GetVentoyVolumeName(pPhyDrive
->PhyDrive
, 2048, DriveLetters
, sizeof(DriveLetters
), FALSE
))
1321 DriveName
[0] = MountDrive
;
1322 bRet
= SetVolumeMountPointA(DriveName
, DriveLetters
);
1323 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName
, DriveLetters
, bRet
, GetLastError());
1325 *pDrvLetter
= MountDrive
;
1329 Log("Failed to find ventoy volume");
1337 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
1340 CHECK_CLOSE_HANDLE(hDrive
);
1344 int InstallVentoy2FileImage(PHY_DRIVE_INFO
*pPhyDrive
, int PartStyle
)
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
;
1367 Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",
1368 PartStyle
? "GPT" : "MBR", pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1369 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1371 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1373 size
= SIZE_1MB
+ VENTOY_EFI_PART_SIZE
+ 33 * 512 + VTSI_IMG_MAX_SEG
* sizeof(VTSI_SEGMENT
) + sizeof(VTSI_FOOTER
);
1375 pData
= (UINT8
*)malloc(size
);
1378 Log("malloc image buffer failed %d.", size
);
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
));
1387 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
);
1389 Log("Writing Boot Image ............................. ");
1390 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG
, 0, (void **)&ImgBuf
, &Len
))
1392 Log("Failed to read stage1 img");
1396 unxz(ImgBuf
, Len
, NULL
, NULL
, pData
, &dataLen
, unxz_error
);
1399 Log("decompress %s len:%d", VENTOY_FILE_STG1_IMG
, dataLen
);
1403 pData
[500] = 35;//update blocklist
1404 memmove(pData
+ 34 * 512, pData
, SIZE_1MB
- 512 * 34);
1405 memset(pData
, 0, 34 * 512);
1407 pGptInfo
= (VTOY_GPT_INFO
*)pData
;
1408 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
1409 VentoyFillGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1411 pBkGptPartTbl
= pData
+ SIZE_1MB
+ VENTOY_EFI_PART_SIZE
;
1412 memset(pBkGptPartTbl
, 0, 33 * 512);
1414 memcpy(pBkGptPartTbl
, pGptInfo
->PartTbl
, 32 * 512);
1415 pBkGptHdr
= (VTOY_GPT_HDR
*)(pBkGptPartTbl
+ 32 * 512);
1416 VentoyFillBackupGptHead(pGptInfo
, pBkGptHdr
);
1418 Part1StartSector
= pGptInfo
->PartTbl
[0].StartLBA
;
1419 Part1SectorCount
= pGptInfo
->PartTbl
[0].LastLBA
- Part1StartSector
+ 1;
1420 Part2StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
1422 Log("Write GPT Info OK ...");
1426 memmove(pData
+ 512, pData
, SIZE_1MB
- 512);
1427 memset(pData
, 0, 512);
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
;
1435 Log("Write MBR OK ...");
1438 Log("Writing EFI part Image ............................. ");
1439 rc
= ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG
, 0, (void **)&ImgBuf
, &Len
);
1442 Log("Failed to read img file %p %u", ImgBuf
, Len
);
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
);
1451 Log("decompress finished success");
1452 g_part_img_buf
[0] = pData
+ SIZE_1MB
;
1454 VentoyProcSecureBoot(g_SecureBoot
);
1458 Log("decompress finished failed");
1462 fopen_s(&fp
, "VentoySparseImg.vtsi", "wb+");
1465 Log("Failed to create Ventoy img file");
1469 Log("Writing stage1 data ............................. ");
1471 fwrite(pData
, 1, SIZE_1MB
, fp
);
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;
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
);
1481 Log("Formatting part1 exFAT ...");
1482 if (0 != FormatPart1exFAT(pPhyDrive
->SizeInBytes
))
1484 Log("FormatPart1exFAT failed.");
1485 disk_io_reset_imghook(&segnum
, &data_offset
);
1489 disk_io_reset_imghook(&segnum
, &data_offset
);
1492 Log("current segment number:%d dataoff:%ld", segnum
, (long)data_offset
);
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;
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;
1514 Log("Writing segment metadata ............................. ");
1516 for (i
= 0; i
< (int)segnum
; i
++)
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);
1522 dataLen
= segnum
* sizeof(VTSI_SEGMENT
);
1523 fwrite(pSegment
, 1, dataLen
, fp
);
1527 //pData + SIZE_1MB - 8192 is a temp data buffer with zero
1528 fwrite(pData
+ SIZE_1MB
- 8192, 1, 512 - (dataLen
% 512), fp
);
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
;
1539 for (i
= 0, chksum
= 0; i
< (int)(segnum
* sizeof(VTSI_SEGMENT
)); i
++)
1541 chksum
+= *((UINT8
*)pSegment
+ i
);
1543 pImgFooter
->segment_chksum
= ~chksum
;
1545 for (i
= 0, chksum
= 0; i
< sizeof(VTSI_FOOTER
); i
++)
1547 chksum
+= *((UINT8
*)pImgFooter
+ i
);
1549 pImgFooter
->foot_chksum
= ~chksum
;
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
);
1554 fwrite(pImgFooter
, 1, sizeof(VTSI_FOOTER
), fp
);
1557 Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset
+ 512 + ((dataLen
+ 511) / 512 * 512));
1563 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1565 Log("retcode:%d\n", rc
);
1574 int InstallVentoy2PhyDrive(PHY_DRIVE_INFO
*pPhyDrive
, int PartStyle
, int TryId
)
1583 CHAR DriveName
[] = "?:\\";
1584 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1586 VTOY_GPT_INFO
*pGptInfo
= NULL
;
1587 UINT64 Part1StartSector
= 0;
1588 UINT64 Part1SectorCount
= 0;
1589 UINT64 Part2StartSector
= 0;
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
));
1597 pGptInfo
= malloc(sizeof(VTOY_GPT_INFO
));
1598 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
1601 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
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
;
1612 VentoyFillMBR(pPhyDrive
->SizeInBytes
, &MBR
, PartStyle
);
1613 Part1StartSector
= MBR
.PartTbl
[0].StartSectorId
;
1614 Part1SectorCount
= MBR
.PartTbl
[0].SectorCount
;
1615 Part2StartSector
= MBR
.PartTbl
[1].StartSectorId
;
1618 Log("Lock disk for clean ............................. ");
1620 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1621 if (hDrive
== INVALID_HANDLE_VALUE
)
1623 Log("Failed to open physical disk");
1628 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1630 if (DriveLetters
[0] == 0)
1632 Log("No drive letter was assigned...");
1633 DriveName
[0] = GetFirstUnusedDriveLetter();
1634 Log("GetFirstUnusedDriveLetter %C: ...", DriveName
[0]);
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
--)
1642 DriveName
[0] = DriveLetters
[i
- 1];
1643 bRet
= DeleteVolumeMountPointA(DriveName
);
1644 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, GetLastError());
1648 MountDrive
= DriveName
[0];
1649 Log("Will use '%C:' as volume mountpoint", DriveName
[0]);
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
);
1656 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
1658 if (!VDS_DeleteAllPartitions(pPhyDrive
->PhyDrive
))
1660 Log("Notice: Could not delete partitions: %u", GetLastError());
1663 Log("Deleting all partitions ......................... OK");
1665 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
1667 Log("Lock disk for write ............................. ");
1668 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1669 if (hDrive
== INVALID_HANDLE_VALUE
)
1671 Log("Failed to GetPhysicalHandle for write.");
1676 //Refresh Drive Layout
1677 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1679 disk_io_set_param(hDrive
, Part1StartSector
+ Part1SectorCount
);// include the 2048 sector gap
1681 PROGRESS_BAR_SET_POS(PT_FORMAT_PART1
);
1683 if (PartStyle
== 1 && pPhyDrive
->PartStyle
== 0)
1685 Log("Wait for format part1 ...");
1689 Log("Formatting part1 exFAT ...");
1690 if (0 != FormatPart1exFAT(pPhyDrive
->SizeInBytes
))
1692 Log("FormatPart1exFAT failed.");
1697 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
1698 Log("Writing part2 FAT img ...");
1700 if (0 != FormatPart2Fat(hDrive
, Part2StartSector
))
1702 Log("FormatPart2Fat failed.");
1707 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG
);
1708 Log("Writing Boot Image ............................. ");
1709 if (WriteGrubStage1ToPhyDrive(hDrive
, PartStyle
) != 0)
1711 Log("WriteGrubStage1ToPhyDrive failed.");
1716 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE
);
1717 Log("Writing Partition Table ........................ ");
1718 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
1722 VTOY_GPT_HDR BackupHead
;
1723 LARGE_INTEGER liCurrentPosition
;
1725 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512);
1726 VentoyFillBackupGptHead(pGptInfo
, &BackupHead
);
1727 if (!WriteFile(hDrive
, &BackupHead
, sizeof(VTOY_GPT_HDR
), &dwSize
, NULL
))
1730 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1734 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512 * 33);
1735 if (!WriteFile(hDrive
, pGptInfo
->PartTbl
, sizeof(pGptInfo
->PartTbl
), &dwSize
, NULL
))
1738 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1743 if (!WriteFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
))
1746 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1750 Log("Write GPT Info OK ...");
1751 memcpy(&(pPhyDrive
->MBR
), &(pGptInfo
->MBR
), 512);
1755 if (!WriteFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
))
1758 Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize
, GetLastError());
1761 Log("Write MBR OK ...");
1762 memcpy(&(pPhyDrive
->MBR
), &MBR
, 512);
1765 //Refresh Drive Layout
1766 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1770 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1774 Log("Mounting Ventoy Partition ....................... ");
1778 memset(DriveLetters
, 0, sizeof(DriveLetters
));
1779 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1780 Log("Logical drive letter after write ventoy: <%s>", DriveLetters
);
1782 for (i
= 0; i
< sizeof(DriveLetters
) && DriveLetters
[i
]; i
++)
1784 DriveName
[0] = DriveLetters
[i
];
1785 if (IsVentoyLogicalDrive(DriveName
[0]))
1787 Log("%s is ventoy part2, delete mountpoint", DriveName
);
1788 DeleteVolumeMountPointA(DriveName
);
1792 Log("%s is ventoy part1, already mounted", DriveName
);
1799 Log("need to mount ventoy part1...");
1801 if (0 == GetVentoyVolumeName(pPhyDrive
->PhyDrive
, Part1StartSector
, DriveLetters
, sizeof(DriveLetters
), FALSE
))
1803 DriveName
[0] = MountDrive
;
1804 bRet
= SetVolumeMountPointA(DriveName
, DriveLetters
);
1805 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName
, DriveLetters
, bRet
, GetLastError());
1809 Log("Failed to find ventoy volume");
1816 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
1824 CHECK_CLOSE_HANDLE(hDrive
);
1829 int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO
*pPhyDrive
, int TryId
)
1834 BOOL ForceMBR
= FALSE
;
1835 BOOL Esp2Basic
= FALSE
;
1841 CHAR DriveName
[] = "?:\\";
1842 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1844 UINT64 ReservedMB
= 0;
1847 VTOY_GPT_INFO
*pGptInfo
= NULL
;
1848 UINT8 ReservedData
[4096];
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
));
1854 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1856 Log("Lock disk for umount ............................ ");
1858 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1859 if (hDrive
== INVALID_HANDLE_VALUE
)
1861 Log("Failed to open physical disk");
1865 if (pPhyDrive
->PartStyle
)
1867 pGptInfo
= malloc(sizeof(VTOY_GPT_INFO
));
1873 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
1876 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
1877 ReadFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
);
1879 //MBR will be used to compare with local boot image
1880 memcpy(&MBR
, &pGptInfo
->MBR
, sizeof(MBR_HEAD
));
1882 StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
1883 Log("GPT StartSector in PartTbl:%llu", (ULONGLONG
)StartSector
);
1885 ReservedMB
= (pPhyDrive
->SizeInBytes
/ 512 - (StartSector
+ VENTOY_EFI_PART_SIZE
/ 512) - 33) / 2048;
1886 Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG
)ReservedMB
);
1891 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
1892 ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
1894 StartSector
= MBR
.PartTbl
[1].StartSectorId
;
1895 Log("MBR StartSector in PartTbl:%llu", (ULONGLONG
)StartSector
);
1897 ReservedMB
= (pPhyDrive
->SizeInBytes
/ 512 - (StartSector
+ VENTOY_EFI_PART_SIZE
/ 512)) / 2048;
1898 Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG
)ReservedMB
);
1901 //Read Reserved Data
1902 SetFilePointer(hDrive
, 512 * 2040, NULL
, FILE_BEGIN
);
1903 ReadFile(hDrive
, ReservedData
, sizeof(ReservedData
), &dwSize
, NULL
);
1905 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1907 if (DriveLetters
[0] == 0)
1909 Log("No drive letter was assigned...");
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
--)
1917 DriveName
[0] = DriveLetters
[i
- 1];
1918 if (IsVentoyLogicalDrive(DriveName
[0]))
1920 Log("%s is ventoy logical drive", DriveName
);
1921 bRet
= DeleteVolumeMountPointA(DriveName
);
1922 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, LASTERR
);
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
);
1933 if (pPhyDrive
->PartStyle
== 1)
1935 Log("TryId=%d EFI GPT partition type is 0x%llx", TryId
, pPhyDrive
->Part2GPTAttr
);
1937 if ((TryId
== 1 && (pPhyDrive
->Part2GPTAttr
>> 56) == 0xC0) || TryId
== 2)
1939 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
1940 Log("Change GPT partition type to ESP");
1942 if (VDS_ChangeVtoyEFI2ESP(pPhyDrive
->PhyDrive
, StartSector
* 512))
1950 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
1952 Log("Lock disk for update ............................ ");
1953 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1954 if (hDrive
== INVALID_HANDLE_VALUE
)
1956 Log("Failed to GetPhysicalHandle for write.");
1961 PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME
);
1963 Log("Lock volume for update .......................... ");
1964 hVolume
= INVALID_HANDLE_VALUE
;
1966 //If we change VTOYEFI to ESP, it can not have s volume name, so don't try to get it.
1969 Status
= ERROR_NOT_FOUND
;
1973 for (i
= 0; i
< MaxRetry
; i
++)
1975 Status
= GetVentoyVolumeName(pPhyDrive
->PhyDrive
, StartSector
, DriveLetters
, sizeof(DriveLetters
), TRUE
);
1976 if (ERROR_SUCCESS
== Status
)
1982 Log("==== Volume not found, wait and retry %d... ====", i
);
1988 if (ERROR_SUCCESS
== Status
)
1990 Log("Now lock and dismount volume <%s>", DriveLetters
);
1992 for (i
= 0; i
< MaxRetry
; i
++)
1994 hVolume
= CreateFileA(DriveLetters
,
1995 GENERIC_READ
| GENERIC_WRITE
,
1999 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_NO_BUFFERING
| FILE_FLAG_WRITE_THROUGH
,
2002 if (hVolume
== INVALID_HANDLE_VALUE
)
2004 Log("Failed to create file volume, errcode:%u, wait and retry ...", LASTERR
);
2013 if (hVolume
== INVALID_HANDLE_VALUE
)
2015 Log("Failed to create file volume, errcode:%u", LASTERR
);
2019 bRet
= DeviceIoControl(hVolume
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2020 Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
2022 bRet
= DeviceIoControl(hVolume
, FSCTL_DISMOUNT_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2023 Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
2026 else if (ERROR_NOT_FOUND
== Status
)
2028 Log("Volume not found, maybe not supported");
2036 if (!TryWritePart2(hDrive
, StartSector
))
2038 if (pPhyDrive
->PartStyle
== 0)
2042 Log("Try write failed, now delete partition 2 for MBR...");
2043 CHECK_CLOSE_HANDLE(hDrive
);
2045 Log("Now delete partition 2...");
2046 VDS_DeleteVtoyEFIPartition(pPhyDrive
->PhyDrive
);
2048 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
2049 if (hDrive
== INVALID_HANDLE_VALUE
)
2051 Log("Failed to GetPhysicalHandle for write.");
2058 Log("TryWritePart2 failed ....");
2064 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
2066 Log("Write Ventoy to disk ............................ ");
2067 if (0 != FormatPart2Fat(hDrive
, StartSector
))
2073 if (hVolume
!= INVALID_HANDLE_VALUE
)
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
);
2080 Log("Updating Boot Image ............................. ");
2081 if (WriteGrubStage1ToPhyDrive(hDrive
, pPhyDrive
->PartStyle
) != 0)
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
);
2093 VentoyGetLocalBootImg(&BootImg
);
2096 memcpy(BootImg
.BootCode
+ 0x180, MBR
.BootCode
+ 0x180, 16);
2097 if (pPhyDrive
->PartStyle
)
2099 BootImg
.BootCode
[92] = 0x22;
2102 if (ForceMBR
== FALSE
&& memcmp(BootImg
.BootCode
, MBR
.BootCode
, 440) == 0)
2104 Log("Boot image has no difference, no need to write.");
2108 Log("Boot image need to write %u.", ForceMBR
);
2110 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
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
);
2117 if (pPhyDrive
->PartStyle
== 0)
2119 if (0x00 == MBR
.PartTbl
[0].Active
&& 0x80 == MBR
.PartTbl
[1].Active
)
2121 Log("Need to chage 1st partition active and 2nd partition inactive.");
2123 MBR
.PartTbl
[0].Active
= 0x80;
2124 MBR
.PartTbl
[1].Active
= 0x00;
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
);
2132 //Refresh Drive Layout
2133 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2143 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
2146 CHECK_CLOSE_HANDLE(hDrive
);
2150 Log("Recover GPT partition type to basic");
2151 VDS_ChangeVtoyEFI2Basic(pPhyDrive
->PhyDrive
, StartSector
* 512);