]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - Ventoy2Disk/Ventoy2Disk/PhyDrive.c
1. Add new options for Windows CLI mode.
[Ventoy.git] / Ventoy2Disk / Ventoy2Disk / PhyDrive.c
index 570f28eac03dae330382f20c16b90914dfd995df..42d74d065274c0ac0b170023447910f4185faf82 100644 (file)
@@ -20,6 +20,7 @@
  */\r
  \r
 #include <Windows.h>\r
+#include <time.h>\r
 #include <winternl.h>\r
 #include <commctrl.h>\r
 #include <initguid.h>\r
 #include "ff.h"\r
 #include "DiskService.h"\r
 \r
+static int g_backup_bin_index = 0;\r
+\r
+\r
+static BOOL WriteDataToPhyDisk(HANDLE hDrive, UINT64 Offset, VOID *buffer, DWORD len)\r
+{\r
+       BOOL bRet;\r
+       DWORD dwSize = 0;\r
+       LARGE_INTEGER liCurPosition;\r
+       LARGE_INTEGER liNewPosition;\r
+\r
+       liCurPosition.QuadPart = (LONGLONG)Offset;\r
+       liNewPosition.QuadPart = 0;\r
+       if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||\r
+               liNewPosition.QuadPart != liCurPosition.QuadPart)\r
+       {\r
+               Log("SetFilePointerEx Failed %u", LASTERR);\r
+               return FALSE;\r
+       }\r
+\r
+       bRet = WriteFile(hDrive, buffer, len, &dwSize, NULL);\r
+       if (bRet == FALSE || dwSize != len)\r
+       {\r
+               Log("Write file error %u %u", dwSize, LASTERR);\r
+               return FALSE;\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+\r
 static DWORD GetVentoyVolumeName(int PhyDrive, UINT64 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash)\r
 {\r
     size_t len;\r
@@ -108,7 +139,7 @@ static DWORD GetVentoyVolumeName(int PhyDrive, UINT64 StartSectorId, CHAR *NameB
     return Status;\r
 }\r
 \r
-static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length)\r
+int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length)\r
 {\r
     int n = 0;\r
     DWORD DataSize = 0;\r
@@ -126,7 +157,7 @@ static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Len
 \r
     for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1)\r
     {\r
-        if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0]))\r
+        if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0], NULL))\r
         {\r
             Log("%C: is belong to phydrive%d", Pos[0], PhyDrive);\r
             DriveLetters[n++] = Pos[0];\r
@@ -137,7 +168,7 @@ static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Len
     return 0;\r
 }\r
 \r
-static HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare)\r
+HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare)\r
 {\r
     int i;\r
     DWORD dwSize;\r
@@ -257,11 +288,11 @@ End:
     return hDrive;\r
 }\r
 \r
-int GetPhyDriveByLogicalDrive(int DriveLetter)\r
+int GetPhyDriveByLogicalDrive(int DriveLetter, UINT64 *Offset)\r
 {\r
-    BOOL Ret;\r
-    DWORD dwSize;\r
-    HANDLE Handle;\r
+    BOOL Ret = FALSE;\r
+    DWORD dwSize = 0;\r
+    HANDLE Handle = INVALID_HANDLE_VALUE;\r
     VOLUME_DISK_EXTENTS DiskExtents;\r
     CHAR PhyPath[128];\r
 \r
@@ -274,6 +305,7 @@ int GetPhyDriveByLogicalDrive(int DriveLetter)
         return -1;\r
     }\r
 \r
+    memset(&DiskExtents, 0, sizeof(DiskExtents));\r
     Ret = DeviceIoControl(Handle,\r
         IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,\r
         NULL,\r
@@ -291,13 +323,19 @@ int GetPhyDriveByLogicalDrive(int DriveLetter)
     }\r
     CHECK_CLOSE_HANDLE(Handle);\r
 \r
-    Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",\r
+    Log("LogicalDrive:%s PhyDrive:%d Num:%d Offset:%llu ExtentLength:%llu",\r
         PhyPath,\r
         DiskExtents.Extents[0].DiskNumber,\r
+        DiskExtents.NumberOfDiskExtents,\r
         DiskExtents.Extents[0].StartingOffset.QuadPart,\r
         DiskExtents.Extents[0].ExtentLength.QuadPart\r
         );\r
 \r
+       if (Offset)\r
+       {\r
+               *Offset = (UINT64)(DiskExtents.Extents[0].StartingOffset.QuadPart);\r
+       }\r
+\r
     return (int)DiskExtents.Extents[0].DiskNumber;\r
 }\r
 \r
@@ -317,6 +355,7 @@ int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)
     STORAGE_PROPERTY_QUERY Query;\r
     STORAGE_DESCRIPTOR_HEADER DevDescHeader;\r
     STORAGE_DEVICE_DESCRIPTOR *pDevDesc;\r
+    STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment;\r
     int PhyDriveId[VENTOY_MAX_PHY_DRIVE];\r
 \r
     Count = GetPhysicalDriveCount();\r
@@ -332,7 +371,7 @@ int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)
     {\r
         if (dwBytes & 0x01)\r
         {\r
-            id = GetPhyDriveByLogicalDrive(Letter);\r
+                       id = GetPhyDriveByLogicalDrive(Letter, NULL);\r
             Log("%C --> %d", Letter, id);\r
             if (id >= 0)\r
             {\r
@@ -430,12 +469,35 @@ int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)
             continue;\r
         }\r
 \r
+\r
+\r
+        memset(&Query, 0, sizeof(STORAGE_PROPERTY_QUERY));\r
+        Query.PropertyId = StorageAccessAlignmentProperty;\r
+        Query.QueryType = PropertyStandardQuery;\r
+        memset(&diskAlignment, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR));\r
+\r
+        bRet = DeviceIoControl(Handle,\r
+                               IOCTL_STORAGE_QUERY_PROPERTY,\r
+                               &Query,\r
+                               sizeof(STORAGE_PROPERTY_QUERY),\r
+                               &diskAlignment,\r
+                               sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),\r
+                               &dwBytes,\r
+                               NULL);\r
+        if (!bRet)\r
+        {\r
+            Log("DeviceIoControl3 error:%u dwBytes:%u", LASTERR, dwBytes);            \r
+        }\r
+\r
         CurDrive->PhyDrive = i;\r
         CurDrive->SizeInBytes = LengthInfo.Length.QuadPart;\r
         CurDrive->DeviceType = pDevDesc->DeviceType;\r
         CurDrive->RemovableMedia = pDevDesc->RemovableMedia;\r
         CurDrive->BusType = pDevDesc->BusType;\r
 \r
+        CurDrive->BytesPerLogicalSector = diskAlignment.BytesPerLogicalSector;\r
+        CurDrive->BytesPerPhysicalSector = diskAlignment.BytesPerPhysicalSector;\r
+\r
         if (pDevDesc->VendorIdOffset)\r
         {\r
             safe_strcpy(CurDrive->VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset);\r
@@ -470,9 +532,10 @@ int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)
 \r
     for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++)\r
     {\r
-        Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",\r
+        Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Sector:%u/%u Name:%s %s",\r
             CurDrive->PhyDrive, GetBusTypeString(CurDrive->BusType), CurDrive->RemovableMedia,\r
             GetHumanReadableGBSize(CurDrive->SizeInBytes), CurDrive->SizeInBytes,\r
+            CurDrive->BytesPerLogicalSector, CurDrive->BytesPerPhysicalSector,\r
             CurDrive->VendorId, CurDrive->ProductId);\r
     }\r
 \r
@@ -687,11 +750,13 @@ int VentoyProcSecureBoot(BOOL SecureBoot)
                        fl_fclose(file);\r
 \r
                        Log("Now delete all efi files ...");\r
-                       fl_remove("/EFI/BOOT/BOOTX64.EFI");\r
-                       fl_remove("/EFI/BOOT/grubx64.efi");\r
+            fl_remove("/EFI/BOOT/BOOTX64.EFI");            \r
+            fl_remove("/EFI/BOOT/grubx64.efi");            \r
                        fl_remove("/EFI/BOOT/grubx64_real.efi");\r
                        fl_remove("/EFI/BOOT/MokManager.efi");\r
+                       fl_remove("/EFI/BOOT/mmx64.efi");\r
             fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");\r
+            fl_remove("/EFI/BOOT/grub.efi");\r
 \r
                        file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");\r
                        Log("Open bootx64 efi file %p ", file);\r
@@ -839,7 +904,7 @@ static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId)
        LARGE_INTEGER liNewPosition;\r
     BYTE *CheckBuf = NULL;\r
 \r
-       Log("FormatPart2Fat %llu...", StartSectorId);\r
+       Log("FormatPart2Fat %llu...", (ULONGLONG)StartSectorId);\r
 \r
     CheckBuf = malloc(SIZE_1MB);\r
     if (!CheckBuf)\r
@@ -1067,6 +1132,79 @@ static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle)
 }\r
 \r
 \r
+static int FormatPart1LargeFAT32(UINT64 DiskSizeBytes, int CluserSize)\r
+{\r
+    MKFS_PARM Option;\r
+    FRESULT Ret;\r
+    FATFS FS;\r
+\r
+    Option.fmt = FM_FAT32;\r
+    Option.n_fat = 1;\r
+    Option.align = 8;\r
+    Option.n_root = 1;\r
+\r
+    if (CluserSize == 0)\r
+    {\r
+        // < 32GB select 32KB as cluster size\r
+        // > 32GB select 128KB as cluster size\r
+        if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32)\r
+        {\r
+            Option.au_size = 32768;\r
+        }\r
+        else\r
+        {\r
+            Option.au_size = 131072;\r
+        }\r
+    }\r
+    else\r
+    {\r
+        Option.au_size = CluserSize;\r
+    }\r
+\r
+    Log("Formatting Part1 large FAT32 ClusterSize:%u(%uKB) ...", CluserSize, CluserSize / 1024);\r
+\r
+    disk_io_reset_write_error();\r
+\r
+    Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);\r
+    if (FR_OK == Ret)\r
+    {\r
+        if (disk_io_is_write_error())\r
+        {\r
+            Log("Formatting Part1 large FAT32 failed, write error.");\r
+            return 1;\r
+        }\r
+\r
+        Log("Formatting Part1 large FAT32 success, now set label");\r
+        \r
+        Ret = f_mount(&FS, TEXT("0:"), 1);\r
+        if (FR_OK == Ret)\r
+        {\r
+            Log("f_mount SUCCESS");\r
+            Ret = f_setlabel(TEXT("0:Ventoy"));\r
+            if (FR_OK == Ret)\r
+            {\r
+                Log("f_setlabel SUCCESS");\r
+                Ret = f_unmount(TEXT("0:"));\r
+                Log("f_unmount %d %s", Ret, (FR_OK == Ret) ? "SUCCESS" : "FAILED");\r
+            }\r
+            else\r
+            {\r
+                Log("f_setlabel failed %d", Ret);\r
+            }\r
+        }\r
+        else\r
+        {\r
+            Log("f_mount failed %d", Ret);\r
+        }\r
+\r
+        return 0;\r
+    }\r
+    else\r
+    {\r
+        Log("Formatting Part1 large FAT32 failed");\r
+        return 1;\r
+    }\r
+}\r
 \r
 static int FormatPart1exFAT(UINT64 DiskSizeBytes)\r
 {\r
@@ -1091,9 +1229,17 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes)
 \r
     Log("Formatting Part1 exFAT ...");\r
 \r
+       disk_io_reset_write_error();\r
+\r
     Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);\r
     if (FR_OK == Ret)\r
     {\r
+               if (disk_io_is_write_error())\r
+               {\r
+                       Log("Formatting Part1 exFAT failed, write error.");\r
+                       return 1;\r
+               }\r
+\r
         Log("Formatting Part1 exFAT success");\r
         return 0;\r
     }\r
@@ -1104,7 +1250,45 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes)
     }\r
 }\r
 \r
+static int ZeroPart1FileSystem(HANDLE hDrive, UINT64 Part2StartSector)\r
+{\r
+    int i;\r
+    DWORD dwSize = 0;\r
+    LARGE_INTEGER liCurPos;\r
+    LARGE_INTEGER liNewPos;\r
+    CHAR TmpBuffer[1024] = { 0 };\r
+\r
+    liCurPos.QuadPart = VENTOY_PART1_START_SECTOR * 512;\r
+    liNewPos.QuadPart = 0;\r
+    if (0 == SetFilePointerEx(hDrive, liCurPos, &liNewPos, FILE_BEGIN) ||\r
+        liNewPos.QuadPart != liCurPos.QuadPart)\r
+    {\r
+        Log("SetFilePointerEx Failed %u %llu %llu", LASTERR, (ULONGLONG)liCurPos.QuadPart, (ULONGLONG)liNewPos.QuadPart);\r
+        return 1;\r
+    }\r
+\r
+    for (i = 0; i < 1024; i++)\r
+    {\r
+        WriteFile(hDrive, TmpBuffer, 1024, &dwSize, NULL);\r
+    }\r
+\r
+    liCurPos.QuadPart = (Part2StartSector * 512) - (1024 * 1024);\r
+    liNewPos.QuadPart = 0;\r
+    if (0 == SetFilePointerEx(hDrive, liCurPos, &liNewPos, FILE_BEGIN) ||\r
+        liNewPos.QuadPart != liCurPos.QuadPart)\r
+    {\r
+        Log("SetFilePointerEx Failed %u %llu %llu", LASTERR, (ULONGLONG)liCurPos.QuadPart, (ULONGLONG)liNewPos.QuadPart);\r
+        return 1;\r
+    }\r
+\r
+    for (i = 0; i < 1024; i++)\r
+    {\r
+        WriteFile(hDrive, TmpBuffer, 1024, &dwSize, NULL);\r
+    }\r
 \r
+    Log("Zero Part1 SUCCESS");\r
+    return 0;\r
+}\r
 \r
 int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter)\r
 {\r
@@ -1290,6 +1474,7 @@ int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLett
 End:\r
     \r
     PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);\r
+    PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH);\r
     \r
     if (pTmpBuf)\r
     {\r
@@ -1427,7 +1612,7 @@ int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
         memset(pData, 0, 512);\r
 \r
         pMBR = (MBR_HEAD *)pData;\r
-        VentoyFillMBR(pPhyDrive->SizeInBytes, pMBR, PartStyle);\r
+        VentoyFillMBR(pPhyDrive->SizeInBytes, pMBR, PartStyle, 0x07);\r
         Part1StartSector = pMBR->PartTbl[0].StartSectorId;\r
         Part1SectorCount = pMBR->PartTbl[0].SectorCount;\r
         Part2StartSector = pMBR->PartTbl[1].StartSectorId;\r
@@ -1561,6 +1746,7 @@ int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
 End:\r
 \r
     PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);\r
+    PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH);\r
 \r
     Log("retcode:%d\n", rc);\r
 \r
@@ -1576,6 +1762,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)
     int i;\r
     int rc = 0;\r
     int state = 0;\r
+    BOOL ReformatOK;\r
     HANDLE hDrive;\r
     DWORD dwSize;\r
     BOOL bRet;\r
@@ -1587,10 +1774,15 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)
     UINT64 Part1StartSector = 0;\r
     UINT64 Part1SectorCount = 0;\r
     UINT64 Part2StartSector = 0;\r
+    BOOL LargeFAT32 = FALSE;\r
+    BOOL DefaultExFAT = FALSE;\r
+    UINT8 FsFlag = 0x07;\r
 \r
+       Log("#####################################################");\r
     Log("InstallVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId,\r
         PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,\r
         GetHumanReadableGBSize(pPhyDrive->SizeInBytes));\r
+       Log("#####################################################");\r
 \r
     if (PartStyle)\r
     {\r
@@ -1609,7 +1801,12 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)
     }\r
     else\r
     {\r
-        VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle);\r
+        if (GetVentoyFsType() == VTOY_FS_FAT32)\r
+        {\r
+            FsFlag = 0x0C;\r
+        }\r
+\r
+        VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle, FsFlag);\r
         Part1StartSector = MBR.PartTbl[0].StartSectorId;\r
         Part1SectorCount = MBR.PartTbl[0].SectorCount;\r
         Part2StartSector = MBR.PartTbl[1].StartSectorId;\r
@@ -1657,9 +1854,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)
 \r
     if (!VDS_DeleteAllPartitions(pPhyDrive->PhyDrive))\r
     {\r
-        Log("Notice: Could not delete partitions: 0x%x", GetLastError());\r
-               rc = 1;\r
-               goto End;\r
+        Log("Notice: Could not delete partitions: 0x%x, but we continue.", GetLastError());\r
     }\r
 \r
     Log("Deleting all partitions ......................... OK");\r
@@ -1688,12 +1883,37 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)
         Sleep(1000 * 5);\r
     }\r
 \r
-    Log("Formatting part1 exFAT ...");\r
-    if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))\r
+    if (GetVentoyFsType() == VTOY_FS_FAT32 && (Part1SectorCount * 512 >= FAT32_MAX_LIMIT))\r
     {\r
-        Log("FormatPart1exFAT failed.");\r
-        rc = 1;\r
-        goto End;\r
+        Log("Formatting part1 large FAT32 ...");\r
+        LargeFAT32 = TRUE;\r
+        if (0 != FormatPart1LargeFAT32(pPhyDrive->SizeInBytes, GetClusterSize()))\r
+        {\r
+            Log("FormatPart1LargeFAT32 failed.");\r
+            rc = 1;\r
+            goto End;\r
+        }\r
+    }\r
+    else if (GetVentoyFsType() == VTOY_FS_EXFAT && GetClusterSize() == 0)\r
+    {\r
+        Log("Formatting part1 exFAT ...");\r
+        DefaultExFAT = TRUE;\r
+        if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))\r
+        {\r
+            Log("FormatPart1exFAT failed.");\r
+            rc = 1;\r
+            goto End;\r
+        }\r
+    }\r
+    else\r
+    {\r
+        Log("Zero part1 file system ...");\r
+        if (0 != ZeroPart1FileSystem(hDrive, Part2StartSector))\r
+        {\r
+            Log("ZeroPart1FileSystem failed.");\r
+            rc = 1;\r
+            goto End;\r
+        }\r
     }\r
 \r
     PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);\r
@@ -1792,6 +2012,7 @@ End:
             else\r
             {\r
                 Log("%s is ventoy part1, already mounted", DriveName);\r
+                MountDrive = DriveName[0];\r
                 state = 1;\r
             }\r
         }\r
@@ -1805,36 +2026,592 @@ End:
                 DriveName[0] = MountDrive;\r
                 bRet = SetVolumeMountPointA(DriveName, DriveLetters);\r
                 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());\r
+\r
+                if (bRet)\r
+                {\r
+                    state = 1;\r
+                }\r
             }\r
             else\r
             {\r
                 Log("Failed to find ventoy volume");\r
             }\r
         }\r
+\r
+        // close handle, or it will deny reformat\r
+        Log("Close handle ...");\r
+        CHECK_CLOSE_HANDLE(hDrive);\r
+\r
+        ReformatOK = TRUE;\r
+\r
+        if (state)\r
+        {\r
+            if (LargeFAT32)\r
+            {\r
+                Log("No need to reformat for large FAT32");\r
+                pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);\r
+            }\r
+            else if (DefaultExFAT)\r
+            {\r
+                Log("No need to reformat for default exfat");\r
+                pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);\r
+            }\r
+            else\r
+            {\r
+                bRet = DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512);\r
+                for (i = 0; bRet == FALSE && i < 2; i++)\r
+                {\r
+                    Log("Wait and retry reformat ...");\r
+                    Sleep(1000);\r
+                    bRet = DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512);\r
+                }\r
+\r
+                if (bRet)\r
+                {\r
+                    Log("Reformat %C:\\ to %s SUCCESS", MountDrive, GetVentoyFsName());\r
+                    pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);\r
+\r
+                    if ((GetVentoyFsType() != VTOY_FS_UDF) && (pPhyDrive->VentoyFsClusterSize < 2048))\r
+                    {\r
+                        for (i = 0; i < 10; i++)\r
+                        {\r
+                            Log("### Invalid cluster size %d ###", pPhyDrive->VentoyFsClusterSize);\r
+                        }\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    ReformatOK = FALSE;\r
+                    Log("Reformat %C:\\ to %s FAILED", MountDrive, GetVentoyFsName());\r
+                }\r
+            }\r
+        }\r
+        else\r
+        {\r
+            Log("Can not reformat %s to %s", DriveName, GetVentoyFsName());\r
+        }\r
+\r
+        if (!ReformatOK)\r
+        {\r
+            Log("Format to exfat with built-in algorithm");\r
+\r
+            hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);\r
+            if (hDrive == INVALID_HANDLE_VALUE)\r
+            {\r
+                Log("Failed to GetPhysicalHandle for write.");\r
+            }\r
+            else\r
+            {\r
+                if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))\r
+                {\r
+                    Log("FormatPart1exFAT SUCCESS.");\r
+                }\r
+                else\r
+                {\r
+                    Log("FormatPart1exFAT FAILED.");\r
+                }\r
+\r
+                CHECK_CLOSE_HANDLE(hDrive);\r
+            }\r
+        }\r
+\r
         Log("OK\n");\r
     }\r
     else\r
     {\r
+               PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);\r
+\r
         FindProcessOccupyDisk(hDrive, pPhyDrive);\r
+\r
+               if (!VDS_IsLastAvaliable())\r
+               {\r
+                       Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");\r
+                       Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");\r
+                       Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");\r
+                       Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");\r
+                       Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");\r
+               }\r
+\r
+        CHECK_CLOSE_HANDLE(hDrive);\r
     }\r
 \r
     if (pGptInfo)\r
     {\r
         free(pGptInfo);\r
     }\r
-\r
-    CHECK_CLOSE_HANDLE(hDrive);\r
+    \r
     return rc;\r
 }\r
 \r
 \r
+int PartitionResizeForVentoy(PHY_DRIVE_INFO *pPhyDrive)\r
+{\r
+       int i, j;\r
+       int rc = 1;\r
+       int PhyDrive;\r
+       int PartStyle;\r
+       INT64 ReservedValue;\r
+       UINT64 RecudeBytes;\r
+       GUID Guid;\r
+       MBR_HEAD MBR;\r
+       VTOY_GPT_INFO *pGPT;\r
+       MBR_HEAD *pMBR;\r
+       DWORD dwSize = 0;\r
+       VTOY_GPT_HDR BackupHead;\r
+       HANDLE hDrive = INVALID_HANDLE_VALUE;\r
+       GUID ZeroGuid = { 0 };\r
+       static GUID WindowsDataPartType = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };\r
+       static GUID EspPartType = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };\r
+       static GUID BiosGrubPartType = { 0x21686148, 0x6449, 0x6e6f, { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } };\r
+\r
+       Log("#####################################################");\r
+       Log("PartitionResizeForVentoy PhyDrive%d <<%s %s %dGB>>",\r
+               pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,\r
+               GetHumanReadableGBSize(pPhyDrive->SizeInBytes));\r
+       Log("#####################################################");\r
+\r
+       pGPT = &(pPhyDrive->Gpt);\r
+       pMBR = &(pPhyDrive->Gpt.MBR);\r
+       Log("Disksize:%llu Part2Start:%llu", pPhyDrive->SizeInBytes, pPhyDrive->ResizePart2StartSector * 512);\r
+\r
+       if (pMBR->PartTbl[0].FsFlag == 0xEE && memcmp(pGPT->Head.Signature, "EFI PART", 8) == 0)\r
+       {\r
+               PartStyle = 1;\r
+       }\r
+       else\r
+       {\r
+               PartStyle = 0;\r
+       }\r
+\r
+       PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);\r
+\r
+       RecudeBytes = VENTOY_EFI_PART_SIZE;\r
+       ReservedValue = GetReservedSpaceInMB();\r
+       if (ReservedValue > 0)\r
+       {\r
+               Log("Reduce add reserved space %lldMB", (LONGLONG)ReservedValue);\r
+               RecudeBytes += (UINT64)(ReservedValue * SIZE_1MB);\r
+       }\r
+\r
+\r
+       if (pPhyDrive->ResizeNoShrink == FALSE)\r
+       {\r
+               Log("Need to shrink the volume");\r
+               if (DISK_ShrinkVolume(pPhyDrive->PhyDrive, pPhyDrive->ResizeVolumeGuid, pPhyDrive->Part1DriveLetter, pPhyDrive->ResizeOldPart1Size, RecudeBytes))\r
+               {\r
+                       Log("Shrink volume success, now check again");\r
+\r
+                       hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);\r
+                       if (hDrive == INVALID_HANDLE_VALUE)\r
+                       {\r
+                               Log("Failed to GetPhysicalHandle for update.");\r
+                               goto End;\r
+                       }\r
+\r
+                       //Refresh Drive Layout\r
+                       DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);\r
+\r
+                       CHECK_CLOSE_HANDLE(hDrive);\r
+\r
+\r
+                       if (PartResizePreCheck(NULL) && pPhyDrive->ResizeNoShrink)\r
+                       {\r
+                               Log("Recheck after Shrink volume success");\r
+                               Log("After shrink Disksize:%llu Part2Start:%llu", pPhyDrive->SizeInBytes, pPhyDrive->ResizePart2StartSector * 512);\r
+                       }\r
+                       else\r
+                       {\r
+                               Log("Recheck after Shrink volume failed %u", pPhyDrive->ResizeNoShrink);\r
+                               goto End;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       Log("Shrink volume failed");\r
+                       goto End;\r
+               }\r
+       }\r
+\r
+\r
+       //Now try write data\r
+       hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);\r
+       if (hDrive == INVALID_HANDLE_VALUE)\r
+       {\r
+               Log("Failed to GetPhysicalHandle for update.");\r
+               goto End;\r
+       }\r
+\r
+\r
+       //Write partition 2 data\r
+       PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);\r
+       if (0 != FormatPart2Fat(hDrive, pPhyDrive->ResizePart2StartSector))\r
+       {\r
+               Log("FormatPart2Fat failed.");\r
+               goto End;\r
+       }\r
+\r
+       //Write grub stage2 gap\r
+       PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);\r
+       Log("Writing Boot Image ............................. ");\r
+       if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0)\r
+       {\r
+               Log("WriteGrubStage1ToPhyDrive failed.");\r
+               goto End;\r
+       }\r
+\r
+\r
+       //Write partition table\r
+       PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);\r
+       Log("Writing partition table ............................. ");\r
+\r
+       VentoyGetLocalBootImg(&MBR);\r
+       CoCreateGuid(&Guid);\r
+       memcpy(MBR.BootCode + 0x180, &Guid, 16);\r
+       memcpy(pMBR->BootCode, MBR.BootCode, 440);\r
+\r
+       if (PartStyle == 0)\r
+       {\r
+               for (i = 1; i < 4; i++)\r
+               {\r
+                       if (pMBR->PartTbl[i].SectorCount == 0)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if (i >= 4)\r
+               {\r
+                       Log("Can not find MBR free partition table");\r
+                       goto End;\r
+               }\r
+\r
+               for (j = i - 1; j > 0; j--)\r
+               {\r
+                       Log("Move MBR partition table %d --> %d", j + 1, j + 2);\r
+                       memcpy(pMBR->PartTbl + (j + 1), pMBR->PartTbl + j, sizeof(PART_TABLE));\r
+               }\r
+\r
+        memset(pMBR->PartTbl + 1, 0, sizeof(PART_TABLE));\r
+               VentoyFillMBRLocation(pPhyDrive->SizeInBytes, (UINT32)pPhyDrive->ResizePart2StartSector, VENTOY_EFI_PART_SIZE / 512, pMBR->PartTbl + 1);\r
+               pMBR->PartTbl[0].Active = 0x80; // bootable\r
+               pMBR->PartTbl[1].Active = 0x00;\r
+               pMBR->PartTbl[1].FsFlag = 0xEF; // EFI System Partition\r
+\r
+               if (!WriteDataToPhyDisk(hDrive, 0, pMBR, 512))\r
+               {\r
+                       Log("Legacy BIOS write MBR failed");\r
+                       goto End;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               for (i = 1; i < 128; i++)\r
+               {\r
+                       if (memcmp(&(pGPT->PartTbl[i].PartGuid), &ZeroGuid, sizeof(GUID)) == 0)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if (i >= 128)\r
+               {\r
+                       Log("Can not find GPT free partition table");\r
+                       goto End;\r
+               }\r
+\r
+               for (j = i - 1; j > 0; j--)\r
+               {\r
+                       Log("Move GPT partition table %d --> %d", j + 1, j + 2);\r
+                       memcpy(pGPT->PartTbl + (j + 1), pGPT->PartTbl + j, sizeof(VTOY_GPT_PART_TBL));\r
+               }\r
+\r
+\r
+               pMBR->BootCode[92] = 0x22;\r
+\r
+               // to fix windows issue\r
+        memset(pGPT->PartTbl + 1, 0, sizeof(VTOY_GPT_PART_TBL));\r
+               memcpy(&(pGPT->PartTbl[1].PartType), &WindowsDataPartType, sizeof(GUID));\r
+               CoCreateGuid(&(pGPT->PartTbl[1].PartGuid));\r
+\r
+               pGPT->PartTbl[1].StartLBA = pGPT->PartTbl[0].LastLBA + 1;\r
+               pGPT->PartTbl[1].LastLBA = pGPT->PartTbl[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1;\r
+               pGPT->PartTbl[1].Attr = 0xC000000000000001ULL;\r
+               memcpy(pGPT->PartTbl[1].Name, L"VTOYEFI", 7 * 2);\r
+\r
+               //Update CRC\r
+               pGPT->Head.PartTblCrc = VentoyCrc32(pGPT->PartTbl, sizeof(pGPT->PartTbl));\r
+        pGPT->Head.Crc = 0;\r
+               pGPT->Head.Crc = VentoyCrc32(&(pGPT->Head), pGPT->Head.Length);\r
+\r
+               Log("pGPT->Head.EfiStartLBA=%llu", (ULONGLONG)pGPT->Head.EfiStartLBA);\r
+               Log("pGPT->Head.EfiBackupLBA=%llu", (ULONGLONG)pGPT->Head.EfiBackupLBA);\r
+\r
+               VentoyFillBackupGptHead(pGPT, &BackupHead);\r
+               if (!WriteDataToPhyDisk(hDrive, pGPT->Head.EfiBackupLBA * 512, &BackupHead, 512))\r
+               {\r
+                       Log("UEFI write backup head failed");\r
+                       goto End;\r
+               }\r
+\r
+               if (!WriteDataToPhyDisk(hDrive, (pGPT->Head.EfiBackupLBA - 32) * 512, pGPT->PartTbl, 512 * 32))\r
+               {\r
+                       Log("UEFI write backup partition table failed");\r
+                       goto End;\r
+               }\r
+\r
+               if (!WriteDataToPhyDisk(hDrive, 0, pGPT, 512 * 34))\r
+               {\r
+                       Log("UEFI write MBR & Main partition table failed");\r
+                       goto End;\r
+               }\r
+       }\r
+\r
+\r
+\r
+       //Refresh Drive Layout\r
+       DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);\r
+       \r
+       //We must close handle here, because it will block the refresh bellow\r
+       CHECK_CLOSE_HANDLE(hDrive);\r
+\r
+       Sleep(2000);\r
+\r
+    if (g_CLI_Mode)\r
+    {\r
+        Log("### Ventoy non-destructive CLI installation successfully finished.");\r
+    }\r
+    else\r
+    {\r
+        //Refresh disk list\r
+        PhyDrive = pPhyDrive->PhyDrive;\r
+\r
+        Log("#### Now Refresh PhyDrive ####");\r
+        Ventoy2DiskDestroy();\r
+        Ventoy2DiskInit();\r
+\r
+        pPhyDrive = GetPhyDriveInfoByPhyDrive(PhyDrive);\r
+        if (pPhyDrive)\r
+        {\r
+            if (pPhyDrive->VentoyVersion[0] == 0)\r
+            {\r
+                Log("After process the Ventoy version is still invalid");\r
+                goto End;\r
+            }\r
+\r
+            Log("### Ventoy non-destructive installation successfully finished <%s>", pPhyDrive->VentoyVersion);\r
+        }\r
+        else\r
+        {\r
+            Log("### Ventoy non-destructive installation successfully finished <not found>");\r
+        }\r
+\r
+        InitComboxCtrl(g_DialogHwnd, PhyDrive);\r
+    }\r
+\r
+       rc = 0;\r
+\r
+End:\r
+       CHECK_CLOSE_HANDLE(hDrive);\r
+       return rc;\r
+}\r
+\r
+\r
+static BOOL DiskCheckWriteAccess(HANDLE hDrive)\r
+{\r
+       DWORD dwSize;\r
+       BOOL ret = FALSE;\r
+       BOOL bRet = FALSE;\r
+       BYTE Buffer[512];\r
+       LARGE_INTEGER liCurPosition;\r
+       LARGE_INTEGER liNewPosition;\r
+\r
+       liCurPosition.QuadPart = 2039 * 512;\r
+       liNewPosition.QuadPart = 0;\r
+       if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||\r
+               liNewPosition.QuadPart != liCurPosition.QuadPart)\r
+       {\r
+               Log("SetFilePointer1 Failed %u", LASTERR);\r
+               goto out;\r
+       }\r
+\r
+\r
+       dwSize = 0;\r
+       ret = ReadFile(hDrive, Buffer, 512, &dwSize, NULL);\r
+       if ((!ret) || (dwSize != 512))\r
+       {\r
+               Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR);\r
+               goto out;\r
+       }\r
+\r
+\r
+       liCurPosition.QuadPart = 2039 * 512;\r
+       liNewPosition.QuadPart = 0;\r
+       if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||\r
+               liNewPosition.QuadPart != liCurPosition.QuadPart)\r
+       {\r
+               Log("SetFilePointer2 Failed %u", LASTERR);\r
+               goto out;\r
+       }\r
+\r
+       dwSize = 0;\r
+       ret = WriteFile(hDrive, Buffer, 512, &dwSize, NULL);\r
+       if ((!ret) || dwSize != 512)\r
+       {\r
+               Log("Failed to write %d %u %u", ret, dwSize, LASTERR);\r
+               goto out;\r
+       }\r
+\r
+       bRet = TRUE;\r
+\r
+out:\r
+       \r
+       return bRet;\r
+}\r
+\r
+static BOOL BackupDataBeforeCleanDisk(int PhyDrive, UINT64 DiskSize, BYTE **pBackup)\r
+{\r
+       DWORD dwSize;\r
+       DWORD dwStatus;\r
+       BOOL Return = FALSE;\r
+       BOOL ret = FALSE;\r
+       BYTE *backup = NULL;\r
+       UINT64 offset;\r
+       HANDLE hDrive = INVALID_HANDLE_VALUE;\r
+       LARGE_INTEGER liCurPosition;\r
+       LARGE_INTEGER liNewPosition;\r
+       VTOY_GPT_INFO *pGPT = NULL;\r
+\r
+       Log("BackupDataBeforeCleanDisk %d", PhyDrive);\r
+\r
+       // step1: check write access\r
+       hDrive = GetPhysicalHandle(PhyDrive, TRUE, TRUE, FALSE);\r
+       if (hDrive == INVALID_HANDLE_VALUE)\r
+       {\r
+               Log("Failed to GetPhysicalHandle for write.");\r
+               goto out;\r
+       }\r
+\r
+       if (DiskCheckWriteAccess(hDrive))\r
+       {\r
+               Log("DiskCheckWriteAccess success");\r
+               CHECK_CLOSE_HANDLE(hDrive);\r
+       }\r
+       else\r
+       {\r
+               Log("DiskCheckWriteAccess failed");\r
+               goto out;\r
+       }\r
+\r
+       //step2 backup 4MB data\r
+       backup = malloc(SIZE_1MB * 4);\r
+       if (!backup)\r
+       {\r
+               goto out;\r
+       }\r
+\r
+       hDrive = GetPhysicalHandle(PhyDrive, FALSE, FALSE, FALSE);\r
+       if (hDrive == INVALID_HANDLE_VALUE)\r
+       {\r
+               goto out;\r
+       }\r
+\r
+       //read first 2MB\r
+       dwStatus = SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
+       if (dwStatus != 0)\r
+       {\r
+               goto out;\r
+       }\r
+       \r
+       dwSize = 0;\r
+       ret = ReadFile(hDrive, backup, SIZE_2MB, &dwSize, NULL);\r
+       if ((!ret) || (dwSize != SIZE_2MB))\r
+       {\r
+               Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR);\r
+               goto out;\r
+       }\r
+       \r
+       pGPT = (VTOY_GPT_INFO *)backup;\r
+       offset = pGPT->Head.EfiBackupLBA * 512;\r
+       if (offset >= (DiskSize - SIZE_2MB) && offset < DiskSize)\r
+       {\r
+               Log("EFI partition table check success"); \r
+       }\r
+       else\r
+       {\r
+               Log("Backup EFI LBA not in last 2MB range: %llu", pGPT->Head.EfiBackupLBA);\r
+               goto out;\r
+       }\r
+\r
+       //read last 2MB\r
+       liCurPosition.QuadPart = DiskSize - SIZE_2MB;\r
+       liNewPosition.QuadPart = 0;\r
+       if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||\r
+               liNewPosition.QuadPart != liCurPosition.QuadPart)\r
+       {\r
+               goto out;\r
+       }\r
+\r
+       dwSize = 0;\r
+       ret = ReadFile(hDrive, backup + SIZE_2MB, SIZE_2MB, &dwSize, NULL);\r
+       if ((!ret) || (dwSize != SIZE_2MB))\r
+       {\r
+               Log("Failed to read %d %u 0x%x", ret, dwSize, LASTERR);\r
+               goto out;\r
+       }\r
+\r
+       *pBackup = backup;\r
+       backup = NULL; //For don't free later\r
+       Return = TRUE;\r
+\r
+out:\r
+       CHECK_CLOSE_HANDLE(hDrive);\r
+       if (backup)\r
+               free(backup);\r
+\r
+       return Return;\r
+}\r
+\r
+\r
+static BOOL WriteBackupDataToDisk(HANDLE hDrive, UINT64 Offset, BYTE *Data, DWORD Length)\r
+{\r
+       DWORD dwSize = 0;\r
+       BOOL ret = FALSE;\r
+       LARGE_INTEGER liCurPosition;\r
+       LARGE_INTEGER liNewPosition;\r
+\r
+       Log("WriteBackupDataToDisk %llu %p %u", Offset, Data, Length);\r
+\r
+       liCurPosition.QuadPart = Offset;\r
+       liNewPosition.QuadPart = 0;\r
+       if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||\r
+               liNewPosition.QuadPart != liCurPosition.QuadPart)\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       ret = WriteFile(hDrive, Data, Length, &dwSize, NULL);\r
+       if ((!ret) || dwSize != Length)\r
+       {\r
+               Log("Failed to write %d %u %u", ret, dwSize, LASTERR);\r
+               return FALSE;\r
+       }\r
+\r
+       Log("WriteBackupDataToDisk %llu %p %u success", Offset, Data, Length);\r
+       return TRUE;\r
+}\r
+\r
+\r
 int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)\r
 {\r
        int i;\r
        int rc = 0;\r
-       int MaxRetry = 3;\r
+       int MaxRetry = 4;\r
        BOOL ForceMBR = FALSE;\r
        BOOL Esp2Basic = FALSE;\r
+       BOOL ChangeAttr = FALSE;\r
+       BOOL CleanDisk = FALSE;\r
+       BOOL DelEFI = FALSE;\r
+       BOOL bWriteBack = TRUE;\r
        HANDLE hVolume;\r
        HANDLE hDrive;\r
        DWORD Status;\r
@@ -1842,16 +2619,21 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
        BOOL bRet;\r
        CHAR DriveName[] = "?:\\";\r
        CHAR DriveLetters[MAX_PATH] = { 0 };\r
+       CHAR BackBinFile[MAX_PATH];\r
        UINT64 StartSector;\r
        UINT64 ReservedMB = 0;\r
        MBR_HEAD BootImg;\r
        MBR_HEAD MBR;\r
+       BYTE *pBackup = NULL;\r
        VTOY_GPT_INFO *pGptInfo = NULL;\r
+       VTOY_GPT_INFO *pGptBkup = NULL;\r
        UINT8 ReservedData[4096];\r
 \r
+       Log("#####################################################");\r
        Log("UpdateVentoy2PhyDrive try%d %s PhyDrive%d <<%s %s %dGB>>", TryId,\r
                pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,\r
                GetHumanReadableGBSize(pPhyDrive->SizeInBytes));\r
+       Log("#####################################################");\r
 \r
        PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);\r
 \r
@@ -1866,17 +2648,19 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
 \r
        if (pPhyDrive->PartStyle)\r
        {\r
-               pGptInfo = malloc(sizeof(VTOY_GPT_INFO));\r
+               pGptInfo = malloc(2 * sizeof(VTOY_GPT_INFO));\r
                if (!pGptInfo)\r
                {\r
                        return 1;\r
                }\r
 \r
-               memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));\r
+               memset(pGptInfo, 0, 2 * sizeof(VTOY_GPT_INFO));\r
+               pGptBkup = pGptInfo + 1;\r
 \r
                // Read GPT Info\r
                SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
                ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL);\r
+               memcpy(pGptBkup, pGptInfo, sizeof(VTOY_GPT_INFO));\r
 \r
                //MBR will be used to compare with local boot image\r
                memcpy(&MBR, &pGptInfo->MBR, sizeof(MBR_HEAD));\r
@@ -1935,20 +2719,53 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
        if (pPhyDrive->PartStyle == 1)\r
        {\r
                Log("TryId=%d EFI GPT partition type is 0x%llx", TryId, pPhyDrive->Part2GPTAttr);\r
+               PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);\r
 \r
-               if ((TryId == 1 && (pPhyDrive->Part2GPTAttr >> 56) == 0xC0) || TryId == 2)\r
+               if (TryId == 1)\r
                {\r
-                       PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);\r
                        Log("Change GPT partition type to ESP");\r
-\r
-                       if (VDS_ChangeVtoyEFI2ESP(pPhyDrive->PhyDrive, StartSector * 512))\r
+                       if (DISK_ChangeVtoyEFI2ESP(pPhyDrive->PhyDrive, StartSector * 512ULL))\r
                        {\r
                                Esp2Basic = TRUE;\r
-                               Sleep(1000);\r
+                               Sleep(3000);\r
+                       }\r
+               }\r
+               else if (TryId == 2)\r
+               {\r
+                       Log("Change GPT partition attribute");\r
+                       if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, 0x8000000000000001))\r
+                       {\r
+                               ChangeAttr = TRUE;\r
+                               Sleep(2000);\r
+                       }\r
+               }\r
+               else if (TryId == 3)\r
+               {\r
+                       DISK_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive, StartSector * 512ULL);\r
+                       DelEFI = TRUE;\r
+               }\r
+               else if (TryId == 4)\r
+               {\r
+                       Log("Clean disk GPT partition table");\r
+                       if (BackupDataBeforeCleanDisk(pPhyDrive->PhyDrive, pPhyDrive->SizeInBytes, &pBackup))\r
+                       {\r
+                               sprintf_s(BackBinFile, sizeof(BackBinFile), ".\\ventoy\\phydrive%d_%u_%d.bin",\r
+                                       pPhyDrive->PhyDrive, GetCurrentProcessId(), g_backup_bin_index++);\r
+                               SaveBufToFile(BackBinFile, pBackup, 4 * SIZE_1MB);\r
+                               Log("Save backup data to %s", BackBinFile);\r
+\r
+                               Log("Success to backup data before clean");\r
+                               CleanDisk = TRUE;\r
+                               DISK_CleanDisk(pPhyDrive->PhyDrive);\r
+                               Sleep(3000);\r
+                       }\r
+                       else\r
+                       {\r
+                               Log("Failed to backup data before clean");\r
                        }\r
                }\r
        }\r
-\r
+       \r
     PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);\r
 \r
     Log("Lock disk for update ............................ ");\r
@@ -1966,7 +2783,27 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
     hVolume = INVALID_HANDLE_VALUE;\r
 \r
        //If we change VTOYEFI to ESP, it can not have s volume name, so don't try to get it.\r
-       if (Esp2Basic)\r
+       if (CleanDisk)\r
+       {\r
+               //writeback the last 2MB\r
+               if (!WriteBackupDataToDisk(hDrive, pPhyDrive->SizeInBytes - SIZE_2MB, pBackup + SIZE_2MB, SIZE_2MB))\r
+               {\r
+                       bWriteBack = FALSE;\r
+               }\r
+\r
+               //write the first 2MB except parttable\r
+               if (!WriteBackupDataToDisk(hDrive, 34 * 512, pBackup + 34 * 512, SIZE_2MB - 34 * 512))\r
+               {\r
+                       bWriteBack = FALSE;\r
+               }\r
+\r
+               Status = ERROR_NOT_FOUND;\r
+       }\r
+       else if (DelEFI)\r
+       {\r
+               Status = ERROR_NOT_FOUND;\r
+       }\r
+       else if (Esp2Basic)\r
        {\r
                Status = ERROR_NOT_FOUND;\r
        }\r
@@ -2035,24 +2872,41 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
         goto End;\r
     }\r
 \r
-    if (!TryWritePart2(hDrive, StartSector))\r
+       bRet = TryWritePart2(hDrive, StartSector);\r
+       if (FALSE == bRet && Esp2Basic)\r
+       {\r
+               Log("TryWritePart2 agagin ...");\r
+               Sleep(3000);\r
+               bRet = TryWritePart2(hDrive, StartSector);\r
+       }\r
+\r
+       if (!bRet)\r
     {\r
                if (pPhyDrive->PartStyle == 0)\r
                {\r
-                       ForceMBR = TRUE;\r
+                       if (DiskCheckWriteAccess(hDrive))\r
+                       {\r
+                               Log("MBR DiskCheckWriteAccess success");\r
 \r
-                       Log("Try write failed, now delete partition 2 for MBR...");\r
-                       CHECK_CLOSE_HANDLE(hDrive);\r
+                               ForceMBR = TRUE;\r
 \r
-                       Log("Now delete partition 2...");\r
-                       VDS_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive);\r
+                               Log("Try write failed, now delete partition 2 for MBR...");\r
+                               CHECK_CLOSE_HANDLE(hDrive);\r
 \r
-                       hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);\r
-                       if (hDrive == INVALID_HANDLE_VALUE)\r
+                               Log("Now delete partition 2...");\r
+                               DISK_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive, StartSector * 512ULL);\r
+\r
+                               hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);\r
+                               if (hDrive == INVALID_HANDLE_VALUE)\r
+                               {\r
+                                       Log("Failed to GetPhysicalHandle for write.");\r
+                                       rc = 1;\r
+                                       goto End;\r
+                               }\r
+                       }\r
+                       else\r
                        {\r
-                               Log("Failed to GetPhysicalHandle for write.");\r
-                               rc = 1;\r
-                               goto End;\r
+                               Log("MBR DiskCheckWriteAccess failed");\r
                        }\r
                }\r
                else\r
@@ -2131,17 +2985,78 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
         }\r
     }\r
 \r
+       if (CleanDisk)\r
+       {\r
+               if (!WriteBackupDataToDisk(hDrive, 0, pBackup, 34 * 512))\r
+               {\r
+                       bWriteBack = FALSE;\r
+               }\r
+\r
+               free(pBackup);\r
+\r
+               if (bWriteBack)\r
+               {\r
+                       Log("Write backup data success, now delete %s", BackBinFile);\r
+                       DeleteFileA(BackBinFile);\r
+               }\r
+               else\r
+               {\r
+                       Log("Write backup data failed");\r
+               }\r
+\r
+               Sleep(1000);\r
+       }\r
+       else if (DelEFI)\r
+       {\r
+               VTOY_GPT_HDR BackupHdr;\r
+\r
+               VentoyFillBackupGptHead(pGptBkup, &BackupHdr);\r
+               if (!WriteBackupDataToDisk(hDrive, 512 * pGptBkup->Head.EfiBackupLBA, (BYTE*)(&BackupHdr), 512))\r
+               {\r
+                       bWriteBack = FALSE;\r
+               }\r
+\r
+               if (!WriteBackupDataToDisk(hDrive, 512 * (pGptBkup->Head.EfiBackupLBA - 32), (BYTE*)(pGptBkup->PartTbl), 32 * 512))\r
+               {\r
+                       bWriteBack = FALSE;\r
+               }\r
+\r
+               if (!WriteBackupDataToDisk(hDrive, 512, (BYTE*)pGptBkup + 512, 33 * 512))\r
+               {\r
+                       bWriteBack = FALSE;\r
+               }\r
+\r
+               if (bWriteBack)\r
+               {\r
+                       Log("Write backup partition table success");\r
+               }\r
+               else\r
+               {\r
+                       Log("Write backup partition table failed");\r
+               }\r
+\r
+               Sleep(1000);\r
+       }\r
+\r
     //Refresh Drive Layout\r
     DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);\r
 \r
 End:\r
 \r
+       if (hVolume != INVALID_HANDLE_VALUE)\r
+       {\r
+               bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);\r
+               Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);\r
+               CHECK_CLOSE_HANDLE(hVolume);\r
+       }\r
+\r
     if (rc == 0)\r
     {\r
         Log("OK");\r
     }\r
     else\r
     {\r
+               PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);\r
         FindProcessOccupyDisk(hDrive, pPhyDrive);\r
     }\r
 \r
@@ -2150,9 +3065,26 @@ End:
     if (Esp2Basic)\r
     {\r
                Log("Recover GPT partition type to basic");\r
-               VDS_ChangeVtoyEFI2Basic(pPhyDrive->PhyDrive, StartSector * 512);\r
+               DISK_ChangeVtoyEFI2Basic(pPhyDrive->PhyDrive, StartSector * 512);\r
     }\r
 \r
+       if (pPhyDrive->PartStyle == 1)\r
+       {\r
+               if (ChangeAttr || ((pPhyDrive->Part2GPTAttr >> 56) != 0xC0))\r
+               {\r
+                       Log("Change EFI partition attr %u <0x%llx> to <0x%llx>", ChangeAttr, pPhyDrive->Part2GPTAttr, 0xC000000000000001ULL);\r
+                       if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, 0xC000000000000001ULL))\r
+                       {\r
+                               Log("Change EFI partition attr success");\r
+                               pPhyDrive->Part2GPTAttr = 0xC000000000000001ULL;\r
+                       }\r
+                       else\r
+                       {\r
+                               Log("Change EFI partition attr failed");\r
+                       }\r
+               }\r
+       }\r
+\r
     if (pGptInfo)\r
     {\r
         free(pGptInfo);\r