I am trying to create some vhd/vhdx files using the VHD API in C#.
There's a C++ union that looks like this:
typedef struct _CREATE_VIRTUAL_DISK_PARAMETERS
{
CREATE_VIRTUAL_DISK_VERSION Version;
union
{
struct
{
GUID UniqueId;
ULONGLONG MaximumSize;
ULONG BlockSizeInBytes;
ULONG SectorSizeInBytes;
PCWSTR ParentPath;
PCWSTR SourcePath;
} Version1;
struct
{
GUID UniqueId;
ULONGLONG MaximumSize;
ULONG BlockSizeInBytes;
ULONG SectorSizeInBytes;
ULONG PhysicalSectorSizeInBytes;
PCWSTR ParentPath;
PCWSTR SourcePath;
OPEN_VIRTUAL_DISK_FLAG OpenFlags;
VIRTUAL_STORAGE_TYPE ParentVirtualStorageType;
VIRTUAL_STORAGE_TYPE SourceVirtualStorageType;
GUID ResiliencyGuid;
} Version2;
struct
{
GUID UniqueId;
ULONGLONG MaximumSize;
ULONG BlockSizeInBytes;
ULONG SectorSizeInBytes;
ULONG PhysicalSectorSizeInBytes;
PCWSTR ParentPath;
PCWSTR SourcePath;
OPEN_VIRTUAL_DISK_FLAG OpenFlags;
VIRTUAL_STORAGE_TYPE ParentVirtualStorageType;
VIRTUAL_STORAGE_TYPE SourceVirtualStorageType;
GUID ResiliencyGuid;
PCWSTR SourceLimitPath;
VIRTUAL_STORAGE_TYPE BackingStorageType;
} Version3;
};
} CREATE_VIRTUAL_DISK_PARAMETERS, *PCREATE_VIRTUAL_DISK_PARAMETERS;
I'm trying to convert that to C#, but not having much luck. I'm not interested in Version3 at all, so am leaving that out.
I've tried a number of things and the best I could get to was having Version2 working (by doing something really bizarre), but I've never managed to get Version1 and Version2 working at the same time.
The solution that has wielded the best results so far has been this, but there has to be something wrong there because Version1 simply doesn't work, and SectorSizeInBytes
in Version1 is a ulong
rather than uint
(if I change it to uint
like it should be, I break Version2 and Version1 still doesn't work!)
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
public struct CreateVirtualDiskParameters
{
[FieldOffset(0)] public CreateVirtualDiskParametersVersion1 Version1;
[FieldOffset(0)] public CreateVirtualDiskParametersVersion2 Version2;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CreateVirtualDiskParametersVersion1
{
public CreateVirtualDiskVersion Version;
public Guid UniqueId;
public ulong MaximumSize;
public uint BlockSizeInBytes;
public ulong SectorSizeInBytes;
public string ParentPath;
public string SourcePath;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CreateVirtualDiskParametersVersion2
{
public CreateVirtualDiskVersion Version;
public Guid UniqueId;
public ulong MaximumSize;
public uint BlockSizeInBytes;
public uint SectorSizeInBytes;
public uint PhysicalSectorSizeInBytes;
public string ParentPath;
public string SourcePath;
public OpenVirtualDiskFlags OpenFlags;
public VirtualStorageType ParentVirtualStorageType;
public VirtualStorageType SourceVirtualStorageType;
public Guid ResiliencyGuid;
}
I know theoretically the Version
field should be set outside the Version structs and I have tried that as well, but it just breaks things even more funnily enough...
So, can someone advise how to properly translate the above to C#, leaving out the Version3 struct as that's not needed?
ULONGLONG (64 bit)
andULONG (32 bit)
both seem to be mapped toulong (64 bit)
. – Plasiaoffsetof
macro. Let it print the offsets for you and define those offsets explicitly on the C# side. – WrinkleParentPath
andSourcePath
are raw pointers in the native structs, but thestring
class in the C# code, which has more than just one pointer in it. – Cousteau