diff options
Diffstat (limited to 'src/vm/interoputil.inl')
-rw-r--r-- | src/vm/interoputil.inl | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/vm/interoputil.inl b/src/vm/interoputil.inl new file mode 100644 index 0000000000..80cd8f496d --- /dev/null +++ b/src/vm/interoputil.inl @@ -0,0 +1,79 @@ +// 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. + +// +#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 |