从磁盘号码检索虚拟磁盘文件名 [英] Retrieving virtual disk file name from disk number

查看:250
本文介绍了从磁盘号码检索虚拟磁盘文件名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我列出的diskpart中创建虚拟磁盘:

  DISKPART>清单虚拟磁盘

虚拟磁盘###磁盘###状态​​类型文件
--------- -------- -------- ------------ --------- ----
虚拟磁盘0磁盘2连接不开式固定C:\Disk.vhd

对于我来说有趣的是这里的文件名。我试图找到等效功能,这将使我的文件名(在文件列),如果我知道磁盘号。



在理想情况下,我会给予 \ ?\ \PhysicalDrive2 和我会得到 C:\Disk.vhd 作为结果



我已经尝试过:




  1. 使用DISKPART和解析输出 - 既然是无证的格式,它可以随时更改。这不是我的依靠。

  2. 常规的 VHD API - 无功能需要的磁盘数为参数

  3. Microsoft.Storage.Vds.dll - 有迹象表明,通过走枚举每个驱动器(如Service.Providers),但没有财产/功能,这将使我的源文件的名称。虽然我现在可以肯定的是如驱动器D:是虚拟光驱,我仍然无法知道哪个.vhd文件附有



你知道哪个函数可能是<? / p>

解决方案

这里有两个解决方案,以在本地机器上检索虚拟磁盘和打印他们的信息。这两种解决方案演示了如何使用VDS COM对象都在本地和托管的方式来访问这些数据。



托管解决方案



我从 MSDN文档并从Windows 7创建一个局部的COM互操作SDK(主要是 vds.h )。需要注意的是在COM包装是局部的,这意味着一些方法还没有被移植



下面是使用.NET COM互操作为托管应用程序:




  • 加载VDS服务

  • 查询虚拟磁盘供应商

  • <
  • 的虚拟磁盘的属性赋予其GUID,其完整的驱动程序路径,它的体积大小和它的磁盘文件

      <:LI>列出每个供应商处理的所有虚拟磁盘/ STRONG>(即 C:\Disk.vhd
    • 的虚拟磁盘也可以查询作为一个通用的磁盘。并给出了它的名字(即<​​code> \\?\PhysicalDrive1 ),其友好的名称和其他属性。

  • 使用系统





 ;使用System.Runtime.InteropServices 
;

命名空间VDiskDumper
{
类节目
{
静态无效的主要(字串[] args)
{
//创建服务加载
VdsServiceLoader loaderClass =新VdsServiceLoader();
IVdsServiceLoader装载机=(IVdsServiceLoader)loaderClass;
Console.WriteLine(得到装载机);

//将服务
IVdsService服务;
loader.LoadService(NULL,停止服务);
Console.WriteLine(得到服务);

//等待readyness
service.WaitForServiceReady();
Console.WriteLine(服务就绪);

//查询有关虚拟磁盘提供商
IEnumVdsObject providerEnum;
service.QueryProviders(VDS_QUERY_PROVIDER_FLAG.VDS_QUERY_VIRTUALDISK_PROVIDERS,出providerEnum);
Console.WriteLine(拿到供应商);

//迭代
,而(真)
{
UINT进账;
对象不明;
providerEnum.Next(1,出未知的,取出来);

如果(取== 0)打破;

//强制转换为所需类型
IVdsVdProvider提供商=(IVdsVdProvider)不明;
Console.WriteLine(得到VD提供商);

转储(供应商);
}

Console.ReadKey();
}

私有静态无效转储(IVdsVdProvider提供商)
{
//查询的虚拟磁盘
IEnumVdsObject diskEnum;
provider.QueryVDisks(出diskEnum);
Console.WriteLine(得到虚拟磁盘);

//迭代
,而(真)
{
UINT进账;
对象不明;
diskEnum.Next(1,出未知的,取出来);

如果(取== 0)打破;

//强制转换为所需的类型
IVdsVDisk虚拟磁盘=(IVdsVDisk)不明;

//获取虚拟磁盘性能
VDS_VDISK_PROPERTIES vdiskProperties;
vDisk.GetProperties(出vdiskProperties);

Console.WriteLine( - >虚拟磁盘n =+ vdiskProperties.Id);
Console.WriteLine( - >虚拟磁盘设备名称=+ vdiskProperties.pDeviceName);
Console.WriteLine( - >虚拟磁盘路径=+ vdiskProperties.pPath);

//获取相关的磁盘
IVdsDisk盘;
provider.GetDiskFromVDisk(虚拟磁盘,磁盘出);

//获取磁盘属性
VDS_DISK_PROP diskProperties;
disk.GetProperties(出diskProperties);

Console.WriteLine( - >磁盘名称=+ diskProperties.pwszName);
Console.WriteLine( - >磁盘友好=+ diskProperties.pwszFriendlyName);
}
}
}

[ComImport,与GUID(118610b7-8d94-4030-b5b8-500889788e4e),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
公共接口IEnumVdsObject
{
无效下一页(UINT numberOfObjects,[的MarshalAs(UnmanagedType.IUnknown)] out对象objectUnk,出UINT numberFetched);
无效跳过(UINT NumberOfObjects);
无效复位();
无效克隆(出IEnumVdsObject枚举);
}

[ComImport,与GUID(07e5c822-f00c-47a1-8fce-b244da56fd06),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
公共接口IVdsDisk
{
无效的GetProperties(出VDS_DISK_PROP diskProperties);
无效GetPack(); // Unported方法
无效GetIdentificationData(IntPtr的lunInfo);
无效QueryExtents(); // Unported方法
无效时隙4();
无效SetFlags(); // Unported方法
无效ClearFlags(); // Unported方法
}

[ComImport,与GUID(0818a8ef-9ba9-40d8-a6f9-e22833cc771e),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
公共接口IVdsService
{
[PreserveSig]
INT IsServiceReady();
[PreserveSig]
INT WaitForServiceReady();
无效的GetProperties(); // Unported方法
无效QueryProviders(VDS_QUERY_PROVIDER_FLAG面具,出IEnumVdsObject提供商);
无效QueryMaskedDisks(出IEnumVdsObject磁盘);
无效QueryUnallocatedDisks(出IEnumVdsObject磁盘);
无效GetObject的(); // Unported方法
无效QueryDriveLetters(); // Unported方法
无效QueryFileSystemTypes(出的IntPtr fileSystemTypeProps,出UINT numberOfFileSystems);
无效重新枚举();
无效刷新();
无效CleanupObsoleteMountPoints();
劝无效(); // Unported方法
无效的Unadvise(); // Unported方法
无效重启();
无效SetFlags(); // Unported方法
无效ClearFlags(); // Unported方法
}

[ComImport,与GUID(e0393303-90d4-4a97-ab71-e9b671ee2729),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
公共接口IVdsServiceLoader
{
无效LoadService([IN,的MarshalAs(UnmanagedType.LPWStr)字符串计算机名,出IVdsService vdsService);
}

[ComImport,与GUID(1e062b84-e5e6-4b4b-8a25-67b81e8f13e8),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
公共接口IVdsVDisk
{
无效的open(); // Unported方法
无效的GetProperties(出VDS_VDISK_PROPERTIES pDiskProperties);
无效GetHostVolume(); // Unported方法
无效GetDeviceName(); // Unported方法
}

[ComImport,与GUID(b481498c-8354-45f9-84a0-0bdd2832a91f),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
公共接口IVdsVdProvider
{
无效QueryVDisks(出IEnumVdsObject ppEnum);
无效CreateVDisk(); // Unported方法
无效AddVDisk(); // Unported方法
无效GetDiskFromVDisk(IVdsVDisk pVDisk,出IVdsDisk ppDisk);
无效GetVDiskFromDisk(IVdsDisk PDISK,出IVdsVDisk ppVDisk);
}

[ComImport,与GUID(9c38ed61-d565-4728-aeee-c80952f0ecde)]
公共类VdsServiceLoader
{
}

[StructLayout(LayoutKind.Explicit)
公共结构签名
{
[FieldOffset(0)]
公共UINT dwSignature;
[FieldOffset(0)]
公众的Guid DiskGuid;
}

[StructLayout(LayoutKind.Sequential)]
公共结构VDS_DISK_PROP
{
公众的Guid标识;
公共VDS_DISK_STATUS状态;
公共VDS_LUN_RESERVE_MODE ReserveMode;
公共VDS_HEALTH健康;
公共UINT dwDeviceType;
公共UINT dwMediaType;
公共ULONG ullSize;
公共UINT ulBytesPerSector;
公共UINT ulSectorsPerTrack;
公共UINT ulTracksPerCylinder;
公共UINT ulFlags;
公共VDS_STORAG​​E_BUS_TYPE BusType;
公共VDS_PARTITION_STYLE PartitionStyle;
公众签名dwSignature;
[的MarshalAs(UnmanagedType.LPWStr)
公共字符串pwszDiskAddress;
[的MarshalAs(UnmanagedType.LPWStr)
公共字符串pwszName;
[的MarshalAs(UnmanagedType.LPWStr)
公共字符串pwszFriendlyName;
[的MarshalAs(UnmanagedType.LPWStr)
公共字符串pwszAdaptorName;
[的MarshalAs(UnmanagedType.LPWStr)
公共字符串pwszDevicePath;
}

[StructLayout(LayoutKind.Sequential)]
公共结构VIRTUAL_STORAG​​E_TYPE
{
公共UINT DEVICEID;
公众的Guid VENDORID;
}

[StructLayout(LayoutKind.Sequential)]
公共结构VDS_VDISK_PROPERTIES
{
公众的Guid标识;
公共VDS_VDISK_STATE国家;
公共VIRTUAL_STORAG​​E_TYPE VirtualDeviceType;
公共ULONG VirtualSize;
公共ULONG PhysicalSize;
[的MarshalAs(UnmanagedType.LPWStr)
公共字符串PPATH;
[的MarshalAs(UnmanagedType.LPWStr)
公共字符串pDeviceName;
公共DEPENDENT_DISK_FLAG DiskFlag;
公共BOOL bIsChild;
[的MarshalAs(UnmanagedType.LPWStr)
公共字符串pParentPath;
}

公共枚举DEPENDENT_DISK_FLAG
{
DEPENDENT_DISK_FLAG_NONE = 00000000,
DEPENDENT_DISK_FLAG_MULT_BACKING_FILES = 00000001,
DEPENDENT_DISK_FLAG_FULLY_ALLOCATED = 0x00000002,
DEPENDENT_DISK_FLAG_READ_ONLY = 0x00000004,
DEPENDENT_DISK_FLAG_REMOTE = 0x00000008,
DEPENDENT_DISK_FLAG_SYSTEM_VOLUME = 0x00000010,
DEPENDENT_DISK_FLAG_SYSTEM_VOLUME_PARENT = 0x00000020,
DEPENDENT_DISK_FLAG_REMOVABLE = 0x00000040,
DEPENDENT_DISK_FLAG_NO_DRIVE_LETTER = 0x00000080,
DEPENDENT_DISK_FLAG_PARENT = 0x00000100 ,
DEPENDENT_DISK_FLAG_NO_HOST_DISK = 0x00000200,
DEPENDENT_DISK_FLAG_PERMANENT_LIFETIME = 0x00000400时,
}

公共枚举VDS_DISK_STATUS
{
VDS_DS_UNKNOWN = 0,
VDS_DS_ONLINE = 1,
VDS_DS_NOT_READY = 2,
VDS_DS_NO_MEDIA = 3,
VDS_DS_FAILED = 5,
VDS_DS_MISSING = 6,
VDS_DS_OFFLINE = 4
}

公共枚举VDS_HEALTH
{
VDS_H_UNKNOWN = 0,
VDS_H_HEALTHY = 1,
VDS_H_REBUILDING = 2,
VDS_H_STALE = 3,
VDS_H_FAILING = 4,
VDS_H_FAILING_REDUNDANCY = 5,
VDS_H_FAILED_REDUNDANCY = 6,
VDS_H_FAILED_REDUNDANCY_FAILING = 7,
VDS_H_FAILED = 8,
VDS_H_REPLACED = 9,
VDS_H_PENDING_FAILURE = 10,
VDS_H_DEGRADED = 11
}

公共枚举VDS_LUN_RESERVE_MODE
{
VDS_LRM_NONE = 0,
VDS_LRM_EXCLUSIVE_RW = 1,
VDS_LRM_EXCLUSIVE_RO = 2,
VDS_LRM_SHARED_RO = 3,
VDS_LRM_SHARED_RW = 4
}

公共枚举VDS_PARTITION_STYLE
{
VDS_PST_UNKNOWN = 0,
VDS_PST_MBR = 1,
VDS_PST_GPT = 2
}

公共枚举VDS_QUERY_PROVIDER_FLAG
{
VDS_QUERY_SOFTWARE_PROVIDERS =为0x1,
VDS_QUERY_HARDWARE_PROVIDERS = 0X2,
VDS_QUERY_VIRTUALDISK_PROVIDERS =为0x4
}

公共枚举VDS_STORAG​​E_BUS_TYPE
{
VDSBusTypeUnknown = 0,
VDSBusTypeScsi =为0x1,
VDSBusTypeAtapi = 0X2,
VDSBusTypeAta = 0x3中,
VDSBusType1394 =为0x4,
VDSBusTypeSsa = 0x5的,
VDSBusTypeFibre =为0x6,
VDSBusTypeUsb = 0x7的,
VDSBusTypeRAID = 0x8中,
VDSBusTypeiScsi = 0x9,
VDSBusTypeSas =为0xA,
VDSBusTypeSata = 0XB,
VDSBusTypeSd = 0xC的,
VDSBusTypeMmc = 0xd中,
VDSBusTypeMax = 0xe,
VDSBusTypeFileBackedVirtual = 0xF的,
VDSBusTypeMaxReserved = 0x7f中的
}

公共枚举VDS_VDISK_STATE
{
VDS_VST_UNKNOWN = 0,
VDS_VST_ADDED,
VDS_VST_OPEN,
VDS_VST_ATTACH_PENDING,
VDS_VST_ATTACHED_NOT_OPEN,
VDS_VST_ATTACHED,
VDS_VST_DETACH_PENDING,
VDS_VST_COMPACTING,
VDS_VST_MERGING,
VDS_VST_EXPANDING,
VDS_VST_DELETED,
VDS_VST_MAX
}
}






本机的解决方案



下面是使用VDS COM接口,本机应用程序:




  • 加载VDS服务

  • 查询虚拟磁盘供应商

  • 列出每个供应商处理的所有虚拟磁盘:

    • 的虚拟磁盘的属性赋予其GUID,其完整的驱动程序路径,它的体积大小和它的磁盘文件(即 C:\Disk.vhd

    • 的虚拟磁盘也可以查询作为一个通用的磁盘,并给它的名字(即 \\?\PhysicalDrive1 ),其友好的名称和其他属性。







 的#includeinitguid.h
的#include vds.h
&#包括LT; stdio.h中>

的#pragma评论(LIB,ole32.lib)
的#pragma评论(LIB,rpcrt4.lib)

//简单的宏释放非空接口。
的#define _SafeRelease(X){如果(NULL = X!){x轴和GT;发行(); X = NULL; }}

无效exploreVDiskProvider(IVdsVdProvider * pVdProvider);

INT __cdecl主要(无效)
{
HRESULT HRESULT;
ULONG ulFetched = 0;
BOOL BDONE = FALSE;

IVdsServiceLoader * pLoader = NULL;
IVdsService * pService = NULL;
IEnumVdsObject * pProviderEnum = NULL;
的IUnknown * pUnknown = NULL;
IVdsVdProvider * pVdProvider = NULL;

//初始化COM
HRESULT = CoInitialize的(NULL);
如果(FAILED(HRESULT))转到保释;

//对于这一点,得到一个指针VDS装载机
HRESULT =的CoCreateInstance(CLSID_VdsLoader,
NULL,
CLSCTX_LOCAL_SERVER,
IID_IVdsServiceLoader,
(无效**)及pLoader);
如果(FAILED(HRESULT))转到保释;

的printf(加载VDS服务...... \\\
);

//启动VDS服务。
HRESULT = pLoader-> LoadService(NULL,&安培; pService);

//我们在这一点加载器界面来完成。
_SafeRelease(pLoader);

如果(FAILED(HRESULT))转到保释;

//等待服务做好准备
HRESULT = pService-> WaitForServiceReady();
如果(FAILED(HRESULT))转到保释;

的printf(VDS服务Loaded\\\
);

//查询虚拟磁盘提供商
HRESULT = pService-> QueryProviders(VDS_QUERY_VIRTUALDISK_PROVIDERS,&安培; pProviderEnum);
如果(FAILED(HRESULT))转到保释;

的printf(查询供应商... \\\
);

//迭代虚拟磁盘供应商
,而(1)
{
ulFetched = 0;
HRESULT = pProviderEnum->接着(1,​​&安培; pUnknown,&放大器; ulFetched);
如果(FAILED(HRESULT)){
中断;
}
如果(HRESULT == S_FALSE){
中断;
}

//当前值转换为虚拟磁盘提供
HRESULT = pUnknown->的QueryInterface(IID_IVdsVdProvider,(无效**)及pVdProvider);
如果(FAILED(HRESULT))转到保释;

的printf(VDS虚拟磁盘提供Found\\\
);

exploreVDiskProvider(pVdProvider);

_SafeRelease(pVdProvider);

_SafeRelease(pUnknown);
}

的getchar();
返回0;

保释金:
的printf(无法HR =%x\\\
,HRESULT);
返回1;
}

无效exploreVDiskProvider(IVdsVdProvider * pVdProvider){
HRESULT HRESULT;
ULONG ulFetched = 0;

IEnumVdsObject * pVDiskEnum = NULL;
IVdsVDisk * pVDisk = NULL;
的IUnknown * pUnknown = NULL;
IVdsVolume * pVolume = NULL;
VDS_VDISK_PROPERTIES vdiskProperties = {0};
TCHAR * UUID = NULL;
IVdsDisk * PDISK = NULL;
VDS_DISK_PROP diskProperties = {0};

//查询由提供者$ B $处理B中的磁盘HRESULT = pVdProvider-> QueryVDisks(安培; pVDiskEnum);
如果(FAILED(HRESULT))转到保释;

的printf(查询虚拟磁盘... \\\
);

//迭代虚拟磁盘
,而(1)
{
ulFetched = 0;
HRESULT = pVDiskEnum->接着(1,​​&安培; pUnknown,&放大器; ulFetched);
如果(HRESULT == S_FALSE){
中断;
}

如果(FAILED(HRESULT))转到保释;

//当前值转换为磁盘
HRESULT = pUnknown->的QueryInterface(IID_IVdsVDisk,(无效**)及pVDisk);
如果(FAILED(HRESULT))转到保释;

的printf(虚拟磁盘Found\\\
);

//获取磁盘的性能,并显示他们中的一些
HRESULT = pVDisk->的GetProperties(安培; vdiskProperties);
如果(FAILED(HRESULT))转到保释;

//转换的GUID为字符串
UuidToString(安培; vdiskProperties.Id,(RPC_WSTR *)及UUID);

//转储某些属性
的printf( - >盘ID =%ws\\\
,UUID);
的printf( - >磁盘设备名称=%ws\\\
,vdiskProperties.pDeviceName);
的printf( - >磁盘路径=%ws\\\
,vdiskProperties.pPath);

//从虚拟磁盘$ B $磁盘实例b = HRESULT&pVdProvider- GT; GetDiskFromVDisk(pVDisk,&安培; PDISK);
如果(FAILED(HRESULT))转到保释;

_SafeRelease(pVDisk);

_SafeRelease(pUnknown);

//获取磁盘的性能,并显示他们中的一些
HRESULT = pDisk->的GetProperties(安培; diskProperties);
如果(FAILED(HRESULT))转到保释;

的printf( - >磁盘名称=%ws\\\
,diskProperties.pwszName);
的printf( - >磁盘友好名称=%ws\\\
,diskProperties.pwszFriendlyName);
}

的回报;

保释金:
的printf(无法HR =%x\\\
,HRESULT);
}


When I list virtual disks within diskpart:

DISKPART> list vdisk

  VDisk ###  Disk ###  State                 Type       File
  ---------  --------  --------------------  ---------  ----
  VDisk 0    Disk 2    Attached not open     Fixed       C:\Disk.vhd

Interesting part for me here is file name. I tried to find equivalent of function that would give me file name (under File column) if I know disk number.

Ideally, I would give "\\?\PhysicalDrive2" and I would get "C:\Disk.vhd" as result.

I already tried:

  1. Using diskpart and parsing output - since it is undocumented format, it can change at any time. This is not something I would rely on.
  2. General VHD API - no function takes disk number as parameter.
  3. Microsoft.Storage.Vds.dll - There are enumerations that go through each drive (e.g. Service.Providers) but there is no property/function that will give me name of source file. While I can now be sure that e.g. drive D: is virtual drive, I still cannot know which .vhd file was attached.

Any idea which function that might be?

解决方案

Here are two solutions to retrieve virtual disks on the local machine and to print their information. The two solutions demonstrate how to use VDS COM objects to access these data both in a native and managed way.

Managed Solution

I have create a partial COM Interop from the MSDN Documentation and from the Windows 7 SDK (mainly vds.h). Note that the COM wrappers are partial, which means that some methods are yet to be ported.

Below is a managed application that uses the .NET COM interop to:

  • Load the VDS service
  • Query for the Virtual Disk Providers
  • List all the Virtual Disk handled by each provider:
    • The virtual disk's properties gives its GUID, its full driver path, its volume size and its disk file (i.e. C:\Disk.vhd).
    • A virtual disk can be also be queried as a generic disk and gives its name (i.e. \\?\PhysicalDrive1), its friendly name and other properties.

using System;
using System.Runtime.InteropServices;

namespace VDiskDumper
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create the service loader
            VdsServiceLoader loaderClass = new VdsServiceLoader();
            IVdsServiceLoader loader = (IVdsServiceLoader)loaderClass;
            Console.WriteLine("Got Loader");

            // Load the service
            IVdsService service;
            loader.LoadService(null, out service);
            Console.WriteLine("Got Service");

            // Wait for readyness
            service.WaitForServiceReady();
            Console.WriteLine("Service is ready");

            // Query for vdisk providers
            IEnumVdsObject providerEnum;
            service.QueryProviders(VDS_QUERY_PROVIDER_FLAG.VDS_QUERY_VIRTUALDISK_PROVIDERS, out providerEnum);
            Console.WriteLine("Got Providers");

            // Iterate
            while (true)
            {
                uint fetched;
                object unknown;
                providerEnum.Next(1, out unknown, out fetched);

                if (fetched == 0) break;

                // Cast to the required type
                IVdsVdProvider provider = (IVdsVdProvider)unknown;
                Console.WriteLine("Got VD Provider");

                Dump(provider);
            }

            Console.ReadKey();
        }

        private static void Dump(IVdsVdProvider provider)
        {
            // Query for the vdisks
            IEnumVdsObject diskEnum;
            provider.QueryVDisks(out diskEnum);
            Console.WriteLine("Got VDisks");

            // Iterate
            while (true)
            {
                uint fetched;
                object unknown;
                diskEnum.Next(1, out unknown, out fetched);

                if (fetched == 0) break;

                // Cast to the required type
                IVdsVDisk vDisk = (IVdsVDisk)unknown;

                // Get the vdisk properties
                VDS_VDISK_PROPERTIES vdiskProperties;
                vDisk.GetProperties(out vdiskProperties);

                Console.WriteLine("-> VDisk Id=" + vdiskProperties.Id);
                Console.WriteLine("-> VDisk Device Name=" + vdiskProperties.pDeviceName);
                Console.WriteLine("-> VDisk Path=" + vdiskProperties.pPath);

                // Get the associated disk
                IVdsDisk disk;
                provider.GetDiskFromVDisk(vDisk, out disk);

                // Get the disk properties
                VDS_DISK_PROP diskProperties;
                disk.GetProperties(out diskProperties);

                Console.WriteLine("-> Disk Name=" + diskProperties.pwszName);
                Console.WriteLine("-> Disk Friendly=" + diskProperties.pwszFriendlyName);
            }
        }
    }

    [ComImport, Guid("118610b7-8d94-4030-b5b8-500889788e4e"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IEnumVdsObject
    {
        void Next(uint numberOfObjects, [MarshalAs(UnmanagedType.IUnknown)] out object objectUnk, out uint numberFetched);
        void Skip(uint NumberOfObjects);
        void Reset();
        void Clone(out IEnumVdsObject Enum);
    }

    [ComImport, Guid("07e5c822-f00c-47a1-8fce-b244da56fd06"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IVdsDisk
    {
        void GetProperties(out VDS_DISK_PROP diskProperties);
        void GetPack(); // Unported method
        void GetIdentificationData(IntPtr lunInfo);
        void QueryExtents(); // Unported method
        void slot4();
        void SetFlags(); // Unported method
        void ClearFlags(); // Unported method
    }

    [ComImport, Guid("0818a8ef-9ba9-40d8-a6f9-e22833cc771e"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IVdsService
    {
        [PreserveSig]
        int IsServiceReady();
        [PreserveSig]
        int WaitForServiceReady();
        void GetProperties(); // Unported method
        void QueryProviders(VDS_QUERY_PROVIDER_FLAG mask, out IEnumVdsObject providers);
        void QueryMaskedDisks(out IEnumVdsObject disks);
        void QueryUnallocatedDisks(out IEnumVdsObject disks);
        void GetObject(); // Unported method
        void QueryDriveLetters(); // Unported method
        void QueryFileSystemTypes(out IntPtr fileSystemTypeProps, out uint numberOfFileSystems);
        void Reenumerate();
        void Refresh();
        void CleanupObsoleteMountPoints();
        void Advise(); // Unported method
        void Unadvise(); // Unported method
        void Reboot();
        void SetFlags(); // Unported method
        void ClearFlags(); // Unported method
    }

    [ComImport, Guid("e0393303-90d4-4a97-ab71-e9b671ee2729"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IVdsServiceLoader
    {
        void LoadService([In, MarshalAs(UnmanagedType.LPWStr)] string machineName, out IVdsService vdsService);
    }

    [ComImport, Guid("1e062b84-e5e6-4b4b-8a25-67b81e8f13e8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IVdsVDisk
    {
        void Open(); // Unported method
        void GetProperties(out VDS_VDISK_PROPERTIES pDiskProperties);
        void GetHostVolume(); // Unported method
        void GetDeviceName(); // Unported method
    }

    [ComImport, Guid("b481498c-8354-45f9-84a0-0bdd2832a91f"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IVdsVdProvider
    {
        void QueryVDisks(out IEnumVdsObject ppEnum);
        void CreateVDisk(); // Unported method
        void AddVDisk(); // Unported method
        void GetDiskFromVDisk(IVdsVDisk pVDisk, out IVdsDisk ppDisk);
        void GetVDiskFromDisk(IVdsDisk pDisk, out IVdsVDisk ppVDisk);
    }

    [ComImport, Guid("9c38ed61-d565-4728-aeee-c80952f0ecde")]
    public class VdsServiceLoader
    {
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct Signature
    {
        [FieldOffset(0)]
        public uint dwSignature;
        [FieldOffset(0)]
        public Guid DiskGuid;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct VDS_DISK_PROP
    {
        public Guid Id;
        public VDS_DISK_STATUS Status;
        public VDS_LUN_RESERVE_MODE ReserveMode;
        public VDS_HEALTH health;
        public uint dwDeviceType;
        public uint dwMediaType;
        public ulong ullSize;
        public uint ulBytesPerSector;
        public uint ulSectorsPerTrack;
        public uint ulTracksPerCylinder;
        public uint ulFlags;
        public VDS_STORAGE_BUS_TYPE BusType;
        public VDS_PARTITION_STYLE PartitionStyle;
        public Signature dwSignature;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pwszDiskAddress;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pwszName;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pwszFriendlyName;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pwszAdaptorName;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pwszDevicePath;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct VIRTUAL_STORAGE_TYPE
    {
        public uint DeviceId;
        public Guid VendorId;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct VDS_VDISK_PROPERTIES
    {
        public Guid Id;
        public VDS_VDISK_STATE State;
        public VIRTUAL_STORAGE_TYPE VirtualDeviceType;
        public ulong VirtualSize;
        public ulong PhysicalSize;
        [MarshalAs(UnmanagedType.LPWStr)]
        public String pPath;
        [MarshalAs(UnmanagedType.LPWStr)]
        public String pDeviceName;
        public DEPENDENT_DISK_FLAG DiskFlag;
        public bool bIsChild;
        [MarshalAs(UnmanagedType.LPWStr)]
        public String pParentPath;
    }

    public enum DEPENDENT_DISK_FLAG
    {
        DEPENDENT_DISK_FLAG_NONE = 0x00000000,
        DEPENDENT_DISK_FLAG_MULT_BACKING_FILES = 0x00000001,
        DEPENDENT_DISK_FLAG_FULLY_ALLOCATED = 0x00000002,
        DEPENDENT_DISK_FLAG_READ_ONLY = 0x00000004,
        DEPENDENT_DISK_FLAG_REMOTE = 0x00000008,
        DEPENDENT_DISK_FLAG_SYSTEM_VOLUME = 0x00000010,
        DEPENDENT_DISK_FLAG_SYSTEM_VOLUME_PARENT = 0x00000020,
        DEPENDENT_DISK_FLAG_REMOVABLE = 0x00000040,
        DEPENDENT_DISK_FLAG_NO_DRIVE_LETTER = 0x00000080,
        DEPENDENT_DISK_FLAG_PARENT = 0x00000100,
        DEPENDENT_DISK_FLAG_NO_HOST_DISK = 0x00000200,
        DEPENDENT_DISK_FLAG_PERMANENT_LIFETIME = 0x00000400,
    }

    public enum VDS_DISK_STATUS
    {
        VDS_DS_UNKNOWN = 0,
        VDS_DS_ONLINE = 1,
        VDS_DS_NOT_READY = 2,
        VDS_DS_NO_MEDIA = 3,
        VDS_DS_FAILED = 5,
        VDS_DS_MISSING = 6,
        VDS_DS_OFFLINE = 4
    }

    public enum VDS_HEALTH
    {
        VDS_H_UNKNOWN = 0,
        VDS_H_HEALTHY = 1,
        VDS_H_REBUILDING = 2,
        VDS_H_STALE = 3,
        VDS_H_FAILING = 4,
        VDS_H_FAILING_REDUNDANCY = 5,
        VDS_H_FAILED_REDUNDANCY = 6,
        VDS_H_FAILED_REDUNDANCY_FAILING = 7,
        VDS_H_FAILED = 8,
        VDS_H_REPLACED = 9,
        VDS_H_PENDING_FAILURE = 10,
        VDS_H_DEGRADED = 11
    }

    public enum VDS_LUN_RESERVE_MODE
    {
        VDS_LRM_NONE = 0,
        VDS_LRM_EXCLUSIVE_RW = 1,
        VDS_LRM_EXCLUSIVE_RO = 2,
        VDS_LRM_SHARED_RO = 3,
        VDS_LRM_SHARED_RW = 4
    }

    public enum VDS_PARTITION_STYLE
    {
        VDS_PST_UNKNOWN = 0,
        VDS_PST_MBR = 1,
        VDS_PST_GPT = 2
    }

    public enum VDS_QUERY_PROVIDER_FLAG
    {
        VDS_QUERY_SOFTWARE_PROVIDERS = 0x1,
        VDS_QUERY_HARDWARE_PROVIDERS = 0x2,
        VDS_QUERY_VIRTUALDISK_PROVIDERS = 0x4
    }

    public enum VDS_STORAGE_BUS_TYPE
    {
        VDSBusTypeUnknown = 0,
        VDSBusTypeScsi = 0x1,
        VDSBusTypeAtapi = 0x2,
        VDSBusTypeAta = 0x3,
        VDSBusType1394 = 0x4,
        VDSBusTypeSsa = 0x5,
        VDSBusTypeFibre = 0x6,
        VDSBusTypeUsb = 0x7,
        VDSBusTypeRAID = 0x8,
        VDSBusTypeiScsi = 0x9,
        VDSBusTypeSas = 0xa,
        VDSBusTypeSata = 0xb,
        VDSBusTypeSd = 0xc,
        VDSBusTypeMmc = 0xd,
        VDSBusTypeMax = 0xe,
        VDSBusTypeFileBackedVirtual = 0xf,
        VDSBusTypeMaxReserved = 0x7f
    }

    public enum VDS_VDISK_STATE
    {
        VDS_VST_UNKNOWN = 0,
        VDS_VST_ADDED,
        VDS_VST_OPEN,
        VDS_VST_ATTACH_PENDING,
        VDS_VST_ATTACHED_NOT_OPEN,
        VDS_VST_ATTACHED,
        VDS_VST_DETACH_PENDING,
        VDS_VST_COMPACTING,
        VDS_VST_MERGING,
        VDS_VST_EXPANDING,
        VDS_VST_DELETED,
        VDS_VST_MAX
    }
}


Native Solution

Below is a native application that uses the VDS COM interfaces to:

  • Load the VDS service
  • Query for the Virtual Disk Providers
  • List all the Virtual Disk handled by each provider:
    • The virtual disk's properties gives its GUID, its full driver path, its volume size and its disk file (i.e. C:\Disk.vhd).
    • A virtual disk can be also be queried as a generic disk and gives its name (i.e. \\?\PhysicalDrive1), its friendly name and other properties.

#include "initguid.h"
#include "vds.h"
#include <stdio.h>

#pragma comment( lib, "ole32.lib" )
#pragma comment( lib, "rpcrt4.lib" )

// Simple macro to release non-null interfaces.
#define _SafeRelease(x) {if (NULL != x) { x->Release(); x = NULL; } }

void exploreVDiskProvider(IVdsVdProvider *pVdProvider);

int __cdecl main(void) 
{
    HRESULT hResult;
    ULONG ulFetched = 0;
    BOOL bDone = FALSE;

    IVdsServiceLoader *pLoader = NULL;
    IVdsService *pService = NULL;
    IEnumVdsObject *pProviderEnum = NULL;
    IUnknown *pUnknown = NULL;
    IVdsVdProvider *pVdProvider = NULL;

    // Initialize COM
    hResult = CoInitialize(NULL);
    if (FAILED(hResult)) goto bail;

    // For this, get a pointer to the VDS Loader
    hResult = CoCreateInstance(CLSID_VdsLoader,
        NULL,
        CLSCTX_LOCAL_SERVER,
        IID_IVdsServiceLoader,
        (void **) &pLoader);
    if (FAILED(hResult)) goto bail;

    printf("Loading VDS Service...\n");

    // Launch the VDS service. 
    hResult = pLoader->LoadService(NULL, &pService);

    // We're done with the Loader interface at this point.
    _SafeRelease(pLoader); 

    if (FAILED(hResult)) goto bail;

    // Wait for service to be ready
    hResult = pService->WaitForServiceReady();
    if (FAILED(hResult)) goto bail;

    printf("VDS Service Loaded\n");

    // Query for virtual disk providers
    hResult = pService->QueryProviders(VDS_QUERY_VIRTUALDISK_PROVIDERS, &pProviderEnum);
    if (FAILED(hResult)) goto bail;

    printf("Querying providers...\n");

    // Iterate over virtual disk providers
    while(1) 
    {
        ulFetched = 0;
        hResult = pProviderEnum->Next(1, &pUnknown, &ulFetched);
        if (FAILED(hResult)) {
            break;
        }
        if (hResult == S_FALSE) {
            break;
        }

        // Cast the current value to a virtual disk provider
        hResult = pUnknown->QueryInterface(IID_IVdsVdProvider, (void **) &pVdProvider); 
        if (FAILED(hResult)) goto bail;

        printf("VDS Virtual Disk Provider Found\n");

        exploreVDiskProvider(pVdProvider);

        _SafeRelease(pVdProvider);

        _SafeRelease(pUnknown);
    }

    getchar();
    return 0;

bail:
    printf("Failed hr=%x\n", hResult);
    return 1;
}

void exploreVDiskProvider(IVdsVdProvider *pVdProvider) {
    HRESULT hResult;
    ULONG ulFetched = 0;

    IEnumVdsObject *pVDiskEnum = NULL;
    IVdsVDisk *pVDisk = NULL;
    IUnknown *pUnknown = NULL;
    IVdsVolume *pVolume = NULL;
    VDS_VDISK_PROPERTIES vdiskProperties = { 0 };
    TCHAR *uuid = NULL;
    IVdsDisk *pDisk = NULL;
    VDS_DISK_PROP diskProperties = { 0 };

    // Query the disks handled by the provider
    hResult = pVdProvider->QueryVDisks(&pVDiskEnum);
    if (FAILED(hResult)) goto bail;

    printf("Querying virtual disks...\n");

    // Iterate over virtual disks
    while(1) 
    {
        ulFetched = 0;
        hResult = pVDiskEnum->Next(1, &pUnknown, &ulFetched);
        if (hResult == S_FALSE) {
            break;
        }

        if (FAILED(hResult)) goto bail;

        // Cast the current value to a disk
        hResult = pUnknown->QueryInterface(IID_IVdsVDisk, (void **) &pVDisk);
        if (FAILED(hResult)) goto bail;

        printf("Virtual disk Found\n");

        // Get the disk's properties and display some of them
        hResult = pVDisk->GetProperties(&vdiskProperties);
        if (FAILED(hResult)) goto bail;

        // Convert the GUID to a string
        UuidToString(&vdiskProperties.Id, (RPC_WSTR *) &uuid);

        // Dump some properties
        printf("-> Disk Id=%ws\n", uuid);
        printf("-> Disk Device Name=%ws\n", vdiskProperties.pDeviceName);
        printf("-> Disk Path=%ws\n", vdiskProperties.pPath);

        // Get the disk instance from the virtual disk
        hResult = pVdProvider->GetDiskFromVDisk(pVDisk, &pDisk);
        if (FAILED(hResult)) goto bail;

        _SafeRelease(pVDisk);

        _SafeRelease(pUnknown);

        // Get the disk's properties and display some of them
        hResult = pDisk->GetProperties(&diskProperties);
        if (FAILED(hResult)) goto bail;

        printf("-> Disk Name=%ws\n", diskProperties.pwszName);
        printf("-> Disk Friendly Name=%ws\n", diskProperties.pwszFriendlyName);
    }

    return;

bail:
    printf("Failed hr=%x\n", hResult);
}

这篇关于从磁盘号码检索虚拟磁盘文件名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆