]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - Ventoy2Disk/Ventoy2Disk/PhyDrive.c
Fix the order issue in TreeView mode. (#3218)
[Ventoy.git] / Ventoy2Disk / Ventoy2Disk / PhyDrive.c
index 535e1a91be73b9d6c19063f7478f7d7699645c0e..c9ac5b1442a98491713030039dc8ef26897c29e6 100644 (file)
-/******************************************************************************
- * PhyDrive.c
- *
- * Copyright (c) 2020, longpanda <admin@ventoy.net>
- * Copyright (c) 2011-2020, Pete Batard <pete@akeo.ie>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- */
-#include <Windows.h>
-#include <winternl.h>
-#include <commctrl.h>
-#include <initguid.h>
-#include <vds.h>
-#include "resource.h"
-#include "Language.h"
-#include "Ventoy2Disk.h"
-#include "fat_filelib.h"
-#include "ff.h"
-
-/* 
- * Some code and functions in the file are copied from rufus.
- * https://github.com/pbatard/rufus
- */
-#define VDS_SET_ERROR SetLastError
-#define IVdsServiceLoader_LoadService(This, pwszMachineName, ppService) (This)->lpVtbl->LoadService(This, pwszMachineName, ppService)
-#define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This)
-#define IVdsService_QueryProviders(This, masks, ppEnum) (This)->lpVtbl->QueryProviders(This, masks, ppEnum)
-#define IVdsService_WaitForServiceReady(This) ((This)->lpVtbl->WaitForServiceReady(This))
-#define IVdsService_CleanupObsoleteMountPoints(This) ((This)->lpVtbl->CleanupObsoleteMountPoints(This))
-#define IVdsService_Refresh(This) ((This)->lpVtbl->Refresh(This))
-#define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This)) 
-#define IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
-#define IVdsProvider_Release(This) (This)->lpVtbl->Release(This)
-#define IVdsSwProvider_QueryPacks(This, ppEnum) (This)->lpVtbl->QueryPacks(This, ppEnum)
-#define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This)
-#define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum)
-#define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties)
-#define IVdsDisk_Release(This) (This)->lpVtbl->Release(This)
-#define IVdsDisk_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
-#define IVdsAdvancedDisk_QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions) (This)->lpVtbl->QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions)
-#define IVdsAdvancedDisk_DeletePartition(This, ullOffset, bForce, bForceProtected) (This)->lpVtbl->DeletePartition(This, ullOffset, bForce, bForceProtected)
-#define IVdsAdvancedDisk_Clean(This, bForce, bForceOEM, bFullClean, ppAsync) (This)->lpVtbl->Clean(This, bForce, bForceOEM, bFullClean, ppAsync)
-#define IVdsAdvancedDisk_Release(This) (This)->lpVtbl->Release(This)
-#define IEnumVdsObject_Next(This, celt, ppObjectArray, pcFetched) (This)->lpVtbl->Next(This, celt, ppObjectArray, pcFetched)
-#define IVdsPack_QueryVolumes(This, ppEnum) (This)->lpVtbl->QueryVolumes(This, ppEnum)
-#define IVdsVolume_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
-#define IVdsVolume_Release(This) (This)->lpVtbl->Release(This)
-#define IVdsVolumeMF3_QueryVolumeGuidPathnames(This, pwszPathArray, pulNumberOfPaths) (This)->lpVtbl->QueryVolumeGuidPathnames(This,pwszPathArray,pulNumberOfPaths)
-#define IVdsVolumeMF3_FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync) (This)->lpVtbl->FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync)
-#define IVdsVolumeMF3_Release(This) (This)->lpVtbl->Release(This)
-#define IVdsVolume_GetProperties(This, pVolumeProperties) (This)->lpVtbl->GetProperties(This,pVolumeProperties)
-#define IVdsAsync_Cancel(This) (This)->lpVtbl->Cancel(This)
-#define IVdsAsync_QueryStatus(This,pHrResult,pulPercentCompleted) (This)->lpVtbl->QueryStatus(This,pHrResult,pulPercentCompleted)
-#define IVdsAsync_Wait(This,pHrResult,pAsyncOut) (This)->lpVtbl->Wait(This,pHrResult,pAsyncOut)
-#define IVdsAsync_Release(This) (This)->lpVtbl->Release(This)
-
-#define IUnknown_QueryInterface(This, a, b) (This)->lpVtbl->QueryInterface(This,a,b)
-#define IUnknown_Release(This) (This)->lpVtbl->Release(This)
-
-/*
-* Delete all the partitions from a disk, using VDS
-* Mostly copied from https://social.msdn.microsoft.com/Forums/vstudio/en-US/b90482ae-4e44-4b08-8731-81915030b32a/createpartition-using-vds-interface-throw-error-enointerface-dcom?forum=vcgeneral
-*/
-BOOL DeletePartitions(DWORD DriveIndex, BOOL OnlyPart2)
-{
-    BOOL r = FALSE;
-    HRESULT hr;
-    ULONG ulFetched;
-    wchar_t wPhysicalName[48];
-    IVdsServiceLoader *pLoader;
-    IVdsService *pService;
-    IEnumVdsObject *pEnum;
-    IUnknown *pUnk;
-
-    swprintf_s(wPhysicalName, ARRAYSIZE(wPhysicalName), L"\\\\?\\PhysicalDrive%lu", DriveIndex);
-
-    // Initialize COM
-    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
-    CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT,
-        RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);
-
-    // Create a VDS Loader Instance
-    hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
-        &IID_IVdsServiceLoader, (void **)&pLoader);
-    if (hr != S_OK) {
-        VDS_SET_ERROR(hr);
-        Log("Could not create VDS Loader Instance: %u", LASTERR);
-        goto out;
-    }
-
-    // Load the VDS Service
-    hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService);
-    IVdsServiceLoader_Release(pLoader);
-    if (hr != S_OK) {
-        VDS_SET_ERROR(hr);
-        Log("Could not load VDS Service: %u", LASTERR);
-        goto out;
-    }
-
-    // Wait for the Service to become ready if needed
-    hr = IVdsService_WaitForServiceReady(pService);
-    if (hr != S_OK) {
-        VDS_SET_ERROR(hr);
-        Log("VDS Service is not ready: %u", LASTERR);
-        goto out;
-    }
-
-    // Query the VDS Service Providers
-    hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
-    if (hr != S_OK) {
-        VDS_SET_ERROR(hr);
-        Log("Could not query VDS Service Providers: %u", LASTERR);
-        goto out;
-    }
-
-    while (IEnumVdsObject_Next(pEnum, 1, &pUnk, &ulFetched) == S_OK) {
-        IVdsProvider *pProvider;
-        IVdsSwProvider *pSwProvider;
-        IEnumVdsObject *pEnumPack;
-        IUnknown *pPackUnk;
-
-        // Get VDS Provider
-        hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider);
-        IUnknown_Release(pUnk);
-        if (hr != S_OK) {
-            VDS_SET_ERROR(hr);
-            Log("Could not get VDS Provider: %u", LASTERR);
-            goto out;
-        }
-
-        // Get VDS Software Provider
-        hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider);
-        IVdsProvider_Release(pProvider);
-        if (hr != S_OK) {
-            VDS_SET_ERROR(hr);
-            Log("Could not get VDS Software Provider: %u", LASTERR);
-            goto out;
-        }
-
-        // Get VDS Software Provider Packs
-        hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack);
-        IVdsSwProvider_Release(pSwProvider);
-        if (hr != S_OK) {
-            VDS_SET_ERROR(hr);
-            Log("Could not get VDS Software Provider Packs: %u", LASTERR);
-            goto out;
-        }
-
-        // Enumerate Provider Packs
-        while (IEnumVdsObject_Next(pEnumPack, 1, &pPackUnk, &ulFetched) == S_OK) {
-            IVdsPack *pPack;
-            IEnumVdsObject *pEnumDisk;
-            IUnknown *pDiskUnk;
-
-            hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack);
-            IUnknown_Release(pPackUnk);
-            if (hr != S_OK) {
-                VDS_SET_ERROR(hr);
-                Log("Could not query VDS Software Provider Pack: %u", LASTERR);
-                goto out;
-            }
-
-            // Use the pack interface to access the disks
-            hr = IVdsPack_QueryDisks(pPack, &pEnumDisk);
-            if (hr != S_OK) {
-                VDS_SET_ERROR(hr);
-                Log("Could not query VDS disks: %u", LASTERR);
-                goto out;
-            }
-
-            // List disks
-            while (IEnumVdsObject_Next(pEnumDisk, 1, &pDiskUnk, &ulFetched) == S_OK) {
-                VDS_DISK_PROP diskprop;
-                VDS_PARTITION_PROP* prop_array;
-                LONG i, prop_array_size;
-                IVdsDisk *pDisk;
-                IVdsAdvancedDisk *pAdvancedDisk;
-
-                // Get the disk interface.
-                hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk);
-                if (hr != S_OK) {
-                    VDS_SET_ERROR(hr);
-                    Log("Could not query VDS Disk Interface: %u", LASTERR);
-                    goto out;
-                }
-
-                // Get the disk properties
-                hr = IVdsDisk_GetProperties(pDisk, &diskprop);
-                if (hr != S_OK) {
-                    VDS_SET_ERROR(hr);
-                    Log("Could not query VDS Disk Properties: %u", LASTERR);
-                    goto out;
-                }
-
-                // Isolate the disk we want
-                if (_wcsicmp(wPhysicalName, diskprop.pwszName) != 0) {
-                    IVdsDisk_Release(pDisk);
-                    continue;
-                }
-
-                // Instantiate the AdvanceDisk interface for our disk.
-                hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk);
-                IVdsDisk_Release(pDisk);
-                if (hr != S_OK) {
-                    VDS_SET_ERROR(hr);
-                    Log("Could not access VDS Advanced Disk interface: %u", LASTERR);
-                    goto out;
-                }
-
-                // Query the partition data, so we can get the start offset, which we need for deletion
-                hr = IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk, &prop_array, &prop_array_size);
-                if (hr == S_OK) {
-                    Log("Deleting ALL partition(s) from disk '%S':", diskprop.pwszName);
-                    // Now go through each partition
-                    for (i = 0; i < prop_array_size; i++) {
-                        
-                        Log("* Partition %d (offset: %lld, size: %llu)", prop_array[i].ulPartitionNumber,
-                            prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize);
-
-                        if (OnlyPart2 && prop_array[i].ullOffset == 2048*512)
-                        {
-                            Log("Skip this partition...");
-                            continue;
-                        }
-
-
-                        hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE);
-                        if (hr != S_OK) {
-                            r = FALSE;
-                            VDS_SET_ERROR(hr);
-                            Log("Could not delete partitions: %u", LASTERR);
-                        }
-                    }
-                    r = TRUE;
-                }
-                else {
-                    Log("No partition to delete on disk '%S'", diskprop.pwszName);
-                    r = TRUE;
-                }
-                CoTaskMemFree(prop_array);
-
-#if 0
-                // Issue a Clean while we're at it
-                HRESULT hr2 = E_FAIL;
-                ULONG completed;
-                IVdsAsync* pAsync;
-                hr = IVdsAdvancedDisk_Clean(pAdvancedDisk, TRUE, FALSE, FALSE, &pAsync);
-                while (SUCCEEDED(hr)) {
-                    if (IS_ERROR(FormatStatus)) {
-                        IVdsAsync_Cancel(pAsync);
-                        break;
-                    }
-                    hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed);
-                    if (SUCCEEDED(hr)) {
-                        hr = hr2;
-                        if (hr == S_OK)
-                            break;
-                        if (hr == VDS_E_OPERATION_PENDING)
-                            hr = S_OK;
-                    }
-                    Sleep(500);
-                }
-                if (hr != S_OK) {
-                    VDS_SET_ERROR(hr);
-                    Log("Could not clean disk: %s", LASTERR);
-                }
-#endif
-                IVdsAdvancedDisk_Release(pAdvancedDisk);
-                goto out;
-            }
-        }
-    }
-
-out:
-    return r;
-}
-
-
-static DWORD GetVentoyVolumeName(int PhyDrive, UINT32 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash)
-{
-    size_t len;
-    BOOL bRet;
-    DWORD dwSize;
-    HANDLE hDrive;
-    HANDLE hVolume;
-    UINT64 PartOffset;
-    DWORD Status = ERROR_NOT_FOUND;
-    DISK_EXTENT *pExtents = NULL;
-    CHAR VolumeName[MAX_PATH] = { 0 };
-    VOLUME_DISK_EXTENTS DiskExtents;
-
-    PartOffset = 512ULL * StartSectorId;
-
-    Log("GetVentoyVolumeName PhyDrive %d PartOffset:%llu", PhyDrive, (ULONGLONG)PartOffset);
-
-    hVolume = FindFirstVolumeA(VolumeName, sizeof(VolumeName));
-    if (hVolume == INVALID_HANDLE_VALUE)
-    {
-        return 1;
-    }
-
-    do {
-
-        len = strlen(VolumeName);
-        Log("Find volume:%s", VolumeName);
-
-        VolumeName[len - 1] = 0;
-
-        hDrive = CreateFileA(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-        if (hDrive == INVALID_HANDLE_VALUE)
-        {
-            continue;
-        }
-
-        bRet = DeviceIoControl(hDrive,
-            IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
-            NULL,
-            0,
-            &DiskExtents,
-            (DWORD)(sizeof(DiskExtents)),
-            (LPDWORD)&dwSize,
-            NULL);
-
-        Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet, LASTERR);
-        Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents.NumberOfDiskExtents, DiskExtents.Extents[0].DiskNumber);
-
-        if (bRet && DiskExtents.NumberOfDiskExtents == 1)
-        {
-            pExtents = DiskExtents.Extents;
-
-            Log("This volume DiskNumber:%u offset:%llu", pExtents->DiskNumber, (ULONGLONG)pExtents->StartingOffset.QuadPart);
-            if ((int)pExtents->DiskNumber == PhyDrive && pExtents->StartingOffset.QuadPart == PartOffset)
-            {
-                Log("This volume match");
-
-                if (!DelSlash)
-                {
-                    VolumeName[len - 1] = '\\';
-                }
-
-                sprintf_s(NameBuf, BufLen, "%s", VolumeName);
-                Status = ERROR_SUCCESS;
-                CloseHandle(hDrive);
-                break;
-            }
-        }
-
-        CloseHandle(hDrive);
-    } while (FindNextVolumeA(hVolume, VolumeName, sizeof(VolumeName)));
-
-    FindVolumeClose(hVolume);
-
-    Log("GetVentoyVolumeName return %u", Status);
-    return Status;
-}
-
-static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length)
-{
-    int n = 0;
-    DWORD DataSize = 0;
-    CHAR *Pos = NULL;
-    CHAR *StringBuf = NULL;
-
-    DataSize = GetLogicalDriveStringsA(0, NULL);
-    StringBuf = (CHAR *)malloc(DataSize + 1);
-    if (StringBuf == NULL)
-    {
-        return 1;
-    }
-
-    GetLogicalDriveStringsA(DataSize, StringBuf);
-
-    for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1)
-    {
-        if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0]))
-        {
-            Log("%C: is belong to phydrive%d", Pos[0], PhyDrive);
-            DriveLetters[n++] = Pos[0];
-        }
-    }
-
-    free(StringBuf);
-    return 0;
-}
-
-static HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare)
-{
-    int i;
-    DWORD dwSize;
-    DWORD LastError;
-    UINT64 EndTime;
-    HANDLE hDrive = INVALID_HANDLE_VALUE;
-    CHAR PhyDrive[128];
-    CHAR DevPath[MAX_PATH] = { 0 };
-
-    safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", Drive);
-
-    if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath)))
-    {
-        Log("QueryDosDeviceA failed error:%u", GetLastError());
-        strcpy_s(DevPath, sizeof(DevPath), "???");
-    }
-    else
-    {
-        Log("QueryDosDeviceA success %s", DevPath);
-    }
-
-    for (i = 0; i < DRIVE_ACCESS_RETRIES; i++)
-    {
-        // Try without FILE_SHARE_WRITE (unless specifically requested) so that
-        // we won't be bothered by the OS or other apps when we set up our data.
-        // However this means we might have to wait for an access gap...
-        // We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is
-        // required for enumeration.
-        hDrive = CreateFileA(PhyDrive,
-            GENERIC_READ | (bWriteAccess ? GENERIC_WRITE : 0),
-            FILE_SHARE_READ | (bWriteShare ? FILE_SHARE_WRITE : 0),
-            NULL,
-            OPEN_EXISTING,
-            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
-            NULL);
-
-        LastError = GetLastError();
-        Log("[%d] CreateFileA %s code:%u %p", i, PhyDrive, LastError, hDrive);
-
-        if (hDrive != INVALID_HANDLE_VALUE)
-        {
-            break;
-        }
-
-        if ((LastError != ERROR_SHARING_VIOLATION) && (LastError != ERROR_ACCESS_DENIED))
-        {
-            break;
-        }
-
-        if (i == 0)
-        {
-            Log("Waiting for access on %s [%s]...", PhyDrive, DevPath);
-        }
-        else if (!bWriteShare && (i > DRIVE_ACCESS_RETRIES / 3))
-        {
-            // If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE...
-            Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");
-            bWriteShare = TRUE;
-
-            // Try to report the process that is locking the drive
-            // We also use bit 6 as a flag to indicate that SearchProcess was called.
-            //access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40;
-
-        }
-        Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
-    }
-
-    if (hDrive == INVALID_HANDLE_VALUE)
-    {
-        Log("Could not open %s %u", PhyDrive, LASTERR);
-        goto End;
-    }
-
-    if (bWriteAccess)
-    {
-        Log("Opened %s for %s write access", PhyDrive, bWriteShare ? "shared" : "exclusive");
-    }
-
-    if (bLockDrive)
-    {
-        if (DeviceIoControl(hDrive, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwSize, NULL))
-        {
-            Log("I/O boundary checks disabled");
-        }
-
-        EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT;
-
-        do {
-            if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL))
-            {
-                Log("FSCTL_LOCK_VOLUME success");
-                goto End;
-            }
-            Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
-        } while (GetTickCount64() < EndTime);
-
-        // If we reached this section, either we didn't manage to get a lock or the user cancelled
-        Log("Could not lock access to %s %u", PhyDrive, LASTERR);
-
-        // See if we can report the processes are accessing the drive
-        //if (!IS_ERROR(FormatStatus) && (access_mask == 0))
-        //    access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE);
-        // Try to continue if the only access rights we saw were for read-only
-        //if ((access_mask & 0x07) != 0x01)
-        //    safe_closehandle(hDrive);
-
-        CHECK_CLOSE_HANDLE(hDrive);
-    }
-
-End:
-
-    if (hDrive == INVALID_HANDLE_VALUE)
-    {
-        Log("Can get handle of %s, maybe some process control it.", DevPath);
-    }
-
-    return hDrive;
-}
-
-int GetPhyDriveByLogicalDrive(int DriveLetter)
-{
-    BOOL Ret;
-    DWORD dwSize;
-    HANDLE Handle;
-    VOLUME_DISK_EXTENTS DiskExtents;
-    CHAR PhyPath[128];
-
-    safe_sprintf(PhyPath, "\\\\.\\%C:", (CHAR)DriveLetter);
-
-    Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
-    if (Handle == INVALID_HANDLE_VALUE)
-    {
-        Log("Could not open the disk<%s>, error:%u", PhyPath, LASTERR);
-        return -1;
-    }
-
-    Ret = DeviceIoControl(Handle,
-        IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
-        NULL,
-        0,
-        &DiskExtents,
-        (DWORD)(sizeof(DiskExtents)),
-        (LPDWORD)&dwSize,
-        NULL);
-
-    if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
-    {
-        Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, LASTERR);
-        CHECK_CLOSE_HANDLE(Handle);
-        return -1;
-    }
-    CHECK_CLOSE_HANDLE(Handle);
-
-    Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
-        PhyPath,
-        DiskExtents.Extents[0].DiskNumber,
-        DiskExtents.Extents[0].StartingOffset.QuadPart,
-        DiskExtents.Extents[0].ExtentLength.QuadPart
-        );
-
-    return (int)DiskExtents.Extents[0].DiskNumber;
-}
-
-int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)
-{
-    int i;
-    int Count;
-    int id;
-    int Letter = 'A';
-    BOOL  bRet;
-    DWORD dwBytes;
-    DWORD DriveCount = 0;
-    HANDLE Handle = INVALID_HANDLE_VALUE;
-    CHAR PhyDrive[128];
-    PHY_DRIVE_INFO *CurDrive = pDriveList;
-    GET_LENGTH_INFORMATION LengthInfo;
-    STORAGE_PROPERTY_QUERY Query;
-    STORAGE_DESCRIPTOR_HEADER DevDescHeader;
-    STORAGE_DEVICE_DESCRIPTOR *pDevDesc;
-    int PhyDriveId[VENTOY_MAX_PHY_DRIVE];
-
-    Count = GetPhysicalDriveCount();
-
-    for (i = 0; i < Count && i < VENTOY_MAX_PHY_DRIVE; i++)
-    {
-        PhyDriveId[i] = i;
-    }
-
-    dwBytes = GetLogicalDrives();
-    Log("Logical Drives: 0x%x", dwBytes);
-    while (dwBytes)
-    {
-        if (dwBytes & 0x01)
-        {
-            id = GetPhyDriveByLogicalDrive(Letter);
-            Log("%C --> %d", Letter, id);
-            if (id >= 0)
-            {
-                for (i = 0; i < Count; i++)
-                {
-                    if (PhyDriveId[i] == id)
-                    {
-                        break;
-                    }
-                }
-
-                if (i >= Count)
-                {
-                    Log("Add phy%d to list", i);
-                    PhyDriveId[Count] = id;
-                    Count++;
-                }
-            }
-        }
-
-        Letter++;
-        dwBytes >>= 1;
-    }
-
-    for (i = 0; i < Count && DriveCount < VENTOY_MAX_PHY_DRIVE; i++)
-    {
-        CHECK_CLOSE_HANDLE(Handle);
-
-        safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", PhyDriveId[i]);
-        Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);        
-        Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR);
-
-        if (Handle == INVALID_HANDLE_VALUE)
-        {
-            continue;
-        }
-
-        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);
-            continue;
-        }
-
-        Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart);
-
-        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);
-            continue;
-        }
-
-        if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))
-        {
-            Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size);
-            continue;
-        }
-
-        pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size);
-        if (!pDevDesc)
-        {
-            Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size);
-            continue;
-        }
-
-        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);
-            continue;
-        }
-
-        CurDrive->PhyDrive = i;
-        CurDrive->SizeInBytes = LengthInfo.Length.QuadPart;
-        CurDrive->DeviceType = pDevDesc->DeviceType;
-        CurDrive->RemovableMedia = pDevDesc->RemovableMedia;
-        CurDrive->BusType = pDevDesc->BusType;
-
-        if (pDevDesc->VendorIdOffset)
-        {
-            safe_strcpy(CurDrive->VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset);
-            TrimString(CurDrive->VendorId);
-        }
-
-        if (pDevDesc->ProductIdOffset)
-        {
-            safe_strcpy(CurDrive->ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset);
-            TrimString(CurDrive->ProductId);
-        }
-
-        if (pDevDesc->ProductRevisionOffset)
-        {
-            safe_strcpy(CurDrive->ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset);
-            TrimString(CurDrive->ProductRev);
-        }
-
-        if (pDevDesc->SerialNumberOffset)
-        {
-            safe_strcpy(CurDrive->SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset);
-            TrimString(CurDrive->SerialNumber);
-        }
-
-        CurDrive++;
-        DriveCount++;
-
-        free(pDevDesc);
-
-        CHECK_CLOSE_HANDLE(Handle);
-    }
-
-    for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++)
-    {
-        Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
-            CurDrive->PhyDrive, GetBusTypeString(CurDrive->BusType), CurDrive->RemovableMedia,
-            GetHumanReadableGBSize(CurDrive->SizeInBytes), CurDrive->SizeInBytes,
-            CurDrive->VendorId, CurDrive->ProductId);
-    }
-
-    *pDriveCount = DriveCount;
-
-    return 0;
-}
-
-
-static HANDLE g_FatPhyDrive;
-static UINT64 g_Part2StartSec;
-static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen)
-{
-    int rc = 1;
-    int size = 0;
-    char *buf = NULL;
-    void *flfile = NULL;
-
-    flfile = fl_fopen("/grub/grub.cfg", "rb");
-    if (flfile)
-    {
-        fl_fseek(flfile, 0, SEEK_END);
-        size = (int)fl_ftell(flfile);
-
-        fl_fseek(flfile, 0, SEEK_SET);
-
-        buf = (char *)malloc(size + 1);
-        if (buf)
-        {
-            fl_fread(buf, 1, size, flfile);
-            buf[size] = 0;
-
-            rc = 0;
-            sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf));
-            free(buf);
-        }
-
-        fl_fclose(flfile);
-    }
-
-    return rc;
-}
-
-static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
-{
-    DWORD dwSize;
-    BOOL bRet;
-    DWORD ReadSize;
-    LARGE_INTEGER liCurrentPosition;
-
-    liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
-    liCurrentPosition.QuadPart *= 512;
-    SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
-
-    ReadSize = (DWORD)(SectorCount * 512);
-
-    bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
-    if (bRet == FALSE || dwSize != ReadSize)
-    {
-        Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, LASTERR);
-    }
-
-    return 1;
-}
-
-
-int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, CHAR *VerBuf, size_t BufLen)
-{
-    int rc = 0;
-    HANDLE hDrive;
-
-    hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE);
-    if (hDrive == INVALID_HANDLE_VALUE)
-    {
-        return 1;
-    }
-    
-    g_FatPhyDrive = hDrive;
-    g_Part2StartSec = (pDriveInfo->SizeInBytes - VENTOY_EFI_PART_SIZE) / 512;
-
-    Log("Parse FAT fs...");
-
-    fl_init();
-
-    if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
-    {
-        rc = GetVentoyVersionFromFatFile(VerBuf, BufLen);
-    }
-    else
-    {
-        rc = 1;
-    }
-
-    fl_shutdown();
-
-    CHECK_CLOSE_HANDLE(hDrive);
-
-    return rc;
-}
-
-
-
-
-
-static unsigned int g_disk_unxz_len = 0;
-static BYTE *g_part_img_pos = NULL;
-static BYTE *g_part_img_buf[VENTOY_EFI_PART_SIZE / SIZE_1MB];
-
-
-static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
-{
-       uint32 i;
-       uint32 offset;
-       BYTE *MbBuf = NULL;
-
-       for (i = 0; i < SectorCount; i++)
-       {
-               offset = (Sector + i) * 512;
-
-               if (g_part_img_buf[1] == NULL)
-               {
-                       MbBuf = g_part_img_buf[0] + offset;
-                       memcpy(Buffer + i * 512, MbBuf, 512);
-               }
-               else
-               {
-                       MbBuf = g_part_img_buf[offset / SIZE_1MB];
-                       memcpy(Buffer + i * 512, MbBuf + (offset % SIZE_1MB), 512);
-               }
-       }
-
-       return 1;
-}
-
-
-static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
-{
-       uint32 i;
-       uint32 offset;
-       BYTE *MbBuf = NULL;
-
-       for (i = 0; i < SectorCount; i++)
-       {
-               offset = (Sector + i) * 512;
-
-               if (g_part_img_buf[1] == NULL)
-               {
-                       MbBuf = g_part_img_buf[0] + offset;
-                       memcpy(MbBuf, Buffer + i * 512, 512);
-               }
-               else
-               {
-                       MbBuf = g_part_img_buf[offset / SIZE_1MB];
-                       memcpy(MbBuf + (offset % SIZE_1MB), Buffer + i * 512, 512);
-               }
-       }
-
-       return 1;
-}
-
-int VentoyProcSecureBoot(BOOL SecureBoot)
-{
-       int rc = 0;
-       int size;
-       char *filebuf = NULL;
-       void *file = NULL;
-
-       Log("VentoyProcSecureBoot %d ...", SecureBoot);
-       
-       if (SecureBoot)
-       {
-               Log("Secure boot is enabled ...");
-               return 0;
-       }
-
-       fl_init();
-
-       if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite))
-       {
-               file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
-               Log("Open ventoy efi file %p ", file);
-               if (file)
-               {
-                       fl_fseek(file, 0, SEEK_END);
-                       size = (int)fl_ftell(file);
-                       fl_fseek(file, 0, SEEK_SET);
-
-                       Log("ventoy efi file size %d ...", size);
-
-                       filebuf = (char *)malloc(size);
-                       if (filebuf)
-                       {
-                               fl_fread(filebuf, 1, size, file);
-                       }
-
-                       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/grubx64_real.efi");
-                       fl_remove("/EFI/BOOT/MokManager.efi");
-
-                       file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
-                       Log("Open bootx64 efi file %p ", file);
-                       if (file)
-                       {
-                               if (filebuf)
-                               {
-                                       fl_fwrite(filebuf, 1, size, file);
-                               }
-                               
-                               fl_fflush(file);
-                               fl_fclose(file);
-                       }
-
-                       if (filebuf)
-                       {
-                               free(filebuf);
-                       }
-               }
-       }
-       else
-       {
-               rc = 1;
-       }
-
-       fl_shutdown();
-
-       return rc;
-}
-
-
-
-static int disk_xz_flush(void *src, unsigned int size)
-{
-    unsigned int i;
-    BYTE *buf = (BYTE *)src;
-
-    for (i = 0; i < size; i++)
-    {
-        *g_part_img_pos = *buf++;
-
-        g_disk_unxz_len++;
-        if ((g_disk_unxz_len % SIZE_1MB) == 0)
-        {
-            g_part_img_pos = g_part_img_buf[g_disk_unxz_len / SIZE_1MB];
-        }
-        else
-        {
-            g_part_img_pos++;
-        }
-    }
-
-    return (int)size;
-}
-
-static void unxz_error(char *x)
-{
-    Log("%s", x);
-}
-
-static BOOL TryWritePart2(HANDLE hDrive, UINT64 StartSectorId)
-{
-    BOOL bRet;
-    DWORD TrySize = 16 * 1024;
-    DWORD dwSize;
-    BYTE *Buffer = NULL;
-    unsigned char *data = NULL;
-    LARGE_INTEGER liCurrentPosition;
-
-    liCurrentPosition.QuadPart = StartSectorId * 512;
-    SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
-    
-    Buffer = malloc(TrySize);
-
-    bRet = WriteFile(hDrive, Buffer, TrySize, &dwSize, NULL);
-
-    free(Buffer);
-
-    Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
-
-    if (bRet && dwSize == TrySize)
-    {
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId)
-{
-    int i;
-    int rc = 0;
-    int len = 0;
-    int writelen = 0;
-    int partwrite = 0;
-    DWORD dwSize = 0;
-    BOOL bRet;
-    unsigned char *data = NULL;
-    LARGE_INTEGER liCurrentPosition;
-
-    Log("FormatPart2Fat ...");
-
-    rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&data, &len);
-    if (rc)
-    {
-        Log("Failed to read img file %p %u", data, len);
-        return 1;
-    }
-
-    liCurrentPosition.QuadPart = StartSectorId * 512;
-    SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
-
-    memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
-
-    g_part_img_buf[0] = (BYTE *)malloc(VENTOY_EFI_PART_SIZE);
-    if (g_part_img_buf[0])
-    {
-        Log("Malloc whole img buffer success, now decompress ...");
-        unxz(data, len, NULL, NULL, g_part_img_buf[0], &writelen, unxz_error);
-
-        if (len == writelen)
-        {
-            Log("decompress finished success");
-
-                       VentoyProcSecureBoot(g_SecureBoot);
-
-            for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
-            {
-                dwSize = 0;
-                bRet = WriteFile(hDrive, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB, &dwSize, NULL);
-                Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
-
-                if (!bRet)
-                {
-                    rc = 1;
-                    goto End;
-                }
-
-                PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i);                
-            }
-        }
-        else
-        {
-            rc = 1;
-            Log("decompress finished failed");
-            goto End;
-        }
-    }
-    else
-    {
-        Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE);
-
-        partwrite = 1;
-        for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
-        {
-            g_part_img_buf[i] = (BYTE *)malloc(SIZE_1MB);
-            if (g_part_img_buf[i] == NULL)
-            {
-                rc = 1;
-                goto End;
-            }
-        }
-
-        Log("Malloc part img buffer success, now decompress ...");
-
-        g_part_img_pos = g_part_img_buf[0];
-
-        unxz(data, len, NULL, disk_xz_flush, NULL, NULL, unxz_error);
-
-        if (g_disk_unxz_len == VENTOY_EFI_PART_SIZE)
-        {
-            Log("decompress finished success");
-                       
-                       VentoyProcSecureBoot(g_SecureBoot);
-
-            for (int i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
-            {
-                dwSize = 0;
-                bRet = WriteFile(hDrive, g_part_img_buf[i], SIZE_1MB, &dwSize, NULL);
-                Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
-
-                if (!bRet)
-                {
-                    rc = 1;
-                    goto End;
-                }
-
-                PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i);
-            }
-        }
-        else
-        {
-            rc = 1;
-            Log("decompress finished failed");
-            goto End;
-        }
-    }
-
-End:
-
-    if (data) free(data);
-
-    if (partwrite)
-    {
-        for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
-        {
-            if (g_part_img_buf[i]) free(g_part_img_buf[i]);
-        }
-    }
-    else
-    {
-        if (g_part_img_buf[0]) free(g_part_img_buf[0]);
-    }
-
-    return rc;
-}
-
-static int WriteGrubStage1ToPhyDrive(HANDLE hDrive)
-{
-    int Len = 0;
-    int readLen = 0;
-    BOOL bRet;
-    DWORD dwSize;
-    BYTE *ImgBuf = NULL;
-    BYTE *RawBuf = NULL;
-
-    Log("WriteGrubStage1ToPhyDrive ...");
-
-    RawBuf = (BYTE *)malloc(SIZE_1MB);
-    if (!RawBuf)
-    {
-        return 1;
-    }
-
-    if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
-    {
-        Log("Failed to read stage1 img");
-        free(RawBuf);
-        return 1;
-    }
-
-    unxz(ImgBuf, Len, NULL, NULL, RawBuf, &readLen, unxz_error);
-
-    SetFilePointer(hDrive, 512, NULL, FILE_BEGIN);
-
-    bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512, &dwSize, NULL);
-    Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet, dwSize, GetLastError());
-
-    free(RawBuf);
-    free(ImgBuf);
-    return 0;
-}
-
-
-
-static int FormatPart1exFAT(UINT64 DiskSizeBytes)
-{
-    MKFS_PARM Option;
-    FRESULT Ret;
-    FATFS fs;
-
-    Option.fmt = FM_EXFAT;
-    Option.n_fat = 1;
-    Option.align = 8;
-    Option.n_root = 1;
-
-    // < 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;
-    }
-
-    Log("Formatting Part1 exFAT ...");
-
-    Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
-
-    if (FR_OK == Ret)
-    {
-        Log("Formatting Part1 exFAT success");
-
-        Ret = f_mount(&fs, TEXT("0:"), 1);
-        Log("mount part %d", Ret);
-
-        if (FR_OK == Ret)
-        {
-            Ret = f_setlabel(TEXT("Ventoy"));
-            Log("f_setlabel %d", Ret);
-
-            Ret = f_mount(0, TEXT("0:"), 1);
-            Log("umount part %d", Ret);
-        }
-
-        return 0;
-    }
-    else
-    {
-        Log("Formatting Part1 exFAT failed");
-        return 1;
-    }
-}
-
-
-int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
-{
-    int i;
-    int rc = 0;
-    int state = 0;
-    HANDLE hDrive;
-    DWORD dwSize;
-    BOOL bRet;
-    CHAR MountDrive;
-    CHAR DriveName[] = "?:\\";
-    CHAR DriveLetters[MAX_PATH] = { 0 };
-    MBR_HEAD MBR;
-
-    Log("InstallVentoy2PhyDrive PhyDrive%d <<%s %s %dGB>>",
-        pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
-        GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
-
-    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
-
-    VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR);
-
-    Log("Lock disk for clean ............................. ");
-
-    hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
-    if (hDrive == INVALID_HANDLE_VALUE)
-    {
-        Log("Failed to open physical disk");
-        return 1;
-    }
-
-    GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
-
-    if (DriveLetters[0] == 0)
-    {
-        Log("No drive letter was assigned...");
-        DriveName[0] = GetFirstUnusedDriveLetter();
-        Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
-    }
-    else
-    {
-        // Unmount all mounted volumes that belong to this drive
-        // Do it in reverse so that we always end on the first volume letter
-        for (i = (int)strlen(DriveLetters); i > 0; i--)
-        {
-            DriveName[0] = DriveLetters[i - 1];
-            bRet = DeleteVolumeMountPointA(DriveName);
-            Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
-        }
-    }
-
-    MountDrive = DriveName[0];
-    Log("Will use '%C:' as volume mountpoint", DriveName[0]);
-
-    // It kind of blows, but we have to relinquish access to the physical drive
-    // for VDS to be able to delete the partitions that reside on it...
-    DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
-    CHECK_CLOSE_HANDLE(hDrive);
-
-    PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
-
-    if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE))
-    {
-        Log("Notice: Could not delete partitions: %u", GetLastError());
-    }
-
-    Log("Deleting all partitions ......................... OK");
-
-    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
-
-    Log("Lock disk for write ............................. ");
-    hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
-    if (hDrive == INVALID_HANDLE_VALUE)
-    {
-        Log("Failed to GetPhysicalHandle for write.");
-        rc = 1;
-        goto End;
-    }
-
-    //Refresh Drive Layout
-    DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
-
-    disk_io_set_param(hDrive, MBR.PartTbl[0].StartSectorId + MBR.PartTbl[0].SectorCount);
-
-    PROGRESS_BAR_SET_POS(PT_FORMAT_PART1);
-
-    Log("Formatting part1 exFAT ...");
-    if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
-    {
-        rc = 1;
-        goto End;
-    }
-
-    PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
-    Log("Writing part2 FAT img ...");
-    if (0 != FormatPart2Fat(hDrive, MBR.PartTbl[1].StartSectorId))
-    {
-        rc = 1;
-        goto End;
-    }
-
-    PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);
-    Log("Writting Boot Image ............................. ");
-    if (WriteGrubStage1ToPhyDrive(hDrive) != 0)
-    {
-        rc = 1;
-        goto End;
-    }
-
-
-    PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);
-    Log("Writting Partition Table ........................ ");
-    SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
-    if (!WriteFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL))
-    {
-        rc = 1;
-        Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize, GetLastError());
-        goto End;
-    }
-
-    Log("Write MBR OK ...");
-
-    //Refresh Drive Layout
-    DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
-
-End:
-    CHECK_CLOSE_HANDLE(hDrive);
-
-    PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
-    Log("Mounting Ventoy Partition ....................... ");
-    Sleep(1000);
-
-    state = 0;
-    memset(DriveLetters, 0, sizeof(DriveLetters));
-    GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
-    Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
-
-    for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
-    {
-        DriveName[0] = DriveLetters[i];
-        if (IsVentoyLogicalDrive(DriveName[0]))
-        {
-            Log("%s is ventoy part2, delete mountpoint", DriveName);
-            DeleteVolumeMountPointA(DriveName);
-        }
-        else
-        {
-            Log("%s is ventoy part1, already mounted", DriveName);
-            state = 1;
-        }
-    }
-
-    if (state != 1)
-    {
-        Log("need to mount ventoy part1...");
-        if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE))
-        {
-            DriveName[0] = MountDrive;
-            bRet = SetVolumeMountPointA(DriveName, DriveLetters);
-            Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
-        }
-        else
-        {
-            Log("Failed to find ventoy volume");
-        }
-    }
-
-    Log("OK\n");
-
-    return rc;
-}
-
-int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
-{
-    int i;
-    int rc = 0;
-    BOOL ForceMBR = FALSE;
-    HANDLE hVolume;
-    HANDLE hDrive;
-    DWORD Status;
-    DWORD dwSize;
-    BOOL bRet;
-    CHAR DriveName[] = "?:\\";
-    CHAR DriveLetters[MAX_PATH] = { 0 };
-    UINT32 StartSector;
-    MBR_HEAD BootImg;
-    MBR_HEAD MBR;
-
-    StartSector = (UINT32)(pPhyDrive->SizeInBytes / 512 - VENTOY_EFI_PART_SIZE / 512);
-
-    Log("UpdateVentoy2PhyDrive PhyDrive%d <<%s %s %dGB>>",
-        pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId, 
-        GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
-
-    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
-
-    Log("Lock disk for umount ............................ ");
-
-    hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
-    if (hDrive == INVALID_HANDLE_VALUE)
-    {
-        Log("Failed to open physical disk");
-        return 1;
-    }
-
-    // Read MBR
-    ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
-
-    GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
-
-    if (DriveLetters[0] == 0)
-    {
-        Log("No drive letter was assigned...");
-    }
-    else
-    {
-        // Unmount all mounted volumes that belong to this drive
-        // Do it in reverse so that we always end on the first volume letter
-        for (i = (int)strlen(DriveLetters); i > 0; i--)
-        {
-            DriveName[0] = DriveLetters[i - 1];
-            if (IsVentoyLogicalDrive(DriveName[0]))
-            {
-                Log("%s is ventoy logical drive", DriveName);
-                bRet = DeleteVolumeMountPointA(DriveName);
-                Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, LASTERR);
-                break;
-            }
-        }
-    }
-
-    // It kind of blows, but we have to relinquish access to the physical drive
-    // for VDS to be able to delete the partitions that reside on it...
-    DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
-    CHECK_CLOSE_HANDLE(hDrive);
-
-    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
-
-    Log("Lock disk for update ............................ ");
-    hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
-    if (hDrive == INVALID_HANDLE_VALUE)
-    {
-        Log("Failed to GetPhysicalHandle for write.");
-        rc = 1;
-        goto End;
-    }
-
-    PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME);
-
-    Log("Lock volume for update .......................... ");
-    hVolume = INVALID_HANDLE_VALUE;
-    Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[1].StartSectorId, DriveLetters, sizeof(DriveLetters), TRUE);
-    if (ERROR_SUCCESS == Status)
-    {
-        Log("Now lock and dismount volume <%s>", DriveLetters);
-        hVolume = CreateFileA(DriveLetters,
-            GENERIC_READ | GENERIC_WRITE,
-            FILE_SHARE_READ,
-            NULL,
-            OPEN_EXISTING,
-            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
-            NULL);
-
-        if (hVolume == INVALID_HANDLE_VALUE)
-        {
-            Log("Failed to create file volume, errcode:%u", LASTERR);
-            rc = 1;
-            goto End;
-        }
-
-        bRet = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
-        Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
-
-        bRet = DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
-        Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet, LASTERR);
-    }
-    else if (ERROR_NOT_FOUND == Status)
-    {
-        Log("Volume not found, maybe not supported");
-    }
-    else
-    {
-        rc = 1;
-        goto End;
-    }
-
-
-    if (!TryWritePart2(hDrive, StartSector))
-    {
-        ForceMBR = TRUE;
-        Log("Try write failed, now delete partition 2...");
-
-        CHECK_CLOSE_HANDLE(hDrive);
-
-        Log("Now delete partition 2...");
-        DeletePartitions(pPhyDrive->PhyDrive, TRUE);
-
-        hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
-        if (hDrive == INVALID_HANDLE_VALUE)
-        {
-            Log("Failed to GetPhysicalHandle for write.");
-            rc = 1;
-            goto End;
-        }
-    }
-
-
-    PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
-
-    Log("Write Ventoy to disk ............................ ");
-    if (0 != FormatPart2Fat(hDrive, StartSector))
-    {
-        rc = 1;
-        goto 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);
-    }
-
-    Log("Updating Boot Image ............................. ");
-    if (WriteGrubStage1ToPhyDrive(hDrive) != 0)
-    {
-        rc = 1;
-        goto End;
-    }
-
-    // Boot Image
-    VentoyGetLocalBootImg(&BootImg);
-
-    // Use Old UUID
-    memcpy(BootImg.BootCode + 0x180, MBR.BootCode + 0x180, 16);
-
-    if (ForceMBR == FALSE && memcmp(BootImg.BootCode, MBR.BootCode, 440) == 0)
-    {
-        Log("Boot image has no difference, no need to write.");
-    }
-    else
-    {
-        Log("Boot image need to write %u.", ForceMBR);
-
-        SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
-
-        memcpy(MBR.BootCode, BootImg.BootCode, 440);
-        bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
-        Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
-    }
-
-    //Refresh Drive Layout
-    DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
-
-End:
-    CHECK_CLOSE_HANDLE(hDrive);
-
-    return rc;
-}
-
+/******************************************************************************\r
+ * PhyDrive.c\r
+ *\r
+ * Copyright (c) 2020, longpanda <admin@ventoy.net>\r
+ * Copyright (c) 2011-2020, Pete Batard <pete@akeo.ie>\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License as\r
+ * published by the Free Software Foundation; either version 3 of the\r
+ * License, or (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful, but\r
+ * WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ * General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+ *\r
+ */\r
\r
+#include <Windows.h>\r
+#include <time.h>\r
+#include <winternl.h>\r
+#include <commctrl.h>\r
+#include <initguid.h>\r
+#include "resource.h"\r
+#include "Language.h"\r
+#include "Ventoy2Disk.h"\r
+#include "fat_filelib.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
+    BOOL bRet;\r
+    DWORD dwSize;\r
+    HANDLE hDrive;\r
+    HANDLE hVolume;\r
+    UINT64 PartOffset;\r
+    DWORD Status = ERROR_NOT_FOUND;\r
+    DISK_EXTENT *pExtents = NULL;\r
+    CHAR VolumeName[MAX_PATH] = { 0 };\r
+    VOLUME_DISK_EXTENTS DiskExtents;\r
+\r
+    PartOffset = 512ULL * StartSectorId;\r
+\r
+       Log("GetVentoyVolumeName PhyDrive %d SectorStart:%llu PartOffset:%llu", PhyDrive, (ULONGLONG)StartSectorId, (ULONGLONG)PartOffset);\r
+\r
+    hVolume = FindFirstVolumeA(VolumeName, sizeof(VolumeName));\r
+    if (hVolume == INVALID_HANDLE_VALUE)\r
+    {\r
+        return 1;\r
+    }\r
+\r
+    do {\r
+\r
+        len = strlen(VolumeName);\r
+        Log("Find volume:%s", VolumeName);\r
+\r
+        VolumeName[len - 1] = 0;\r
+\r
+        hDrive = CreateFileA(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\r
+        if (hDrive == INVALID_HANDLE_VALUE)\r
+        {\r
+            continue;\r
+        }\r
+\r
+        bRet = DeviceIoControl(hDrive,\r
+            IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,\r
+            NULL,\r
+            0,\r
+            &DiskExtents,\r
+            (DWORD)(sizeof(DiskExtents)),\r
+            (LPDWORD)&dwSize,\r
+            NULL);\r
+\r
+        Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet, LASTERR);\r
+        Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents.NumberOfDiskExtents, DiskExtents.Extents[0].DiskNumber);\r
+\r
+        if (bRet && DiskExtents.NumberOfDiskExtents == 1)\r
+        {\r
+            pExtents = DiskExtents.Extents;\r
+\r
+            Log("This volume DiskNumber:%u offset:%llu", pExtents->DiskNumber, (ULONGLONG)pExtents->StartingOffset.QuadPart);\r
+            if ((int)pExtents->DiskNumber == PhyDrive && pExtents->StartingOffset.QuadPart == PartOffset)\r
+            {\r
+                Log("This volume match");\r
+\r
+                if (!DelSlash)\r
+                {\r
+                    VolumeName[len - 1] = '\\';\r
+                }\r
+\r
+                sprintf_s(NameBuf, BufLen, "%s", VolumeName);\r
+                Status = ERROR_SUCCESS;\r
+                CloseHandle(hDrive);\r
+                break;\r
+            }\r
+        }\r
+\r
+        CloseHandle(hDrive);\r
+    } while (FindNextVolumeA(hVolume, VolumeName, sizeof(VolumeName)));\r
+\r
+    FindVolumeClose(hVolume);\r
+\r
+    Log("GetVentoyVolumeName return %u", Status);\r
+    return Status;\r
+}\r
+\r
+int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length)\r
+{\r
+    int n = 0;\r
+    DWORD DataSize = 0;\r
+    CHAR *Pos = NULL;\r
+    CHAR *StringBuf = NULL;\r
+\r
+    DataSize = GetLogicalDriveStringsA(0, NULL);\r
+    StringBuf = (CHAR *)malloc(DataSize + 1);\r
+    if (StringBuf == NULL)\r
+    {\r
+        return 1;\r
+    }\r
+\r
+    GetLogicalDriveStringsA(DataSize, StringBuf);\r
+\r
+    for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1)\r
+    {\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
+        }\r
+    }\r
+\r
+    free(StringBuf);\r
+    return 0;\r
+}\r
+\r
+HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare)\r
+{\r
+    int i;\r
+    DWORD dwSize;\r
+    DWORD LastError;\r
+    UINT64 EndTime;\r
+    HANDLE hDrive = INVALID_HANDLE_VALUE;\r
+    CHAR PhyDrive[128];\r
+    CHAR DevPath[MAX_PATH] = { 0 };\r
+\r
+    safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", Drive);\r
+\r
+    if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath)))\r
+    {\r
+        Log("QueryDosDeviceA failed error:%u", GetLastError());\r
+        strcpy_s(DevPath, sizeof(DevPath), "???");\r
+    }\r
+    else\r
+    {\r
+        Log("QueryDosDeviceA success %s", DevPath);\r
+    }\r
+\r
+    for (i = 0; i < DRIVE_ACCESS_RETRIES; i++)\r
+    {\r
+        // Try without FILE_SHARE_WRITE (unless specifically requested) so that\r
+        // we won't be bothered by the OS or other apps when we set up our data.\r
+        // However this means we might have to wait for an access gap...\r
+        // We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is\r
+        // required for enumeration.\r
+        hDrive = CreateFileA(PhyDrive,\r
+            GENERIC_READ | (bWriteAccess ? GENERIC_WRITE : 0),\r
+            FILE_SHARE_READ | (bWriteShare ? FILE_SHARE_WRITE : 0),\r
+            NULL,\r
+            OPEN_EXISTING,\r
+            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,\r
+            NULL);\r
+\r
+        LastError = GetLastError();\r
+        Log("[%d] CreateFileA %s code:%u %p", i, PhyDrive, LastError, hDrive);\r
+\r
+        if (hDrive != INVALID_HANDLE_VALUE)\r
+        {\r
+            break;\r
+        }\r
+\r
+        if ((LastError != ERROR_SHARING_VIOLATION) && (LastError != ERROR_ACCESS_DENIED))\r
+        {\r
+            break;\r
+        }\r
+\r
+        if (i == 0)\r
+        {\r
+            Log("Waiting for access on %s [%s]...", PhyDrive, DevPath);\r
+        }\r
+        else if (!bWriteShare && (i > DRIVE_ACCESS_RETRIES / 3))\r
+        {\r
+            // If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE...\r
+            Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");\r
+            bWriteShare = TRUE;\r
+\r
+            // Try to report the process that is locking the drive\r
+            // We also use bit 6 as a flag to indicate that SearchProcess was called.\r
+            //access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40;\r
+\r
+        }\r
+        Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);\r
+    }\r
+\r
+    if (hDrive == INVALID_HANDLE_VALUE)\r
+    {\r
+        Log("Could not open %s %u", PhyDrive, LASTERR);\r
+        goto End;\r
+    }\r
+\r
+    if (bWriteAccess)\r
+    {\r
+        Log("Opened %s for %s write access", PhyDrive, bWriteShare ? "shared" : "exclusive");\r
+    }\r
+\r
+    if (bLockDrive)\r
+    {\r
+        if (DeviceIoControl(hDrive, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwSize, NULL))\r
+        {\r
+            Log("I/O boundary checks disabled");\r
+        }\r
+\r
+        EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT;\r
+\r
+        do {\r
+            if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL))\r
+            {\r
+                Log("FSCTL_LOCK_VOLUME success");\r
+                goto End;\r
+            }\r
+            Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);\r
+        } while (GetTickCount64() < EndTime);\r
+\r
+        // If we reached this section, either we didn't manage to get a lock or the user cancelled\r
+        Log("Could not lock access to %s %u", PhyDrive, LASTERR);\r
+\r
+        // See if we can report the processes are accessing the drive\r
+        //if (!IS_ERROR(FormatStatus) && (access_mask == 0))\r
+        //    access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE);\r
+        // Try to continue if the only access rights we saw were for read-only\r
+        //if ((access_mask & 0x07) != 0x01)\r
+        //    safe_closehandle(hDrive);\r
+\r
+        CHECK_CLOSE_HANDLE(hDrive);\r
+    }\r
+\r
+End:\r
+\r
+    if (hDrive == INVALID_HANDLE_VALUE)\r
+    {\r
+        Log("Can get handle of %s, maybe some process control it.", DevPath);\r
+    }\r
+\r
+    return hDrive;\r
+}\r
+\r
+int GetPhyDriveByLogicalDrive(int DriveLetter, UINT64 *Offset)\r
+{\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
+    safe_sprintf(PhyPath, "\\\\.\\%C:", (CHAR)DriveLetter);\r
+\r
+    Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+    if (Handle == INVALID_HANDLE_VALUE)\r
+    {\r
+        Log("Could not open the disk<%s>, error:%u", PhyPath, LASTERR);\r
+        return -1;\r
+    }\r
+\r
+    memset(&DiskExtents, 0, sizeof(DiskExtents));\r
+    Ret = DeviceIoControl(Handle,\r
+        IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,\r
+        NULL,\r
+        0,\r
+        &DiskExtents,\r
+        (DWORD)(sizeof(DiskExtents)),\r
+        (LPDWORD)&dwSize,\r
+        NULL);\r
+\r
+    if (!Ret || DiskExtents.NumberOfDiskExtents == 0)\r
+    {\r
+        Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, LASTERR);\r
+        CHECK_CLOSE_HANDLE(Handle);\r
+        return -1;\r
+    }\r
+    CHECK_CLOSE_HANDLE(Handle);\r
+\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
+int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)\r
+{\r
+    int i;\r
+    int Count;\r
+    int id;\r
+    int Letter = 'A';\r
+    BOOL  bRet;\r
+    DWORD dwBytes;\r
+    DWORD DriveCount = 0;\r
+    HANDLE Handle = INVALID_HANDLE_VALUE;\r
+    CHAR PhyDrive[128];\r
+    PHY_DRIVE_INFO *CurDrive = pDriveList;\r
+    GET_LENGTH_INFORMATION LengthInfo;\r
+    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
+\r
+    for (i = 0; i < Count && i < VENTOY_MAX_PHY_DRIVE; i++)\r
+    {\r
+        PhyDriveId[i] = i;\r
+    }\r
+\r
+    dwBytes = GetLogicalDrives();\r
+    Log("Logical Drives: 0x%x", dwBytes);\r
+    while (dwBytes)\r
+    {\r
+        if (dwBytes & 0x01)\r
+        {\r
+                       id = GetPhyDriveByLogicalDrive(Letter, NULL);\r
+            Log("%C --> %d", Letter, id);\r
+            if (id >= 0)\r
+            {\r
+                for (i = 0; i < Count; i++)\r
+                {\r
+                    if (PhyDriveId[i] == id)\r
+                    {\r
+                        break;\r
+                    }\r
+                }\r
+\r
+                if (i >= Count)\r
+                {\r
+                    Log("Add phy%d to list", i);\r
+                    PhyDriveId[Count] = id;\r
+                    Count++;\r
+                }\r
+            }\r
+        }\r
+\r
+        Letter++;\r
+        dwBytes >>= 1;\r
+    }\r
+\r
+    for (i = 0; i < Count && DriveCount < VENTOY_MAX_PHY_DRIVE; i++)\r
+    {\r
+        CHECK_CLOSE_HANDLE(Handle);\r
+\r
+        safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", PhyDriveId[i]);\r
+        Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);        \r
+        Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR);\r
+\r
+        if (Handle == INVALID_HANDLE_VALUE)\r
+        {\r
+            continue;\r
+        }\r
+\r
+        bRet = DeviceIoControl(Handle,\r
+                               IOCTL_DISK_GET_LENGTH_INFO, NULL,\r
+                               0,\r
+                               &LengthInfo,\r
+                               sizeof(LengthInfo),\r
+                               &dwBytes,\r
+                               NULL);\r
+        if (!bRet)\r
+        {\r
+            Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR);\r
+            continue;\r
+        }\r
+\r
+        Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart);\r
+\r
+        Query.PropertyId = StorageDeviceProperty;\r
+        Query.QueryType = PropertyStandardQuery;\r
+\r
+        bRet = DeviceIoControl(Handle,\r
+                               IOCTL_STORAGE_QUERY_PROPERTY,\r
+                               &Query,\r
+                               sizeof(Query),\r
+                               &DevDescHeader,\r
+                               sizeof(STORAGE_DESCRIPTOR_HEADER),\r
+                               &dwBytes,\r
+                               NULL);\r
+        if (!bRet)\r
+        {\r
+            Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes);\r
+            continue;\r
+        }\r
+\r
+        if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))\r
+        {\r
+            Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size);\r
+            continue;\r
+        }\r
+\r
+        pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size);\r
+        if (!pDevDesc)\r
+        {\r
+            Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size);\r
+            continue;\r
+        }\r
+\r
+        bRet = DeviceIoControl(Handle,\r
+                               IOCTL_STORAGE_QUERY_PROPERTY,\r
+                               &Query,\r
+                               sizeof(Query),\r
+                               pDevDesc,\r
+                               DevDescHeader.Size,\r
+                               &dwBytes,\r
+                               NULL);\r
+        if (!bRet)\r
+        {\r
+            Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes);\r
+            free(pDevDesc);\r
+            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
+            TrimString(CurDrive->VendorId);\r
+        }\r
+\r
+        if (pDevDesc->ProductIdOffset)\r
+        {\r
+            safe_strcpy(CurDrive->ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset);\r
+            TrimString(CurDrive->ProductId);\r
+        }\r
+\r
+        if (pDevDesc->ProductRevisionOffset)\r
+        {\r
+            safe_strcpy(CurDrive->ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset);\r
+            TrimString(CurDrive->ProductRev);\r
+        }\r
+\r
+        if (pDevDesc->SerialNumberOffset)\r
+        {\r
+            safe_strcpy(CurDrive->SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset);\r
+            TrimString(CurDrive->SerialNumber);\r
+        }\r
+\r
+        CurDrive++;\r
+        DriveCount++;\r
+\r
+        free(pDevDesc);\r
+\r
+        CHECK_CLOSE_HANDLE(Handle);\r
+    }\r
+\r
+    for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++)\r
+    {\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
+    *pDriveCount = DriveCount;\r
+\r
+    return 0;\r
+}\r
+\r
+BOOL VentoyPhydriveMatch(PHY_DRIVE_INFO* pPhyDrive)\r
+{\r
+    BOOL  bRet = FALSE;\r
+    DWORD dwBytes;\r
+    HANDLE Handle = INVALID_HANDLE_VALUE;\r
+    CHAR PhyDrive[128];\r
+    GET_LENGTH_INFORMATION LengthInfo;\r
+    STORAGE_PROPERTY_QUERY Query;\r
+    STORAGE_DESCRIPTOR_HEADER DevDescHeader;\r
+    STORAGE_DEVICE_DESCRIPTOR* pDevDesc = NULL;\r
+    STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment;\r
+    CHAR VendorId[128] = { 0 };\r
+    CHAR ProductId[128] = { 0 };\r
+    CHAR ProductRev[128] = { 0 };\r
+    CHAR SerialNumber[128] = { 0 };\r
+\r
+\r
+    safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", pPhyDrive->PhyDrive);\r
+    Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);\r
+    if (Handle == INVALID_HANDLE_VALUE)\r
+    {\r
+        Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR);\r
+        return FALSE;\r
+    }\r
+\r
+    bRet = DeviceIoControl(Handle,\r
+        IOCTL_DISK_GET_LENGTH_INFO, NULL,\r
+        0,\r
+        &LengthInfo,\r
+        sizeof(LengthInfo),\r
+        &dwBytes,\r
+        NULL);\r
+    if (!bRet)\r
+    {\r
+        Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR);\r
+        return FALSE;\r
+    }\r
+\r
+    if (pPhyDrive->SizeInBytes != (ULONGLONG)LengthInfo.Length.QuadPart)\r
+    {\r
+        Log("PHYSICALDRIVE%d size not match %llu %llu", pPhyDrive->PhyDrive, (ULONGLONG)LengthInfo.Length.QuadPart,\r
+            (ULONGLONG)pPhyDrive->SizeInBytes);\r
+        CHECK_CLOSE_HANDLE(Handle);\r
+        return FALSE;\r
+    }\r
+\r
+    Query.PropertyId = StorageDeviceProperty;\r
+    Query.QueryType = PropertyStandardQuery;\r
+\r
+    bRet = DeviceIoControl(Handle,\r
+        IOCTL_STORAGE_QUERY_PROPERTY,\r
+        &Query,\r
+        sizeof(Query),\r
+        &DevDescHeader,\r
+        sizeof(STORAGE_DESCRIPTOR_HEADER),\r
+        &dwBytes,\r
+        NULL);\r
+    if (!bRet)\r
+    {\r
+        Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes);\r
+        CHECK_CLOSE_HANDLE(Handle);\r
+        return FALSE;\r
+    }\r
+\r
+    if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))\r
+    {\r
+        Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size);\r
+        CHECK_CLOSE_HANDLE(Handle);\r
+        return FALSE;\r
+    }\r
+\r
+    pDevDesc = (STORAGE_DEVICE_DESCRIPTOR*)malloc(DevDescHeader.Size);\r
+    if (!pDevDesc)\r
+    {\r
+        Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size);\r
+        CHECK_CLOSE_HANDLE(Handle);\r
+        return FALSE;\r
+    }\r
+\r
+    bRet = DeviceIoControl(Handle,\r
+        IOCTL_STORAGE_QUERY_PROPERTY,\r
+        &Query,\r
+        sizeof(Query),\r
+        pDevDesc,\r
+        DevDescHeader.Size,\r
+        &dwBytes,\r
+        NULL);\r
+    if (!bRet)\r
+    {\r
+        Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes);\r
+        free(pDevDesc);\r
+        goto out;\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
+    if (pPhyDrive->DeviceType != pDevDesc->DeviceType ||\r
+        pPhyDrive->RemovableMedia != pDevDesc->RemovableMedia ||\r
+        pPhyDrive->BusType != pDevDesc->BusType ||\r
+        pPhyDrive->BytesPerLogicalSector != diskAlignment.BytesPerLogicalSector ||\r
+        pPhyDrive->BytesPerPhysicalSector != diskAlignment.BytesPerPhysicalSector\r
+        )\r
+    {\r
+        Log("Some properties not match DeviceType[%u %u] Removable[%u %u] BusType[%u %u] LogSec[%u %u] PhySec[%u %u]", \r
+            pPhyDrive->DeviceType, pDevDesc->DeviceType,\r
+            pPhyDrive->RemovableMedia, pDevDesc->RemovableMedia,\r
+            pPhyDrive->BusType, pDevDesc->BusType,\r
+            pPhyDrive->BytesPerLogicalSector, diskAlignment.BytesPerLogicalSector,\r
+            pPhyDrive->BytesPerPhysicalSector, diskAlignment.BytesPerPhysicalSector\r
+            );\r
+        goto out;\r
+    }\r
+\r
+    if (pDevDesc->VendorIdOffset)\r
+    {\r
+        safe_strcpy(VendorId, (char*)pDevDesc + pDevDesc->VendorIdOffset);\r
+        TrimString(VendorId);\r
+\r
+        if (strcmp(pPhyDrive->VendorId, VendorId))\r
+        {\r
+            Log("VendorId not match <%s %s>", pPhyDrive->VendorId, VendorId);\r
+            goto out;\r
+        }\r
+    }\r
+\r
+    if (pDevDesc->ProductIdOffset)\r
+    {\r
+        safe_strcpy(ProductId, (char*)pDevDesc + pDevDesc->ProductIdOffset);\r
+        TrimString(ProductId);\r
+\r
+        if (strcmp(pPhyDrive->ProductId, ProductId))\r
+        {\r
+            Log("ProductId not match <%s %s>", pPhyDrive->ProductId, ProductId);\r
+            goto out;\r
+        }\r
+    }\r
+\r
+    if (pDevDesc->ProductRevisionOffset)\r
+    {\r
+        safe_strcpy(ProductRev, (char*)pDevDesc + pDevDesc->ProductRevisionOffset);\r
+        TrimString(ProductRev);\r
+\r
+        if (strcmp(pPhyDrive->ProductRev, ProductRev))\r
+        {\r
+            Log("ProductRev not match <%s %s>", pPhyDrive->ProductRev, ProductRev);\r
+            goto out;\r
+        }\r
+    }\r
+\r
+    if (pDevDesc->SerialNumberOffset)\r
+    {\r
+        safe_strcpy(SerialNumber, (char*)pDevDesc + pDevDesc->SerialNumberOffset);\r
+        TrimString(SerialNumber);\r
+\r
+        if (strcmp(pPhyDrive->SerialNumber, SerialNumber))\r
+        {\r
+            Log("ProductRev not match <%s %s>", pPhyDrive->SerialNumber, SerialNumber);\r
+            goto out;\r
+        }\r
+    }\r
+\r
+    Log("PhyDrive%d ALL match, now continue", pPhyDrive->PhyDrive);\r
+\r
+    bRet = TRUE;\r
+\r
+out:\r
+    if (pDevDesc)\r
+    {\r
+        free(pDevDesc);\r
+    }\r
+\r
+    CHECK_CLOSE_HANDLE(Handle);\r
+\r
+    return bRet;\r
+}\r
+\r
+static HANDLE g_FatPhyDrive;\r
+static UINT64 g_Part2StartSec;\r
+static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen)\r
+{\r
+    int rc = 1;\r
+    int size = 0;\r
+    char *buf = NULL;\r
+    void *flfile = NULL;\r
+\r
+    flfile = fl_fopen("/grub/grub.cfg", "rb");\r
+    if (flfile)\r
+    {\r
+        fl_fseek(flfile, 0, SEEK_END);\r
+        size = (int)fl_ftell(flfile);\r
+\r
+        fl_fseek(flfile, 0, SEEK_SET);\r
+\r
+        buf = (char *)malloc(size + 1);\r
+        if (buf)\r
+        {\r
+            fl_fread(buf, 1, size, flfile);\r
+            buf[size] = 0;\r
+\r
+            rc = 0;\r
+            sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf));\r
+            free(buf);\r
+        }\r
+\r
+        fl_fclose(flfile);\r
+    }\r
+\r
+    return rc;\r
+}\r
+\r
+static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)\r
+{\r
+    DWORD dwSize;\r
+    BOOL bRet;\r
+    DWORD ReadSize;\r
+    LARGE_INTEGER liCurrentPosition;\r
+\r
+    liCurrentPosition.QuadPart = Sector + g_Part2StartSec;\r
+    liCurrentPosition.QuadPart *= 512;\r
+    SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);\r
+\r
+    ReadSize = (DWORD)(SectorCount * 512);\r
+\r
+    bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);\r
+    if (bRet == FALSE || dwSize != ReadSize)\r
+    {\r
+        Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, LASTERR);\r
+    }\r
+\r
+    return 1;\r
+}\r
+\r
+\r
+int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen, BOOL *pSecureBoot)\r
+{\r
+    int rc = 0;\r
+    HANDLE hDrive;\r
+    void *flfile;\r
+\r
+    hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE);\r
+    if (hDrive == INVALID_HANDLE_VALUE)\r
+    {\r
+        return 1;\r
+    }\r
+    \r
+    g_FatPhyDrive = hDrive;\r
+       g_Part2StartSec = Part2StartSector;\r
+\r
+    Log("Parse FAT fs...");\r
+\r
+    fl_init();\r
+\r
+    if (0 == fl_attach_media(VentoyFatDiskRead, NULL))\r
+    {\r
+        Log("attach media success...");\r
+        rc = GetVentoyVersionFromFatFile(VerBuf, BufLen);\r
+    }\r
+    else\r
+    {\r
+        Log("attach media failed...");\r
+        rc = 1;\r
+    }\r
+\r
+    Log("GetVentoyVerInPhyDrive rc=%d...", rc);\r
+    if (rc == 0)\r
+    {\r
+        Log("VentoyVerInPhyDrive %d is <%s>...", pDriveInfo->PhyDrive, VerBuf);\r
+\r
+        flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");\r
+        if (flfile)\r
+        {\r
+            *pSecureBoot = TRUE;\r
+            fl_fclose(flfile);\r
+        }\r
+    }\r
+\r
+    fl_shutdown();\r
+\r
+    CHECK_CLOSE_HANDLE(hDrive);\r
+\r
+    return rc;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+static unsigned int g_disk_unxz_len = 0;\r
+static BYTE *g_part_img_pos = NULL;\r
+static BYTE *g_part_img_buf[VENTOY_EFI_PART_SIZE / SIZE_1MB];\r
+\r
+\r
+static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)\r
+{\r
+       uint32 i;\r
+       uint32 offset;\r
+       BYTE *MbBuf = NULL;\r
+\r
+       for (i = 0; i < SectorCount; i++)\r
+       {\r
+               offset = (Sector + i) * 512;\r
+\r
+               if (g_part_img_buf[1] == NULL)\r
+               {\r
+                       MbBuf = g_part_img_buf[0] + offset;\r
+                       memcpy(Buffer + i * 512, MbBuf, 512);\r
+               }\r
+               else\r
+               {\r
+                       MbBuf = g_part_img_buf[offset / SIZE_1MB];\r
+                       memcpy(Buffer + i * 512, MbBuf + (offset % SIZE_1MB), 512);\r
+               }\r
+       }\r
+\r
+       return 1;\r
+}\r
+\r
+\r
+static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount)\r
+{\r
+       uint32 i;\r
+       uint32 offset;\r
+       BYTE *MbBuf = NULL;\r
+\r
+       for (i = 0; i < SectorCount; i++)\r
+       {\r
+               offset = (Sector + i) * 512;\r
+\r
+               if (g_part_img_buf[1] == NULL)\r
+               {\r
+                       MbBuf = g_part_img_buf[0] + offset;\r
+                       memcpy(MbBuf, Buffer + i * 512, 512);\r
+               }\r
+               else\r
+               {\r
+                       MbBuf = g_part_img_buf[offset / SIZE_1MB];\r
+                       memcpy(MbBuf + (offset % SIZE_1MB), Buffer + i * 512, 512);\r
+               }\r
+       }\r
+\r
+       return 1;\r
+}\r
+\r
+int VentoyProcSecureBoot(BOOL SecureBoot)\r
+{\r
+       int rc = 0;\r
+       int size;\r
+       char *filebuf = NULL;\r
+       void *file = NULL;\r
+\r
+       Log("VentoyProcSecureBoot %d ...", SecureBoot);\r
+       \r
+       if (SecureBoot)\r
+       {\r
+               Log("Secure boot is enabled ...");\r
+               return 0;\r
+       }\r
+\r
+       fl_init();\r
+\r
+       if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite))\r
+       {\r
+               file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");\r
+               Log("Open ventoy efi file %p ", file);\r
+               if (file)\r
+               {\r
+                       fl_fseek(file, 0, SEEK_END);\r
+                       size = (int)fl_ftell(file);\r
+                       fl_fseek(file, 0, SEEK_SET);\r
+\r
+                       Log("ventoy efi file size %d ...", size);\r
+\r
+                       filebuf = (char *)malloc(size);\r
+                       if (filebuf)\r
+                       {\r
+                               fl_fread(filebuf, 1, size, file);\r
+                       }\r
+\r
+                       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/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
+                       if (file)\r
+                       {\r
+                               if (filebuf)\r
+                               {\r
+                                       fl_fwrite(filebuf, 1, size, file);\r
+                               }\r
+                               \r
+                               fl_fflush(file);\r
+                               fl_fclose(file);\r
+                       }\r
+\r
+                       if (filebuf)\r
+                       {\r
+                               free(filebuf);\r
+                       }\r
+               }\r
+\r
+        file = fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");\r
+        Log("Open ventoy efi file %p ", file);\r
+        if (file)\r
+        {\r
+            fl_fseek(file, 0, SEEK_END);\r
+            size = (int)fl_ftell(file);\r
+            fl_fseek(file, 0, SEEK_SET);\r
+\r
+            Log("ventoy efi file size %d ...", size);\r
+\r
+            filebuf = (char *)malloc(size);\r
+            if (filebuf)\r
+            {\r
+                fl_fread(filebuf, 1, size, file);\r
+            }\r
+\r
+            fl_fclose(file);\r
+\r
+            Log("Now delete all efi files ...");\r
+            fl_remove("/EFI/BOOT/BOOTIA32.EFI");\r
+            fl_remove("/EFI/BOOT/grubia32.efi");\r
+            fl_remove("/EFI/BOOT/grubia32_real.efi");\r
+            fl_remove("/EFI/BOOT/mmia32.efi");            \r
+\r
+            file = fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");\r
+            Log("Open bootia32 efi file %p ", file);\r
+            if (file)\r
+            {\r
+                if (filebuf)\r
+                {\r
+                    fl_fwrite(filebuf, 1, size, file);\r
+                }\r
+\r
+                fl_fflush(file);\r
+                fl_fclose(file);\r
+            }\r
+\r
+            if (filebuf)\r
+            {\r
+                free(filebuf);\r
+            }\r
+        }\r
+\r
+       }\r
+       else\r
+       {\r
+               rc = 1;\r
+       }\r
+\r
+       fl_shutdown();\r
+\r
+       return rc;\r
+}\r
+\r
+\r
+\r
+static int disk_xz_flush(void *src, unsigned int size)\r
+{\r
+    unsigned int i;\r
+    BYTE *buf = (BYTE *)src;\r
+\r
+    for (i = 0; i < size; i++)\r
+    {\r
+        *g_part_img_pos = *buf++;\r
+\r
+        g_disk_unxz_len++;\r
+        if ((g_disk_unxz_len % SIZE_1MB) == 0)\r
+        {\r
+            g_part_img_pos = g_part_img_buf[g_disk_unxz_len / SIZE_1MB];\r
+        }\r
+        else\r
+        {\r
+            g_part_img_pos++;\r
+        }\r
+    }\r
+\r
+    return (int)size;\r
+}\r
+\r
+static void unxz_error(char *x)\r
+{\r
+    Log("%s", x);\r
+}\r
+\r
+static BOOL TryWritePart2(HANDLE hDrive, UINT64 StartSectorId)\r
+{\r
+    BOOL bRet;\r
+    DWORD TrySize = 16 * 1024;\r
+    DWORD dwSize;\r
+    BYTE *Buffer = NULL;\r
+    unsigned char *data = NULL;\r
+    LARGE_INTEGER liCurrentPosition;\r
+\r
+    liCurrentPosition.QuadPart = StartSectorId * 512;\r
+    SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);\r
+    \r
+    Buffer = malloc(TrySize);\r
+\r
+    bRet = WriteFile(hDrive, Buffer, TrySize, &dwSize, NULL);\r
+\r
+    free(Buffer);\r
+\r
+    Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);\r
+\r
+    if (bRet && dwSize == TrySize)\r
+    {\r
+        return TRUE;\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId)\r
+{\r
+    int i;\r
+    int rc = 0;\r
+    int len = 0;\r
+    int writelen = 0;\r
+    int partwrite = 0;\r
+    int Pos = PT_WRITE_VENTOY_START;\r
+    DWORD dwSize = 0;\r
+    BOOL bRet;\r
+    unsigned char *data = NULL;\r
+    LARGE_INTEGER liCurrentPosition;\r
+       LARGE_INTEGER liNewPosition;\r
+    BYTE *CheckBuf = NULL;\r
+\r
+       Log("FormatPart2Fat %llu...", (ULONGLONG)StartSectorId);\r
+\r
+    CheckBuf = malloc(SIZE_1MB);\r
+    if (!CheckBuf)\r
+    {\r
+        Log("Failed to malloc check buf");\r
+        return 1;\r
+    }\r
+\r
+    rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&data, &len);\r
+    if (rc)\r
+    {\r
+        Log("Failed to read img file %p %u", data, len);\r
+        free(CheckBuf);\r
+        return 1;\r
+    }\r
+\r
+    liCurrentPosition.QuadPart = StartSectorId * 512;\r
+    SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);\r
+\r
+    memset(g_part_img_buf, 0, sizeof(g_part_img_buf));\r
+\r
+    g_part_img_buf[0] = (BYTE *)malloc(VENTOY_EFI_PART_SIZE);\r
+    if (g_part_img_buf[0])\r
+    {\r
+        Log("Malloc whole img buffer success, now decompress ...");\r
+        unxz(data, len, NULL, NULL, g_part_img_buf[0], &writelen, unxz_error);\r
+\r
+        if (len == writelen)\r
+        {\r
+            Log("decompress finished success");\r
+\r
+                       VentoyProcSecureBoot(g_SecureBoot);\r
+\r
+            for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)\r
+            {\r
+                dwSize = 0;\r
+                               bRet = WriteFile(hDrive, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB, &dwSize, NULL);\r
+                Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);\r
+\r
+                if (!bRet)\r
+                {\r
+                    rc = 1;\r
+                    goto End;\r
+                }\r
+\r
+                PROGRESS_BAR_SET_POS(Pos);\r
+                if (i % 2 == 0)\r
+                {\r
+                    Pos++;\r
+                }\r
+            }\r
+\r
+            //Read and check the data\r
+            liCurrentPosition.QuadPart = StartSectorId * 512;\r
+            SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);\r
+\r
+            for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)\r
+            {\r
+                bRet = ReadFile(hDrive, CheckBuf, SIZE_1MB, &dwSize, NULL);\r
+                Log("Read part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);\r
+\r
+                if (!bRet || memcmp(CheckBuf, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB))\r
+                {\r
+                    Log("### [Check Fail] The data write and read does not match");\r
+                    rc = 1;\r
+                    goto End;\r
+                }\r
+\r
+                PROGRESS_BAR_SET_POS(Pos);\r
+                if (i % 2 == 0)\r
+                {\r
+                    Pos++;\r
+                }\r
+            }\r
+        }\r
+        else\r
+        {\r
+            rc = 1;\r
+            Log("decompress finished failed");\r
+            goto End;\r
+        }\r
+    }\r
+    else\r
+    {\r
+        Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE);\r
+\r
+        partwrite = 1;\r
+        for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)\r
+        {\r
+            g_part_img_buf[i] = (BYTE *)malloc(SIZE_1MB);\r
+            if (g_part_img_buf[i] == NULL)\r
+            {\r
+                rc = 1;\r
+                goto End;\r
+            }\r
+        }\r
+\r
+        Log("Malloc part img buffer success, now decompress ...");\r
+\r
+        g_part_img_pos = g_part_img_buf[0];\r
+\r
+        unxz(data, len, NULL, disk_xz_flush, NULL, NULL, unxz_error);\r
+\r
+        if (g_disk_unxz_len == VENTOY_EFI_PART_SIZE)\r
+        {\r
+            Log("decompress finished success");\r
+                       \r
+                       VentoyProcSecureBoot(g_SecureBoot);\r
+\r
+            for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)\r
+            {\r
+                dwSize = 0;\r
+                bRet = WriteFile(hDrive, g_part_img_buf[i], SIZE_1MB, &dwSize, NULL);\r
+                Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);\r
+\r
+                if (!bRet)\r
+                {\r
+                    rc = 1;\r
+                    goto End;\r
+                }\r
+                \r
+                PROGRESS_BAR_SET_POS(Pos);\r
+                if (i % 2 == 0)\r
+                {\r
+                    Pos++;\r
+                }\r
+            }\r
+\r
+            //Read and check the data\r
+            liCurrentPosition.QuadPart = StartSectorId * 512;\r
+            SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);\r
+\r
+            for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)\r
+            {\r
+                bRet = ReadFile(hDrive, CheckBuf, SIZE_1MB, &dwSize, NULL);\r
+                Log("Read part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);\r
+\r
+                if (!bRet || memcmp(CheckBuf, g_part_img_buf[i], SIZE_1MB))\r
+                {\r
+                    Log("### [Check Fail] The data write and read does not match");\r
+                    rc = 1;\r
+                    goto End;\r
+                }\r
+\r
+                PROGRESS_BAR_SET_POS(Pos);\r
+                if (i % 2 == 0)\r
+                {\r
+                    Pos++;\r
+                }\r
+            }\r
+        }\r
+        else\r
+        {\r
+            rc = 1;\r
+            Log("decompress finished failed");\r
+            goto End;\r
+        }\r
+    }\r
+\r
+End:\r
+\r
+    if (data) free(data);\r
+    if (CheckBuf)free(CheckBuf);\r
+\r
+    if (partwrite)\r
+    {\r
+        for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)\r
+        {\r
+            if (g_part_img_buf[i]) free(g_part_img_buf[i]);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        if (g_part_img_buf[0]) free(g_part_img_buf[0]);\r
+    }\r
+\r
+    return rc;\r
+}\r
+\r
+static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle)\r
+{\r
+    int Len = 0;\r
+    int readLen = 0;\r
+    BOOL bRet;\r
+    DWORD dwSize;\r
+    BYTE *ImgBuf = NULL;\r
+    BYTE *RawBuf = NULL;\r
+\r
+    Log("WriteGrubStage1ToPhyDrive ...");\r
+\r
+    RawBuf = (BYTE *)malloc(SIZE_1MB);\r
+    if (!RawBuf)\r
+    {\r
+        return 1;\r
+    }\r
+\r
+    if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))\r
+    {\r
+        Log("Failed to read stage1 img");\r
+        free(RawBuf);\r
+        return 1;\r
+    }\r
+\r
+    unxz(ImgBuf, Len, NULL, NULL, RawBuf, &readLen, unxz_error);\r
+\r
+    if (PartStyle)\r
+    {\r
+        Log("Write GPT stage1 ...");\r
+        RawBuf[500] = 35;//update blocklist\r
+        SetFilePointer(hDrive, 512 * 34, NULL, FILE_BEGIN);        \r
+        bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512 * 34, &dwSize, NULL);\r
+    }\r
+    else\r
+    {\r
+        Log("Write MBR stage1 ...");\r
+        SetFilePointer(hDrive, 512, NULL, FILE_BEGIN);\r
+        bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512, &dwSize, NULL);\r
+    }\r
+\r
+    Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet, dwSize, GetLastError());\r
+\r
+    free(RawBuf);\r
+    free(ImgBuf);\r
+    return 0;\r
+}\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
+    MKFS_PARM Option;\r
+    FRESULT Ret;\r
+\r
+    Option.fmt = FM_EXFAT;\r
+    Option.n_fat = 1;\r
+    Option.align = 8;\r
+    Option.n_root = 1;\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
+    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
+    else\r
+    {\r
+        Log("Formatting Part1 exFAT failed");\r
+        return 1;\r
+    }\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
+    int i;\r
+    int rc = 0;\r
+    int state = 0;\r
+    HANDLE hDrive;\r
+    DWORD dwSize;\r
+    BOOL bRet;\r
+    CHAR MountDrive;\r
+    CHAR DriveName[] = "?:\\";\r
+    CHAR DriveLetters[MAX_PATH] = { 0 };\r
+    LARGE_INTEGER liCurrentPosition;\r
+    char *pTmpBuf = NULL;\r
+    MBR_HEAD MBR;\r
+\r
+    *pDrvLetter = 0;\r
+\r
+    Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",\r
+        pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,\r
+        GetHumanReadableGBSize(pPhyDrive->SizeInBytes));\r
+\r
+    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);\r
+\r
+    Log("Lock disk for clean ............................. ");\r
+\r
+    hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);\r
+    if (hDrive == INVALID_HANDLE_VALUE)\r
+    {\r
+        Log("Failed to open physical disk");\r
+        return 1;\r
+    }\r
+\r
+    GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));\r
+\r
+    if (DriveLetters[0] == 0)\r
+    {\r
+        Log("No drive letter was assigned...");\r
+        DriveName[0] = GetFirstUnusedDriveLetter();\r
+        Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);\r
+    }\r
+    else\r
+    {\r
+        // Unmount all mounted volumes that belong to this drive\r
+        // Do it in reverse so that we always end on the first volume letter\r
+        for (i = (int)strlen(DriveLetters); i > 0; i--)\r
+        {\r
+            DriveName[0] = DriveLetters[i - 1];\r
+            bRet = DeleteVolumeMountPointA(DriveName);\r
+            Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());\r
+        }\r
+    }\r
+\r
+    MountDrive = DriveName[0];\r
+    Log("Will use '%C:' as volume mountpoint", DriveName[0]);\r
+\r
+    // It kind of blows, but we have to relinquish access to the physical drive\r
+    // for VDS to be able to delete the partitions that reside on it...\r
+    DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);\r
+    CHECK_CLOSE_HANDLE(hDrive);\r
+\r
+    PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);\r
+\r
+    if (!VDS_DeleteAllPartitions(pPhyDrive->PhyDrive))\r
+    {\r
+        Log("Notice: Could not delete partitions: %u", GetLastError());\r
+    }\r
+\r
+    Log("Deleting all partitions ......................... OK");\r
+\r
+    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);\r
+\r
+    Log("Lock disk for write ............................. ");\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
+    // clear first and last 2MB space\r
+    pTmpBuf = malloc(SIZE_2MB);\r
+    if (!pTmpBuf)\r
+    {\r
+        Log("Failed to alloc memory.");\r
+        rc = 1;\r
+        goto End;\r
+    }\r
+    memset(pTmpBuf, 0, SIZE_2MB);\r
+\r
+    SET_FILE_POS(512);\r
+    bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB - 512, &dwSize, NULL);\r
+    Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);\r
+    if (!bRet)\r
+    {\r
+        rc = 1;\r
+        goto End;\r
+    }\r
+\r
+    SET_FILE_POS(pPhyDrive->SizeInBytes - SIZE_2MB);\r
+    bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB, &dwSize, NULL);\r
+    Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);\r
+    if (!bRet)\r
+    {\r
+        rc = 1;\r
+        goto End;\r
+    }\r
+\r
+    SET_FILE_POS(0);\r
+\r
+    if (pPhyDrive->SizeInBytes > 2199023255552ULL)\r
+    {\r
+        VTOY_GPT_INFO *pGptInfo;\r
+        VTOY_GPT_HDR BackupHead;\r
+        LARGE_INTEGER liCurrentPosition;\r
+\r
+        pGptInfo = (VTOY_GPT_INFO *)pTmpBuf;\r
+\r
+        VentoyFillWholeGpt(pPhyDrive->SizeInBytes, pGptInfo);\r
+\r
+        SET_FILE_POS(pPhyDrive->SizeInBytes - 512);\r
+        VentoyFillBackupGptHead(pGptInfo, &BackupHead);\r
+        if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))\r
+        {\r
+            rc = 1;\r
+            Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());\r
+            goto End;\r
+        }\r
+\r
+        SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);\r
+        if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))\r
+        {\r
+            rc = 1;\r
+            Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());\r
+            goto End;\r
+        }\r
+\r
+        SET_FILE_POS(0);\r
+        if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))\r
+        {\r
+            rc = 1;\r
+            Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());\r
+            goto End;\r
+        }\r
+\r
+        Log("Write GPT Info OK ...");\r
+    }\r
+    else\r
+    {\r
+        bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);\r
+        Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);\r
+        if (!bRet)\r
+        {\r
+            rc = 1;\r
+            goto End;\r
+        }\r
+\r
+        //clear boot code and partition table (reserved disk signature)\r
+        memset(MBR.BootCode, 0, 440);\r
+        memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl));\r
+\r
+        VentoyFillMBRLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl);\r
+\r
+        MBR.PartTbl[0].Active = 0x00; // bootable\r
+        MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS\r
+\r
+        SET_FILE_POS(0);\r
+        bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);\r
+        Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);\r
+        if (!bRet)\r
+        {\r
+            rc = 1;\r
+            goto End;\r
+        }\r
+    }\r
+\r
+    Log("Clear Ventoy successfully finished");\r
+\r
+       //Refresh Drive Layout\r
+       DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);\r
+\r
+End:\r
+    \r
+    PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);\r
+    PROGRESS_BAR_SET_POS(PT_REFORMAT_FINISH);\r
+    \r
+    if (pTmpBuf)\r
+    {\r
+        free(pTmpBuf);\r
+    }\r
+\r
+    if (rc == 0)\r
+    {\r
+        Log("Mounting Ventoy Partition ....................... ");\r
+        Sleep(1000);\r
+\r
+        state = 0;\r
+        memset(DriveLetters, 0, sizeof(DriveLetters));\r
+        GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));\r
+        Log("Logical drive letter after write ventoy: <%s>", DriveLetters);\r
+\r
+        for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)\r
+        {\r
+            DriveName[0] = DriveLetters[i];\r
+            Log("%s is ventoy part1, already mounted", DriveName);\r
+            state = 1;\r
+        }\r
+\r
+        if (state != 1)\r
+        {\r
+            Log("need to mount ventoy part1...");\r
+            if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, 2048, DriveLetters, sizeof(DriveLetters), FALSE))\r
+            {\r
+                DriveName[0] = MountDrive;\r
+                bRet = SetVolumeMountPointA(DriveName, DriveLetters);\r
+                Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());\r
+\r
+                *pDrvLetter = MountDrive;\r
+            }\r
+            else\r
+            {\r
+                Log("Failed to find ventoy volume");\r
+            }\r
+        }\r
+\r
+        Log("OK\n");\r
+    }\r
+    else\r
+    {\r
+        FindProcessOccupyDisk(hDrive, pPhyDrive);\r
+    }\r
+\r
+    CHECK_CLOSE_HANDLE(hDrive);\r
+    return rc;\r
+}\r
+\r
+int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)\r
+{\r
+    int i;\r
+    int rc = 1;\r
+    int Len = 0;\r
+    int dataLen = 0;\r
+    UINT size = 0;\r
+    UINT segnum = 0;\r
+    UINT32 chksum = 0;\r
+    UINT64 data_offset = 0;\r
+    UINT64 Part2StartSector = 0;\r
+    UINT64 Part1StartSector = 0;\r
+    UINT64 Part1SectorCount = 0;\r
+    UINT8 *pData = NULL;    \r
+    UINT8 *pBkGptPartTbl = NULL;\r
+    BYTE *ImgBuf = NULL;\r
+    MBR_HEAD *pMBR = NULL;\r
+    VTSI_FOOTER *pImgFooter = NULL;\r
+    VTSI_SEGMENT *pSegment = NULL;\r
+    VTOY_GPT_INFO *pGptInfo = NULL;\r
+    VTOY_GPT_HDR *pBkGptHdr = NULL;\r
+    FILE *fp = NULL;\r
+\r
+    Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",\r
+        PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,\r
+        GetHumanReadableGBSize(pPhyDrive->SizeInBytes));\r
+\r
+    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);\r
+\r
+    size = SIZE_1MB + VENTOY_EFI_PART_SIZE + 33 * 512 + VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT) + sizeof(VTSI_FOOTER);\r
+\r
+    pData = (UINT8 *)malloc(size);\r
+    if (!pData)\r
+    {\r
+        Log("malloc image buffer failed %d.", size);\r
+        goto End;\r
+    }\r
+\r
+    pImgFooter = (VTSI_FOOTER *)(pData + size - sizeof(VTSI_FOOTER));\r
+    pSegment = (VTSI_SEGMENT *)((UINT8 *)pImgFooter - VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));\r
+    memset(pImgFooter, 0, sizeof(VTSI_FOOTER));\r
+    memset(pSegment, 0, VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));\r
+\r
+    PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START);\r
+\r
+    Log("Writing Boot Image ............................. ");\r
+    if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))\r
+    {\r
+        Log("Failed to read stage1 img");\r
+        goto End;\r
+    }\r
+\r
+    unxz(ImgBuf, Len, NULL, NULL, pData, &dataLen, unxz_error);\r
+    SAFE_FREE(ImgBuf);\r
+\r
+    Log("decompress %s len:%d", VENTOY_FILE_STG1_IMG, dataLen);\r
+\r
+    if (PartStyle)\r
+    {\r
+        pData[500] = 35;//update blocklist\r
+        memmove(pData + 34 * 512, pData, SIZE_1MB - 512 * 34);\r
+        memset(pData, 0, 34 * 512);\r
+\r
+        pGptInfo = (VTOY_GPT_INFO *)pData;\r
+        memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));\r
+        VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);\r
+\r
+        pBkGptPartTbl = pData + SIZE_1MB + VENTOY_EFI_PART_SIZE;\r
+        memset(pBkGptPartTbl, 0, 33 * 512);\r
+\r
+        memcpy(pBkGptPartTbl, pGptInfo->PartTbl, 32 * 512);\r
+        pBkGptHdr = (VTOY_GPT_HDR *)(pBkGptPartTbl + 32 * 512);\r
+        VentoyFillBackupGptHead(pGptInfo, pBkGptHdr);\r
+\r
+        Part1StartSector = pGptInfo->PartTbl[0].StartLBA;\r
+        Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;\r
+        Part2StartSector = pGptInfo->PartTbl[1].StartLBA;\r
+\r
+        Log("Write GPT Info OK ...");\r
+    }\r
+    else\r
+    {\r
+        memmove(pData + 512, pData, SIZE_1MB - 512);\r
+        memset(pData, 0, 512);\r
+\r
+        pMBR = (MBR_HEAD *)pData;\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
+\r
+        Log("Write MBR OK ...");\r
+    }\r
+\r
+    Log("Writing EFI part Image ............................. ");\r
+    rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&ImgBuf, &Len);\r
+    if (rc)\r
+    {\r
+        Log("Failed to read img file %p %u", ImgBuf, Len);\r
+        goto End;\r
+    }\r
+\r
+    PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + 28);\r
+    memset(g_part_img_buf, 0, sizeof(g_part_img_buf));\r
+    unxz(ImgBuf, Len, NULL, NULL, pData + SIZE_1MB, &dataLen, unxz_error);\r
+    if (dataLen == Len)\r
+    {\r
+        Log("decompress finished success");\r
+        g_part_img_buf[0] = pData + SIZE_1MB;\r
+\r
+        VentoyProcSecureBoot(g_SecureBoot);\r
+    }\r
+    else\r
+    {\r
+        Log("decompress finished failed");\r
+        goto End;\r
+    }\r
+\r
+    fopen_s(&fp, "VentoySparseImg.vtsi", "wb+");\r
+    if (!fp)\r
+    {\r
+        Log("Failed to create Ventoy img file");\r
+        goto End;\r
+    }\r
+\r
+    Log("Writing stage1 data ............................. ");\r
+\r
+    fwrite(pData, 1, SIZE_1MB, fp);\r
+\r
+    pSegment[0].disk_start_sector = 0;\r
+    pSegment[0].sector_num = SIZE_1MB / 512;\r
+    pSegment[0].data_offset = data_offset;\r
+    data_offset += pSegment[0].sector_num * 512;\r
+\r
+    disk_io_set_param(INVALID_HANDLE_VALUE, Part1StartSector + Part1SectorCount);// include the 2048 sector gap\r
+    disk_io_set_imghook(fp, pSegment + 1, VTSI_IMG_MAX_SEG - 1, data_offset);\r
+\r
+    Log("Formatting part1 exFAT ...");\r
+    if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))\r
+    {\r
+        Log("FormatPart1exFAT failed.");\r
+        disk_io_reset_imghook(&segnum, &data_offset);\r
+        goto End;\r
+    }\r
+\r
+    disk_io_reset_imghook(&segnum, &data_offset);\r
+    segnum++;\r
+\r
+    Log("current segment number:%d dataoff:%ld", segnum, (long)data_offset);\r
+\r
+    //write data\r
+    Log("Writing part2 data ............................. ");\r
+    fwrite(pData + SIZE_1MB, 1, VENTOY_EFI_PART_SIZE, fp);\r
+    pSegment[segnum].disk_start_sector = Part2StartSector;\r
+    pSegment[segnum].sector_num = VENTOY_EFI_PART_SIZE / 512;\r
+    pSegment[segnum].data_offset = data_offset;\r
+    data_offset += pSegment[segnum].sector_num * 512;\r
+    segnum++;\r
+\r
+    if (PartStyle)\r
+    {\r
+        Log("Writing backup gpt table ............................. ");\r
+        fwrite(pBkGptPartTbl, 1, 33 * 512, fp);\r
+        pSegment[segnum].disk_start_sector = pPhyDrive->SizeInBytes / 512 - 33;\r
+        pSegment[segnum].sector_num = 33;\r
+        pSegment[segnum].data_offset = data_offset;\r
+        data_offset += pSegment[segnum].sector_num * 512;\r
+        segnum++;\r
+    }\r
+\r
+    Log("Writing segment metadata ............................. ");\r
+\r
+    for (i = 0; i < (int)segnum; i++)\r
+    {\r
+        Log("SEG[%d]:  PhySector:%llu SectorNum:%llu DataOffset:%llu(sector:%llu)", i, pSegment[i].disk_start_sector, pSegment[i].sector_num,\r
+            pSegment[i].data_offset, pSegment[i].data_offset / 512);\r
+    }\r
+\r
+    dataLen = segnum * sizeof(VTSI_SEGMENT);\r
+    fwrite(pSegment, 1, dataLen, fp);\r
+\r
+    if (dataLen % 512)\r
+    {\r
+        //pData + SIZE_1MB - 8192 is a temp data buffer with zero\r
+        fwrite(pData + SIZE_1MB - 8192, 1, 512 - (dataLen % 512), fp);\r
+    }\r
+\r
+    //Fill footer\r
+    pImgFooter->magic = VTSI_IMG_MAGIC;\r
+    pImgFooter->version = 1;\r
+    pImgFooter->disk_size = pPhyDrive->SizeInBytes;\r
+    memcpy(&pImgFooter->disk_signature, pPhyDrive->MBR.BootCode + 0x1b8, 4);\r
+    pImgFooter->segment_num = segnum;\r
+    pImgFooter->segment_offset = data_offset;\r
+\r
+    for (i = 0, chksum = 0; i < (int)(segnum * sizeof(VTSI_SEGMENT)); i++)\r
+    {\r
+        chksum += *((UINT8 *)pSegment + i);\r
+    }\r
+    pImgFooter->segment_chksum = ~chksum;\r
+\r
+    for (i = 0, chksum = 0; i < sizeof(VTSI_FOOTER); i++)\r
+    {\r
+        chksum += *((UINT8 *)pImgFooter + i);\r
+    }\r
+    pImgFooter->foot_chksum = ~chksum;\r
+\r
+    Log("Writing footer segnum(%u)  segoffset(%llu) ......................", segnum, data_offset);\r
+    Log("disk_size=%llu disk_signature=%lx segment_offset=%llu", pImgFooter->disk_size, pImgFooter->disk_signature, pImgFooter->segment_offset);\r
+\r
+    fwrite(pImgFooter, 1, sizeof(VTSI_FOOTER), fp);\r
+    fclose(fp);\r
+\r
+    Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset + 512 + ((dataLen + 511) / 512 * 512));\r
+\r
+    rc = 0;\r
+\r
+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
+    SAFE_FREE(pData);\r
+    SAFE_FREE(ImgBuf);\r
+    \r
+    return rc;\r
+}\r
+\r
+\r
+int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)\r
+{\r
+    int i;\r
+    int rc = 0;\r
+    int state = 0;\r
+    BOOL ReformatOK;\r
+    HANDLE hDrive;\r
+    DWORD dwSize;\r
+    BOOL bRet;\r
+    CHAR MountDrive;\r
+    CHAR DriveName[] = "?:\\";\r
+    CHAR DriveLetters[MAX_PATH] = { 0 };\r
+    MBR_HEAD MBR;\r
+    VTOY_GPT_INFO *pGptInfo = NULL;\r
+    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
+        pGptInfo = malloc(sizeof(VTOY_GPT_INFO));\r
+        memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));\r
+    }\r
+\r
+    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);\r
+\r
+    if (PartStyle)\r
+    {\r
+        VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);\r
+        Part1StartSector = pGptInfo->PartTbl[0].StartLBA;\r
+        Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;\r
+        Part2StartSector = pGptInfo->PartTbl[1].StartLBA;\r
+    }\r
+    else\r
+    {\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
+    }\r
+\r
+    Log("Lock disk for clean ............................. ");\r
+\r
+    hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);\r
+    if (hDrive == INVALID_HANDLE_VALUE)\r
+    {\r
+        Log("Failed to open physical disk");\r
+        free(pGptInfo);\r
+        return 1;\r
+    }\r
+\r
+    GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));\r
+\r
+    if (DriveLetters[0] == 0)\r
+    {\r
+        Log("No drive letter was assigned...");\r
+        DriveName[0] = GetFirstUnusedDriveLetter();\r
+        Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);\r
+    }\r
+    else\r
+    {\r
+        // Unmount all mounted volumes that belong to this drive\r
+        // Do it in reverse so that we always end on the first volume letter\r
+        for (i = (int)strlen(DriveLetters); i > 0; i--)\r
+        {\r
+            DriveName[0] = DriveLetters[i - 1];\r
+            bRet = DeleteVolumeMountPointA(DriveName);\r
+            Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());\r
+        }\r
+    }\r
+\r
+    MountDrive = DriveName[0];\r
+    Log("Will use '%C:' as volume mountpoint", DriveName[0]);\r
+\r
+    // It kind of blows, but we have to relinquish access to the physical drive\r
+    // for VDS to be able to delete the partitions that reside on it...\r
+    DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);\r
+    CHECK_CLOSE_HANDLE(hDrive);\r
+\r
+    PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);\r
+\r
+    if (!VDS_DeleteAllPartitions(pPhyDrive->PhyDrive))\r
+    {\r
+        Log("Notice: Could not delete partitions: 0x%x, but we continue.", GetLastError());\r
+    }\r
+\r
+    Log("Deleting all partitions ......................... OK");\r
+\r
+    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);\r
+\r
+    Log("Lock disk for write ............................. ");\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
+    //Refresh Drive Layout\r
+    DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);\r
+\r
+    disk_io_set_param(hDrive, Part1StartSector + Part1SectorCount);// include the 2048 sector gap\r
+\r
+    PROGRESS_BAR_SET_POS(PT_FORMAT_PART1);\r
+\r
+    if (PartStyle == 1 && pPhyDrive->PartStyle == 0)\r
+    {\r
+        Log("Wait for format part1 ...");\r
+        Sleep(1000 * 5);\r
+    }\r
+\r
+    if (GetVentoyFsType() == VTOY_FS_FAT32 && (Part1SectorCount * 512 >= FAT32_MAX_LIMIT))\r
+    {\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
+    Log("Writing part2 FAT img ...");\r
+    \r
+    if (0 != FormatPart2Fat(hDrive, Part2StartSector))\r
+    {\r
+        Log("FormatPart2Fat failed.");\r
+        rc = 1;\r
+        goto End;\r
+    }\r
+\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
+        rc = 1;\r
+        goto End;\r
+    }\r
+\r
+    PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);\r
+    Log("Writing Partition Table ........................ ");\r
+    SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
+\r
+    if (PartStyle)\r
+    {\r
+        VTOY_GPT_HDR BackupHead;\r
+        LARGE_INTEGER liCurrentPosition;\r
+\r
+        SET_FILE_POS(pPhyDrive->SizeInBytes - 512);\r
+        VentoyFillBackupGptHead(pGptInfo, &BackupHead);\r
+        if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))\r
+        {\r
+            rc = 1;\r
+            Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());\r
+            goto End;\r
+        }\r
+\r
+        SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);\r
+        if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))\r
+        {\r
+            rc = 1;\r
+            Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());\r
+            goto End;\r
+        }\r
+\r
+        SET_FILE_POS(0);\r
+        if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))\r
+        {\r
+            rc = 1;\r
+            Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());\r
+            goto End;\r
+        }\r
+\r
+        Log("Write GPT Info OK ...");\r
+        memcpy(&(pPhyDrive->MBR), &(pGptInfo->MBR), 512);\r
+    }\r
+    else\r
+    {\r
+        if (!WriteFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL))\r
+        {\r
+            rc = 1;\r
+            Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize, GetLastError());\r
+            goto End;\r
+        }\r
+        Log("Write MBR OK ...");\r
+        memcpy(&(pPhyDrive->MBR), &MBR, 512);\r
+    }\r
+\r
+    //Refresh Drive Layout\r
+    DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);\r
+\r
+End:\r
+\r
+    PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);\r
+\r
+    if (rc == 0)\r
+    {\r
+        Log("Mounting Ventoy Partition ....................... ");\r
+        Sleep(1000);\r
+\r
+        state = 0;\r
+        memset(DriveLetters, 0, sizeof(DriveLetters));\r
+        GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));\r
+        Log("Logical drive letter after write ventoy: <%s>", DriveLetters);\r
+\r
+        for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)\r
+        {\r
+            DriveName[0] = DriveLetters[i];\r
+            if (IsVentoyLogicalDrive(DriveName[0]))\r
+            {\r
+                Log("%s is ventoy part2, delete mountpoint", DriveName);\r
+                DeleteVolumeMountPointA(DriveName);\r
+            }\r
+            else\r
+            {\r
+                Log("%s is ventoy part1, already mounted", DriveName);\r
+                MountDrive = DriveName[0];\r
+                state = 1;\r
+            }\r
+        }\r
+\r
+        if (state != 1)\r
+        {\r
+            Log("need to mount ventoy part1...");\r
+            \r
+            if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, Part1StartSector, DriveLetters, sizeof(DriveLetters), FALSE))\r
+            {\r
+                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
+    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
+       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
+\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 = VENTOY_EFI_PART_ATTR;\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 = 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
+       BOOL bUpdateEFIAttr = FALSE;\r
+       HANDLE hVolume;\r
+       HANDLE hDrive;\r
+       DWORD Status;\r
+       DWORD dwSize;\r
+       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
+       Log("Lock disk for umount ............................ ");\r
+\r
+       hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);\r
+       if (hDrive == INVALID_HANDLE_VALUE)\r
+       {\r
+               Log("Failed to open physical disk");\r
+               return 1;\r
+       }\r
+\r
+       if (pPhyDrive->PartStyle)\r
+       {\r
+               pGptInfo = malloc(2 * sizeof(VTOY_GPT_INFO));\r
+               if (!pGptInfo)\r
+               {\r
+                       return 1;\r
+               }\r
+\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
+\r
+               StartSector = pGptInfo->PartTbl[1].StartLBA;\r
+               Log("GPT StartSector in PartTbl:%llu", (ULONGLONG)StartSector);\r
+\r
+               ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512) - 33) / 2048;\r
+               Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);\r
+       }\r
+       else\r
+       {\r
+               // Read MBR\r
+               SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
+               ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);\r
+\r
+               StartSector = MBR.PartTbl[1].StartSectorId;\r
+               Log("MBR StartSector in PartTbl:%llu", (ULONGLONG)StartSector);\r
+\r
+               ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512)) / 2048;\r
+               Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);\r
+       }\r
+\r
+       //Read Reserved Data\r
+       SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);\r
+       ReadFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);\r
+\r
+       GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));\r
+\r
+       if (DriveLetters[0] == 0)\r
+       {\r
+               Log("No drive letter was assigned...");\r
+       }\r
+       else\r
+       {\r
+               // Unmount all mounted volumes that belong to this drive\r
+               // Do it in reverse so that we always end on the first volume letter\r
+               for (i = (int)strlen(DriveLetters); i > 0; i--)\r
+               {\r
+                       DriveName[0] = DriveLetters[i - 1];\r
+                       if (IsVentoyLogicalDrive(DriveName[0]))\r
+                       {\r
+                               Log("%s is ventoy logical drive", DriveName);\r
+                               bRet = DeleteVolumeMountPointA(DriveName);\r
+                               Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, LASTERR);\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       // It kind of blows, but we have to relinquish access to the physical drive\r
+       // for VDS to be able to delete the partitions that reside on it...\r
+       DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);\r
+       CHECK_CLOSE_HANDLE(hDrive);\r
+\r
+       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 (pGptInfo->PartTbl[1].Attr != VENTOY_EFI_PART_ATTR)\r
+        {\r
+            bUpdateEFIAttr = TRUE;            \r
+        }        \r
+\r
+\r
+               if (TryId == 1)\r
+               {\r
+                       Log("Change GPT partition type to ESP");\r
+                       if (DISK_ChangeVtoyEFI2ESP(pPhyDrive->PhyDrive, StartSector * 512ULL))\r
+                       {\r
+                               Esp2Basic = TRUE;\r
+                               Sleep(3000);\r
+                       }\r
+               }\r
+               else if (TryId == 2)\r
+               {\r
+                       Log("Try2 Change GPT partition attribute to 0x%016llx", VENTOY_EFI_PART_ATTR & 0xFFFFFFFFFFFFFFFEULL);\r
+                       if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, VENTOY_EFI_PART_ATTR & 0xFFFFFFFFFFFFFFFEULL))\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
+    PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);\r
+\r
+    Log("Lock disk for update ............................ ");\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
+    PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME);\r
+\r
+    Log("Lock volume for update .......................... ");\r
+    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 (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
+       else\r
+       {\r
+               for (i = 0; i < MaxRetry; i++)\r
+               {\r
+                       Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, StartSector, DriveLetters, sizeof(DriveLetters), TRUE);\r
+                       if (ERROR_SUCCESS == Status)\r
+                       {\r
+                               break;\r
+                       }\r
+                       else\r
+                       {\r
+                               Log("==== Volume not found, wait and retry %d... ====", i);\r
+                               Sleep(2);\r
+                       }\r
+               }\r
+       }\r
+       \r
+    if (ERROR_SUCCESS == Status)\r
+    {\r
+        Log("Now lock and dismount volume <%s>", DriveLetters);\r
+\r
+        for (i = 0; i < MaxRetry; i++)\r
+        {\r
+            hVolume = CreateFileA(DriveLetters,\r
+                GENERIC_READ | GENERIC_WRITE,\r
+                FILE_SHARE_READ,\r
+                NULL,\r
+                OPEN_EXISTING,\r
+                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,\r
+                NULL);\r
+\r
+            if (hVolume == INVALID_HANDLE_VALUE)\r
+            {\r
+                Log("Failed to create file volume, errcode:%u, wait and retry ...", LASTERR);\r
+                Sleep(2000);\r
+            }\r
+            else\r
+            {\r
+                break;\r
+            }\r
+        }\r
+\r
+        if (hVolume == INVALID_HANDLE_VALUE)\r
+        {\r
+            Log("Failed to create file volume, errcode:%u", LASTERR);\r
+        }\r
+        else\r
+        {\r
+            bRet = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);\r
+            Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);\r
+\r
+            bRet = DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);\r
+            Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet, LASTERR);\r
+        }\r
+    }\r
+    else if (ERROR_NOT_FOUND == Status)\r
+    {\r
+        Log("Volume not found, maybe not supported");\r
+    }\r
+    else\r
+    {\r
+        rc = 1;\r
+        goto End;\r
+    }\r
+\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
+                       if (DiskCheckWriteAccess(hDrive))\r
+                       {\r
+                               Log("MBR DiskCheckWriteAccess success");\r
+\r
+                               ForceMBR = TRUE;\r
+\r
+                               Log("Try write failed, now delete partition 2 for MBR...");\r
+                               CHECK_CLOSE_HANDLE(hDrive);\r
+\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("MBR DiskCheckWriteAccess failed");\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       Log("TryWritePart2 failed ....");\r
+                       rc = 1;\r
+                       goto End;\r
+               }\r
+    }\r
+\r
+    PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);\r
+\r
+    Log("Write Ventoy to disk ............................ ");\r
+    if (0 != FormatPart2Fat(hDrive, StartSector))\r
+    {\r
+        rc = 1;\r
+        goto End;\r
+    }\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
+    Log("Updating Boot Image ............................. ");\r
+    if (WriteGrubStage1ToPhyDrive(hDrive, pPhyDrive->PartStyle) != 0)\r
+    {\r
+        rc = 1;\r
+        goto End;\r
+    }\r
+\r
+    //write reserved data\r
+    SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);    \r
+    bRet = WriteFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);\r
+    Log("Write resv data ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);\r
+\r
+    // Boot Image\r
+    VentoyGetLocalBootImg(&BootImg);\r
+\r
+    // Use Old UUID\r
+    memcpy(BootImg.BootCode + 0x180, MBR.BootCode + 0x180, 16);\r
+    if (pPhyDrive->PartStyle)\r
+    {\r
+        BootImg.BootCode[92] = 0x22;\r
+    }\r
+\r
+    if (ForceMBR == FALSE && memcmp(BootImg.BootCode, MBR.BootCode, 440) == 0)\r
+    {\r
+        Log("Boot image has no difference, no need to write.");\r
+    }\r
+    else\r
+    {\r
+        Log("Boot image need to write %u.", ForceMBR);\r
+\r
+        SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
+\r
+        memcpy(MBR.BootCode, BootImg.BootCode, 440);\r
+        bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);\r
+        Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);\r
+    }\r
+\r
+    if (pPhyDrive->PartStyle == 0)\r
+    {\r
+        if (0x00 == MBR.PartTbl[0].Active && 0x80 == MBR.PartTbl[1].Active)\r
+        {\r
+            Log("Need to chage 1st partition active and 2nd partition inactive.");\r
+\r
+            MBR.PartTbl[0].Active = 0x80;\r
+            MBR.PartTbl[1].Active = 0x00;\r
+\r
+            SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
+            bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);\r
+            Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);\r
+        }\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
+    CHECK_CLOSE_HANDLE(hDrive);\r
+\r
+    if (Esp2Basic)\r
+    {\r
+               Log("Recover GPT partition type to basic");\r
+               DISK_ChangeVtoyEFI2Basic(pPhyDrive->PhyDrive, StartSector * 512);\r
+    }\r
+\r
+\r
+       if (pPhyDrive->PartStyle == 1)\r
+       {\r
+               if (ChangeAttr || bUpdateEFIAttr)\r
+               {\r
+                       Log("Change EFI partition attr %u <0x%llx> to <0x%llx>", ChangeAttr, pGptInfo->PartTbl[1].Attr, VENTOY_EFI_PART_ATTR);\r
+                       if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, VENTOY_EFI_PART_ATTR))\r
+                       {\r
+                               Log("Change EFI partition attr success");\r
+                               pPhyDrive->Part2GPTAttr = VENTOY_EFI_PART_ATTR;\r
+                       }\r
+                       else\r
+                       {\r
+                               Log("Change EFI partition attr failed");\r
+                       }\r
+               }\r
+       }\r
+\r
+    if (pGptInfo)\r
+    {\r
+        free(pGptInfo);\r
+    }\r
+    \r
+    return rc;\r
+}\r
+\r
+\r