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;
37 static BOOL
WriteDataToPhyDisk(HANDLE hDrive
, UINT64 Offset
, VOID
*buffer
, DWORD len
)
41 LARGE_INTEGER liCurPosition
;
42 LARGE_INTEGER liNewPosition
;
44 liCurPosition
.QuadPart
= (LONGLONG
)Offset
;
45 liNewPosition
.QuadPart
= 0;
46 if (0 == SetFilePointerEx(hDrive
, liCurPosition
, &liNewPosition
, FILE_BEGIN
) ||
47 liNewPosition
.QuadPart
!= liCurPosition
.QuadPart
)
49 Log("SetFilePointerEx Failed %u", LASTERR
);
53 bRet
= WriteFile(hDrive
, buffer
, len
, &dwSize
, NULL
);
54 if (bRet
== FALSE
|| dwSize
!= len
)
56 Log("Write file error %u %u", dwSize
, LASTERR
);
64 static DWORD
GetVentoyVolumeName(int PhyDrive
, UINT64 StartSectorId
, CHAR
*NameBuf
, UINT32 BufLen
, BOOL DelSlash
)
72 DWORD Status
= ERROR_NOT_FOUND
;
73 DISK_EXTENT
*pExtents
= NULL
;
74 CHAR VolumeName
[MAX_PATH
] = { 0 };
75 VOLUME_DISK_EXTENTS DiskExtents
;
77 PartOffset
= 512ULL * StartSectorId
;
79 Log("GetVentoyVolumeName PhyDrive %d SectorStart:%llu PartOffset:%llu", PhyDrive
, (ULONGLONG
)StartSectorId
, (ULONGLONG
)PartOffset
);
81 hVolume
= FindFirstVolumeA(VolumeName
, sizeof(VolumeName
));
82 if (hVolume
== INVALID_HANDLE_VALUE
)
89 len
= strlen(VolumeName
);
90 Log("Find volume:%s", VolumeName
);
92 VolumeName
[len
- 1] = 0;
94 hDrive
= CreateFileA(VolumeName
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
95 if (hDrive
== INVALID_HANDLE_VALUE
)
100 bRet
= DeviceIoControl(hDrive
,
101 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
105 (DWORD
)(sizeof(DiskExtents
)),
109 Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet
, LASTERR
);
110 Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents
.NumberOfDiskExtents
, DiskExtents
.Extents
[0].DiskNumber
);
112 if (bRet
&& DiskExtents
.NumberOfDiskExtents
== 1)
114 pExtents
= DiskExtents
.Extents
;
116 Log("This volume DiskNumber:%u offset:%llu", pExtents
->DiskNumber
, (ULONGLONG
)pExtents
->StartingOffset
.QuadPart
);
117 if ((int)pExtents
->DiskNumber
== PhyDrive
&& pExtents
->StartingOffset
.QuadPart
== PartOffset
)
119 Log("This volume match");
123 VolumeName
[len
- 1] = '\\';
126 sprintf_s(NameBuf
, BufLen
, "%s", VolumeName
);
127 Status
= ERROR_SUCCESS
;
134 } while (FindNextVolumeA(hVolume
, VolumeName
, sizeof(VolumeName
)));
136 FindVolumeClose(hVolume
);
138 Log("GetVentoyVolumeName return %u", Status
);
142 int GetLettersBelongPhyDrive(int PhyDrive
, char *DriveLetters
, size_t Length
)
147 CHAR
*StringBuf
= NULL
;
149 DataSize
= GetLogicalDriveStringsA(0, NULL
);
150 StringBuf
= (CHAR
*)malloc(DataSize
+ 1);
151 if (StringBuf
== NULL
)
156 GetLogicalDriveStringsA(DataSize
, StringBuf
);
158 for (Pos
= StringBuf
; *Pos
; Pos
+= strlen(Pos
) + 1)
160 if (n
< (int)Length
&& PhyDrive
== GetPhyDriveByLogicalDrive(Pos
[0], NULL
))
162 Log("%C: is belong to phydrive%d", Pos
[0], PhyDrive
);
163 DriveLetters
[n
++] = Pos
[0];
171 HANDLE
GetPhysicalHandle(int Drive
, BOOLEAN bLockDrive
, BOOLEAN bWriteAccess
, BOOLEAN bWriteShare
)
177 HANDLE hDrive
= INVALID_HANDLE_VALUE
;
179 CHAR DevPath
[MAX_PATH
] = { 0 };
181 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", Drive
);
183 if (0 == QueryDosDeviceA(PhyDrive
+ 4, DevPath
, sizeof(DevPath
)))
185 Log("QueryDosDeviceA failed error:%u", GetLastError());
186 strcpy_s(DevPath
, sizeof(DevPath
), "???");
190 Log("QueryDosDeviceA success %s", DevPath
);
193 for (i
= 0; i
< DRIVE_ACCESS_RETRIES
; i
++)
195 // Try without FILE_SHARE_WRITE (unless specifically requested) so that
196 // we won't be bothered by the OS or other apps when we set up our data.
197 // However this means we might have to wait for an access gap...
198 // We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is
199 // required for enumeration.
200 hDrive
= CreateFileA(PhyDrive
,
201 GENERIC_READ
| (bWriteAccess
? GENERIC_WRITE
: 0),
202 FILE_SHARE_READ
| (bWriteShare
? FILE_SHARE_WRITE
: 0),
205 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_NO_BUFFERING
| FILE_FLAG_WRITE_THROUGH
,
208 LastError
= GetLastError();
209 Log("[%d] CreateFileA %s code:%u %p", i
, PhyDrive
, LastError
, hDrive
);
211 if (hDrive
!= INVALID_HANDLE_VALUE
)
216 if ((LastError
!= ERROR_SHARING_VIOLATION
) && (LastError
!= ERROR_ACCESS_DENIED
))
223 Log("Waiting for access on %s [%s]...", PhyDrive
, DevPath
);
225 else if (!bWriteShare
&& (i
> DRIVE_ACCESS_RETRIES
/ 3))
227 // If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE...
228 Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");
231 // Try to report the process that is locking the drive
232 // We also use bit 6 as a flag to indicate that SearchProcess was called.
233 //access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40;
236 Sleep(DRIVE_ACCESS_TIMEOUT
/ DRIVE_ACCESS_RETRIES
);
239 if (hDrive
== INVALID_HANDLE_VALUE
)
241 Log("Could not open %s %u", PhyDrive
, LASTERR
);
247 Log("Opened %s for %s write access", PhyDrive
, bWriteShare
? "shared" : "exclusive");
252 if (DeviceIoControl(hDrive
, FSCTL_ALLOW_EXTENDED_DASD_IO
, NULL
, 0, NULL
, 0, &dwSize
, NULL
))
254 Log("I/O boundary checks disabled");
257 EndTime
= GetTickCount64() + DRIVE_ACCESS_TIMEOUT
;
260 if (DeviceIoControl(hDrive
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
))
262 Log("FSCTL_LOCK_VOLUME success");
265 Sleep(DRIVE_ACCESS_TIMEOUT
/ DRIVE_ACCESS_RETRIES
);
266 } while (GetTickCount64() < EndTime
);
268 // If we reached this section, either we didn't manage to get a lock or the user cancelled
269 Log("Could not lock access to %s %u", PhyDrive
, LASTERR
);
271 // See if we can report the processes are accessing the drive
272 //if (!IS_ERROR(FormatStatus) && (access_mask == 0))
273 // access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE);
274 // Try to continue if the only access rights we saw were for read-only
275 //if ((access_mask & 0x07) != 0x01)
276 // safe_closehandle(hDrive);
278 CHECK_CLOSE_HANDLE(hDrive
);
283 if (hDrive
== INVALID_HANDLE_VALUE
)
285 Log("Can get handle of %s, maybe some process control it.", DevPath
);
291 int GetPhyDriveByLogicalDrive(int DriveLetter
, UINT64
*Offset
)
295 HANDLE Handle
= INVALID_HANDLE_VALUE
;
296 VOLUME_DISK_EXTENTS DiskExtents
;
299 safe_sprintf(PhyPath
, "\\\\.\\%C:", (CHAR
)DriveLetter
);
301 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
302 if (Handle
== INVALID_HANDLE_VALUE
)
304 Log("Could not open the disk<%s>, error:%u", PhyPath
, LASTERR
);
308 memset(&DiskExtents
, 0, sizeof(DiskExtents
));
309 Ret
= DeviceIoControl(Handle
,
310 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
314 (DWORD
)(sizeof(DiskExtents
)),
318 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
320 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath
, LASTERR
);
321 CHECK_CLOSE_HANDLE(Handle
);
324 CHECK_CLOSE_HANDLE(Handle
);
326 Log("LogicalDrive:%s PhyDrive:%d Num:%d Offset:%llu ExtentLength:%llu",
328 DiskExtents
.Extents
[0].DiskNumber
,
329 DiskExtents
.NumberOfDiskExtents
,
330 DiskExtents
.Extents
[0].StartingOffset
.QuadPart
,
331 DiskExtents
.Extents
[0].ExtentLength
.QuadPart
336 *Offset
= (UINT64
)(DiskExtents
.Extents
[0].StartingOffset
.QuadPart
);
339 return (int)DiskExtents
.Extents
[0].DiskNumber
;
342 int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO
*pDriveList
, DWORD
*pDriveCount
)
350 DWORD DriveCount
= 0;
351 HANDLE Handle
= INVALID_HANDLE_VALUE
;
353 PHY_DRIVE_INFO
*CurDrive
= pDriveList
;
354 GET_LENGTH_INFORMATION LengthInfo
;
355 STORAGE_PROPERTY_QUERY Query
;
356 STORAGE_DESCRIPTOR_HEADER DevDescHeader
;
357 STORAGE_DEVICE_DESCRIPTOR
*pDevDesc
;
358 STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment
;
359 int PhyDriveId
[VENTOY_MAX_PHY_DRIVE
];
361 Count
= GetPhysicalDriveCount();
363 for (i
= 0; i
< Count
&& i
< VENTOY_MAX_PHY_DRIVE
; i
++)
368 dwBytes
= GetLogicalDrives();
369 Log("Logical Drives: 0x%x", dwBytes
);
374 id
= GetPhyDriveByLogicalDrive(Letter
, NULL
);
375 Log("%C --> %d", Letter
, id
);
378 for (i
= 0; i
< Count
; i
++)
380 if (PhyDriveId
[i
] == id
)
388 Log("Add phy%d to list", i
);
389 PhyDriveId
[Count
] = id
;
399 for (i
= 0; i
< Count
&& DriveCount
< VENTOY_MAX_PHY_DRIVE
; i
++)
401 CHECK_CLOSE_HANDLE(Handle
);
403 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", PhyDriveId
[i
]);
404 Handle
= CreateFileA(PhyDrive
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
405 Log("Create file Handle:%p %s status:%u", Handle
, PhyDrive
, LASTERR
);
407 if (Handle
== INVALID_HANDLE_VALUE
)
412 bRet
= DeviceIoControl(Handle
,
413 IOCTL_DISK_GET_LENGTH_INFO
, NULL
,
421 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR
);
425 Log("PHYSICALDRIVE%d size %llu bytes", i
, (ULONGLONG
)LengthInfo
.Length
.QuadPart
);
427 Query
.PropertyId
= StorageDeviceProperty
;
428 Query
.QueryType
= PropertyStandardQuery
;
430 bRet
= DeviceIoControl(Handle
,
431 IOCTL_STORAGE_QUERY_PROPERTY
,
435 sizeof(STORAGE_DESCRIPTOR_HEADER
),
440 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR
, dwBytes
);
444 if (DevDescHeader
.Size
< sizeof(STORAGE_DEVICE_DESCRIPTOR
))
446 Log("Invalid DevDescHeader.Size:%u", DevDescHeader
.Size
);
450 pDevDesc
= (STORAGE_DEVICE_DESCRIPTOR
*)malloc(DevDescHeader
.Size
);
453 Log("failed to malloc error:%u len:%u", LASTERR
, DevDescHeader
.Size
);
457 bRet
= DeviceIoControl(Handle
,
458 IOCTL_STORAGE_QUERY_PROPERTY
,
467 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR
, dwBytes
);
474 memset(&Query
, 0, sizeof(STORAGE_PROPERTY_QUERY
));
475 Query
.PropertyId
= StorageAccessAlignmentProperty
;
476 Query
.QueryType
= PropertyStandardQuery
;
477 memset(&diskAlignment
, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
));
479 bRet
= DeviceIoControl(Handle
,
480 IOCTL_STORAGE_QUERY_PROPERTY
,
482 sizeof(STORAGE_PROPERTY_QUERY
),
484 sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
),
489 Log("DeviceIoControl3 error:%u dwBytes:%u", LASTERR
, dwBytes
);
492 CurDrive
->PhyDrive
= i
;
493 CurDrive
->SizeInBytes
= LengthInfo
.Length
.QuadPart
;
494 CurDrive
->DeviceType
= pDevDesc
->DeviceType
;
495 CurDrive
->RemovableMedia
= pDevDesc
->RemovableMedia
;
496 CurDrive
->BusType
= pDevDesc
->BusType
;
498 CurDrive
->BytesPerLogicalSector
= diskAlignment
.BytesPerLogicalSector
;
499 CurDrive
->BytesPerPhysicalSector
= diskAlignment
.BytesPerPhysicalSector
;
501 if (pDevDesc
->VendorIdOffset
)
503 safe_strcpy(CurDrive
->VendorId
, (char *)pDevDesc
+ pDevDesc
->VendorIdOffset
);
504 TrimString(CurDrive
->VendorId
);
507 if (pDevDesc
->ProductIdOffset
)
509 safe_strcpy(CurDrive
->ProductId
, (char *)pDevDesc
+ pDevDesc
->ProductIdOffset
);
510 TrimString(CurDrive
->ProductId
);
513 if (pDevDesc
->ProductRevisionOffset
)
515 safe_strcpy(CurDrive
->ProductRev
, (char *)pDevDesc
+ pDevDesc
->ProductRevisionOffset
);
516 TrimString(CurDrive
->ProductRev
);
519 if (pDevDesc
->SerialNumberOffset
)
521 safe_strcpy(CurDrive
->SerialNumber
, (char *)pDevDesc
+ pDevDesc
->SerialNumberOffset
);
522 TrimString(CurDrive
->SerialNumber
);
530 CHECK_CLOSE_HANDLE(Handle
);
533 for (i
= 0, CurDrive
= pDriveList
; i
< (int)DriveCount
; i
++, CurDrive
++)
535 Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Sector:%u/%u Name:%s %s",
536 CurDrive
->PhyDrive
, GetBusTypeString(CurDrive
->BusType
), CurDrive
->RemovableMedia
,
537 GetHumanReadableGBSize(CurDrive
->SizeInBytes
), CurDrive
->SizeInBytes
,
538 CurDrive
->BytesPerLogicalSector
, CurDrive
->BytesPerPhysicalSector
,
539 CurDrive
->VendorId
, CurDrive
->ProductId
);
542 *pDriveCount
= DriveCount
;
547 BOOL
VentoyPhydriveMatch(PHY_DRIVE_INFO
* pPhyDrive
)
551 HANDLE Handle
= INVALID_HANDLE_VALUE
;
553 GET_LENGTH_INFORMATION LengthInfo
;
554 STORAGE_PROPERTY_QUERY Query
;
555 STORAGE_DESCRIPTOR_HEADER DevDescHeader
;
556 STORAGE_DEVICE_DESCRIPTOR
* pDevDesc
= NULL
;
557 STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment
;
558 CHAR VendorId
[128] = { 0 };
559 CHAR ProductId
[128] = { 0 };
560 CHAR ProductRev
[128] = { 0 };
561 CHAR SerialNumber
[128] = { 0 };
564 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", pPhyDrive
->PhyDrive
);
565 Handle
= CreateFileA(PhyDrive
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
566 if (Handle
== INVALID_HANDLE_VALUE
)
568 Log("Create file Handle:%p %s status:%u", Handle
, PhyDrive
, LASTERR
);
572 bRet
= DeviceIoControl(Handle
,
573 IOCTL_DISK_GET_LENGTH_INFO
, NULL
,
581 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR
);
585 if (pPhyDrive
->SizeInBytes
!= (ULONGLONG
)LengthInfo
.Length
.QuadPart
)
587 Log("PHYSICALDRIVE%d size not match %llu %llu", pPhyDrive
->PhyDrive
, (ULONGLONG
)LengthInfo
.Length
.QuadPart
,
588 (ULONGLONG
)pPhyDrive
->SizeInBytes
);
589 CHECK_CLOSE_HANDLE(Handle
);
593 Query
.PropertyId
= StorageDeviceProperty
;
594 Query
.QueryType
= PropertyStandardQuery
;
596 bRet
= DeviceIoControl(Handle
,
597 IOCTL_STORAGE_QUERY_PROPERTY
,
601 sizeof(STORAGE_DESCRIPTOR_HEADER
),
606 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR
, dwBytes
);
607 CHECK_CLOSE_HANDLE(Handle
);
611 if (DevDescHeader
.Size
< sizeof(STORAGE_DEVICE_DESCRIPTOR
))
613 Log("Invalid DevDescHeader.Size:%u", DevDescHeader
.Size
);
614 CHECK_CLOSE_HANDLE(Handle
);
618 pDevDesc
= (STORAGE_DEVICE_DESCRIPTOR
*)malloc(DevDescHeader
.Size
);
621 Log("failed to malloc error:%u len:%u", LASTERR
, DevDescHeader
.Size
);
622 CHECK_CLOSE_HANDLE(Handle
);
626 bRet
= DeviceIoControl(Handle
,
627 IOCTL_STORAGE_QUERY_PROPERTY
,
636 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR
, dwBytes
);
643 memset(&Query
, 0, sizeof(STORAGE_PROPERTY_QUERY
));
644 Query
.PropertyId
= StorageAccessAlignmentProperty
;
645 Query
.QueryType
= PropertyStandardQuery
;
646 memset(&diskAlignment
, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
));
648 bRet
= DeviceIoControl(Handle
,
649 IOCTL_STORAGE_QUERY_PROPERTY
,
651 sizeof(STORAGE_PROPERTY_QUERY
),
653 sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR
),
658 Log("DeviceIoControl3 error:%u dwBytes:%u", LASTERR
, dwBytes
);
661 if (pPhyDrive
->DeviceType
!= pDevDesc
->DeviceType
||
662 pPhyDrive
->RemovableMedia
!= pDevDesc
->RemovableMedia
||
663 pPhyDrive
->BusType
!= pDevDesc
->BusType
||
664 pPhyDrive
->BytesPerLogicalSector
!= diskAlignment
.BytesPerLogicalSector
||
665 pPhyDrive
->BytesPerPhysicalSector
!= diskAlignment
.BytesPerPhysicalSector
668 Log("Some properties not match DeviceType[%u %u] Removable[%u %u] BusType[%u %u] LogSec[%u %u] PhySec[%u %u]",
669 pPhyDrive
->DeviceType
, pDevDesc
->DeviceType
,
670 pPhyDrive
->RemovableMedia
, pDevDesc
->RemovableMedia
,
671 pPhyDrive
->BusType
, pDevDesc
->BusType
,
672 pPhyDrive
->BytesPerLogicalSector
, diskAlignment
.BytesPerLogicalSector
,
673 pPhyDrive
->BytesPerPhysicalSector
, diskAlignment
.BytesPerPhysicalSector
678 if (pDevDesc
->VendorIdOffset
)
680 safe_strcpy(VendorId
, (char*)pDevDesc
+ pDevDesc
->VendorIdOffset
);
681 TrimString(VendorId
);
683 if (strcmp(pPhyDrive
->VendorId
, VendorId
))
685 Log("VendorId not match <%s %s>", pPhyDrive
->VendorId
, VendorId
);
690 if (pDevDesc
->ProductIdOffset
)
692 safe_strcpy(ProductId
, (char*)pDevDesc
+ pDevDesc
->ProductIdOffset
);
693 TrimString(ProductId
);
695 if (strcmp(pPhyDrive
->ProductId
, ProductId
))
697 Log("ProductId not match <%s %s>", pPhyDrive
->ProductId
, ProductId
);
702 if (pDevDesc
->ProductRevisionOffset
)
704 safe_strcpy(ProductRev
, (char*)pDevDesc
+ pDevDesc
->ProductRevisionOffset
);
705 TrimString(ProductRev
);
707 if (strcmp(pPhyDrive
->ProductRev
, ProductRev
))
709 Log("ProductRev not match <%s %s>", pPhyDrive
->ProductRev
, ProductRev
);
714 if (pDevDesc
->SerialNumberOffset
)
716 safe_strcpy(SerialNumber
, (char*)pDevDesc
+ pDevDesc
->SerialNumberOffset
);
717 TrimString(SerialNumber
);
719 if (strcmp(pPhyDrive
->SerialNumber
, SerialNumber
))
721 Log("ProductRev not match <%s %s>", pPhyDrive
->SerialNumber
, SerialNumber
);
726 Log("PhyDrive%d ALL match, now continue", pPhyDrive
->PhyDrive
);
736 CHECK_CLOSE_HANDLE(Handle
);
741 static HANDLE g_FatPhyDrive
;
742 static UINT64 g_Part2StartSec
;
743 static int GetVentoyVersionFromFatFile(CHAR
*VerBuf
, size_t BufLen
)
750 flfile
= fl_fopen("/grub/grub.cfg", "rb");
753 fl_fseek(flfile
, 0, SEEK_END
);
754 size
= (int)fl_ftell(flfile
);
756 fl_fseek(flfile
, 0, SEEK_SET
);
758 buf
= (char *)malloc(size
+ 1);
761 fl_fread(buf
, 1, size
, flfile
);
765 sprintf_s(VerBuf
, BufLen
, "%s", ParseVentoyVersionFromString(buf
));
775 static int VentoyFatDiskRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
780 LARGE_INTEGER liCurrentPosition
;
782 liCurrentPosition
.QuadPart
= Sector
+ g_Part2StartSec
;
783 liCurrentPosition
.QuadPart
*= 512;
784 SetFilePointerEx(g_FatPhyDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
786 ReadSize
= (DWORD
)(SectorCount
* 512);
788 bRet
= ReadFile(g_FatPhyDrive
, Buffer
, ReadSize
, &dwSize
, NULL
);
789 if (bRet
== FALSE
|| dwSize
!= ReadSize
)
791 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet
, ReadSize
, dwSize
, LASTERR
);
798 int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO
*pDriveInfo
, UINT64 Part2StartSector
, CHAR
*VerBuf
, size_t BufLen
, BOOL
*pSecureBoot
)
804 hDrive
= GetPhysicalHandle(pDriveInfo
->PhyDrive
, FALSE
, FALSE
, FALSE
);
805 if (hDrive
== INVALID_HANDLE_VALUE
)
810 g_FatPhyDrive
= hDrive
;
811 g_Part2StartSec
= Part2StartSector
;
813 Log("Parse FAT fs...");
817 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
819 Log("attach media success...");
820 rc
= GetVentoyVersionFromFatFile(VerBuf
, BufLen
);
824 Log("attach media failed...");
828 Log("GetVentoyVerInPhyDrive rc=%d...", rc
);
831 Log("VentoyVerInPhyDrive %d is <%s>...", pDriveInfo
->PhyDrive
, VerBuf
);
833 flfile
= fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
843 CHECK_CLOSE_HANDLE(hDrive
);
852 static unsigned int g_disk_unxz_len
= 0;
853 static BYTE
*g_part_img_pos
= NULL
;
854 static BYTE
*g_part_img_buf
[VENTOY_EFI_PART_SIZE
/ SIZE_1MB
];
857 static int VentoyFatMemRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
863 for (i
= 0; i
< SectorCount
; i
++)
865 offset
= (Sector
+ i
) * 512;
867 if (g_part_img_buf
[1] == NULL
)
869 MbBuf
= g_part_img_buf
[0] + offset
;
870 memcpy(Buffer
+ i
* 512, MbBuf
, 512);
874 MbBuf
= g_part_img_buf
[offset
/ SIZE_1MB
];
875 memcpy(Buffer
+ i
* 512, MbBuf
+ (offset
% SIZE_1MB
), 512);
883 static int VentoyFatMemWrite(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
889 for (i
= 0; i
< SectorCount
; i
++)
891 offset
= (Sector
+ i
) * 512;
893 if (g_part_img_buf
[1] == NULL
)
895 MbBuf
= g_part_img_buf
[0] + offset
;
896 memcpy(MbBuf
, Buffer
+ i
* 512, 512);
900 MbBuf
= g_part_img_buf
[offset
/ SIZE_1MB
];
901 memcpy(MbBuf
+ (offset
% SIZE_1MB
), Buffer
+ i
* 512, 512);
908 int VentoyProcSecureBoot(BOOL SecureBoot
)
912 char *filebuf
= NULL
;
915 Log("VentoyProcSecureBoot %d ...", SecureBoot
);
919 Log("Secure boot is enabled ...");
925 if (0 == fl_attach_media(VentoyFatMemRead
, VentoyFatMemWrite
))
927 file
= fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
928 Log("Open ventoy efi file %p ", file
);
931 fl_fseek(file
, 0, SEEK_END
);
932 size
= (int)fl_ftell(file
);
933 fl_fseek(file
, 0, SEEK_SET
);
935 Log("ventoy efi file size %d ...", size
);
937 filebuf
= (char *)malloc(size
);
940 fl_fread(filebuf
, 1, size
, file
);
945 Log("Now delete all efi files ...");
946 fl_remove("/EFI/BOOT/BOOTX64.EFI");
947 fl_remove("/EFI/BOOT/grubx64.efi");
948 fl_remove("/EFI/BOOT/grubx64_real.efi");
949 fl_remove("/EFI/BOOT/MokManager.efi");
950 fl_remove("/EFI/BOOT/mmx64.efi");
951 fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
952 fl_remove("/EFI/BOOT/grub.efi");
954 file
= fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
955 Log("Open bootx64 efi file %p ", file
);
960 fl_fwrite(filebuf
, 1, size
, file
);
973 file
= fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");
974 Log("Open ventoy efi file %p ", file
);
977 fl_fseek(file
, 0, SEEK_END
);
978 size
= (int)fl_ftell(file
);
979 fl_fseek(file
, 0, SEEK_SET
);
981 Log("ventoy efi file size %d ...", size
);
983 filebuf
= (char *)malloc(size
);
986 fl_fread(filebuf
, 1, size
, file
);
991 Log("Now delete all efi files ...");
992 fl_remove("/EFI/BOOT/BOOTIA32.EFI");
993 fl_remove("/EFI/BOOT/grubia32.efi");
994 fl_remove("/EFI/BOOT/grubia32_real.efi");
995 fl_remove("/EFI/BOOT/mmia32.efi");
997 file
= fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");
998 Log("Open bootia32 efi file %p ", file
);
1003 fl_fwrite(filebuf
, 1, size
, file
);
1029 static int disk_xz_flush(void *src
, unsigned int size
)
1032 BYTE
*buf
= (BYTE
*)src
;
1034 for (i
= 0; i
< size
; i
++)
1036 *g_part_img_pos
= *buf
++;
1039 if ((g_disk_unxz_len
% SIZE_1MB
) == 0)
1041 g_part_img_pos
= g_part_img_buf
[g_disk_unxz_len
/ SIZE_1MB
];
1052 static void unxz_error(char *x
)
1057 static BOOL
TryWritePart2(HANDLE hDrive
, UINT64 StartSectorId
)
1060 DWORD TrySize
= 16 * 1024;
1062 BYTE
*Buffer
= NULL
;
1063 unsigned char *data
= NULL
;
1064 LARGE_INTEGER liCurrentPosition
;
1066 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
1067 SetFilePointerEx(hDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
1069 Buffer
= malloc(TrySize
);
1071 bRet
= WriteFile(hDrive
, Buffer
, TrySize
, &dwSize
, NULL
);
1075 Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1077 if (bRet
&& dwSize
== TrySize
)
1085 static int FormatPart2Fat(HANDLE hDrive
, UINT64 StartSectorId
)
1092 int Pos
= PT_WRITE_VENTOY_START
;
1095 unsigned char *data
= NULL
;
1096 LARGE_INTEGER liCurrentPosition
;
1097 LARGE_INTEGER liNewPosition
;
1098 BYTE
*CheckBuf
= NULL
;
1100 Log("FormatPart2Fat %llu...", (ULONGLONG
)StartSectorId
);
1102 CheckBuf
= malloc(SIZE_1MB
);
1105 Log("Failed to malloc check buf");
1109 rc
= ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG
, 0, (void **)&data
, &len
);
1112 Log("Failed to read img file %p %u", data
, len
);
1117 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
1118 SetFilePointerEx(hDrive
, liCurrentPosition
, &liNewPosition
, FILE_BEGIN
);
1120 memset(g_part_img_buf
, 0, sizeof(g_part_img_buf
));
1122 g_part_img_buf
[0] = (BYTE
*)malloc(VENTOY_EFI_PART_SIZE
);
1123 if (g_part_img_buf
[0])
1125 Log("Malloc whole img buffer success, now decompress ...");
1126 unxz(data
, len
, NULL
, NULL
, g_part_img_buf
[0], &writelen
, unxz_error
);
1128 if (len
== writelen
)
1130 Log("decompress finished success");
1132 VentoyProcSecureBoot(g_SecureBoot
);
1134 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1137 bRet
= WriteFile(hDrive
, g_part_img_buf
[0] + i
* SIZE_1MB
, SIZE_1MB
, &dwSize
, NULL
);
1138 Log("Write part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1146 PROGRESS_BAR_SET_POS(Pos
);
1153 //Read and check the data
1154 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
1155 SetFilePointerEx(hDrive
, liCurrentPosition
, &liNewPosition
, FILE_BEGIN
);
1157 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1159 bRet
= ReadFile(hDrive
, CheckBuf
, SIZE_1MB
, &dwSize
, NULL
);
1160 Log("Read part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1162 if (!bRet
|| memcmp(CheckBuf
, g_part_img_buf
[0] + i
* SIZE_1MB
, SIZE_1MB
))
1164 Log("### [Check Fail] The data write and read does not match");
1169 PROGRESS_BAR_SET_POS(Pos
);
1179 Log("decompress finished failed");
1185 Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE
);
1188 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1190 g_part_img_buf
[i
] = (BYTE
*)malloc(SIZE_1MB
);
1191 if (g_part_img_buf
[i
] == NULL
)
1198 Log("Malloc part img buffer success, now decompress ...");
1200 g_part_img_pos
= g_part_img_buf
[0];
1202 unxz(data
, len
, NULL
, disk_xz_flush
, NULL
, NULL
, unxz_error
);
1204 if (g_disk_unxz_len
== VENTOY_EFI_PART_SIZE
)
1206 Log("decompress finished success");
1208 VentoyProcSecureBoot(g_SecureBoot
);
1210 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1213 bRet
= WriteFile(hDrive
, g_part_img_buf
[i
], SIZE_1MB
, &dwSize
, NULL
);
1214 Log("Write part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1222 PROGRESS_BAR_SET_POS(Pos
);
1229 //Read and check the data
1230 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
1231 SetFilePointerEx(hDrive
, liCurrentPosition
, &liNewPosition
, FILE_BEGIN
);
1233 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1235 bRet
= ReadFile(hDrive
, CheckBuf
, SIZE_1MB
, &dwSize
, NULL
);
1236 Log("Read part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1238 if (!bRet
|| memcmp(CheckBuf
, g_part_img_buf
[i
], SIZE_1MB
))
1240 Log("### [Check Fail] The data write and read does not match");
1245 PROGRESS_BAR_SET_POS(Pos
);
1255 Log("decompress finished failed");
1262 if (data
) free(data
);
1263 if (CheckBuf
)free(CheckBuf
);
1267 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1269 if (g_part_img_buf
[i
]) free(g_part_img_buf
[i
]);
1274 if (g_part_img_buf
[0]) free(g_part_img_buf
[0]);
1280 static int WriteGrubStage1ToPhyDrive(HANDLE hDrive
, int PartStyle
)
1286 BYTE
*ImgBuf
= NULL
;
1287 BYTE
*RawBuf
= NULL
;
1289 Log("WriteGrubStage1ToPhyDrive ...");
1291 RawBuf
= (BYTE
*)malloc(SIZE_1MB
);
1297 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG
, 0, (void **)&ImgBuf
, &Len
))
1299 Log("Failed to read stage1 img");
1304 unxz(ImgBuf
, Len
, NULL
, NULL
, RawBuf
, &readLen
, unxz_error
);
1308 Log("Write GPT stage1 ...");
1309 RawBuf
[500] = 35;//update blocklist
1310 SetFilePointer(hDrive
, 512 * 34, NULL
, FILE_BEGIN
);
1311 bRet
= WriteFile(hDrive
, RawBuf
, SIZE_1MB
- 512 * 34, &dwSize
, NULL
);
1315 Log("Write MBR stage1 ...");
1316 SetFilePointer(hDrive
, 512, NULL
, FILE_BEGIN
);
1317 bRet
= WriteFile(hDrive
, RawBuf
, SIZE_1MB
- 512, &dwSize
, NULL
);
1320 Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet
, dwSize
, GetLastError());
1328 static int FormatPart1LargeFAT32(UINT64 DiskSizeBytes
, int CluserSize
)
1334 Option
.fmt
= FM_FAT32
;
1339 if (CluserSize
== 0)
1341 // < 32GB select 32KB as cluster size
1342 // > 32GB select 128KB as cluster size
1343 if (DiskSizeBytes
/ 1024 / 1024 / 1024 <= 32)
1345 Option
.au_size
= 32768;
1349 Option
.au_size
= 131072;
1354 Option
.au_size
= CluserSize
;
1357 Log("Formatting Part1 large FAT32 ClusterSize:%u(%uKB) ...", CluserSize
, CluserSize
/ 1024);
1359 disk_io_reset_write_error();
1361 Ret
= f_mkfs(TEXT("0:"), &Option
, 0, 8 * 1024 * 1024);
1364 if (disk_io_is_write_error())
1366 Log("Formatting Part1 large FAT32 failed, write error.");
1370 Log("Formatting Part1 large FAT32 success, now set label");
1372 Ret
= f_mount(&FS
, TEXT("0:"), 1);
1375 Log("f_mount SUCCESS");
1376 Ret
= f_setlabel(TEXT("0:Ventoy"));
1379 Log("f_setlabel SUCCESS");
1380 Ret
= f_unmount(TEXT("0:"));
1381 Log("f_unmount %d %s", Ret
, (FR_OK
== Ret
) ? "SUCCESS" : "FAILED");
1385 Log("f_setlabel failed %d", Ret
);
1390 Log("f_mount failed %d", Ret
);
1397 Log("Formatting Part1 large FAT32 failed");
1402 static int FormatPart1exFAT(UINT64 DiskSizeBytes
)
1407 Option
.fmt
= FM_EXFAT
;
1412 // < 32GB select 32KB as cluster size
1413 // > 32GB select 128KB as cluster size
1414 if (DiskSizeBytes
/ 1024 / 1024 / 1024 <= 32)
1416 Option
.au_size
= 32768;
1420 Option
.au_size
= 131072;
1423 Log("Formatting Part1 exFAT ...");
1425 disk_io_reset_write_error();
1427 Ret
= f_mkfs(TEXT("0:"), &Option
, 0, 8 * 1024 * 1024);
1430 if (disk_io_is_write_error())
1432 Log("Formatting Part1 exFAT failed, write error.");
1436 Log("Formatting Part1 exFAT success");
1441 Log("Formatting Part1 exFAT failed");
1446 static int ZeroPart1FileSystem(HANDLE hDrive
, UINT64 Part2StartSector
)
1450 LARGE_INTEGER liCurPos
;
1451 LARGE_INTEGER liNewPos
;
1452 CHAR TmpBuffer
[1024] = { 0 };
1454 liCurPos
.QuadPart
= VENTOY_PART1_START_SECTOR
* 512;
1455 liNewPos
.QuadPart
= 0;
1456 if (0 == SetFilePointerEx(hDrive
, liCurPos
, &liNewPos
, FILE_BEGIN
) ||
1457 liNewPos
.QuadPart
!= liCurPos
.QuadPart
)
1459 Log("SetFilePointerEx Failed %u %llu %llu", LASTERR
, (ULONGLONG
)liCurPos
.QuadPart
, (ULONGLONG
)liNewPos
.QuadPart
);
1463 for (i
= 0; i
< 1024; i
++)
1465 WriteFile(hDrive
, TmpBuffer
, 1024, &dwSize
, NULL
);
1468 liCurPos
.QuadPart
= (Part2StartSector
* 512) - (1024 * 1024);
1469 liNewPos
.QuadPart
= 0;
1470 if (0 == SetFilePointerEx(hDrive
, liCurPos
, &liNewPos
, FILE_BEGIN
) ||
1471 liNewPos
.QuadPart
!= liCurPos
.QuadPart
)
1473 Log("SetFilePointerEx Failed %u %llu %llu", LASTERR
, (ULONGLONG
)liCurPos
.QuadPart
, (ULONGLONG
)liNewPos
.QuadPart
);
1477 for (i
= 0; i
< 1024; i
++)
1479 WriteFile(hDrive
, TmpBuffer
, 1024, &dwSize
, NULL
);
1482 Log("Zero Part1 SUCCESS");
1486 int ClearVentoyFromPhyDrive(HWND hWnd
, PHY_DRIVE_INFO
*pPhyDrive
, char *pDrvLetter
)
1495 CHAR DriveName
[] = "?:\\";
1496 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1497 LARGE_INTEGER liCurrentPosition
;
1498 char *pTmpBuf
= NULL
;
1503 Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
1504 pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1505 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1507 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1509 Log("Lock disk for clean ............................. ");
1511 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1512 if (hDrive
== INVALID_HANDLE_VALUE
)
1514 Log("Failed to open physical disk");
1518 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1520 if (DriveLetters
[0] == 0)
1522 Log("No drive letter was assigned...");
1523 DriveName
[0] = GetFirstUnusedDriveLetter();
1524 Log("GetFirstUnusedDriveLetter %C: ...", DriveName
[0]);
1528 // Unmount all mounted volumes that belong to this drive
1529 // Do it in reverse so that we always end on the first volume letter
1530 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
1532 DriveName
[0] = DriveLetters
[i
- 1];
1533 bRet
= DeleteVolumeMountPointA(DriveName
);
1534 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, GetLastError());
1538 MountDrive
= DriveName
[0];
1539 Log("Will use '%C:' as volume mountpoint", DriveName
[0]);
1541 // It kind of blows, but we have to relinquish access to the physical drive
1542 // for VDS to be able to delete the partitions that reside on it...
1543 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1544 CHECK_CLOSE_HANDLE(hDrive
);
1546 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
1548 if (!VDS_DeleteAllPartitions(pPhyDrive
->PhyDrive
))
1550 Log("Notice: Could not delete partitions: %u", GetLastError());
1553 Log("Deleting all partitions ......................... OK");
1555 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
1557 Log("Lock disk for write ............................. ");
1558 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1559 if (hDrive
== INVALID_HANDLE_VALUE
)
1561 Log("Failed to GetPhysicalHandle for write.");
1566 // clear first and last 2MB space
1567 pTmpBuf
= malloc(SIZE_2MB
);
1570 Log("Failed to alloc memory.");
1574 memset(pTmpBuf
, 0, SIZE_2MB
);
1577 bRet
= WriteFile(hDrive
, pTmpBuf
, SIZE_2MB
- 512, &dwSize
, NULL
);
1578 Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1585 SET_FILE_POS(pPhyDrive
->SizeInBytes
- SIZE_2MB
);
1586 bRet
= WriteFile(hDrive
, pTmpBuf
, SIZE_2MB
, &dwSize
, NULL
);
1587 Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1596 if (pPhyDrive
->SizeInBytes
> 2199023255552ULL)
1598 VTOY_GPT_INFO
*pGptInfo
;
1599 VTOY_GPT_HDR BackupHead
;
1600 LARGE_INTEGER liCurrentPosition
;
1602 pGptInfo
= (VTOY_GPT_INFO
*)pTmpBuf
;
1604 VentoyFillWholeGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1606 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512);
1607 VentoyFillBackupGptHead(pGptInfo
, &BackupHead
);
1608 if (!WriteFile(hDrive
, &BackupHead
, sizeof(VTOY_GPT_HDR
), &dwSize
, NULL
))
1611 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1615 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512 * 33);
1616 if (!WriteFile(hDrive
, pGptInfo
->PartTbl
, sizeof(pGptInfo
->PartTbl
), &dwSize
, NULL
))
1619 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1624 if (!WriteFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
))
1627 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1631 Log("Write GPT Info OK ...");
1635 bRet
= ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
1636 Log("Read MBR ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1643 //clear boot code and partition table (reserved disk signature)
1644 memset(MBR
.BootCode
, 0, 440);
1645 memset(MBR
.PartTbl
, 0, sizeof(MBR
.PartTbl
));
1647 VentoyFillMBRLocation(pPhyDrive
->SizeInBytes
, 2048, (UINT32
)(pPhyDrive
->SizeInBytes
/ 512 - 2048), MBR
.PartTbl
);
1649 MBR
.PartTbl
[0].Active
= 0x00; // bootable
1650 MBR
.PartTbl
[0].FsFlag
= 0x07; // exFAT/NTFS/HPFS
1653 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
1654 Log("Write MBR ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1662 Log("Clear Ventoy successfully finished");
1664 //Refresh Drive Layout
1665 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1669 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1670 PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH
);
1679 Log("Mounting Ventoy Partition ....................... ");
1683 memset(DriveLetters
, 0, sizeof(DriveLetters
));
1684 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1685 Log("Logical drive letter after write ventoy: <%s>", DriveLetters
);
1687 for (i
= 0; i
< sizeof(DriveLetters
) && DriveLetters
[i
]; i
++)
1689 DriveName
[0] = DriveLetters
[i
];
1690 Log("%s is ventoy part1, already mounted", DriveName
);
1696 Log("need to mount ventoy part1...");
1697 if (0 == GetVentoyVolumeName(pPhyDrive
->PhyDrive
, 2048, DriveLetters
, sizeof(DriveLetters
), FALSE
))
1699 DriveName
[0] = MountDrive
;
1700 bRet
= SetVolumeMountPointA(DriveName
, DriveLetters
);
1701 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName
, DriveLetters
, bRet
, GetLastError());
1703 *pDrvLetter
= MountDrive
;
1707 Log("Failed to find ventoy volume");
1715 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
1718 CHECK_CLOSE_HANDLE(hDrive
);
1722 int InstallVentoy2FileImage(PHY_DRIVE_INFO
*pPhyDrive
, int PartStyle
)
1731 UINT64 data_offset
= 0;
1732 UINT64 Part2StartSector
= 0;
1733 UINT64 Part1StartSector
= 0;
1734 UINT64 Part1SectorCount
= 0;
1735 UINT8
*pData
= NULL
;
1736 UINT8
*pBkGptPartTbl
= NULL
;
1737 BYTE
*ImgBuf
= NULL
;
1738 MBR_HEAD
*pMBR
= NULL
;
1739 VTSI_FOOTER
*pImgFooter
= NULL
;
1740 VTSI_SEGMENT
*pSegment
= NULL
;
1741 VTOY_GPT_INFO
*pGptInfo
= NULL
;
1742 VTOY_GPT_HDR
*pBkGptHdr
= NULL
;
1745 Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",
1746 PartStyle
? "GPT" : "MBR", pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1747 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1749 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1751 size
= SIZE_1MB
+ VENTOY_EFI_PART_SIZE
+ 33 * 512 + VTSI_IMG_MAX_SEG
* sizeof(VTSI_SEGMENT
) + sizeof(VTSI_FOOTER
);
1753 pData
= (UINT8
*)malloc(size
);
1756 Log("malloc image buffer failed %d.", size
);
1760 pImgFooter
= (VTSI_FOOTER
*)(pData
+ size
- sizeof(VTSI_FOOTER
));
1761 pSegment
= (VTSI_SEGMENT
*)((UINT8
*)pImgFooter
- VTSI_IMG_MAX_SEG
* sizeof(VTSI_SEGMENT
));
1762 memset(pImgFooter
, 0, sizeof(VTSI_FOOTER
));
1763 memset(pSegment
, 0, VTSI_IMG_MAX_SEG
* sizeof(VTSI_SEGMENT
));
1765 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
);
1767 Log("Writing Boot Image ............................. ");
1768 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG
, 0, (void **)&ImgBuf
, &Len
))
1770 Log("Failed to read stage1 img");
1774 unxz(ImgBuf
, Len
, NULL
, NULL
, pData
, &dataLen
, unxz_error
);
1777 Log("decompress %s len:%d", VENTOY_FILE_STG1_IMG
, dataLen
);
1781 pData
[500] = 35;//update blocklist
1782 memmove(pData
+ 34 * 512, pData
, SIZE_1MB
- 512 * 34);
1783 memset(pData
, 0, 34 * 512);
1785 pGptInfo
= (VTOY_GPT_INFO
*)pData
;
1786 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
1787 VentoyFillGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1789 pBkGptPartTbl
= pData
+ SIZE_1MB
+ VENTOY_EFI_PART_SIZE
;
1790 memset(pBkGptPartTbl
, 0, 33 * 512);
1792 memcpy(pBkGptPartTbl
, pGptInfo
->PartTbl
, 32 * 512);
1793 pBkGptHdr
= (VTOY_GPT_HDR
*)(pBkGptPartTbl
+ 32 * 512);
1794 VentoyFillBackupGptHead(pGptInfo
, pBkGptHdr
);
1796 Part1StartSector
= pGptInfo
->PartTbl
[0].StartLBA
;
1797 Part1SectorCount
= pGptInfo
->PartTbl
[0].LastLBA
- Part1StartSector
+ 1;
1798 Part2StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
1800 Log("Write GPT Info OK ...");
1804 memmove(pData
+ 512, pData
, SIZE_1MB
- 512);
1805 memset(pData
, 0, 512);
1807 pMBR
= (MBR_HEAD
*)pData
;
1808 VentoyFillMBR(pPhyDrive
->SizeInBytes
, pMBR
, PartStyle
, 0x07);
1809 Part1StartSector
= pMBR
->PartTbl
[0].StartSectorId
;
1810 Part1SectorCount
= pMBR
->PartTbl
[0].SectorCount
;
1811 Part2StartSector
= pMBR
->PartTbl
[1].StartSectorId
;
1813 Log("Write MBR OK ...");
1816 Log("Writing EFI part Image ............................. ");
1817 rc
= ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG
, 0, (void **)&ImgBuf
, &Len
);
1820 Log("Failed to read img file %p %u", ImgBuf
, Len
);
1824 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
+ 28);
1825 memset(g_part_img_buf
, 0, sizeof(g_part_img_buf
));
1826 unxz(ImgBuf
, Len
, NULL
, NULL
, pData
+ SIZE_1MB
, &dataLen
, unxz_error
);
1829 Log("decompress finished success");
1830 g_part_img_buf
[0] = pData
+ SIZE_1MB
;
1832 VentoyProcSecureBoot(g_SecureBoot
);
1836 Log("decompress finished failed");
1840 fopen_s(&fp
, "VentoySparseImg.vtsi", "wb+");
1843 Log("Failed to create Ventoy img file");
1847 Log("Writing stage1 data ............................. ");
1849 fwrite(pData
, 1, SIZE_1MB
, fp
);
1851 pSegment
[0].disk_start_sector
= 0;
1852 pSegment
[0].sector_num
= SIZE_1MB
/ 512;
1853 pSegment
[0].data_offset
= data_offset
;
1854 data_offset
+= pSegment
[0].sector_num
* 512;
1856 disk_io_set_param(INVALID_HANDLE_VALUE
, Part1StartSector
+ Part1SectorCount
);// include the 2048 sector gap
1857 disk_io_set_imghook(fp
, pSegment
+ 1, VTSI_IMG_MAX_SEG
- 1, data_offset
);
1859 Log("Formatting part1 exFAT ...");
1860 if (0 != FormatPart1exFAT(pPhyDrive
->SizeInBytes
))
1862 Log("FormatPart1exFAT failed.");
1863 disk_io_reset_imghook(&segnum
, &data_offset
);
1867 disk_io_reset_imghook(&segnum
, &data_offset
);
1870 Log("current segment number:%d dataoff:%ld", segnum
, (long)data_offset
);
1873 Log("Writing part2 data ............................. ");
1874 fwrite(pData
+ SIZE_1MB
, 1, VENTOY_EFI_PART_SIZE
, fp
);
1875 pSegment
[segnum
].disk_start_sector
= Part2StartSector
;
1876 pSegment
[segnum
].sector_num
= VENTOY_EFI_PART_SIZE
/ 512;
1877 pSegment
[segnum
].data_offset
= data_offset
;
1878 data_offset
+= pSegment
[segnum
].sector_num
* 512;
1883 Log("Writing backup gpt table ............................. ");
1884 fwrite(pBkGptPartTbl
, 1, 33 * 512, fp
);
1885 pSegment
[segnum
].disk_start_sector
= pPhyDrive
->SizeInBytes
/ 512 - 33;
1886 pSegment
[segnum
].sector_num
= 33;
1887 pSegment
[segnum
].data_offset
= data_offset
;
1888 data_offset
+= pSegment
[segnum
].sector_num
* 512;
1892 Log("Writing segment metadata ............................. ");
1894 for (i
= 0; i
< (int)segnum
; i
++)
1896 Log("SEG[%d]: PhySector:%llu SectorNum:%llu DataOffset:%llu(sector:%llu)", i
, pSegment
[i
].disk_start_sector
, pSegment
[i
].sector_num
,
1897 pSegment
[i
].data_offset
, pSegment
[i
].data_offset
/ 512);
1900 dataLen
= segnum
* sizeof(VTSI_SEGMENT
);
1901 fwrite(pSegment
, 1, dataLen
, fp
);
1905 //pData + SIZE_1MB - 8192 is a temp data buffer with zero
1906 fwrite(pData
+ SIZE_1MB
- 8192, 1, 512 - (dataLen
% 512), fp
);
1910 pImgFooter
->magic
= VTSI_IMG_MAGIC
;
1911 pImgFooter
->version
= 1;
1912 pImgFooter
->disk_size
= pPhyDrive
->SizeInBytes
;
1913 memcpy(&pImgFooter
->disk_signature
, pPhyDrive
->MBR
.BootCode
+ 0x1b8, 4);
1914 pImgFooter
->segment_num
= segnum
;
1915 pImgFooter
->segment_offset
= data_offset
;
1917 for (i
= 0, chksum
= 0; i
< (int)(segnum
* sizeof(VTSI_SEGMENT
)); i
++)
1919 chksum
+= *((UINT8
*)pSegment
+ i
);
1921 pImgFooter
->segment_chksum
= ~chksum
;
1923 for (i
= 0, chksum
= 0; i
< sizeof(VTSI_FOOTER
); i
++)
1925 chksum
+= *((UINT8
*)pImgFooter
+ i
);
1927 pImgFooter
->foot_chksum
= ~chksum
;
1929 Log("Writing footer segnum(%u) segoffset(%llu) ......................", segnum
, data_offset
);
1930 Log("disk_size=%llu disk_signature=%lx segment_offset=%llu", pImgFooter
->disk_size
, pImgFooter
->disk_signature
, pImgFooter
->segment_offset
);
1932 fwrite(pImgFooter
, 1, sizeof(VTSI_FOOTER
), fp
);
1935 Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset
+ 512 + ((dataLen
+ 511) / 512 * 512));
1941 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1942 PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH
);
1944 Log("retcode:%d\n", rc
);
1953 int InstallVentoy2PhyDrive(PHY_DRIVE_INFO
*pPhyDrive
, int PartStyle
, int TryId
)
1963 CHAR DriveName
[] = "?:\\";
1964 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1966 VTOY_GPT_INFO
*pGptInfo
= NULL
;
1967 UINT64 Part1StartSector
= 0;
1968 UINT64 Part1SectorCount
= 0;
1969 UINT64 Part2StartSector
= 0;
1970 BOOL LargeFAT32
= FALSE
;
1971 BOOL DefaultExFAT
= FALSE
;
1972 UINT8 FsFlag
= 0x07;
1974 Log("#####################################################");
1975 Log("InstallVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId
,
1976 PartStyle
? "GPT" : "MBR", pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1977 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1978 Log("#####################################################");
1982 pGptInfo
= malloc(sizeof(VTOY_GPT_INFO
));
1983 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
1986 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1990 VentoyFillGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1991 Part1StartSector
= pGptInfo
->PartTbl
[0].StartLBA
;
1992 Part1SectorCount
= pGptInfo
->PartTbl
[0].LastLBA
- Part1StartSector
+ 1;
1993 Part2StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
1997 if (GetVentoyFsType() == VTOY_FS_FAT32
)
2002 VentoyFillMBR(pPhyDrive
->SizeInBytes
, &MBR
, PartStyle
, FsFlag
);
2003 Part1StartSector
= MBR
.PartTbl
[0].StartSectorId
;
2004 Part1SectorCount
= MBR
.PartTbl
[0].SectorCount
;
2005 Part2StartSector
= MBR
.PartTbl
[1].StartSectorId
;
2008 Log("Lock disk for clean ............................. ");
2010 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
2011 if (hDrive
== INVALID_HANDLE_VALUE
)
2013 Log("Failed to open physical disk");
2018 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
2020 if (DriveLetters
[0] == 0)
2022 Log("No drive letter was assigned...");
2023 DriveName
[0] = GetFirstUnusedDriveLetter();
2024 Log("GetFirstUnusedDriveLetter %C: ...", DriveName
[0]);
2028 // Unmount all mounted volumes that belong to this drive
2029 // Do it in reverse so that we always end on the first volume letter
2030 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
2032 DriveName
[0] = DriveLetters
[i
- 1];
2033 bRet
= DeleteVolumeMountPointA(DriveName
);
2034 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, GetLastError());
2038 MountDrive
= DriveName
[0];
2039 Log("Will use '%C:' as volume mountpoint", DriveName
[0]);
2041 // It kind of blows, but we have to relinquish access to the physical drive
2042 // for VDS to be able to delete the partitions that reside on it...
2043 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2044 CHECK_CLOSE_HANDLE(hDrive
);
2046 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
2048 if (!VDS_DeleteAllPartitions(pPhyDrive
->PhyDrive
))
2050 Log("Notice: Could not delete partitions: 0x%x, but we continue.", GetLastError());
2053 Log("Deleting all partitions ......................... OK");
2055 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
2057 Log("Lock disk for write ............................. ");
2058 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
2059 if (hDrive
== INVALID_HANDLE_VALUE
)
2061 Log("Failed to GetPhysicalHandle for write.");
2066 //Refresh Drive Layout
2067 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2069 disk_io_set_param(hDrive
, Part1StartSector
+ Part1SectorCount
);// include the 2048 sector gap
2071 PROGRESS_BAR_SET_POS(PT_FORMAT_PART1
);
2073 if (PartStyle
== 1 && pPhyDrive
->PartStyle
== 0)
2075 Log("Wait for format part1 ...");
2079 if (GetVentoyFsType() == VTOY_FS_FAT32
&& (Part1SectorCount
* 512 >= FAT32_MAX_LIMIT
))
2081 Log("Formatting part1 large FAT32 ...");
2083 if (0 != FormatPart1LargeFAT32(pPhyDrive
->SizeInBytes
, GetClusterSize()))
2085 Log("FormatPart1LargeFAT32 failed.");
2090 else if (GetVentoyFsType() == VTOY_FS_EXFAT
&& GetClusterSize() == 0)
2092 Log("Formatting part1 exFAT ...");
2093 DefaultExFAT
= TRUE
;
2094 if (0 != FormatPart1exFAT(pPhyDrive
->SizeInBytes
))
2096 Log("FormatPart1exFAT failed.");
2103 Log("Zero part1 file system ...");
2104 if (0 != ZeroPart1FileSystem(hDrive
, Part2StartSector
))
2106 Log("ZeroPart1FileSystem failed.");
2112 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
2113 Log("Writing part2 FAT img ...");
2115 if (0 != FormatPart2Fat(hDrive
, Part2StartSector
))
2117 Log("FormatPart2Fat failed.");
2122 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG
);
2123 Log("Writing Boot Image ............................. ");
2124 if (WriteGrubStage1ToPhyDrive(hDrive
, PartStyle
) != 0)
2126 Log("WriteGrubStage1ToPhyDrive failed.");
2131 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE
);
2132 Log("Writing Partition Table ........................ ");
2133 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2137 VTOY_GPT_HDR BackupHead
;
2138 LARGE_INTEGER liCurrentPosition
;
2140 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512);
2141 VentoyFillBackupGptHead(pGptInfo
, &BackupHead
);
2142 if (!WriteFile(hDrive
, &BackupHead
, sizeof(VTOY_GPT_HDR
), &dwSize
, NULL
))
2145 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
2149 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512 * 33);
2150 if (!WriteFile(hDrive
, pGptInfo
->PartTbl
, sizeof(pGptInfo
->PartTbl
), &dwSize
, NULL
))
2153 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
2158 if (!WriteFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
))
2161 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
2165 Log("Write GPT Info OK ...");
2166 memcpy(&(pPhyDrive
->MBR
), &(pGptInfo
->MBR
), 512);
2170 if (!WriteFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
))
2173 Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize
, GetLastError());
2176 Log("Write MBR OK ...");
2177 memcpy(&(pPhyDrive
->MBR
), &MBR
, 512);
2180 //Refresh Drive Layout
2181 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2185 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
2189 Log("Mounting Ventoy Partition ....................... ");
2193 memset(DriveLetters
, 0, sizeof(DriveLetters
));
2194 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
2195 Log("Logical drive letter after write ventoy: <%s>", DriveLetters
);
2197 for (i
= 0; i
< sizeof(DriveLetters
) && DriveLetters
[i
]; i
++)
2199 DriveName
[0] = DriveLetters
[i
];
2200 if (IsVentoyLogicalDrive(DriveName
[0]))
2202 Log("%s is ventoy part2, delete mountpoint", DriveName
);
2203 DeleteVolumeMountPointA(DriveName
);
2207 Log("%s is ventoy part1, already mounted", DriveName
);
2208 MountDrive
= DriveName
[0];
2215 Log("need to mount ventoy part1...");
2217 if (0 == GetVentoyVolumeName(pPhyDrive
->PhyDrive
, Part1StartSector
, DriveLetters
, sizeof(DriveLetters
), FALSE
))
2219 DriveName
[0] = MountDrive
;
2220 bRet
= SetVolumeMountPointA(DriveName
, DriveLetters
);
2221 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName
, DriveLetters
, bRet
, GetLastError());
2230 Log("Failed to find ventoy volume");
2234 // close handle, or it will deny reformat
2235 Log("Close handle ...");
2236 CHECK_CLOSE_HANDLE(hDrive
);
2244 Log("No need to reformat for large FAT32");
2245 pPhyDrive
->VentoyFsClusterSize
= GetVolumeClusterSize(MountDrive
);
2247 else if (DefaultExFAT
)
2249 Log("No need to reformat for default exfat");
2250 pPhyDrive
->VentoyFsClusterSize
= GetVolumeClusterSize(MountDrive
);
2254 bRet
= DISK_FormatVolume(MountDrive
, GetVentoyFsType(), Part1SectorCount
* 512);
2255 for (i
= 0; bRet
== FALSE
&& i
< 2; i
++)
2257 Log("Wait and retry reformat ...");
2259 bRet
= DISK_FormatVolume(MountDrive
, GetVentoyFsType(), Part1SectorCount
* 512);
2264 Log("Reformat %C:\\ to %s SUCCESS", MountDrive
, GetVentoyFsName());
2265 pPhyDrive
->VentoyFsClusterSize
= GetVolumeClusterSize(MountDrive
);
2267 if ((GetVentoyFsType() != VTOY_FS_UDF
) && (pPhyDrive
->VentoyFsClusterSize
< 2048))
2269 for (i
= 0; i
< 10; i
++)
2271 Log("### Invalid cluster size %d ###", pPhyDrive
->VentoyFsClusterSize
);
2278 Log("Reformat %C:\\ to %s FAILED", MountDrive
, GetVentoyFsName());
2284 Log("Can not reformat %s to %s", DriveName
, GetVentoyFsName());
2289 Log("Format to exfat with built-in algorithm");
2291 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
2292 if (hDrive
== INVALID_HANDLE_VALUE
)
2294 Log("Failed to GetPhysicalHandle for write.");
2298 if (0 != FormatPart1exFAT(pPhyDrive
->SizeInBytes
))
2300 Log("FormatPart1exFAT SUCCESS.");
2304 Log("FormatPart1exFAT FAILED.");
2307 CHECK_CLOSE_HANDLE(hDrive
);
2315 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
2317 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
2319 if (!VDS_IsLastAvaliable())
2321 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2322 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2323 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2324 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2325 Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
2328 CHECK_CLOSE_HANDLE(hDrive
);
2340 int PartitionResizeForVentoy(PHY_DRIVE_INFO
*pPhyDrive
)
2349 VTOY_GPT_INFO
*pGPT
;
2352 VTOY_GPT_HDR BackupHead
;
2353 HANDLE hDrive
= INVALID_HANDLE_VALUE
;
2354 GUID ZeroGuid
= { 0 };
2355 static GUID WindowsDataPartType
= { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };
2356 static GUID EspPartType
= { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };
2357 static GUID BiosGrubPartType
= { 0x21686148, 0x6449, 0x6e6f, { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } };
2359 Log("#####################################################");
2360 Log("PartitionResizeForVentoy PhyDrive%d <<%s %s %dGB>>",
2361 pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
2362 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
2363 Log("#####################################################");
2365 pGPT
= &(pPhyDrive
->Gpt
);
2366 pMBR
= &(pPhyDrive
->Gpt
.MBR
);
2367 Log("Disksize:%llu Part2Start:%llu", pPhyDrive
->SizeInBytes
, pPhyDrive
->ResizePart2StartSector
* 512);
2369 if (pMBR
->PartTbl
[0].FsFlag
== 0xEE && memcmp(pGPT
->Head
.Signature
, "EFI PART", 8) == 0)
2378 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
2380 RecudeBytes
= VENTOY_EFI_PART_SIZE
;
2382 if (pPhyDrive
->ResizeNoShrink
== FALSE
)
2384 Log("Need to shrink the volume");
2385 if (DISK_ShrinkVolume(pPhyDrive
->PhyDrive
, pPhyDrive
->ResizeVolumeGuid
, pPhyDrive
->Part1DriveLetter
, pPhyDrive
->ResizeOldPart1Size
, RecudeBytes
))
2387 Log("Shrink volume success, now check again");
2389 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
2390 if (hDrive
== INVALID_HANDLE_VALUE
)
2392 Log("Failed to GetPhysicalHandle for update.");
2396 //Refresh Drive Layout
2397 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2399 CHECK_CLOSE_HANDLE(hDrive
);
2402 if (PartResizePreCheck(NULL
) && pPhyDrive
->ResizeNoShrink
)
2404 Log("Recheck after Shrink volume success");
2405 Log("After shrink Disksize:%llu Part2Start:%llu", pPhyDrive
->SizeInBytes
, pPhyDrive
->ResizePart2StartSector
* 512);
2409 Log("Recheck after Shrink volume failed %u", pPhyDrive
->ResizeNoShrink
);
2415 Log("Shrink volume failed");
2421 //Now try write data
2422 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
2423 if (hDrive
== INVALID_HANDLE_VALUE
)
2425 Log("Failed to GetPhysicalHandle for update.");
2430 //Write partition 2 data
2431 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
2432 if (0 != FormatPart2Fat(hDrive
, pPhyDrive
->ResizePart2StartSector
))
2434 Log("FormatPart2Fat failed.");
2438 //Write grub stage2 gap
2439 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG
);
2440 Log("Writing Boot Image ............................. ");
2441 if (WriteGrubStage1ToPhyDrive(hDrive
, PartStyle
) != 0)
2443 Log("WriteGrubStage1ToPhyDrive failed.");
2448 //Write partition table
2449 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE
);
2450 Log("Writing partition table ............................. ");
2452 VentoyGetLocalBootImg(&MBR
);
2453 CoCreateGuid(&Guid
);
2454 memcpy(MBR
.BootCode
+ 0x180, &Guid
, 16);
2455 memcpy(pMBR
->BootCode
, MBR
.BootCode
, 440);
2459 for (i
= 1; i
< 4; i
++)
2461 if (pMBR
->PartTbl
[i
].SectorCount
== 0)
2469 Log("Can not find MBR free partition table");
2473 for (j
= i
- 1; j
> 0; j
--)
2475 Log("Move MBR partition table %d --> %d", j
+ 1, j
+ 2);
2476 memcpy(pMBR
->PartTbl
+ (j
+ 1), pMBR
->PartTbl
+ j
, sizeof(PART_TABLE
));
2479 memset(pMBR
->PartTbl
+ 1, 0, sizeof(PART_TABLE
));
2480 VentoyFillMBRLocation(pPhyDrive
->SizeInBytes
, (UINT32
)pPhyDrive
->ResizePart2StartSector
, VENTOY_EFI_PART_SIZE
/ 512, pMBR
->PartTbl
+ 1);
2481 pMBR
->PartTbl
[0].Active
= 0x80; // bootable
2482 pMBR
->PartTbl
[1].Active
= 0x00;
2483 pMBR
->PartTbl
[1].FsFlag
= 0xEF; // EFI System Partition
2485 if (!WriteDataToPhyDisk(hDrive
, 0, pMBR
, 512))
2487 Log("Legacy BIOS write MBR failed");
2493 for (i
= 1; i
< 128; i
++)
2495 if (memcmp(&(pGPT
->PartTbl
[i
].PartGuid
), &ZeroGuid
, sizeof(GUID
)) == 0)
2503 Log("Can not find GPT free partition table");
2507 for (j
= i
- 1; j
> 0; j
--)
2509 Log("Move GPT partition table %d --> %d", j
+ 1, j
+ 2);
2510 memcpy(pGPT
->PartTbl
+ (j
+ 1), pGPT
->PartTbl
+ j
, sizeof(VTOY_GPT_PART_TBL
));
2514 pMBR
->BootCode
[92] = 0x22;
2516 // to fix windows issue
2517 memset(pGPT
->PartTbl
+ 1, 0, sizeof(VTOY_GPT_PART_TBL
));
2518 memcpy(&(pGPT
->PartTbl
[1].PartType
), &WindowsDataPartType
, sizeof(GUID
));
2519 CoCreateGuid(&(pGPT
->PartTbl
[1].PartGuid
));
2521 pGPT
->PartTbl
[1].StartLBA
= pGPT
->PartTbl
[0].LastLBA
+ 1;
2522 pGPT
->PartTbl
[1].LastLBA
= pGPT
->PartTbl
[1].StartLBA
+ VENTOY_EFI_PART_SIZE
/ 512 - 1;
2523 pGPT
->PartTbl
[1].Attr
= 0xC000000000000001ULL
;
2524 memcpy(pGPT
->PartTbl
[1].Name
, L
"VTOYEFI", 7 * 2);
2527 pGPT
->Head
.PartTblCrc
= VentoyCrc32(pGPT
->PartTbl
, sizeof(pGPT
->PartTbl
));
2529 pGPT
->Head
.Crc
= VentoyCrc32(&(pGPT
->Head
), pGPT
->Head
.Length
);
2531 Log("pGPT->Head.EfiStartLBA=%llu", (ULONGLONG
)pGPT
->Head
.EfiStartLBA
);
2532 Log("pGPT->Head.EfiBackupLBA=%llu", (ULONGLONG
)pGPT
->Head
.EfiBackupLBA
);
2534 VentoyFillBackupGptHead(pGPT
, &BackupHead
);
2535 if (!WriteDataToPhyDisk(hDrive
, pGPT
->Head
.EfiBackupLBA
* 512, &BackupHead
, 512))
2537 Log("UEFI write backup head failed");
2541 if (!WriteDataToPhyDisk(hDrive
, (pGPT
->Head
.EfiBackupLBA
- 32) * 512, pGPT
->PartTbl
, 512 * 32))
2543 Log("UEFI write backup partition table failed");
2547 if (!WriteDataToPhyDisk(hDrive
, 0, pGPT
, 512 * 34))
2549 Log("UEFI write MBR & Main partition table failed");
2556 //Refresh Drive Layout
2557 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2559 //We must close handle here, because it will block the refresh bellow
2560 CHECK_CLOSE_HANDLE(hDrive
);
2566 Log("### Ventoy non-destructive CLI installation successfully finished.");
2571 PhyDrive
= pPhyDrive
->PhyDrive
;
2573 Log("#### Now Refresh PhyDrive ####");
2574 Ventoy2DiskDestroy();
2577 pPhyDrive
= GetPhyDriveInfoByPhyDrive(PhyDrive
);
2580 if (pPhyDrive
->VentoyVersion
[0] == 0)
2582 Log("After process the Ventoy version is still invalid");
2586 Log("### Ventoy non-destructive installation successfully finished <%s>", pPhyDrive
->VentoyVersion
);
2590 Log("### Ventoy non-destructive installation successfully finished <not found>");
2593 InitComboxCtrl(g_DialogHwnd
, PhyDrive
);
2599 CHECK_CLOSE_HANDLE(hDrive
);
2604 static BOOL
DiskCheckWriteAccess(HANDLE hDrive
)
2610 LARGE_INTEGER liCurPosition
;
2611 LARGE_INTEGER liNewPosition
;
2613 liCurPosition
.QuadPart
= 2039 * 512;
2614 liNewPosition
.QuadPart
= 0;
2615 if (0 == SetFilePointerEx(hDrive
, liCurPosition
, &liNewPosition
, FILE_BEGIN
) ||
2616 liNewPosition
.QuadPart
!= liCurPosition
.QuadPart
)
2618 Log("SetFilePointer1 Failed %u", LASTERR
);
2624 ret
= ReadFile(hDrive
, Buffer
, 512, &dwSize
, NULL
);
2625 if ((!ret
) || (dwSize
!= 512))
2627 Log("Failed to read %d %u 0x%x", ret
, dwSize
, LASTERR
);
2632 liCurPosition
.QuadPart
= 2039 * 512;
2633 liNewPosition
.QuadPart
= 0;
2634 if (0 == SetFilePointerEx(hDrive
, liCurPosition
, &liNewPosition
, FILE_BEGIN
) ||
2635 liNewPosition
.QuadPart
!= liCurPosition
.QuadPart
)
2637 Log("SetFilePointer2 Failed %u", LASTERR
);
2642 ret
= WriteFile(hDrive
, Buffer
, 512, &dwSize
, NULL
);
2643 if ((!ret
) || dwSize
!= 512)
2645 Log("Failed to write %d %u %u", ret
, dwSize
, LASTERR
);
2656 static BOOL
BackupDataBeforeCleanDisk(int PhyDrive
, UINT64 DiskSize
, BYTE
**pBackup
)
2660 BOOL Return
= FALSE
;
2662 BYTE
*backup
= NULL
;
2664 HANDLE hDrive
= INVALID_HANDLE_VALUE
;
2665 LARGE_INTEGER liCurPosition
;
2666 LARGE_INTEGER liNewPosition
;
2667 VTOY_GPT_INFO
*pGPT
= NULL
;
2669 Log("BackupDataBeforeCleanDisk %d", PhyDrive
);
2671 // step1: check write access
2672 hDrive
= GetPhysicalHandle(PhyDrive
, TRUE
, TRUE
, FALSE
);
2673 if (hDrive
== INVALID_HANDLE_VALUE
)
2675 Log("Failed to GetPhysicalHandle for write.");
2679 if (DiskCheckWriteAccess(hDrive
))
2681 Log("DiskCheckWriteAccess success");
2682 CHECK_CLOSE_HANDLE(hDrive
);
2686 Log("DiskCheckWriteAccess failed");
2690 //step2 backup 4MB data
2691 backup
= malloc(SIZE_1MB
* 4);
2697 hDrive
= GetPhysicalHandle(PhyDrive
, FALSE
, FALSE
, FALSE
);
2698 if (hDrive
== INVALID_HANDLE_VALUE
)
2704 dwStatus
= SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2711 ret
= ReadFile(hDrive
, backup
, SIZE_2MB
, &dwSize
, NULL
);
2712 if ((!ret
) || (dwSize
!= SIZE_2MB
))
2714 Log("Failed to read %d %u 0x%x", ret
, dwSize
, LASTERR
);
2718 pGPT
= (VTOY_GPT_INFO
*)backup
;
2719 offset
= pGPT
->Head
.EfiBackupLBA
* 512;
2720 if (offset
>= (DiskSize
- SIZE_2MB
) && offset
< DiskSize
)
2722 Log("EFI partition table check success");
2726 Log("Backup EFI LBA not in last 2MB range: %llu", pGPT
->Head
.EfiBackupLBA
);
2731 liCurPosition
.QuadPart
= DiskSize
- SIZE_2MB
;
2732 liNewPosition
.QuadPart
= 0;
2733 if (0 == SetFilePointerEx(hDrive
, liCurPosition
, &liNewPosition
, FILE_BEGIN
) ||
2734 liNewPosition
.QuadPart
!= liCurPosition
.QuadPart
)
2740 ret
= ReadFile(hDrive
, backup
+ SIZE_2MB
, SIZE_2MB
, &dwSize
, NULL
);
2741 if ((!ret
) || (dwSize
!= SIZE_2MB
))
2743 Log("Failed to read %d %u 0x%x", ret
, dwSize
, LASTERR
);
2748 backup
= NULL
; //For don't free later
2752 CHECK_CLOSE_HANDLE(hDrive
);
2760 static BOOL
WriteBackupDataToDisk(HANDLE hDrive
, UINT64 Offset
, BYTE
*Data
, DWORD Length
)
2764 LARGE_INTEGER liCurPosition
;
2765 LARGE_INTEGER liNewPosition
;
2767 Log("WriteBackupDataToDisk %llu %p %u", Offset
, Data
, Length
);
2769 liCurPosition
.QuadPart
= Offset
;
2770 liNewPosition
.QuadPart
= 0;
2771 if (0 == SetFilePointerEx(hDrive
, liCurPosition
, &liNewPosition
, FILE_BEGIN
) ||
2772 liNewPosition
.QuadPart
!= liCurPosition
.QuadPart
)
2777 ret
= WriteFile(hDrive
, Data
, Length
, &dwSize
, NULL
);
2778 if ((!ret
) || dwSize
!= Length
)
2780 Log("Failed to write %d %u %u", ret
, dwSize
, LASTERR
);
2784 Log("WriteBackupDataToDisk %llu %p %u success", Offset
, Data
, Length
);
2789 int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO
*pPhyDrive
, int TryId
)
2794 BOOL ForceMBR
= FALSE
;
2795 BOOL Esp2Basic
= FALSE
;
2796 BOOL ChangeAttr
= FALSE
;
2797 BOOL CleanDisk
= FALSE
;
2798 BOOL DelEFI
= FALSE
;
2799 BOOL bWriteBack
= TRUE
;
2805 CHAR DriveName
[] = "?:\\";
2806 CHAR DriveLetters
[MAX_PATH
] = { 0 };
2807 CHAR BackBinFile
[MAX_PATH
];
2809 UINT64 ReservedMB
= 0;
2812 BYTE
*pBackup
= NULL
;
2813 VTOY_GPT_INFO
*pGptInfo
= NULL
;
2814 VTOY_GPT_INFO
*pGptBkup
= NULL
;
2815 UINT8 ReservedData
[4096];
2817 Log("#####################################################");
2818 Log("UpdateVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId
,
2819 pPhyDrive
->PartStyle
? "GPT" : "MBR", pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
2820 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
2821 Log("#####################################################");
2823 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
2825 Log("Lock disk for umount ............................ ");
2827 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
2828 if (hDrive
== INVALID_HANDLE_VALUE
)
2830 Log("Failed to open physical disk");
2834 if (pPhyDrive
->PartStyle
)
2836 pGptInfo
= malloc(2 * sizeof(VTOY_GPT_INFO
));
2842 memset(pGptInfo
, 0, 2 * sizeof(VTOY_GPT_INFO
));
2843 pGptBkup
= pGptInfo
+ 1;
2846 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2847 ReadFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
);
2848 memcpy(pGptBkup
, pGptInfo
, sizeof(VTOY_GPT_INFO
));
2850 //MBR will be used to compare with local boot image
2851 memcpy(&MBR
, &pGptInfo
->MBR
, sizeof(MBR_HEAD
));
2853 StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
2854 Log("GPT StartSector in PartTbl:%llu", (ULONGLONG
)StartSector
);
2856 ReservedMB
= (pPhyDrive
->SizeInBytes
/ 512 - (StartSector
+ VENTOY_EFI_PART_SIZE
/ 512) - 33) / 2048;
2857 Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG
)ReservedMB
);
2862 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2863 ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
2865 StartSector
= MBR
.PartTbl
[1].StartSectorId
;
2866 Log("MBR StartSector in PartTbl:%llu", (ULONGLONG
)StartSector
);
2868 ReservedMB
= (pPhyDrive
->SizeInBytes
/ 512 - (StartSector
+ VENTOY_EFI_PART_SIZE
/ 512)) / 2048;
2869 Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG
)ReservedMB
);
2872 //Read Reserved Data
2873 SetFilePointer(hDrive
, 512 * 2040, NULL
, FILE_BEGIN
);
2874 ReadFile(hDrive
, ReservedData
, sizeof(ReservedData
), &dwSize
, NULL
);
2876 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
2878 if (DriveLetters
[0] == 0)
2880 Log("No drive letter was assigned...");
2884 // Unmount all mounted volumes that belong to this drive
2885 // Do it in reverse so that we always end on the first volume letter
2886 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
2888 DriveName
[0] = DriveLetters
[i
- 1];
2889 if (IsVentoyLogicalDrive(DriveName
[0]))
2891 Log("%s is ventoy logical drive", DriveName
);
2892 bRet
= DeleteVolumeMountPointA(DriveName
);
2893 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, LASTERR
);
2899 // It kind of blows, but we have to relinquish access to the physical drive
2900 // for VDS to be able to delete the partitions that reside on it...
2901 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2902 CHECK_CLOSE_HANDLE(hDrive
);
2904 if (pPhyDrive
->PartStyle
== 1)
2906 Log("TryId=%d EFI GPT partition type is 0x%llx", TryId
, pPhyDrive
->Part2GPTAttr
);
2907 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
2911 Log("Change GPT partition type to ESP");
2912 if (DISK_ChangeVtoyEFI2ESP(pPhyDrive
->PhyDrive
, StartSector
* 512ULL))
2918 else if (TryId
== 2)
2920 Log("Change GPT partition attribute");
2921 if (DISK_ChangeVtoyEFIAttr(pPhyDrive
->PhyDrive
, StartSector
* 512ULL, 0x8000000000000001))
2927 else if (TryId
== 3)
2929 DISK_DeleteVtoyEFIPartition(pPhyDrive
->PhyDrive
, StartSector
* 512ULL);
2932 else if (TryId
== 4)
2934 Log("Clean disk GPT partition table");
2935 if (BackupDataBeforeCleanDisk(pPhyDrive
->PhyDrive
, pPhyDrive
->SizeInBytes
, &pBackup
))
2937 sprintf_s(BackBinFile
, sizeof(BackBinFile
), ".\\ventoy\\phydrive%d_%u_%d.bin",
2938 pPhyDrive
->PhyDrive
, GetCurrentProcessId(), g_backup_bin_index
++);
2939 SaveBufToFile(BackBinFile
, pBackup
, 4 * SIZE_1MB
);
2940 Log("Save backup data to %s", BackBinFile
);
2942 Log("Success to backup data before clean");
2944 DISK_CleanDisk(pPhyDrive
->PhyDrive
);
2949 Log("Failed to backup data before clean");
2954 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
2956 Log("Lock disk for update ............................ ");
2957 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
2958 if (hDrive
== INVALID_HANDLE_VALUE
)
2960 Log("Failed to GetPhysicalHandle for write.");
2965 PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME
);
2967 Log("Lock volume for update .......................... ");
2968 hVolume
= INVALID_HANDLE_VALUE
;
2970 //If we change VTOYEFI to ESP, it can not have s volume name, so don't try to get it.
2973 //writeback the last 2MB
2974 if (!WriteBackupDataToDisk(hDrive
, pPhyDrive
->SizeInBytes
- SIZE_2MB
, pBackup
+ SIZE_2MB
, SIZE_2MB
))
2979 //write the first 2MB except parttable
2980 if (!WriteBackupDataToDisk(hDrive
, 34 * 512, pBackup
+ 34 * 512, SIZE_2MB
- 34 * 512))
2985 Status
= ERROR_NOT_FOUND
;
2989 Status
= ERROR_NOT_FOUND
;
2993 Status
= ERROR_NOT_FOUND
;
2997 for (i
= 0; i
< MaxRetry
; i
++)
2999 Status
= GetVentoyVolumeName(pPhyDrive
->PhyDrive
, StartSector
, DriveLetters
, sizeof(DriveLetters
), TRUE
);
3000 if (ERROR_SUCCESS
== Status
)
3006 Log("==== Volume not found, wait and retry %d... ====", i
);
3012 if (ERROR_SUCCESS
== Status
)
3014 Log("Now lock and dismount volume <%s>", DriveLetters
);
3016 for (i
= 0; i
< MaxRetry
; i
++)
3018 hVolume
= CreateFileA(DriveLetters
,
3019 GENERIC_READ
| GENERIC_WRITE
,
3023 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_NO_BUFFERING
| FILE_FLAG_WRITE_THROUGH
,
3026 if (hVolume
== INVALID_HANDLE_VALUE
)
3028 Log("Failed to create file volume, errcode:%u, wait and retry ...", LASTERR
);
3037 if (hVolume
== INVALID_HANDLE_VALUE
)
3039 Log("Failed to create file volume, errcode:%u", LASTERR
);
3043 bRet
= DeviceIoControl(hVolume
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
3044 Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
3046 bRet
= DeviceIoControl(hVolume
, FSCTL_DISMOUNT_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
3047 Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
3050 else if (ERROR_NOT_FOUND
== Status
)
3052 Log("Volume not found, maybe not supported");
3060 bRet
= TryWritePart2(hDrive
, StartSector
);
3061 if (FALSE
== bRet
&& Esp2Basic
)
3063 Log("TryWritePart2 agagin ...");
3065 bRet
= TryWritePart2(hDrive
, StartSector
);
3070 if (pPhyDrive
->PartStyle
== 0)
3072 if (DiskCheckWriteAccess(hDrive
))
3074 Log("MBR DiskCheckWriteAccess success");
3078 Log("Try write failed, now delete partition 2 for MBR...");
3079 CHECK_CLOSE_HANDLE(hDrive
);
3081 Log("Now delete partition 2...");
3082 DISK_DeleteVtoyEFIPartition(pPhyDrive
->PhyDrive
, StartSector
* 512ULL);
3084 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
3085 if (hDrive
== INVALID_HANDLE_VALUE
)
3087 Log("Failed to GetPhysicalHandle for write.");
3094 Log("MBR DiskCheckWriteAccess failed");
3099 Log("TryWritePart2 failed ....");
3105 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
3107 Log("Write Ventoy to disk ............................ ");
3108 if (0 != FormatPart2Fat(hDrive
, StartSector
))
3114 if (hVolume
!= INVALID_HANDLE_VALUE
)
3116 bRet
= DeviceIoControl(hVolume
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
3117 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
3118 CHECK_CLOSE_HANDLE(hVolume
);
3121 Log("Updating Boot Image ............................. ");
3122 if (WriteGrubStage1ToPhyDrive(hDrive
, pPhyDrive
->PartStyle
) != 0)
3128 //write reserved data
3129 SetFilePointer(hDrive
, 512 * 2040, NULL
, FILE_BEGIN
);
3130 bRet
= WriteFile(hDrive
, ReservedData
, sizeof(ReservedData
), &dwSize
, NULL
);
3131 Log("Write resv data ret:%u dwSize:%u Error:%u", bRet
, dwSize
, LASTERR
);
3134 VentoyGetLocalBootImg(&BootImg
);
3137 memcpy(BootImg
.BootCode
+ 0x180, MBR
.BootCode
+ 0x180, 16);
3138 if (pPhyDrive
->PartStyle
)
3140 BootImg
.BootCode
[92] = 0x22;
3143 if (ForceMBR
== FALSE
&& memcmp(BootImg
.BootCode
, MBR
.BootCode
, 440) == 0)
3145 Log("Boot image has no difference, no need to write.");
3149 Log("Boot image need to write %u.", ForceMBR
);
3151 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
3153 memcpy(MBR
.BootCode
, BootImg
.BootCode
, 440);
3154 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
3155 Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet
, dwSize
, LASTERR
);
3158 if (pPhyDrive
->PartStyle
== 0)
3160 if (0x00 == MBR
.PartTbl
[0].Active
&& 0x80 == MBR
.PartTbl
[1].Active
)
3162 Log("Need to chage 1st partition active and 2nd partition inactive.");
3164 MBR
.PartTbl
[0].Active
= 0x80;
3165 MBR
.PartTbl
[1].Active
= 0x00;
3167 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
3168 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
3169 Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet
, dwSize
, LASTERR
);
3175 if (!WriteBackupDataToDisk(hDrive
, 0, pBackup
, 34 * 512))
3184 Log("Write backup data success, now delete %s", BackBinFile
);
3185 DeleteFileA(BackBinFile
);
3189 Log("Write backup data failed");
3196 VTOY_GPT_HDR BackupHdr
;
3198 VentoyFillBackupGptHead(pGptBkup
, &BackupHdr
);
3199 if (!WriteBackupDataToDisk(hDrive
, 512 * pGptBkup
->Head
.EfiBackupLBA
, (BYTE
*)(&BackupHdr
), 512))
3204 if (!WriteBackupDataToDisk(hDrive
, 512 * (pGptBkup
->Head
.EfiBackupLBA
- 32), (BYTE
*)(pGptBkup
->PartTbl
), 32 * 512))
3209 if (!WriteBackupDataToDisk(hDrive
, 512, (BYTE
*)pGptBkup
+ 512, 33 * 512))
3216 Log("Write backup partition table success");
3220 Log("Write backup partition table failed");
3226 //Refresh Drive Layout
3227 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
3231 if (hVolume
!= INVALID_HANDLE_VALUE
)
3233 bRet
= DeviceIoControl(hVolume
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
3234 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
3235 CHECK_CLOSE_HANDLE(hVolume
);
3244 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
3245 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
3248 CHECK_CLOSE_HANDLE(hDrive
);
3252 Log("Recover GPT partition type to basic");
3253 DISK_ChangeVtoyEFI2Basic(pPhyDrive
->PhyDrive
, StartSector
* 512);
3256 if (pPhyDrive
->PartStyle
== 1)
3258 if (ChangeAttr
|| ((pPhyDrive
->Part2GPTAttr
>> 56) != 0xC0))
3260 Log("Change EFI partition attr %u <0x%llx> to <0x%llx>", ChangeAttr
, pPhyDrive
->Part2GPTAttr
, 0xC000000000000001ULL
);
3261 if (DISK_ChangeVtoyEFIAttr(pPhyDrive
->PhyDrive
, StartSector
* 512ULL, 0xC000000000000001ULL
))
3263 Log("Change EFI partition attr success");
3264 pPhyDrive
->Part2GPTAttr
= 0xC000000000000001ULL
;
3268 Log("Change EFI partition attr failed");