]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - Ventoy2Disk/Ventoy2Disk/DiskService_vds.c
Update Romanian Translation (#2001)
[Ventoy.git] / Ventoy2Disk / Ventoy2Disk / DiskService_vds.c
index 763ab0351584f2fe268a9757c11145268f9b738a..e2a1fab7f4e96cc2a696c35b730b3be1e7abe578 100644 (file)
 // 3. Filter out the crap we don't need.\r
 static const char *GetVdsError(DWORD error_code)\r
 {\r
+       static char code[32];\r
+\r
+       sprintf_s(code, sizeof(code), "[0x%08x]", error_code);\r
+\r
        switch (error_code) {\r
        case 0x80042400:        // VDS_E_NOT_SUPPORTED\r
                return "The operation is not supported by the object.";\r
@@ -386,6 +390,10 @@ static const char *GetVdsError(DWORD error_code)
                return "The offline operation failed.";\r
        case 0x80042598:        // VDS_E_BAD_REVISION_NUMBER\r
                return "The operation could not be completed because the specified revision number is not supported.";\r
+       case 0x80042599:    // VDS_E_SHRINK_USER_CANCELLED\r
+               return "The shrink operation was cancelled by the user.";\r
+       case 0x8004259a:    // VDS_E_SHRINK_DIRTY_VOLUME\r
+               return "The volume you have selected to shrink may be corrupted. Use Chkdsk to fix the corruption problem, and then try again.";\r
        case 0x00042700:        // VDS_S_NAME_TRUNCATED\r
                return "The name was set successfully but had to be truncated.";\r
        case 0x80042701:        // VDS_E_NAME_NOT_UNIQUE\r
@@ -450,7 +458,7 @@ static const char *GetVdsError(DWORD error_code)
        case 0x80042918:        // VDS_E_COMPRESSION_NOT_SUPPORTED\r
                return "The specified file system does not support compression.";\r
        default:\r
-               return NULL;\r
+               return code;\r
        }\r
 }\r
 \r
@@ -537,6 +545,8 @@ const char *WindowsErrorString(DWORD error_code)
 #define INTF_ADVANCEDDISK2  2\r
 #define INTF_CREATEPARTITIONEX  3\r
 #define INTF_PARTITIONMF 4\r
+#define INTF_VOLUME 5\r
+#define INTF_VOLUME_MF3 6\r
 \r
 /* \r
  * Some code and functions in the file are copied from rufus.\r
@@ -580,6 +590,7 @@ const char *WindowsErrorString(DWORD error_code)
 #define IVdsVolume_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)\r
 #define IVdsVolume_Release(This) (This)->lpVtbl->Release(This)\r
 #define IVdsVolumeMF3_QueryVolumeGuidPathnames(This, pwszPathArray, pulNumberOfPaths) (This)->lpVtbl->QueryVolumeGuidPathnames(This,pwszPathArray,pulNumberOfPaths)\r
+#define IVdsVolumeMF_Format(This, type, pwsszLabel, dwUnitAllocationSize, bForce, bQuickFormat, bEnableCompression, ppAsync) (This)->lpVtbl->Format(This, type, pwsszLabel, dwUnitAllocationSize, bForce, bQuickFormat, bEnableCompression, ppAsync)\r
 #define IVdsVolumeMF3_FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync) (This)->lpVtbl->FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync)\r
 #define IVdsVolumeMF3_Release(This) (This)->lpVtbl->Release(This)\r
 #define IVdsVolume_GetProperties(This, pVolumeProperties) (This)->lpVtbl->GetProperties(This,pVolumeProperties)\r
@@ -588,11 +599,20 @@ const char *WindowsErrorString(DWORD error_code)
 #define IVdsAsync_Wait(This,pHrResult,pAsyncOut) (This)->lpVtbl->Wait(This,pHrResult,pAsyncOut)\r
 #define IVdsAsync_Release(This) (This)->lpVtbl->Release(This)\r
 \r
+#define IVdsVolume_Shrink(This, ullNumberOfBytesToRemove, ppAsync) (This)->lpVtbl->Shrink(This, ullNumberOfBytesToRemove, ppAsync)\r
+\r
 #define IUnknown_QueryInterface(This, a, b) (This)->lpVtbl->QueryInterface(This,a,b)\r
 #define IUnknown_Release(This) (This)->lpVtbl->Release(This)\r
 \r
 typedef BOOL(*VDS_Callback_PF)(void *pInterface, VDS_DISK_PROP *pDiskProp, UINT64 data);\r
 \r
+static BOOL g_vds_available = TRUE;\r
+\r
+BOOL VDS_IsLastAvaliable(void)\r
+{\r
+       return g_vds_available;\r
+}\r
+\r
 STATIC IVdsService * VDS_InitService(void)\r
 {\r
     HRESULT hr;\r
@@ -619,6 +639,7 @@ STATIC IVdsService * VDS_InitService(void)
     {\r
         VDS_SET_ERROR(hr);\r
         Log("Could not load VDS Service: 0x%x", LASTERR);\r
+               g_vds_available = FALSE;\r
         return NULL;\r
     }\r
 \r
@@ -632,9 +653,166 @@ STATIC IVdsService * VDS_InitService(void)
     }\r
 \r
     Log("VDS init OK, service %p", pService);\r
+       g_vds_available = TRUE;\r
     return pService;\r
 }\r
 \r
+STATIC BOOL VDS_VolumeCommProc(int intf, const WCHAR* wVolumeGuid, VDS_Callback_PF callback, UINT64 data)\r
+{\r
+       int Pos = 0;\r
+       BOOL Find = FALSE;\r
+       BOOL r = FALSE;\r
+       HRESULT hr;\r
+       ULONG ulFetched;\r
+       IUnknown* pUnk = NULL;\r
+       IEnumVdsObject* pEnum = NULL;\r
+       IVdsService* pService = NULL;\r
+\r
+       pService = VDS_InitService();\r
+       if (!pService)\r
+       {\r
+               Log("Could not query VDS Service");\r
+               goto out;\r
+       }\r
+\r
+       // Query the VDS Service Providers\r
+       hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);\r
+       if (hr != S_OK)\r
+       {\r
+               VDS_SET_ERROR(hr);\r
+               Log("Could not query VDS Service Providers: 0x%lx %u", hr, LASTERR);\r
+               goto out;\r
+       }\r
+\r
+       while (IEnumVdsObject_Next(pEnum, 1, &pUnk, &ulFetched) == S_OK)\r
+       {\r
+               IVdsProvider* pProvider;\r
+               IVdsSwProvider* pSwProvider;\r
+               IEnumVdsObject* pEnumPack;\r
+               IUnknown* pPackUnk;\r
+\r
+               // Get VDS Provider\r
+               hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void**)&pProvider);\r
+               IUnknown_Release(pUnk);\r
+               if (hr != S_OK)\r
+               {\r
+                       VDS_SET_ERROR(hr);\r
+                       Log("Could not get VDS Provider: %u", LASTERR);\r
+                       goto out;\r
+               }\r
+\r
+               // Get VDS Software Provider\r
+               hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void**)&pSwProvider);\r
+               IVdsProvider_Release(pProvider);\r
+               if (hr != S_OK)\r
+               {\r
+                       VDS_SET_ERROR(hr);\r
+                       Log("Could not get VDS Software Provider: %u", LASTERR);\r
+                       goto out;\r
+               }\r
+\r
+               // Get VDS Software Provider Packs\r
+               hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack);\r
+               IVdsSwProvider_Release(pSwProvider);\r
+               if (hr != S_OK)\r
+               {\r
+                       VDS_SET_ERROR(hr);\r
+                       Log("Could not get VDS Software Provider Packs: %u", LASTERR);\r
+                       goto out;\r
+               }\r
+\r
+               // Enumerate Provider Packs\r
+               while (IEnumVdsObject_Next(pEnumPack, 1, &pPackUnk, &ulFetched) == S_OK)\r
+               {\r
+                       IVdsPack* pPack;\r
+                       IEnumVdsObject* pEnumVolume;\r
+                       IUnknown* pVolumeUnk;\r
+\r
+                       hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void**)&pPack);\r
+                       IUnknown_Release(pPackUnk);\r
+                       if (hr != S_OK)\r
+                       {\r
+                               VDS_SET_ERROR(hr);\r
+                               Log("Could not query VDS Software Provider Pack: %u", LASTERR);\r
+                               goto out;\r
+                       }\r
+\r
+                       // Use the pack interface to access the volume\r
+                       hr = IVdsPack_QueryVolumes(pPack, &pEnumVolume);;\r
+                       if (hr != S_OK) {\r
+                               VDS_SET_ERROR(hr);\r
+                               Log("Could not query VDS volume: %u", LASTERR);\r
+                               goto out;\r
+                       }\r
+\r
+                       // List disks\r
+                       while (IEnumVdsObject_Next(pEnumVolume, 1, &pVolumeUnk, &ulFetched) == S_OK)\r
+                       {\r
+                               IVdsVolume* pVolume;\r
+                               IVdsVolumeMF3* pVolumeMF3;\r
+                               LPWSTR* wszPathArray;\r
+                               ULONG ulNumberOfPaths;\r
+\r
+                               // Get the disk interface.\r
+                               hr = IUnknown_QueryInterface(pVolumeUnk, &IID_IVdsVolumeMF3, (void**)&pVolumeMF3);\r
+                               if (hr != S_OK) {\r
+                                       VDS_SET_ERROR(hr);\r
+                                       Log("Could not query VDS Volume Interface: %u", LASTERR);\r
+                                       goto out;\r
+                               }\r
+\r
+                               // Get the volume properties\r
+                               hr = IVdsVolumeMF3_QueryVolumeGuidPathnames(pVolumeMF3, &wszPathArray, &ulNumberOfPaths);\r
+                               if ((hr != S_OK) && (hr != VDS_S_PROPERTIES_INCOMPLETE)) \r
+                               {\r
+                                       Log("Could not query VDS VolumeMF3 GUID PathNames: %s", GetVdsError(hr));\r
+                                       IVdsVolume_Release(pVolumeMF3);\r
+                                       IUnknown_Release(pVolumeUnk);\r
+                                       continue;\r
+                               }\r
+\r
+                               Log("Get Volume %d %lu <%S>", intf, ulNumberOfPaths, wszPathArray[0]);\r
+\r
+                               if ((ulNumberOfPaths >= 1) && wcsstr(wszPathArray[0], wVolumeGuid))\r
+                               {\r
+                                       Find = TRUE;\r
+                                       Log("Call back for this Volume %d <%S>", intf, wVolumeGuid);\r
+\r
+                                       if (INTF_VOLUME_MF3 == intf)\r
+                                       {\r
+                                               r = callback(pVolumeMF3, NULL, data);\r
+                                       }\r
+                                       else if (INTF_VOLUME == intf)\r
+                                       {\r
+                                               // Get the disk interface.\r
+                                               hr = IUnknown_QueryInterface(pVolumeUnk, &IID_IVdsVolume, (void**)&pVolume);\r
+                                               if (hr != S_OK) {\r
+                                                       VDS_SET_ERROR(hr);\r
+                                                       Log("Could not query VDS Volume Interface: %u", LASTERR);\r
+                                               }\r
+                                               else {\r
+                                                       r = callback(pVolume, NULL, data);\r
+                                                       IVdsVolume_Release(pVolume);\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               CoTaskMemFree(wszPathArray);\r
+                               IVdsVolume_Release(pVolumeMF3);\r
+                               IUnknown_Release(pVolumeUnk);\r
+\r
+                               if (Find)\r
+                               {\r
+                                       goto out;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+out:\r
+       return r;\r
+}\r
+\r
 \r
 STATIC BOOL VDS_DiskCommProc(int intf, int DriveIndex, VDS_Callback_PF callback, UINT64 data)\r
 {\r
@@ -897,16 +1075,16 @@ STATIC BOOL VDS_CallBack_DeletePartition(void *pInterface, VDS_DISK_PROP *pDiskP
     HRESULT hr;\r
     VDS_PARTITION_PROP* prop_array = NULL;\r
     LONG i, prop_array_size;\r
-    ULONG PartNumber = (ULONG)data;\r
+    UINT64 PartOffset = data;\r
        IVdsAdvancedDisk *pAdvancedDisk = (IVdsAdvancedDisk *)pInterface;\r
 \r
-    if (PartNumber == 0)\r
+       if (PartOffset == 0)\r
     {\r
         Log("Deleting ALL partitions from disk '%S':", pDiskProp->pwszName);\r
     }\r
     else\r
     {\r
-               Log("Deleting partition(%ld) from disk '%S':", PartNumber, pDiskProp->pwszName);\r
+               Log("Deleting partition(offset=%llu) from disk '%S':", PartOffset, pDiskProp->pwszName);\r
     }\r
 \r
     // Query the partition data, so we can get the start offset, which we need for deletion\r
@@ -916,7 +1094,7 @@ STATIC BOOL VDS_CallBack_DeletePartition(void *pInterface, VDS_DISK_PROP *pDiskP
                r = TRUE;\r
         for (i = 0; i < prop_array_size; i++) \r
         {\r
-            if (PartNumber == 0 || PartNumber == prop_array[i].ulPartitionNumber)\r
+                       if (PartOffset == 0 || PartOffset == prop_array[i].ullOffset)\r
             {\r
                 Log("* Partition %d (offset: %lld, size: %llu) delete it.",\r
                     prop_array[i].ulPartitionNumber, prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize);\r
@@ -963,9 +1141,9 @@ BOOL VDS_DeleteAllPartitions(int DriveIndex)
     return ret;\r
 }\r
 \r
-BOOL VDS_DeleteVtoyEFIPartition(int DriveIndex)\r
+BOOL VDS_DeleteVtoyEFIPartition(int DriveIndex, UINT64 EfiPartOffset)\r
 {\r
-       BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_DeletePartition, 2);\r
+       BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_DeletePartition, EfiPartOffset);\r
        Log("VDS_DeleteVtoyEFIPartition %d ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");\r
     return ret;\r
 }\r
@@ -974,6 +1152,7 @@ STATIC BOOL VDS_CallBack_ChangeEFIAttr(void *pInterface, VDS_DISK_PROP *pDiskPro
 {\r
     BOOL r = FALSE;\r
     HRESULT hr;\r
+       VDS_PARA *VdsPara = (VDS_PARA *)data;\r
     VDS_PARTITION_PROP* prop_array = NULL;\r
     LONG i, prop_array_size;\r
     CHANGE_ATTRIBUTES_PARAMETERS AttrPara;\r
@@ -987,12 +1166,13 @@ STATIC BOOL VDS_CallBack_ChangeEFIAttr(void *pInterface, VDS_DISK_PROP *pDiskPro
         {\r
             if (prop_array[i].ullSize == VENTOY_EFI_PART_SIZE &&\r
                 prop_array[i].PartitionStyle == VDS_PST_GPT &&\r
-                memcmp(prop_array[i].Gpt.name, L"VTOYEFI", 7 * 2) == 0)\r
+                memcmp(prop_array[i].Gpt.name, L"VTOYEFI", 7 * 2) == 0 &&\r
+                               VdsPara->Offset == prop_array[i].ullOffset)\r
             {\r
-                Log("* Partition %d (offset: %lld, size: %llu, Attr:0x%llx)", prop_array[i].ulPartitionNumber,\r
+                Log("** Partition %d (offset: %lld, size: %llu, Attr:0x%llx)", prop_array[i].ulPartitionNumber,\r
                     prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize, prop_array[i].Gpt.attributes);\r
 \r
-                if (prop_array[i].Gpt.attributes == data)\r
+                               if (prop_array[i].Gpt.attributes == VdsPara->Attr)\r
                 {\r
                     Log("Attribute match, No need to change.");\r
                     r = TRUE;\r
@@ -1000,7 +1180,7 @@ STATIC BOOL VDS_CallBack_ChangeEFIAttr(void *pInterface, VDS_DISK_PROP *pDiskPro
                 else\r
                 {\r
                     AttrPara.style = VDS_PST_GPT;\r
-                    AttrPara.GptPartInfo.attributes = data;\r
+                                       AttrPara.GptPartInfo.attributes = VdsPara->Attr;\r
                     hr = IVdsAdvancedDisk_ChangeAttributes(pAdvancedDisk, prop_array[i].ullOffset, &AttrPara);\r
                     if (hr == S_OK)\r
                     {\r
@@ -1027,10 +1207,15 @@ STATIC BOOL VDS_CallBack_ChangeEFIAttr(void *pInterface, VDS_DISK_PROP *pDiskPro
     return r;\r
 }\r
 \r
-BOOL VDS_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Attr)\r
+BOOL VDS_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Offset, UINT64 Attr)\r
 {\r
-       BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_ChangeEFIAttr, Attr);    \r
-       Log("VDS_ChangeVtoyEFIAttr %d ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");\r
+       VDS_PARA Para;\r
+\r
+       Para.Attr = Attr;\r
+       Para.Offset = Offset;\r
+\r
+       BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_ChangeEFIAttr, (UINT64)&Para);\r
+       Log("VDS_ChangeVtoyEFIAttr %d (offset:%llu) ret:%d (%s)", DriveIndex, Offset, ret, ret ? "SUCCESS" : "FAIL");\r
     return ret;\r
 }\r
 \r
@@ -1041,7 +1226,7 @@ STATIC BOOL VDS_CallBack_ChangeEFIType(void *pInterface, VDS_DISK_PROP *pDiskPro
        BOOL r = FALSE;\r
        HRESULT hr;\r
        IVdsAdvancedDisk2 *pAdvancedDisk2 = (IVdsAdvancedDisk2 *)pInterface;\r
-       VDS_PARA *VdsPara = (VDS_PARA *)(ULONG)data;\r
+       VDS_PARA *VdsPara = (VDS_PARA *)data;\r
        CHANGE_PARTITION_TYPE_PARAMETERS para;\r
 \r
        para.style = VDS_PST_GPT;\r
@@ -1069,11 +1254,12 @@ BOOL VDS_ChangeVtoyEFI2ESP(int DriveIndex, UINT64 Offset)
        memcpy(&(Para.Type), &EspPartType, sizeof(GUID));\r
        Para.Offset = Offset;\r
 \r
-       BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK2, DriveIndex, VDS_CallBack_ChangeEFIType, (ULONG)&Para);\r
+       BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK2, DriveIndex, VDS_CallBack_ChangeEFIType, (UINT64)&Para);\r
        Log("VDS_ChangeVtoyEFI2ESP %d ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");\r
        return ret;\r
 }\r
 \r
+\r
 BOOL VDS_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset)\r
 {\r
        VDS_PARA Para;\r
@@ -1082,98 +1268,169 @@ BOOL VDS_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset)
        memcpy(&(Para.Type), &WindowsDataPartType, sizeof(GUID));\r
        Para.Offset = Offset;\r
 \r
-       BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK2, DriveIndex, VDS_CallBack_ChangeEFIType, (ULONG)&Para);\r
+       BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK2, DriveIndex, VDS_CallBack_ChangeEFIType, (UINT64)&Para);\r
        Log("VDS_ChangeVtoyEFI2Basic %d ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");\r
        return ret;\r
 }\r
 \r
+STATIC BOOL CHKDSK_Volume(CHAR LogicalDrive)\r
+{\r
+       CHAR CmdBuf[1024];\r
+       STARTUPINFOA Si;\r
+       PROCESS_INFORMATION Pi;\r
 \r
-STATIC BOOL VDS_CallBack_CreateVtoyEFI(void *pInterface, VDS_DISK_PROP *pDiskProp, UINT64 data)\r
+       if ((!IsFileExist("C:\\Windows\\System32\\chkdsk.exe")) || (LogicalDrive == 0))\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       GetStartupInfoA(&Si);\r
+       Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+       Si.wShowWindow = SW_HIDE;\r
+\r
+       sprintf_s(CmdBuf, sizeof(CmdBuf), "C:\\Windows\\System32\\chkdsk.exe %C: /f", LogicalDrive);\r
+\r
+       Log("CreateProcess <%s>", CmdBuf);\r
+       CreateProcessA(NULL, CmdBuf, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+\r
+       Log("Wair process ...");\r
+       WaitForSingleObject(Pi.hProcess, INFINITE);\r
+       Log("Process finished...");\r
+\r
+       CHECK_CLOSE_HANDLE(Pi.hProcess);\r
+       CHECK_CLOSE_HANDLE(Pi.hThread);\r
+\r
+       return TRUE;\r
+}\r
+\r
+STATIC HRESULT VDS_RealShrinkVolume(void* pInterface, VDS_DISK_PROP* pDiskProp, UINT64 data)\r
 {\r
-    HRESULT hr, hr2;\r
-    ULONG completed;\r
-    IVdsAsync* pAsync;\r
-       CREATE_PARTITION_PARAMETERS para;\r
-       IVdsCreatePartitionEx *pCreatePartitionEx = (IVdsCreatePartitionEx *)pInterface;\r
-    VDS_PARA *VdsPara = (VDS_PARA *)(ULONG)data;\r
+       HRESULT hr, hr2;\r
+       IVdsVolume* pVolume = (IVdsVolume*)pInterface;\r
+       ULONG completed;\r
+       IVdsAsync* pAsync;\r
+       VDS_PARA* VdsPara = (VDS_PARA*)data;\r
 \r
-    (void)pDiskProp;\r
+       (void)pDiskProp;\r
 \r
-    memset(&para, 0, sizeof(para));\r
-    para.style = VDS_PST_GPT;\r
-    memcpy(&(para.GptPartInfo.partitionType), &VdsPara->Type, sizeof(GUID));\r
-    memcpy(&(para.GptPartInfo.partitionId), &VdsPara->Id, sizeof(GUID));\r
-       para.GptPartInfo.attributes = VdsPara->Attr;\r
-       memcpy(para.GptPartInfo.name, VdsPara->Name, sizeof(WCHAR)* VdsPara->NameLen);\r
+       Log("VDS_ShrinkVolume (%C:) (%llu) ...", VdsPara->DriveLetter, (ULONGLONG)VdsPara->Offset);\r
 \r
-       hr = IVdsCreatePartitionEx_CreatePartitionEx(pCreatePartitionEx, VdsPara->Offset, VENTOY_EFI_PART_SIZE, 512, &para, &pAsync);\r
-    while (SUCCEEDED(hr))\r
-    {\r
-        hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed);\r
-        if (SUCCEEDED(hr))\r
-        {\r
-            hr = hr2;\r
-            if (hr == S_OK)\r
-            {\r
-                               Log("Disk create partition QueryStatus OK, %lu%%", completed);\r
-                break;\r
-            }\r
-            else if (hr == VDS_E_OPERATION_PENDING)\r
-            {\r
-                               Log("Disk partition finish: %lu%%", completed);\r
-                hr = S_OK;\r
-            }\r
-            else\r
-            {\r
-                Log("QueryStatus invalid status:0x%lx", hr);\r
-            }\r
-        }\r
-        Sleep(1000);\r
-    }\r
+       hr = IVdsVolume_Shrink(pVolume, (ULONGLONG)VdsPara->Offset, &pAsync);\r
 \r
-    if (hr != S_OK)\r
-    {\r
-        VDS_SET_ERROR(hr);\r
-               Log("Could not create partition, err:0x%lx(%s)", LASTERR, WindowsErrorString(hr));\r
-        return FALSE;\r
-    }\r
+       while (SUCCEEDED(hr))\r
+       {\r
+               hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed);\r
+               if (SUCCEEDED(hr))\r
+               {\r
+                       hr = hr2;\r
+                       if (hr == S_OK)\r
+                       {\r
+                               Log("ShrinkVolume QueryStatus OK, %lu%%", completed);\r
+                               break;\r
+                       }\r
+                       else if (hr == VDS_E_OPERATION_PENDING)\r
+                       {\r
+                               Log("ShrinkVolume: %lu%%", completed);\r
+                               hr = S_OK;\r
+                       }\r
+                       else\r
+                       {\r
+                               Log("ShrinkVolume invalid status:0x%lx", hr);\r
+                       }\r
+               }\r
+               Sleep(1000);\r
+       }\r
 \r
-    return TRUE;\r
+       return hr;\r
 }\r
 \r
-BOOL VDS_CreateVtoyEFIPart(int DriveIndex, UINT64 Offset)\r
+STATIC BOOL VDS_CallBack_ShrinkVolume(void* pInterface, VDS_DISK_PROP* pDiskProp, UINT64 data)\r
 {\r
-    VDS_PARA Para;\r
-    GUID WindowsDataPartType = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };\r
-       GUID EspPartType = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };\r
+       int i;\r
+       HRESULT hr;\r
+       VDS_PARA *VdsPara = (VDS_PARA *)data;\r
 \r
-       Log("VDS_CreateVtoyEFIPart %u Offset:%llu Sector:%llu", DriveIndex, Offset, Offset / 512);\r
+       Log("VDS_CallBack_ShrinkVolume (%C:) (%llu) ...", VdsPara->DriveLetter, (ULONGLONG)VdsPara->Offset);\r
 \r
-    memset(&Para, 0, sizeof(Para));\r
-    Para.Attr = 0x8000000000000000ULL;\r
-    Para.Offset = Offset;\r
-    memcpy(Para.Name, L"VTOYEFI", 7 * 2);\r
-       Para.NameLen = 7;\r
-       memcpy(&(Para.Type), &EspPartType, sizeof(GUID));\r
-    CoCreateGuid(&(Para.Id));\r
+       hr = VDS_RealShrinkVolume(pInterface, pDiskProp, data);\r
+       if (hr == VDS_E_SHRINK_DIRTY_VOLUME)\r
+       {\r
+               Log("Volume %C: is dirty, run chkdsk and retry.", VdsPara->DriveLetter);\r
+               CHKDSK_Volume(VdsPara->DriveLetter);\r
 \r
-       BOOL ret = VDS_DiskCommProc(INTF_CREATEPARTITIONEX, DriveIndex, VDS_CallBack_CreateVtoyEFI, (ULONG)&Para);    \r
-       Log("VDS_CreateVtoyEFIPart %d ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");\r
-    return ret; \r
+               hr = VDS_RealShrinkVolume(pInterface, pDiskProp, data);\r
+               if (hr == VDS_E_SHRINK_DIRTY_VOLUME)\r
+               {\r
+                       Log("################################################################");\r
+                       Log("################################################################");\r
+                       for (i = 0; i < 20; i++)\r
+                       {\r
+                               Log("###### Volume dirty, Please run \"chkdsk /f %C:\" and retry. ######", VdsPara->Name[0]);\r
+                       }\r
+                       Log("################################################################");\r
+                       Log("################################################################");\r
+               }\r
+       }\r
+\r
+       if (hr != S_OK)\r
+       {\r
+               VDS_SET_ERROR(hr);\r
+               Log("Could not ShrinkVolume, 0x%x err:0x%lx (%s)", hr, LASTERR, WindowsErrorString(hr));\r
+\r
+               VDS_SET_ERROR(hr);\r
+               return FALSE;\r
+       }\r
+\r
+       return TRUE;\r
 }\r
 \r
+BOOL VDS_ShrinkVolume(int DriveIndex, const char* VolumeGuid, CHAR DriveLetter, UINT64 OldBytes, UINT64 ReduceBytes)\r
+{\r
+       int i;\r
+       BOOL ret = FALSE;\r
+       WCHAR wGuid[128] = { 0 };\r
+       const char *guid = NULL;\r
+       VDS_PARA Para;\r
+\r
+       (VOID)DriveIndex;\r
+       (VOID)OldBytes;\r
+\r
+       guid = strstr(VolumeGuid, "{");\r
+       if (!guid)\r
+       {\r
+               return FALSE;\r
+       }\r
+\r
+       for (i = 0; i < 128 && guid[i]; i++)\r
+       {\r
+               wGuid[i] = guid[i];\r
+       }\r
+\r
+       Para.Offset = ReduceBytes;\r
+       Para.DriveLetter = DriveLetter;\r
 \r
-STATIC BOOL VDS_CallBack_FormatVtoyEFI(void *pInterface, VDS_DISK_PROP *pDiskProp, UINT64 data)\r
+       ret = VDS_VolumeCommProc(INTF_VOLUME, wGuid, VDS_CallBack_ShrinkVolume, (UINT64)&Para);\r
+       Log("VDS_ShrinkVolume %C: ret:%d (%s)", DriveLetter, ret, ret ? "SUCCESS" : "FAIL");\r
+       return ret;\r
+}\r
+\r
+\r
+STATIC BOOL VDS_CallBack_FormatVolume(void* pInterface, VDS_DISK_PROP* pDiskProp, UINT64 data)\r
 {\r
+       int fs;\r
        HRESULT hr, hr2;\r
        ULONG completed;\r
-       IVdsAsync* pAsync;      \r
-       IVdsDiskPartitionMF *pPartitionMF = (IVdsDiskPartitionMF *)pInterface;\r
-       VDS_PARA *VdsPara = (VDS_PARA *)(ULONG)data;\r
-\r
-       (void)pDiskProp;\r
+       IVdsAsync* pAsync;\r
+       IVdsVolumeMF3* pVolume = (IVdsVolumeMF3*)pInterface;\r
+       WCHAR* pFs = NULL;\r
+       VDS_PARA* VdsPara = (VDS_PARA*)data;\r
        \r
-       hr = IVdsPartitionMF_FormatPartitionEx(pPartitionMF, VdsPara->Offset, L"FAT", 0x0100, 0, VdsPara->Name, TRUE, TRUE, FALSE, &pAsync);\r
+       fs = (int)VdsPara->Attr;\r
+       pFs = GetVentoyFsFmtNameByTypeW(fs);\r
+       \r
+       Log("VDS_CallBack_FormatVolume (%C:) (%s) ClusterSize:%u ...", VdsPara->DriveLetter, GetVentoyFsFmtNameByTypeA(fs), VdsPara->ClusterSize);\r
+\r
+       hr = IVdsVolumeMF3_FormatEx2(pVolume, pFs, 0, VdsPara->ClusterSize, L"Ventoy", VDS_FSOF_FORCE | VDS_FSOF_QUICK, &pAsync);\r
        while (SUCCEEDED(hr))\r
        {\r
                hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed);\r
@@ -1182,17 +1439,17 @@ STATIC BOOL VDS_CallBack_FormatVtoyEFI(void *pInterface, VDS_DISK_PROP *pDiskPro
                        hr = hr2;\r
                        if (hr == S_OK)\r
                        {\r
-                               Log("Disk format partition QueryStatus OK, %lu%%", completed);\r
+                               Log("FormatVolume QueryStatus OK, %lu%%", completed);\r
                                break;\r
                        }\r
                        else if (hr == VDS_E_OPERATION_PENDING)\r
                        {\r
-                               Log("Disk format finish: %lu%%", completed);\r
+                               Log("FormatVolume: %lu%%", completed);\r
                                hr = S_OK;\r
                        }\r
                        else\r
                        {\r
-                               Log("QueryStatus invalid status:0x%lx", hr);\r
+                               Log("FormatVolume invalid status:0x%lx", hr);\r
                        }\r
                }\r
                Sleep(1000);\r
@@ -1201,24 +1458,48 @@ STATIC BOOL VDS_CallBack_FormatVtoyEFI(void *pInterface, VDS_DISK_PROP *pDiskPro
        if (hr != S_OK)\r
        {\r
                VDS_SET_ERROR(hr);\r
-               Log("Could not format partition, err:0x%lx (%s)", LASTERR, WindowsErrorString(hr));\r
+               Log("Could not FormatVolume, 0x%x err:0x%lx (%s)", hr, LASTERR, WindowsErrorString(hr));\r
+\r
+               VDS_SET_ERROR(hr);\r
                return FALSE;\r
        }\r
 \r
        return TRUE;\r
 }\r
-\r
-// Not supported for removable disk\r
-BOOL VDS_FormatVtoyEFIPart(int DriveIndex, UINT64 Offset)\r
+BOOL VDS_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize)\r
 {\r
+       int i;\r
+       BOOL ret = FALSE;\r
+       const char* guid = NULL;\r
+       CHAR Drive[32] = { 0 };\r
+       WCHAR wGuid[128] = { 0 };\r
+       CHAR VolumeGuid[128] = { 0 };\r
        VDS_PARA Para;\r
 \r
-       memset(&Para, 0, sizeof(Para));\r
-       Para.Offset = Offset;\r
-       memcpy(Para.Name, L"VTOYEFI", 7 * 2);\r
+       Drive[0] = DriveLetter;\r
+       Drive[1] = ':';\r
+       Drive[2] = '\\';\r
+       GetVolumeNameForVolumeMountPointA(Drive, VolumeGuid, sizeof(VolumeGuid) / 2);\r
+\r
+       guid = strstr(VolumeGuid, "{");\r
+       if (!guid)\r
+       {\r
+               Log("Can not find volume GUID for %s:", Drive);\r
+               return FALSE;\r
+       }\r
+\r
+       for (i = 0; i < 128 && guid[i]; i++)\r
+       {\r
+               wGuid[i] = guid[i];\r
+       }\r
+       Log("VDS_FormatVolume find GUID %C: <%s> ", DriveLetter, VolumeGuid);\r
+\r
+       Para.Attr = fs;\r
+       Para.DriveLetter = DriveLetter;\r
+       Para.ClusterSize = ClusterSize;\r
+\r
+       ret = VDS_VolumeCommProc(INTF_VOLUME_MF3, wGuid, VDS_CallBack_FormatVolume, (UINT64)&Para);\r
+       Log("VDS_FormatVolume %C: <%s> ret:%d (%s)", DriveLetter, VolumeGuid, ret, ret ? "SUCCESS" : "FAIL");\r
 \r
-       BOOL ret = VDS_DiskCommProc(INTF_PARTITIONMF, DriveIndex, VDS_CallBack_FormatVtoyEFI, (ULONG)&Para);    \r
-       Log("VDS_FormatVtoyEFIPart %d ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");\r
        return ret;\r
 }\r
-\r