summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs
blob: 8aa9f97586b32353cc3a4119fd50cc87ce425306 (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
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

/*============================================================
**
**
**
** Purpose: This class only exists to provide support for 
**          implenting IDispatch on managed objects. It is 
**          used to provide OleAut style coercion rules.
**
** 
===========================================================*/
namespace Microsoft.Win32 {
    
    using System;
    using System.Diagnostics.Contracts;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.Versioning;
    using CultureInfo = System.Globalization.CultureInfo;

    internal static class OAVariantLib
    {
        #region Constants

        // Constants for VariantChangeType from OleAuto.h
        public const int NoValueProp = 0x01;
        public const int AlphaBool = 0x02;
        public const int NoUserOverride = 0x04;
        public const int CalendarHijri = 0x08;
        public const int LocalBool = 0x10;
        
        internal static readonly Type [] ClassTypes = {
            typeof(Empty),
            typeof(void),
            typeof(Boolean),
            typeof(Char),
            typeof(SByte),
            typeof(Byte),
            typeof(Int16),
            typeof(UInt16),
            typeof(Int32),
            typeof(UInt32),
            typeof(Int64),
            typeof(UInt64),
            typeof(Single),
            typeof(Double),
            typeof(String),
            typeof(void),
            typeof(DateTime),
            typeof(TimeSpan),
            typeof(Object),
            typeof(Decimal),
            null,  // Enums - what do we do here?
            typeof(Missing),
            typeof(DBNull),
        };

    	// Keep these numbers in sync w/ the above array.
        private const int CV_OBJECT=0x12;
        
        #endregion

        
        #region Internal Methods

        /**
         * Changes a Variant from one type to another, calling the OLE
         * Automation VariantChangeTypeEx routine.  Note the legal types here are
         * restricted to the subset of what can be legally found in a VB
         * Variant and the types that CLR supports explicitly in the 
         * CLR Variant class.  
         */
        [System.Security.SecurityCritical]  // auto-generated
        internal static Variant ChangeType(Variant source, Type targetClass, short options, CultureInfo culture)
        {
            if (targetClass == null)
                throw new ArgumentNullException("targetClass");
            if (culture == null)
                throw new ArgumentNullException("culture");
            Variant result = new Variant ();
            ChangeTypeEx(ref result, ref source, 
#if FEATURE_USE_LCID
                         culture.LCID, 
#else
        // @CORESYSTODO: what does CoreSystem expect for this argument?
                        0,
#endif
                         targetClass.TypeHandle.Value, GetCVTypeFromClass(targetClass), options);
            return result;
        }       

        #endregion


        #region Private Helpers

        private static int GetCVTypeFromClass(Type ctype) 
        {
            Contract.Requires(ctype != null);
#if _DEBUG
            BCLDebug.Assert(ClassTypes[CV_OBJECT] == typeof(Object), "OAVariantLib::ClassTypes[CV_OBJECT] == Object.class");
#endif
    
            int cvtype=-1;
            for (int i=0; i<ClassTypes.Length; i++) {
                if (ctype.Equals(ClassTypes[i])) {
                    cvtype=i;
                    break;
                }
            }
    
            // OleAut Binder works better if unrecognized
            // types were changed to Object.  So don't throw here.
            if (cvtype == -1)
                cvtype = CV_OBJECT;
    
            return cvtype;
        }

        #endregion


        #region Private FCalls

        [System.Security.SecurityCritical]  // auto-generated
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void ChangeTypeEx(ref Variant result, ref Variant source, int lcid, IntPtr typeHandle, int cvType, short flags);

        #endregion
    }
}