summaryrefslogtreecommitdiff
path: root/src/vm/interoputil.inl
blob: ed0ab029c2c40ffecd16f9c8cbd7ffdb1cea1fe7 (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
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

//
#include "comcallablewrapper.h"

#ifndef DACCESS_COMPILE
inline BOOL ComInterfaceSlotIs(IUnknown* pUnk, int slot, LPVOID pvFunction)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        FORBID_FAULT;
        MODE_ANY;
        SO_TOLERANT;
        PRECONDITION(CheckPointer(pUnk));
    }
    CONTRACTL_END;
    
    LPVOID pvRetVal = (*((LPVOID**)pUnk))[slot];

    return (pvRetVal == (LPVOID)GetEEFuncEntryPoint(pvFunction));
}

//Helpers
// Is the tear-off a CLR created tear-off
inline BOOL IsInProcCCWTearOff(IUnknown* pUnk)
{
    WRAPPER_NO_CONTRACT;
    return ComInterfaceSlotIs(pUnk, 0, Unknown_QueryInterface) || 
           ComInterfaceSlotIs(pUnk, 0, Unknown_QueryInterface_IErrorInfo) ||
           ComInterfaceSlotIs(pUnk, 0, Unknown_QueryInterface_ICCW);
}
    
// is the tear-off represent one of the standard interfaces such as IProvideClassInfo, IErrorInfo etc.
inline BOOL IsSimpleTearOff(IUnknown* pUnk)
{
    WRAPPER_NO_CONTRACT;
    return ComInterfaceSlotIs(pUnk, TEAR_OFF_SLOT, TEAR_OFF_SIMPLE);
}

// Is the tear-off represent the inner unknown or the original unknown for the object
inline BOOL IsInnerUnknown(IUnknown* pUnk)
{
    WRAPPER_NO_CONTRACT;
    return ComInterfaceSlotIs(pUnk, TEAR_OFF_SLOT, TEAR_OFF_SIMPLE_INNER);
}

// Is this one of our "standard" ComCallWrappers
inline BOOL IsStandardTearOff(IUnknown* pUnk)
{
    WRAPPER_NO_CONTRACT;
    return ComInterfaceSlotIs(pUnk, TEAR_OFF_SLOT, TEAR_OFF_STANDARD);
}

// Convert an IUnknown to CCW, does not handle aggregation and ICustomQI.
FORCEINLINE ComCallWrapper* MapIUnknownToWrapper(IUnknown* pUnk)
{   
    CONTRACT (ComCallWrapper*)
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
        SO_TOLERANT;
        PRECONDITION(CheckPointer(pUnk, NULL_OK));
    }
    CONTRACT_END;
    
    if (IsStandardTearOff(pUnk))
        RETURN ComCallWrapper::GetWrapperFromIP(pUnk);

    if (IsSimpleTearOff(pUnk) || IsInnerUnknown(pUnk))
        RETURN SimpleComCallWrapper::GetWrapperFromIP(pUnk)->GetMainWrapper();

    RETURN NULL;
}
#endif // !DACCESS_COMPILE