summaryrefslogtreecommitdiff
path: root/src/vm/mngstdinterfaces.h
blob: 2aaee9574dbf4831a4762f96229dfa7802f915b6 (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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
// 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.

/*============================================================
**
** Header:  MngStdInterfaceMap.h
**
**
** Purpose: Contains types and method signatures for the Com wrapper class
**
**

===========================================================*/

#ifndef _MNGSTDINTERFACEMAP_H
#define _MNGSTDINTERFACEMAP_H

#ifndef FEATURE_COMINTEROP
#error FEATURE_COMINTEROP is required for this file
#endif // FEATURE_COMINTEROP

#include "vars.hpp"
#include "eehash.h"
#include "class.h"
#include "mlinfo.h"

#ifndef DACCESS_COMPILE
//
// This class is used to establish a mapping between a managed standard interface and its
// unmanaged counterpart.
//

class MngStdInterfaceMap
{
public:
    // This method retrieves the native IID of the interface that the specified
    // managed type is a standard interface for. If the specified type is not
    // a standard interface then GUIDNULL is returned.
    inline static IID* GetNativeIIDForType(TypeHandle th)
    {
        CONTRACTL
        {
            THROWS;
            GC_TRIGGERS;
            INJECT_FAULT(COMPlusThrowOM());
        }
        CONTRACTL_END

        // Only simple class types can have native IIDs
        if (th.IsTypeDesc())
            return NULL;

        HashDatum Data;

        // Retrieve the name of the type.
        LPCUTF8 ns, name;
        LPUTF8 strTypeName;
        name = th.GetMethodTable()->GetFullyQualifiedNameInfo(&ns);
        MAKE_FULL_PATH_ON_STACK_UTF8(strTypeName, ns, name);
    
        if (m_pMngStdItfMap == NULL) {
            MngStdInterfaceMap *tmp = new MngStdInterfaceMap;
            if (FastInterlockCompareExchangePointer(&m_pMngStdItfMap, tmp, NULL) != NULL) {
                tmp->m_TypeNameToNativeIIDMap.ClearHashTable();
                delete tmp;
            }
        }
        if (m_pMngStdItfMap->m_TypeNameToNativeIIDMap.GetValue(strTypeName, &Data) && (*((GUID*)Data) != GUID_NULL))
        {
            // The type is a standard interface.
            return (IID*)Data;
        }
        else
        {
            // The type is not a standard interface.
            return NULL;
        }
    }

private:
    // Disalow creation of this class by anybody outside of it.
    MngStdInterfaceMap();

    // The map of type names to native IID's.
    EEUtf8StringHashTable m_TypeNameToNativeIIDMap;

    // The one and only instance of the managed std interface map.
    static MngStdInterfaceMap *m_pMngStdItfMap;
};

#endif // DACCESS_COMPILE

//
// Base class for all the classes that contain the ECall's for the managed standard interfaces.
//

class MngStdItfBase
{
protected:
    static void InitHelper(
                    LPCUTF8 strMngItfTypeName, 
                    LPCUTF8 strUComItfTypeName, 
                    LPCUTF8 strCMTypeName, 
                    LPCUTF8 strCookie, 
                    LPCUTF8 strManagedViewName, 
                    TypeHandle *pMngItfType, 
                    TypeHandle *pUComItfType, 
                    TypeHandle *pCustomMarshalerType, 
                    TypeHandle *pManagedViewType, 
                    OBJECTHANDLE *phndMarshaler);

    static LPVOID ForwardCallToManagedView(
                    OBJECTHANDLE hndMarshaler, 
                    MethodDesc *pMngItfMD, 
                    MethodDesc *pUComItfMD, 
                    MethodDesc *pMarshalNativeToManagedMD, 
                    MethodDesc *pMngViewMD, 
                    IID *pMngItfIID, 
                    IID *pNativeItfIID, 
                    ARG_SLOT* pArgs);
};


//
// Define the enum of methods on the managed standard interface.
//

#define MNGSTDITF_BEGIN_INTERFACE(FriendlyName, strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, NativeItfIID, bCanCastOnNativeItfQI) \
\
enum FriendlyName##Methods \
{  \
    FriendlyName##Methods_Dummy = -1,


#define MNGSTDITF_DEFINE_METH_IMPL(FriendlyName, ECallMethName, MethName, MethSig, FcallDecl) \
    FriendlyName##Methods_##ECallMethName, 


#define MNGSTDITF_END_INTERFACE(FriendlyName) \
    FriendlyName##Methods_LastMember \
}; \


#include "mngstditflist.h"


#undef MNGSTDITF_BEGIN_INTERFACE
#undef MNGSTDITF_DEFINE_METH_IMPL
#undef MNGSTDITF_END_INTERFACE


//
// Define the class that implements the ECall's for the managed standard interface.
//

#define MNGSTDITF_BEGIN_INTERFACE(FriendlyName, strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, NativeItfIID, bCanCastOnNativeItfQI) \
\
class FriendlyName : public MngStdItfBase \
{ \
public: \
    FriendlyName() \
    { \
        CONTRACTL \
        {         \
            THROWS; \
            GC_TRIGGERS; \
            INJECT_FAULT(COMPlusThrowOM()); \
        } \
        CONTRACTL_END \
        InitHelper(strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, &m_MngItfType, &m_UComItfType, &m_CustomMarshalerType, &m_ManagedViewType, &m_hndCustomMarshaler); \
        m_NativeItfIID = NativeItfIID; \
        m_UComItfType.GetMethodTable()->GetGuid(&m_MngItfIID, TRUE); \
        memset(m_apCustomMarshalerMD, 0, CustomMarshalerMethods_LastMember * sizeof(MethodDesc *)); \
        memset(m_apManagedViewMD, 0, FriendlyName##Methods_LastMember * sizeof(MethodDesc *)); \
        memset(m_apUComItfMD, 0, FriendlyName##Methods_LastMember * sizeof(MethodDesc *)); \
        memset(m_apMngItfMD, 0, FriendlyName##Methods_LastMember * sizeof(MethodDesc *)); \
    } \
\
    OBJECTREF GetCustomMarshaler() \
    { \
        WRAPPER_NO_CONTRACT; \
        return ObjectFromHandle(m_hndCustomMarshaler); \
    } \
\
    MethodDesc* GetCustomMarshalerMD(EnumCustomMarshalerMethods Method) \
    { \
        CONTRACTL \
        {         \
            THROWS; \
            GC_TRIGGERS; \
            INJECT_FAULT(COMPlusThrowOM()); \
        } \
        CONTRACTL_END \
        MethodDesc *pMD = NULL; \
        \
        if (m_apCustomMarshalerMD[Method]) \
            return m_apCustomMarshalerMD[Method]; \
        \
        pMD = CustomMarshalerInfo::GetCustomMarshalerMD(Method, m_CustomMarshalerType); \
        _ASSERTE(pMD && "Unable to find specified method on the custom marshaler"); \
        MetaSig::EnsureSigValueTypesLoaded(pMD); \
        \
        m_apCustomMarshalerMD[Method] = pMD; \
        return pMD; \
    } \
\
    MethodDesc* GetManagedViewMD(FriendlyName##Methods Method, LPCUTF8 strMethName, LPHARDCODEDMETASIG pSig) \
    { \
        CONTRACTL \
        {         \
            THROWS; \
            GC_TRIGGERS; \
            INJECT_FAULT(COMPlusThrowOM()); \
        } \
        CONTRACTL_END \
        MethodDesc *pMD = NULL; \
        \
        if (m_apManagedViewMD[Method]) \
            return m_apManagedViewMD[Method]; \
        \
        pMD = MemberLoader::FindMethod(m_ManagedViewType.GetMethodTable(), strMethName, pSig); \
        _ASSERTE(pMD && "Unable to find specified method on the managed view"); \
        MetaSig::EnsureSigValueTypesLoaded(pMD); \
        \
        m_apManagedViewMD[Method] = pMD; \
        return pMD; \
    } \
\
    MethodDesc* GetUComItfMD(FriendlyName##Methods Method, LPCUTF8 strMethName, LPHARDCODEDMETASIG pSig) \
    { \
        CONTRACTL \
        {         \
            THROWS; \
            GC_TRIGGERS; \
            INJECT_FAULT(COMPlusThrowOM()); \
        } \
        CONTRACTL_END \
        MethodDesc *pMD = NULL; \
        \
        if (m_apUComItfMD[Method]) \
            return m_apUComItfMD[Method]; \
        \
        pMD = MemberLoader::FindMethod(m_UComItfType.GetMethodTable(), strMethName, pSig); \
        _ASSERTE(pMD && "Unable to find specified method in UCom interface"); \
        MetaSig::EnsureSigValueTypesLoaded(pMD); \
        \
        m_apUComItfMD[Method] = pMD; \
        return pMD; \
    } \
\
    MethodDesc* GetMngItfMD(FriendlyName##Methods Method, LPCUTF8 strMethName, LPHARDCODEDMETASIG pSig) \
    { \
        CONTRACTL \
        {         \
            THROWS; \
            GC_TRIGGERS; \
            INJECT_FAULT(COMPlusThrowOM()); \
        } \
        CONTRACTL_END \
        MethodDesc *pMD = NULL; \
        \
        if (m_apMngItfMD[Method]) \
            return m_apMngItfMD[Method]; \
        \
        pMD = MemberLoader::FindMethod(m_MngItfType.GetMethodTable(), strMethName, pSig); \
        _ASSERTE(pMD && "Unable to find specified method in UCom interface"); \
        MetaSig::EnsureSigValueTypesLoaded(pMD); \
        \
        m_apMngItfMD[Method] = pMD; \
        return pMD; \
    } \
\
private: \
    MethodDesc*     m_apCustomMarshalerMD[CustomMarshalerMethods_LastMember]; \
    MethodDesc*     m_apManagedViewMD[FriendlyName##Methods_LastMember]; \
    MethodDesc*     m_apUComItfMD[FriendlyName##Methods_LastMember]; \
    MethodDesc*     m_apMngItfMD[FriendlyName##Methods_LastMember]; \
    TypeHandle      m_CustomMarshalerType; \
    TypeHandle      m_ManagedViewType; \
    TypeHandle      m_UComItfType; \
    TypeHandle      m_MngItfType; \
    OBJECTHANDLE    m_hndCustomMarshaler; \
    GUID            m_MngItfIID; \
    GUID            m_NativeItfIID; \
\

#define MNGSTDITF_DEFINE_METH_IMPL(FriendlyName, ECallMethName, MethName, MethSig, FcallDecl) \
\
public: static LPVOID __stdcall ECallMethName##Worker(ARG_SLOT* pArgs); \
public: static FcallDecl; \
\

#define MNGSTDITF_END_INTERFACE(FriendlyName) \
}; \
\


#include "mngstditflist.h"


#undef MNGSTDITF_BEGIN_INTERFACE
#undef MNGSTDITF_DEFINE_METH_IMPL
#undef MNGSTDITF_END_INTERFACE


//
// App domain level information on the managed standard interfaces .
//

class MngStdInterfacesInfo
{
public:
    // Constructor and destructor.
    MngStdInterfacesInfo()
    {
        STATIC_CONTRACT_THROWS;
        STATIC_CONTRACT_FAULT;

#define MNGSTDITF_BEGIN_INTERFACE(FriendlyName, strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, NativeItfIID, bCanCastOnNativeItfQI) \
\
        m_p##FriendlyName = 0; \
\

#define MNGSTDITF_DEFINE_METH_IMPL(FriendlyName, ECallMethName, MethName, MethSig, FcallDecl)
#define MNGSTDITF_END_INTERFACE(FriendlyName)


#include "mngstditflist.h"


#undef MNGSTDITF_BEGIN_INTERFACE
#undef MNGSTDITF_DEFINE_METH_IMPL
#undef MNGSTDITF_END_INTERFACE
    }

    ~MngStdInterfacesInfo()
    {
        WRAPPER_NO_CONTRACT;

#define MNGSTDITF_BEGIN_INTERFACE(FriendlyName, strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, NativeItfIID, bCanCastOnNativeItfQI) \
\
        if (m_p##FriendlyName) \
            delete m_p##FriendlyName; \
\

#define MNGSTDITF_DEFINE_METH_IMPL(FriendlyName, ECallMethName, MethName, MethSig, FcallDecl)
#define MNGSTDITF_END_INTERFACE(FriendlyName)


#include "mngstditflist.h"


#undef MNGSTDITF_BEGIN_INTERFACE
#undef MNGSTDITF_DEFINE_METH_IMPL
#undef MNGSTDITF_END_INTERFACE
    }


    // Accessors for each of the managed standard interfaces.
#define MNGSTDITF_BEGIN_INTERFACE(FriendlyName, strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, NativeItfIID, bCanCastOnNativeItfQI) \
\
public: \
    FriendlyName *Get##FriendlyName() \
    { \
        CONTRACTL \
        {         \
            THROWS; \
            GC_TRIGGERS; \
            INJECT_FAULT(COMPlusThrowOM()); \
        } \
        CONTRACTL_END \
        if (!m_p##FriendlyName) \
        { \
            NewHolder<FriendlyName> pFriendlyName = new FriendlyName(); \
            if (InterlockedCompareExchangeT(&m_p##FriendlyName, pFriendlyName.GetValue(), NULL) == NULL) \
                pFriendlyName.SuppressRelease(); \
        } \
        return m_p##FriendlyName; \
    } \
\
private: \
    FriendlyName *m_p##FriendlyName; \
\

#define MNGSTDITF_DEFINE_METH_IMPL(FriendlyName, ECallMethName, MethName, MethSig, FcallDecl)
#define MNGSTDITF_END_INTERFACE(FriendlyName)


#include "mngstditflist.h"


#undef MNGSTDITF_BEGIN_INTERFACE
#undef MNGSTDITF_DEFINE_METH_IMPL
#undef MNGSTDITF_END_INTERFACE
};

#endif // _MNGSTDINTERFACEMAP_H