Пример #1
0
        // VARENUMs that are VARIANT only (e.g. not valid for PROPVARIANT)
        //
        //  VT_DISPATCH
        //  VT_UNKNOWN
        //  VT_DECIMAL
        //  VT_UINT
        //  VT_ARRAY
        //  VT_BYREF

        public override object?GetData()
        {
            VARENUM propertyType = RawVariantType;

            if ((propertyType & VARENUM.VT_BYREF) != 0 ||
                (propertyType & VARENUM.VT_ARRAY) != 0)
            {
                // Not legit for PROPVARIANT
                throw new InvalidOleVariantTypeException();
            }

            if ((propertyType & VARENUM.VT_VECTOR) != 0)
            {
                throw new NotImplementedException();
            }

            propertyType &= VARENUM.VT_TYPEMASK;

            switch (propertyType)
            {
            case VARENUM.VT_DISPATCH:
            case VARENUM.VT_UNKNOWN:
            case VARENUM.VT_DECIMAL:
            case VARENUM.VT_UINT:
                throw new InvalidOleVariantTypeException();
            }

            return(base.GetData());
        }
Пример #2
0
        public Type Test_ObjectConversion_IConvertible(VARENUM vt, TypeCode code)
        {
            var convertible = new ConvertibleTest(code);
            var result      = VariantConverter.ChangeType(convertible, vt);

            return(result.GetType());
        }
        public void SAFEARRAY_CreateSingleDimension_GetProperties_Success(ushort vt, ushort expectedFeatures, uint expectedCbElements)
        {
            var saBound = new SAFEARRAYBOUND
            {
                cElements = 10,
                lLbound   = 1
            };
            SAFEARRAY *psa = SafeArrayCreate((VARENUM)vt, 1, &saBound);

            Assert.True(psa != null);

            try
            {
                Assert.Equal(1u, psa->cDims);
                Assert.Equal((FADF)expectedFeatures, psa->fFeatures);
                Assert.Equal((uint)expectedCbElements, psa->cbElements);
                Assert.Equal(0u, psa->cLocks);
                Assert.True(psa->pvData != null);
                Assert.Equal(10u, psa->rgsabound[0].cElements);
                Assert.Equal(1, psa->rgsabound[0].lLbound);

                VARENUM arrayVt = VARENUM.EMPTY;
                HRESULT hr      = SafeArrayGetVartype(psa, &arrayVt);
                Assert.Equal(HRESULT.S_OK, hr);
                Assert.Equal((VARENUM)vt, arrayVt);
            }
            finally
            {
                HRESULT hr = SafeArrayDestroy(psa);
                Assert.Equal(HRESULT.S_OK, hr);
            }
        }
Пример #4
0
        // VARENUMs that are VARIANT only (e.g. not valid for PROPVARIANT)
        //
        //  VT_DISPATCH
        //  VT_UNKNOWN
        //  VT_DECIMAL
        //  VT_UINT
        //  VT_ARRAY
        //  VT_BYREF
        //
        protected virtual unsafe object GetCoreType(VARENUM propertyType, void *data)
        {
            switch (propertyType)
            {
            case VARENUM.VT_I4:
            case VARENUM.VT_INT:
            case VARENUM.VT_ERROR:     // SCODE
                return(*((int *)data));

            case VARENUM.VT_UI4:
            case VARENUM.VT_UINT:
                return(*((uint *)data));

            case VARENUM.VT_I2:
                return(*((short *)data));

            case VARENUM.VT_UI2:
                return(*((ushort *)data));

            case VARENUM.VT_I1:
                return(*((sbyte *)data));

            case VARENUM.VT_UI1:
                return(*((byte *)data));

            case VARENUM.VT_CY:     // Currency (long long)
                return(*((long *)data));

            case VARENUM.VT_R4:
                return(*((float *)data));

            case VARENUM.VT_R8:
                return(*((double *)data));

            case VARENUM.VT_DECIMAL:
                return((*((DECIMAL *)data)).ToDecimal());

            case VARENUM.VT_BOOL:
                // VARIANT_TRUE is -1
                return(*((short *)data) == -1);

            case VARENUM.VT_BSTR:
                return(Marshal.PtrToStringBSTR((IntPtr)(*((void **)data))));

            case VARENUM.VT_VARIANT:
                return(new VARIANT(new IntPtr(*((void **)data)), ownsHandle: false));

            case VARENUM.VT_DATE:
                return(Conversion.VariantDateToDateTime(*((double *)data)));

            case VARENUM.VT_RECORD:
            case VARENUM.VT_DISPATCH:
            case VARENUM.VT_UNKNOWN:
                throw new NotImplementedException();

            default:
                return(s_UnsupportedObject);
            }
        }
Пример #5
0
                static void HeapTransposeArray(SAFEARRAY *psa, Array array, VARENUM arrayType)
                {
                    var indices = new int[array.Rank];
                    var lower   = new int[array.Rank];
                    var upper   = new int[array.Rank];

                    InternalTransposeArray(psa, array, arrayType, indices, lower, upper);
                }
Пример #6
0
                static void StackTransposeArray(SAFEARRAY *psa, Array array, VARENUM arrayType)
                {
                    Span <int> indices = stackalloc int[array.Rank];
                    Span <int> lower   = stackalloc int[array.Rank];
                    Span <int> upper   = stackalloc int[array.Rank];

                    InternalTransposeArray(psa, array, arrayType, indices, lower, upper);
                }
Пример #7
0
            public void Clear()
            {
                fixed(VARIANT *pThis = &this)
                {
                    VariantClear(pThis);
                }

                vt    = VARENUM.EMPTY;
                data1 = IntPtr.Zero;
                data2 = IntPtr.Zero;
            }
Пример #8
0
 private static void TransposeArray(SAFEARRAY *psa, Array array, VARENUM arrayType)
 {
     if (array.Rank <= 32)
     {
         StackTransposeArray(psa, array, arrayType);
     }
     else
     {
         Debug.Fail("The CLR should not support arrays with more than 32 dimensions.");
         HeapTransposeArray(psa, array, arrayType);
     }
Пример #9
0
        public static object ChangeType(object value, VARENUM vt, CultureInfo cultureInfo)
        {
            object result = null;
            var    hr     = cultureInfo == null
                ? VariantChangeType(ref result, ref value, VariantConversionFlags.NO_FLAGS, vt)
                : VariantChangeTypeEx(ref result, ref value, cultureInfo.LCID, VariantConversionFlags.NO_FLAGS, vt);

            if (HRESULT_FAILED(hr))
            {
                throw Marshal.GetExceptionForHR(hr);
            }

            return(result);
        }
Пример #10
0
            public void Clear()
            {
                if ((vt == VARENUM.UNKNOWN || vt == VARENUM.DISPATCH) && data1 != IntPtr.Zero)
                {
                    Marshal.Release(data1);
                }

                if (vt == VARENUM.BSTR && data1 != IntPtr.Zero)
                {
                    Oleaut32.SysFreeString(data1);
                }

                data1 = data2 = IntPtr.Zero;
                vt    = VARENUM.EMPTY;
            }
        public void SAFEARRAY_CreateSingleDimensionRECORD_GetProperties_Success()
        {
            var saBound = new SAFEARRAYBOUND
            {
                cElements = 10,
                lLbound   = 1
            };
            var    record  = new CustomRecordInfo();
            IntPtr pRecord = Marshal.GetComInterfaceForObject <CustomRecordInfo, IRecordInfo>(record);

            try
            {
                SAFEARRAY *psa = SafeArrayCreateEx(VARENUM.RECORD, 1, &saBound, pRecord);
                Assert.True(psa != null);

                try
                {
                    Assert.Equal(1u, psa->cDims);
                    Assert.Equal(FADF.RECORD, psa->fFeatures);
                    Assert.Equal((uint)sizeof(int), psa->cbElements);
                    Assert.Equal(0u, psa->cLocks);
                    Assert.True(psa->pvData != null);
                    Assert.Equal(10u, psa->rgsabound[0].cElements);
                    Assert.Equal(1, psa->rgsabound[0].lLbound);

                    VARENUM arrayVt = VARENUM.EMPTY;
                    HRESULT hr      = SafeArrayGetVartype(psa, &arrayVt);
                    Assert.Equal(HRESULT.S_OK, hr);
                    Assert.Equal(VARENUM.RECORD, arrayVt);
                }
                finally
                {
                    HRESULT hr = SafeArrayDestroy(psa);
                    Assert.Equal(HRESULT.S_OK, hr);
                }
            }
            finally
            {
                Marshal.Release(pRecord);
            }
        }
Пример #12
0
        protected override unsafe object?GetCoreType(VARENUM propertyType, void *data)
        {
            object?value = base.GetCoreType(propertyType, data);

            if (!ReferenceEquals(value, s_UnsupportedObject))
            {
                return(value);
            }

            switch (propertyType)
            {
            case VARENUM.VT_I8:
                return(*((long *)data));

            case VARENUM.VT_UI8:
                return(*((ulong *)data));

            case VARENUM.VT_LPSTR:
                return(Marshal.PtrToStringAnsi((IntPtr)data));

            case VARENUM.VT_LPWSTR:
                return(Marshal.PtrToStringUni((IntPtr)data));

            case VARENUM.VT_CLSID:
                return(Marshal.PtrToStructure <Guid>((IntPtr)(*((void **)data))));

            case VARENUM.VT_FILETIME:
            case VARENUM.VT_BLOB:
            case VARENUM.VT_STREAM:
            case VARENUM.VT_STORAGE:
            case VARENUM.VT_STREAMED_OBJECT:
            case VARENUM.VT_STORED_OBJECT:
            case VARENUM.VT_VERSIONED_STREAM:
            case VARENUM.VT_BLOB_OBJECT:
            case VARENUM.VT_CF:
            case VARENUM.VT_VECTOR:
            default:
                return(s_UnsupportedObject);
            }
        }
Пример #13
0
        public unsafe virtual object GetData()
        {
            VARENUM propertyType = VariantType;

            switch (propertyType)
            {
            case VARENUM.VT_EMPTY:
            case VARENUM.VT_NULL:
                return(null);
            }

            if (IsArray)
            {
                throw new NotImplementedException();
            }

            void *data = handle.Offset(DataOffset);

            if (IsByRef)
            {
                data = *((void **)data);
            }
            else if (propertyType == VARENUM.VT_DECIMAL)
            {
                // DECIMAL starts at the beginning of the VARIANT, with the VARIANT's type occupying
                // the reserved ushort in the DECIMAL and the DECIMAL occupying the reserved WORDs
                // in the VARIANT.
                data = handle.ToPointer();
            }

            object result = GetCoreType(propertyType, data);

            if (ReferenceEquals(result, s_UnsupportedObject))
            {
                throw new InvalidOleVariantTypeException();
            }

            return(result);
        }
Пример #14
0
                static void InternalTransposeArray(SAFEARRAY *psa, Array array, VARENUM arrayType, Span <int> indices, Span <int> lower, Span <int> upper)
                {
                    int lastIndex = array.Rank - 1;
                    int i;

                    for (i = 0; i < array.Rank; i++)
                    {
                        indices[i] = lower[i] = array.GetLowerBound(i);
                        upper[i]   = array.GetUpperBound(i);
                    }

                    // Loop through all the indices.
                    while (true)
                    {
BeginMainLoop:

                        SetArrayValue(psa, array, indices, lower, arrayType);

                        for (i = lastIndex; i > 0;)
                        {
                            if (++indices[i] <= upper[i])
                            {
                                goto BeginMainLoop;
                            }

                            indices[i] = lower[i];
                            --i;
                        }

                        // Special case for the first index, it must be enumerated only once
                        if (++indices[0] > upper[0])
                        {
                            break;
                        }
                    }
                }
Пример #15
0
 public static object ChangeType(object value, VARENUM vt)
 {
     return(ChangeType(value, vt, null));
 }
Пример #16
0
 public void Clear()
 {
     PropVariantClear(ref this);
     vt   = VARENUM.EMPTY;
     data = new VARIANTUnion();
 }
Пример #17
0
            private static object?ToArray(SAFEARRAY *psa, VARENUM vt)
            {
                if (psa is null)
                {
                    return(null);
                }

                VARENUM arrayType = vt & ~VARENUM.ARRAY;
                Array   array     = CreateArrayFromSafeArray(psa, arrayType);

                HRESULT hr = SafeArrayLock(psa);

                Debug.Assert(hr == HRESULT.S_OK);

                try
                {
                    if (array.Rank == 1)
                    {
                        switch (arrayType)
                        {
                        case VARENUM.I1:
                            new Span <sbyte>(psa->pvData, array.Length)
                            .CopyTo(GetSpan <sbyte>(array));
                            break;

                        case VARENUM.UI1:
                            new Span <byte>(psa->pvData, array.Length)
                            .CopyTo(GetSpan <byte>(array));
                            break;

                        case VARENUM.I2:
                            new Span <short>(psa->pvData, array.Length)
                            .CopyTo(GetSpan <short>(array));
                            break;

                        case VARENUM.UI2:
                            new Span <ushort>(psa->pvData, array.Length)
                            .CopyTo(GetSpan <ushort>(array));
                            break;

                        case VARENUM.I4:
                        case VARENUM.INT:
                            new Span <int>(psa->pvData, array.Length)
                            .CopyTo(GetSpan <int>(array));
                            break;

                        case VARENUM.UI4:
                        case VARENUM.UINT:
                        case VARENUM.ERROR:     // Not explicitly mentioned in the docs but trivial to implement.
                            new Span <uint>(psa->pvData, array.Length)
                            .CopyTo(GetSpan <uint>(array));
                            break;

                        case VARENUM.I8:
                            new Span <long>(psa->pvData, array.Length)
                            .CopyTo(GetSpan <long>(array));
                            break;

                        case VARENUM.UI8:
                            new Span <ulong>(psa->pvData, array.Length)
                            .CopyTo(GetSpan <ulong>(array));
                            break;

                        case VARENUM.R4:
                            new Span <float>(psa->pvData, array.Length)
                            .CopyTo(GetSpan <float>(array));
                            break;

                        case VARENUM.R8:
                            new Span <double>(psa->pvData, array.Length)
                            .CopyTo(GetSpan <double>(array));
                            break;

                        case VARENUM.BOOL:
                        {
                            var data   = new Span <VARIANT_BOOL>(psa->pvData, array.Length);
                            var result = GetSpan <bool>(array);
                            for (int i = 0; i < data.Length; i++)
                            {
                                result[i] = data[i] != VARIANT_BOOL.FALSE;
                            }

                            break;
                        }

                        case VARENUM.DECIMAL:
                        {
                            var data   = new Span <DECIMAL>(psa->pvData, array.Length);
                            var result = GetSpan <decimal>(array);
                            for (int i = 0; i < data.Length; i++)
                            {
                                result[i] = data[i].ToDecimal();
                            }

                            break;
                        }

                        case VARENUM.CY:
                        {
                            var data   = new Span <long>(psa->pvData, array.Length);
                            var result = GetSpan <decimal>(array);
                            for (int i = 0; i < data.Length; i++)
                            {
                                result[i] = decimal.FromOACurrency(data[i]);
                            }

                            break;
                        }

                        case VARENUM.DATE:
                        {
                            var data   = new Span <double>(psa->pvData, array.Length);
                            var result = GetSpan <DateTime>(array);
                            for (int i = 0; i < data.Length; i++)
                            {
                                result[i] = DateTime.FromOADate(data[i]);
                            }

                            break;
                        }

                        case VARENUM.BSTR:
                        {
                            var data   = new Span <IntPtr>(psa->pvData, array.Length);
                            var result = GetSpan <string?>(array);
                            for (int i = 0; i < data.Length; i++)
                            {
                                result[i] = Marshal.PtrToStringUni(data[i]);
                            }

                            break;
                        }

                        case VARENUM.DISPATCH:
                        case VARENUM.UNKNOWN:
                        {
                            var data   = new Span <IntPtr>(psa->pvData, array.Length);
                            var result = GetSpan <object?>(array);
                            for (int i = 0; i < data.Length; i++)
                            {
                                if (data[i] == IntPtr.Zero)
                                {
                                    result[i] = null;
                                }
                                else
                                {
                                    result[i] = Marshal.GetObjectForIUnknown(data[i]);
                                }
                            }

                            break;
                        }

                        case VARENUM.VARIANT:
                        {
                            var data   = new Span <VARIANT>(psa->pvData, array.Length);
                            var result = GetSpan <object?>(array);
                            for (int i = 0; i < data.Length; i++)
                            {
                                result[i] = data[i].ToObject();
                            }

                            break;
                        }

                        case VARENUM.RECORD:
                            throw new NotImplementedException();

                        default:
                            throw new ArgumentException(string.Format(SR.COM2UnhandledVT, vt));
                        }
                    }
                    else if (array.Length != 0)
                    {
                        // CLR arrays are laid out in row-major order.
                        // See CLI 8.9.1: https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf
                        // However, SAFEARRAYs are laid out in column-major order.
                        // See https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/array-manipulation-functions
                        // Therefore, we need to transpose data.
                        TransposeArray(psa, array, arrayType);
                    }
                }
                finally
                {
                    hr = SafeArrayUnlock(psa);
                    Debug.Assert(hr == HRESULT.S_OK);
                }

                return(array);
            }
Пример #18
0
 public static extern HRESULT PropVariantChangeType(
     [Out] IntPtr ppvDest,
     [In] IntPtr ppvIn,
     [In] int flags,             // Reserved, must be zero
     [In] VARENUM vt);
Пример #19
0
            public object ToObject()
            {
                IntPtr val = data1;
                long   longVal;

                VARENUM vtType = vt & ~VARENUM.TYPEMASK;

                switch (vtType)
                {
                case VARENUM.EMPTY:
                    return(null);

                case VARENUM.NULL:
                    return(Convert.DBNull);

                case VARENUM.I1:
                    if (Byref)
                    {
                        val = (IntPtr)Marshal.ReadByte(val);
                    }
                    return((sbyte)(0xFF & (sbyte)val));

                case VARENUM.UI1:
                    if (Byref)
                    {
                        val = (IntPtr)Marshal.ReadByte(val);
                    }

                    return((byte)(0xFF & (byte)val));

                case VARENUM.I2:
                    if (Byref)
                    {
                        val = (IntPtr)Marshal.ReadInt16(val);
                    }
                    return((short)(0xFFFF & (short)val));

                case VARENUM.UI2:
                    if (Byref)
                    {
                        val = (IntPtr)Marshal.ReadInt16(val);
                    }
                    return((ushort)(0xFFFF & (ushort)val));

                case VARENUM.I4:
                case VARENUM.INT:
                    if (Byref)
                    {
                        val = (IntPtr)Marshal.ReadInt32(val);
                    }
                    return((int)val);

                case VARENUM.UI4:
                case VARENUM.UINT:
                    if (Byref)
                    {
                        val = (IntPtr)Marshal.ReadInt32(val);
                    }
                    return((uint)val);

                case VARENUM.I8:
                case VARENUM.UI8:
                    if (Byref)
                    {
                        longVal = Marshal.ReadInt64(val);
                    }
                    else
                    {
                        longVal = ((uint)data1 & 0xffffffff) | ((uint)data2 << 32);
                    }

                    if (vt == VARENUM.I8)
                    {
                        return((long)longVal);
                    }
                    else
                    {
                        return((ulong)longVal);
                    }
                }

                if (Byref)
                {
                    val = GetRefInt(val);
                }

                switch (vtType)
                {
                case VARENUM.R4:
                case VARENUM.R8:

                    // can I use unsafe here?
                    throw new FormatException(SR.CannotConvertIntToFloat);

                case VARENUM.CY:
                    // internally currency is 8-byte int scaled by 10,000
                    longVal = ((uint)data1 & 0xffffffff) | ((uint)data2 << 32);
                    return(new decimal(longVal));

                case VARENUM.DATE:
                    throw new FormatException(SR.CannotConvertDoubleToDate);

                case VARENUM.BSTR:
                case VARENUM.LPWSTR:
                    return(Marshal.PtrToStringUni(val));

                case VARENUM.LPSTR:
                    return(Marshal.PtrToStringAnsi(val));

                case VARENUM.DISPATCH:
                case VARENUM.UNKNOWN:
                {
                    return(Marshal.GetObjectForIUnknown(val));
                }

                case VARENUM.HRESULT:
                    return(val);

                case VARENUM.DECIMAL:
                    longVal = ((uint)data1 & 0xffffffff) | ((uint)data2 << 32);
                    return(new decimal(longVal));

                case VARENUM.BOOL:
                    return(val != IntPtr.Zero);

                case VARENUM.VARIANT:
                    VARIANT varStruct = Marshal.PtrToStructure <VARIANT>(val);
                    return(varStruct.ToObject());

                case VARENUM.CLSID:
                    Guid guid = Marshal.PtrToStructure <Guid>(val);
                    return(guid);

                case VARENUM.FILETIME:
                    longVal = ((uint)data1 & 0xffffffff) | ((uint)data2 << 32);
                    return(new DateTime(longVal));

                case VARENUM.USERDEFINED:
                    throw new ArgumentException(string.Format(SR.COM2UnhandledVT, "USERDEFINED"));

                case VARENUM.ARRAY:
                case VARENUM.VOID:
                case VARENUM.PTR:
                case VARENUM.SAFEARRAY:
                case VARENUM.CARRAY:

                case VARENUM.RECORD:
                case VARENUM.BLOB:
                case VARENUM.STREAM:
                case VARENUM.STORAGE:
                case VARENUM.STREAMED_OBJECT:
                case VARENUM.STORED_OBJECT:
                case VARENUM.BLOB_OBJECT:
                case VARENUM.CF:
                case VARENUM.BSTR_BLOB:
                case VARENUM.VECTOR:
                case VARENUM.BYREF:
                default:
                    throw new ArgumentException(string.Format(SR.COM2UnhandledVT, vt));
                }
            }
Пример #20
0
 private static extern int VariantChangeTypeEx(ref object pvargDest, ref object pvarSrc, int lcid, VariantConversionFlags wFlags, VARENUM vt);
Пример #21
0
 private static void SetArrayValue(SAFEARRAY *psa, Array array, Span <int> indices, Span <int> lowerBounds, VARENUM arrayType)
 {
Пример #22
0
        private void Serialize_Object(BinaryWriter bw, object obj)
        {
            if (obj == null)
            {
                // 型: VT_EMPTY, 要素数: 1
                bw.Write(bCAPByteConverter.Value2Byte((Int16)VARENUM.VT_EMPTY));
                bw.Write(bCAPByteConverter.Value2Byte((Int32)1));
            }
            else
            {
                // 引数の型を取得
                Type t = obj.GetType();

                if (t.IsArray)
                {
                    // 配列に変換
                    Array objArray = (Array)obj;

                    // 要素の型を取得
                    t = t.GetElementType();

                    if (t == typeof(Object))
                    {
                        // 型: (VT_VARIANT | VT_ARRAY), 要素数: objArray.Length
                        bw.Write(bCAPByteConverter.Value2Byte((Int16)(VARENUM.VT_VARIANT | VARENUM.VT_ARRAY)));
                        bw.Write(bCAPByteConverter.Value2Byte((Int32)objArray.Length));
                        // 再帰
                        Serialize_ObjectArray(bw, new ArrayList(objArray));
                    }
                    else
                    {
                        // TypeをVARENUMに変換
                        VARENUM vt = FindVtFromType(t);

                        // 型: (vt | VT_ARRAY), 要素数: objArray.Length
                        bw.Write(bCAPByteConverter.Value2Byte((Int16)(vt | VARENUM.VT_ARRAY)));
                        bw.Write(bCAPByteConverter.Value2Byte((Int32)objArray.Length));

                        if (t == typeof(Byte))
                        {
                            // バイト配列はそのまま代入
                            bw.Write((byte[])objArray);
                        }
                        else if (t == typeof(String))
                        {
                            // 文字列配列をバイト配列に変換
                            foreach (String tmp in objArray)
                            {
                                bw.Write(bCAPByteConverter.Value2Byte((Int32)(2 * tmp.Length)));
                                bw.Write(bCAPByteConverter.Value2Byte(tmp));
                            }
                        }
                        else
                        {
                            // 各要素をバイト配列に変換
                            foreach (object tmp in objArray)
                            {
                                bw.Write(bCAPByteConverter.Value2Byte(tmp));
                            }
                        }
                    }
                }
                else
                {
                    // TypeをVARENUMに変換
                    VARENUM vt = FindVtFromType(t);

                    // 型: vt, 要素数: 1
                    bw.Write(bCAPByteConverter.Value2Byte((Int16)vt));
                    bw.Write(bCAPByteConverter.Value2Byte((Int32)1));

                    if (t == typeof(Byte))
                    {
                        // バイトはそのまま代入
                        bw.Write((byte)obj);
                    }
                    else if (t == typeof(String))
                    {
                        // 文字列をバイト配列に変換
                        bw.Write(bCAPByteConverter.Value2Byte((Int32)(2 * ((String)obj).Length)));
                        bw.Write(bCAPByteConverter.Value2Byte(obj));
                    }
                    else
                    {
                        // 要素をバイト配列に変換
                        bw.Write(bCAPByteConverter.Value2Byte(obj));
                    }
                }
            }
        }
 internal static extern int VariantChangeType(ref object pvargDest, ref object pvarSrc, VariantConversionFlags wFlags, VARENUM vt);
Пример #24
0
        /// <summary>
        /// Coerces a <see cref="PropVariant"/> value to the specified type. and returns that value as a native instance of that type
        /// </summary>
        /// <typeparam name="T">The native type required</typeparam>
        /// <returns>The value of the PropVariant</returns>
        public T ToType <T>()
        {
            using (PropVariant propVar = new PropVariant()) {
                HRESULT hr;
                VARENUM vt = VARENUM.VT_EMPTY;
                switch (Type.GetTypeCode(typeof(T)))
                {
                case TypeCode.Boolean:
                    vt = VARENUM.VT_BOOL;
                    break;

                case TypeCode.Byte:
                    vt = VARENUM.VT_UI1;
                    break;

                case TypeCode.Char:
                    vt = VARENUM.VT_I1;
                    break;

                case TypeCode.Single:
                    vt = VARENUM.VT_R4;
                    break;

                case TypeCode.Double:
                    vt = VARENUM.VT_R8;
                    break;

                case TypeCode.DateTime:
                    vt = VARENUM.VT_FILETIME;
                    break;

                case TypeCode.Decimal:
                    vt = VARENUM.VT_DECIMAL;
                    break;

                case TypeCode.Int16:
                    vt = VARENUM.VT_I2;
                    break;

                case TypeCode.Int32:
                    vt = VARENUM.VT_I4;
                    break;

                case TypeCode.Int64:
                    vt = VARENUM.VT_I8;
                    break;

                case TypeCode.UInt16:
                    vt = VARENUM.VT_UI2;
                    break;

                case TypeCode.UInt32:
                    vt = VARENUM.VT_UI4;
                    break;

                case TypeCode.UInt64:
                    vt = VARENUM.VT_UI8;
                    break;

                case TypeCode.String: {
                    IntPtr pStr = IntPtr.Zero;
                    PropVariantToStringAlloc(MarshalledPointer, out pStr).ThrowIfFailed();
                    object sResult = Marshal.PtrToStringAuto(pStr);
                    Marshal.FreeCoTaskMem(pStr);
                    return((T)sResult);
                }

                case TypeCode.Object:
                    if (typeof(T) == typeof(Guid))
                    {
                        try {
                            if (IsVector && _propVar.VarType.HasFlag(VARENUM.VT_UI1))
                            {
                                byte[] data   = (byte[])Value;
                                object result = new Guid(data);
                                return((T)result);
                            }
                            if (IsString)
                            {
                                object result = new Guid((string)Value);
                                return((T)result);
                            }
                            if (_propVar.VarType == VARENUM.VT_CLSID || _propVar.VarType == VARENUM.VT_RECORD)
                            {
                                return((T)Value);
                            }
                        }
                        catch { }
                    }
                    throw new VariantTypeException($"Cannot convert PropVariant with {_propVar.VarType} To {typeof(T)}");

                default:
                    throw new VariantTypeException($"Cannot convert PropVariant with {_propVar.VarType} To {typeof(T)}");
                }
                hr = PropVariantChangeType(propVar.MarshalledPointer, MarshalledPointer, 0, vt);
                if (hr.Failed)
                {
                    throw new VariantTypeException($"Cannot convert  PropVariant with {_propVar.VarType} To {typeof(T)}", hr.GetException());
                }
                propVar.MarshalPointerToValue();
                return((T)propVar.Value);
            }
        }
Пример #25
0
            private static object?ToObject(VARENUM type, bool byRef, void *data)
            {
                switch (type)
                {
                case VARENUM.EMPTY:
                    if (byRef)
                    {
                        // CLR returns VT_EMPTY | VT_BYREF data as nuint.
                        if (IntPtr.Size == 8)
                        {
                            return((ulong)data);
                        }

                        return((uint)data);
                    }

                    return(null);

                case VARENUM.NULL:
                    return(Convert.DBNull);

                case VARENUM.I1:
                    return(*((sbyte *)data));

                case VARENUM.UI1:
                    return(*((byte *)data));

                case VARENUM.I2:
                    return(*((short *)data));

                case VARENUM.UI2:
                    return(*((ushort *)data));

                case VARENUM.I4:
                case VARENUM.INT:
                case VARENUM.ERROR:
                case VARENUM.HRESULT:
                    return(*((int *)data));

                case VARENUM.UI4:
                case VARENUM.UINT:
                    return(*((uint *)data));

                case VARENUM.I8:
                    return(*((long *)data));

                case VARENUM.UI8:
                    return(*((ulong *)data));

                case VARENUM.R4:
                    return(*((float *)data));

                case VARENUM.R8:
                    return(*((double *)data));

                case VARENUM.CY:
                    long cyVal = *((long *)data);
                    return(decimal.FromOACurrency(cyVal));

                case VARENUM.DATE:
                    double date = *((double *)data);
                    return(DateTime.FromOADate(date));

                case VARENUM.BSTR:
                case VARENUM.LPWSTR:
                    return(Marshal.PtrToStringUni(*(IntPtr *)data));

                case VARENUM.LPSTR:
                    return(Marshal.PtrToStringAnsi(*(IntPtr *)data));

                case VARENUM.DISPATCH:
                case VARENUM.UNKNOWN:
                    IntPtr pInterface = *(IntPtr *)data;
                    if (pInterface == IntPtr.Zero)
                    {
                        return(null);
                    }

                    return(Marshal.GetObjectForIUnknown(pInterface));

                case VARENUM.DECIMAL:
                    return(((DECIMAL *)data)->ToDecimal());

                case VARENUM.BOOL:
                    return((*(VARIANT_BOOL *)data) != VARIANT_BOOL.FALSE);

                case VARENUM.VARIANT:
                    // We only support VT_VARIANT | VT_BYREF.
                    if (!byRef)
                    {
                        break;
                    }

                    // BYREF VARIANTS are not allowed to be nested.
                    VARIANT *pVariant = (VARIANT *)data;
                    if (pVariant->Byref)
                    {
                        throw new InvalidOleVariantTypeException();
                    }

                    return(pVariant->ToObject());

                case VARENUM.CLSID:
                    // We only support VT_CLSID.
                    // This is the type of InitPropVariantFromCLSID.
                    if (byRef)
                    {
                        break;
                    }

                    return(**((Guid **)data));

                case VARENUM.FILETIME:
                    // We only support VT_FILETIME.
                    // This is the type of InitPropVariantFromFILETIME.
                    if (byRef)
                    {
                        break;
                    }

                    return((*(Kernel32.FILETIME *)data).ToDateTime());

                case VARENUM.VOID:
                    return(null);

                case VARENUM.RECORD:
                {
                    VARIANTRecord *record = (VARIANTRecord *)data;
                    if (record->pRecInfo == IntPtr.Zero)
                    {
                        throw new ArgumentException("Specified OLE variant is invalid.");
                    }

                    if (record->pvRecord is null)
                    {
                        return(null);
                    }

                    // TODO: cast IntPtr to IRecordInfo. Not that much of a concern
                    // as .NET Core doesn't support records anyway.
                    // Type recordType = GetRecordElementType(record->pvRecord);
                    throw new ArgumentException("Record marshalling doesn't actually work in .NET Core. Matching that behaviour.");
                }
                }

                throw new ArgumentException(string.Format(SR.COM2UnhandledVT, type));
            }
Пример #26
0
        internal static Type VarEnumToSystemType(VARENUM varEnumType)
        {
            switch (varEnumType)
            {
            case (VARENUM.VT_EMPTY):
            case (VARENUM.VT_NULL):
                return(typeof(Object));

            case (VARENUM.VT_UI1):
                return(typeof(Byte?));

            case (VARENUM.VT_I2):
                return(typeof(Int16?));

            case (VARENUM.VT_UI2):
                return(typeof(UInt16?));

            case (VARENUM.VT_I4):
                return(typeof(Int32?));

            case (VARENUM.VT_UI4):
                return(typeof(UInt32?));

            case (VARENUM.VT_I8):
                return(typeof(Int64?));

            case (VARENUM.VT_UI8):
                return(typeof(UInt64?));

            case (VARENUM.VT_R8):
                return(typeof(Double?));

            case (VARENUM.VT_BOOL):
                return(typeof(Boolean?));

            case (VARENUM.VT_FILETIME):
                return(typeof(DateTime?));

            case (VARENUM.VT_CLSID):
                return(typeof(IntPtr?));

            case (VARENUM.VT_CF):
                return(typeof(IntPtr?));

            case (VARENUM.VT_BLOB):
                return(typeof(Byte[]));

            case (VARENUM.VT_LPWSTR):
                return(typeof(String));

            case (VARENUM.VT_UNKNOWN):
                return(typeof(IntPtr?));

            case (VARENUM.VT_STREAM):
                return(typeof(IStream));

            case (VARENUM.VT_VECTOR | VARENUM.VT_UI1):
                return(typeof(Byte[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_I2):
                return(typeof(Int16[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_UI2):
                return(typeof(UInt16[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_I4):
                return(typeof(Int32[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_UI4):
                return(typeof(UInt32[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_I8):
                return(typeof(Int64[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_UI8):
                return(typeof(UInt64[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_R8):
                return(typeof(Double[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_BOOL):
                return(typeof(Boolean[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_FILETIME):
                return(typeof(DateTime[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_CLSID):
                return(typeof(IntPtr[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_CF):
                return(typeof(IntPtr[]));

            case (VARENUM.VT_VECTOR | VARENUM.VT_LPWSTR):
                return(typeof(String[]));

            default:
                return(typeof(Object));
            }
        }