[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;
}

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。