winapivhdvds

Formatting a VHD Disk (or any other disk) with Vds


  1. I'm creating a virtual drive with CreateVirtualDisk.
  2. I'm attaching it with AttachVirtualDisk.
  3. I initialize it with IOCTL_DISK_CREATE_DISK for a single GPT partition.
  4. I create a single partition with IOCTL_DISK_SET_DRIVE_LAYOUT_EX.

Now I have to format it with NTFS. I can use the FormatEx described in this question but this requires a mount point.

I tried instead ot use VDS. I got a IVdsServiceLoader , I queried for VDS_QUERY_VIRTUALDISK_PROVIDERS, and I found my attached disk as IVdsDisk.

However I don't know from this point how to format it. I saw that the IVdsAdvancedDisk has the format options but I don't know how to get this interface.

Any other options? As I found out, I can't format using DeviceIoControl.


Solution

  • For anyone looking for a solution (error handling removed). The idea is to get the name from the Virtual Provider, then, when finding the same drive in the software proviver in a IVdsDisk, ask for an IVdsAdvancedDisk and perform the format.

     // Helper
    template <typename T>
    static int EnumObject(IEnumVdsObject* o,std::vector<CComPtr<T>>& res)
    {
        int n = 0;
        for (;;)
        {
            CComPtr<IUnknown> prov;
            ULONG uf = 0;
            o->Next(1, &prov, &uf);
            if (!prov)
                break;
            CComPtr<T> a;
            a = prov;
            if (!a)
                continue;
            res.push_back(a);
        }
        o->Reset();
        return n;
    }
    
     // Vds Loading
     CComPtr<IVdsServiceLoader> sl;
     CoCreateInstance(CLSID_VdsLoader, 0, CLSCTX_ALL, __uuidof(IVdsServiceLoader), 
      (void**) & sl);
     CComPtr<IVdsService> pService = NULL;
     sl->LoadService(0,&pService);
     pService->WaitForServiceReady();
    
     // Enum providers
     CComPtr<IEnumVdsObject> pEnumVdsObject = NULL; 
     hr = pService->QueryProviders(VDS_QUERY_VIRTUALDISK_PROVIDERS | 
     VDS_QUERY_HARDWARE_PROVIDERS | VDS_QUERY_SOFTWARE_PROVIDERS, &pEnumVdsObject);
    
     // Check the Virtual Provider for the disk you have just created
    EnumObject(pEnumVdsObject, VdsProviders);
    std::wstring Diskname;
    for (auto& v : VdsProviders)
    {
        CComPtr<IEnumVdsObject> pEnumVdsObject2 = NULL;
        v->QueryVDisks(&pEnumVdsObject2);
    
        std::vector<CComPtr<IVdsVDisk>> disks;
        EnumObject(pEnumVdsObject2, disks);
    
        for (auto& disk : disks)
        {
            LPWSTR dn = 0;
            disk->GetDeviceName(&dn);
    
            if (dn)
                Diskname = dn;
        }
    }
    
    // Check the software provider for such a disk
    for (auto& v : SwProviders)
    {
        CComPtr<IEnumVdsObject> pEnumVdsObject2 = NULL;
        v->QueryPacks(&pEnumVdsObject2);
    
        std::vector<CComPtr<IVdsPack>> packs;
        EnumObject(pEnumVdsObject2, packs);
    
        for (auto& pack : packs)
        {
            if (1)
            {
                CComPtr<IEnumVdsObject> pEnumVdsObject3 = NULL;
                pack->QueryDisks(&pEnumVdsObject3);
                std::vector<CComPtr<IVdsDisk>> disks;
                EnumObject(pEnumVdsObject3, disks);
    
                for (auto& disk : disks)
                {
                    VDS_DISK_PROP p = {};
                    disk->GetProperties(&p);
                    if (wcscmp(p.pwszDevicePath, Diskname.c_str()) == 0 && p.BusType == VDSBusTypeFileBackedVirtual)
                    {
                        CComPtr<IVdsAdvancedDisk> ad;
                        ad = disk;
                        if (ad)
                        {
                            CComPtr<IVdsAsync> as;
                            HRESULT hr = 0;
                            hr = ad->FormatPartition(34 * SECTOR_SIZE, VDS_FST_NTFS,(LPWSTR)L"Label",SECTOR_SIZE,0,1,0,&as);
                            if (as)
                            {
                                VDS_ASYNC_OUTPUT ao = {};
                                as->Wait(&hr, &ao);
                                if (SUCCEEDED(hr))
                                    R = 1;
                            }
                        }
                    }
                }
            }
        }
    }