summaryrefslogtreecommitdiff
path: root/src/vm/winrtredirector.h
blob: f725ca8eb301134b56eba84fea07ad5dd5377390 (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
143
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// File: winrtredirector.h
//

//

//
// ============================================================================

#ifndef WINRT_DELEGATE_REDIRECTOR_H
#define WINRT_DELEGATE_REDIRECTOR_H

#include "winrttypenameconverter.h"

// Provides functionality related to redirecting WinRT interfaces.
// @TODO: This should take advantage of the macros in WinRTProjectedTypes.h instead of hardcoding
// the knowledge about redirected interfaces here.
class WinRTInterfaceRedirector
{
public:
    // Returns a MethodDesc to be used as an interop stub for the given redirected interface/slot/direction.
    static MethodDesc *GetStubMethodForRedirectedInterface(
        WinMDAdapter::RedirectedTypeIndex   interfaceIndex,                // redirected interface index
        int                                 slot,                          // slot number of the method for which a stub is needed
        TypeHandle::InteropKind             interopKind,                   // Interop_ManagedToNative (stub for RCW) or Interop_NativeToManaged (stub for CCW)
        BOOL                                fICollectionStub,              // need stub for ICollection`1 (only valid with Interop_ManagedToNative)
        Instantiation                       methodInst = Instantiation()); // requested method instantiation if the stub method is generic

    // Returns a MethodDesc to be used as an interop stub for the given method and direction.
    static MethodDesc *GetStubMethodForRedirectedInterfaceMethod(MethodDesc *pMD, TypeHandle::InteropKind interopKind);

    // Returns MethodTable (typical instantiation) of the Framework copy of the specified redirected WinRT interface.
    static MethodTable *GetWinRTTypeForRedirectedInterfaceIndex(WinMDAdapter::RedirectedTypeIndex index);
    
    // Loads a method from the given Framework assembly.
    static MethodDesc *LoadMethodFromRedirectedAssembly(LPCUTF8 szAssemblyQualifiedTypeName, LPCUTF8 szMethodName);

    // Lists WinRT-legal types assignable from .NET reference types that are projected from WinRT structures/arrays/delegates.
    enum WinRTLegalStructureBaseType
    {
        BaseType_None,
        BaseType_Object,            // System.Object                                (assignable from Type, string, Exception)
        BaseType_IEnumerable,       // System.Collections.IEnumerable               (assignable from string)
        BaseType_IEnumerableOfChar  // System.Collections.Generic.IEnumerable<char> (assignable from string)
    };

    // Determines if the generic argument in the given instantiation is a WinRT-legal base type of a WinRT structure type.
    static WinRTLegalStructureBaseType GetStructureBaseType(Instantiation inst)
    {
        LIMITED_METHOD_CONTRACT;

        _ASSERTE(inst.GetNumArgs() == 1);

        if (!inst[0].IsTypeDesc())
        {
            MethodTable *pInstArgMT = inst[0].AsMethodTable();
            
            if (pInstArgMT == g_pObjectClass)
                return BaseType_Object;

            if (pInstArgMT == MscorlibBinder::GetExistingClass(CLASS__IENUMERABLE))
                return BaseType_IEnumerable;

            if (pInstArgMT->HasSameTypeDefAs(MscorlibBinder::GetExistingClass(CLASS__IENUMERABLEGENERIC)) &&
                pInstArgMT->GetInstantiation()[0].GetSignatureCorElementType() == ELEMENT_TYPE_CHAR)
                return BaseType_IEnumerableOfChar;
        }
        return BaseType_None;
    }

    // Returns the redirection index if the MethodTable* is a redirected interface.
    static inline bool ResolveRedirectedInterface(MethodTable *pMT, WinMDAdapter::RedirectedTypeIndex * pIndex);

#ifdef _DEBUG
    static void VerifyRedirectedInterfaceStubs();
#endif // _DEBUG

private:
    static inline int GetStubInfoIndex(WinMDAdapter::RedirectedTypeIndex index)
    {
        LIMITED_METHOD_CONTRACT;

        switch (index)
        {
            case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IEnumerable:                  return 0;
            case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IList:                        return 1;
            case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IDictionary:                  return 2;
            case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IReadOnlyList:                return 3;
            case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IReadOnlyDictionary:          return 4;
            case WinMDAdapter::RedirectedTypeIndex_System_Collections_IEnumerable:                          return 5;
            case WinMDAdapter::RedirectedTypeIndex_System_Collections_IList:                                return 6;
            case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_INotifyCollectionChanged: return 7;
            case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_INotifyPropertyChanged:            return 8;
            case WinMDAdapter::RedirectedTypeIndex_System_Windows_Input_ICommand:                           return 9;
            case WinMDAdapter::RedirectedTypeIndex_System_IDisposable:                                      return 10;
            default:
                UNREACHABLE();
        }
    }

    struct RedirectedInterfaceStubInfo
    {
        const BinderClassID m_WinRTInterface;
        const int m_iCLRMethodCount;
        const BinderMethodID *m_rCLRStubMethods;
        const int m_iWinRTMethodCount;
        const BinderMethodID *m_rWinRTStubMethods;
    };

    struct NonMscorlibRedirectedInterfaceInfo
    {
        const LPCUTF8 m_szWinRTInterfaceAssemblyQualifiedTypeName;
        const LPCUTF8 m_szCLRStubClassAssemblyQualifiedTypeName;
        const LPCUTF8 m_szWinRTStubClassAssemblyQualifiedTypeName;
        const LPCUTF8 *m_rszMethodNames;
    };

    enum
    {
        s_NumRedirectedInterfaces = 11
    };

    // Describes stubs used for marshaling of redirected interfaces.
    const static RedirectedInterfaceStubInfo s_rInterfaceStubInfos[2 * s_NumRedirectedInterfaces];
    const static NonMscorlibRedirectedInterfaceInfo s_rNonMscorlibInterfaceInfos[3];

    const static int NON_MSCORLIB_MARKER = 0x80000000;
};


// Provides functionality related to redirecting WinRT delegates.
class WinRTDelegateRedirector
{
public:
    static MethodTable *GetWinRTTypeForRedirectedDelegateIndex(WinMDAdapter::RedirectedTypeIndex index);

    static bool ResolveRedirectedDelegate(MethodTable *pMT, WinMDAdapter::RedirectedTypeIndex *pIndex);
};

#endif // WINRT_DELEGATE_REDIRECTOR_H