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