[Win32] [COM] VDS Object Enumeration
NTFS、パーティション マネジメントあたりがマイブームなので、VDS の COM インターフェースを使って各種オブジェクトを列挙するプログラムを書いてみた。
サンプルはこのへん。
Loading VDS (Windows)
http://msdn.microsoft.com/en-us/library/aa383037.aspx
Working with Enumeration Objects (Windows)
http://msdn.microsoft.com/en-us/library/aa383988.aspx
コードは下に貼りますが、特に捻りもない普通のコードです。
ConsumeVDS で IVdsService インターフェースを取得して、EnumVdsObjects でソフトウェア プロバイダーの,インターフェース (IVdsPack) を取得して EnumVdsVolumes, EnumVdsDisks でそれぞれボリュームとディスクを列挙。
Dump***Prop 関数は、GetProperties で取ってきた構造体をパースして表示しているだけなので省略。
そう言えば、衝撃の事実が上記 MSDN ページに。
VDS とダイナミック ディスクは星になるようです。
[Both the Virtual Disk Service and dynamic disks are deprecated as of Windows 8 Consumer Preview and Windows Server 8 Beta, and may be unavailable in subsequent versions of Windows. For more information, see Windows Storage Management API.]
VDS サービスはスタートアップ種別が手動であり、IVdsVolume インターフェースを取得するため、IVdsServiceLoader::LoadService を呼んだときに起動され、インターフェースを破棄するとサービスが停止します。このデザインはパフォーマンス的にあまりよくない気がします。
そんなこんなでソース。
//
// vds.cpp
//
// http://msdn.microsoft.com/en-us/library/aa383037.aspx
// http://msdn.microsoft.com/en-us/library/aa383988.aspx
//
#include <initguid.h>
#include <vds.h>
#include <stdio.h>
#pragma comment( lib, "rpcrt4.lib" )
void Logging(LPCWSTR fmt, DWORD err) {
//SYSTEMTIME st;
//GetSystemTime(&st);
//wprintf(L"[%d/%02d/%02d %02d:%02d:%02d.%03d] ",
// st.wYear,
// st.wMonth,
// st.wDay,
// st.wHour,
// st.wMinute,
// st.wSecond,
// st.wMilliseconds);
wprintf(fmt, err);
}
#define GET_LODWORD(ll) (((PLARGE_INTEGER)&ll)->LowPart)
#define GET_HIDWORD(ll) (((PLARGE_INTEGER)&ll)->HighPart)
void EnumVdsVolumes(IVdsPack *VdsPack) {
HRESULT Ret;
ULONG Fetched= 0;
IUnknown *Unknown= NULL;
IEnumVdsObject *EnumVolumes= NULL;
Ret= VdsPack->QueryVolumes(&EnumVolumes);
if ( FAILED(Ret) ) {
Logging(L"IVdsPack::QueryVolumes failed - 0x%08x\n", Ret);
goto cleanup;
}
do {
IVdsVolume *Volume= NULL;
IVdsVolumeMF *VolumeMF= NULL;
VDS_VOLUME_PROP PropVol;
VDS_FILE_SYSTEM_PROP PropFs;
Ret= EnumVolumes->Next(1, &Unknown, &Fetched);
if ( Ret==S_FALSE ) break;
if ( FAILED(Ret) ) goto cleanup;
Ret= Unknown->QueryInterface(IID_IVdsVolume, (void**)&Volume);
Unknown->Release();
if ( FAILED(Ret) ) {
Logging(L"IID_IVdsVolume::QueryInterface failed - 0x%08x\n",
Ret);
continue;
}
Ret= Volume->GetProperties(&PropVol);
if ( Ret==S_OK || Ret==VDS_S_PROPERTIES_INCOMPLETE )
DumpVolumeProp(&PropVol);
if ( Ret==VDS_S_PROPERTIES_INCOMPLETE )
wprintf(L" ** IID_IVdsVolume::GetProperties returned VDS_S_PROPERTIES_INCOMPLETE(0x%08x)\n\n", VDS_S_PROPERTIES_INCOMPLETE);
else if ( FAILED(Ret) )
Logging(L"IID_IVdsVolume::GetProperties failed - 0x%08x\n", Ret);
Ret= Volume->QueryInterface(IID_IVdsVolumeMF, (void**)&VolumeMF);
Volume->Release();
if ( Ret!=S_OK )
Logging(L"IID_IVdsVolumeMF::QueryInterface failed - 0x%08x\n",
Ret);
Ret= VolumeMF->GetFileSystemProperties(&PropFs);
if ( Ret==VDS_E_NO_MEDIA )
wprintf(L" ** IID_IVdsVolumeMF::GetProperties returned VDS_E_NO_MEDIA(0x%08x)\n\n", VDS_E_NO_MEDIA);
else if ( FAILED(Ret) )
Logging(L"IID_IVdsVolumeMF::GetFileSystemProperties failed - 0x%08x\n", Ret);
else
DumpFileSystemProp(&PropFs);
} while(1);
cleanup:
if ( EnumVolumes )
EnumVolumes->Release();
return;
}
void EnumVdsDisks(IVdsPack *VdsPack) {
HRESULT Ret;
ULONG Fetched= 0;
IUnknown *Unknown= NULL;
IEnumVdsObject *EnumDisks= NULL;
Ret= VdsPack->QueryDisks(&EnumDisks);
if ( FAILED(Ret) ) {
Logging(L"IVdsPack::QueryDisks failed - 0x%08x\n", Ret);
goto cleanup;
}
do {
IVdsDisk *Disk= NULL;
VDS_DISK_PROP DiskProp;
Ret= EnumDisks->Next(1, &Unknown, &Fetched);
if ( Ret==S_FALSE ) break;
if ( FAILED(Ret) ) goto cleanup;
Ret= Unknown->QueryInterface(IID_IVdsDisk, (void**)&Disk);
Unknown->Release();
if ( FAILED(Ret) ) continue;
Ret= Disk->GetProperties(&DiskProp);
if ( FAILED(Ret) )
Logging(L"IID_IVdsDisk::GetProperties failed - 0x%08x\n", Ret);
else
DumpDiskProp(&DiskProp);
} while (1);
cleanup:
if ( EnumDisks )
EnumDisks->Release();
return;
}
void EnumVdsObjects(IVdsService *VdsService) {
HRESULT Ret;
ULONG Fetched= 0;
IEnumVdsObject *EnumSwProviders= NULL;
IEnumVdsObject *EnumPacks= NULL;
IUnknown *Unknown= NULL;
IVdsProvider *Provider= NULL;
IVdsSwProvider *SwProvider= NULL;
IVdsPack *VdsPack= NULL;
VDS_PROVIDER_PROP ProviderProp;
VDS_PACK_PROP PackProp;
Ret= VdsService->QueryProviders(VDS_QUERY_SOFTWARE_PROVIDERS,
&EnumSwProviders);
if ( Ret!=S_OK ) {
Logging(L"IVdsService::QueryProviders failed - 0x%08x\n", Ret);
return;
}
do {
Ret= EnumSwProviders->Next(1, &Unknown, &Fetched);
if ( Ret==S_FALSE ) break;
if ( FAILED(Ret) ) goto cleanup;
Ret= Unknown->QueryInterface(IID_IVdsProvider, (void**)&Provider);
Unknown->Release();
if ( FAILED(Ret) ) continue;
Ret= Provider->GetProperties(&ProviderProp);
if ( FAILED(Ret) )
Logging(L"IID_IVdsProvider::GetProperties failed - 0x%08x\n",
Ret);
else
DumpProviderProp(&ProviderProp);
Ret= Provider->QueryInterface(IID_IVdsSwProvider,
(void**)&SwProvider);
Provider->Release();
if ( FAILED(Ret) ) continue;
Ret= SwProvider->QueryPacks(&EnumPacks);
SwProvider->Release();
if ( FAILED(Ret) ) continue;
do {
Ret= EnumPacks->Next(1, &Unknown, &Fetched);
if ( Ret==S_FALSE ) break;
if ( FAILED(Ret) ) goto cleanup;
Ret= Unknown->QueryInterface(IID_IVdsPack, (void**)&VdsPack);
Unknown->Release();
if ( FAILED(Ret) ) continue;
Ret= VdsPack->GetProperties(&PackProp);
if ( FAILED(Ret) )
Logging(L"IID_IVdsPack::GetProperties failed - %08x\n", Ret);
else
DumpPackProp(&PackProp);
EnumVdsDisks(VdsPack);
EnumVdsVolumes(VdsPack);
} while (1);
EnumPacks->Release();
EnumPacks= NULL;
} while (1);
cleanup:
if ( EnumPacks )
EnumPacks->Release();
if ( EnumSwProviders )
EnumSwProviders->Release();
return;
}
void ConsumeVDS() {
HRESULT Ret= 0;
IVdsServiceLoader *VdsServiceLoader= NULL;
IVdsService *VdsService= NULL;
Ret = CoInitialize(NULL);
if ( Ret!=S_OK ) {
Logging(L"CoInitialize failed - 0x%08x\n", Ret);
goto cleanup;
}
Ret= CoCreateInstance(CLSID_VdsLoader,
NULL,
CLSCTX_LOCAL_SERVER,
IID_IVdsServiceLoader,
(void **) &VdsServiceLoader);
if ( Ret!=S_OK ) {
Logging(L"CoCreateInstance(IVdsServiceLoader) failed - 0x%08x\n",
Ret);
goto cleanup;
}
Ret= VdsServiceLoader->LoadService(NULL, &VdsService);
VdsServiceLoader->Release();
VdsServiceLoader= NULL;
if ( Ret!=S_OK ) {
Logging(L"IVdsServiceLoader::LoadService failed - 0x%08x\n", Ret);
goto cleanup;
}
Ret= VdsService->WaitForServiceReady();
if ( Ret!=S_OK ) {
Logging(L"IVdsService::WaitForServiceReady failed - 0x%08x\n", Ret);
goto cleanup;
}
EnumVdsObjects(VdsService);
cleanup:
if ( VdsService )
VdsService->Release();
if ( VdsServiceLoader )
VdsServiceLoader->Release();
CoUninitialize();
return;
}