IVdsDisk 接口

IVdsDisk 接口 提供查询和配置基本磁盘和动态磁盘的方法。
用于查询磁盘信息,与WMI查询方式相比调用更加复杂,但是可以直接对磁盘进行一系列的操作,比如说格式化磁盘分区,转换磁盘分区样式等;

VDS_DISK_PROP结构

VDS_DISK_PROP结构 定义 磁盘对象的属性。获取磁盘设备类型,媒体类型,磁盘的大小,字节数,扇区数,轨道数,分区类型,创建的对象的句柄的名称等数据。
多用于获取pwszName来创建句柄对象来获取其他信息,如硬盘柱面数等。

typedef struct _VDS_DISK_PROP {
  VDS_OBJECT_ID        id;
  VDS_DISK_STATUS      status;
  VDS_LUN_RESERVE_MODE ReserveMode;
  VDS_HEALTH           health;
  DWORD                dwDeviceType;
  DWORD                dwMediaType;
  ULONGLONG            ullSize;
  ULONG                ulBytesPerSector;
  ULONG                ulSectorsPerTrack;
  ULONG                ulTracksPerCylinder;
  ULONG                ulFlags;
  VDS_STORAGE_BUS_TYPE BusType;
  VDS_PARTITION_STYLE  PartitionStyle;
  union {
    DWORD dwSignature;
    GUID  DiskGuid;
  };
  LPWSTR               pwszDiskAddress;
  LPWSTR               pwszName;
  LPWSTR               pwszFriendlyName;
  LPWSTR               pwszAdaptorName;
  LPWSTR               pwszDevicePath;
} VDS_DISK_PROP, *PVDS_DISK_PROP;

VDS_PARTITION_PROP 结构

VDS_PARTITION_PROP 结构 定义分区的属性,获取分区偏移量,分区大小,分区类型,主启动记录。
VDS_PARTITION_PROP 结构需要先获取IVdsAdvancedDisk 接口示例,在通过QueryPartitions方法获取
在一些调用第三方软件需要传入操作分区的时候很有用。以及格式化分区时适用。

typedef struct _VDS_PARTITION_PROP {
  VDS_PARTITION_STYLE PartitionStyle;
  ULONG               ulFlags;
  ULONG               ulPartitionNumber;
  ULONGLONG           ullOffset;
  ULONGLONG           ullSize;
  union {
    VDS_PARTITION_INFO_MBR Mbr;
    VDS_PARTITION_INFO_GPT Gpt;
  };
} VDS_PARTITION_PROP;

调用示例

释放资源宏定义:
#define _SafeRelease(x) {if (NULL != x) { x->Release(); x = NULL; } }

	IVdsService* pService= NULL;
    IVdsServiceLoader* pLoader= NULL;
    IEnumVdsObject* pEnum= NULL;
    IUnknown * pUnk= NULL;
    ULONG ulFetched=0;

    HRESULT hResult = CoCreateInstance(CLSID_VdsLoader,NULL,CLSCTX_LOCAL_SERVER,IID_IVdsServiceLoader,(void **) &pLoader);
    if(!SUCCEEDED(hResult))
    {
        qDebug()<<"CoCreateInstance 服务 VDS未启动 "<<GetLastError();
        goto out;
    }
    hResult = pLoader->LoadService(NULL, &pService);
    if(!SUCCEEDED(hResult))
    {
        qDebug()<<"VDS Service failed !"<<GetLastError();
        goto out;
    }
    hResult = pService->WaitForServiceReady();
    if (!SUCCEEDED(hResult))
    {
        qDebug()<<"VDS Service Loaded failed !"<<GetLastError();
        goto out;
    }

    hResult= pService->QueryProviders( VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
    if (!SUCCEEDED(hResult))
    {
        qDebug("Could not query VDS Service Providers: %s",GetLastError());
        goto out;
    }
    while (pEnum->Next( 1, &pUnk, &ulFetched) == S_OK)
    {
        IVdsProvider* pProvider= NULL;
        IVdsSwProvider* pSwProvider= NULL;
        IEnumVdsObject* pEnumPack= NULL;
        IUnknown* pPackUnk= NULL;
        ULONG ulFetched2=0;

        hResult = pUnk->QueryInterface(IID_IVdsProvider, (void **)&pProvider);
        if (hResult != S_OK) {
            qDebug("Could not get VDS Provider: %s", GetLastError());
            goto out;
        }
        // Get VDS Software Provider
        hResult = pProvider->QueryInterface(IID_IVdsSwProvider, (void **)&pSwProvider);
        _SafeRelease(pProvider);
        if (hResult != S_OK) {
            qDebug("Could not get VDS Software Provider: %s", GetLastError());
            goto out;
        }
        // Get VDS Software Provider Packs

        hResult = pSwProvider->QueryPacks( &pEnumPack);
        _SafeRelease(pSwProvider);
        if (hResult != S_OK) {
            qDebug("Could not get VDS Software Provider Packs: %s", GetLastError());
            goto out;
        }
        while (pEnumPack->Next( 1, &pPackUnk, &ulFetched2) == S_OK)
        {

            IVdsPack* pPack= NULL;
            IEnumVdsObject* pEnumDisk= NULL;
            IUnknown* pDiskUnk= NULL;
            ULONG ulFetched3=0;
            hResult = pPackUnk->QueryInterface(IID_IVdsPack, (void**)&pPack);
            if (hResult != S_OK) {
                qDebug("Could not query VDS Software Provider Pack: %s", GetLastError());
                break;
            }

            hResult = pPack->QueryDisks(&pEnumDisk);
            _SafeRelease(pPack);
            if (hResult != S_OK) {
                qDebug("Could not query VDS disks: %s", GetLastError());
                break;
            }
            while (pEnumDisk->Next( 1, &pDiskUnk, &ulFetched3) == S_OK)
            {
                VDS_DISK_PROP prop;
                IVdsDisk* pDisk= NULL;
                IVdsAdvancedDisk* pAdvancedDisk= NULL;
                hResult = pDiskUnk->QueryInterface(IID_IVdsDisk, (void**)&pDisk);
                if (hResult != S_OK) {
                    qDebug("Could not query VDS Disk Interface: %s", GetLastError());
                    continue;
                }
                hResult = pDisk->GetProperties(&prop);
                if ((hResult != S_OK) && (hResult != VDS_S_PROPERTIES_INCOMPLETE)) {
                    qDebug("Could not query VDS Disk Properties: %s", GetLastError());
                    continue;
                }
                QString PwszName=QString::fromWCharArray(prop.pwszName);
                HRESULT hResult= pDisk->QueryInterface(IID_IVdsAdvancedDisk,(void **)&pAdvancedDisk);
                if (hResult != S_OK)
                {
                    qDebug("Could not access the requested Disk interface: %s", GetLastError());
                    continue;
                }

                VDS_PARTITION_PROP* prop_array = NULL;
                LONG prop_size=0;
                hResult= pAdvancedDisk->QueryPartitions(&prop_array, &prop_size);
                if(hResult != S_OK)
                {
                    qDebug()<<"No partition on disk! ";
                    continue;
                }
                }
                CoTaskMemFree(prop_array);

                _SafeRelease(pDisk);
                _SafeRelease(pAdvancedDisk);
            }

            _SafeRelease(pEnumDisk);
            _SafeRelease(pDiskUnk);
        }
        _SafeRelease(pEnumPack);
        _SafeRelease(pPackUnk);
    }

out:
    _SafeRelease(pService);
    _SafeRelease(pLoader);
    _SafeRelease(pEnum);
    _SafeRelease(pUnk);

IVdsVolume 接口

IVdsVolume 接口 提供管理卷的方法。
IVdsVolume 与IVdsDisk 接口调用声明方式差不多,只是调用的
pPack->QueryVolumes(&pEnumDisk);
实际使用也很少使用IVdsVolume 接口获取盘符信息

VDS_VOLUME_PROP结构

VDS_VOLUME_PROP结构 定义 卷对象的属性,
获取卷的大小,状态,类型,文件系统,卷句柄的名称等

typedef struct _VDS_VOLUME_PROP {
  VDS_OBJECT_ID        id;
  VDS_VOLUME_TYPE      type;
  VDS_VOLUME_STATUS    status;
  VDS_HEALTH           health;
  VDS_TRANSITION_STATE TransitionState;
  ULONGLONG            ullSize;
  ULONG                ulFlags;
  VDS_FILE_SYSTEM_TYPE RecommendedFileSystemType;
  LPWSTR               pwszName;
} VDS_VOLUME_PROP, *PVDS_VOLUME_PROP;

调用示例

IVdsService* pService= NULL;
    IVdsServiceLoader* pLoader= NULL;
    IEnumVdsObject* pEnum= NULL;
    IUnknown * pUnk= NULL;
    ULONG ulFetched=0;

    HRESULT hResult = CoCreateInstance(CLSID_VdsLoader,NULL,CLSCTX_LOCAL_SERVER,IID_IVdsServiceLoader,(void **) &pLoader);
    if(!SUCCEEDED(hResult))
    {
        qDebug()<<"CoCreateInstance 服务 VDS未启动 "<<GetLastError();
        goto out;
    }
    hResult = pLoader->LoadService(NULL, &pService);
    if(!SUCCEEDED(hResult))
    {
        qDebug()<<"VDS Service failed !"<<GetLastError();
        goto out;
    }
    hResult = pService->WaitForServiceReady();
    if (!SUCCEEDED(hResult))
    {
        qDebug()<<"VDS Service Loaded failed !"<<GetLastError();
        goto out;
    }

    hResult= pService->QueryProviders( VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
    if (!SUCCEEDED(hResult))
    {
        qDebug("Could not query VDS Service Providers: %s",GetLastError());
        goto out;
    }
    while (pEnum->Next( 1, &pUnk, &ulFetched) == S_OK)
    {
        IVdsProvider* pProvider= NULL;
        IVdsSwProvider* pSwProvider= NULL;
        IEnumVdsObject* pEnumPack= NULL;
        IUnknown* pPackUnk= NULL;
        ULONG ulFetched2=0;

        hResult = pUnk->QueryInterface(IID_IVdsProvider, (void **)&pProvider);
        if (hResult != S_OK) {
            qDebug("Could not get VDS Provider: %s", GetLastError());
            goto out;
        }
        // Get VDS Software Provider
        hResult = pProvider->QueryInterface(IID_IVdsSwProvider, (void **)&pSwProvider);
        _SafeRelease(pProvider);
        if (hResult != S_OK) {
            qDebug("Could not get VDS Software Provider: %s", GetLastError());
            goto out;
        }
        // Get VDS Software Provider Packs

        hResult = pSwProvider->QueryPacks( &pEnumPack);
        _SafeRelease(pSwProvider);
        if (hResult != S_OK) {
            qDebug("Could not get VDS Software Provider Packs: %s", GetLastError());
            goto out;
        }
        while (pEnumPack->Next( 1, &pPackUnk, &ulFetched2) == S_OK)
        {

            IVdsPack* pPack= NULL;
            IEnumVdsObject* pEnumDisk= NULL;
            IUnknown* pDiskUnk= NULL;
            ULONG ulFetched3=0;
            hResult = pPackUnk->QueryInterface(IID_IVdsPack, (void**)&pPack);
            if (hResult != S_OK) {
                qDebug("Could not query VDS Software Provider Pack: %s", GetLastError());
                break;
            }

            hResult = pPack->QueryVolumes(&pEnumDisk);
            _SafeRelease(pPack);
            if (hResult != S_OK) {
                qDebug("Could not query VDS disks: %s", GetLastError());
                break;
            }
            while (pEnumDisk->Next( 1, &pDiskUnk, &ulFetched3) == S_OK)
            {
                
                    IVdsVolume *pVolume;
                    VDS_VOLUME_PROP VolumeProps;
                    hResult = pDiskUnk->QueryInterface(IID_IVdsVolume, (void **)&pVolume);
                    pDiskUnk->Release();
                    if (hResult != S_OK) {
                        qDebug("Could not query VDS Volume Interface: %s", GetLastError());
                        goto out;
                    }
                    hResult = pVolume->GetProperties( &VolumeProps);
                    if ((hResult != S_OK) && (hResult != VDS_S_PROPERTIES_INCOMPLETE)) {
                        pVolume->Release();
                        qDebug("Could not query VDS Volume Properties: %s", GetLastError());
                        continue;
                    }
                    
                    CoTaskMemFree (VolumeProps.pwszName);
                _SafeRelease(pVolume);
            }

            _SafeRelease(pEnumDisk);
            _SafeRelease(pDiskUnk);
        }
        _SafeRelease(pEnumPack);
        _SafeRelease(pPackUnk);
    }

out:
    _SafeRelease(pService);
    _SafeRelease(pLoader);
    _SafeRelease(pEnum);
    _SafeRelease(pUnk);
  1. 在看过WMI调用的示例后,我简单了解了CComPtr<> 的使用,我想着同样是继承 IUnknown 接口 的接口,大差不差, 就打算在上面示例中直接使用 CComPtr<> 来保存实例,这样就避免了重复调用 _SafeRelease 释放内存。
    然而实际却是,程序直接闪崩,断点都找不到,唯一的解释就是 CComPtr<> 提前释放了内存。只能老老实实的使用 _SafeRelease 释放内存,不知道有没有大佬能说说原因。。。
  2. 如果出现 无法解析的外部符号 __CLSID_VdsLoader 异常:
    #添加include <initguid.h> 在 #include <vds.h>前面
  3. 如果出现 无法解析的外部符号 ConvertStringToBSTR(char const *)
    不确定具体是添加哪一个了,那就两个都加上
    添加#include <comdef.h> #include <comutil.h>
  4. 如果出现 无法解析的外部符号 __imp_CoInitializeEx
    添加#pragma comment(lib,"ole32.lib") 在 #pragma comment(lib,"virtdisk.lib") 前面
  5. 如果出现 解决无法解析的外部符号 void __cdecl _com_issue_error(long)
    这是在调用 wininet.lib会出现的异常
    添加 #pragma comment(lib, "comsupp.lib") 在 #pragma comment(lib, "wininet.lib") 前面
  6. 如果出现 存在编码格式问题
    具体异常信息内容忘了,但是包含这段文字
    添加 #pragma comment(lib, "wbemuuid.lib")
01-28 12:33