summaryrefslogtreecommitdiff
path: root/tests/src/Interop/MarshalAPI/GetObjectForNativeVariant/GetObjectForNativeVariant.cs
blob: 00710a37bcc1cf2277f3edd398fa96a29f4995d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using CoreFXTestLibrary;

public class GetObjectForNativeVariantTest 
{  
    [StructLayout(LayoutKind.Sequential)]
    public struct Record {
            private IntPtr _record;
            private IntPtr _recordInfo;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct UnionTypes {
            [FieldOffset(0)] internal SByte _i1;
            [FieldOffset(0)] internal Int16 _i2;
            [FieldOffset(0)] internal Int32 _i4;
            [FieldOffset(0)] internal Int64 _i8;
            [FieldOffset(0)] internal Byte _ui1;
            [FieldOffset(0)] internal UInt16 _ui2;
            [FieldOffset(0)] internal UInt32 _ui4;
            [FieldOffset(0)] internal UInt64 _ui8;
            [FieldOffset(0)] internal Int32 _int;
            [FieldOffset(0)] internal UInt32 _uint;
            [FieldOffset(0)] internal Single _r4;
            [FieldOffset(0)] internal Double _r8;
            [FieldOffset(0)] internal Int64 _cy;
            [FieldOffset(0)] internal double _date;
            [FieldOffset(0)] internal IntPtr _bstr;
            [FieldOffset(0)] internal IntPtr _unknown;
            [FieldOffset(0)] internal IntPtr _dispatch;
            [FieldOffset(0)] internal IntPtr _pvarVal;
            [FieldOffset(0)] internal IntPtr _byref;
            [FieldOffset(0)] internal Record _record;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct TypeUnion
    {
        public ushort vt;
        public ushort wReserved1;
        public ushort wReserved2;
        public ushort wReserved3;
        public UnionTypes _unionTypes;
    }

    [StructLayout(LayoutKind.Explicit)]
    internal struct Variant
    {
       [FieldOffset(0)] public TypeUnion  m_Variant;
       [FieldOffset(0)]  public decimal m_decimal;
    }
        
    public static void NullParameter()
    {
        Assert.Throws<ArgumentNullException>(() => Marshal.GetObjectForNativeVariant(IntPtr.Zero));
        Assert.Throws<ArgumentNullException>(() => Marshal.GetObjectForNativeVariant<int>(IntPtr.Zero));
    }
    
    [DllImport(@"oleaut32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
    static extern Int32 VariantClear(IntPtr pvarg);
    
    private static void DeleteVariant(IntPtr pVariant)
    {
        VariantClear(pVariant);
        Marshal.FreeHGlobal(pVariant);
    }

    public static void Decimal()
    {
        Variant v = new Variant();
        IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
        Marshal.GetNativeVariantForObject(3.14m, pNative);
        decimal d = Marshal.GetObjectForNativeVariant<decimal>(pNative);
        Assert.AreEqual(3.14m, d);

        DeleteVariant(pNative);
    }
        
    public static void PrimitiveType()
    {
        Variant v = new Variant();
        IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
        Marshal.GetNativeVariantForObject<ushort>(99, pNative);
        ushort actual = Marshal.GetObjectForNativeVariant<ushort>(pNative);
        Assert.AreEqual(99, actual);

        DeleteVariant(pNative);
    }
        
    public static void StringType()
    {
        Variant v = new Variant();
        IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
        Marshal.GetNativeVariantForObject<string>("99", pNative);
        string actual = Marshal.GetObjectForNativeVariant<string>(pNative);
        Assert.AreEqual("99", actual);

        DeleteVariant(pNative);
    }
        
    public static void DoubleType()
    {
        Variant v = new Variant();
        IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
        Marshal.GetNativeVariantForObject<double>(3.14, pNative);
        double actual = Marshal.GetObjectForNativeVariant<double>(pNative);
        Assert.AreEqual(3.14, actual);

        DeleteVariant(pNative);
    }
        
    public static void IUnknownType()
    {
        Variant v = new Variant();
        object obj = new object();

        // Technically we don't need this - but this is necessary for forcing
        // COM initialization
        IntPtr pUnk = Marshal.GetIUnknownForObject(obj);
        IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
        Marshal.GetNativeVariantForObject<object>(obj, pNative);
        object actual = Marshal.GetObjectForNativeVariant<object>(pNative);
        Assert.AreEqual(obj, actual);
        Marshal.Release(pUnk);

        DeleteVariant(pNative);
    }

    public static int Main(String[] unusedArgs)
    {
        IUnknownType();
        DoubleType();
        StringType();
        PrimitiveType();
        Decimal();
        NullParameter();
        return 100;
    }
}