+/******************************************************************************\r
+ * DiskService_vds.c\r
+ *\r
+ * Copyright (c) 2021, 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 <winternl.h>\r
+#include <commctrl.h>\r
+#include <initguid.h>\r
+#include <vds.h>\r
+#include "Ventoy2Disk.h"\r
+#include "DiskService.h"\r
+\r
+\r
+#define INTF_ADVANCEDDISK 1\r
+#define INTF_ADVANCEDDISK2 2\r
+#define INTF_CREATEPARTITIONEX 3\r
+\r
+/* \r
+ * Some code and functions in the file are copied from rufus.\r
+ * https://github.com/pbatard/rufus\r
+ */\r
+#define VDS_SET_ERROR SetLastError\r
+#define IVdsServiceLoader_LoadService(This, pwszMachineName, ppService) (This)->lpVtbl->LoadService(This, pwszMachineName, ppService)\r
+#define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This)\r
+#define IVdsService_QueryProviders(This, masks, ppEnum) (This)->lpVtbl->QueryProviders(This, masks, ppEnum)\r
+#define IVdsService_WaitForServiceReady(This) ((This)->lpVtbl->WaitForServiceReady(This))\r
+#define IVdsService_CleanupObsoleteMountPoints(This) ((This)->lpVtbl->CleanupObsoleteMountPoints(This))\r
+#define IVdsService_Refresh(This) ((This)->lpVtbl->Refresh(This))\r
+#define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This)) \r
+#define IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)\r
+#define IVdsProvider_Release(This) (This)->lpVtbl->Release(This)\r
+#define IVdsSwProvider_QueryPacks(This, ppEnum) (This)->lpVtbl->QueryPacks(This, ppEnum)\r
+#define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This)\r
+#define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum)\r
+#define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties)\r
+#define IVdsDisk_Release(This) (This)->lpVtbl->Release(This)\r
+#define IVdsDisk_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)\r
+#define IVdsAdvancedDisk_QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions) (This)->lpVtbl->QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions)\r
+#define IVdsAdvancedDisk_DeletePartition(This, ullOffset, bForce, bForceProtected) (This)->lpVtbl->DeletePartition(This, ullOffset, bForce, bForceProtected)\r
+#define IVdsAdvancedDisk_ChangeAttributes(This, ullOffset, para) (This)->lpVtbl->ChangeAttributes(This, ullOffset, para)\r
+#define IVdsAdvancedDisk_CreatePartition(This, ullOffset, ullSize, para, ppAsync) (This)->lpVtbl->CreatePartition(This, ullOffset, ullSize, para, ppAsync)\r
+#define IVdsAdvancedDisk_Clean(This, bForce, bForceOEM, bFullClean, ppAsync) (This)->lpVtbl->Clean(This, bForce, bForceOEM, bFullClean, ppAsync)\r
+#define IVdsAdvancedDisk_Release(This) (This)->lpVtbl->Release(This)\r
+\r
+#define IVdsAdvancedDisk2_ChangePartitionType(This, ullOffset, bForce, para) (This)->lpVtbl->ChangePartitionType(This, ullOffset, bForce, para)\r
+#define IVdsAdvancedDisk2_Release(This) (This)->lpVtbl->Release(This)\r
+\r
+#define IVdsCreatePartitionEx_CreatePartitionEx(This, ullOffset, ullSize, ulAlign, para, ppAsync) (This)->lpVtbl->CreatePartitionEx(This, ullOffset, ullSize, ulAlign, para, ppAsync)\r
+#define IVdsCreatePartitionEx_Release(This) (This)->lpVtbl->Release(This)\r
+#define IEnumVdsObject_Next(This, celt, ppObjectArray, pcFetched) (This)->lpVtbl->Next(This, celt, ppObjectArray, pcFetched)\r
+#define IVdsPack_QueryVolumes(This, ppEnum) (This)->lpVtbl->QueryVolumes(This, ppEnum)\r
+#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 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
+#define IVdsAsync_Cancel(This) (This)->lpVtbl->Cancel(This)\r
+#define IVdsAsync_QueryStatus(This,pHrResult,pulPercentCompleted) (This)->lpVtbl->QueryStatus(This,pHrResult,pulPercentCompleted)\r
+#define IVdsAsync_Wait(This,pHrResult,pAsyncOut) (This)->lpVtbl->Wait(This,pHrResult,pAsyncOut)\r
+#define IVdsAsync_Release(This) (This)->lpVtbl->Release(This)\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 IVdsService * VDS_InitService(void)\r
+{\r
+ HRESULT hr;\r
+ IVdsServiceLoader *pLoader;\r
+ IVdsService *pService;\r
+\r
+ // Initialize COM\r
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);\r
+ CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL);\r
+\r
+ // Create a VDS Loader Instance\r
+ hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, &IID_IVdsServiceLoader, (void **)&pLoader);\r
+ if (hr != S_OK) \r
+ {\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not create VDS Loader Instance: %u", LASTERR);\r
+ return NULL;\r
+ }\r
+\r
+ // Load the VDS Service\r
+ hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService);\r
+ IVdsServiceLoader_Release(pLoader);\r
+ if (hr != S_OK) \r
+ {\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not load VDS Service: %u", LASTERR);\r
+ return NULL;\r
+ }\r
+\r
+ // Wait for the Service to become ready if needed\r
+ hr = IVdsService_WaitForServiceReady(pService);\r
+ if (hr != S_OK) \r
+ {\r
+ VDS_SET_ERROR(hr);\r
+ Log("VDS Service is not ready: %u", LASTERR);\r
+ return NULL;\r
+ }\r
+\r
+ Log("VDS init OK, service %p", pService);\r
+ return pService;\r
+}\r
+\r
+\r
+STATIC BOOL VDS_DiskCommProc(int intf, int DriveIndex, VDS_Callback_PF callback, UINT64 data)\r
+{\r
+ BOOL r = FALSE;\r
+ HRESULT hr;\r
+ ULONG ulFetched;\r
+ IUnknown *pUnk = NULL;\r
+ IEnumVdsObject *pEnum = NULL; \r
+ IVdsService *pService = NULL;\r
+ wchar_t wPhysicalName[48];\r
+\r
+ swprintf_s(wPhysicalName, ARRAYSIZE(wPhysicalName), L"\\\\?\\PhysicalDrive%d", DriveIndex);\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 *pEnumDisk;\r
+ IUnknown *pDiskUnk;\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 disks\r
+ hr = IVdsPack_QueryDisks(pPack, &pEnumDisk);\r
+ if (hr != S_OK) {\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not query VDS disks: %u", LASTERR);\r
+ goto out;\r
+ }\r
+\r
+ // List disks\r
+ while (IEnumVdsObject_Next(pEnumDisk, 1, &pDiskUnk, &ulFetched) == S_OK) \r
+ {\r
+ VDS_DISK_PROP diskprop;\r
+ IVdsDisk *pDisk;\r
+ IVdsAdvancedDisk *pAdvancedDisk;\r
+ IVdsAdvancedDisk2 *pAdvancedDisk2;\r
+ IVdsCreatePartitionEx *pCreatePartitionEx;\r
+\r
+ // Get the disk interface.\r
+ hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk);\r
+ if (hr != S_OK) {\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not query VDS Disk Interface: %u", LASTERR);\r
+ goto out;\r
+ }\r
+\r
+ // Get the disk properties\r
+ hr = IVdsDisk_GetProperties(pDisk, &diskprop);\r
+ if (hr != S_OK) {\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not query VDS Disk Properties: %u", LASTERR);\r
+ goto out;\r
+ }\r
+\r
+ // Isolate the disk we want\r
+ if (_wcsicmp(wPhysicalName, diskprop.pwszName) != 0) \r
+ {\r
+ IVdsDisk_Release(pDisk);\r
+ continue;\r
+ }\r
+\r
+ if (intf == INTF_ADVANCEDDISK)\r
+ {\r
+ // Instantiate the AdvanceDisk interface for our disk.\r
+ hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk);\r
+ IVdsDisk_Release(pDisk);\r
+ if (hr != S_OK)\r
+ {\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not access VDS Advanced Disk interface: %u", LASTERR);\r
+ goto out;\r
+ }\r
+ else\r
+ {\r
+ Log("Callback %d process for disk <%S>", intf, diskprop.pwszName);\r
+ r = callback(pAdvancedDisk, &diskprop, data);\r
+ }\r
+ IVdsAdvancedDisk_Release(pAdvancedDisk);\r
+ }\r
+ else if (intf == INTF_ADVANCEDDISK2)\r
+ {\r
+ // Instantiate the AdvanceDisk interface for our disk.\r
+ hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk2, (void **)&pAdvancedDisk2);\r
+ IVdsDisk_Release(pDisk);\r
+ if (hr != S_OK)\r
+ {\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not access VDS Advanced Disk2 interface: %u", LASTERR);\r
+ goto out;\r
+ }\r
+ else\r
+ {\r
+ Log("Callback %d process for disk2 <%S>", intf, diskprop.pwszName);\r
+ r = callback(pAdvancedDisk2, &diskprop, data);\r
+ }\r
+ IVdsAdvancedDisk2_Release(pAdvancedDisk2);\r
+ }\r
+ else if (intf == INTF_CREATEPARTITIONEX)\r
+ {\r
+ // Instantiate the CreatePartitionEx interface for our disk.\r
+ hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsCreatePartitionEx, (void **)&pCreatePartitionEx);\r
+ IVdsDisk_Release(pDisk);\r
+ if (hr != S_OK)\r
+ {\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not access VDS CreatePartitionEx interface: %u", LASTERR);\r
+ goto out;\r
+ }\r
+ else\r
+ {\r
+ Log("Callback %d process for disk <%S>", intf, diskprop.pwszName);\r
+ r = callback(pCreatePartitionEx, &diskprop, data);\r
+ }\r
+ IVdsCreatePartitionEx_Release(pCreatePartitionEx);\r
+ }\r
+\r
+ goto out;\r
+ }\r
+ }\r
+ }\r
+\r
+out:\r
+ return r;\r
+}\r
+\r
+STATIC BOOL VDS_CallBack_CleanDisk(void *pInterface, VDS_DISK_PROP *pDiskProp, UINT64 data)\r
+{ \r
+ HRESULT hr, hr2;\r
+ ULONG completed;\r
+ IVdsAsync* pAsync;\r
+ IVdsAdvancedDisk *pAdvancedDisk = (IVdsAdvancedDisk *)pInterface;\r
+\r
+ (void)pDiskProp;\r
+ (void)data;\r
+\r
+ hr = IVdsAdvancedDisk_Clean(pAdvancedDisk, TRUE, TRUE, FALSE, &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 clean QueryStatus OK");\r
+ break;\r
+ }\r
+ else if (hr == VDS_E_OPERATION_PENDING)\r
+ {\r
+ hr = S_OK;\r
+ }\r
+ else\r
+ {\r
+ Log("QueryStatus invalid status:%u", hr);\r
+ }\r
+ }\r
+ Sleep(500);\r
+ }\r
+\r
+ if (hr != S_OK) \r
+ {\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not clean disk 0x%lx err:%u", hr, LASTERR);\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+BOOL VDS_CleanDisk(int DriveIndex)\r
+{\r
+ BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_CleanDisk, 0);\r
+ Log("VDS_CleanDisk %d ret:%d", DriveIndex, ret);\r
+ return ret;\r
+}\r
+\r
+STATIC BOOL VDS_CallBack_DeletePartition(void *pInterface, VDS_DISK_PROP *pDiskProp, UINT64 data)\r
+{\r
+ BOOL r = FALSE;\r
+ HRESULT hr;\r
+ VDS_PARTITION_PROP* prop_array = NULL;\r
+ LONG i, prop_array_size;\r
+ ULONG PartNumber = (ULONG)data;\r
+ IVdsAdvancedDisk *pAdvancedDisk = (IVdsAdvancedDisk *)pInterface;\r
+\r
+ if (PartNumber == 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
+ }\r
+\r
+ // Query the partition data, so we can get the start offset, which we need for deletion\r
+ hr = IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk, &prop_array, &prop_array_size);\r
+ if (hr == S_OK) \r
+ {\r
+ for (i = 0; i < prop_array_size; i++) \r
+ {\r
+ if (PartNumber == 0 || PartNumber == prop_array[i].ulPartitionNumber)\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
+ }\r
+ else\r
+ {\r
+ Log(" Partition %d (offset: %lld, size: %llu) skip it.",\r
+ prop_array[i].ulPartitionNumber, prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize);\r
+ continue;\r
+ }\r
+\r
+ hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE);\r
+ if (hr != S_OK) \r
+ {\r
+ r = FALSE;\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not delete partitions: %u", LASTERR);\r
+ }\r
+ else \r
+ {\r
+ Log("Delete this partitions success");\r
+ }\r
+ }\r
+ r = TRUE;\r
+ }\r
+ else \r
+ {\r
+ Log("No partition to delete on disk '%S'", pDiskProp->pwszName);\r
+ r = TRUE;\r
+ }\r
+ CoTaskMemFree(prop_array);\r
+\r
+ return r;\r
+}\r
+\r
+BOOL VDS_DeleteAllPartitions(int DriveIndex)\r
+{\r
+ BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_DeletePartition, 0);\r
+ Log("VDS_DeleteAllPartitions %d ret:%d", DriveIndex, ret);\r
+ return ret;\r
+}\r
+\r
+BOOL VDS_DeleteVtoyEFIPartition(int DriveIndex)\r
+{\r
+ BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_DeletePartition, 2);\r
+ Log("VDS_DeleteVtoyEFIPartition %d ret:%d", DriveIndex, ret);\r
+ return ret;\r
+}\r
+\r
+STATIC BOOL VDS_CallBack_ChangeEFIAttr(void *pInterface, VDS_DISK_PROP *pDiskProp, UINT64 data)\r
+{\r
+ BOOL r = FALSE;\r
+ HRESULT hr;\r
+ VDS_PARTITION_PROP* prop_array = NULL;\r
+ LONG i, prop_array_size;\r
+ CHANGE_ATTRIBUTES_PARAMETERS AttrPara;\r
+ IVdsAdvancedDisk *pAdvancedDisk = (IVdsAdvancedDisk *)pInterface;\r
+\r
+ // Query the partition data, so we can get the start offset, which we need for deletion\r
+ hr = IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk, &prop_array, &prop_array_size);\r
+ if (hr == S_OK)\r
+ {\r
+ for (i = 0; i < prop_array_size; i++)\r
+ {\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
+ {\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
+ {\r
+ Log("Attribute match, No need to change.");\r
+ r = TRUE;\r
+ }\r
+ else\r
+ {\r
+ AttrPara.style = VDS_PST_GPT;\r
+ AttrPara.GptPartInfo.attributes = data;\r
+ hr = IVdsAdvancedDisk_ChangeAttributes(pAdvancedDisk, prop_array[i].ullOffset, &AttrPara);\r
+ if (hr == S_OK)\r
+ {\r
+ r = TRUE;\r
+ Log("Change this partitions attribute success");\r
+ }\r
+ else\r
+ {\r
+ r = FALSE;\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not change partitions attr: %u", LASTERR);\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Log("No partition found on disk '%S'", pDiskProp->pwszName);\r
+ }\r
+ CoTaskMemFree(prop_array);\r
+\r
+ return r;\r
+}\r
+\r
+BOOL VDS_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Attr)\r
+{\r
+ BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_ChangeEFIAttr, Attr);\r
+ Log("VDS_ChangeVtoyEFIAttr %d ret:%d", DriveIndex, ret);\r
+ return ret;\r
+}\r
+\r
+\r
+\r
+STATIC BOOL VDS_CallBack_ChangeEFIType(void *pInterface, VDS_DISK_PROP *pDiskProp, UINT64 data)\r
+{\r
+ BOOL r = FALSE;\r
+ HRESULT hr;\r
+ IVdsAdvancedDisk2 *pAdvancedDisk2 = (IVdsAdvancedDisk2 *)pInterface;\r
+ VDS_PARA *VdsPara = (VDS_PARA *)(ULONG)data;\r
+ CHANGE_PARTITION_TYPE_PARAMETERS para;\r
+\r
+ para.style = VDS_PST_GPT;\r
+ memcpy(&(para.GptPartInfo.partitionType), &VdsPara->Type, sizeof(GUID));\r
+\r
+ hr = IVdsAdvancedDisk2_ChangePartitionType(pAdvancedDisk2, VdsPara->Offset, TRUE, ¶);\r
+ if (hr == S_OK)\r
+ {\r
+ r = TRUE;\r
+ }\r
+ else\r
+ {\r
+ Log("Failed to change partition type 0x%lx", hr);\r
+ }\r
+\r
+ return r;\r
+}\r
+\r
+\r
+BOOL VDS_ChangeVtoyEFI2ESP(int DriveIndex, UINT64 Offset)\r
+{\r
+ VDS_PARA Para; \r
+ GUID EspPartType = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };\r
+\r
+ 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
+ Log("VDS_ChangeVtoyEFI2ESP %d ret:%d", DriveIndex, ret);\r
+ return ret;\r
+}\r
+\r
+BOOL VDS_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset)\r
+{\r
+ VDS_PARA Para;\r
+ GUID WindowsDataPartType = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };\r
+\r
+ 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
+ Log("VDS_ChangeVtoyEFI2ESP %d ret:%d", DriveIndex, ret);\r
+ return ret;\r
+}\r
+\r
+\r
+STATIC BOOL VDS_CallBack_CreateVtoyEFI(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
+\r
+ (void)pDiskProp;\r
+\r
+ memset(¶, 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
+\r
+ hr = IVdsCreatePartitionEx_CreatePartitionEx(pCreatePartitionEx, VdsPara->Offset, VENTOY_EFI_PART_SIZE, 512, ¶, &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
+\r
+ if (hr != S_OK)\r
+ {\r
+ VDS_SET_ERROR(hr);\r
+ Log("Could not create partition, err:0x%lx", LASTERR);\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+BOOL VDS_CreateVtoyEFIPart(int DriveIndex, UINT64 Offset)\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
+\r
+ Log("VDS_CreateVtoyEFIPart %u Offset:%llu Sector:%llu", DriveIndex, Offset, Offset / 512);\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
+\r
+ BOOL ret = VDS_DiskCommProc(INTF_CREATEPARTITIONEX, DriveIndex, VDS_CallBack_CreateVtoyEFI, (ULONG)&Para);\r
+ Log("VDS_CreateVtoyEFIPart %d ret:%d", DriveIndex, ret);\r
+ return ret; \r
+}\r
+\r