1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //---------------------------------------------------------------------------------
7 // Defines various standard com interfaces
9 //---------------------------------------------------------------------------------
15 #include <guidfromname.h>
17 #include <objsafe.h> // IID_IObjectSafety
23 #include "runtimecallablewrapper.h"
24 #include "stdinterfaces.h"
25 #include "comcallablewrapper.h"
28 #include "interoputil.h"
29 #include "comdelegate.h"
30 #include "olevariant.h"
32 #include "typehandle.h"
33 #include "posterror.h"
38 #include "interopconverter.h"
39 #include "cominterfacemarshaler.h"
40 #include "eecontract.h"
41 #include "stdinterfaces_internal.h"
42 #include <restrictederrorinfo.h> // IRestrictedErrorInfo
43 #include "winrttypenameconverter.h"
44 #include "interoputil.inl"
47 //------------------------------------------------------------------------------------------
48 // Definitions used by the IDispatchEx implementation
50 // The names of the properties that are accessed on the managed member info's
51 #define MEMBER_INFO_NAME_PROP "Name"
52 #define MEMBER_INFO_TYPE_PROP "MemberType"
53 #define PROPERTY_INFO_CAN_READ_PROP "CanRead"
54 #define PROPERTY_INFO_CAN_WRITE_PROP "CanWrite"
57 // {00020430-0000-0000-C000-000000000046}
58 static const GUID LIBID_STDOLE2 = { 0x00020430, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
60 // The uuid.lib doesn't have IID_IRestrictedErrorInfo in their lib. Remove this once it is included in the lib
61 static const GUID IID_IRestrictedErrorInfo = { 0x82BA7092, 0x4C88, 0x427D, { 0xA7, 0xBC, 0x16, 0xDD, 0x93, 0xFE, 0xB6, 0x7E } };
62 EXTERN_C SELECTANY const IID IID_ILanguageExceptionErrorInfo = { 0x04a2dbf3, 0xdf83, 0x116c, { 0x09, 0x46, 0x08, 0x12, 0xab, 0xf6, 0xe0, 0x7d } };
64 // Until the Windows SDK is updated, just hard-code the IAgileObject IID
65 #ifndef __IAgileObject_INTERFACE_DEFINED__
66 EXTERN_C SELECTANY const GUID IID_IAgileObject = { 0x94ea2b94, 0xe9cc, 0x49e0, { 0xc0, 0xff, 0xee, 0x64, 0xca, 0x8f, 0x5b, 0x90 } };
67 #endif // !__IAgileObject_INTERFACE_DEFINED__
69 // Until the Windows SDK is updated, just hard-code the INoMarshal IID
70 #ifndef __INoMarshal_INTERFACE_DEFINED__
71 static const GUID IID_INoMarshal = {0xecc8691b, 0xc1db, 0x4dc0, { 0x85, 0x5e, 0x65, 0xf6, 0xc5, 0x51, 0xaf, 0x49 } };
72 #endif // !__INoMarshal_INTERFACE_DEFINED__
74 // NOTE: In the following vtables, QI points to the same function
75 // this is because, during marshalling between COM & COM+ we want a fast way to
76 // check if a COM IP is a tear-off that we created.
78 // array of vtable pointers for std. interfaces such as IProvideClassInfo etc.
79 const SLOT * const g_rgStdVtables[] =
81 (SLOT*)&g_InnerUnknown.m_vtable,
82 (SLOT*)&g_IProvideClassInfo.m_vtable,
83 (SLOT*)&g_IMarshal.m_vtable,
84 (SLOT*)&g_ISupportsErrorInfo.m_vtable,
85 (SLOT*)&g_IErrorInfo.m_vtable,
86 (SLOT*)&g_IConnectionPointContainer.m_vtable,
87 (SLOT*)&g_IObjectSafety.m_vtable,
88 (SLOT*)&g_IDispatchEx.m_vtable,
89 (SLOT*)&g_IWeakReferenceSource.m_vtable,
90 (SLOT*)&g_ICustomPropertyProvider.m_vtable,
91 (SLOT*)&g_ICCW.m_vtable,
92 (SLOT*)&g_IAgileObject.m_vtable,
93 (SLOT*)&g_IStringable.m_vtable
97 const IID IID_IWeakReferenceSource = __uuidof(IWeakReferenceSource);
98 const IID IID_IWeakReference = __uuidof(IWeakReference);
100 // {7C925755-3E48-42B4-8677-76372267033F}
101 const IID IID_ICustomPropertyProvider = {0x7C925755,0x3E48,0x42B4,{0x86, 0x77, 0x76, 0x37, 0x22, 0x67, 0x03, 0x3F}};
103 const IID IID_IStringable = {0x96369f54,0x8eb6,0x48f0, {0xab,0xce,0xc1,0xb2,0x11,0xe6,0x27,0xc3}};
105 // For free-threaded marshaling, we must not be spoofed by out-of-process or cross-runtime marshal data.
106 // Only unmarshal data that comes from our own runtime.
107 BYTE g_UnmarshalSecret[sizeof(GUID)];
108 bool g_fInitedUnmarshalSecret = false;
111 static HRESULT InitUnmarshalSecret()
123 if (!g_fInitedUnmarshalSecret)
125 ComCall::LockHolder lh;
127 if (!g_fInitedUnmarshalSecret)
129 hr = ::CoCreateGuid((GUID *) g_UnmarshalSecret);
131 g_fInitedUnmarshalSecret = true;
137 //------------------------------------------------------------------------------------------
138 // IUnknown methods for CLR objects
142 Unknown_QueryInterface_Internal(ComCallWrapper* pWrap, IUnknown* pUnk, REFIID riid, void** ppv)
149 PRECONDITION(CheckPointer(pUnk));
150 PRECONDITION(IsInProcCCWTearOff(pUnk));
151 PRECONDITION(CheckPointer(ppv, NULL_OK));
152 PRECONDITION(CheckPointer(pWrap));
157 SafeComHolderPreemp<IUnknown> pDestItf = NULL;
159 // Validate the arguments.
163 // Initialize the returned interface pointer to NULL before we start.
166 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
168 // Initialize the HRESULT to E_NOINTERFACE. This must be done after the
169 // BEGIN_EXTERNAL_ENTRYPOINT since otherwise it will be reset to S_OK by
170 // BEGIN_EXTERNAL_ENTRYPOINT.
173 // Check for QIs on inner unknown
174 if (!IsInnerUnknown(pUnk))
176 // Aggregation support, delegate to the outer unknown if non null.
177 IUnknown *pOuter = pWrap->GetSimpleWrapper()->GetOuter();
180 hr = SafeQueryInterfacePreemp(pOuter, riid, &pDestItf);
181 LogInteropQI(pOuter, riid, hr, "QI to outer Unknown");
187 // Assert the component has been aggregated
188 _ASSERTE(pWrap->GetSimpleWrapper()->GetOuter() != NULL);
190 // Okay special case IUnknown
191 if (IsEqualIID(riid, IID_IUnknown))
193 SafeAddRefPreemp(pUnk);
198 // If we haven't found the IP or if we haven't looked yet (because we aren't
199 // being aggregated), now look on the managed object to see if it supports the interface.
200 if (pDestItf == NULL)
204 pDestItf = ComCallWrapper::GetComIPFromCCW(pWrap, riid, NULL, GetComIPFromCCW::CheckVisibility);
208 Exception *e = GET_EXCEPTION();
211 EX_END_CATCH(RethrowTerminalExceptions)
215 // If we succeeded in obtaining the requested IP then return S_OK.
216 if (pDestItf != NULL)
219 END_EXTERNAL_ENTRYPOINT;
223 // If we succeeded in obtaining the requested IP, set ppv to the interface.
224 _ASSERTE(pDestItf != NULL);
226 pDestItf.SuppressRelease();
230 } // Unknown_QueryInterface_Internal
234 Unknown_AddRefInner_Internal(IUnknown* pUnk)
241 PRECONDITION(CheckPointer(pUnk));
245 SimpleComCallWrapper* pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
246 ComCallWrapper* pWrap = pSimpleWrap->GetMainWrapper();
248 // Assert the component has been aggregated
249 _ASSERTE(pSimpleWrap->GetOuter() != NULL);
251 // We are guaranteed to be in the right domain here, so can always get the oref
252 // w/o fear of the handle having been deleted.
253 return pWrap->AddRef();
258 Unknown_AddRef_Internal(IUnknown* pUnk)
265 PRECONDITION(CheckPointer(pUnk));
269 ComCallWrapper* pWrap = ComCallWrapper::GetWrapperFromIP(pUnk);
271 // check for aggregation
273 SimpleComCallWrapper* pSimpleWrap = pWrap->GetSimpleWrapper();
274 if (pSimpleWrap && (pOuter = pSimpleWrap->GetOuter()) != NULL)
276 // If we are in process detach, we cannot safely call release on our outer.
277 if (g_fProcessDetach)
280 ULONG cbRef = pOuter->AddRef();
281 LogInteropAddRef(pOuter, cbRef, "Delegate to outer");
284 // are guaranteed to be in the right domain here, so can always get the oref
285 // w/o fear of the handle having been deleted.
286 return pWrap->AddRef();
291 Unknown_ReleaseInner_Internal(IUnknown* pUnk)
298 PRECONDITION(CheckPointer(pUnk));
305 SimpleComCallWrapper* pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
306 ComCallWrapper* pWrap = pSimpleWrap->GetMainWrapper();
308 // Assert the component has been aggregated
309 _ASSERTE(pSimpleWrap->GetOuter() != NULL);
311 // We know for sure this wrapper is a start wrapper let us pass this information in
312 cbRef = pWrap->Release();
318 Unknown_Release_Internal(IUnknown* pUnk)
325 PRECONDITION(CheckPointer(pUnk));
332 // check for aggregation
333 ComCallWrapper* pWrap = ComCallWrapper::GetWrapperFromIP(pUnk);
334 SimpleComCallWrapper* pSimpleWrap = pWrap->GetSimpleWrapper();
336 if (pSimpleWrap && (pOuter = pSimpleWrap->GetOuter()) != NULL)
338 // If we are in process detach, we cannot safely call release on our outer.
339 if (g_fProcessDetach)
342 cbRef = SafeReleasePreemp(pOuter);
343 LogInteropRelease(pOuter, cbRef, "Delegate Release to outer");
347 cbRef = pWrap->Release();
354 // ---------------------------------------------------------------------------
355 // for simple tearoffs
356 // ---------------------------------------------------------------------------
358 Unknown_AddRefSpecial_Internal(IUnknown* pUnk)
365 PRECONDITION(CheckPointer(pUnk));
366 PRECONDITION(IsSimpleTearOff(pUnk));
370 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
371 return pSimpleWrap->AddRefWithAggregationCheck();
372 } // Unknown_AddRefSpecial
374 // ---------------------------------------------------------------------------
375 // for simplecomcall wrappers, stdinterfaces such as IProvideClassInfo etc.
376 // ---------------------------------------------------------------------------
378 Unknown_ReleaseSpecial_Internal(IUnknown* pUnk)
385 PRECONDITION(CheckPointer(pUnk));
386 PRECONDITION(IsSimpleTearOff(pUnk));
393 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
396 IUnknown *pOuter = pSimpleWrap->GetOuter();
399 cbRef = SafeReleasePreemp(pOuter);
403 cbRef = pSimpleWrap->Release();
411 Unknown_QueryInterface_IErrorInfo_Simple(IUnknown* pUnk, REFIID riid, void** ppv)
418 PRECONDITION(CheckPointer(pUnk));
419 PRECONDITION(IsInProcCCWTearOff(pUnk));
420 PRECONDITION(CheckPointer(ppv, NULL_OK));
434 _ASSERTE(!IsInnerUnknown(pUnk) && IsSimpleTearOff(pUnk));
436 SimpleComCallWrapper* pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
438 // we must not switch to cooperative GC mode here, so respond only to the
439 // two interfaces we always support
440 if (riid == IID_IUnknown || riid == IID_IErrorInfo)
443 pSimpleWrap->AddRef();
447 EX_CATCH_HRESULT_NO_ERRORINFO(hr);
450 } // Unknown_QueryInterface_IErrorInfo_Simple
452 // ---------------------------------------------------------------------------
454 Unknown_ReleaseSpecial_IErrorInfo_Internal(IUnknown* pUnk)
461 PRECONDITION(CheckPointer(pUnk));
462 PRECONDITION(IsSimpleTearOff(pUnk));
469 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
470 cbRef = pSimpleWrap->Release();
472 EX_END_CATCH(SwallowAllExceptions)
478 // ---------------------------------------------------------------------------
479 // Interface IProvideClassInfo
480 // ---------------------------------------------------------------------------
482 ClassInfo_GetClassInfo(IUnknown* pUnk, ITypeInfo** ppTI)
489 PRECONDITION(CheckPointer(pUnk));
490 PRECONDITION(CheckPointer(ppTI));
496 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
498 _ASSERTE(IsSimpleTearOff(pUnk));
500 SimpleComCallWrapper *pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
502 // If this is an extensible RCW then we need to check to see if the CLR part of the
503 // herarchy is visible to COM.
504 if (pWrap->IsExtendsCOMObject())
506 // Retrieve the wrapper template for the class.
507 ComCallWrapperTemplate *pTemplate = ComCallWrapperTemplate::GetTemplate(pWrap->GetMethodTable());
509 // Find the first COM visible IClassX starting at ComMethodTable passed in and
510 // walking up the hierarchy.
511 ComMethodTable *pComMT = NULL;
512 if (pTemplate->SupportsIClassX())
514 for (pComMT = pTemplate->GetClassComMT(); pComMT && !pComMT->IsComVisible(); pComMT = pComMT->GetParentClassComMT());
517 // If the CLR part of the object is not visible then delegate the call to the
518 // base COM object if it implements IProvideClassInfo.
519 if (!pComMT || pComMT->GetMethodTable()->ParentEquals(g_pObjectClass))
521 IProvideClassInfo *pProvClassInfo = NULL;
523 SyncBlock* pBlock = pWrap->GetSyncBlock();
526 RCWHolder pRCW(GetThread());
527 RCWPROTECT_BEGIN(pRCW, pBlock);
529 hr = pRCW->SafeQueryInterfaceRemoteAware(IID_IProvideClassInfo, (IUnknown**)&pProvClassInfo);
532 hr = pProvClassInfo->GetClassInfo(ppTI);
533 ULONG cbRef = SafeRelease(pProvClassInfo);
534 LogInteropRelease(pProvClassInfo, cbRef, "ClassInfo_GetClassInfo");
538 RCWPROTECT_END(pRCW);
542 MethodTable* pClass = pWrap->GetMethodTable();
543 IfFailThrow(GetITypeInfoForEEClass(pClass, ppTI, true /* bClassInfo */));
545 END_EXTERNAL_ENTRYPOINT;
550 //------------------------------------------------------------------------------------------
551 HRESULT GetDefaultInterfaceForCoclass(ITypeInfo *pTI, ITypeInfo **ppTIDef)
558 PRECONDITION(CheckPointer(pTI));
559 PRECONDITION(CheckPointer(ppTIDef));
564 TYPEATTRHolder pAttr(pTI); // Attributes on the first TypeInfo.
566 IfFailRet(pTI->GetTypeAttr(&pAttr));
567 if (pAttr->typekind != TKIND_COCLASS)
568 return TYPE_E_ELEMENTNOTFOUND;
572 // If no impltype has the default flag, use 0.
573 int defaultInterface = 0;
574 for (int i = 0; i < pAttr->cImplTypes; ++i)
576 IfFailRet(pTI->GetImplTypeFlags(i, &flags));
577 if (flags & IMPLTYPEFLAG_FDEFAULT)
579 defaultInterface = i;
585 IfFailRet(pTI->GetRefTypeOfImplType(defaultInterface, &href));
586 IfFailRet(pTI->GetRefTypeInfo(href, ppTIDef));
589 } // HRESULT GetDefaultInterfaceForCoclass()
591 //------------------------------------------------------------------------------------------
592 // Helper to get the ITypeLib* for a Assembly.
593 HRESULT GetITypeLibForAssembly(_In_ Assembly *pAssembly, _Outptr_ ITypeLib **ppTlb)
600 PRECONDITION(CheckPointer(pAssembly));
601 PRECONDITION(CheckPointer(ppTlb));
605 // If the module wasn't imported from COM, fail. In .NET Framework the runtime
606 // would generate a ITypeLib instance, but .NET Core doesn't support that.
607 if (!pAssembly->IsImportedFromTypeLib())
608 return COR_E_NOTSUPPORTED;
612 // Check for cached copy.
613 ITypeLib *pTlb = pAssembly->GetTypeLib();
616 // If the cached value is the invalid sentinal, an attempt was already made but failed.
617 if (pTlb == Assembly::InvalidTypeLib)
618 return TLBX_E_LIBNOTREGISTERED;
624 // Retrieve the guid for the assembly.
626 IfFailRet(GetTypeLibGuidForAssembly(pAssembly, &assemblyGuid));
628 // Retrieve the major and minor version number.
631 IfFailRet(GetTypeLibVersionForAssembly(pAssembly, &wMajor, &wMinor));
633 // Attempt to load the exact TypeLib
634 hr = LoadRegTypeLib(assemblyGuid, wMajor, wMinor, &pTlb);
637 // Try just the Assembly version
638 IfFailRet(pAssembly->GetVersion(&wMajor, &wMinor, nullptr, nullptr));
639 hr = LoadRegTypeLib(assemblyGuid, wMajor, wMinor, &pTlb);
642 // Try loading the highest registered version.
643 hr = LoadRegTypeLib(assemblyGuid, -1, -1, &pTlb);
645 pTlb = Assembly::InvalidTypeLib;
649 bool setCache = pAssembly->TrySetTypeLib(pTlb);
652 // Release the TypeLib that isn't going to be used
653 if (pTlb != Assembly::InvalidTypeLib)
656 // This call lost the race to set the TypeLib so recusively call
657 // this function again to get the one that is set.
658 return GetITypeLibForAssembly(pAssembly, ppTlb);
663 // Pass the HRESULT on if it is any error other than "TypeLib not registered".
664 return (hr == TYPE_E_LIBNOTREGISTERED) ? TLBX_E_LIBNOTREGISTERED : hr;
669 } // HRESULT GetITypeLibForAssembly()
671 HRESULT GetITypeInfoForEEClass(MethodTable *pClass, ITypeInfo **ppTI, bool bClassInfo)
678 INJECT_FAULT(return E_OUTOFMEMORY);
684 ComMethodTable *pComMT = NULL;
686 SafeComHolder<ITypeLib> pITLB = NULL;
687 SafeComHolder<ITypeInfo> pTI = NULL;
688 SafeComHolder<ITypeInfo> pTIDef = NULL; // Default typeinfo of a coclass.
689 ComCallWrapperTemplate *pTemplate = NULL;
691 if (pClass->IsProjectedFromWinRT() || pClass->IsExportedToWinRT())
693 // ITypeInfo is not used in the WinRT world
700 if (bClassInfo || pClass->IsInterface() || pClass->IsValueType() || pClass->IsEnum())
702 // If the class is not an interface then find the first COM visible IClassX in the hierarchy.
703 if (!pClass->IsInterface() && !pClass->IsComImport())
706 // Retrieve the ComCallWrapperTemplate from the type.
708 OBJECTREF pThrowable = NULL;
709 GCPROTECT_BEGIN(pThrowable);
713 pTemplate = ComCallWrapperTemplate::GetTemplate(pClass);
714 if (pTemplate->SupportsIClassX())
716 // Find the first COM visible IClassX starting at ComMethodTable passed in and
717 // walking up the hierarchy.
718 pComMT = pTemplate->GetClassComMT();
719 while (pComMT && !pComMT->IsComVisible())
720 pComMT = pComMT->GetParentClassComMT();
725 pThrowable = GET_THROWABLE();
727 EX_END_CATCH(SwallowAllExceptions);
729 if (pThrowable != NULL)
730 hr = SetupErrorInfo(pThrowable);
744 // If we haven't managed to find any visible IClassX's then return TYPE_E_ELEMENTNOTFOUND.
747 hr = TYPE_E_ELEMENTNOTFOUND;
751 // Use the type of the first visible IClassX.
752 pClass = pComMT->GetMethodTable();
755 // Retrieve the ITypeLib for the assembly containing the type.
756 IfFailGo(GetITypeLibForAssembly(pClass->GetAssembly(), &pITLB));
758 // Get the GUID of the desired TypeRef.
759 IfFailGo(pClass->GetGuidNoThrow(&clsid, TRUE));
761 // Retrieve the ITypeInfo from the ITypeLib.
762 IfFailGo(pITLB->GetTypeInfoOfGuid(clsid, ppTI));
764 else if (pClass->IsComImport())
766 // This is a COM imported class, with no IClassX. Get default interface.
767 IfFailGo(GetITypeLibForAssembly(pClass->GetAssembly(), &pITLB));
768 IfFailGo(pClass->GetGuidNoThrow(&clsid, TRUE));
769 IfFailGo(pITLB->GetTypeInfoOfGuid(clsid, &pTI));
770 IfFailGo(GetDefaultInterfaceForCoclass(pTI, &pTIDef));
773 pTIDef.SuppressRelease();
777 // We are attempting to retrieve an ITypeInfo for the default interface on a class.
778 TypeHandle hndDefItfClass;
779 DefaultInterfaceType DefItfType;
780 IfFailGo(TryGetDefaultInterfaceForClass(TypeHandle(pClass), &hndDefItfClass, &DefItfType));
783 case DefaultInterfaceType_Explicit:
785 _ASSERTE(!hndDefItfClass.IsNull());
786 _ASSERTE(hndDefItfClass.IsInterface());
787 hr = GetITypeInfoForEEClass(hndDefItfClass.GetMethodTable(), ppTI, false /* bClassInfo */);
791 case DefaultInterfaceType_AutoDispatch:
792 case DefaultInterfaceType_AutoDual:
794 _ASSERTE(!hndDefItfClass.IsNull());
795 _ASSERTE(!hndDefItfClass.IsInterface());
797 PTR_MethodTable itfClassMT = hndDefItfClass.GetMethodTable();
799 // Retrieve the ITypeLib for the assembly containing the type.
800 IfFailGo(GetITypeLibForAssembly(itfClassMT->GetAssembly(), &pITLB));
802 // Get the GUID of the desired TypeRef.
803 IfFailGo(itfClassMT->GetGuidNoThrow(&clsid, TRUE));
805 // Generate the IClassX IID from the class.
806 TryGenerateClassItfGuid(hndDefItfClass, &ciid);
808 hr = pITLB->GetTypeInfoOfGuid(ciid, ppTI);
812 case DefaultInterfaceType_IUnknown:
813 case DefaultInterfaceType_BaseComClass:
815 // @PERF: Optimize this.
816 IfFailGo(LoadRegTypeLib(LIBID_STDOLE2, -1, -1, 0, &pITLB));
817 IfFailGo(pITLB->GetTypeInfoOfGuid(IID_IUnknown, ppTI));
824 _ASSERTE(!"Invalid default interface type!");
840 } // HRESULT GetITypeInfoForEEClass()
842 // Returns a NON-ADDREF'd ITypeInfo.
843 HRESULT GetITypeInfoForMT(ComMethodTable *pMT, ITypeInfo **ppTI)
850 PRECONDITION(CheckPointer(pMT));
851 PRECONDITION(CheckPointer(ppTI));
855 HRESULT hr = S_OK; // A result.
856 ITypeInfo *pTI; // The ITypeInfo.
858 pTI = pMT->GetITypeInfo();
862 MethodTable *pClass = pMT->GetMethodTable();
864 hr = GetITypeInfoForEEClass(pClass, &pTI);
868 pMT->SetITypeInfo(pTI);
869 SafeReleasePreemp(pTI);
877 //------------------------------------------------------------------------------------------
878 // helper function to locate error info (if any) after a call, and make sure
879 // that the error info comes from that call
881 IErrorInfo *GetSupportedErrorInfo(IUnknown *iface, REFIID riid, BOOL checkForIRestrictedErrInfo)
888 INJECT_FAULT(COMPlusThrowOM());
889 PRECONDITION(CheckPointer(iface));
893 IErrorInfo *pRetErrorInfo = NULL;
894 BOOL bUseThisErrorInfo = FALSE;
896 // This function must run in preemptive GC mode.
900 SafeComHolderPreemp<IErrorInfo> pErrorInfo;
902 // See if we have any error info. (Also this clears out the error info,
903 // we want to do this whether it is a recent error or not.)
904 hr = SafeGetErrorInfo(&pErrorInfo);
907 // If we successfully retrieved an IErrorInfo, we need to verify if
908 // it is for the specifed interface.
911 // Make sure that the object we called follows the error info protocol,
912 // otherwise the error may be stale, so we just throw it away.
913 SafeComHolderPreemp<ISupportErrorInfo> pSupport;
914 hr = SafeQueryInterfacePreemp(iface, IID_ISupportErrorInfo, (IUnknown **) &pSupport);
915 LogInteropQI(iface, IID_ISupportErrorInfo, hr, "ISupportErrorInfo");
918 hr = pSupport->InterfaceSupportsErrorInfo(riid);
921 // The IErrorInfo is indeed for the specified interface so return it.
922 bUseThisErrorInfo = TRUE;
927 if (!bUseThisErrorInfo && pErrorInfo != NULL && checkForIRestrictedErrInfo)
930 // Do we support IRestrictedErrorInfo?
931 SafeComHolderPreemp<IRestrictedErrorInfo> pRestrictedErrorInfo;
932 hr = SafeQueryInterfacePreemp(pErrorInfo, IID_IRestrictedErrorInfo, (IUnknown **) &pRestrictedErrorInfo);
933 LogInteropQI(pErrorInfo, IID_IRestrictedErrorInfo, hr, "IRestrictedErrorInfo");
937 // This is a WinRT IRestrictedErrorInfo scenario
938 bUseThisErrorInfo = TRUE;
942 if (bUseThisErrorInfo)
944 pRetErrorInfo = pErrorInfo;
945 pErrorInfo.SuppressRelease();
950 return pRetErrorInfo;
953 // ---------------------------------------------------------------------------
954 // Interface ISupportsErrorInfo
955 /// ---------------------------------------------------------------------------
957 SupportsErroInfo_IntfSupportsErrorInfo(IUnknown* pUnk, REFIID riid)
964 PRECONDITION(CheckPointer(pUnk));
965 PRECONDITION(IsSimpleTearOff(pUnk));
969 // All interfaces support ErrorInfo
974 // ---------------------------------------------------------------------------
975 // Interface IErrorInfo
976 // %%Function: ErrorInfo_GetDescription
977 // ---------------------------------------------------------------------------
979 ErrorInfo_GetDescription(IUnknown* pUnk, BSTR* pbstrDescription)
986 PRECONDITION(CheckPointer(pUnk));
987 PRECONDITION(IsSimpleTearOff(pUnk));
988 PRECONDITION(CheckPointer(pbstrDescription, NULL_OK));
993 SimpleComCallWrapper *pWrap = NULL;
995 if (pbstrDescription == NULL)
998 pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
1000 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1002 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1004 *pbstrDescription = pWrap->IErrorInfo_bstrDescription();
1006 END_EXTERNAL_ENTRYPOINT;
1012 // ---------------------------------------------------------------------------
1013 // Interface IErrorInfo
1014 // %%Function: ErrorInfo_GetGUID
1015 // ---------------------------------------------------------------------------
1016 HRESULT __stdcall ErrorInfo_GetGUID(IUnknown* pUnk, GUID* pguid)
1023 PRECONDITION(CheckPointer(pUnk));
1024 PRECONDITION(IsSimpleTearOff(pUnk));
1025 PRECONDITION(CheckPointer(pguid, NULL_OK));
1030 SimpleComCallWrapper *pWrap = NULL;
1035 pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
1037 *pguid = pWrap->IErrorInfo_guid();
1042 // ---------------------------------------------------------------------------
1043 // Interface IErrorInfo
1044 // %%Function: ErrorInfo_GetHelpContext
1045 // ---------------------------------------------------------------------------
1046 HRESULT _stdcall ErrorInfo_GetHelpContext(IUnknown* pUnk, DWORD* pdwHelpCtxt)
1053 PRECONDITION(CheckPointer(pUnk));
1054 PRECONDITION(IsSimpleTearOff(pUnk));
1055 PRECONDITION(CheckPointer(pdwHelpCtxt, NULL_OK));
1060 SimpleComCallWrapper *pWrap = NULL;
1062 if (pdwHelpCtxt == NULL)
1065 pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
1067 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1069 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1071 *pdwHelpCtxt = pWrap->IErrorInfo_dwHelpContext();
1073 END_EXTERNAL_ENTRYPOINT;
1078 // ---------------------------------------------------------------------------
1079 // Interface IErrorInfo
1080 // %%Function: ErrorInfo_GetHelpFile
1081 // ---------------------------------------------------------------------------
1082 HRESULT __stdcall ErrorInfo_GetHelpFile(IUnknown* pUnk, BSTR* pbstrHelpFile)
1089 PRECONDITION(CheckPointer(pUnk));
1090 PRECONDITION(IsSimpleTearOff(pUnk));
1091 PRECONDITION(CheckPointer(pbstrHelpFile, NULL_OK));
1096 SimpleComCallWrapper *pWrap = NULL;
1098 if (pbstrHelpFile == NULL)
1101 pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
1103 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1105 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1107 *pbstrHelpFile = pWrap->IErrorInfo_bstrHelpFile();
1109 END_EXTERNAL_ENTRYPOINT;
1114 // ---------------------------------------------------------------------------
1115 // Interface IErrorInfo
1116 // %%Function: ErrorInfo_GetSource
1117 // ---------------------------------------------------------------------------
1118 HRESULT __stdcall ErrorInfo_GetSource(IUnknown* pUnk, BSTR* pbstrSource)
1125 PRECONDITION(CheckPointer(pUnk));
1126 PRECONDITION(IsSimpleTearOff(pUnk));
1127 PRECONDITION(CheckPointer(pbstrSource, NULL_OK));
1132 SimpleComCallWrapper *pWrap = NULL;
1134 if (pbstrSource == NULL)
1137 pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
1139 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1141 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1143 *pbstrSource = pWrap->IErrorInfo_bstrSource();
1145 END_EXTERNAL_ENTRYPOINT;
1151 //------------------------------------------------------------------------------------------
1152 // IDispatch methods that forward to the right implementation based on the flags set
1153 // on the IClassX COM method table.
1156 Dispatch_GetTypeInfoCount(IDispatch* pDisp, unsigned int *pctinfo)
1163 PRECONDITION(CheckPointer(pDisp));
1164 PRECONDITION(IsInProcCCWTearOff(pDisp));
1165 PRECONDITION(CheckPointer(pctinfo, NULL_OK));
1174 ComMethodTable *pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1175 if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1176 if (pCMT->HasInvisibleParent())
1180 HRESULT hr = GetITypeInfoForMT(pCMT, &pTI);
1192 Dispatch_GetTypeInfo(IDispatch* pDisp, unsigned int itinfo, LCID lcid, ITypeInfo **pptinfo)
1199 PRECONDITION(CheckPointer(pDisp));
1200 PRECONDITION(IsInProcCCWTearOff(pDisp));
1201 PRECONDITION(CheckPointer(pptinfo, NULL_OK));
1210 ComMethodTable *pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1211 if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1212 if (pCMT->HasInvisibleParent())
1217 return DISP_E_BADINDEX;
1220 HRESULT hr = GetITypeInfoForMT(pCMT, pptinfo);
1223 // GetITypeInfoForMT() can return other success codes besides S_OK so
1224 // we need to convert them to S_OK.
1226 SafeAddRefPreemp(*pptinfo);
1233 Dispatch_GetIDsOfNames(IDispatch* pDisp, REFIID riid, __in_ecount(cNames) OLECHAR **rgszNames, unsigned int cNames, LCID lcid, DISPID *rgdispid)
1240 INJECT_FAULT(return E_OUTOFMEMORY);
1241 PRECONDITION(CheckPointer(pDisp));
1242 PRECONDITION(IsInProcCCWTearOff(pDisp));
1243 PRECONDITION(CheckPointer(rgszNames, NULL_OK));
1247 // Get the CMT that matches the interface passed in.
1248 ComMethodTable *pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1249 if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1250 if (pCMT->HasInvisibleParent())
1253 ComCallWrapperTemplate *pTemplate = MapIUnknownToWrapper(pDisp)->GetComCallWrapperTemplate();
1254 if (pTemplate->IsUseOleAutDispatchImpl())
1256 return OleAutDispatchImpl_GetIDsOfNames(pDisp, riid, rgszNames, cNames, lcid, rgdispid);
1259 return InternalDispatchImpl_GetIDsOfNames(pDisp, riid, rgszNames, cNames, lcid, rgdispid);
1266 DISPID dispidMember,
1269 unsigned short wFlags,
1270 DISPPARAMS *pdispparams,
1271 VARIANT *pvarResult,
1272 EXCEPINFO *pexcepinfo,
1273 unsigned int *puArgErr
1278 THROWS; // InternalDispatchImpl_Invoke can throw if it encounters CE
1281 INJECT_FAULT(return E_OUTOFMEMORY);
1282 PRECONDITION(CheckPointer(pDisp));
1283 PRECONDITION(IsInProcCCWTearOff(pDisp));
1287 // Get the CMT that matches the interface passed in.
1288 ComMethodTable *pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1289 if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1290 if (pCMT->HasInvisibleParent())
1293 ComCallWrapperTemplate *pTemplate = MapIUnknownToWrapper(pDisp)->GetComCallWrapperTemplate();
1294 if (pTemplate->IsUseOleAutDispatchImpl())
1296 return OleAutDispatchImpl_Invoke(pDisp, dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
1299 return InternalDispatchImpl_Invoke(pDisp, dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
1303 //------------------------------------------------------------------------------------------
1304 // IDispatch methods for COM+ objects implemented internally using reflection.
1308 OleAutDispatchImpl_GetIDsOfNames
1312 __in_ecount(cNames) OLECHAR **rgszNames,
1313 unsigned int cNames,
1323 INJECT_FAULT(return E_OUTOFMEMORY);
1324 PRECONDITION(CheckPointer(pDisp));
1325 PRECONDITION(IsInProcCCWTearOff(pDisp));
1326 PRECONDITION(CheckPointer(rgszNames));
1330 // Make sure that riid is IID_NULL.
1331 if (riid != IID_NULL)
1332 return DISP_E_UNKNOWNINTERFACE;
1334 // Retrieve the COM method table from the IP.
1335 ComMethodTable *pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1336 if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1337 if (pCMT->HasInvisibleParent())
1341 HRESULT hr = GetITypeInfoForMT(pCMT, &pTI);
1345 hr = pTI->GetIDsOfNames(rgszNames, cNames, rgdispid);
1350 OleAutDispatchImpl_Invoke
1353 DISPID dispidMember,
1356 unsigned short wFlags,
1357 DISPPARAMS *pdispparams,
1358 VARIANT *pvarResult,
1359 EXCEPINFO *pexcepinfo,
1360 unsigned int *puArgErr
1368 PRECONDITION(CheckPointer(pDisp));
1369 PRECONDITION(IsInProcCCWTearOff(pDisp));
1375 // Make sure that riid is IID_NULL.
1376 if (riid != IID_NULL)
1377 return DISP_E_UNKNOWNINTERFACE;
1379 // Retrieve the COM method table from the IP.
1380 ComMethodTable *pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1381 if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1382 if (pCMT->HasInvisibleParent())
1386 hr = GetITypeInfoForMT(pCMT, &pTI);
1392 // If we have a basic or IClassX interface then we're going to invoke through
1393 // the class interface.
1394 if (pCMT->IsIClassXOrBasicItf())
1396 CCWHolder pCCW = ComCallWrapper::GetWrapperFromIP(pDisp);
1397 pDisp = (IDispatch*)pCCW->GetIClassXIP();
1400 hr = pTI->Invoke(pDisp, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
1404 hr = GET_EXCEPTION()->GetHR();
1406 EX_END_CATCH(SwallowAllExceptions);
1412 InternalDispatchImpl_GetIDsOfNames (
1415 __in_ecount(cNames) OLECHAR **rgszNames,
1416 unsigned int cNames,
1425 PRECONDITION(CheckPointer(pDisp));
1426 PRECONDITION(IsInProcCCWTearOff(pDisp));
1431 DispatchInfo *pDispInfo;
1432 SimpleComCallWrapper *pSimpleWrap;
1434 // Validate the arguments.
1438 if (riid != IID_NULL)
1439 return DISP_E_UNKNOWNINTERFACE;
1443 else if (!rgszNames)
1446 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1448 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1450 // This call is coming thru an interface that inherits from IDispatch.
1451 ComCallWrapper* pCCW = ComCallWrapper::GetStartWrapperFromIP(pDisp);
1453 ComMethodTable* pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1454 if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1455 pCMT->CheckParentComVisibility(FALSE);
1457 pSimpleWrap = pCCW->GetSimpleWrapper();
1458 pDispInfo = ComMethodTable::ComMethodTableFromIP(pDisp)->GetDispatchInfo();
1460 // Attempt to find the member in the DispatchEx information.
1461 SString sName(rgszNames[0]);
1462 DispatchMemberInfo *pDispMemberInfo = pDispInfo->FindMember(sName, FALSE);
1464 // Check to see if the member has been found.
1465 if (pDispMemberInfo)
1467 // Get the DISPID of the member.
1468 rgdispid[0] = pDispMemberInfo->m_DispID;
1470 // Get the ID's of the named arguments.
1472 hr = pDispMemberInfo->GetIDsOfParameters(rgszNames + 1, cNames - 1, rgdispid + 1, FALSE);
1476 rgdispid[0] = DISPID_UNKNOWN;
1477 hr = DISP_E_UNKNOWNNAME;
1480 END_EXTERNAL_ENTRYPOINT;
1487 InternalDispatchImpl_Invoke
1490 DISPID dispidMember,
1493 unsigned short wFlags,
1494 DISPPARAMS *pdispparams,
1495 VARIANT *pvarResult,
1496 EXCEPINFO *pexcepinfo,
1497 unsigned int *puArgErr
1505 PRECONDITION(CheckPointer(pDisp));
1506 PRECONDITION(IsInProcCCWTearOff(pDisp));
1510 DispatchInfo *pDispInfo;
1511 SimpleComCallWrapper *pSimpleWrap;
1514 // Check for valid input args that are not covered by DispatchInfo::InvokeMember.
1515 if (riid != IID_NULL)
1516 return DISP_E_UNKNOWNINTERFACE;
1518 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1520 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1522 // This call is coming thru an interface that inherits form IDispatch.
1523 ComCallWrapper* pCCW = ComCallWrapper::GetStartWrapperFromIP(pDisp);
1525 ComMethodTable* pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1526 if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1527 pCMT->CheckParentComVisibility(FALSE);
1529 pSimpleWrap = pCCW->GetSimpleWrapper();
1531 // Invoke the member.
1532 pDispInfo = ComMethodTable::ComMethodTableFromIP(pDisp)->GetDispatchInfo();
1533 hr = pDispInfo->InvokeMember(pSimpleWrap, dispidMember, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, NULL, puArgErr);
1536 END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS; // This will ensure that entry points wont swallow CE and continue to let them propagate out.
1542 //------------------------------------------------------------------------------------------
1543 // IDispatchEx methods for COM+ objects
1545 // IDispatchEx::GetTypeInfoCount
1546 HRESULT __stdcall DispatchEx_GetTypeInfoCount(IDispatch* pDisp, unsigned int *pctinfo)
1553 PRECONDITION(CheckPointer(pDisp));
1554 PRECONDITION(IsSimpleTearOff(pDisp));
1555 PRECONDITION(CheckPointer(pctinfo, NULL_OK));
1560 ITypeInfo *pTI = NULL;
1562 // Validate the arguments.
1566 // Initialize the count of type info's to 0.
1569 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1571 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1573 // Retrieve the class ComMethodTable.
1574 ComMethodTable *pComMT = ComCallWrapperTemplate::SetupComMethodTableForClass(pSimpleWrap->GetMethodTable(), FALSE);
1576 // Retrieve the ITypeInfo for the ComMethodTable.
1577 IfFailThrow(GetITypeInfoForMT(pComMT, &pTI));
1579 // GetITypeInfoForMT() can return other success codes besides S_OK so
1580 // we need to convert them to S_OK.
1584 END_EXTERNAL_ENTRYPOINT;
1589 // IDispatchEx::GetTypeInfo
1590 HRESULT __stdcall DispatchEx_GetTypeInfo (
1592 unsigned int itinfo,
1602 PRECONDITION(CheckPointer(pDisp));
1603 PRECONDITION(IsSimpleTearOff(pDisp));
1604 PRECONDITION(CheckPointer(pptinfo, NULL_OK));
1610 // Validate the arguments.
1614 // Initialize the ITypeInfo pointer to NULL.
1617 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1619 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1621 // Retrieve the class ComMethodTable.
1622 ComMethodTable *pComMT = ComCallWrapperTemplate::SetupComMethodTableForClass(pSimpleWrap->GetMethodTable(), FALSE);
1624 // Retrieve the ITypeInfo for the ComMethodTable.
1625 IfFailThrow(GetITypeInfoForMT(pComMT, pptinfo));
1627 // GetITypeInfoForMT() can return other success codes besides S_OK so
1628 // we need to convert them to S_OK.
1630 SafeAddRefPreemp(*pptinfo);
1632 END_EXTERNAL_ENTRYPOINT;
1637 // IDispatchEx::GetIDsofNames
1638 HRESULT __stdcall DispatchEx_GetIDsOfNames (
1641 __in_ecount(cNames) OLECHAR **rgszNames,
1642 unsigned int cNames,
1652 PRECONDITION(CheckPointer(pDisp));
1653 PRECONDITION(IsSimpleTearOff(pDisp));
1654 PRECONDITION(CheckPointer(rgdispid, NULL_OK));
1660 // Validate the arguments.
1664 if (riid != IID_NULL)
1665 return DISP_E_UNKNOWNINTERFACE;
1669 else if (!rgszNames)
1672 // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1673 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1675 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1677 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1679 // Attempt to find the member in the DispatchEx information.
1680 DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1682 SString sName(rgszNames[0]);
1683 DispatchMemberInfo *pDispMemberInfo = pDispExInfo->SynchFindMember(sName, FALSE);
1685 // Check to see if the member has been found.
1686 if (pDispMemberInfo)
1688 // Get the DISPID of the member.
1689 rgdispid[0] = pDispMemberInfo->m_DispID;
1691 // Get the ID's of the named arguments.
1693 hr = pDispMemberInfo->GetIDsOfParameters(rgszNames + 1, cNames - 1, rgdispid + 1, FALSE);
1697 rgdispid[0] = DISPID_UNKNOWN;
1698 hr = DISP_E_UNKNOWNNAME;
1701 END_EXTERNAL_ENTRYPOINT;
1706 // IDispatchEx::Invoke
1707 HRESULT __stdcall DispatchEx_Invoke (
1709 DISPID dispidMember,
1712 unsigned short wFlags,
1713 DISPPARAMS *pdispparams,
1714 VARIANT *pvarResult,
1715 EXCEPINFO *pexcepinfo,
1716 unsigned int *puArgErr
1724 PRECONDITION(CheckPointer(pDisp));
1725 PRECONDITION(IsSimpleTearOff(pDisp));
1726 PRECONDITION(CheckPointer(pdispparams, NULL_OK));
1727 PRECONDITION(CheckPointer(pvarResult, NULL_OK));
1728 PRECONDITION(CheckPointer(pexcepinfo, NULL_OK));
1729 PRECONDITION(CheckPointer(puArgErr, NULL_OK));
1735 // Check for valid input args that are not covered by DispatchInfo::InvokeMember.
1736 if (riid != IID_NULL)
1737 return DISP_E_UNKNOWNINTERFACE;
1739 // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1740 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1742 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1744 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1746 // Invoke the member.
1747 DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1748 hr = pDispExInfo->SynchInvokeMember(pSimpleWrap, dispidMember, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, NULL, puArgErr);
1750 END_EXTERNAL_ENTRYPOINT;
1755 // IDispatchEx::DeleteMemberByDispID
1756 HRESULT __stdcall DispatchEx_DeleteMemberByDispID (
1766 PRECONDITION(CheckPointer(pDisp));
1767 PRECONDITION(IsSimpleTearOff(pDisp));
1773 // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1774 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1776 DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1778 // If the member does not support expando operations then we cannot remove the member.
1779 if (!pDispExInfo->SupportsExpando())
1782 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1784 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1786 // Delete the member from the IExpando. This method takes care of synchronizing with
1787 // the managed view to make sure the member gets deleted.
1788 pDispExInfo->DeleteMember(id);
1791 END_EXTERNAL_ENTRYPOINT;
1796 // IDispatchEx::DeleteMemberByName
1797 HRESULT __stdcall DispatchEx_DeleteMemberByName (
1808 PRECONDITION(CheckPointer(pDisp));
1809 PRECONDITION(IsSimpleTearOff(pDisp));
1819 // The only two supported flags are fdexNameCaseSensitive and fdexNameCaseInsensitive.
1820 if (grfdex & ~(fdexNameCaseSensitive | fdexNameCaseInsensitive))
1821 return E_INVALIDARG;
1823 // Ensure both fdexNameCaseSensitive and fdexNameCaseInsensitive aren't both set.
1824 if ((grfdex & (fdexNameCaseSensitive | fdexNameCaseInsensitive)) == (fdexNameCaseSensitive | fdexNameCaseInsensitive))
1825 return E_INVALIDARG;
1827 // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1828 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1829 DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1831 // If the member does not support expando operations then we cannot remove the member.
1832 if (!pDispExInfo->SupportsExpando())
1835 // Simply find the associated DISPID and delegate the call to DeleteMemberByDispID.
1836 hr = DispatchEx_GetDispID(pDisp, bstrName, grfdex, &DispID);
1838 hr = DispatchEx_DeleteMemberByDispID(pDisp, DispID);
1843 // IDispatchEx::GetDispID
1844 HRESULT __stdcall DispatchEx_GetDispID (
1856 PRECONDITION(CheckPointer(pDisp));
1857 PRECONDITION(CheckPointer(bstrName, NULL_OK));
1858 PRECONDITION(IsSimpleTearOff(pDisp));
1859 PRECONDITION(CheckPointer(pid, NULL_OK));
1864 SimpleComCallWrapper *pSimpleWrap;
1865 DispatchExInfo *pDispExInfo;
1867 // Validate the arguments.
1868 if (!pid || !bstrName)
1871 // We don't support fdexNameImplicit, but let the search continue anyway
1873 // Ensure both fdexNameCaseSensitive and fdexNameCaseInsensitive aren't both set.
1874 if ((grfdex & (fdexNameCaseSensitive | fdexNameCaseInsensitive)) == (fdexNameCaseSensitive | fdexNameCaseInsensitive))
1875 return E_INVALIDARG;
1877 // Initialize the pid to DISPID_UNKNOWN before we start.
1878 *pid = DISPID_UNKNOWN;
1880 // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1881 pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1883 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1885 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1887 // Attempt to find the member in the DispatchEx information.
1888 pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1890 SString sName(bstrName);
1891 DispatchMemberInfo *pDispMemberInfo = pDispExInfo->SynchFindMember(sName, grfdex & fdexNameCaseSensitive);
1893 // If we still have not found a match and the fdexNameEnsure flag is set then we
1894 // need to add the member to the expando object.
1895 if (!pDispMemberInfo)
1897 if (grfdex & fdexNameEnsure)
1899 if (pDispExInfo->SupportsExpando())
1901 pDispMemberInfo = pDispExInfo->AddMember(sName, grfdex);
1902 if (!pDispMemberInfo)
1912 hr = DISP_E_UNKNOWNNAME;
1916 // Set the return DISPID if the member has been found.
1917 if (pDispMemberInfo)
1918 *pid = pDispMemberInfo->m_DispID;
1920 END_EXTERNAL_ENTRYPOINT;
1925 // IDispatchEx::GetMemberName
1926 HRESULT __stdcall DispatchEx_GetMemberName (
1937 PRECONDITION(CheckPointer(pDisp));
1938 PRECONDITION(IsSimpleTearOff(pDisp));
1939 PRECONDITION(CheckPointer(pbstrName, NULL_OK));
1945 // Validate the arguments.
1949 // Initialize the pbstrName to NULL before we start.
1952 // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1953 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1955 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1957 GCX_COOP_THREAD_EXISTS(GET_THREAD());
1959 // Do a lookup in the hashtable to find the DispatchMemberInfo for the DISPID.
1960 DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1961 DispatchMemberInfo *pDispMemberInfo = pDispExInfo->SynchFindMember(id);
1963 // If the member does not exist then we return DISP_E_MEMBERNOTFOUND.
1964 if (!pDispMemberInfo || !pDispMemberInfo->GetMemberInfoObject())
1966 hr = DISP_E_MEMBERNOTFOUND;
1970 // Copy the name into the output string.
1971 *pbstrName = SysAllocString(pDispMemberInfo->m_strName);
1974 END_EXTERNAL_ENTRYPOINT;
1979 // IDispatchEx::GetMemberProperties
1980 HRESULT __stdcall DispatchEx_GetMemberProperties (
1992 PRECONDITION(CheckPointer(pDisp));
1993 PRECONDITION(IsSimpleTearOff(pDisp));
1994 PRECONDITION(CheckPointer(pgrfdex, NULL_OK));
2000 // Validate the arguments.
2004 // Initialize the return properties to 0.
2007 EnumMemberTypes MemberType;
2009 // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
2010 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
2012 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2014 GCX_COOP_THREAD_EXISTS(GET_THREAD());
2016 DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
2017 OBJECTREF MemberInfoObj = NULL;
2018 GCPROTECT_BEGIN(MemberInfoObj)
2020 // Do a lookup in the hashtable to find the DispatchMemberInfo for the DISPID.
2021 DispatchMemberInfo *pDispMemberInfo = pDispExInfo->SynchFindMember(id);
2023 // If the member does not exist then we return DISP_E_MEMBERNOTFOUND.
2024 if (!pDispMemberInfo || (MemberInfoObj = pDispMemberInfo->GetMemberInfoObject()) == NULL)
2026 hr = DISP_E_MEMBERNOTFOUND;
2030 // Retrieve the type of the member.
2031 MemberType = pDispMemberInfo->GetMemberType();
2033 // Retrieve the member properties based on the type of the member.
2038 *pgrfdex = fdexPropCanGet |
2040 fdexPropCannotPutRef |
2041 fdexPropCannotCall |
2042 fdexPropCannotConstruct |
2043 fdexPropCannotSourceEvents;
2049 BOOL bCanRead = FALSE;
2050 BOOL bCanWrite = FALSE;
2052 // Find the MethodDesc's for the CanRead property.
2053 MethodDesc *pCanReadMD = MemberLoader::FindPropertyMethod(MemberInfoObj->GetMethodTable(), PROPERTY_INFO_CAN_READ_PROP, PropertyGet);
2054 PREFIX_ASSUME_MSG((pCanReadMD != NULL), "Unable to find getter method for property PropertyInfo::CanRead");
2055 MethodDescCallSite canRead(pCanReadMD, &MemberInfoObj);
2057 // Find the MethodDesc's for the CanWrite property.
2058 MethodDesc *pCanWriteMD = MemberLoader::FindPropertyMethod(MemberInfoObj->GetMethodTable(), PROPERTY_INFO_CAN_WRITE_PROP, PropertyGet);
2059 PREFIX_ASSUME_MSG((pCanWriteMD != NULL), "Unable to find setter method for property PropertyInfo::CanWrite");
2060 MethodDescCallSite canWrite(pCanWriteMD, &MemberInfoObj);
2062 // Check to see if the property can be read.
2063 ARG_SLOT CanReadArgs[] =
2065 ObjToArgSlot(MemberInfoObj)
2068 bCanRead = canRead.Call_RetBool(CanReadArgs);
2070 // Check to see if the property can be written to.
2071 ARG_SLOT CanWriteArgs[] =
2073 ObjToArgSlot(MemberInfoObj)
2076 bCanWrite = canWrite.Call_RetBool(CanWriteArgs);
2078 *pgrfdex = (bCanRead ? fdexPropCanGet : fdexPropCannotGet) |
2079 (bCanWrite ? fdexPropCanPut : fdexPropCannotPut) |
2080 fdexPropCannotPutRef |
2081 fdexPropCannotCall |
2082 fdexPropCannotConstruct |
2083 fdexPropCannotSourceEvents;
2089 *pgrfdex = fdexPropCannotGet |
2091 fdexPropCannotPutRef |
2093 fdexPropCannotConstruct |
2094 fdexPropCannotSourceEvents;
2105 // Mask out the unwanted properties.
2106 *pgrfdex &= grfdexFetch;
2111 END_EXTERNAL_ENTRYPOINT;
2116 // IDispatchEx::GetNameSpaceParent
2117 HRESULT __stdcall DispatchEx_GetNameSpaceParent (
2127 PRECONDITION(CheckPointer(pDisp));
2128 PRECONDITION(IsSimpleTearOff(pDisp));
2129 PRECONDITION(CheckPointer(ppunk, NULL_OK));
2133 // Validate the arguments.
2137 // @TODO (DM): Implement this.
2143 // IDispatchEx::GetNextDispID
2144 HRESULT __stdcall DispatchEx_GetNextDispID (
2156 PRECONDITION(CheckPointer(pDisp));
2157 PRECONDITION(IsSimpleTearOff(pDisp));
2158 PRECONDITION(CheckPointer(pid, NULL_OK));
2162 DispatchMemberInfo *pNextMember = NULL;
2165 // Validate the arguments.
2169 // The only two supported flags are fdexEnumDefault and fdexEnumAll.
2170 if (grfdex & ~(fdexEnumDefault | fdexEnumAll))
2171 return E_INVALIDARG;
2173 // Initialize the pid to DISPID_UNKNOWN.
2174 *pid = DISPID_UNKNOWN;
2176 // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
2177 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
2179 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2181 GCX_COOP_THREAD_EXISTS(GET_THREAD());
2183 DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
2184 // Retrieve either the first member or the next based on the DISPID.
2185 if (id == DISPID_STARTENUM)
2186 pNextMember = pDispExInfo->GetFirstMember();
2188 pNextMember = pDispExInfo->GetNextMember(id);
2190 // If we have found a member that has not been deleted then return its DISPID.
2193 *pid = pNextMember->m_DispID;
2201 END_EXTERNAL_ENTRYPOINT;
2207 // IDispatchEx::InvokeEx
2208 HRESULT __stdcall DispatchEx_InvokeEx (
2216 IServiceProvider *pspCaller
2224 PRECONDITION(CheckPointer(pDisp));
2225 PRECONDITION(IsSimpleTearOff(pDisp));
2226 PRECONDITION(CheckPointer(pdp, NULL_OK));
2227 PRECONDITION(CheckPointer(pVarRes, NULL_OK));
2228 PRECONDITION(CheckPointer(pei, NULL_OK));
2229 PRECONDITION(CheckPointer(pspCaller, NULL_OK));
2235 // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
2236 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
2237 DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
2239 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2241 GCX_COOP_THREAD_EXISTS(GET_THREAD());
2243 // Invoke the member.
2244 hr = pDispExInfo->SynchInvokeMember(pSimpleWrap, id, lcid, wFlags, pdp, pVarRes, pei, pspCaller, NULL);
2246 END_EXTERNAL_ENTRYPOINT;
2251 HRESULT __stdcall Inspectable_GetIIDs (
2252 IInspectable *pInsp,
2261 PRECONDITION(CheckPointer(pInsp));
2262 PRECONDITION(IsInProcCCWTearOff(pInsp));
2268 if (iidCount == NULL || iids == NULL)
2274 // Either it is ICustomPropertyProvider or IWeakReferenceSource
2275 ComCallWrapper *pWrap = MapIUnknownToWrapper(pInsp);
2277 ComCallWrapperTemplate *pTemplate = pWrap->GetComCallWrapperTemplate();
2279 ULONG numInterfaces = pTemplate->GetNumInterfaces();
2281 // determine the number of IIDs to return
2282 // Always add IID_ICustomPropertyProvider and skip any managed WinRT interface that is IID_ICustomPropertyProvider
2283 ULONG numInspectables = 1;
2284 for (ULONG i = 0; i < numInterfaces; i++)
2286 ComMethodTable *pComMT = pTemplate->GetComMTForIndex(i);
2288 // Skip any managed WinRT interface that is IID_ICustomPropertyProvider
2289 if (pComMT != NULL && pComMT->GetInterfaceType() == ifInspectable &&
2290 !IsEqualGUID(pComMT->GetIID(), IID_ICustomPropertyProvider))
2297 // we shouldn't ever come here if the CCW does not support IInspectable
2298 _ASSERTE(numInspectables > 0);
2300 // as per the spec, make sure *iidCount is set even if the allocation fails
2301 *iidCount = numInspectables;
2303 S_UINT32 cbAlloc = S_UINT32(numInspectables) * S_UINT32(sizeof(IID));
2304 if (cbAlloc.IsOverflow())
2305 return E_OUTOFMEMORY;
2307 NewArrayHolder<IID> result = (IID *)CoTaskMemAlloc(cbAlloc.Value());
2309 return E_OUTOFMEMORY;
2311 // now fill out the output array with IIDs
2312 result[0] = IID_ICustomPropertyProvider;
2315 for (ULONG i = 0; i < numInterfaces; i++)
2317 ComMethodTable *pComMT = pTemplate->GetComMTForIndex(i);
2319 // Skip any managed WinRT interface that is IID_ICustomPropertyProvider
2320 if (pComMT != NULL && pComMT->GetInterfaceType() == ifInspectable &&
2321 !IsEqualGUID(pComMT->GetIID(), IID_ICustomPropertyProvider))
2323 result[index] = pComMT->GetIID();
2327 _ASSERTE(index == numInspectables);
2329 *iids = result.Extract();
2334 HRESULT __stdcall Inspectable_GetRuntimeClassName(IInspectable *pInsp, HSTRING *className)
2341 PRECONDITION(CheckPointer(pInsp));
2342 PRECONDITION(IsInProcCCWTearOff(pInsp));
2346 if (className == NULL)
2350 ComCallWrapper *pWrap = MapIUnknownToWrapper(pInsp);
2354 MethodTable *pMT = pWrap->GetSimpleWrapper()->GetMethodTable();
2355 _ASSERTE(pMT != NULL);
2359 StackSString strClassName;
2360 TypeHandle thManagedType;
2364 OBJECTREF objref = NULL;
2366 GCPROTECT_BEGIN(objref);
2368 objref = pWrap->GetObjectRef();
2369 thManagedType = objref->GetTypeHandle();
2374 bool bIsPrimitive = false;
2375 if (WinRTTypeNameConverter::AppendWinRTTypeNameForManagedType(
2376 thManagedType, // thManagedType
2377 strClassName, // strWinRTTypeName
2378 TRUE, // bForGetRuntimeClassName,
2379 &bIsPrimitive // pbIsPrimitiveType
2383 hr = WindowsCreateString(strClassName.GetUnicode(), strClassName.GetCount(), className);
2388 hr = GET_EXCEPTION()->GetHR();
2390 EX_END_CATCH(SwallowAllExceptions);
2395 HRESULT __stdcall WeakReferenceSource_GetWeakReference (
2396 IWeakReferenceSource *pRefSrc,
2397 IWeakReference **weakReference)
2404 PRECONDITION(CheckPointer(pRefSrc));
2405 PRECONDITION(IsInProcCCWTearOff(pRefSrc));
2409 if (weakReference == NULL)
2410 return E_INVALIDARG;
2412 *weakReference = NULL;
2415 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2417 SimpleComCallWrapper *pWrap = SimpleComCallWrapper::GetWrapperFromIP(pRefSrc);
2419 // Creates a new WeakReferenceImpl that tracks the object lifetime in the current domain
2420 // Note that this WeakReferenceImpl is not bound to a specific CCW
2421 *weakReference = pWrap->CreateWeakReference(GET_THREAD());
2423 END_EXTERNAL_ENTRYPOINT;
2429 // Helper to setup IMarshal
2430 HRESULT GetSpecialMarshaler(IMarshal* pMarsh, SimpleComCallWrapper* pSimpleWrap, ULONG dwDestContext, IMarshal **ppMarshalRet)
2437 PRECONDITION(CheckPointer(pMarsh, NULL_OK));
2438 PRECONDITION(CheckPointer(pSimpleWrap));
2445 // In case of APPX process we always use the standard marshaller.
2446 // In Non-APPX process use standard marshalling for everything except in-proc servers.
2447 // In case of CoreCLR, we always use the standard marshaller as well.
2449 SafeComHolderPreemp<IUnknown> pMarshalerObj = NULL;
2450 IfFailRet(CoCreateFreeThreadedMarshaler(NULL, &pMarshalerObj));
2451 return SafeQueryInterfacePreemp(pMarshalerObj, IID_IMarshal, (IUnknown**)ppMarshalRet);
2455 //------------------------------------------------------------------------------------------
2456 // IMarshal methods for COM+ objects
2458 //------------------------------------------------------------------------------------------
2460 HRESULT __stdcall Marshal_GetUnmarshalClass (
2462 REFIID riid, void * pv, ULONG dwDestContext,
2463 void * pvDestContext, ULONG mshlflags,
2471 PRECONDITION(CheckPointer(pMarsh));
2472 PRECONDITION(IsSimpleTearOff(pMarsh));
2473 PRECONDITION(CheckPointer(pv, NULL_OK));
2474 PRECONDITION(CheckPointer(pvDestContext, NULL_OK));
2475 PRECONDITION(CheckPointer(pclsid, NULL_OK));
2481 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pMarsh);
2483 // Prevent access to reflection over DCOM
2484 if(dwDestContext != MSHCTX_INPROC)
2486 if(!pSimpleWrap->GetComCallWrapperTemplate()->IsSafeTypeForMarshalling())
2488 LogInterop(W("Unmarshal class blocked for reflection types."));
2494 SafeComHolderPreemp<IMarshal> pMsh = NULL;
2495 hr = GetSpecialMarshaler(pMarsh, pSimpleWrap, dwDestContext, (IMarshal **)&pMsh);
2501 hr = pMsh->GetUnmarshalClass (riid, pv, dwDestContext, pvDestContext, mshlflags, pclsid);
2505 // Use a statically allocated singleton class to do all unmarshalling.
2506 *pclsid = CLSID_ComCallUnmarshalV4;
2511 HRESULT __stdcall Marshal_GetMarshalSizeMax (
2513 REFIID riid, void * pv, ULONG dwDestContext,
2514 void * pvDestContext, ULONG mshlflags,
2522 PRECONDITION(CheckPointer(pMarsh));
2523 PRECONDITION(IsSimpleTearOff(pMarsh));
2524 PRECONDITION(CheckPointer(pv, NULL_OK));
2525 PRECONDITION(CheckPointer(pvDestContext, NULL_OK));
2526 PRECONDITION(CheckPointer(pSize, NULL_OK));
2530 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pMarsh);
2532 SafeComHolderPreemp<IMarshal> pMsh = NULL;
2533 HRESULT hr = GetSpecialMarshaler(pMarsh, pSimpleWrap, dwDestContext, (IMarshal **)&pMsh);
2539 HRESULT hr = pMsh->GetMarshalSizeMax (riid, pv, dwDestContext, pvDestContext, mshlflags, pSize);
2543 *pSize = sizeof (IUnknown *) + sizeof (ULONG) + sizeof(GUID);
2548 HRESULT __stdcall Marshal_MarshalInterface (
2550 LPSTREAM pStm, REFIID riid, void * pv,
2551 ULONG dwDestContext, LPVOID pvDestContext,
2559 PRECONDITION(CheckPointer(pMarsh));
2560 PRECONDITION(IsSimpleTearOff(pMarsh));
2561 PRECONDITION(CheckPointer(pv));
2562 PRECONDITION(CheckPointer(pvDestContext, NULL_OK));
2569 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pMarsh);
2571 // Prevent access to reflection over DCOM
2572 if(dwDestContext != MSHCTX_INPROC)
2574 if(!pSimpleWrap->GetComCallWrapperTemplate()->IsSafeTypeForMarshalling())
2576 LogInterop(W("Marshal interface blocked for reflection types."));
2582 SafeComHolderPreemp<IMarshal> pMsh = NULL;
2583 hr = GetSpecialMarshaler(pMarsh, pSimpleWrap, dwDestContext, (IMarshal **)&pMsh);
2589 hr = pMsh->MarshalInterface (pStm, riid, pv, dwDestContext, pvDestContext, mshlflags);
2593 // Write the raw IP into the marshalling stream.
2594 hr = pStm->Write (&pv, sizeof (pv), 0);
2598 // Followed by the marshalling flags (we need these on the remote end to
2599 // manage refcounting the IP).
2600 hr = pStm->Write (&mshlflags, sizeof (mshlflags), 0);
2604 // Followed by the secret, which confirms that the pointer above can be trusted
2605 // because it originated from our runtime.
2606 hr = InitUnmarshalSecret();
2610 hr = pStm->Write(g_UnmarshalSecret, sizeof(g_UnmarshalSecret), 0);
2614 // We have now created an additional reference to the object.
2615 cbRef = SafeAddRefPreemp((IUnknown *)pv);
2616 LogInteropAddRef((IUnknown *)pv, cbRef, "MarshalInterface");
2621 HRESULT __stdcall Marshal_UnmarshalInterface (
2623 LPSTREAM pStm, REFIID riid,
2631 PRECONDITION(CheckPointer(pMarsh));
2632 PRECONDITION(IsSimpleTearOff(pMarsh));
2633 PRECONDITION(CheckPointer(pStm, NULL_OK));
2634 PRECONDITION(CheckPointer(ppvObj, NULL_OK));
2638 // Unmarshal side only.
2642 HRESULT __stdcall Marshal_ReleaseMarshalData (IMarshal* pMarsh, LPSTREAM pStm)
2649 PRECONDITION(CheckPointer(pMarsh));
2650 PRECONDITION(IsSimpleTearOff(pMarsh));
2651 PRECONDITION(CheckPointer(pStm, NULL_OK));
2655 // Unmarshal side only.
2659 HRESULT __stdcall Marshal_DisconnectObject (IMarshal* pMarsh, ULONG dwReserved)
2666 PRECONDITION(CheckPointer(pMarsh));
2667 PRECONDITION(IsSimpleTearOff(pMarsh));
2671 // Nothing we can (or need to) do here. The client is using a raw IP to
2672 // access this server, so the server shouldn't go away until the client
2677 //------------------------------------------------------------------------------------------
2678 // IConnectionPointContainer methods for COM+ objects
2679 //------------------------------------------------------------------------------------------
2681 // Enumerate all the connection points supported by the component.
2682 HRESULT __stdcall ConnectionPointContainer_EnumConnectionPoints(IUnknown* pUnk,
2683 IEnumConnectionPoints **ppEnum)
2690 PRECONDITION(CheckPointer(pUnk));
2691 PRECONDITION(CheckPointer(ppEnum, NULL_OK));
2702 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2704 _ASSERTE(IsSimpleTearOff(pUnk));
2705 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
2706 pSimpleWrap->EnumConnectionPoints(ppEnum);
2708 END_EXTERNAL_ENTRYPOINT;
2713 // Find a specific connection point based on the IID of the event interface.
2714 HRESULT __stdcall ConnectionPointContainer_FindConnectionPoint(IUnknown* pUnk,
2716 IConnectionPoint **ppCP)
2723 PRECONDITION(CheckPointer(pUnk));
2724 PRECONDITION(CheckPointer(ppCP, NULL_OK));
2735 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2737 _ASSERTE(IsSimpleTearOff(pUnk));
2738 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
2739 if (!pSimpleWrap->FindConnectionPoint(riid, ppCP))
2740 hr = CONNECT_E_NOCONNECTION;
2742 END_EXTERNAL_ENTRYPOINT;
2748 //------------------------------------------------------------------------------------------
2749 // IObjectSafety methods for COM+ objects
2750 //------------------------------------------------------------------------------------------
2752 HRESULT __stdcall ObjectSafety_GetInterfaceSafetyOptions(IUnknown* pUnk,
2754 DWORD *pdwSupportedOptions,
2755 DWORD *pdwEnabledOptions)
2762 PRECONDITION(CheckPointer(pUnk));
2763 PRECONDITION(IsSimpleTearOff(pUnk));
2764 PRECONDITION(CheckPointer(pdwSupportedOptions, NULL_OK));
2765 PRECONDITION(CheckPointer(pdwEnabledOptions, NULL_OK));
2769 if (pdwSupportedOptions == NULL || pdwEnabledOptions == NULL)
2772 // Make sure the COM+ object implements the requested interface.
2773 SafeComHolderPreemp<IUnknown> pItf;
2774 HRESULT hr = SafeQueryInterfacePreemp(pUnk, riid, (IUnknown**)&pItf);
2775 LogInteropQI(pUnk, riid, hr, "QI to for riid in GetInterfaceSafetyOptions");
2778 // We support this interface so set the safety options accordingly
2779 *pdwSupportedOptions = (INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACESAFE_FOR_UNTRUSTED_CALLER);
2780 *pdwEnabledOptions = (INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACESAFE_FOR_UNTRUSTED_CALLER);
2785 // We don't support this interface
2786 *pdwSupportedOptions = 0;
2787 *pdwEnabledOptions = 0;
2788 return E_NOINTERFACE;
2792 HRESULT __stdcall ObjectSafety_SetInterfaceSafetyOptions(IUnknown* pUnk,
2794 DWORD dwOptionSetMask,
2795 DWORD dwEnabledOptions)
2802 PRECONDITION(CheckPointer(pUnk));
2803 PRECONDITION(IsSimpleTearOff(pUnk));
2807 // Make sure the COM+ object implements the requested interface.
2808 SafeComHolderPreemp<IUnknown> pItf;
2809 HRESULT hr = SafeQueryInterfacePreemp(pUnk, riid, (IUnknown**)&pItf);
2810 LogInteropQI(pUnk, riid, hr, "QI to for riid in SetInterfaceSafetyOptions");
2814 if ((dwEnabledOptions & ~(INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACESAFE_FOR_UNTRUSTED_CALLER)) != 0)
2820 HRESULT __stdcall ICustomPropertyProvider_GetProperty(IUnknown *pPropertyProvider, HSTRING hstrName, IUnknown **ppProperty)
2827 PRECONDITION(CheckPointer(pPropertyProvider));
2828 PRECONDITION(IsSimpleTearOff(pPropertyProvider));
2829 PRECONDITION(CheckPointer(ppProperty, NULL_OK));
2833 if (ppProperty == NULL)
2836 // Initialize [out] parameters
2841 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2843 _ASSERTE(IsSimpleTearOff(pPropertyProvider));
2844 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pPropertyProvider);
2849 OBJECTREF TargetObj;
2850 STRINGREF StringRef;
2853 ZeroMemory(&gc, sizeof(gc));
2855 GCPROTECT_BEGIN(gc);
2857 gc.TargetObj = pSimpleWrap->GetObjectRef();
2860 // Marshal HSTRING to String object
2861 // NULL HSTRINGS are equivilent to empty strings
2863 UINT32 cchString = 0;
2864 LPCWSTR pwszString = W("");
2865 if (hstrName != NULL)
2867 pwszString = WindowsGetStringRawBuffer(hstrName, &cchString);
2870 gc.StringRef = StringObject::NewString(pwszString, cchString);
2873 // Call ICustomPropertyProviderImpl.CreateProperty
2875 PREPARE_NONVIRTUAL_CALLSITE(METHOD__ICUSTOMPROPERTYPROVIDERIMPL__CREATE_PROPERTY);
2876 DECLARE_ARGHOLDER_ARRAY(args, 2);
2877 args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(gc.TargetObj);
2878 args[ARGNUM_1] = OBJECTREF_TO_ARGHOLDER(gc.StringRef);
2880 CALL_MANAGED_METHOD_RETREF(gc.RetVal, OBJECTREF, args);
2882 if (gc.RetVal != NULL)
2884 // The object is a CustomPropertyImpl. Get the ICustomProperty implementation from CCW and return that
2885 *ppProperty = GetComIPFromObjectRef(&gc.RetVal, MscorlibBinder::GetClass(CLASS__ICUSTOMPROPERTY));
2890 END_EXTERNAL_ENTRYPOINT;
2892 // Don't fail if property can't be found - just return S_OK and NULL property
2896 HRESULT __stdcall ICustomPropertyProvider_GetIndexedProperty(IUnknown *pPropertyProvider,
2898 TypeNameNative indexedParamType,
2899 /* [out, retval] */ IUnknown **ppProperty)
2906 PRECONDITION(CheckPointer(pPropertyProvider));
2907 PRECONDITION(IsSimpleTearOff(pPropertyProvider));
2908 PRECONDITION(CheckPointer(ppProperty, NULL_OK));
2912 if (ppProperty == NULL)
2915 // Initialize [out] parameters
2920 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2922 _ASSERTE(IsSimpleTearOff(pPropertyProvider));
2923 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pPropertyProvider);
2928 OBJECTREF TargetObj;
2929 STRINGREF StringRef;
2932 ZeroMemory(&gc, sizeof(gc));
2934 GCPROTECT_BEGIN(gc);
2936 gc.TargetObj = pSimpleWrap->GetObjectRef();
2939 // Marshal HSTRING to String object
2940 // NULL HSTRINGS are equivilent to empty strings
2942 UINT32 cchString = 0;
2943 LPCWSTR pwszString = W("");
2944 if (hstrName != NULL)
2946 pwszString = WindowsGetStringRawBuffer(hstrName, &cchString);
2949 gc.StringRef = StringObject::NewString(pwszString, cchString);
2952 // Call ICustomPropertyProviderImpl.CreateIndexedProperty
2954 PREPARE_NONVIRTUAL_CALLSITE(METHOD__ICUSTOMPROPERTYPROVIDERIMPL__CREATE_INDEXED_PROPERTY);
2955 DECLARE_ARGHOLDER_ARRAY(args, 3);
2956 args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(gc.TargetObj);
2957 args[ARGNUM_1] = OBJECTREF_TO_ARGHOLDER(gc.StringRef);
2958 args[ARGNUM_2] = PTR_TO_ARGHOLDER(&indexedParamType);
2960 CALL_MANAGED_METHOD_RETREF(gc.RetVal, OBJECTREF, args);
2962 if (gc.RetVal != NULL)
2964 // The object is a CustomPropertyImpl. Get the ICustomProperty implementation from CCW and return that
2965 *ppProperty = GetComIPFromObjectRef(&gc.RetVal, MscorlibBinder::GetClass(CLASS__ICUSTOMPROPERTY));
2970 END_EXTERNAL_ENTRYPOINT;
2972 // Don't fail if property can't be found - just return S_OK and NULL property
2976 HRESULT __stdcall ICustomPropertyProvider_GetStringRepresentation(IUnknown *pPropertyProvider,
2977 /* [out, retval] */ HSTRING *phstrStringRepresentation)
2984 PRECONDITION(CheckPointer(pPropertyProvider));
2985 PRECONDITION(IsSimpleTearOff(pPropertyProvider));
2986 PRECONDITION(CheckPointer(phstrStringRepresentation, NULL_OK));
2990 if (phstrStringRepresentation == NULL)
2993 // Initialize [out] parameters
2994 *phstrStringRepresentation = NULL;
2998 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
3000 _ASSERTE(IsSimpleTearOff(pPropertyProvider));
3001 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pPropertyProvider);
3006 OBJECTREF TargetObj;
3009 ZeroMemory(&gc, sizeof(gc));
3011 GCPROTECT_BEGIN(gc);
3013 gc.TargetObj = pSimpleWrap->GetObjectRef();
3016 // Call IStringableHelper.ToString() to get string representation either from IStringable.ToString() or ToString()
3018 PREPARE_NONVIRTUAL_CALLSITE(METHOD__ISTRINGABLEHELPER__TO_STRING);
3019 DECLARE_ARGHOLDER_ARRAY(args, 1);
3020 args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(gc.TargetObj);
3021 CALL_MANAGED_METHOD_RETREF(gc.RetVal, STRINGREF, args);
3024 // Convert managed string to HSTRING
3026 if (gc.RetVal == NULL)
3027 *phstrStringRepresentation = NULL;
3029 hr = ::WindowsCreateString(gc.RetVal->GetBuffer(), gc.RetVal->GetStringLength(), phstrStringRepresentation);
3034 END_EXTERNAL_ENTRYPOINT;
3039 HRESULT __stdcall ICustomPropertyProvider_GetType(IUnknown *pPropertyProvider,
3040 /* [out, retval] */ TypeNameNative *pTypeIdentifier)
3047 PRECONDITION(CheckPointer(pPropertyProvider));
3048 PRECONDITION(IsSimpleTearOff(pPropertyProvider));
3049 PRECONDITION(CheckPointer(pTypeIdentifier));
3053 if (pTypeIdentifier == NULL)
3056 // Initialize [out] parameters
3057 ::ZeroMemory(pTypeIdentifier, sizeof(TypeNameNative));
3061 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
3063 _ASSERTE(IsSimpleTearOff(pPropertyProvider));
3064 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pPropertyProvider);
3068 OBJECTREF refTargetObj = NULL;
3069 GCPROTECT_BEGIN(refTargetObj);
3071 refTargetObj = pSimpleWrap->GetObjectRef();
3074 // Call ICustomPropertyProviderImpl.GetType()
3076 PREPARE_NONVIRTUAL_CALLSITE(METHOD__ICUSTOMPROPERTYPROVIDERIMPL__GET_TYPE);
3077 DECLARE_ARGHOLDER_ARRAY(args, 2);
3078 args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(refTargetObj);
3079 args[ARGNUM_1] = PTR_TO_ARGHOLDER(pTypeIdentifier);
3081 CALL_MANAGED_METHOD_NORET(args);
3085 END_EXTERNAL_ENTRYPOINT;
3090 HRESULT __stdcall IStringable_ToString(IUnknown* pStringable,
3091 /* [out, retval] */ HSTRING* pResult)
3098 PRECONDITION(CheckPointer(pStringable));
3099 PRECONDITION(IsSimpleTearOff(pStringable));
3100 PRECONDITION(CheckPointer(pResult, NULL_OK));
3104 if (pResult == NULL)
3107 // Initialize [out] parameters
3112 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
3114 _ASSERTE(IsSimpleTearOff(pStringable));
3115 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pStringable);
3120 OBJECTREF TargetObj;
3123 ZeroMemory(&gc, sizeof(gc));
3125 GCPROTECT_BEGIN(gc);
3127 gc.TargetObj = pSimpleWrap->GetObjectRef();
3128 MethodDesc* pToStringMD = NULL;
3130 MethodTable* pMT = gc.TargetObj->GetMethodTable();
3133 // Get the MethodTable for Windows.Foundation.IStringable.
3134 StackSString strIStringable(SString::Utf8, W("Windows.Foundation.IStringable"));
3135 MethodTable *pMTIStringable = LoadWinRTType(&strIStringable, /* bThrowIfNotFound = */ FALSE).GetMethodTable();
3137 if (pMT != NULL && pMTIStringable != NULL && pMT->ImplementsInterface(pMTIStringable))
3139 // Find the ToString() method of the interface.
3140 pToStringMD = MemberLoader::FindMethod(
3145 _ASSERTE(pToStringMD != NULL);
3149 // The object does not implement IStringable interface we need to call the default implementation using Object.ToString() call.
3150 pToStringMD = MscorlibBinder::GetMethod(METHOD__OBJECT__TO_STRING);
3151 _ASSERTE(pToStringMD != NULL);
3156 PREPARE_VIRTUAL_CALLSITE_USING_METHODDESC(pToStringMD, gc.TargetObj);
3157 DECLARE_ARGHOLDER_ARRAY(args, 1);
3158 args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(gc.TargetObj);
3160 CALL_MANAGED_METHOD_RETREF(gc.RetVal, STRINGREF, args);
3163 // Convert managed string to HSTRING
3165 if (gc.RetVal == NULL)
3168 hr = ::WindowsCreateString(gc.RetVal->GetBuffer(), gc.RetVal->GetStringLength(), pResult);
3173 END_EXTERNAL_ENTRYPOINT;
3181 ICCW_AddRefFromJupiter(IUnknown* pUnk)
3188 PRECONDITION(CheckPointer(pUnk));
3189 PRECONDITION(IsSimpleTearOff(pUnk));
3193 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
3195 return pSimpleWrap->AddJupiterRef();
3199 ICCW_ReleaseFromJupiter(IUnknown* pUnk)
3206 PRECONDITION(CheckPointer(pUnk));
3213 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
3215 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
3217 cbRef = pSimpleWrap->ReleaseJupiterRef();
3219 END_EXTERNAL_ENTRYPOINT;
3225 ICCW_Peg(IUnknown* pUnk)
3232 PRECONDITION(CheckPointer(pUnk));
3236 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
3238 pSimpleWrap->MarkPegged();
3240 STRESS_LOG1(LF_INTEROP, LL_INFO1000, "CCW 0x%p pegged\n", (ComCallWrapper *)pSimpleWrap->GetMainWrapper());
3246 ICCW_Unpeg(IUnknown* pUnk)
3253 PRECONDITION(CheckPointer(pUnk));
3257 SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
3259 pSimpleWrap->UnMarkPegged();
3261 STRESS_LOG1(LF_INTEROP, LL_INFO1000, "CCW 0x%p unpegged\n", (ComCallWrapper *)pSimpleWrap->GetMainWrapper());