diff options
Diffstat (limited to 'src/vm/stdinterfaces_wrapper.cpp')
-rw-r--r-- | src/vm/stdinterfaces_wrapper.cpp | 3269 |
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); +} |