Search code examples
c#windowswinapimarshallingunmanaged

marshall unmanaged structure to C#


how can I translate this unmanaged structure into c#.

typedef struct _EC_VARIANT {
  union {
    BOOL                            BooleanVal;
    UINT32                          UInt32Val;
    ULONGLONG                       DateTimeVal;
    LPCWSTR                         StringVal;
    PBYTE                           BinaryVal;
    BOOL                            *BooleanArr;
    INT32                           *Int32Arr;
    LPWSTR                          *StringArr;
    EC_OBJECT_ARRAY_PROPERTY_HANDLE PropertyHandleVal;
  };
  DWORD Count;
  DWORD Type;
} EC_VARIANT, *PEC_VARIANT;

docs: https://learn.microsoft.com/ru-ru/windows/win32/api/evcoll/ns-evcoll-ec_variant i try this code:

uint get = Internals.EcOpenSubscription("adfs", (uint)WecAcessTypes.EC_READ_ACCESS, (uint)WecFlags.EC_OPEN_EXISTING);
Console.WriteLine($"addr :{get}");
byte[] some = new byte[16];
uint a = 0;
bool success = Internals.EcGetSubscriptionProperty(get, (uint)EC_SUBSCRIPTION_PROPERTY_ID.EcSubscriptionEventSources, 0, 128, some, out a);
if (!success)
{
    Console.WriteLine("err EcSubscriptionEventSources");
    Console.ReadKey();
    return;
}
foreach (byte b in some)
{
    Console.Write(b);
}
GCHandle gCHandle = GCHandle.Alloc(some, GCHandleType.Pinned);
EC_VARIANT eC = (EC_VARIANT)Marshal.PtrToStructure(gCHandle.AddrOfPinnedObject(), typeof(EC_VARIANT));
Console.WriteLine($"\n{eC.Type} {eC.EC_OBJECT_ARRAY_PROPERTY_HANDLE}");
Console.WriteLine($"length {a}");
Console.ReadKey();

my struct:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct EC_VARIANT
{
    public uint BooleanVal;
    public uint UInt32Val;
    public ulong DateTimeVal;
    public IntPtr StringVal;
    public IntPtr BinaryVal;
    public IntPtr BoolArr;
    public IntPtr Int32Arr;
    public IntPtr StringArr;
    public int EC_OBJECT_ARRAY_PROPERTY_HANDLE;
    public int Type;
    public int Count;
}

I tried to use LayoutKind.Explicit and arrange the fields differently but to no avail


Solution

  • The equivalent C# structure would be this:

        public partial struct EC_VARIANT
        {
            [StructLayout(LayoutKind.Explicit)]
            public struct EC_VARIANT_UNION
            {
                [FieldOffset(0)]
                public bool BooleanVal;
    
                [FieldOffset(0)]
                public uint UInt32Val;
    
                [FieldOffset(0)]
                public ulong DateTimeVal;
    
                [FieldOffset(0)]
                public IntPtr StringVal;
    
                [FieldOffset(0)]
                public IntPtr BinaryVal;
    
                [FieldOffset(0)]
                public IntPtr BooleanArr;
    
                [FieldOffset(0)]
                public IntPtr Int32Arr;
    
                [FieldOffset(0)]
                public IntPtr StringArr;
    
                [FieldOffset(0)]
                public IntPtr PropertyHandleVal;
            }
    
            public EC_VARIANT_UNION Anonymous;
            public uint Count;
            public uint Type;
        }