X-Git-Url: https://glassweightruler.freedombox.rocks/gitweb/Ventoy.git/blobdiff_plain/be8b6e8976c0b0aa3336ce8d3f91fb5cd104d190..0ffb1b15ef6fcbc8774133799f463bdfdbb15b4d:/Ventoy2Disk/Ventoy2Disk/PhyDrive.c diff --git a/Ventoy2Disk/Ventoy2Disk/PhyDrive.c b/Ventoy2Disk/Ventoy2Disk/PhyDrive.c index 2fb5273..d64916e 100644 --- a/Ventoy2Disk/Ventoy2Disk/PhyDrive.c +++ b/Ventoy2Disk/Ventoy2Disk/PhyDrive.c @@ -31,6 +31,36 @@ #include "ff.h" #include "DiskService.h" +static int g_backup_bin_index = 0; + + +static BOOL WriteDataToPhyDisk(HANDLE hDrive, UINT64 Offset, VOID *buffer, DWORD len) +{ + BOOL bRet; + DWORD dwSize = 0; + LARGE_INTEGER liCurPosition; + LARGE_INTEGER liNewPosition; + + liCurPosition.QuadPart = (LONGLONG)Offset; + liNewPosition.QuadPart = 0; + if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) || + liNewPosition.QuadPart != liCurPosition.QuadPart) + { + Log("SetFilePointerEx Failed %u", LASTERR); + return FALSE; + } + + bRet = WriteFile(hDrive, buffer, len, &dwSize, NULL); + if (bRet == FALSE || dwSize != len) + { + Log("Write file error %u %u", dwSize, LASTERR); + return FALSE; + } + + return TRUE; +} + + static DWORD GetVentoyVolumeName(int PhyDrive, UINT64 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash) { size_t len; @@ -109,7 +139,7 @@ static DWORD GetVentoyVolumeName(int PhyDrive, UINT64 StartSectorId, CHAR *NameB return Status; } -static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length) +int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length) { int n = 0; DWORD DataSize = 0; @@ -127,7 +157,7 @@ static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Len for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1) { - if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0])) + if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0], NULL)) { Log("%C: is belong to phydrive%d", Pos[0], PhyDrive); DriveLetters[n++] = Pos[0]; @@ -138,7 +168,7 @@ static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Len return 0; } -static HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare) +HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare) { int i; DWORD dwSize; @@ -258,11 +288,11 @@ End: return hDrive; } -int GetPhyDriveByLogicalDrive(int DriveLetter) +int GetPhyDriveByLogicalDrive(int DriveLetter, UINT64 *Offset) { - BOOL Ret; - DWORD dwSize; - HANDLE Handle; + BOOL Ret = FALSE; + DWORD dwSize = 0; + HANDLE Handle = INVALID_HANDLE_VALUE; VOLUME_DISK_EXTENTS DiskExtents; CHAR PhyPath[128]; @@ -275,6 +305,7 @@ int GetPhyDriveByLogicalDrive(int DriveLetter) return -1; } + memset(&DiskExtents, 0, sizeof(DiskExtents)); Ret = DeviceIoControl(Handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, @@ -292,13 +323,19 @@ int GetPhyDriveByLogicalDrive(int DriveLetter) } CHECK_CLOSE_HANDLE(Handle); - Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu", + Log("LogicalDrive:%s PhyDrive:%d Num:%d Offset:%llu ExtentLength:%llu", PhyPath, DiskExtents.Extents[0].DiskNumber, + DiskExtents.NumberOfDiskExtents, DiskExtents.Extents[0].StartingOffset.QuadPart, DiskExtents.Extents[0].ExtentLength.QuadPart ); + if (Offset) + { + *Offset = (UINT64)(DiskExtents.Extents[0].StartingOffset.QuadPart); + } + return (int)DiskExtents.Extents[0].DiskNumber; } @@ -318,6 +355,7 @@ int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount) STORAGE_PROPERTY_QUERY Query; STORAGE_DESCRIPTOR_HEADER DevDescHeader; STORAGE_DEVICE_DESCRIPTOR *pDevDesc; + STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment; int PhyDriveId[VENTOY_MAX_PHY_DRIVE]; Count = GetPhysicalDriveCount(); @@ -333,7 +371,7 @@ int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount) { if (dwBytes & 0x01) { - id = GetPhyDriveByLogicalDrive(Letter); + id = GetPhyDriveByLogicalDrive(Letter, NULL); Log("%C --> %d", Letter, id); if (id >= 0) { @@ -431,12 +469,35 @@ int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount) continue; } + + + memset(&Query, 0, sizeof(STORAGE_PROPERTY_QUERY)); + Query.PropertyId = StorageAccessAlignmentProperty; + Query.QueryType = PropertyStandardQuery; + memset(&diskAlignment, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR)); + + bRet = DeviceIoControl(Handle, + IOCTL_STORAGE_QUERY_PROPERTY, + &Query, + sizeof(STORAGE_PROPERTY_QUERY), + &diskAlignment, + sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), + &dwBytes, + NULL); + if (!bRet) + { + Log("DeviceIoControl3 error:%u dwBytes:%u", LASTERR, dwBytes); + } + CurDrive->PhyDrive = i; CurDrive->SizeInBytes = LengthInfo.Length.QuadPart; CurDrive->DeviceType = pDevDesc->DeviceType; CurDrive->RemovableMedia = pDevDesc->RemovableMedia; CurDrive->BusType = pDevDesc->BusType; + CurDrive->BytesPerLogicalSector = diskAlignment.BytesPerLogicalSector; + CurDrive->BytesPerPhysicalSector = diskAlignment.BytesPerPhysicalSector; + if (pDevDesc->VendorIdOffset) { safe_strcpy(CurDrive->VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset); @@ -471,9 +532,10 @@ int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount) for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++) { - Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s", + Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Sector:%u/%u Name:%s %s", CurDrive->PhyDrive, GetBusTypeString(CurDrive->BusType), CurDrive->RemovableMedia, GetHumanReadableGBSize(CurDrive->SizeInBytes), CurDrive->SizeInBytes, + CurDrive->BytesPerLogicalSector, CurDrive->BytesPerPhysicalSector, CurDrive->VendorId, CurDrive->ProductId); } @@ -482,6 +544,199 @@ int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount) return 0; } +BOOL VentoyPhydriveMatch(PHY_DRIVE_INFO* pPhyDrive) +{ + BOOL bRet = FALSE; + DWORD dwBytes; + HANDLE Handle = INVALID_HANDLE_VALUE; + CHAR PhyDrive[128]; + GET_LENGTH_INFORMATION LengthInfo; + STORAGE_PROPERTY_QUERY Query; + STORAGE_DESCRIPTOR_HEADER DevDescHeader; + STORAGE_DEVICE_DESCRIPTOR* pDevDesc = NULL; + STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment; + CHAR VendorId[128] = { 0 }; + CHAR ProductId[128] = { 0 }; + CHAR ProductRev[128] = { 0 }; + CHAR SerialNumber[128] = { 0 }; + + + safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", pPhyDrive->PhyDrive); + Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (Handle == INVALID_HANDLE_VALUE) + { + Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR); + return FALSE; + } + + bRet = DeviceIoControl(Handle, + IOCTL_DISK_GET_LENGTH_INFO, NULL, + 0, + &LengthInfo, + sizeof(LengthInfo), + &dwBytes, + NULL); + if (!bRet) + { + Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR); + return FALSE; + } + + if (pPhyDrive->SizeInBytes != (ULONGLONG)LengthInfo.Length.QuadPart) + { + Log("PHYSICALDRIVE%d size not match %llu %llu", pPhyDrive->PhyDrive, (ULONGLONG)LengthInfo.Length.QuadPart, + (ULONGLONG)pPhyDrive->SizeInBytes); + CHECK_CLOSE_HANDLE(Handle); + return FALSE; + } + + Query.PropertyId = StorageDeviceProperty; + Query.QueryType = PropertyStandardQuery; + + bRet = DeviceIoControl(Handle, + IOCTL_STORAGE_QUERY_PROPERTY, + &Query, + sizeof(Query), + &DevDescHeader, + sizeof(STORAGE_DESCRIPTOR_HEADER), + &dwBytes, + NULL); + if (!bRet) + { + Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes); + CHECK_CLOSE_HANDLE(Handle); + return FALSE; + } + + if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR)) + { + Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size); + CHECK_CLOSE_HANDLE(Handle); + return FALSE; + } + + pDevDesc = (STORAGE_DEVICE_DESCRIPTOR*)malloc(DevDescHeader.Size); + if (!pDevDesc) + { + Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size); + CHECK_CLOSE_HANDLE(Handle); + return FALSE; + } + + bRet = DeviceIoControl(Handle, + IOCTL_STORAGE_QUERY_PROPERTY, + &Query, + sizeof(Query), + pDevDesc, + DevDescHeader.Size, + &dwBytes, + NULL); + if (!bRet) + { + Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes); + free(pDevDesc); + goto out; + } + + + + memset(&Query, 0, sizeof(STORAGE_PROPERTY_QUERY)); + Query.PropertyId = StorageAccessAlignmentProperty; + Query.QueryType = PropertyStandardQuery; + memset(&diskAlignment, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR)); + + bRet = DeviceIoControl(Handle, + IOCTL_STORAGE_QUERY_PROPERTY, + &Query, + sizeof(STORAGE_PROPERTY_QUERY), + &diskAlignment, + sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), + &dwBytes, + NULL); + if (!bRet) + { + Log("DeviceIoControl3 error:%u dwBytes:%u", LASTERR, dwBytes); + } + + if (pPhyDrive->DeviceType != pDevDesc->DeviceType || + pPhyDrive->RemovableMedia != pDevDesc->RemovableMedia || + pPhyDrive->BusType != pDevDesc->BusType || + pPhyDrive->BytesPerLogicalSector != diskAlignment.BytesPerLogicalSector || + pPhyDrive->BytesPerPhysicalSector != diskAlignment.BytesPerPhysicalSector + ) + { + Log("Some properties not match DeviceType[%u %u] Removable[%u %u] BusType[%u %u] LogSec[%u %u] PhySec[%u %u]", + pPhyDrive->DeviceType, pDevDesc->DeviceType, + pPhyDrive->RemovableMedia, pDevDesc->RemovableMedia, + pPhyDrive->BusType, pDevDesc->BusType, + pPhyDrive->BytesPerLogicalSector, diskAlignment.BytesPerLogicalSector, + pPhyDrive->BytesPerPhysicalSector, diskAlignment.BytesPerPhysicalSector + ); + goto out; + } + + if (pDevDesc->VendorIdOffset) + { + safe_strcpy(VendorId, (char*)pDevDesc + pDevDesc->VendorIdOffset); + TrimString(VendorId); + + if (strcmp(pPhyDrive->VendorId, VendorId)) + { + Log("VendorId not match <%s %s>", pPhyDrive->VendorId, VendorId); + goto out; + } + } + + if (pDevDesc->ProductIdOffset) + { + safe_strcpy(ProductId, (char*)pDevDesc + pDevDesc->ProductIdOffset); + TrimString(ProductId); + + if (strcmp(pPhyDrive->ProductId, ProductId)) + { + Log("ProductId not match <%s %s>", pPhyDrive->ProductId, ProductId); + goto out; + } + } + + if (pDevDesc->ProductRevisionOffset) + { + safe_strcpy(ProductRev, (char*)pDevDesc + pDevDesc->ProductRevisionOffset); + TrimString(ProductRev); + + if (strcmp(pPhyDrive->ProductRev, ProductRev)) + { + Log("ProductRev not match <%s %s>", pPhyDrive->ProductRev, ProductRev); + goto out; + } + } + + if (pDevDesc->SerialNumberOffset) + { + safe_strcpy(SerialNumber, (char*)pDevDesc + pDevDesc->SerialNumberOffset); + TrimString(SerialNumber); + + if (strcmp(pPhyDrive->SerialNumber, SerialNumber)) + { + Log("ProductRev not match <%s %s>", pPhyDrive->SerialNumber, SerialNumber); + goto out; + } + } + + Log("PhyDrive%d ALL match, now continue", pPhyDrive->PhyDrive); + + bRet = TRUE; + +out: + if (pDevDesc) + { + free(pDevDesc); + } + + CHECK_CLOSE_HANDLE(Handle); + + return bRet; +} static HANDLE g_FatPhyDrive; static UINT64 g_Part2StartSec; @@ -688,11 +943,13 @@ int VentoyProcSecureBoot(BOOL SecureBoot) fl_fclose(file); Log("Now delete all efi files ..."); - fl_remove("/EFI/BOOT/BOOTX64.EFI"); - fl_remove("/EFI/BOOT/grubx64.efi"); + fl_remove("/EFI/BOOT/BOOTX64.EFI"); + fl_remove("/EFI/BOOT/grubx64.efi"); fl_remove("/EFI/BOOT/grubx64_real.efi"); fl_remove("/EFI/BOOT/MokManager.efi"); + fl_remove("/EFI/BOOT/mmx64.efi"); fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer"); + fl_remove("/EFI/BOOT/grub.efi"); file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb"); Log("Open bootx64 efi file %p ", file); @@ -840,7 +1097,7 @@ static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId) LARGE_INTEGER liNewPosition; BYTE *CheckBuf = NULL; - Log("FormatPart2Fat %llu...", StartSectorId); + Log("FormatPart2Fat %llu...", (ULONGLONG)StartSectorId); CheckBuf = malloc(SIZE_1MB); if (!CheckBuf) @@ -1068,6 +1325,79 @@ static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle) } +static int FormatPart1LargeFAT32(UINT64 DiskSizeBytes, int CluserSize) +{ + MKFS_PARM Option; + FRESULT Ret; + FATFS FS; + + Option.fmt = FM_FAT32; + Option.n_fat = 1; + Option.align = 8; + Option.n_root = 1; + + if (CluserSize == 0) + { + // < 32GB select 32KB as cluster size + // > 32GB select 128KB as cluster size + if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32) + { + Option.au_size = 32768; + } + else + { + Option.au_size = 131072; + } + } + else + { + Option.au_size = CluserSize; + } + + Log("Formatting Part1 large FAT32 ClusterSize:%u(%uKB) ...", CluserSize, CluserSize / 1024); + + disk_io_reset_write_error(); + + Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024); + if (FR_OK == Ret) + { + if (disk_io_is_write_error()) + { + Log("Formatting Part1 large FAT32 failed, write error."); + return 1; + } + + Log("Formatting Part1 large FAT32 success, now set label"); + + Ret = f_mount(&FS, TEXT("0:"), 1); + if (FR_OK == Ret) + { + Log("f_mount SUCCESS"); + Ret = f_setlabel(TEXT("0:Ventoy")); + if (FR_OK == Ret) + { + Log("f_setlabel SUCCESS"); + Ret = f_unmount(TEXT("0:")); + Log("f_unmount %d %s", Ret, (FR_OK == Ret) ? "SUCCESS" : "FAILED"); + } + else + { + Log("f_setlabel failed %d", Ret); + } + } + else + { + Log("f_mount failed %d", Ret); + } + + return 0; + } + else + { + Log("Formatting Part1 large FAT32 failed"); + return 1; + } +} static int FormatPart1exFAT(UINT64 DiskSizeBytes) { @@ -1092,9 +1422,17 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes) Log("Formatting Part1 exFAT ..."); + disk_io_reset_write_error(); + Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024); if (FR_OK == Ret) { + if (disk_io_is_write_error()) + { + Log("Formatting Part1 exFAT failed, write error."); + return 1; + } + Log("Formatting Part1 exFAT success"); return 0; } @@ -1105,7 +1443,45 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes) } } +static int ZeroPart1FileSystem(HANDLE hDrive, UINT64 Part2StartSector) +{ + int i; + DWORD dwSize = 0; + LARGE_INTEGER liCurPos; + LARGE_INTEGER liNewPos; + CHAR TmpBuffer[1024] = { 0 }; + + liCurPos.QuadPart = VENTOY_PART1_START_SECTOR * 512; + liNewPos.QuadPart = 0; + if (0 == SetFilePointerEx(hDrive, liCurPos, &liNewPos, FILE_BEGIN) || + liNewPos.QuadPart != liCurPos.QuadPart) + { + Log("SetFilePointerEx Failed %u %llu %llu", LASTERR, (ULONGLONG)liCurPos.QuadPart, (ULONGLONG)liNewPos.QuadPart); + return 1; + } + + for (i = 0; i < 1024; i++) + { + WriteFile(hDrive, TmpBuffer, 1024, &dwSize, NULL); + } + + liCurPos.QuadPart = (Part2StartSector * 512) - (1024 * 1024); + liNewPos.QuadPart = 0; + if (0 == SetFilePointerEx(hDrive, liCurPos, &liNewPos, FILE_BEGIN) || + liNewPos.QuadPart != liCurPos.QuadPart) + { + Log("SetFilePointerEx Failed %u %llu %llu", LASTERR, (ULONGLONG)liCurPos.QuadPart, (ULONGLONG)liNewPos.QuadPart); + return 1; + } + + for (i = 0; i < 1024; i++) + { + WriteFile(hDrive, TmpBuffer, 1024, &dwSize, NULL); + } + Log("Zero Part1 SUCCESS"); + return 0; +} int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter) { @@ -1291,6 +1667,7 @@ int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLett End: PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME); + PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH); if (pTmpBuf) { @@ -1428,7 +1805,7 @@ int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle) memset(pData, 0, 512); pMBR = (MBR_HEAD *)pData; - VentoyFillMBR(pPhyDrive->SizeInBytes, pMBR, PartStyle); + VentoyFillMBR(pPhyDrive->SizeInBytes, pMBR, PartStyle, 0x07); Part1StartSector = pMBR->PartTbl[0].StartSectorId; Part1SectorCount = pMBR->PartTbl[0].SectorCount; Part2StartSector = pMBR->PartTbl[1].StartSectorId; @@ -1562,6 +1939,7 @@ int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle) End: PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME); + PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH); Log("retcode:%d\n", rc); @@ -1577,6 +1955,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId) int i; int rc = 0; int state = 0; + BOOL ReformatOK; HANDLE hDrive; DWORD dwSize; BOOL bRet; @@ -1588,10 +1967,15 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId) UINT64 Part1StartSector = 0; UINT64 Part1SectorCount = 0; UINT64 Part2StartSector = 0; + BOOL LargeFAT32 = FALSE; + BOOL DefaultExFAT = FALSE; + UINT8 FsFlag = 0x07; + Log("#####################################################"); Log("InstallVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId, PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); + Log("#####################################################"); if (PartStyle) { @@ -1610,7 +1994,12 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId) } else { - VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle); + if (GetVentoyFsType() == VTOY_FS_FAT32) + { + FsFlag = 0x0C; + } + + VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle, FsFlag); Part1StartSector = MBR.PartTbl[0].StartSectorId; Part1SectorCount = MBR.PartTbl[0].SectorCount; Part2StartSector = MBR.PartTbl[1].StartSectorId; @@ -1658,9 +2047,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId) if (!VDS_DeleteAllPartitions(pPhyDrive->PhyDrive)) { - Log("Notice: Could not delete partitions: 0x%x", GetLastError()); - rc = 1; - goto End; + Log("Notice: Could not delete partitions: 0x%x, but we continue.", GetLastError()); } Log("Deleting all partitions ......................... OK"); @@ -1689,12 +2076,37 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId) Sleep(1000 * 5); } - Log("Formatting part1 exFAT ..."); - if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes)) + if (GetVentoyFsType() == VTOY_FS_FAT32 && (Part1SectorCount * 512 >= FAT32_MAX_LIMIT)) { - Log("FormatPart1exFAT failed."); - rc = 1; - goto End; + Log("Formatting part1 large FAT32 ..."); + LargeFAT32 = TRUE; + if (0 != FormatPart1LargeFAT32(pPhyDrive->SizeInBytes, GetClusterSize())) + { + Log("FormatPart1LargeFAT32 failed."); + rc = 1; + goto End; + } + } + else if (GetVentoyFsType() == VTOY_FS_EXFAT && GetClusterSize() == 0) + { + Log("Formatting part1 exFAT ..."); + DefaultExFAT = TRUE; + if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes)) + { + Log("FormatPart1exFAT failed."); + rc = 1; + goto End; + } + } + else + { + Log("Zero part1 file system ..."); + if (0 != ZeroPart1FileSystem(hDrive, Part2StartSector)) + { + Log("ZeroPart1FileSystem failed."); + rc = 1; + goto End; + } } PROGRESS_BAR_SET_POS(PT_FORMAT_PART2); @@ -1793,6 +2205,7 @@ End: else { Log("%s is ventoy part1, already mounted", DriveName); + MountDrive = DriveName[0]; state = 1; } } @@ -1806,42 +2219,476 @@ End: DriveName[0] = MountDrive; bRet = SetVolumeMountPointA(DriveName, DriveLetters); Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError()); + + if (bRet) + { + state = 1; + } } else { Log("Failed to find ventoy volume"); } } - Log("OK\n"); - } - else - { - FindProcessOccupyDisk(hDrive, pPhyDrive); - } - if (pGptInfo) - { - free(pGptInfo); - } + // close handle, or it will deny reformat + Log("Close handle ..."); + CHECK_CLOSE_HANDLE(hDrive); - CHECK_CLOSE_HANDLE(hDrive); - return rc; -} + ReformatOK = TRUE; -static BOOL BackupDataBeforeCleanDisk(int PhyDrive, UINT64 DiskSize, BYTE **pBackup) -{ - DWORD dwSize; - DWORD dwStatus; - BOOL Return = FALSE; - BOOL ret = FALSE; - BYTE *backup = NULL; - HANDLE hDrive = INVALID_HANDLE_VALUE; - LARGE_INTEGER liCurPosition; - LARGE_INTEGER liNewPosition; + if (state) + { + if (LargeFAT32) + { + Log("No need to reformat for large FAT32"); + pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive); + } + else if (DefaultExFAT) + { + Log("No need to reformat for default exfat"); + pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive); + } + else + { + bRet = DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512); + for (i = 0; bRet == FALSE && i < 2; i++) + { + Log("Wait and retry reformat ..."); + Sleep(1000); + bRet = DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512); + } + + if (bRet) + { + Log("Reformat %C:\\ to %s SUCCESS", MountDrive, GetVentoyFsName()); + pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive); + + if ((GetVentoyFsType() != VTOY_FS_UDF) && (pPhyDrive->VentoyFsClusterSize < 2048)) + { + for (i = 0; i < 10; i++) + { + Log("### Invalid cluster size %d ###", pPhyDrive->VentoyFsClusterSize); + } + } + } + else + { + ReformatOK = FALSE; + Log("Reformat %C:\\ to %s FAILED", MountDrive, GetVentoyFsName()); + } + } + } + else + { + Log("Can not reformat %s to %s", DriveName, GetVentoyFsName()); + } + + if (!ReformatOK) + { + Log("Format to exfat with built-in algorithm"); + + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to GetPhysicalHandle for write."); + } + else + { + if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes)) + { + Log("FormatPart1exFAT SUCCESS."); + } + else + { + Log("FormatPart1exFAT FAILED."); + } + + CHECK_CLOSE_HANDLE(hDrive); + } + } + + Log("OK\n"); + } + else + { + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); + + FindProcessOccupyDisk(hDrive, pPhyDrive); + + if (!VDS_IsLastAvaliable()) + { + Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######"); + Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######"); + Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######"); + Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######"); + Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######"); + } + + CHECK_CLOSE_HANDLE(hDrive); + } + + if (pGptInfo) + { + free(pGptInfo); + } + + return rc; +} + + +int PartitionResizeForVentoy(PHY_DRIVE_INFO *pPhyDrive) +{ + int i, j; + int rc = 1; + int PhyDrive; + int PartStyle; + UINT64 RecudeBytes; + GUID Guid; + MBR_HEAD MBR; + VTOY_GPT_INFO *pGPT; + MBR_HEAD *pMBR; + DWORD dwSize = 0; + VTOY_GPT_HDR BackupHead; + HANDLE hDrive = INVALID_HANDLE_VALUE; + GUID ZeroGuid = { 0 }; + static GUID WindowsDataPartType = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } }; + static GUID EspPartType = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } }; + static GUID BiosGrubPartType = { 0x21686148, 0x6449, 0x6e6f, { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } }; + + Log("#####################################################"); + Log("PartitionResizeForVentoy PhyDrive%d <<%s %s %dGB>>", + pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, + GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); + Log("#####################################################"); + + pGPT = &(pPhyDrive->Gpt); + pMBR = &(pPhyDrive->Gpt.MBR); + Log("Disksize:%llu Part2Start:%llu", pPhyDrive->SizeInBytes, pPhyDrive->ResizePart2StartSector * 512); + + if (pMBR->PartTbl[0].FsFlag == 0xEE && memcmp(pGPT->Head.Signature, "EFI PART", 8) == 0) + { + PartStyle = 1; + } + else + { + PartStyle = 0; + } + + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); + + RecudeBytes = VENTOY_EFI_PART_SIZE; + + if (pPhyDrive->ResizeNoShrink == FALSE) + { + Log("Need to shrink the volume"); + if (DISK_ShrinkVolume(pPhyDrive->PhyDrive, pPhyDrive->ResizeVolumeGuid, pPhyDrive->Part1DriveLetter, pPhyDrive->ResizeOldPart1Size, RecudeBytes)) + { + Log("Shrink volume success, now check again"); + + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to GetPhysicalHandle for update."); + goto End; + } + + //Refresh Drive Layout + DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); + + CHECK_CLOSE_HANDLE(hDrive); + + + if (PartResizePreCheck(NULL) && pPhyDrive->ResizeNoShrink) + { + Log("Recheck after Shrink volume success"); + Log("After shrink Disksize:%llu Part2Start:%llu", pPhyDrive->SizeInBytes, pPhyDrive->ResizePart2StartSector * 512); + } + else + { + Log("Recheck after Shrink volume failed %u", pPhyDrive->ResizeNoShrink); + goto End; + } + } + else + { + Log("Shrink volume failed"); + goto End; + } + } + + + //Now try write data + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to GetPhysicalHandle for update."); + goto End; + } + + + //Write partition 2 data + PROGRESS_BAR_SET_POS(PT_FORMAT_PART2); + if (0 != FormatPart2Fat(hDrive, pPhyDrive->ResizePart2StartSector)) + { + Log("FormatPart2Fat failed."); + goto End; + } + + //Write grub stage2 gap + PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG); + Log("Writing Boot Image ............................. "); + if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0) + { + Log("WriteGrubStage1ToPhyDrive failed."); + goto End; + } + + + //Write partition table + PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE); + Log("Writing partition table ............................. "); + + VentoyGetLocalBootImg(&MBR); + CoCreateGuid(&Guid); + memcpy(MBR.BootCode + 0x180, &Guid, 16); + memcpy(pMBR->BootCode, MBR.BootCode, 440); + + if (PartStyle == 0) + { + for (i = 1; i < 4; i++) + { + if (pMBR->PartTbl[i].SectorCount == 0) + { + break; + } + } + + if (i >= 4) + { + Log("Can not find MBR free partition table"); + goto End; + } + + for (j = i - 1; j > 0; j--) + { + Log("Move MBR partition table %d --> %d", j + 1, j + 2); + memcpy(pMBR->PartTbl + (j + 1), pMBR->PartTbl + j, sizeof(PART_TABLE)); + } + + memset(pMBR->PartTbl + 1, 0, sizeof(PART_TABLE)); + VentoyFillMBRLocation(pPhyDrive->SizeInBytes, (UINT32)pPhyDrive->ResizePart2StartSector, VENTOY_EFI_PART_SIZE / 512, pMBR->PartTbl + 1); + pMBR->PartTbl[0].Active = 0x80; // bootable + pMBR->PartTbl[1].Active = 0x00; + pMBR->PartTbl[1].FsFlag = 0xEF; // EFI System Partition + + if (!WriteDataToPhyDisk(hDrive, 0, pMBR, 512)) + { + Log("Legacy BIOS write MBR failed"); + goto End; + } + } + else + { + for (i = 1; i < 128; i++) + { + if (memcmp(&(pGPT->PartTbl[i].PartGuid), &ZeroGuid, sizeof(GUID)) == 0) + { + break; + } + } + + if (i >= 128) + { + Log("Can not find GPT free partition table"); + goto End; + } + + for (j = i - 1; j > 0; j--) + { + Log("Move GPT partition table %d --> %d", j + 1, j + 2); + memcpy(pGPT->PartTbl + (j + 1), pGPT->PartTbl + j, sizeof(VTOY_GPT_PART_TBL)); + } + + + pMBR->BootCode[92] = 0x22; + + // to fix windows issue + memset(pGPT->PartTbl + 1, 0, sizeof(VTOY_GPT_PART_TBL)); + memcpy(&(pGPT->PartTbl[1].PartType), &WindowsDataPartType, sizeof(GUID)); + CoCreateGuid(&(pGPT->PartTbl[1].PartGuid)); + + pGPT->PartTbl[1].StartLBA = pGPT->PartTbl[0].LastLBA + 1; + pGPT->PartTbl[1].LastLBA = pGPT->PartTbl[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1; + pGPT->PartTbl[1].Attr = 0xC000000000000001ULL; + memcpy(pGPT->PartTbl[1].Name, L"VTOYEFI", 7 * 2); + + //Update CRC + pGPT->Head.PartTblCrc = VentoyCrc32(pGPT->PartTbl, sizeof(pGPT->PartTbl)); + pGPT->Head.Crc = 0; + pGPT->Head.Crc = VentoyCrc32(&(pGPT->Head), pGPT->Head.Length); + + Log("pGPT->Head.EfiStartLBA=%llu", (ULONGLONG)pGPT->Head.EfiStartLBA); + Log("pGPT->Head.EfiBackupLBA=%llu", (ULONGLONG)pGPT->Head.EfiBackupLBA); + + VentoyFillBackupGptHead(pGPT, &BackupHead); + if (!WriteDataToPhyDisk(hDrive, pGPT->Head.EfiBackupLBA * 512, &BackupHead, 512)) + { + Log("UEFI write backup head failed"); + goto End; + } + + if (!WriteDataToPhyDisk(hDrive, (pGPT->Head.EfiBackupLBA - 32) * 512, pGPT->PartTbl, 512 * 32)) + { + Log("UEFI write backup partition table failed"); + goto End; + } + + if (!WriteDataToPhyDisk(hDrive, 0, pGPT, 512 * 34)) + { + Log("UEFI write MBR & Main partition table failed"); + goto End; + } + } + + + + //Refresh Drive Layout + DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL); + + //We must close handle here, because it will block the refresh bellow + CHECK_CLOSE_HANDLE(hDrive); + + Sleep(2000); + + if (g_CLI_Mode) + { + Log("### Ventoy non-destructive CLI installation successfully finished."); + } + else + { + //Refresh disk list + PhyDrive = pPhyDrive->PhyDrive; + + Log("#### Now Refresh PhyDrive ####"); + Ventoy2DiskDestroy(); + Ventoy2DiskInit(); + + pPhyDrive = GetPhyDriveInfoByPhyDrive(PhyDrive); + if (pPhyDrive) + { + if (pPhyDrive->VentoyVersion[0] == 0) + { + Log("After process the Ventoy version is still invalid"); + goto End; + } + + Log("### Ventoy non-destructive installation successfully finished <%s>", pPhyDrive->VentoyVersion); + } + else + { + Log("### Ventoy non-destructive installation successfully finished "); + } + + InitComboxCtrl(g_DialogHwnd, PhyDrive); + } + + rc = 0; + +End: + CHECK_CLOSE_HANDLE(hDrive); + return rc; +} + + +static BOOL DiskCheckWriteAccess(HANDLE hDrive) +{ + DWORD dwSize; + BOOL ret = FALSE; + BOOL bRet = FALSE; + BYTE Buffer[512]; + LARGE_INTEGER liCurPosition; + LARGE_INTEGER liNewPosition; + + liCurPosition.QuadPart = 2039 * 512; + liNewPosition.QuadPart = 0; + if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) || + liNewPosition.QuadPart != liCurPosition.QuadPart) + { + Log("SetFilePointer1 Failed %u", LASTERR); + goto out; + } + + + dwSize = 0; + ret = ReadFile(hDrive, Buffer, 512, &dwSize, NULL); + if ((!ret) || (dwSize != 512)) + { + Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR); + goto out; + } + + + liCurPosition.QuadPart = 2039 * 512; + liNewPosition.QuadPart = 0; + if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) || + liNewPosition.QuadPart != liCurPosition.QuadPart) + { + Log("SetFilePointer2 Failed %u", LASTERR); + goto out; + } + + dwSize = 0; + ret = WriteFile(hDrive, Buffer, 512, &dwSize, NULL); + if ((!ret) || dwSize != 512) + { + Log("Failed to write %d %u %u", ret, dwSize, LASTERR); + goto out; + } + + bRet = TRUE; + +out: + + return bRet; +} + +static BOOL BackupDataBeforeCleanDisk(int PhyDrive, UINT64 DiskSize, BYTE **pBackup) +{ + DWORD dwSize; + DWORD dwStatus; + BOOL Return = FALSE; + BOOL ret = FALSE; + BYTE *backup = NULL; + UINT64 offset; + HANDLE hDrive = INVALID_HANDLE_VALUE; + LARGE_INTEGER liCurPosition; + LARGE_INTEGER liNewPosition; + VTOY_GPT_INFO *pGPT = NULL; Log("BackupDataBeforeCleanDisk %d", PhyDrive); - backup = malloc(SIZE_1MB * 3); + // step1: check write access + hDrive = GetPhysicalHandle(PhyDrive, TRUE, TRUE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to GetPhysicalHandle for write."); + goto out; + } + + if (DiskCheckWriteAccess(hDrive)) + { + Log("DiskCheckWriteAccess success"); + CHECK_CLOSE_HANDLE(hDrive); + } + else + { + Log("DiskCheckWriteAccess failed"); + goto out; + } + + //step2 backup 4MB data + backup = malloc(SIZE_1MB * 4); if (!backup) { goto out; @@ -1853,7 +2700,7 @@ static BOOL BackupDataBeforeCleanDisk(int PhyDrive, UINT64 DiskSize, BYTE **pBac goto out; } - //read first 1MB + //read first 2MB dwStatus = SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); if (dwStatus != 0) { @@ -1861,14 +2708,27 @@ static BOOL BackupDataBeforeCleanDisk(int PhyDrive, UINT64 DiskSize, BYTE **pBac } dwSize = 0; - ret = ReadFile(hDrive, backup, SIZE_1MB, &dwSize, NULL); - if ((!ret) || (dwSize != SIZE_1MB)) + ret = ReadFile(hDrive, backup, SIZE_2MB, &dwSize, NULL); + if ((!ret) || (dwSize != SIZE_2MB)) { Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR); goto out; } - liCurPosition.QuadPart = DiskSize - (SIZE_1MB * 2); + pGPT = (VTOY_GPT_INFO *)backup; + offset = pGPT->Head.EfiBackupLBA * 512; + if (offset >= (DiskSize - SIZE_2MB) && offset < DiskSize) + { + Log("EFI partition table check success"); + } + else + { + Log("Backup EFI LBA not in last 2MB range: %llu", pGPT->Head.EfiBackupLBA); + goto out; + } + + //read last 2MB + liCurPosition.QuadPart = DiskSize - SIZE_2MB; liNewPosition.QuadPart = 0; if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) || liNewPosition.QuadPart != liCurPosition.QuadPart) @@ -1877,8 +2737,8 @@ static BOOL BackupDataBeforeCleanDisk(int PhyDrive, UINT64 DiskSize, BYTE **pBac } dwSize = 0; - ret = ReadFile(hDrive, backup + SIZE_1MB, 2 * SIZE_1MB, &dwSize, NULL); - if ((!ret) || (dwSize != 2 * SIZE_1MB)) + ret = ReadFile(hDrive, backup + SIZE_2MB, SIZE_2MB, &dwSize, NULL); + if ((!ret) || (dwSize != SIZE_2MB)) { Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR); goto out; @@ -1930,11 +2790,13 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId) { int i; int rc = 0; - int MaxRetry = 3; + int MaxRetry = 4; BOOL ForceMBR = FALSE; BOOL Esp2Basic = FALSE; BOOL ChangeAttr = FALSE; BOOL CleanDisk = FALSE; + BOOL DelEFI = FALSE; + BOOL bWriteBack = TRUE; HANDLE hVolume; HANDLE hDrive; DWORD Status; @@ -1942,17 +2804,21 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId) BOOL bRet; CHAR DriveName[] = "?:\\"; CHAR DriveLetters[MAX_PATH] = { 0 }; + CHAR BackBinFile[MAX_PATH]; UINT64 StartSector; UINT64 ReservedMB = 0; MBR_HEAD BootImg; MBR_HEAD MBR; BYTE *pBackup = NULL; VTOY_GPT_INFO *pGptInfo = NULL; + VTOY_GPT_INFO *pGptBkup = NULL; UINT8 ReservedData[4096]; + Log("#####################################################"); Log("UpdateVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId, pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, GetHumanReadableGBSize(pPhyDrive->SizeInBytes)); + Log("#####################################################"); PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); @@ -1967,17 +2833,19 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId) if (pPhyDrive->PartStyle) { - pGptInfo = malloc(sizeof(VTOY_GPT_INFO)); + pGptInfo = malloc(2 * sizeof(VTOY_GPT_INFO)); if (!pGptInfo) { return 1; } - memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO)); + memset(pGptInfo, 0, 2 * sizeof(VTOY_GPT_INFO)); + pGptBkup = pGptInfo + 1; // Read GPT Info SetFilePointer(hDrive, 0, NULL, FILE_BEGIN); ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL); + memcpy(pGptBkup, pGptInfo, sizeof(VTOY_GPT_INFO)); //MBR will be used to compare with local boot image memcpy(&MBR, &pGptInfo->MBR, sizeof(MBR_HEAD)); @@ -2041,30 +2909,40 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId) if (TryId == 1) { Log("Change GPT partition type to ESP"); - if (VDS_ChangeVtoyEFI2ESP(pPhyDrive->PhyDrive, StartSector * 512)) + if (DISK_ChangeVtoyEFI2ESP(pPhyDrive->PhyDrive, StartSector * 512ULL)) { Esp2Basic = TRUE; - Sleep(1000); + Sleep(3000); } } else if (TryId == 2) { Log("Change GPT partition attribute"); - if (VDS_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, 0x8000000000000001)) + if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, 0x8000000000000001)) { ChangeAttr = TRUE; - Sleep(1000); + Sleep(2000); } } else if (TryId == 3) + { + DISK_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive, StartSector * 512ULL); + DelEFI = TRUE; + } + else if (TryId == 4) { Log("Clean disk GPT partition table"); if (BackupDataBeforeCleanDisk(pPhyDrive->PhyDrive, pPhyDrive->SizeInBytes, &pBackup)) { + sprintf_s(BackBinFile, sizeof(BackBinFile), ".\\ventoy\\phydrive%d_%u_%d.bin", + pPhyDrive->PhyDrive, GetCurrentProcessId(), g_backup_bin_index++); + SaveBufToFile(BackBinFile, pBackup, 4 * SIZE_1MB); + Log("Save backup data to %s", BackBinFile); + Log("Success to backup data before clean"); CleanDisk = TRUE; - VDS_CleanDisk(pPhyDrive->PhyDrive); - Sleep(1000); + DISK_CleanDisk(pPhyDrive->PhyDrive); + Sleep(3000); } else { @@ -2092,7 +2970,22 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId) //If we change VTOYEFI to ESP, it can not have s volume name, so don't try to get it. if (CleanDisk) { - WriteBackupDataToDisk(hDrive, pPhyDrive->SizeInBytes - (2 * SIZE_1MB), pBackup + SIZE_1MB, 2 * SIZE_1MB); + //writeback the last 2MB + if (!WriteBackupDataToDisk(hDrive, pPhyDrive->SizeInBytes - SIZE_2MB, pBackup + SIZE_2MB, SIZE_2MB)) + { + bWriteBack = FALSE; + } + + //write the first 2MB except parttable + if (!WriteBackupDataToDisk(hDrive, 34 * 512, pBackup + 34 * 512, SIZE_2MB - 34 * 512)) + { + bWriteBack = FALSE; + } + + Status = ERROR_NOT_FOUND; + } + else if (DelEFI) + { Status = ERROR_NOT_FOUND; } else if (Esp2Basic) @@ -2164,24 +3057,41 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId) goto End; } - if (!TryWritePart2(hDrive, StartSector)) + bRet = TryWritePart2(hDrive, StartSector); + if (FALSE == bRet && Esp2Basic) + { + Log("TryWritePart2 agagin ..."); + Sleep(3000); + bRet = TryWritePart2(hDrive, StartSector); + } + + if (!bRet) { if (pPhyDrive->PartStyle == 0) { - ForceMBR = TRUE; + if (DiskCheckWriteAccess(hDrive)) + { + Log("MBR DiskCheckWriteAccess success"); - Log("Try write failed, now delete partition 2 for MBR..."); - CHECK_CLOSE_HANDLE(hDrive); + ForceMBR = TRUE; - Log("Now delete partition 2..."); - VDS_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive); + Log("Try write failed, now delete partition 2 for MBR..."); + CHECK_CLOSE_HANDLE(hDrive); - hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); - if (hDrive == INVALID_HANDLE_VALUE) + Log("Now delete partition 2..."); + DISK_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive, StartSector * 512ULL); + + hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE); + if (hDrive == INVALID_HANDLE_VALUE) + { + Log("Failed to GetPhysicalHandle for write."); + rc = 1; + goto End; + } + } + else { - Log("Failed to GetPhysicalHandle for write."); - rc = 1; - goto End; + Log("MBR DiskCheckWriteAccess failed"); } } else @@ -2262,9 +3172,55 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId) if (CleanDisk) { - WriteBackupDataToDisk(hDrive, 4 * 512, pBackup + 4 * 512, SIZE_1MB - 4 * 512); - WriteBackupDataToDisk(hDrive, 0, pBackup, 4 * 512); + if (!WriteBackupDataToDisk(hDrive, 0, pBackup, 34 * 512)) + { + bWriteBack = FALSE; + } + free(pBackup); + + if (bWriteBack) + { + Log("Write backup data success, now delete %s", BackBinFile); + DeleteFileA(BackBinFile); + } + else + { + Log("Write backup data failed"); + } + + Sleep(1000); + } + else if (DelEFI) + { + VTOY_GPT_HDR BackupHdr; + + VentoyFillBackupGptHead(pGptBkup, &BackupHdr); + if (!WriteBackupDataToDisk(hDrive, 512 * pGptBkup->Head.EfiBackupLBA, (BYTE*)(&BackupHdr), 512)) + { + bWriteBack = FALSE; + } + + if (!WriteBackupDataToDisk(hDrive, 512 * (pGptBkup->Head.EfiBackupLBA - 32), (BYTE*)(pGptBkup->PartTbl), 32 * 512)) + { + bWriteBack = FALSE; + } + + if (!WriteBackupDataToDisk(hDrive, 512, (BYTE*)pGptBkup + 512, 33 * 512)) + { + bWriteBack = FALSE; + } + + if (bWriteBack) + { + Log("Write backup partition table success"); + } + else + { + Log("Write backup partition table failed"); + } + + Sleep(1000); } //Refresh Drive Layout @@ -2272,12 +3228,20 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId) End: + if (hVolume != INVALID_HANDLE_VALUE) + { + bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL); + Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR); + CHECK_CLOSE_HANDLE(hVolume); + } + if (rc == 0) { Log("OK"); } else { + PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN); FindProcessOccupyDisk(hDrive, pPhyDrive); } @@ -2286,20 +3250,23 @@ End: if (Esp2Basic) { Log("Recover GPT partition type to basic"); - VDS_ChangeVtoyEFI2Basic(pPhyDrive->PhyDrive, StartSector * 512); + DISK_ChangeVtoyEFI2Basic(pPhyDrive->PhyDrive, StartSector * 512); } - if (ChangeAttr || ((pPhyDrive->Part2GPTAttr >> 56) != 0xC0)) + if (pPhyDrive->PartStyle == 1) { - Log("Change EFI partition attr %u <0x%llx> to <0x%llx>", ChangeAttr, pPhyDrive->Part2GPTAttr, 0xC000000000000001ULL); - if (VDS_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, 0xC000000000000001ULL)) - { - Log("Change EFI partition attr success"); - pPhyDrive->Part2GPTAttr = 0xC000000000000001ULL; - } - else + if (ChangeAttr || ((pPhyDrive->Part2GPTAttr >> 56) != 0xC0)) { - Log("Change EFI partition attr failed"); + Log("Change EFI partition attr %u <0x%llx> to <0x%llx>", ChangeAttr, pPhyDrive->Part2GPTAttr, 0xC000000000000001ULL); + if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, 0xC000000000000001ULL)) + { + Log("Change EFI partition attr success"); + pPhyDrive->Part2GPTAttr = 0xC000000000000001ULL; + } + else + { + Log("Change EFI partition attr failed"); + } } }