summaryrefslogtreecommitdiff
path: root/src/vm/stdinterfaces_wrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/stdinterfaces_wrapper.cpp')
-rw-r--r--src/vm/stdinterfaces_wrapper.cpp3269
1 files changed, 3269 insertions, 0 deletions
diff --git a/src/vm/stdinterfaces_wrapper.cpp b/src/vm/stdinterfaces_wrapper.cpp
new file mode 100644
index 0000000000..c33c330798
--- /dev/null
+++ b/src/vm/stdinterfaces_wrapper.cpp
@@ -0,0 +1,3269 @@
+// 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.
+//---------------------------------------------------------------------------------
+// stdinterfaces_wrapper.cpp
+//
+// Defines various standard com interfaces
+
+//---------------------------------------------------------------------------------
+
+
+#include "common.h"
+
+#include <ole2.h>
+#include <guidfromname.h>
+#include <olectl.h>
+#include <objsafe.h> // IID_IObjectSafe
+#include "vars.hpp"
+#include "object.h"
+#include "excep.h"
+#include "frames.h"
+#include "vars.hpp"
+#include "runtimecallablewrapper.h"
+#include "comcallablewrapper.h"
+#include "field.h"
+#include "threads.h"
+#include "interoputil.h"
+#include "tlbexport.h"
+#include "comdelegate.h"
+#include "olevariant.h"
+#include "eeconfig.h"
+#include "typehandle.h"
+#include "posterror.h"
+#include <corerror.h>
+#include <mscoree.h>
+#include "mtx.h"
+#include "cgencpu.h"
+#include "interopconverter.h"
+#include "cominterfacemarshaler.h"
+#include "stdinterfaces.h"
+#include "stdinterfaces_internal.h"
+#include "interoputil.inl"
+
+
+interface IEnumConnectionPoints;
+interface IManagedObject;
+
+// IUnknown is part of IDispatch
+// Common vtables for well-known COM interfaces
+// shared by all COM+ callable wrappers.
+
+// All Com+ created vtables have well known IUnknown methods, which is used to identify
+// the type of the interface
+// For e.g. all com+ created tear-offs have the same QI method in their IUnknown portion
+// Unknown_QueryInterface is the QI method for all the tear-offs created from COM+
+//
+// Tearoff interfaces created for std. interfaces such as IProvideClassInfo, IErrorInfo etc.
+// have the AddRef & Release function point to Unknown_AddRefSpecial & Unknown_ReleaseSpecial
+//
+// Inner unknown, or the original unknown for a wrapper has
+// AddRef & Release point to a Unknown_AddRefInner & Unknown_ReleaseInner
+
+// global inner Unknown vtable
+const StdInterfaceDesc<3> g_InnerUnknown =
+{
+ enum_InnerUnknown,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefInner, // special addref to distinguish inner unk
+ (UINT_PTR*)Unknown_ReleaseInner, // special release to distinguish inner unknown
+ }
+};
+
+// global IProvideClassInfo vtable
+const StdInterfaceDesc<4> g_IProvideClassInfo =
+{
+ enum_IProvideClassInfo,
+ {
+ (UINT_PTR*)Unknown_QueryInterface, // don't change this
+ (UINT_PTR*)Unknown_AddRefSpecial, // special addref for std. interface
+ (UINT_PTR*)Unknown_ReleaseSpecial, // special release for std. interface
+ (UINT_PTR*)ClassInfo_GetClassInfo_Wrapper // GetClassInfo
+ }
+};
+
+// global IMarshal vtable
+const StdInterfaceDesc<9> g_IMarshal =
+{
+ enum_IMarshal,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial,
+ (UINT_PTR*)Marshal_GetUnmarshalClass_Wrapper,
+ (UINT_PTR*)Marshal_GetMarshalSizeMax_Wrapper,
+ (UINT_PTR*)Marshal_MarshalInterface_Wrapper,
+ (UINT_PTR*)Marshal_UnmarshalInterface_Wrapper,
+ (UINT_PTR*)Marshal_ReleaseMarshalData_Wrapper,
+ (UINT_PTR*)Marshal_DisconnectObject_Wrapper
+ }
+};
+
+// global ISupportsErrorInfo vtable
+const StdInterfaceDesc<4> g_ISupportsErrorInfo =
+{
+ enum_ISupportsErrorInfo,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial,
+ (UINT_PTR*)SupportsErroInfo_IntfSupportsErrorInfo_Wrapper
+ }
+};
+
+// global IErrorInfo vtable
+const StdInterfaceDesc<8> g_IErrorInfo =
+{
+ enum_IErrorInfo,
+ {
+ (UINT_PTR*)Unknown_QueryInterface_IErrorInfo,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial_IErrorInfo,
+ (UINT_PTR*)ErrorInfo_GetGUID_Wrapper,
+ (UINT_PTR*)ErrorInfo_GetSource_Wrapper,
+ (UINT_PTR*)ErrorInfo_GetDescription_Wrapper,
+ (UINT_PTR*)ErrorInfo_GetHelpFile_Wrapper,
+ (UINT_PTR*)ErrorInfo_GetHelpContext_Wrapper
+ }
+};
+
+// global IManagedObject vtable
+const StdInterfaceDesc<5> g_IManagedObject =
+{
+ enum_IManagedObject,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial,
+ (UINT_PTR*)ManagedObject_GetSerializedBuffer_Wrapper,
+ (UINT_PTR*)ManagedObject_GetObjectIdentity_Wrapper
+ }
+};
+
+// global IConnectionPointContainer vtable
+const StdInterfaceDesc<5> g_IConnectionPointContainer =
+{
+ enum_IConnectionPointContainer,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial,
+ (UINT_PTR*)ConnectionPointContainer_EnumConnectionPoints_Wrapper,
+ (UINT_PTR*)ConnectionPointContainer_FindConnectionPoint_Wrapper
+ }
+};
+
+// global IObjectSafety vtable
+const StdInterfaceDesc<5> g_IObjectSafety =
+{
+ enum_IObjectSafety,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial,
+ (UINT_PTR*)ObjectSafety_GetInterfaceSafetyOptions_Wrapper,
+ (UINT_PTR*)ObjectSafety_SetInterfaceSafetyOptions_Wrapper
+ }
+};
+
+// global IDispatchEx vtable
+const StdInterfaceDesc<15> g_IDispatchEx =
+{
+ enum_IDispatchEx,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial,
+ (UINT_PTR*)DispatchEx_GetTypeInfoCount_Wrapper,
+ (UINT_PTR*)DispatchEx_GetTypeInfo_Wrapper,
+ (UINT_PTR*)DispatchEx_GetIDsOfNames_Wrapper,
+ (UINT_PTR*)DispatchEx_Invoke_Wrapper,
+ (UINT_PTR*)DispatchEx_GetDispID_Wrapper,
+ (UINT_PTR*)DispatchEx_InvokeEx_Wrapper,
+ (UINT_PTR*)DispatchEx_DeleteMemberByName_Wrapper,
+ (UINT_PTR*)DispatchEx_DeleteMemberByDispID_Wrapper,
+ (UINT_PTR*)DispatchEx_GetMemberProperties_Wrapper,
+ (UINT_PTR*)DispatchEx_GetMemberName_Wrapper,
+ (UINT_PTR*)DispatchEx_GetNextDispID_Wrapper,
+ (UINT_PTR*)DispatchEx_GetNameSpaceParent_Wrapper
+ }
+};
+
+// global IWeakReferenceSource vtable
+const StdInterfaceDesc<4> g_IWeakReferenceSource =
+{
+ enum_IWeakReferenceSource,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial,
+ (UINT_PTR*)WeakReferenceSource_GetWeakReference_Wrapper
+ }
+};
+
+// global ICustomPropertyProvider vtable
+const StdInterfaceDesc<10> g_ICustomPropertyProvider =
+{
+ enum_ICustomPropertyProvider,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial,
+ (UINT_PTR*)Inspectable_GetIIDs_Wrapper,
+ (UINT_PTR*)Inspectable_GetRuntimeClassName_Wrapper,
+ (UINT_PTR*)Inspectable_GetTrustLevel_Wrapper,
+ (UINT_PTR*)ICustomPropertyProvider_GetProperty_Wrapper,
+ (UINT_PTR*)ICustomPropertyProvider_GetIndexedProperty_Wrapper,
+ (UINT_PTR*)ICustomPropertyProvider_GetStringRepresentation_Wrapper,
+ (UINT_PTR*)ICustomPropertyProvider_GetType_Wrapper
+ }
+};
+
+// global ICCW vtable
+const StdInterfaceDesc<7> g_ICCW =
+{
+ enum_ICCW,
+ {
+ (UINT_PTR*)Unknown_QueryInterface_ICCW,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial,
+ (UINT_PTR*)ICCW_AddRefFromJupiter_Wrapper,
+ (UINT_PTR*)ICCW_ReleaseFromJupiter_Wrapper,
+ (UINT_PTR*)ICCW_Peg_Wrapper,
+ (UINT_PTR*)ICCW_Unpeg_Wrapper
+ }
+};
+
+// global IAgileObject vtable
+const StdInterfaceDesc<3> g_IAgileObject =
+{
+ enum_IAgileObject,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial
+ }
+};
+
+// global IStringable vtable
+const StdInterfaceDesc<7> g_IStringable =
+{
+ enum_IStringable,
+ {
+ (UINT_PTR*)Unknown_QueryInterface,
+ (UINT_PTR*)Unknown_AddRefSpecial,
+ (UINT_PTR*)Unknown_ReleaseSpecial,
+ (UINT_PTR*)Inspectable_GetIIDs_Wrapper,
+ (UINT_PTR*)Inspectable_GetRuntimeClassName_Wrapper,
+ (UINT_PTR*)Inspectable_GetTrustLevel_Wrapper,
+ (UINT_PTR*)IStringable_ToString_Wrapper
+ }
+};
+
+
+// Generic helper to check if AppDomain matches and perform a DoCallBack otherwise
+inline BOOL IsCurrentDomainValid(ComCallWrapper* pWrap, Thread* pThread)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_ANY;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pWrap));
+ PRECONDITION(CheckPointer(pThread));
+ }
+ CONTRACTL_END;
+
+ _ASSERTE(pWrap != NULL);
+ PREFIX_ASSUME(pWrap != NULL);
+
+ // If we are finalizing all alive objects, or after this stage, we do not allow
+ // a thread to enter EE.
+ if ((g_fEEShutDown & ShutDown_Finalize2) || g_fForbidEnterEE)
+ return FALSE;
+
+ return (!pWrap->NeedToSwitchDomains(pThread));
+}
+
+BOOL IsCurrentDomainValid(ComCallWrapper* pWrap)
+{
+ CONTRACTL { NOTHROW; GC_TRIGGERS; MODE_ANY; SO_TOLERANT; } CONTRACTL_END;
+
+ return IsCurrentDomainValid(pWrap, GetThread());
+}
+
+struct AppDomainSwitchToPreemptiveHelperArgs
+{
+ Context::ADCallBackFcnType pRealCallback;
+ void* pRealArgs;
+};
+
+VOID __stdcall AppDomainSwitchToPreemptiveHelper(LPVOID pv)
+{
+ AppDomainSwitchToPreemptiveHelperArgs* pArgs = (AppDomainSwitchToPreemptiveHelperArgs*)pv;
+
+ CONTRACTL
+ {
+ GC_TRIGGERS;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(pv));
+
+ VOID __stdcall Dispatch_Invoke_CallBack(LPVOID ptr);
+ if (pArgs->pRealCallback == Dispatch_Invoke_CallBack) THROWS; else NOTHROW;
+ }
+ CONTRACTL_END;
+
+ GCX_PREEMP();
+ pArgs->pRealCallback(pArgs->pRealArgs);
+}
+
+VOID AppDomainDoCallBack(ComCallWrapper* pWrap, Context::ADCallBackFcnType pTarget, LPVOID pArgs, HRESULT* phr)
+{
+ CONTRACTL
+ {
+ DISABLED(NOTHROW);
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pWrap));
+ PRECONDITION(CheckPointer(pTarget));
+ PRECONDITION(CheckPointer(pArgs));
+ PRECONDITION(CheckPointer(phr));
+ }
+ CONTRACTL_END;
+
+ // If we are finalizing all alive objects, or after this stage, we do not allow
+ // a thread to enter EE.
+ if ((g_fEEShutDown & ShutDown_Finalize2) || g_fForbidEnterEE)
+ {
+ *phr = E_FAIL;
+ return;
+ }
+
+ BEGIN_EXTERNAL_ENTRYPOINT(phr)
+ {
+ GCX_COOP_THREAD_EXISTS(GET_THREAD());
+ Thread *pThread = GET_THREAD();
+
+ ADID targetADID;
+ Context *pTargetContext;
+ if (pWrap->NeedToSwitchDomains(pThread, &targetADID, &pTargetContext))
+ {
+ // call ourselves again through DoCallBack with a domain transition.
+ // We need to switch back to preemptive GC mode before we call the
+ // real target method.
+ AppDomainSwitchToPreemptiveHelperArgs args = {(Context::ADCallBackFcnType)pTarget, pArgs};
+ pThread->DoContextCallBack(targetADID, pTargetContext, AppDomainSwitchToPreemptiveHelper, &args);
+ }
+ else
+ {
+ // make the call directly not forgetting to switch to preemptive GC mode
+ GCX_PREEMP();
+ ((Context::ADCallBackFcnType)pTarget)(pArgs);
+ }
+ }
+ END_EXTERNAL_ENTRYPOINT;
+}
+
+//-------------------------------------------------------------------------
+// IUnknown methods
+
+struct QIArgs
+{
+ ComCallWrapper* pWrap;
+ IUnknown* pUnk;
+ const IID* riid;
+ void** ppv;
+ HRESULT* hr;
+};
+
+VOID __stdcall Unknown_QueryInterface_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ QIArgs* pArgs = (QIArgs*)ptr;
+
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Unknown_QueryInterface_Internal(pArgs->pWrap, pArgs->pUnk, *pArgs->riid, pArgs->ppv);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Unknown_QueryInterface_CallBack, pArgs, pArgs->hr);;
+ }
+}
+
+HRESULT __stdcall Unknown_QueryInterface(IUnknown* pUnk, REFIID riid, void** ppv)
+{
+ SetupThreadForComCall(E_OUTOFMEMORY);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(ppv, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pUnk);
+ if (IsCurrentDomainValid(pWrap, GET_THREAD()))
+ {
+ return Unknown_QueryInterface_Internal(pWrap, pUnk, riid, ppv);
+ }
+ else
+ {
+ HRESULT hr = S_OK;
+ QIArgs args = {pWrap, pUnk, &riid, ppv, &hr};
+ Unknown_QueryInterface_CallBack(&args);
+ return hr;
+ }
+}
+
+//
+// Non crashing version of Unknown_QueryInterface for ICCW
+// This will either succeed and return a valid AddRef-ed interface pointer, or
+// fail with COR_E_ACCESS_CCW
+//
+HRESULT __stdcall Unknown_QueryInterface_ICCW(IUnknown *pUnk, REFIID riid, void **ppv)
+{
+ SetupThreadForComCall(E_OUTOFMEMORY);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(ppv, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pUnk);
+
+ //
+ // AddRef to keep the object alive
+ // AddRef is "safe" at this point because if it is a CCW with outstanding Jupiter Ref,
+ // we know for sure the CCW is no claimed yet (but the object itself could be)
+ //
+ pWrap->AddRef();
+
+ CCWHolder pCCW = pWrap;
+
+ //
+ // Check if the object is still alive, if it is, it'll be kept alive until we release the extra
+ // ref in CCWHolder
+ // We need to do this in COOP mode to make sure next GC will observe the AddRef change on RefCountHandle
+ // and avoids a race that GC could in the middle of NULL-ing out the RefCountHandle
+ //
+ {
+ GCX_COOP_THREAD_EXISTS(GET_THREAD());
+
+ SimpleComCallWrapper *pSimpleWrap = pWrap->GetSimpleWrapper();
+
+ AppDomainFromIDHolder ad((ADID)pSimpleWrap->GetRawDomainID(), TRUE);
+
+ if (ad.IsUnloaded() || ad->IsUnloading())
+ return COR_E_APPDOMAINUNLOADED;
+
+ //
+ // For CCWs that have outstanding Jupiter-reference, they could be either:
+ // 1. Neutered - in this case it is unsafe to touch m_ppThis
+ // 2. RefCounted handle NULLed out by GC
+ //
+ if (pWrap->GetSimpleWrapper()->IsNeutered() ||
+ pWrap->GetObjectRef() == NULL)
+ {
+ // In those cases, it is unsafe to proceed with a QueryInterface call
+ return COR_E_ACCESSING_CCW;
+ }
+ }
+
+ //
+ // OK. Now the CCW is going to be alive until the end of this scope. We can go ahead and do the
+ // QI now
+ //
+ if (IsCurrentDomainValid(pWrap, GET_THREAD()))
+ {
+ return Unknown_QueryInterface_Internal(pWrap, pUnk, riid, ppv);
+ }
+ else
+ {
+ HRESULT hr = S_OK;
+ QIArgs args = {pWrap, pUnk, &riid, ppv, &hr};
+ Unknown_QueryInterface_CallBack(&args);
+ return hr;
+ }
+}
+
+struct AddRefReleaseArgs
+{
+ IUnknown* pUnk;
+ ULONG* pLong;
+ HRESULT* hr;
+};
+
+#ifdef MDA_SUPPORTED
+VOID __stdcall DirtyCast_Assert(IUnknown* pUnk)
+{
+ WRAPPER_NO_CONTRACT;
+
+ _ASSERTE(!"The native code calling into the CLR has performed an illegal dirty cast on this IUnknown or IDispatch pointer. "
+ "The caller neglected to QI for the correct interface before making this call. This is not a CLR bug. "
+ "A bug should be filed against the native caller.");
+
+ MDA_TRIGGER_ASSISTANT(DirtyCastAndCallOnInterface, ReportViolation(pUnk));
+}
+#endif
+
+ULONG __stdcall Unknown_AddRef(IUnknown* pUnk)
+{
+ // Ensure the Thread is available for contracts and other users of the Thread, but don't do any of
+ // the other "entering managed code" work like going to SO_INTOLERANT or checking for reentrancy.
+ // We don't really need to "enter" the runtime to do an interlocked increment on a refcount, so
+ // all of that stuff should be isolated to rare paths here.
+ SetupThreadForComCall(-1);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ ENTRY_POINT; // implies SO_TOLERANT
+ }
+ CONTRACTL_END;
+
+ // Allow addrefs to go through, coz we are allowing
+ // all releases to go through, otherwise we would
+ // have a mismatch of ref-counts
+ return Unknown_AddRef_Internal(pUnk);
+}
+
+ULONG __stdcall Unknown_Release(IUnknown* pUnk)
+{
+ // Ensure the Thread is available for contracts and other users of the Thread, but don't do any of
+ // the other "entering managed code" work like going to SO_INTOLERANT or checking for reentrancy.
+ // We don't really need to "enter" the runtime to do an interlocked decrement on a refcount, so
+ // all of that stuff should be isolated to rare paths here.
+ SetupThreadForComCall(-1);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ ENTRY_POINT; // implies SO_TOLERANT
+ }
+ CONTRACTL_END;
+
+ // Don't switch domains since we need to allow release calls to go through
+ // even after the AD has been unlaoded. Furthermore release doesn't require
+ // us to transition into the domain to work properly.
+ return Unknown_Release_Internal(pUnk);
+}
+
+ULONG __stdcall Unknown_AddRefInner(IUnknown* pUnk)
+{
+ // Ensure the Thread is available for contracts and other users of the Thread, but don't do any of
+ // the other "entering managed code" work like going to SO_INTOLERANT or checking for reentrancy.
+ // We don't really need to "enter" the runtime to do an interlocked increment on a refcount, so
+ // all of that stuff should be isolated to rare paths here.
+ SetupThreadForComCall(-1);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ ENTRY_POINT; // implies SO_TOLERANT
+ }
+ CONTRACTL_END;
+
+ // Allow addrefs to go through, coz we are allowing
+ // all releases to go through, otherwise we would
+ // have a mismatch of ref-counts
+ return Unknown_AddRefInner_Internal(pUnk);
+}
+
+ULONG __stdcall Unknown_ReleaseInner(IUnknown* pUnk)
+{
+ // Ensure the Thread is available for contracts and other users of the Thread, but don't do any of
+ // the other "entering managed code" work like going to SO_INTOLERANT or checking for reentrancy.
+ // We don't really need to "enter" the runtime to do an interlocked decrement on a refcount, so
+ // all of that stuff should be isolated to rare paths here.
+ SetupThreadForComCall(-1);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ ENTRY_POINT; // implies SO_TOLERANT
+ }
+ CONTRACTL_END;
+
+ // Don't switch domains since we need to allow release calls to go through
+ // even after the AD has been unlaoded. Furthermore release doesn't require
+ // us to transition into the domain to work properly.
+ return Unknown_ReleaseInner_Internal(pUnk);
+}
+
+ULONG __stdcall Unknown_AddRefSpecial(IUnknown* pUnk)
+{
+ // Ensure the Thread is available for contracts and other users of the Thread, but don't do any of
+ // the other "entering managed code" work like going to SO_INTOLERANT or checking for reentrancy.
+ // We don't really need to "enter" the runtime to do an interlocked increment on a refcount, so
+ // all of that stuff should be isolated to rare paths here.
+ SetupThreadForComCall(-1);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ ENTRY_POINT; // implies SO_TOLERANT
+ }
+ CONTRACTL_END;
+
+ // Allow addrefs to go through, coz we are allowing
+ // all releases to go through, otherwise we would
+ // have a mismatch of ref-counts
+ return Unknown_AddRefSpecial_Internal(pUnk);
+}
+
+ULONG __stdcall Unknown_ReleaseSpecial(IUnknown* pUnk)
+{
+ // Ensure the Thread is available for contracts and other users of the Thread, but don't do any of
+ // the other "entering managed code" work like going to SO_INTOLERANT or checking for reentrancy.
+ // We don't really need to "enter" the runtime to do an interlocked decrement on a refcount, so
+ // all of that stuff should be isolated to rare paths here.
+ SetupThreadForComCall(-1);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ ENTRY_POINT; // implies SO_TOLERANT
+ }
+ CONTRACTL_END;
+
+ // Don't switch domains since we need to allow release calls to go through
+ // even after the AD has been unlaoded. Furthermore release doesn't require
+ // us to transition into the domain to work properly.
+ return Unknown_ReleaseSpecial_Internal(pUnk);
+}
+
+HRESULT __stdcall Unknown_QueryInterface_IErrorInfo(IUnknown* pUnk, REFIID riid, void** ppv)
+{
+ // Special version of SetupForComCallHR that doesn't call
+ // CanRunManagedCode() to avoid firing LoaderLock MDA
+ SetupForComCallHRNoCheckCanRunManagedCode();
+
+ WRAPPER_NO_CONTRACT;
+ STATIC_CONTRACT_SO_TOLERANT;
+
+ HRESULT hr = S_OK;
+ if (!CanRunManagedCode(LoaderLockCheck::ForCorrectness))
+ {
+ // if we cannot run managed code, do a very simple QI which responds only to IUnknown and IErrorInfo
+ hr = Unknown_QueryInterface_IErrorInfo_Simple(pUnk, riid, ppv);
+
+ if (hr == E_NOINTERFACE)
+ {
+ // make sure that the MDA fires
+ VERIFY(!CanRunManagedCode(LoaderLockCheck::ForMDA));
+ hr = HOST_E_CLRNOTAVAILABLE;
+ }
+ }
+
+ // otherwise do a regular QI
+ return Unknown_QueryInterface(pUnk, riid, ppv);
+}
+
+// ---------------------------------------------------------------------------
+// Release for IErrorInfo that takes into account that this can be called
+// while holding the loader lock
+// ---------------------------------------------------------------------------
+ULONG __stdcall Unknown_ReleaseSpecial_IErrorInfo(IUnknown* pUnk)
+{
+ // Special version of SetupForComCallDWORD that doesn't call
+ // CanRunManagedCode() to avoid firing LoaderLock MDA
+ // No managed code will be executed in this function
+ SetupForComCallDWORDNoCheckCanRunManagedCode();
+
+ WRAPPER_NO_CONTRACT;
+ STATIC_CONTRACT_SO_TOLERANT;
+
+ // <TODO>Address this violation in context of bug 27409</TODO>
+ CONTRACT_VIOLATION(GCViolation);
+
+ if (!CanRunManagedCode(LoaderLockCheck::None))
+ {
+ // CCW cleanup doesn't run managed code but may trigger operations such as
+ // switching the thread to cooperative mode which is not safe during shutdown.
+ return 0;
+ }
+ else
+ {
+ // Don't switch domains since we need to allow release calls to go through
+ // even after the AD has been unlaoded. Furthermore release doesn't require
+ // us to transition into the domain to work properly.
+ return Unknown_ReleaseSpecial_IErrorInfo_Internal(pUnk);
+ }
+}
+
+
+//-------------------------------------------------------------------------
+// IProvideClassInfo methods
+
+struct GetClassInfoArgs
+{
+ IUnknown* pUnk;
+ ITypeInfo** ppTI; //Address of output variable that receives the type info.
+ HRESULT* hr;
+};
+
+VOID __stdcall ClassInfo_GetClassInfo_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetClassInfoArgs* pArgs = (GetClassInfoArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ClassInfo_GetClassInfo(pArgs->pUnk, pArgs->ppTI);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ClassInfo_GetClassInfo_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall ClassInfo_GetClassInfo_Wrapper(IUnknown* pUnk, ITypeInfo** ppTI)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(ppTI, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetClassInfoArgs args = {pUnk, ppTI, &hr};
+ ClassInfo_GetClassInfo_CallBack(&args);
+ return hr;
+}
+
+
+// ---------------------------------------------------------------------------
+// Interface ISupportsErrorInfo
+
+struct IntfSupportsErrorInfoArgs
+{
+ IUnknown* pUnk;
+ const IID* riid;
+ HRESULT* hr;
+};
+
+VOID __stdcall SupportsErroInfo_IntfSupportsErrorInfo_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ IntfSupportsErrorInfoArgs* pArgs = (IntfSupportsErrorInfoArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = SupportsErroInfo_IntfSupportsErrorInfo(pArgs->pUnk, *pArgs->riid);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, SupportsErroInfo_IntfSupportsErrorInfo_CallBack, pArgs, pArgs->hr);;
+ }
+}
+
+HRESULT __stdcall
+SupportsErroInfo_IntfSupportsErrorInfo_Wrapper(IUnknown* pUnk, REFIID riid)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ IntfSupportsErrorInfoArgs args = {pUnk, &riid, &hr};
+ SupportsErroInfo_IntfSupportsErrorInfo_CallBack(&args);
+ return hr;
+}
+
+// ---------------------------------------------------------------------------
+// Interface IErrorInfo
+
+struct GetDescriptionArgs
+{
+ IUnknown* pUnk;
+ BSTR* pbstDescription;
+ HRESULT* hr;
+};
+
+VOID __stdcall ErrorInfo_GetDescription_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetDescriptionArgs* pArgs = (GetDescriptionArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ErrorInfo_GetDescription(pArgs->pUnk, pArgs->pbstDescription);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ErrorInfo_GetDescription_CallBack, pArgs, pArgs->hr);;
+ }
+}
+
+HRESULT __stdcall ErrorInfo_GetDescription_Wrapper(IUnknown* pUnk, BSTR* pbstrDescription)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(pbstrDescription, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetDescriptionArgs args = {pUnk, pbstrDescription, &hr};
+ ErrorInfo_GetDescription_CallBack(&args);
+ return hr;
+}
+
+struct GetGUIDArgs
+{
+ IUnknown* pUnk;
+ GUID* pguid;
+ HRESULT* hr;
+};
+
+VOID __stdcall ErrorInfo_GetGUID_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetGUIDArgs* pArgs = (GetGUIDArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ErrorInfo_GetGUID(pArgs->pUnk, pArgs->pguid);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ErrorInfo_GetGUID_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall ErrorInfo_GetGUID_Wrapper(IUnknown* pUnk, GUID* pguid)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(pguid, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetGUIDArgs args = {pUnk, pguid, &hr};
+ ErrorInfo_GetGUID_CallBack(&args);
+ return hr;
+}
+
+struct GetHelpContextArgs
+{
+ IUnknown* pUnk;
+ DWORD* pdwHelpCtxt;
+ HRESULT* hr;
+};
+
+VOID _stdcall ErrorInfo_GetHelpContext_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetHelpContextArgs* pArgs = (GetHelpContextArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ErrorInfo_GetHelpContext(pArgs->pUnk, pArgs->pdwHelpCtxt);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ErrorInfo_GetHelpContext_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT _stdcall ErrorInfo_GetHelpContext_Wrapper(IUnknown* pUnk, DWORD* pdwHelpCtxt)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(pdwHelpCtxt, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetHelpContextArgs args = {pUnk, pdwHelpCtxt, &hr};
+ ErrorInfo_GetHelpContext_CallBack(&args);
+ return hr;
+}
+
+struct GetHelpFileArgs
+{
+ IUnknown* pUnk;
+ BSTR* pbstrHelpFile;
+ HRESULT* hr;
+};
+
+VOID __stdcall ErrorInfo_GetHelpFile_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetHelpFileArgs* pArgs = (GetHelpFileArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ErrorInfo_GetHelpFile(pArgs->pUnk, pArgs->pbstrHelpFile);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ErrorInfo_GetHelpFile_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall ErrorInfo_GetHelpFile_Wrapper(IUnknown* pUnk, BSTR* pbstrHelpFile)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(pbstrHelpFile, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetHelpFileArgs args = {pUnk, pbstrHelpFile, &hr};
+ ErrorInfo_GetHelpFile_CallBack(&args);
+ return hr;
+}
+
+struct GetSourceArgs
+{
+ IUnknown* pUnk;
+ BSTR* pbstrSource;
+ HRESULT* hr;
+};
+
+VOID __stdcall ErrorInfo_GetSource_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetSourceArgs* pArgs = (GetSourceArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ErrorInfo_GetSource(pArgs->pUnk, pArgs->pbstrSource);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ErrorInfo_GetSource_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall ErrorInfo_GetSource_Wrapper(IUnknown* pUnk, BSTR* pbstrSource)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(pbstrSource, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetSourceArgs args = {pUnk, pbstrSource, &hr};
+ ErrorInfo_GetSource_CallBack(&args);
+ return hr;
+}
+
+
+// ---------------------------------------------------------------------------
+// Interface IDispatch
+//
+// IDispatch methods for COM+ objects. These methods dispatch's to the
+// appropriate implementation based on the flags of the class that
+// implements them.
+
+struct GetTypeInfoCountArgs
+{
+ IDispatch* pUnk;
+ unsigned int *pctinfo;
+ HRESULT* hr;
+};
+
+VOID __stdcall Dispatch_GetTypeInfoCount_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetTypeInfoCountArgs* pArgs = (GetTypeInfoCountArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Dispatch_GetTypeInfoCount(pArgs->pUnk, pArgs->pctinfo);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Dispatch_GetTypeInfoCount_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Dispatch_GetTypeInfoCount_Wrapper(IDispatch* pDisp, unsigned int *pctinfo)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pctinfo, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetTypeInfoCountArgs args = {pDisp, pctinfo, &hr};
+ Dispatch_GetTypeInfoCount_CallBack(&args);
+ return hr;
+}
+
+struct GetTypeInfoArgs
+{
+ IDispatch* pUnk;
+ unsigned int itinfo;
+ LCID lcid;
+ ITypeInfo **pptinfo;
+ HRESULT* hr;
+};
+
+VOID __stdcall Dispatch_GetTypeInfo_CallBack (LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetTypeInfoArgs* pArgs = (GetTypeInfoArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Dispatch_GetTypeInfo(pArgs->pUnk, pArgs->itinfo, pArgs->lcid, pArgs->pptinfo);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Dispatch_GetTypeInfo_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Dispatch_GetTypeInfo_Wrapper(IDispatch* pDisp, unsigned int itinfo, LCID lcid, ITypeInfo **pptinfo)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pptinfo, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetTypeInfoArgs args = {pDisp, itinfo, lcid, pptinfo, &hr};
+ Dispatch_GetTypeInfo_CallBack(&args);
+ return hr;
+}
+
+struct GetIDsOfNamesArgs
+{
+ IDispatch* pUnk;
+ const IID* riid;
+ OLECHAR **rgszNames;
+ unsigned int cNames;
+ LCID lcid;
+ DISPID *rgdispid;
+ HRESULT* hr;
+};
+
+VOID __stdcall Dispatch_GetIDsOfNames_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetIDsOfNamesArgs* pArgs = (GetIDsOfNamesArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Dispatch_GetIDsOfNames(pArgs->pUnk, *pArgs->riid, pArgs->rgszNames,
+ pArgs->cNames, pArgs->lcid, pArgs->rgdispid);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Dispatch_GetIDsOfNames_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Dispatch_GetIDsOfNames_Wrapper(IDispatch* pDisp, REFIID riid, __in_ecount(cNames) OLECHAR **rgszNames,
+ unsigned int cNames, LCID lcid, DISPID *rgdispid)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(rgszNames, NULL_OK));
+ PRECONDITION(CheckPointer(rgdispid, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetIDsOfNamesArgs args = {pDisp, &riid, rgszNames, cNames, lcid, rgdispid, &hr};
+ Dispatch_GetIDsOfNames_CallBack(&args);
+ return hr;
+}
+
+VOID __stdcall InternalDispatchImpl_GetIDsOfNames_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetIDsOfNamesArgs* pArgs = (GetIDsOfNamesArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = InternalDispatchImpl_GetIDsOfNames(pArgs->pUnk, *pArgs->riid, pArgs->rgszNames,
+ pArgs->cNames, pArgs->lcid, pArgs->rgdispid);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, InternalDispatchImpl_GetIDsOfNames_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall InternalDispatchImpl_GetIDsOfNames_Wrapper(IDispatch* pDisp, REFIID riid, __in_ecount(cNames) OLECHAR **rgszNames,
+ unsigned int cNames, LCID lcid, DISPID *rgdispid)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(rgszNames, NULL_OK));
+ PRECONDITION(CheckPointer(rgdispid, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetIDsOfNamesArgs args = {pDisp, &riid, rgszNames, cNames, lcid, rgdispid, &hr};
+ InternalDispatchImpl_GetIDsOfNames_CallBack(&args);
+ return hr;
+}
+
+struct InvokeArgs
+{
+ IDispatch* pUnk;
+ DISPID dispidMember;
+ const IID* riid;
+ LCID lcid;
+ unsigned short wFlags;
+ DISPPARAMS *pdispparams;
+ VARIANT *pvarResult;
+ EXCEPINFO *pexcepinfo;
+ unsigned int *puArgErr;
+ HRESULT* hr;
+};
+
+VOID __stdcall Dispatch_Invoke_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ THROWS; // Dispatch_Invoke can throw
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ InvokeArgs* pArgs = (InvokeArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Dispatch_Invoke(pArgs->pUnk, pArgs->dispidMember, *pArgs->riid,
+ pArgs->lcid, pArgs->wFlags, pArgs->pdispparams, pArgs->pvarResult,
+ pArgs->pexcepinfo, pArgs->puArgErr);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Dispatch_Invoke_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Dispatch_Invoke_Wrapper(IDispatch* pDisp, DISPID dispidMember, REFIID riid, LCID lcid, unsigned short wFlags,
+ DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, unsigned int *puArgErr)
+{
+ HRESULT hrRetVal = S_OK;
+
+#ifdef FEATURE_CORRUPTING_EXCEPTIONS
+ // SetupForComCallHR uses "SO_INTOLERANT_CODE_NOTHROW" to setup the SO-Intolerant transition
+ // for COM Interop. However, "SO_INTOLERANT_CODE_NOTHROW" expects that no exception can escape
+ // through this boundary but all it does is (in addition to checking that no exception has escaped it)
+ // do stack probing.
+ //
+ // However, Corrupting Exceptions [CE] can escape the COM Interop boundary. Thus, to address that scenario,
+ // we use the macro below that uses BEGIN_SO_INTOLERANT_CODE_NOTHROW to do the equivalent of
+ // SO_INTOLERANT_CODE_NOTHROW and yet allow for CEs to escape through. Since there will be a corresponding
+ // END_SO_INTOLERANT_CODE, the call is splitted into two parts: the Begin and End (see below).
+ BeginSetupForComCallHRWithEscapingCorruptingExceptions();
+#else // !FEATURE_CORRUPTING_EXCEPTIONS
+ SetupForComCallHR();
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+
+
+ CONTRACTL
+ {
+ THROWS; // Dispatch_Invoke_CallBack can throw
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pdispparams, NULL_OK));
+ PRECONDITION(CheckPointer(pvarResult, NULL_OK));
+ PRECONDITION(CheckPointer(pexcepinfo, NULL_OK));
+ PRECONDITION(CheckPointer(puArgErr, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ InvokeArgs args = {pDisp, dispidMember, &riid, lcid, wFlags, pdispparams,
+ pvarResult, pexcepinfo, puArgErr, &hrRetVal};
+ Dispatch_Invoke_CallBack(&args);
+
+#ifdef FEATURE_CORRUPTING_EXCEPTIONS
+ EndSetupForComCallHRWithEscapingCorruptingExceptions();
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+
+ return hrRetVal;
+}
+
+VOID __stdcall InternalDispatchImpl_Invoke_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ InvokeArgs* pArgs = (InvokeArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = InternalDispatchImpl_Invoke(pArgs->pUnk, pArgs->dispidMember, *pArgs->riid,
+ pArgs->lcid, pArgs->wFlags, pArgs->pdispparams, pArgs->pvarResult,
+ pArgs->pexcepinfo, pArgs->puArgErr);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, InternalDispatchImpl_Invoke_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall InternalDispatchImpl_Invoke_Wrapper(IDispatch* pDisp, DISPID dispidMember, REFIID riid, LCID lcid,
+ unsigned short wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult,
+ EXCEPINFO *pexcepinfo, unsigned int *puArgErr)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pdispparams, NULL_OK));
+ PRECONDITION(CheckPointer(pvarResult, NULL_OK));
+ PRECONDITION(CheckPointer(pexcepinfo, NULL_OK));
+ PRECONDITION(CheckPointer(puArgErr, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ InvokeArgs args = {pDisp, dispidMember, &riid, lcid, wFlags, pdispparams,
+ pvarResult, pexcepinfo, puArgErr, &hr};
+ InternalDispatchImpl_Invoke_CallBack(&args);
+ return hr;
+}
+
+// ---------------------------------------------------------------------------
+// Interface IDispatchEx
+
+struct GetTypeInfoCountExArgs
+{
+ IDispatchEx* pUnk;
+ unsigned int *pctinfo;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_GetTypeInfoCount_CallBack (LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetTypeInfoCountExArgs* pArgs = (GetTypeInfoCountExArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_GetTypeInfoCount(pArgs->pUnk, pArgs->pctinfo);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_GetTypeInfoCount_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_GetTypeInfoCount_Wrapper(IDispatchEx* pDisp, unsigned int *pctinfo)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pctinfo, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetTypeInfoCountExArgs args = {pDisp, pctinfo, &hr};
+ DispatchEx_GetTypeInfoCount_CallBack(&args);
+ return hr;
+}
+
+struct GetTypeInfoExArgs
+{
+ IDispatch* pUnk;
+ unsigned int itinfo;
+ LCID lcid;
+ ITypeInfo **pptinfo;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_GetTypeInfo_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetTypeInfoExArgs* pArgs = (GetTypeInfoExArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_GetTypeInfo(pArgs->pUnk, pArgs->itinfo, pArgs->lcid, pArgs->pptinfo);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_GetTypeInfo_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_GetTypeInfo_Wrapper(IDispatchEx* pDisp, unsigned int itinfo, LCID lcid, ITypeInfo **pptinfo)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pptinfo, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetTypeInfoExArgs args = {pDisp, itinfo, lcid, pptinfo, &hr};
+ DispatchEx_GetTypeInfo_CallBack(&args);
+ return hr;
+}
+
+struct GetIDsOfNamesExArgs
+{
+ IDispatchEx* pUnk;
+ const IID* riid;
+ OLECHAR **rgszNames;
+ unsigned int cNames;
+ LCID lcid;
+ DISPID *rgdispid;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_GetIDsOfNames_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetIDsOfNamesExArgs* pArgs = (GetIDsOfNamesExArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_GetIDsOfNames(pArgs->pUnk, *pArgs->riid, pArgs->rgszNames,
+ pArgs->cNames, pArgs->lcid, pArgs->rgdispid);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_GetIDsOfNames_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_GetIDsOfNames_Wrapper(IDispatchEx* pDisp, REFIID riid, __in_ecount(cNames) OLECHAR **rgszNames,
+ unsigned int cNames, LCID lcid, DISPID *rgdispid)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(rgszNames, NULL_OK));
+ PRECONDITION(CheckPointer(rgdispid, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetIDsOfNamesExArgs args = {pDisp, &riid, rgszNames, cNames, lcid, rgdispid, &hr};
+ DispatchEx_GetIDsOfNames_CallBack(&args);
+ return hr;
+}
+
+struct DispExInvokeArgs
+{
+ IDispatchEx* pUnk;
+ DISPID dispidMember;
+ const IID* riid;
+ LCID lcid;
+ unsigned short wFlags;
+ DISPPARAMS *pdispparams;
+ VARIANT *pvarResult;
+ EXCEPINFO *pexcepinfo;
+ unsigned int *puArgErr;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_Invoke_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ DispExInvokeArgs* pArgs = (DispExInvokeArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_Invoke(pArgs->pUnk, pArgs->dispidMember, *pArgs->riid,
+ pArgs->lcid, pArgs->wFlags, pArgs->pdispparams, pArgs->pvarResult,
+ pArgs->pexcepinfo, pArgs->puArgErr);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_Invoke_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_Invoke_Wrapper(IDispatchEx* pDisp, DISPID dispidMember, REFIID riid, LCID lcid,
+ unsigned short wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult,
+ EXCEPINFO *pexcepinfo, unsigned int *puArgErr)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pdispparams, NULL_OK));
+ PRECONDITION(CheckPointer(pvarResult, NULL_OK));
+ PRECONDITION(CheckPointer(pexcepinfo, NULL_OK));
+ PRECONDITION(CheckPointer(puArgErr, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ DispExInvokeArgs args = {pDisp, dispidMember, &riid, lcid, wFlags, pdispparams,
+ pvarResult, pexcepinfo, puArgErr, &hr};
+ DispatchEx_Invoke_CallBack(&args);
+ return hr;
+}
+
+struct DeleteMemberByDispIDArgs
+{
+ IDispatchEx* pDisp;
+ DISPID id;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_DeleteMemberByDispID_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ DeleteMemberByDispIDArgs* pArgs = (DeleteMemberByDispIDArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pDisp);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_DeleteMemberByDispID(pArgs->pDisp, pArgs->id);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_DeleteMemberByDispID_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_DeleteMemberByDispID_Wrapper(IDispatchEx* pDisp, DISPID id)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ DeleteMemberByDispIDArgs args = {pDisp, id, &hr};
+ DispatchEx_DeleteMemberByDispID_CallBack(&args);
+ return hr;
+}
+
+struct DeleteMemberByNameArgs
+{
+ IDispatchEx* pDisp;
+ BSTR bstrName;
+ DWORD grfdex;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_DeleteMemberByName_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ DeleteMemberByNameArgs* pArgs = (DeleteMemberByNameArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pDisp);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_DeleteMemberByName(pArgs->pDisp, pArgs->bstrName, pArgs->grfdex);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_DeleteMemberByName_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_DeleteMemberByName_Wrapper(IDispatchEx* pDisp, BSTR bstrName, DWORD grfdex)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ DeleteMemberByNameArgs args = {pDisp, bstrName, grfdex, &hr};
+ DispatchEx_DeleteMemberByName_CallBack(&args);
+ return hr;
+}
+
+struct GetMemberNameArgs
+{
+ IDispatchEx* pDisp;
+ DISPID id;
+ BSTR *pbstrName;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_GetMemberName_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetMemberNameArgs* pArgs = (GetMemberNameArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pDisp);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_GetMemberName(pArgs->pDisp, pArgs->id, pArgs->pbstrName);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_GetMemberName_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_GetMemberName_Wrapper(IDispatchEx* pDisp, DISPID id, BSTR *pbstrName)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pbstrName, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetMemberNameArgs args = {pDisp, id, pbstrName, &hr};
+ DispatchEx_GetMemberName_CallBack(&args);
+ return hr;
+}
+
+struct GetDispIDArgs
+{
+ IDispatchEx* pDisp;
+ BSTR bstrName;
+ DWORD grfdex;
+ DISPID *pid;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_GetDispID_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetDispIDArgs* pArgs = (GetDispIDArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pDisp);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_GetDispID(pArgs->pDisp, pArgs->bstrName, pArgs->grfdex, pArgs->pid);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_GetDispID_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_GetDispID_Wrapper(IDispatchEx* pDisp, BSTR bstrName, DWORD grfdex, DISPID *pid)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pid, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetDispIDArgs args = {pDisp, bstrName, grfdex, pid, &hr};
+ DispatchEx_GetDispID_CallBack(&args);
+ return hr;
+}
+
+struct GetMemberPropertiesArgs
+{
+ IDispatchEx* pDisp;
+ DISPID id;
+ DWORD grfdexFetch;
+ DWORD *pgrfdex;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_GetMemberProperties_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetMemberPropertiesArgs* pArgs = (GetMemberPropertiesArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pDisp);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_GetMemberProperties(pArgs->pDisp, pArgs->id, pArgs->grfdexFetch,
+ pArgs->pgrfdex);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_GetMemberProperties_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_GetMemberProperties_Wrapper(IDispatchEx* pDisp, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pgrfdex, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetMemberPropertiesArgs args = {pDisp, id, grfdexFetch, pgrfdex, &hr};
+ DispatchEx_GetMemberProperties_CallBack(&args);
+ return hr;
+}
+
+struct GetNameSpaceParentArgs
+{
+ IDispatchEx* pDisp;
+ IUnknown **ppunk;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_GetNameSpaceParent_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetNameSpaceParentArgs* pArgs = (GetNameSpaceParentArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pDisp);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_GetNameSpaceParent(pArgs->pDisp, pArgs->ppunk);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_GetNameSpaceParent_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_GetNameSpaceParent_Wrapper(IDispatchEx* pDisp, IUnknown **ppunk)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(ppunk, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetNameSpaceParentArgs args = {pDisp, ppunk, &hr};
+ DispatchEx_GetNameSpaceParent_CallBack(&args);
+ return hr;
+}
+
+struct GetNextDispIDArgs
+{
+ IDispatchEx* pDisp;
+ DWORD grfdex;
+ DISPID id;
+ DISPID *pid;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_GetNextDispID_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetNextDispIDArgs* pArgs = (GetNextDispIDArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pDisp);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_GetNextDispID(pArgs->pDisp, pArgs->grfdex, pArgs->id, pArgs->pid);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_GetNextDispID_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_GetNextDispID_Wrapper(IDispatchEx* pDisp, DWORD grfdex, DISPID id, DISPID *pid)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pid, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetNextDispIDArgs args = {pDisp, grfdex, id, pid, &hr};
+ DispatchEx_GetNextDispID_CallBack(&args);
+ return hr;
+}
+
+struct DispExInvokeExArgs
+{
+ IDispatchEx* pDisp;
+ DISPID id;
+ LCID lcid;
+ WORD wFlags;
+ DISPPARAMS *pdp;
+ VARIANT *pVarRes;
+ EXCEPINFO *pei;
+ IServiceProvider *pspCaller;
+ HRESULT* hr;
+};
+
+VOID __stdcall DispatchEx_InvokeEx_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ DispExInvokeExArgs* pArgs = (DispExInvokeExArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pDisp);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = DispatchEx_InvokeEx(pArgs->pDisp, pArgs->id,
+ pArgs->lcid, pArgs->wFlags, pArgs->pdp, pArgs->pVarRes,
+ pArgs->pei, pArgs->pspCaller);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, DispatchEx_InvokeEx_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall DispatchEx_InvokeEx_Wrapper(IDispatchEx* pDisp, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
+ VARIANT *pVarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pDisp));
+ PRECONDITION(CheckPointer(pdp, NULL_OK));
+ PRECONDITION(CheckPointer(pVarRes, NULL_OK));
+ PRECONDITION(CheckPointer(pei, NULL_OK));
+ PRECONDITION(CheckPointer(pspCaller, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ DispExInvokeExArgs args = {pDisp, id, lcid, wFlags, pdp, pVarRes, pei, pspCaller, &hr};
+ DispatchEx_InvokeEx_CallBack(&args);
+ return hr;
+}
+
+// ---------------------------------------------------------------------------
+// Interface IInspectable
+
+struct InspectableGetIIDsArgs
+{
+ IInspectable *pInsp;
+ ULONG *iidCount;
+ IID **iids;
+ HRESULT* hr;
+};
+
+VOID __stdcall Inspectable_GetIIDs_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ InspectableGetIIDsArgs* pArgs = (InspectableGetIIDsArgs *)ptr;
+ ComCallWrapper *pWrap = MapIUnknownToWrapper(pArgs->pInsp);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Inspectable_GetIIDs(pArgs->pInsp, pArgs->iidCount, pArgs->iids);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Inspectable_GetIIDs_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Inspectable_GetIIDs_Wrapper(IInspectable *pInsp, ULONG *iidCount, IID **iids)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pInsp));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ InspectableGetIIDsArgs args = {pInsp, iidCount, iids, &hr};
+ Inspectable_GetIIDs_CallBack(&args);
+ return hr;
+}
+
+struct InspectableGetRuntimeClassNameArgs
+{
+ IInspectable *pInsp;
+ HSTRING *className;
+ HRESULT* hr;
+};
+
+VOID Inspectable_GetRuntimeClassName_Callback(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ InspectableGetRuntimeClassNameArgs* pArgs = (InspectableGetRuntimeClassNameArgs *)ptr;
+ ComCallWrapper *pWrap = MapIUnknownToWrapper(pArgs->pInsp);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Inspectable_GetRuntimeClassName(pArgs->pInsp, pArgs->className);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Inspectable_GetRuntimeClassName_Callback, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Inspectable_GetRuntimeClassName_Wrapper(IInspectable *pInsp, HSTRING *className)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pInsp));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ InspectableGetRuntimeClassNameArgs args = { pInsp, className, &hr };
+ Inspectable_GetRuntimeClassName_Callback(&args);
+
+ return hr;
+}
+
+HRESULT __stdcall Inspectable_GetTrustLevel_Wrapper(IInspectable *pInsp, TrustLevel *trustLevel)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pInsp));
+ }
+ CONTRACTL_END;
+
+ if (trustLevel == NULL)
+ return E_POINTER;
+
+ // all managed WinRT objects are BaseTrust for now
+ *trustLevel = BaseTrust;
+ return S_OK;
+}
+
+// ---------------------------------------------------------------------------
+// Interface IWeakReferenceSource
+
+struct GetWeakReferenceArgs
+{
+ IWeakReferenceSource *pRefSrc;
+ IWeakReference **weakReference;
+ HRESULT* hr;
+};
+
+VOID __stdcall WeakReferenceSource_GetWeakReference_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetWeakReferenceArgs* pArgs = (GetWeakReferenceArgs *)ptr;
+ ComCallWrapper *pWrap = MapIUnknownToWrapper(pArgs->pRefSrc);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = WeakReferenceSource_GetWeakReference(pArgs->pRefSrc, pArgs->weakReference);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, WeakReferenceSource_GetWeakReference_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall WeakReferenceSource_GetWeakReference_Wrapper(IWeakReferenceSource *pRefSrc, IWeakReference **weakReference)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pRefSrc));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetWeakReferenceArgs args = {pRefSrc, weakReference, &hr};
+ WeakReferenceSource_GetWeakReference_CallBack(&args);
+ return hr;
+}
+
+// ---------------------------------------------------------------------------
+// Interface IMarshal
+
+struct GetUnmarshalClassArgs
+{
+ IMarshal* pUnk;
+ const IID* riid;
+ void * pv;
+ ULONG dwDestContext;
+ void * pvDestContext;
+ ULONG mshlflags;
+ LPCLSID pclsid;
+ HRESULT* hr;
+
+};
+
+VOID __stdcall Marshal_GetUnmarshalClass_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetUnmarshalClassArgs* pArgs = (GetUnmarshalClassArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Marshal_GetUnmarshalClass(pArgs->pUnk, *(pArgs->riid), pArgs->pv,
+ pArgs->dwDestContext, pArgs->pvDestContext, pArgs->mshlflags,
+ pArgs->pclsid);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Marshal_GetUnmarshalClass_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Marshal_GetUnmarshalClass_Wrapper(IMarshal* pMarsh, REFIID riid, void * pv, ULONG dwDestContext,
+ void * pvDestContext, ULONG mshlflags, LPCLSID pclsid)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pMarsh));
+ PRECONDITION(CheckPointer(pv, NULL_OK));
+ PRECONDITION(CheckPointer(pvDestContext, NULL_OK));
+ PRECONDITION(CheckPointer(pclsid, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetUnmarshalClassArgs args = {pMarsh, &riid, pv, dwDestContext, pvDestContext,
+ mshlflags, pclsid, &hr};
+ Marshal_GetUnmarshalClass_CallBack(&args);
+ return hr;
+}
+
+struct GetMarshalSizeMaxArgs
+{
+ IMarshal* pUnk;
+ const IID* riid;
+ void * pv;
+ ULONG dwDestContext;
+ void * pvDestContext;
+ ULONG mshlflags;
+ ULONG * pSize;
+ HRESULT* hr;
+
+};
+
+VOID __stdcall Marshal_GetMarshalSizeMax_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetMarshalSizeMaxArgs* pArgs = (GetMarshalSizeMaxArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Marshal_GetMarshalSizeMax(pArgs->pUnk, *(pArgs->riid), pArgs->pv,
+ pArgs->dwDestContext, pArgs->pvDestContext, pArgs->mshlflags,
+ pArgs->pSize);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Marshal_GetMarshalSizeMax_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+
+HRESULT __stdcall Marshal_GetMarshalSizeMax_Wrapper(IMarshal* pMarsh, REFIID riid, void * pv, ULONG dwDestContext,
+ void * pvDestContext, ULONG mshlflags, ULONG * pSize)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pMarsh));
+ PRECONDITION(CheckPointer(pv, NULL_OK));
+ PRECONDITION(CheckPointer(pvDestContext, NULL_OK));
+ PRECONDITION(CheckPointer(pSize, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetMarshalSizeMaxArgs args = {pMarsh, &riid, pv, dwDestContext, pvDestContext,
+ mshlflags, pSize, &hr};
+ Marshal_GetMarshalSizeMax_CallBack(&args);
+ return hr;
+}
+
+struct MarshalInterfaceArgs
+{
+ IMarshal* pUnk;
+ LPSTREAM pStm;
+ const IID* riid;
+ void * pv;
+ ULONG dwDestContext;
+ void * pvDestContext;
+ ULONG mshlflags;
+ HRESULT* hr;
+
+};
+
+VOID __stdcall Marshal_MarshalInterface_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ MarshalInterfaceArgs* pArgs = (MarshalInterfaceArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Marshal_MarshalInterface(pArgs->pUnk, pArgs->pStm, *(pArgs->riid), pArgs->pv,
+ pArgs->dwDestContext, pArgs->pvDestContext, pArgs->mshlflags);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Marshal_MarshalInterface_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Marshal_MarshalInterface_Wrapper(IMarshal* pMarsh, LPSTREAM pStm, REFIID riid, void * pv,
+ ULONG dwDestContext, LPVOID pvDestContext, ULONG mshlflags)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pMarsh));
+ PRECONDITION(CheckPointer(pv, NULL_OK));
+ PRECONDITION(CheckPointer(pvDestContext, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ MarshalInterfaceArgs args = {pMarsh, pStm, &riid, pv, dwDestContext, pvDestContext,
+ mshlflags, &hr};
+ Marshal_MarshalInterface_CallBack(&args);
+ return hr;
+}
+
+struct UnmarshalInterfaceArgs
+{
+ IMarshal* pUnk;
+ LPSTREAM pStm;
+ const IID* riid;
+ void ** ppvObj;
+ HRESULT* hr;
+
+};
+
+VOID __stdcall Marshal_UnmarshalInterface_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ UnmarshalInterfaceArgs* pArgs = (UnmarshalInterfaceArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Marshal_UnmarshalInterface(pArgs->pUnk, pArgs->pStm, *(pArgs->riid), pArgs->ppvObj);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Marshal_UnmarshalInterface_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Marshal_UnmarshalInterface_Wrapper(IMarshal* pMarsh, LPSTREAM pStm, REFIID riid, void ** ppvObj)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pMarsh));
+ PRECONDITION(CheckPointer(pStm, NULL_OK));
+ PRECONDITION(CheckPointer(ppvObj, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ UnmarshalInterfaceArgs args = {pMarsh, pStm, &riid, ppvObj, &hr};
+ Marshal_UnmarshalInterface_CallBack(&args);
+ return hr;
+}
+
+struct ReleaseMarshalDataArgs
+{
+ IMarshal* pUnk;
+ LPSTREAM pStm;
+ HRESULT* hr;
+
+};
+
+VOID __stdcall Marshal_ReleaseMarshalData_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ ReleaseMarshalDataArgs* pArgs = (ReleaseMarshalDataArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Marshal_ReleaseMarshalData(pArgs->pUnk, pArgs->pStm);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Marshal_ReleaseMarshalData_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Marshal_ReleaseMarshalData_Wrapper(IMarshal* pMarsh, LPSTREAM pStm)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pMarsh));
+ PRECONDITION(CheckPointer(pStm, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ ReleaseMarshalDataArgs args = {pMarsh, pStm, &hr};
+ Marshal_ReleaseMarshalData_CallBack(&args);
+ return hr;
+}
+
+struct DisconnectObjectArgs
+{
+ IMarshal* pUnk;
+ ULONG dwReserved;
+ HRESULT* hr;
+};
+
+VOID __stdcall Marshal_DisconnectObject_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ DisconnectObjectArgs* pArgs = (DisconnectObjectArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = Marshal_DisconnectObject(pArgs->pUnk, pArgs->dwReserved);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, Marshal_DisconnectObject_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall Marshal_DisconnectObject_Wrapper(IMarshal* pMarsh, ULONG dwReserved)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pMarsh));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ DisconnectObjectArgs args = {pMarsh, dwReserved, &hr};
+ Marshal_DisconnectObject_CallBack(&args);
+ return hr;
+}
+
+
+// ---------------------------------------------------------------------------
+// Interface IManagedObject
+
+struct GetObjectIdentityArgs
+{
+ IManagedObject *pUnk;
+ BSTR* pBSTRGUID;
+ DWORD* pAppDomainID;
+ void** pCCW;
+ HRESULT* hr;
+};
+
+VOID __stdcall ManagedObject_GetObjectIdentity_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetObjectIdentityArgs* pArgs = (GetObjectIdentityArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ManagedObject_GetObjectIdentity(pArgs->pUnk, pArgs->pBSTRGUID, pArgs->pAppDomainID,
+ pArgs->pCCW);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ManagedObject_GetObjectIdentity_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall ManagedObject_GetObjectIdentity_Wrapper(IManagedObject *pUnk, BSTR* pBSTRGUID, DWORD* pAppDomainID, void** pCCW)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(pBSTRGUID, NULL_OK));
+ PRECONDITION(CheckPointer(pAppDomainID, NULL_OK));
+ PRECONDITION(CheckPointer(pCCW, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetObjectIdentityArgs args = {pUnk, pBSTRGUID, pAppDomainID, pCCW, &hr};
+ ManagedObject_GetObjectIdentity_CallBack(&args);
+ return hr;
+}
+
+struct GetSerializedBufferArgs
+{
+ IManagedObject *pUnk;
+ BSTR* pBStr;
+ HRESULT* hr;
+};
+
+VOID __stdcall ManagedObject_GetSerializedBuffer_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetSerializedBufferArgs* pArgs = (GetSerializedBufferArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ManagedObject_GetSerializedBuffer(pArgs->pUnk, pArgs->pBStr);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ManagedObject_GetSerializedBuffer_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall ManagedObject_GetSerializedBuffer_Wrapper(IManagedObject *pUnk, BSTR* pBStr)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(pBStr, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetSerializedBufferArgs args = {pUnk, pBStr, &hr};
+ ManagedObject_GetSerializedBuffer_CallBack(&args);
+ return hr;
+}
+
+
+// ---------------------------------------------------------------------------
+// Interface IConnectionPointContainer
+
+struct EnumConnectionPointsArgs
+{
+ IUnknown* pUnk;
+ IEnumConnectionPoints **ppEnum;
+ HRESULT* hr;
+};
+
+VOID __stdcall ConnectionPointContainer_EnumConnectionPoints_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ EnumConnectionPointsArgs* pArgs = (EnumConnectionPointsArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ConnectionPointContainer_EnumConnectionPoints(pArgs->pUnk, pArgs->ppEnum);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ConnectionPointContainer_EnumConnectionPoints_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall ConnectionPointContainer_EnumConnectionPoints_Wrapper(IUnknown* pUnk, IEnumConnectionPoints **ppEnum)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(ppEnum, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ EnumConnectionPointsArgs args = {pUnk, ppEnum, &hr};
+ ConnectionPointContainer_EnumConnectionPoints_CallBack(&args);
+ return hr;
+}
+
+struct FindConnectionPointArgs
+{
+ IUnknown* pUnk;
+ const IID* riid;
+ IConnectionPoint **ppCP;
+ HRESULT* hr;
+};
+
+VOID __stdcall ConnectionPointContainer_FindConnectionPoint_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ FindConnectionPointArgs* pArgs = (FindConnectionPointArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ConnectionPointContainer_FindConnectionPoint(pArgs->pUnk, *(pArgs->riid),
+ pArgs->ppCP);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ConnectionPointContainer_FindConnectionPoint_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+HRESULT __stdcall ConnectionPointContainer_FindConnectionPoint_Wrapper(IUnknown* pUnk, REFIID riid, IConnectionPoint **ppCP)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(ppCP, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ FindConnectionPointArgs args = {pUnk, &riid, ppCP, &hr};
+ ConnectionPointContainer_FindConnectionPoint_CallBack(&args);
+ return hr;
+}
+
+
+//------------------------------------------------------------------------------------------
+// IObjectSafety methods for COM+ objects
+
+struct GetInterfaceSafetyArgs
+{
+ IUnknown* pUnk;
+ const IID* riid;
+ DWORD *pdwSupportedOptions;
+ DWORD *pdwEnabledOptions;
+ HRESULT* hr;
+};
+
+VOID __stdcall ObjectSafety_GetInterfaceSafetyOptions_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ GetInterfaceSafetyArgs* pArgs = (GetInterfaceSafetyArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ObjectSafety_GetInterfaceSafetyOptions(pArgs->pUnk, *(pArgs->riid),
+ pArgs->pdwSupportedOptions,
+ pArgs->pdwEnabledOptions);
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ObjectSafety_GetInterfaceSafetyOptions_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+
+HRESULT __stdcall ObjectSafety_GetInterfaceSafetyOptions_Wrapper(IUnknown* pUnk, REFIID riid,
+ DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ PRECONDITION(CheckPointer(pdwSupportedOptions, NULL_OK));
+ PRECONDITION(CheckPointer(pdwEnabledOptions, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ GetInterfaceSafetyArgs args = {pUnk, &riid, pdwSupportedOptions, pdwEnabledOptions, &hr};
+ ObjectSafety_GetInterfaceSafetyOptions_CallBack(&args);
+ return hr;
+}
+
+struct SetInterfaceSafetyArgs
+{
+ IUnknown* pUnk;
+ const IID* riid;
+ DWORD dwOptionSetMask;
+ DWORD dwEnabledOptions;
+ HRESULT* hr;
+};
+
+VOID __stdcall ObjectSafety_SetInterfaceSafetyOptions_CallBack(LPVOID ptr)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ PRECONDITION(CheckPointer(ptr));
+ }
+ CONTRACTL_END;
+
+ SetInterfaceSafetyArgs* pArgs = (SetInterfaceSafetyArgs*)ptr;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pArgs->pUnk);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ *(pArgs->hr) = ObjectSafety_SetInterfaceSafetyOptions(pArgs->pUnk, *(pArgs->riid),
+ pArgs->dwOptionSetMask,
+ pArgs->dwEnabledOptions
+ );
+ }
+ else
+ {
+ AppDomainDoCallBack(pWrap, ObjectSafety_SetInterfaceSafetyOptions_CallBack, pArgs, pArgs->hr);
+ }
+}
+
+
+HRESULT __stdcall ObjectSafety_SetInterfaceSafetyOptions_Wrapper(IUnknown* pUnk, REFIID riid,
+ DWORD dwOptionSetMask, DWORD dwEnabledOptions)
+{
+ SetupForComCallHR();
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pUnk));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ SetInterfaceSafetyArgs args = {pUnk, &riid, dwOptionSetMask, dwEnabledOptions, &hr};
+ ObjectSafety_SetInterfaceSafetyOptions_CallBack(&args);
+ return hr;
+}
+
+//------------------------------------------------------------------------------------------
+// ICustomPropertyProvider methods for Jupiter
+
+#define APPDOMAIN_DOCALLBACK_CONTRACT \
+ CONTRACTL \
+ { \
+ NOTHROW; \
+ GC_TRIGGERS; \
+ MODE_PREEMPTIVE; \
+ PRECONDITION(CheckPointer(ptr)); \
+ } \
+ CONTRACTL_END; \
+
+
+struct ICustomPropertyProvider_GetProperty_Args
+{
+ IUnknown *pPropertyProvider;
+ HSTRING hstrName;
+ IUnknown **ppProperty;
+ HRESULT *pHR;
+};
+
+VOID __stdcall ICustomPropertyProvider_GetProperty_Callback(LPVOID ptr)
+{
+ APPDOMAIN_DOCALLBACK_CONTRACT;
+
+ ICustomPropertyProvider_GetProperty_Args* pArgs = (ICustomPropertyProvider_GetProperty_Args*)ptr;
+ *(pArgs->pHR) = ICustomPropertyProvider_GetProperty(pArgs->pPropertyProvider, pArgs->hstrName, pArgs->ppProperty);
+}
+
+HRESULT __stdcall ICustomPropertyProvider_GetProperty_Wrapper(IUnknown *pPropertyProvider, HSTRING hstrName, /* [out] */ IUnknown **ppProperty)
+{
+ SetupThreadForComCall(E_OUTOFMEMORY);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pPropertyProvider));
+ }
+ CONTRACTL_END;
+
+ if (ppProperty == NULL)
+ return E_POINTER;
+
+
+ HRESULT hr = S_OK;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pPropertyProvider);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ hr = ICustomPropertyProvider_GetProperty(pPropertyProvider, hstrName, ppProperty);
+ }
+ else
+ {
+ ICustomPropertyProvider_GetProperty_Args args = { pPropertyProvider, hstrName, ppProperty, &hr };
+ AppDomainDoCallBack(pWrap, ICustomPropertyProvider_GetProperty_Callback, &args, &hr);
+ }
+ return hr;
+}
+
+struct ICustomPropertyProvider_GetIndexedProperty_Args
+{
+ IUnknown *pPropertyProvider;
+ HSTRING hstrName;
+ TypeNameNative indexedParamType;
+ IUnknown **ppProperty;
+ HRESULT *pHR;
+};
+
+VOID __stdcall ICustomPropertyProvider_GetIndexedProperty_Callback(LPVOID ptr)
+{
+ APPDOMAIN_DOCALLBACK_CONTRACT;
+
+ ICustomPropertyProvider_GetIndexedProperty_Args* pArgs = (ICustomPropertyProvider_GetIndexedProperty_Args*)ptr;
+ *(pArgs->pHR) = ICustomPropertyProvider_GetIndexedProperty(pArgs->pPropertyProvider, pArgs->hstrName, pArgs->indexedParamType, pArgs->ppProperty);
+}
+
+HRESULT __stdcall ICustomPropertyProvider_GetIndexedProperty_Wrapper(IUnknown *pPropertyProvider,
+ HSTRING hstrName,
+ TypeNameNative indexedParamType,
+ /* [out, retval] */ IUnknown **ppProperty)
+{
+ SetupThreadForComCall(E_OUTOFMEMORY);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pPropertyProvider));
+ }
+ CONTRACTL_END;
+
+
+ HRESULT hr = S_OK;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pPropertyProvider);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ hr = ICustomPropertyProvider_GetIndexedProperty(pPropertyProvider, hstrName, indexedParamType, ppProperty);
+ }
+ else
+ {
+ ICustomPropertyProvider_GetIndexedProperty_Args args = { pPropertyProvider, hstrName, indexedParamType, ppProperty, &hr };
+ AppDomainDoCallBack(pWrap, ICustomPropertyProvider_GetIndexedProperty_Callback, &args, &hr);
+ }
+
+ return hr;
+}
+
+struct ICustomPropertyProvider_GetStringRepresentation_Args
+{
+ IUnknown *pPropertyProvider;
+ HSTRING *phstrStringRepresentation;
+ HRESULT *pHR;
+};
+
+VOID __stdcall ICustomPropertyProvider_GetStringRepresentation_Callback(LPVOID ptr)
+{
+ APPDOMAIN_DOCALLBACK_CONTRACT;
+
+ ICustomPropertyProvider_GetStringRepresentation_Args* pArgs = (ICustomPropertyProvider_GetStringRepresentation_Args*)ptr;
+ *(pArgs->pHR) = ICustomPropertyProvider_GetStringRepresentation(pArgs->pPropertyProvider, pArgs->phstrStringRepresentation);
+}
+
+HRESULT __stdcall ICustomPropertyProvider_GetStringRepresentation_Wrapper(IUnknown *pPropertyProvider,
+ /* [out, retval] */ HSTRING *phstrStringRepresentation)
+{
+ SetupThreadForComCall(E_OUTOFMEMORY);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pPropertyProvider));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pPropertyProvider);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ hr = ICustomPropertyProvider_GetStringRepresentation(pPropertyProvider, phstrStringRepresentation);
+ }
+ else
+ {
+ ICustomPropertyProvider_GetStringRepresentation_Args args = { pPropertyProvider, phstrStringRepresentation, &hr };
+ AppDomainDoCallBack(pWrap, ICustomPropertyProvider_GetStringRepresentation_Callback, &args, &hr);
+ }
+
+ return hr;
+}
+
+struct ICustomPropertyProvider_GetType_Args
+{
+ IUnknown *pPropertyProvider;
+ TypeNameNative *pTypeIdentifier;
+ HRESULT *pHR;
+};
+
+VOID __stdcall ICustomPropertyProvider_GetType_Callback(LPVOID ptr)
+{
+ APPDOMAIN_DOCALLBACK_CONTRACT;
+
+ ICustomPropertyProvider_GetType_Args* pArgs = (ICustomPropertyProvider_GetType_Args*)ptr;
+ *(pArgs->pHR) = ICustomPropertyProvider_GetType(pArgs->pPropertyProvider, pArgs->pTypeIdentifier);
+}
+
+HRESULT __stdcall ICustomPropertyProvider_GetType_Wrapper(IUnknown *pPropertyProvider,
+ /* [out, retval] */ TypeNameNative *pTypeIdentifier)
+{
+ SetupThreadForComCall(E_OUTOFMEMORY);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pPropertyProvider));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pPropertyProvider);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ hr = ICustomPropertyProvider_GetType(pPropertyProvider, pTypeIdentifier);
+ }
+ else
+ {
+ ICustomPropertyProvider_GetType_Args args = { pPropertyProvider, pTypeIdentifier, &hr };
+ AppDomainDoCallBack(pWrap, ICustomPropertyProvider_GetType_Callback, &args, &hr);
+ }
+ return hr;
+}
+
+
+struct IStringable_ToString_Args
+{
+ IUnknown *pStringable;
+ HSTRING *pResult;
+ HRESULT *pHR;
+};
+
+VOID __stdcall IStringable_ToString_Callback(LPVOID ptr)
+{
+ APPDOMAIN_DOCALLBACK_CONTRACT;
+
+ IStringable_ToString_Args* pArgs = (IStringable_ToString_Args*)ptr;
+ *(pArgs->pHR) = IStringable_ToString(pArgs->pStringable, pArgs->pResult);
+}
+
+HRESULT __stdcall IStringable_ToString_Wrapper(IUnknown *pStringable,
+ /* [out, retval] */ HSTRING *pResult)
+{
+ SetupThreadForComCall(E_OUTOFMEMORY);
+
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ SO_TOLERANT;
+ PRECONDITION(CheckPointer(pStringable));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+ ComCallWrapper* pWrap = MapIUnknownToWrapper(pStringable);
+ if (IsCurrentDomainValid(pWrap))
+ {
+ hr = IStringable_ToString(pStringable, pResult);
+ }
+ else
+ {
+ IStringable_ToString_Args args = { pStringable, pResult, &hr };
+ AppDomainDoCallBack(pWrap, IStringable_ToString_Callback, &args, &hr);
+ }
+
+ return hr;
+}
+
+
+ULONG __stdcall ICCW_AddRefFromJupiter_Wrapper(IUnknown *pUnk)
+{
+ // We do not need to hook with host here
+ SetupForComCallDWORDNoHostNotif();
+
+ WRAPPER_NO_CONTRACT;
+ STATIC_CONTRACT_SO_TOLERANT;
+
+ return ICCW_AddRefFromJupiter(pUnk);
+}
+
+ULONG __stdcall ICCW_ReleaseFromJupiter_Wrapper(IUnknown *pUnk)
+{
+ // We do not need to hook with host here
+ SetupForComCallDWORDNoHostNotif();
+
+ WRAPPER_NO_CONTRACT;
+ STATIC_CONTRACT_SO_TOLERANT;
+
+ return ICCW_ReleaseFromJupiter(pUnk);
+}
+
+HRESULT __stdcall ICCW_Peg_Wrapper(IUnknown *pUnk)
+{
+ // We do not need to hook with host here and we cannot do CanRunManagedCode check
+ // as we are most likely in the middle of a GC
+ SetupForComCallHRNoHostNotifNoCheckCanRunManagedCode();
+
+ WRAPPER_NO_CONTRACT;
+ STATIC_CONTRACT_SO_TOLERANT;
+
+ return ICCW_Peg(pUnk);
+}
+
+HRESULT __stdcall ICCW_Unpeg_Wrapper(IUnknown *pUnk)
+{
+ // We do not need to hook with host here and we cannot do CanRunManagedCode check
+ // as we are most likely in the middle of a GC
+ SetupForComCallHRNoHostNotifNoCheckCanRunManagedCode();
+
+ WRAPPER_NO_CONTRACT;
+ STATIC_CONTRACT_SO_TOLERANT;
+
+ return ICCW_Unpeg(pUnk);
+}