[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / vm / stdinterfaces.cpp
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 //---------------------------------------------------------------------------------
5 // stdinterfaces.cpp
6 //
7 // Defines various standard com interfaces 
8
9 //---------------------------------------------------------------------------------
10
11
12 #include "common.h"
13
14 #include <ole2.h>
15 #include <guidfromname.h>
16 #include <olectl.h>
17 #include <objsafe.h>    // IID_IObjectSafety
18 #include "vars.hpp"
19 #include "object.h"
20 #include "excep.h"
21 #include "frames.h"
22 #include "vars.hpp"
23 #include "runtimecallablewrapper.h"
24 #include "stdinterfaces.h"
25 #include "comcallablewrapper.h"
26 #include "field.h"
27 #include "threads.h"
28 #include "interoputil.h"
29 #include "comdelegate.h"
30 #include "olevariant.h"
31 #include "eeconfig.h"
32 #include "typehandle.h"
33 #include "posterror.h"
34 #include <corerror.h>
35 #include <mscoree.h>
36 #include "mtx.h"
37 #include "cgencpu.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"
45
46
47 //------------------------------------------------------------------------------------------
48 //      Definitions used by the IDispatchEx implementation
49
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"
55
56
57 // {00020430-0000-0000-C000-000000000046}
58 static const GUID LIBID_STDOLE2 = { 0x00020430, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
59
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 } };
63
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__
68
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__
73
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.
77
78 // array of vtable pointers for std. interfaces such as IProvideClassInfo etc.
79 const SLOT * const g_rgStdVtables[] =  
80 {
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
94 };
95
96
97 const IID IID_IWeakReferenceSource = __uuidof(IWeakReferenceSource);
98 const IID IID_IWeakReference = __uuidof(IWeakReference);
99
100 // {7C925755-3E48-42B4-8677-76372267033F}
101 const IID IID_ICustomPropertyProvider = {0x7C925755,0x3E48,0x42B4,{0x86, 0x77, 0x76, 0x37, 0x22, 0x67, 0x03, 0x3F}};
102
103 const IID IID_IStringable = {0x96369f54,0x8eb6,0x48f0, {0xab,0xce,0xc1,0xb2,0x11,0xe6,0x27,0xc3}};
104
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;
109
110
111 static HRESULT InitUnmarshalSecret()
112 {
113     CONTRACTL
114     {
115         NOTHROW;
116         GC_NOTRIGGER;
117         MODE_PREEMPTIVE;
118     }
119     CONTRACTL_END;
120        
121     HRESULT hr = S_OK;
122
123     if (!g_fInitedUnmarshalSecret)
124     {
125         ComCall::LockHolder lh;
126
127         if (!g_fInitedUnmarshalSecret)
128         {
129             hr = ::CoCreateGuid((GUID *) g_UnmarshalSecret);
130             if (SUCCEEDED(hr))
131                 g_fInitedUnmarshalSecret = true;
132         }
133     }
134     return hr;
135 }
136
137 //------------------------------------------------------------------------------------------
138 //      IUnknown methods for CLR objects
139
140
141 HRESULT
142 Unknown_QueryInterface_Internal(ComCallWrapper* pWrap, IUnknown* pUnk, REFIID riid, void** ppv)
143 {
144     CONTRACTL
145     {
146         NOTHROW;
147         GC_TRIGGERS;
148         MODE_PREEMPTIVE;
149         PRECONDITION(CheckPointer(pUnk));
150         PRECONDITION(IsInProcCCWTearOff(pUnk));
151         PRECONDITION(CheckPointer(ppv, NULL_OK));
152         PRECONDITION(CheckPointer(pWrap));
153     }
154     CONTRACTL_END;
155
156     HRESULT hr = S_OK;
157     SafeComHolderPreemp<IUnknown> pDestItf = NULL;
158
159     // Validate the arguments.
160     if (!ppv)
161         return E_POINTER;
162
163     // Initialize the returned interface pointer to NULL before we start.
164     *ppv = NULL;
165
166     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
167     {
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.
171         hr = E_NOINTERFACE;
172
173         // Check for QIs on inner unknown
174         if (!IsInnerUnknown(pUnk))
175         {
176             // Aggregation support, delegate to the outer unknown if non null.
177             IUnknown *pOuter = pWrap->GetSimpleWrapper()->GetOuter();
178             if (pOuter != NULL)
179             {
180                 hr = SafeQueryInterfacePreemp(pOuter, riid, &pDestItf);
181                 LogInteropQI(pOuter, riid, hr, "QI to outer Unknown");
182                 IfFailGo(hr);
183             }
184         }
185         else
186         {
187             // Assert the component has been aggregated     
188             _ASSERTE(pWrap->GetSimpleWrapper()->GetOuter() != NULL);
189
190             // Okay special case IUnknown
191             if (IsEqualIID(riid, IID_IUnknown))
192             {
193                 SafeAddRefPreemp(pUnk);
194                 pDestItf = pUnk;
195             }
196         }
197
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)
201         {
202             EX_TRY
203             {
204                 pDestItf = ComCallWrapper::GetComIPFromCCW(pWrap, riid, NULL, GetComIPFromCCW::CheckVisibility);
205             }
206             EX_CATCH
207             {
208                 Exception *e = GET_EXCEPTION();
209                 hr = e->GetHR();
210             }
211             EX_END_CATCH(RethrowTerminalExceptions)
212         }
213
214 ErrExit:
215         // If we succeeded in obtaining the requested IP then return S_OK.
216         if (pDestItf != NULL)
217             hr = S_OK;
218     }
219     END_EXTERNAL_ENTRYPOINT;
220
221     if (SUCCEEDED(hr))
222     {
223         // If we succeeded in obtaining the requested IP, set ppv to the interface.
224         _ASSERTE(pDestItf != NULL);
225         *ppv = pDestItf;
226         pDestItf.SuppressRelease();
227     }
228
229     return hr;
230 }  // Unknown_QueryInterface_Internal
231
232
233 ULONG __stdcall
234 Unknown_AddRefInner_Internal(IUnknown* pUnk)
235 {
236     CONTRACTL
237     {
238         NOTHROW;
239         GC_TRIGGERS;
240         MODE_PREEMPTIVE;
241         PRECONDITION(CheckPointer(pUnk));
242     }
243     CONTRACTL_END;
244
245     SimpleComCallWrapper* pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
246     ComCallWrapper* pWrap = pSimpleWrap->GetMainWrapper();     
247
248     // Assert the component has been aggregated     
249     _ASSERTE(pSimpleWrap->GetOuter() != NULL);
250
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();
254 } // Unknown_AddRef
255
256
257 ULONG __stdcall
258 Unknown_AddRef_Internal(IUnknown* pUnk)
259 {
260     CONTRACTL
261     {
262         NOTHROW;
263         GC_TRIGGERS;
264         MODE_PREEMPTIVE;
265         PRECONDITION(CheckPointer(pUnk));
266     }
267     CONTRACTL_END;
268
269     ComCallWrapper* pWrap = ComCallWrapper::GetWrapperFromIP(pUnk);
270
271     // check for aggregation
272     IUnknown *pOuter; 
273     SimpleComCallWrapper* pSimpleWrap = pWrap->GetSimpleWrapper();
274     if (pSimpleWrap  && (pOuter = pSimpleWrap->GetOuter()) != NULL)
275     {
276         // If we are in process detach, we cannot safely call release on our outer.
277         if (g_fProcessDetach)
278             return 1;
279
280         ULONG cbRef = pOuter->AddRef();
281         LogInteropAddRef(pOuter, cbRef, "Delegate to outer");
282         return cbRef;
283     }
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();
287 } // Unknown_AddRef
288
289
290 ULONG __stdcall
291 Unknown_ReleaseInner_Internal(IUnknown* pUnk)
292 {
293     CONTRACTL
294     {
295         NOTHROW;
296         GC_TRIGGERS;
297         MODE_PREEMPTIVE;
298         PRECONDITION(CheckPointer(pUnk));
299     }
300     CONTRACTL_END;
301
302     HRESULT hr = S_OK;
303     ULONG cbRef = -1;
304
305     SimpleComCallWrapper* pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
306     ComCallWrapper* pWrap = pSimpleWrap->GetMainWrapper();  
307
308     // Assert the component has been aggregated     
309     _ASSERTE(pSimpleWrap->GetOuter() != NULL);
310
311     // We know for sure this wrapper is a start wrapper let us pass this information in
312     cbRef = pWrap->Release();
313
314     return cbRef;
315 } // Unknown_Release
316
317 ULONG __stdcall
318 Unknown_Release_Internal(IUnknown* pUnk)
319 {
320     CONTRACTL
321     {
322         NOTHROW;
323         GC_TRIGGERS;
324         MODE_PREEMPTIVE;
325         PRECONDITION(CheckPointer(pUnk));
326     }
327     CONTRACTL_END;
328     
329     HRESULT hr = S_OK;
330     ULONG cbRef = -1;
331
332     // check for aggregation
333     ComCallWrapper* pWrap = ComCallWrapper::GetWrapperFromIP(pUnk);
334     SimpleComCallWrapper* pSimpleWrap = pWrap->GetSimpleWrapper();
335     IUnknown *pOuter; 
336     if (pSimpleWrap  && (pOuter = pSimpleWrap->GetOuter()) != NULL)
337     {
338         // If we are in process detach, we cannot safely call release on our outer.
339         if (g_fProcessDetach)
340             cbRef = 1;
341
342         cbRef = SafeReleasePreemp(pOuter);
343         LogInteropRelease(pOuter, cbRef, "Delegate Release to outer");
344     }
345     else
346     {
347         cbRef = pWrap->Release();
348     }
349
350     return cbRef;
351 } // Unknown_Release
352
353
354 // ---------------------------------------------------------------------------
355 //  for simple tearoffs
356 // ---------------------------------------------------------------------------
357 ULONG __stdcall
358 Unknown_AddRefSpecial_Internal(IUnknown* pUnk)
359 {
360     CONTRACTL
361     {
362         NOTHROW;
363         GC_TRIGGERS;
364         MODE_PREEMPTIVE;
365         PRECONDITION(CheckPointer(pUnk));
366         PRECONDITION(IsSimpleTearOff(pUnk));
367     }
368     CONTRACTL_END;
369
370     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
371     return pSimpleWrap->AddRefWithAggregationCheck();
372 } // Unknown_AddRefSpecial
373
374 // ---------------------------------------------------------------------------
375 // for simplecomcall wrappers, stdinterfaces such as IProvideClassInfo etc.
376 // ---------------------------------------------------------------------------
377 ULONG __stdcall
378 Unknown_ReleaseSpecial_Internal(IUnknown* pUnk)
379 {
380     CONTRACTL
381     {
382         NOTHROW;
383         GC_TRIGGERS;
384         MODE_PREEMPTIVE;
385         PRECONDITION(CheckPointer(pUnk));
386         PRECONDITION(IsSimpleTearOff(pUnk));
387     }
388     CONTRACTL_END;
389
390     HRESULT hr = S_OK;
391     ULONG cbRef = -1;
392
393     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
394         
395     // aggregation check
396     IUnknown *pOuter = pSimpleWrap->GetOuter();
397     if (pOuter != NULL)
398     {
399         cbRef = SafeReleasePreemp(pOuter);
400     }
401     else
402     {
403         cbRef = pSimpleWrap->Release();
404     }
405
406     return cbRef;
407 } // Unknown_Release
408
409
410 HRESULT __stdcall
411 Unknown_QueryInterface_IErrorInfo_Simple(IUnknown* pUnk, REFIID riid, void** ppv)
412 {
413     CONTRACTL
414     {
415         NOTHROW;
416         GC_NOTRIGGER;
417         MODE_PREEMPTIVE;
418         PRECONDITION(CheckPointer(pUnk));
419         PRECONDITION(IsInProcCCWTearOff(pUnk));
420         PRECONDITION(CheckPointer(ppv, NULL_OK));
421     }
422     CONTRACTL_END;
423
424     HRESULT hr = S_OK;
425
426     if (!ppv)
427         return E_POINTER;
428     *ppv = NULL;
429
430     EX_TRY
431     {
432         hr = E_NOINTERFACE;
433
434         _ASSERTE(!IsInnerUnknown(pUnk) && IsSimpleTearOff(pUnk));
435
436         SimpleComCallWrapper* pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
437         
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)
441         {
442             *ppv = pUnk;
443             pSimpleWrap->AddRef();
444             hr = S_OK;
445         }
446     }
447     EX_CATCH_HRESULT_NO_ERRORINFO(hr);
448
449     return hr;
450 }  // Unknown_QueryInterface_IErrorInfo_Simple
451
452 // ---------------------------------------------------------------------------
453 ULONG __stdcall
454 Unknown_ReleaseSpecial_IErrorInfo_Internal(IUnknown* pUnk)
455 {
456     CONTRACTL
457     {
458         NOTHROW;
459         GC_TRIGGERS;
460         MODE_PREEMPTIVE;
461         PRECONDITION(CheckPointer(pUnk));
462         PRECONDITION(IsSimpleTearOff(pUnk));
463     }
464     CONTRACTL_END;
465
466     ULONG cbRef = -1;
467
468     EX_TRY
469         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
470         cbRef = pSimpleWrap->Release();
471     EX_CATCH
472     EX_END_CATCH(SwallowAllExceptions)
473
474     return cbRef;
475 }
476
477
478 // ---------------------------------------------------------------------------
479 //  Interface IProvideClassInfo
480 // ---------------------------------------------------------------------------
481 HRESULT __stdcall 
482 ClassInfo_GetClassInfo(IUnknown* pUnk, ITypeInfo** ppTI)
483 {
484     CONTRACTL
485     {
486         DISABLED(NOTHROW);
487         GC_TRIGGERS;
488         MODE_ANY;
489         PRECONDITION(CheckPointer(pUnk));
490         PRECONDITION(CheckPointer(ppTI));
491     }
492     CONTRACTL_END;
493     
494     HRESULT hr = S_OK;
495
496     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
497     {
498         _ASSERTE(IsSimpleTearOff(pUnk));
499
500         SimpleComCallWrapper *pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
501
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())
505         {
506             // Retrieve the wrapper template for the class.
507             ComCallWrapperTemplate *pTemplate = ComCallWrapperTemplate::GetTemplate(pWrap->GetMethodTable());
508
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())
513             {
514                 for (pComMT = pTemplate->GetClassComMT(); pComMT && !pComMT->IsComVisible(); pComMT = pComMT->GetParentClassComMT());
515             }
516
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))
520             {
521                 IProvideClassInfo *pProvClassInfo = NULL;
522                 
523                 SyncBlock* pBlock = pWrap->GetSyncBlock();
524                 _ASSERTE(pBlock);
525
526                 RCWHolder pRCW(GetThread());
527                 RCWPROTECT_BEGIN(pRCW, pBlock);
528                 
529                 hr = pRCW->SafeQueryInterfaceRemoteAware(IID_IProvideClassInfo, (IUnknown**)&pProvClassInfo);
530                 if (SUCCEEDED(hr))
531                 {
532                     hr = pProvClassInfo->GetClassInfo(ppTI);
533                     ULONG cbRef = SafeRelease(pProvClassInfo);
534                     LogInteropRelease(pProvClassInfo, cbRef, "ClassInfo_GetClassInfo");
535                     IfFailThrow(hr);
536                 }
537
538                 RCWPROTECT_END(pRCW);
539             }
540         }
541
542         MethodTable* pClass = pWrap->GetMethodTable();
543         IfFailThrow(GetITypeInfoForEEClass(pClass, ppTI, true /* bClassInfo */));
544     }
545     END_EXTERNAL_ENTRYPOINT;
546
547     return hr;
548 }
549
550 //------------------------------------------------------------------------------------------
551 HRESULT GetDefaultInterfaceForCoclass(ITypeInfo *pTI, ITypeInfo **ppTIDef)
552 {
553     CONTRACTL
554     {
555         NOTHROW;
556         GC_TRIGGERS;
557         MODE_PREEMPTIVE;
558         PRECONDITION(CheckPointer(pTI));
559         PRECONDITION(CheckPointer(ppTIDef));
560     }
561     CONTRACTL_END;
562
563     HRESULT     hr;
564     TYPEATTRHolder pAttr(pTI); // Attributes on the first TypeInfo.
565
566     IfFailRet(pTI->GetTypeAttr(&pAttr));
567     if (pAttr->typekind != TKIND_COCLASS)
568         return TYPE_E_ELEMENTNOTFOUND;
569
570     int flags;
571
572     // If no impltype has the default flag, use 0.
573     int defaultInterface = 0;
574     for (int i = 0; i < pAttr->cImplTypes; ++i)
575     {
576         IfFailRet(pTI->GetImplTypeFlags(i, &flags));
577         if (flags & IMPLTYPEFLAG_FDEFAULT)
578         {
579             defaultInterface = i;
580             break;
581         }
582     }
583
584     HREFTYPE href;
585     IfFailRet(pTI->GetRefTypeOfImplType(defaultInterface, &href));
586     IfFailRet(pTI->GetRefTypeInfo(href, ppTIDef));
587
588     return S_OK;
589 } // HRESULT GetDefaultInterfaceForCoclass()
590
591 //------------------------------------------------------------------------------------------
592 // Helper to get the ITypeLib* for a Assembly.
593 HRESULT GetITypeLibForAssembly(_In_ Assembly *pAssembly, _Outptr_ ITypeLib **ppTlb)
594 {
595     CONTRACTL
596     {
597         NOTHROW;
598         GC_TRIGGERS;
599         MODE_PREEMPTIVE;
600         PRECONDITION(CheckPointer(pAssembly));
601         PRECONDITION(CheckPointer(ppTlb));
602     }
603     CONTRACTL_END;
604
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;
609
610     HRESULT hr;
611
612     // Check for cached copy.
613     ITypeLib *pTlb = pAssembly->GetTypeLib();
614     if (pTlb != nullptr)
615     {
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;
619
620         *ppTlb = pTlb;
621         return S_OK;
622     }
623
624     // Retrieve the guid for the assembly.
625     GUID assemblyGuid;
626     IfFailRet(GetTypeLibGuidForAssembly(pAssembly, &assemblyGuid));
627
628     // Retrieve the major and minor version number.
629     USHORT wMajor;
630     USHORT wMinor;
631     IfFailRet(GetTypeLibVersionForAssembly(pAssembly, &wMajor, &wMinor));
632
633     // Attempt to load the exact TypeLib
634     hr = LoadRegTypeLib(assemblyGuid, wMajor, wMinor, &pTlb);
635     if (FAILED(hr))
636     {
637         // Try just the Assembly version
638         IfFailRet(pAssembly->GetVersion(&wMajor, &wMinor, nullptr, nullptr));
639         hr = LoadRegTypeLib(assemblyGuid, wMajor, wMinor, &pTlb);
640         if (FAILED(hr))
641         {
642             // Try loading the highest registered version.
643             hr = LoadRegTypeLib(assemblyGuid, -1, -1, &pTlb);
644             if (FAILED(hr))
645                 pTlb = Assembly::InvalidTypeLib;
646         }
647     }
648
649     bool setCache = pAssembly->TrySetTypeLib(pTlb);
650     if (!setCache)
651     {
652         // Release the TypeLib that isn't going to be used
653         if (pTlb != Assembly::InvalidTypeLib)
654             pTlb->Release();
655
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);
659     }
660
661     if (FAILED(hr))
662     {
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;
665     }
666
667     *ppTlb = pTlb;
668     return S_OK;
669 } // HRESULT GetITypeLibForAssembly()
670
671 HRESULT GetITypeInfoForEEClass(MethodTable *pClass, ITypeInfo **ppTI, bool bClassInfo)
672 {
673     CONTRACTL
674     {
675         DISABLED(NOTHROW);
676         GC_TRIGGERS;
677         MODE_ANY;
678         INJECT_FAULT(return E_OUTOFMEMORY);
679     }
680     CONTRACTL_END;
681
682     GUID clsid;
683     GUID ciid;
684     ComMethodTable *pComMT              = NULL;
685     HRESULT                 hr          = S_OK;
686     SafeComHolder<ITypeLib> pITLB       = NULL;
687     SafeComHolder<ITypeInfo> pTI        = NULL;
688     SafeComHolder<ITypeInfo> pTIDef     = NULL;  // Default typeinfo of a coclass.
689     ComCallWrapperTemplate *pTemplate   = NULL;
690
691     if (pClass->IsProjectedFromWinRT() || pClass->IsExportedToWinRT())
692     {
693         // ITypeInfo is not used in the WinRT world
694         return E_NOTIMPL;
695     }
696
697     GCX_PREEMP();
698
699     // Get the typeinfo.
700     if (bClassInfo || pClass->IsInterface() || pClass->IsValueType() || pClass->IsEnum())
701     {
702         // If the class is not an interface then find the first COM visible IClassX in the hierarchy.
703         if (!pClass->IsInterface() && !pClass->IsComImport())
704         {
705             {
706                 // Retrieve the ComCallWrapperTemplate from the type.
707                 GCX_COOP();
708                 OBJECTREF pThrowable = NULL;
709                 GCPROTECT_BEGIN(pThrowable);
710                 {
711                     EX_TRY 
712                     {
713                         pTemplate = ComCallWrapperTemplate::GetTemplate(pClass);
714                         if (pTemplate->SupportsIClassX())
715                         {
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();
721                         }
722                     } 
723                     EX_CATCH
724                     {
725                         pThrowable = GET_THROWABLE();
726                     }
727                     EX_END_CATCH(SwallowAllExceptions);
728
729                     if (pThrowable != NULL)
730                         hr = SetupErrorInfo(pThrowable);
731                 }
732                 GCPROTECT_END();
733             }
734         
735             if (hr != S_OK) 
736                 goto ReturnHR;
737
738             if (!pTemplate)
739             {
740                 hr = E_OUTOFMEMORY;
741                 goto ReturnHR;
742             }
743
744             // If we haven't managed to find any visible IClassX's then return TYPE_E_ELEMENTNOTFOUND.
745             if (!pComMT)
746             {
747                 hr = TYPE_E_ELEMENTNOTFOUND;
748                 goto ReturnHR;
749             }
750
751             // Use the type of the first visible IClassX.
752             pClass = pComMT->GetMethodTable();
753         }
754
755         // Retrieve the ITypeLib for the assembly containing the type.
756         IfFailGo(GetITypeLibForAssembly(pClass->GetAssembly(), &pITLB));
757
758         // Get the GUID of the desired TypeRef.
759         IfFailGo(pClass->GetGuidNoThrow(&clsid, TRUE));
760
761         // Retrieve the ITypeInfo from the ITypeLib.
762         IfFailGo(pITLB->GetTypeInfoOfGuid(clsid, ppTI));
763     }
764     else if (pClass->IsComImport())
765     {   
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));
771
772         *ppTI = pTIDef;
773         pTIDef.SuppressRelease();
774     }
775     else
776     {
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));
781         switch (DefItfType)
782         {
783             case DefaultInterfaceType_Explicit:
784             {
785                 _ASSERTE(!hndDefItfClass.IsNull());
786                 _ASSERTE(hndDefItfClass.IsInterface());
787                 hr = GetITypeInfoForEEClass(hndDefItfClass.GetMethodTable(), ppTI, false /* bClassInfo */);
788                 break;
789             }
790
791             case DefaultInterfaceType_AutoDispatch:
792             case DefaultInterfaceType_AutoDual:
793             {
794                 _ASSERTE(!hndDefItfClass.IsNull());
795                 _ASSERTE(!hndDefItfClass.IsInterface());
796
797                 PTR_MethodTable itfClassMT = hndDefItfClass.GetMethodTable();
798
799                 // Retrieve the ITypeLib for the assembly containing the type.
800                 IfFailGo(GetITypeLibForAssembly(itfClassMT->GetAssembly(), &pITLB));
801
802                 // Get the GUID of the desired TypeRef.
803                 IfFailGo(itfClassMT->GetGuidNoThrow(&clsid, TRUE));
804         
805                 // Generate the IClassX IID from the class.
806                 TryGenerateClassItfGuid(hndDefItfClass, &ciid);
807         
808                 hr = pITLB->GetTypeInfoOfGuid(ciid, ppTI);
809                 break;
810             }
811
812             case DefaultInterfaceType_IUnknown:
813             case DefaultInterfaceType_BaseComClass:
814             {
815                 // @PERF: Optimize this.
816                 IfFailGo(LoadRegTypeLib(LIBID_STDOLE2, -1, -1, 0, &pITLB));
817                 IfFailGo(pITLB->GetTypeInfoOfGuid(IID_IUnknown, ppTI));
818                 hr = S_USEIUNKNOWN;
819                 break;
820             }
821
822             default:
823             {
824                 _ASSERTE(!"Invalid default interface type!");
825                 hr = E_FAIL;
826                 break;
827             }
828         }
829     }
830
831 ErrExit:
832     if (*ppTI == NULL)
833     {
834         if (!FAILED(hr))
835             hr = E_FAIL;
836     }
837
838 ReturnHR:
839     return hr;
840 } // HRESULT GetITypeInfoForEEClass()
841
842 // Returns a NON-ADDREF'd ITypeInfo.
843 HRESULT GetITypeInfoForMT(ComMethodTable *pMT, ITypeInfo **ppTI)
844 {
845     CONTRACTL
846     {
847         NOTHROW;
848         GC_TRIGGERS;
849         MODE_PREEMPTIVE;
850         PRECONDITION(CheckPointer(pMT));
851         PRECONDITION(CheckPointer(ppTI));
852     }
853     CONTRACTL_END;
854
855     HRESULT     hr = S_OK;              // A result.
856     ITypeInfo   *pTI;                   // The ITypeInfo.
857     
858     pTI = pMT->GetITypeInfo();
859
860     if (pTI == 0)
861     {
862         MethodTable *pClass = pMT->GetMethodTable();
863
864         hr = GetITypeInfoForEEClass(pClass, &pTI);
865
866         if (SUCCEEDED(hr))
867         {
868             pMT->SetITypeInfo(pTI);
869             SafeReleasePreemp(pTI);
870         }
871     }
872
873     *ppTI = pTI;
874     return hr;
875 }
876
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
880
881 IErrorInfo *GetSupportedErrorInfo(IUnknown *iface, REFIID riid, BOOL checkForIRestrictedErrInfo)
882 {
883     CONTRACTL
884     {
885         THROWS;
886         GC_TRIGGERS;
887         MODE_ANY;
888         INJECT_FAULT(COMPlusThrowOM());
889         PRECONDITION(CheckPointer(iface));
890     }
891     CONTRACTL_END;
892
893     IErrorInfo *pRetErrorInfo = NULL;
894     BOOL bUseThisErrorInfo = FALSE;
895     
896     // This function must run in preemptive GC mode.
897     {
898         GCX_PREEMP();
899         HRESULT hr = S_OK;
900         SafeComHolderPreemp<IErrorInfo> pErrorInfo;
901
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);
905         IfFailThrow(hr);
906
907         // If we successfully retrieved an IErrorInfo, we need to verify if
908         // it is for the specifed interface.
909         if (hr == S_OK)
910         {
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");
916             if (SUCCEEDED(hr))
917             {
918                 hr = pSupport->InterfaceSupportsErrorInfo(riid);
919                 if (hr == S_OK)
920                 {
921                     // The IErrorInfo is indeed for the specified interface so return it.
922                     bUseThisErrorInfo = TRUE;
923                 }
924             }
925         }
926
927         if (!bUseThisErrorInfo && pErrorInfo != NULL && checkForIRestrictedErrInfo)
928         {
929
930             // Do we support IRestrictedErrorInfo?
931             SafeComHolderPreemp<IRestrictedErrorInfo> pRestrictedErrorInfo;
932             hr = SafeQueryInterfacePreemp(pErrorInfo, IID_IRestrictedErrorInfo, (IUnknown **) &pRestrictedErrorInfo);
933             LogInteropQI(pErrorInfo, IID_IRestrictedErrorInfo, hr, "IRestrictedErrorInfo");
934             if (SUCCEEDED(hr))
935             {
936
937                 // This is a WinRT IRestrictedErrorInfo scenario
938                 bUseThisErrorInfo = TRUE;    
939             }                
940         }
941
942         if (bUseThisErrorInfo)
943         {
944             pRetErrorInfo = pErrorInfo;
945             pErrorInfo.SuppressRelease();
946             pErrorInfo = NULL;        
947         }
948     }
949
950     return pRetErrorInfo;
951 }
952
953 // ---------------------------------------------------------------------------
954 //  Interface ISupportsErrorInfo
955 /// ---------------------------------------------------------------------------
956 HRESULT __stdcall 
957 SupportsErroInfo_IntfSupportsErrorInfo(IUnknown* pUnk, REFIID riid)
958 {
959     CONTRACTL
960     {
961         NOTHROW;
962         GC_NOTRIGGER;
963         MODE_ANY;
964         PRECONDITION(CheckPointer(pUnk));
965         PRECONDITION(IsSimpleTearOff(pUnk));
966     }
967     CONTRACTL_END;
968
969     // All interfaces support ErrorInfo
970     return S_OK;
971 }
972
973
974 // ---------------------------------------------------------------------------
975 //  Interface IErrorInfo
976 // %%Function: ErrorInfo_GetDescription
977 // ---------------------------------------------------------------------------
978 HRESULT __stdcall 
979 ErrorInfo_GetDescription(IUnknown* pUnk, BSTR* pbstrDescription)
980 {
981     CONTRACTL
982     {
983         DISABLED(NOTHROW);
984         GC_TRIGGERS;
985         MODE_PREEMPTIVE;
986         PRECONDITION(CheckPointer(pUnk));
987         PRECONDITION(IsSimpleTearOff(pUnk));
988         PRECONDITION(CheckPointer(pbstrDescription, NULL_OK));
989     }
990     CONTRACTL_END;
991     
992     HRESULT hr = S_OK;
993     SimpleComCallWrapper *pWrap = NULL;
994
995     if (pbstrDescription == NULL) 
996         IfFailGo(E_POINTER);
997
998     pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
999
1000     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1001     {
1002         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1003
1004         *pbstrDescription = pWrap->IErrorInfo_bstrDescription();
1005     }
1006     END_EXTERNAL_ENTRYPOINT;
1007
1008 ErrExit:
1009     return hr;
1010 }
1011
1012 // ---------------------------------------------------------------------------
1013 //  Interface IErrorInfo
1014 // %%Function: ErrorInfo_GetGUID
1015 // ---------------------------------------------------------------------------
1016 HRESULT __stdcall ErrorInfo_GetGUID(IUnknown* pUnk, GUID* pguid)
1017 {
1018     CONTRACTL
1019     {
1020         NOTHROW;
1021         GC_NOTRIGGER;
1022         MODE_PREEMPTIVE;
1023         PRECONDITION(CheckPointer(pUnk));
1024         PRECONDITION(IsSimpleTearOff(pUnk));
1025         PRECONDITION(CheckPointer(pguid, NULL_OK));
1026     }
1027     CONTRACTL_END;
1028     
1029     HRESULT hr = S_OK;
1030     SimpleComCallWrapper *pWrap = NULL;
1031
1032     if (pguid == NULL)
1033         return E_POINTER;
1034
1035     pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
1036
1037     *pguid = pWrap->IErrorInfo_guid();
1038
1039     return hr;
1040 }
1041
1042 // ---------------------------------------------------------------------------
1043 //  Interface IErrorInfo
1044 // %%Function: ErrorInfo_GetHelpContext
1045 // ---------------------------------------------------------------------------
1046 HRESULT _stdcall ErrorInfo_GetHelpContext(IUnknown* pUnk, DWORD* pdwHelpCtxt)
1047 {
1048     CONTRACTL
1049     {
1050         DISABLED(NOTHROW);
1051         GC_TRIGGERS;
1052         MODE_PREEMPTIVE;
1053         PRECONDITION(CheckPointer(pUnk));
1054         PRECONDITION(IsSimpleTearOff(pUnk));        
1055         PRECONDITION(CheckPointer(pdwHelpCtxt, NULL_OK));
1056     }
1057     CONTRACTL_END;
1058     
1059     HRESULT hr = S_OK;
1060     SimpleComCallWrapper *pWrap = NULL;
1061
1062     if (pdwHelpCtxt == NULL)
1063         return E_POINTER;
1064
1065     pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
1066
1067     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1068     {
1069         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1070
1071         *pdwHelpCtxt = pWrap->IErrorInfo_dwHelpContext();
1072     } 
1073     END_EXTERNAL_ENTRYPOINT;
1074
1075     return hr;
1076 }
1077
1078 // ---------------------------------------------------------------------------
1079 //  Interface IErrorInfo
1080 // %%Function: ErrorInfo_GetHelpFile
1081 // ---------------------------------------------------------------------------
1082 HRESULT __stdcall ErrorInfo_GetHelpFile(IUnknown* pUnk, BSTR* pbstrHelpFile)
1083 {
1084     CONTRACTL
1085     {
1086         DISABLED(NOTHROW);
1087         GC_TRIGGERS;
1088         MODE_PREEMPTIVE;
1089         PRECONDITION(CheckPointer(pUnk));
1090         PRECONDITION(IsSimpleTearOff(pUnk));        
1091         PRECONDITION(CheckPointer(pbstrHelpFile, NULL_OK));
1092     }
1093     CONTRACTL_END;
1094     
1095     HRESULT hr = S_OK;
1096     SimpleComCallWrapper *pWrap = NULL;
1097
1098     if (pbstrHelpFile == NULL)
1099         return E_POINTER;
1100
1101     pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
1102
1103     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1104     {
1105         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1106
1107         *pbstrHelpFile = pWrap->IErrorInfo_bstrHelpFile();
1108     }
1109     END_EXTERNAL_ENTRYPOINT;
1110
1111     return hr;
1112 }
1113
1114 // ---------------------------------------------------------------------------
1115 //  Interface IErrorInfo
1116 // %%Function: ErrorInfo_GetSource
1117 // ---------------------------------------------------------------------------
1118 HRESULT __stdcall ErrorInfo_GetSource(IUnknown* pUnk, BSTR* pbstrSource)
1119 {
1120     CONTRACTL
1121     {
1122         DISABLED(NOTHROW);
1123         GC_TRIGGERS;
1124         MODE_PREEMPTIVE;
1125         PRECONDITION(CheckPointer(pUnk));
1126         PRECONDITION(IsSimpleTearOff(pUnk));        
1127         PRECONDITION(CheckPointer(pbstrSource, NULL_OK));
1128     }
1129     CONTRACTL_END;
1130     
1131     HRESULT hr = S_OK;
1132     SimpleComCallWrapper *pWrap = NULL;
1133
1134     if (pbstrSource == NULL)
1135         return E_POINTER;
1136
1137     pWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
1138
1139     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1140     {
1141         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1142
1143         *pbstrSource = pWrap->IErrorInfo_bstrSource();
1144     }
1145     END_EXTERNAL_ENTRYPOINT;
1146
1147     return hr;
1148 }
1149
1150
1151 //------------------------------------------------------------------------------------------
1152 //  IDispatch methods that forward to the right implementation based on the flags set
1153 //  on the IClassX COM method table.
1154
1155 HRESULT __stdcall
1156 Dispatch_GetTypeInfoCount(IDispatch* pDisp, unsigned int *pctinfo)
1157 {
1158     CONTRACTL
1159     {
1160         NOTHROW;
1161         GC_TRIGGERS;
1162         MODE_PREEMPTIVE;
1163         PRECONDITION(CheckPointer(pDisp));
1164         PRECONDITION(IsInProcCCWTearOff(pDisp));        
1165         PRECONDITION(CheckPointer(pctinfo, NULL_OK));
1166     }
1167     CONTRACTL_END;
1168
1169     if (!pctinfo)
1170         return E_POINTER;
1171
1172     *pctinfo = 0;
1173
1174     ComMethodTable *pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1175     if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1176         if (pCMT->HasInvisibleParent())
1177             return E_NOTIMPL;
1178
1179     ITypeInfo *pTI; 
1180     HRESULT hr = GetITypeInfoForMT(pCMT, &pTI);
1181
1182     if (SUCCEEDED(hr))
1183     {
1184         hr = S_OK;
1185         *pctinfo = 1;
1186     }
1187
1188     return hr;
1189 }
1190
1191 HRESULT __stdcall
1192 Dispatch_GetTypeInfo(IDispatch* pDisp, unsigned int itinfo, LCID lcid, ITypeInfo **pptinfo)
1193 {
1194     CONTRACTL
1195     {
1196         NOTHROW;
1197         GC_TRIGGERS;
1198         MODE_PREEMPTIVE;
1199         PRECONDITION(CheckPointer(pDisp));
1200         PRECONDITION(IsInProcCCWTearOff(pDisp));        
1201         PRECONDITION(CheckPointer(pptinfo, NULL_OK));
1202     }
1203     CONTRACTL_END;
1204
1205     if (!pptinfo)
1206         return E_POINTER;
1207
1208     *pptinfo = NULL;
1209
1210     ComMethodTable *pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1211     if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1212         if (pCMT->HasInvisibleParent())
1213             return E_NOTIMPL;
1214
1215     if (NULL != itinfo)
1216     {
1217         return DISP_E_BADINDEX;
1218     }
1219
1220     HRESULT hr = GetITypeInfoForMT(pCMT, pptinfo);
1221     if (SUCCEEDED(hr))
1222     {
1223         // GetITypeInfoForMT() can return other success codes besides S_OK so 
1224         // we need to convert them to S_OK.
1225         hr = S_OK;
1226         SafeAddRefPreemp(*pptinfo);
1227     }
1228
1229     return hr;
1230 }
1231
1232 HRESULT __stdcall
1233 Dispatch_GetIDsOfNames(IDispatch* pDisp, REFIID riid, __in_ecount(cNames) OLECHAR **rgszNames, unsigned int cNames, LCID lcid, DISPID *rgdispid)
1234 {
1235     CONTRACTL
1236 {
1237         NOTHROW;
1238         GC_TRIGGERS;
1239         MODE_PREEMPTIVE;
1240         INJECT_FAULT(return E_OUTOFMEMORY);
1241         PRECONDITION(CheckPointer(pDisp));
1242         PRECONDITION(IsInProcCCWTearOff(pDisp));        
1243         PRECONDITION(CheckPointer(rgszNames, NULL_OK));
1244     }
1245     CONTRACTL_END;
1246
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())
1251             return E_NOTIMPL;
1252
1253     ComCallWrapperTemplate *pTemplate = MapIUnknownToWrapper(pDisp)->GetComCallWrapperTemplate();
1254     if (pTemplate->IsUseOleAutDispatchImpl())
1255     {
1256         return OleAutDispatchImpl_GetIDsOfNames(pDisp, riid, rgszNames, cNames, lcid, rgdispid);
1257     }
1258
1259     return InternalDispatchImpl_GetIDsOfNames(pDisp, riid, rgszNames, cNames, lcid, rgdispid);
1260 }
1261
1262 HRESULT __stdcall
1263 Dispatch_Invoke
1264     (
1265     IDispatch* pDisp,
1266     DISPID dispidMember,
1267     REFIID riid,
1268     LCID lcid,
1269     unsigned short wFlags,
1270     DISPPARAMS *pdispparams,
1271     VARIANT *pvarResult,
1272     EXCEPINFO *pexcepinfo,
1273     unsigned int *puArgErr
1274     )
1275 {
1276     CONTRACTL
1277     {
1278         THROWS; // InternalDispatchImpl_Invoke can throw if it encounters CE
1279         GC_TRIGGERS;
1280         MODE_PREEMPTIVE;
1281         INJECT_FAULT(return E_OUTOFMEMORY);
1282         PRECONDITION(CheckPointer(pDisp));
1283         PRECONDITION(IsInProcCCWTearOff(pDisp));        
1284     }
1285     CONTRACTL_END;
1286
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())
1291             return E_NOTIMPL;
1292
1293     ComCallWrapperTemplate *pTemplate = MapIUnknownToWrapper(pDisp)->GetComCallWrapperTemplate();
1294     if (pTemplate->IsUseOleAutDispatchImpl())
1295     {
1296         return OleAutDispatchImpl_Invoke(pDisp, dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
1297     }
1298
1299     return InternalDispatchImpl_Invoke(pDisp, dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
1300 }
1301
1302
1303 //------------------------------------------------------------------------------------------
1304 //  IDispatch methods for COM+ objects implemented internally using reflection.
1305
1306
1307 HRESULT __stdcall
1308 OleAutDispatchImpl_GetIDsOfNames
1309 (
1310     IDispatch* pDisp,
1311     REFIID riid,
1312     __in_ecount(cNames) OLECHAR **rgszNames,
1313     unsigned int cNames,
1314     LCID lcid,
1315     DISPID *rgdispid
1316 )
1317 {
1318     CONTRACTL
1319     {
1320         NOTHROW;
1321         GC_TRIGGERS;
1322         MODE_PREEMPTIVE;
1323         INJECT_FAULT(return E_OUTOFMEMORY);
1324         PRECONDITION(CheckPointer(pDisp));
1325         PRECONDITION(IsInProcCCWTearOff(pDisp));   
1326         PRECONDITION(CheckPointer(rgszNames));
1327     }
1328     CONTRACTL_END;
1329
1330     // Make sure that riid is IID_NULL.
1331     if (riid != IID_NULL)
1332         return DISP_E_UNKNOWNINTERFACE;
1333
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())
1338             return E_NOTIMPL;
1339
1340     ITypeInfo *pTI;
1341     HRESULT hr = GetITypeInfoForMT(pCMT, &pTI);
1342     if (FAILED(hr))
1343         return (hr);
1344
1345     hr = pTI->GetIDsOfNames(rgszNames, cNames, rgdispid);
1346     return hr;
1347 }
1348
1349 HRESULT __stdcall
1350 OleAutDispatchImpl_Invoke
1351     (
1352     IDispatch* pDisp,
1353     DISPID dispidMember,
1354     REFIID riid,
1355     LCID lcid,
1356     unsigned short wFlags,
1357     DISPPARAMS *pdispparams,
1358     VARIANT *pvarResult,
1359     EXCEPINFO *pexcepinfo,
1360     unsigned int *puArgErr
1361     )
1362 {
1363     CONTRACTL
1364     {
1365         NOTHROW;
1366         GC_TRIGGERS;
1367         MODE_PREEMPTIVE;
1368         PRECONDITION(CheckPointer(pDisp));
1369         PRECONDITION(IsInProcCCWTearOff(pDisp));
1370     }
1371     CONTRACTL_END;
1372     
1373     HRESULT hr = S_OK;
1374
1375     // Make sure that riid is IID_NULL.
1376     if (riid != IID_NULL)
1377         return DISP_E_UNKNOWNINTERFACE;
1378
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())
1383             return E_NOTIMPL;
1384
1385     ITypeInfo *pTI;
1386     hr = GetITypeInfoForMT(pCMT, &pTI);
1387     if (FAILED(hr)) 
1388         return hr;
1389
1390     EX_TRY
1391     {
1392         // If we have a basic or IClassX interface then we're going to invoke through
1393         //  the class interface.
1394         if (pCMT->IsIClassXOrBasicItf())
1395         {
1396             CCWHolder pCCW = ComCallWrapper::GetWrapperFromIP(pDisp);
1397             pDisp = (IDispatch*)pCCW->GetIClassXIP();
1398         }
1399
1400         hr = pTI->Invoke(pDisp, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
1401     }
1402     EX_CATCH
1403     {
1404         hr = GET_EXCEPTION()->GetHR();
1405     }
1406     EX_END_CATCH(SwallowAllExceptions);
1407
1408     return hr;
1409 }
1410
1411 HRESULT __stdcall
1412 InternalDispatchImpl_GetIDsOfNames (
1413     IDispatch* pDisp,
1414     REFIID riid,
1415     __in_ecount(cNames) OLECHAR **rgszNames,
1416     unsigned int cNames,
1417     LCID lcid,
1418     DISPID *rgdispid)
1419 {
1420     CONTRACTL
1421     {
1422         DISABLED(NOTHROW);
1423         GC_TRIGGERS;
1424         MODE_PREEMPTIVE;
1425         PRECONDITION(CheckPointer(pDisp));
1426         PRECONDITION(IsInProcCCWTearOff(pDisp));
1427     }
1428     CONTRACTL_END;
1429     
1430     HRESULT hr = S_OK;
1431     DispatchInfo *pDispInfo;
1432     SimpleComCallWrapper *pSimpleWrap;
1433
1434     // Validate the arguments.
1435     if (!rgdispid)
1436         return E_POINTER;
1437
1438     if (riid != IID_NULL)
1439         return DISP_E_UNKNOWNINTERFACE;
1440
1441     if (cNames < 1)
1442         return S_OK;
1443     else if (!rgszNames)
1444         return E_POINTER;
1445
1446     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1447     {
1448         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1449
1450         // This call is coming thru an interface that inherits from IDispatch.
1451         ComCallWrapper* pCCW = ComCallWrapper::GetStartWrapperFromIP(pDisp);
1452
1453         ComMethodTable* pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1454         if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1455             pCMT->CheckParentComVisibility(FALSE);
1456
1457         pSimpleWrap = pCCW->GetSimpleWrapper();
1458         pDispInfo = ComMethodTable::ComMethodTableFromIP(pDisp)->GetDispatchInfo();
1459
1460         // Attempt to find the member in the DispatchEx information.
1461         SString sName(rgszNames[0]);
1462         DispatchMemberInfo *pDispMemberInfo = pDispInfo->FindMember(sName, FALSE);
1463
1464         // Check to see if the member has been found.
1465         if (pDispMemberInfo)
1466         {
1467             // Get the DISPID of the member.
1468             rgdispid[0] = pDispMemberInfo->m_DispID;
1469
1470             // Get the ID's of the named arguments.
1471             if (cNames > 1)
1472                 hr = pDispMemberInfo->GetIDsOfParameters(rgszNames + 1, cNames - 1, rgdispid + 1, FALSE);
1473         }
1474         else
1475         {
1476             rgdispid[0] = DISPID_UNKNOWN;
1477             hr = DISP_E_UNKNOWNNAME;
1478         }
1479     }
1480     END_EXTERNAL_ENTRYPOINT;
1481
1482     return hr;
1483 }
1484
1485
1486 HRESULT __stdcall
1487 InternalDispatchImpl_Invoke
1488     (
1489     IDispatch* pDisp,
1490     DISPID dispidMember,
1491     REFIID riid,
1492     LCID lcid,
1493     unsigned short wFlags,
1494     DISPPARAMS *pdispparams,
1495     VARIANT *pvarResult,
1496     EXCEPINFO *pexcepinfo,
1497     unsigned int *puArgErr
1498     )
1499 {
1500     CONTRACTL
1501     {
1502         DISABLED(NOTHROW);
1503         GC_TRIGGERS;
1504         MODE_PREEMPTIVE;
1505         PRECONDITION(CheckPointer(pDisp));
1506         PRECONDITION(IsInProcCCWTearOff(pDisp));
1507     }
1508     CONTRACTL_END;
1509     
1510     DispatchInfo *pDispInfo;
1511     SimpleComCallWrapper *pSimpleWrap;
1512     HRESULT hr = S_OK;
1513
1514     // Check for valid input args that are not covered by DispatchInfo::InvokeMember.
1515     if (riid != IID_NULL)
1516         return DISP_E_UNKNOWNINTERFACE;
1517
1518     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1519     {
1520         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1521
1522         // This call is coming thru an interface that inherits form IDispatch.
1523         ComCallWrapper* pCCW = ComCallWrapper::GetStartWrapperFromIP(pDisp);
1524
1525         ComMethodTable* pCMT = ComMethodTable::ComMethodTableFromIP(pDisp);
1526         if (pCMT->IsIClassXOrBasicItf() && pCMT->GetClassInterfaceType() != clsIfNone)
1527             pCMT->CheckParentComVisibility(FALSE);
1528
1529         pSimpleWrap = pCCW->GetSimpleWrapper();
1530
1531         // Invoke the member.
1532         pDispInfo = ComMethodTable::ComMethodTableFromIP(pDisp)->GetDispatchInfo();
1533         hr = pDispInfo->InvokeMember(pSimpleWrap, dispidMember, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, NULL, puArgErr);
1534         
1535     }
1536     END_EXTERNAL_ENTRYPOINT_RETHROW_CORRUPTING_EXCEPTIONS; // This will ensure that entry points wont swallow CE and continue to let them propagate out.
1537
1538     return hr;
1539 }
1540
1541
1542 //------------------------------------------------------------------------------------------
1543 //      IDispatchEx methods for COM+ objects
1544
1545 // IDispatchEx::GetTypeInfoCount
1546 HRESULT __stdcall   DispatchEx_GetTypeInfoCount(IDispatch* pDisp, unsigned int *pctinfo)
1547 {
1548     CONTRACTL
1549     {
1550         DISABLED(NOTHROW);
1551         GC_TRIGGERS;
1552         MODE_PREEMPTIVE;
1553         PRECONDITION(CheckPointer(pDisp));
1554         PRECONDITION(IsSimpleTearOff(pDisp));
1555         PRECONDITION(CheckPointer(pctinfo, NULL_OK));
1556     }
1557     CONTRACTL_END;
1558     
1559     HRESULT hr = S_OK;
1560     ITypeInfo *pTI = NULL;
1561
1562     // Validate the arguments.
1563     if (!pctinfo)
1564         return E_POINTER;
1565
1566     // Initialize the count of type info's to 0.
1567     *pctinfo = 0;
1568
1569     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1570     {
1571         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1572
1573         // Retrieve the class ComMethodTable.
1574         ComMethodTable *pComMT = ComCallWrapperTemplate::SetupComMethodTableForClass(pSimpleWrap->GetMethodTable(), FALSE);
1575
1576         // Retrieve the ITypeInfo for the ComMethodTable.
1577         IfFailThrow(GetITypeInfoForMT(pComMT, &pTI));
1578
1579         // GetITypeInfoForMT() can return other success codes besides S_OK so 
1580         // we need to convert them to S_OK.
1581         hr = S_OK;
1582         *pctinfo = 1;
1583     }
1584     END_EXTERNAL_ENTRYPOINT;
1585
1586     return hr;
1587 }
1588
1589 // IDispatchEx::GetTypeInfo
1590 HRESULT __stdcall   DispatchEx_GetTypeInfo (
1591                                     IDispatch* pDisp,
1592                                     unsigned int itinfo,
1593                                     LCID lcid,
1594                                     ITypeInfo **pptinfo
1595                                     )
1596 {
1597     CONTRACTL
1598     {
1599         DISABLED(NOTHROW);
1600         GC_TRIGGERS;
1601         MODE_PREEMPTIVE;
1602         PRECONDITION(CheckPointer(pDisp));
1603         PRECONDITION(IsSimpleTearOff(pDisp));
1604         PRECONDITION(CheckPointer(pptinfo, NULL_OK));
1605     }
1606     CONTRACTL_END;
1607     
1608     HRESULT hr = S_OK;
1609
1610     // Validate the arguments.
1611     if (!pptinfo)
1612         return E_POINTER;
1613
1614     // Initialize the ITypeInfo pointer to NULL.
1615     *pptinfo = NULL;
1616
1617     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1618     {
1619         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1620
1621         // Retrieve the class ComMethodTable.
1622         ComMethodTable *pComMT = ComCallWrapperTemplate::SetupComMethodTableForClass(pSimpleWrap->GetMethodTable(), FALSE);
1623
1624         // Retrieve the ITypeInfo for the ComMethodTable.
1625         IfFailThrow(GetITypeInfoForMT(pComMT, pptinfo));
1626
1627         // GetITypeInfoForMT() can return other success codes besides S_OK so 
1628         // we need to convert them to S_OK.
1629         hr = S_OK;
1630         SafeAddRefPreemp(*pptinfo);
1631     }
1632     END_EXTERNAL_ENTRYPOINT;
1633
1634     return hr;
1635 }
1636
1637 // IDispatchEx::GetIDsofNames
1638 HRESULT __stdcall   DispatchEx_GetIDsOfNames (
1639                                     IDispatchEx* pDisp,
1640                                     REFIID riid,
1641                                     __in_ecount(cNames) OLECHAR **rgszNames,
1642                                     unsigned int cNames,
1643                                     LCID lcid,
1644                                     DISPID *rgdispid
1645                                     )
1646 {
1647     CONTRACTL
1648     {
1649         DISABLED(NOTHROW);
1650         GC_TRIGGERS;
1651         MODE_PREEMPTIVE;
1652         PRECONDITION(CheckPointer(pDisp));
1653         PRECONDITION(IsSimpleTearOff(pDisp));
1654         PRECONDITION(CheckPointer(rgdispid, NULL_OK));
1655     }
1656     CONTRACTL_END;
1657     
1658     HRESULT hr = S_OK;
1659
1660     // Validate the arguments.
1661     if (!rgdispid)
1662         return E_POINTER;
1663
1664     if (riid != IID_NULL)
1665         return DISP_E_UNKNOWNINTERFACE;
1666
1667     if (cNames < 1)
1668         return S_OK;
1669     else if (!rgszNames)
1670         return E_POINTER;
1671
1672     // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1673     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1674
1675     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1676     {
1677         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1678
1679         // Attempt to find the member in the DispatchEx information.
1680         DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1681
1682         SString sName(rgszNames[0]);
1683         DispatchMemberInfo *pDispMemberInfo = pDispExInfo->SynchFindMember(sName, FALSE);
1684
1685         // Check to see if the member has been found.
1686         if (pDispMemberInfo)
1687         {
1688             // Get the DISPID of the member.
1689             rgdispid[0] = pDispMemberInfo->m_DispID;
1690
1691             // Get the ID's of the named arguments.
1692             if (cNames > 1)
1693                 hr = pDispMemberInfo->GetIDsOfParameters(rgszNames + 1, cNames - 1, rgdispid + 1, FALSE);
1694         }
1695         else
1696         {
1697             rgdispid[0] = DISPID_UNKNOWN;
1698             hr = DISP_E_UNKNOWNNAME;
1699         }
1700     }
1701     END_EXTERNAL_ENTRYPOINT;
1702
1703     return hr;
1704 }
1705
1706 // IDispatchEx::Invoke
1707 HRESULT __stdcall   DispatchEx_Invoke (
1708                                     IDispatchEx* pDisp,
1709                                     DISPID dispidMember,
1710                                     REFIID riid,
1711                                     LCID lcid,
1712                                     unsigned short wFlags,
1713                                     DISPPARAMS *pdispparams,
1714                                     VARIANT *pvarResult,
1715                                     EXCEPINFO *pexcepinfo,
1716                                     unsigned int *puArgErr
1717                                     )
1718 {
1719     CONTRACTL
1720     {
1721         DISABLED(NOTHROW);
1722         GC_TRIGGERS;
1723         MODE_PREEMPTIVE;
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));
1730     }
1731     CONTRACTL_END;
1732     
1733     HRESULT hr = S_OK;
1734
1735     // Check for valid input args that are not covered by DispatchInfo::InvokeMember.
1736     if (riid != IID_NULL)
1737         return DISP_E_UNKNOWNINTERFACE;
1738
1739     // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1740     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1741
1742     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1743     {
1744         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1745
1746         // Invoke the member.
1747         DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1748         hr = pDispExInfo->SynchInvokeMember(pSimpleWrap, dispidMember, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, NULL, puArgErr);
1749     }
1750     END_EXTERNAL_ENTRYPOINT;
1751
1752     return hr;
1753 }
1754
1755 // IDispatchEx::DeleteMemberByDispID
1756 HRESULT __stdcall   DispatchEx_DeleteMemberByDispID (
1757                                     IDispatchEx* pDisp,
1758                                     DISPID id
1759                                     )
1760 {
1761     CONTRACTL
1762     {
1763         DISABLED(NOTHROW);
1764         GC_TRIGGERS;
1765         MODE_PREEMPTIVE;
1766         PRECONDITION(CheckPointer(pDisp));
1767         PRECONDITION(IsSimpleTearOff(pDisp));
1768     }
1769     CONTRACTL_END;
1770     
1771     HRESULT hr = S_OK;
1772
1773     // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1774     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1775
1776     DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1777
1778     // If the member does not support expando operations then we cannot remove the member.
1779     if (!pDispExInfo->SupportsExpando())
1780         return E_NOTIMPL;
1781
1782     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1783     {
1784         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1785
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);
1789         hr = S_OK;
1790     }
1791     END_EXTERNAL_ENTRYPOINT;
1792
1793     return hr;
1794 }
1795
1796 // IDispatchEx::DeleteMemberByName
1797 HRESULT __stdcall   DispatchEx_DeleteMemberByName (
1798                                     IDispatchEx* pDisp,
1799                                     BSTR bstrName,
1800                                     DWORD grfdex
1801                                     )
1802 {
1803     CONTRACTL
1804     {
1805         NOTHROW;
1806         GC_TRIGGERS;
1807         MODE_PREEMPTIVE;
1808         PRECONDITION(CheckPointer(pDisp));
1809         PRECONDITION(IsSimpleTearOff(pDisp));
1810     }
1811     CONTRACTL_END;
1812
1813     HRESULT hr = S_OK;
1814     DISPID DispID;
1815
1816     if (!bstrName)
1817         return E_POINTER;
1818
1819     // The only two supported flags are fdexNameCaseSensitive and fdexNameCaseInsensitive.
1820     if (grfdex & ~(fdexNameCaseSensitive | fdexNameCaseInsensitive))
1821         return E_INVALIDARG;
1822
1823     // Ensure both fdexNameCaseSensitive and fdexNameCaseInsensitive aren't both set.
1824     if ((grfdex & (fdexNameCaseSensitive | fdexNameCaseInsensitive)) == (fdexNameCaseSensitive | fdexNameCaseInsensitive))
1825         return E_INVALIDARG;
1826
1827     // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1828     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1829     DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1830
1831     // If the member does not support expando operations then we cannot remove the member.
1832     if (!pDispExInfo->SupportsExpando())
1833         return E_NOTIMPL;
1834
1835     // Simply find the associated DISPID and delegate the call to DeleteMemberByDispID.
1836     hr = DispatchEx_GetDispID(pDisp, bstrName, grfdex, &DispID);
1837     if (SUCCEEDED(hr))
1838         hr = DispatchEx_DeleteMemberByDispID(pDisp, DispID);
1839
1840     return hr;
1841 }
1842
1843 // IDispatchEx::GetDispID
1844 HRESULT __stdcall   DispatchEx_GetDispID (
1845                                     IDispatchEx* pDisp,
1846                                     BSTR bstrName,
1847                                     DWORD grfdex,
1848                                     DISPID *pid
1849                                     )
1850 {
1851     CONTRACTL
1852     {
1853         DISABLED(NOTHROW);
1854         GC_TRIGGERS;
1855         MODE_PREEMPTIVE;
1856         PRECONDITION(CheckPointer(pDisp));
1857         PRECONDITION(CheckPointer(bstrName, NULL_OK));
1858         PRECONDITION(IsSimpleTearOff(pDisp));
1859         PRECONDITION(CheckPointer(pid, NULL_OK));
1860     }
1861     CONTRACTL_END;
1862     
1863     HRESULT hr = S_OK;
1864     SimpleComCallWrapper *pSimpleWrap;
1865     DispatchExInfo *pDispExInfo;
1866
1867     // Validate the arguments.
1868     if (!pid || !bstrName)
1869         return E_POINTER;
1870
1871     // We don't support fdexNameImplicit, but let the search continue anyway
1872
1873     // Ensure both fdexNameCaseSensitive and fdexNameCaseInsensitive aren't both set.
1874     if ((grfdex & (fdexNameCaseSensitive | fdexNameCaseInsensitive)) == (fdexNameCaseSensitive | fdexNameCaseInsensitive))
1875         return E_INVALIDARG;
1876
1877     // Initialize the pid to DISPID_UNKNOWN before we start.
1878     *pid = DISPID_UNKNOWN;
1879
1880     // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1881     pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1882
1883     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1884     {
1885         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1886
1887         // Attempt to find the member in the DispatchEx information.
1888         pDispExInfo = pSimpleWrap->GetDispatchExInfo();
1889
1890         SString sName(bstrName);
1891         DispatchMemberInfo *pDispMemberInfo = pDispExInfo->SynchFindMember(sName, grfdex & fdexNameCaseSensitive);
1892
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)
1896         {
1897             if (grfdex & fdexNameEnsure)
1898             {
1899                 if (pDispExInfo->SupportsExpando())
1900                 {
1901                     pDispMemberInfo = pDispExInfo->AddMember(sName, grfdex);
1902                     if (!pDispMemberInfo)
1903                         hr = E_UNEXPECTED;
1904                 }
1905                 else
1906                 {
1907                     hr = E_NOTIMPL;
1908                 }
1909             }
1910             else
1911             {
1912                 hr = DISP_E_UNKNOWNNAME;
1913             }
1914         }
1915
1916         // Set the return DISPID if the member has been found.
1917         if (pDispMemberInfo)
1918             *pid = pDispMemberInfo->m_DispID;
1919     }
1920     END_EXTERNAL_ENTRYPOINT;
1921
1922     return hr;
1923 }
1924
1925 // IDispatchEx::GetMemberName
1926 HRESULT __stdcall   DispatchEx_GetMemberName (
1927                                     IDispatchEx* pDisp,
1928                                     DISPID id,
1929                                     BSTR *pbstrName
1930                                     )
1931 {
1932     CONTRACTL
1933     {
1934         DISABLED(NOTHROW);
1935         GC_TRIGGERS;
1936         MODE_PREEMPTIVE;
1937         PRECONDITION(CheckPointer(pDisp));
1938         PRECONDITION(IsSimpleTearOff(pDisp));
1939         PRECONDITION(CheckPointer(pbstrName, NULL_OK));
1940     }
1941     CONTRACTL_END;
1942     
1943     HRESULT hr = S_OK;
1944
1945     // Validate the arguments.
1946     if (!pbstrName)
1947         return E_POINTER;
1948
1949     // Initialize the pbstrName to NULL before we start.
1950     *pbstrName = NULL;
1951
1952     // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
1953     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
1954
1955     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
1956     {
1957         GCX_COOP_THREAD_EXISTS(GET_THREAD());
1958
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);
1962
1963         // If the member does not exist then we return DISP_E_MEMBERNOTFOUND.
1964         if (!pDispMemberInfo || !pDispMemberInfo->GetMemberInfoObject())
1965         {
1966             hr = DISP_E_MEMBERNOTFOUND;
1967         }
1968         else
1969         {
1970             // Copy the name into the output string.
1971             *pbstrName = SysAllocString(pDispMemberInfo->m_strName);
1972         }
1973     }
1974     END_EXTERNAL_ENTRYPOINT;
1975
1976     return hr;
1977 }
1978
1979 // IDispatchEx::GetMemberProperties
1980 HRESULT __stdcall   DispatchEx_GetMemberProperties (
1981                                     IDispatchEx* pDisp,
1982                                     DISPID id,
1983                                     DWORD grfdexFetch,
1984                                     DWORD *pgrfdex
1985                                     )
1986 {
1987     CONTRACTL
1988     {
1989         DISABLED(NOTHROW);
1990         GC_TRIGGERS;
1991         MODE_PREEMPTIVE;
1992         PRECONDITION(CheckPointer(pDisp));
1993         PRECONDITION(IsSimpleTearOff(pDisp));
1994         PRECONDITION(CheckPointer(pgrfdex, NULL_OK));
1995     }
1996     CONTRACTL_END;
1997     
1998     HRESULT hr = S_OK;
1999
2000     // Validate the arguments.
2001     if (!pgrfdex)
2002         return E_POINTER;
2003
2004     // Initialize the return properties to 0.
2005     *pgrfdex = 0;
2006
2007     EnumMemberTypes MemberType;
2008
2009     // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
2010     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
2011
2012     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2013     {
2014         GCX_COOP_THREAD_EXISTS(GET_THREAD());
2015
2016         DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
2017         OBJECTREF MemberInfoObj = NULL;
2018         GCPROTECT_BEGIN(MemberInfoObj)
2019         {
2020             // Do a lookup in the hashtable to find the DispatchMemberInfo for the DISPID.
2021             DispatchMemberInfo *pDispMemberInfo = pDispExInfo->SynchFindMember(id);
2022
2023             // If the member does not exist then we return DISP_E_MEMBERNOTFOUND.
2024             if (!pDispMemberInfo || (MemberInfoObj = pDispMemberInfo->GetMemberInfoObject()) == NULL)
2025             {
2026                 hr = DISP_E_MEMBERNOTFOUND;
2027             }
2028             else
2029             {
2030                 // Retrieve the type of the member.
2031                 MemberType = pDispMemberInfo->GetMemberType();
2032
2033                 // Retrieve the member properties based on the type of the member.
2034                 switch (MemberType)
2035                 {
2036                     case Field:
2037                     {
2038                         *pgrfdex = fdexPropCanGet | 
2039                                    fdexPropCanPut | 
2040                                    fdexPropCannotPutRef | 
2041                                    fdexPropCannotCall | 
2042                                    fdexPropCannotConstruct |
2043                                    fdexPropCannotSourceEvents;
2044                         break;
2045                     }
2046
2047                     case Property:
2048                     {
2049                         BOOL bCanRead = FALSE;
2050                         BOOL bCanWrite = FALSE;
2051
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);
2056
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);
2061
2062                         // Check to see if the property can be read.
2063                         ARG_SLOT CanReadArgs[] =
2064                         { 
2065                             ObjToArgSlot(MemberInfoObj)
2066                         };
2067                         
2068                         bCanRead = canRead.Call_RetBool(CanReadArgs);
2069
2070                         // Check to see if the property can be written to.
2071                         ARG_SLOT CanWriteArgs[] =
2072                         { 
2073                             ObjToArgSlot(MemberInfoObj)
2074                         };
2075                         
2076                         bCanWrite = canWrite.Call_RetBool(CanWriteArgs);
2077
2078                         *pgrfdex = (bCanRead ? fdexPropCanGet : fdexPropCannotGet) |
2079                                    (bCanWrite ? fdexPropCanPut : fdexPropCannotPut) |
2080                                    fdexPropCannotPutRef | 
2081                                    fdexPropCannotCall | 
2082                                    fdexPropCannotConstruct |
2083                                    fdexPropCannotSourceEvents;
2084                         break;
2085                     }
2086
2087                     case Method:
2088                     {
2089                         *pgrfdex = fdexPropCannotGet | 
2090                                    fdexPropCannotPut | 
2091                                    fdexPropCannotPutRef | 
2092                                    fdexPropCanCall | 
2093                                    fdexPropCannotConstruct |
2094                                    fdexPropCannotSourceEvents;
2095                         break;
2096                     }
2097
2098                     default:
2099                     {
2100                         hr = E_UNEXPECTED;
2101                         break;
2102                     }
2103                 }
2104
2105                 // Mask out the unwanted properties.
2106                 *pgrfdex &= grfdexFetch;
2107             }
2108         }
2109         GCPROTECT_END();
2110     }
2111     END_EXTERNAL_ENTRYPOINT;
2112
2113     return hr;
2114 }
2115
2116 // IDispatchEx::GetNameSpaceParent
2117 HRESULT __stdcall   DispatchEx_GetNameSpaceParent (
2118                                     IDispatchEx* pDisp,
2119                                     IUnknown **ppunk
2120                                     )
2121 {
2122     CONTRACTL
2123     {
2124         NOTHROW;
2125         GC_NOTRIGGER;
2126         MODE_PREEMPTIVE;
2127         PRECONDITION(CheckPointer(pDisp));
2128         PRECONDITION(IsSimpleTearOff(pDisp));
2129         PRECONDITION(CheckPointer(ppunk, NULL_OK));
2130     }
2131     CONTRACTL_END;
2132
2133     // Validate the arguments.
2134     if (!ppunk)
2135         return E_POINTER;
2136
2137     // @TODO (DM): Implement this.
2138     *ppunk = NULL;
2139     return E_NOTIMPL;
2140 }
2141
2142
2143 // IDispatchEx::GetNextDispID
2144 HRESULT __stdcall   DispatchEx_GetNextDispID (
2145                                     IDispatchEx* pDisp,
2146                                     DWORD grfdex,
2147                                     DISPID id,
2148                                     DISPID *pid
2149                                     )
2150 {
2151     CONTRACTL
2152     {
2153         DISABLED(NOTHROW);
2154         GC_TRIGGERS;
2155         MODE_PREEMPTIVE;
2156         PRECONDITION(CheckPointer(pDisp));
2157         PRECONDITION(IsSimpleTearOff(pDisp));
2158         PRECONDITION(CheckPointer(pid, NULL_OK));
2159     }
2160     CONTRACTL_END;
2161     
2162     DispatchMemberInfo *pNextMember = NULL;
2163     HRESULT hr = S_OK;
2164
2165     // Validate the arguments.
2166     if (!pid)
2167         return E_POINTER;
2168
2169     // The only two supported flags are fdexEnumDefault and fdexEnumAll.
2170     if (grfdex & ~(fdexEnumDefault | fdexEnumAll))
2171         return E_INVALIDARG;
2172
2173     // Initialize the pid to DISPID_UNKNOWN.
2174     *pid = DISPID_UNKNOWN;
2175
2176     // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
2177     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
2178
2179     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2180     {
2181         GCX_COOP_THREAD_EXISTS(GET_THREAD());
2182
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();
2187         else
2188             pNextMember = pDispExInfo->GetNextMember(id);
2189
2190         // If we have found a member that has not been deleted then return its DISPID.
2191         if (pNextMember)
2192         {
2193             *pid = pNextMember->m_DispID;
2194             hr = S_OK;
2195         }
2196         else
2197         {
2198             hr = S_FALSE;
2199         }
2200     }
2201     END_EXTERNAL_ENTRYPOINT;
2202
2203     return hr;
2204 }
2205
2206
2207 // IDispatchEx::InvokeEx
2208 HRESULT __stdcall   DispatchEx_InvokeEx (
2209                                     IDispatchEx* pDisp,
2210                                     DISPID id,
2211                                     LCID lcid,
2212                                     WORD wFlags,
2213                                     DISPPARAMS *pdp,
2214                                     VARIANT *pVarRes, 
2215                                     EXCEPINFO *pei, 
2216                                     IServiceProvider *pspCaller 
2217                                     )
2218 {
2219     CONTRACTL
2220     {
2221         DISABLED(NOTHROW);
2222         GC_TRIGGERS;
2223         MODE_PREEMPTIVE;
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));
2230     }
2231     CONTRACTL_END;
2232     
2233     HRESULT hr = S_OK;
2234     
2235     // Retrieve the dispatch info and the simpler wrapper for this IDispatchEx.
2236     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pDisp);
2237     DispatchExInfo *pDispExInfo = pSimpleWrap->GetDispatchExInfo();
2238
2239     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2240     {
2241         GCX_COOP_THREAD_EXISTS(GET_THREAD());
2242
2243         // Invoke the member.
2244         hr = pDispExInfo->SynchInvokeMember(pSimpleWrap, id, lcid, wFlags, pdp, pVarRes, pei, pspCaller, NULL);
2245     }
2246     END_EXTERNAL_ENTRYPOINT;
2247
2248     return hr;
2249 }
2250
2251 HRESULT __stdcall Inspectable_GetIIDs (
2252                                     IInspectable *pInsp,
2253                                     ULONG *iidCount,
2254                                     IID **iids)
2255 {
2256     CONTRACTL
2257     {
2258         NOTHROW;
2259         GC_NOTRIGGER;
2260         MODE_PREEMPTIVE;
2261         PRECONDITION(CheckPointer(pInsp));
2262         PRECONDITION(IsInProcCCWTearOff(pInsp));        
2263     }
2264     CONTRACTL_END;
2265
2266     HRESULT hr = S_OK;
2267
2268     if (iidCount == NULL || iids == NULL)
2269         return E_POINTER;
2270
2271     *iidCount = 0;
2272     *iids = NULL;
2273
2274     // Either it is ICustomPropertyProvider or IWeakReferenceSource
2275     ComCallWrapper *pWrap = MapIUnknownToWrapper(pInsp);
2276
2277     ComCallWrapperTemplate *pTemplate = pWrap->GetComCallWrapperTemplate();
2278
2279     ULONG numInterfaces = pTemplate->GetNumInterfaces();
2280
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++)
2285     {
2286         ComMethodTable *pComMT = pTemplate->GetComMTForIndex(i);
2287         
2288         // Skip any managed WinRT interface that is IID_ICustomPropertyProvider
2289         if (pComMT != NULL && pComMT->GetInterfaceType() == ifInspectable && 
2290             !IsEqualGUID(pComMT->GetIID(), IID_ICustomPropertyProvider))
2291         {
2292             numInspectables++;
2293         }
2294     }
2295
2296     
2297     // we shouldn't ever come here if the CCW does not support IInspectable
2298     _ASSERTE(numInspectables > 0);
2299
2300     // as per the spec, make sure *iidCount is set even if the allocation fails
2301     *iidCount = numInspectables;
2302
2303     S_UINT32 cbAlloc = S_UINT32(numInspectables) * S_UINT32(sizeof(IID));
2304     if (cbAlloc.IsOverflow())
2305         return E_OUTOFMEMORY;
2306
2307     NewArrayHolder<IID> result = (IID *)CoTaskMemAlloc(cbAlloc.Value());
2308     if (result == NULL)
2309         return E_OUTOFMEMORY;
2310     
2311     // now fill out the output array with IIDs
2312     result[0] = IID_ICustomPropertyProvider;
2313     
2314     ULONG index = 1;
2315     for (ULONG i = 0; i < numInterfaces; i++)
2316     {
2317         ComMethodTable *pComMT = pTemplate->GetComMTForIndex(i);
2318
2319         // Skip any managed WinRT interface that is IID_ICustomPropertyProvider
2320         if (pComMT != NULL && pComMT->GetInterfaceType() == ifInspectable &&
2321             !IsEqualGUID(pComMT->GetIID(), IID_ICustomPropertyProvider))
2322         {
2323             result[index] = pComMT->GetIID();
2324             index++;
2325         }
2326     }
2327     _ASSERTE(index == numInspectables);
2328
2329     *iids = result.Extract();
2330     return hr;
2331 }
2332
2333
2334 HRESULT __stdcall Inspectable_GetRuntimeClassName(IInspectable *pInsp, HSTRING *className)
2335 {
2336     CONTRACTL
2337     {
2338         NOTHROW;
2339         GC_TRIGGERS;
2340         MODE_PREEMPTIVE;
2341         PRECONDITION(CheckPointer(pInsp));
2342         PRECONDITION(IsInProcCCWTearOff(pInsp));        
2343     }
2344     CONTRACTL_END;
2345
2346     if (className == NULL)
2347         return E_POINTER;
2348
2349     HRESULT hr = S_OK;
2350     ComCallWrapper *pWrap = MapIUnknownToWrapper(pInsp);
2351
2352     *className = NULL;
2353     
2354     MethodTable *pMT = pWrap->GetSimpleWrapper()->GetMethodTable();
2355     _ASSERTE(pMT != NULL);
2356
2357     EX_TRY
2358     {        
2359         StackSString strClassName;
2360         TypeHandle thManagedType;
2361         
2362         {
2363             GCX_COOP();
2364             OBJECTREF objref = NULL;
2365             
2366             GCPROTECT_BEGIN(objref);
2367             {
2368                 objref = pWrap->GetObjectRef();
2369                 thManagedType = objref->GetTypeHandle();
2370             }
2371             GCPROTECT_END();
2372         }
2373
2374         bool bIsPrimitive = false;
2375         if (WinRTTypeNameConverter::AppendWinRTTypeNameForManagedType(
2376             thManagedType,                                  // thManagedType
2377             strClassName,                                   // strWinRTTypeName
2378             TRUE,                                           // bForGetRuntimeClassName,
2379             &bIsPrimitive                                   // pbIsPrimitiveType
2380             )
2381             && !bIsPrimitive)
2382         {
2383             hr = WindowsCreateString(strClassName.GetUnicode(), strClassName.GetCount(), className);
2384         }
2385     }
2386     EX_CATCH
2387     {
2388         hr = GET_EXCEPTION()->GetHR();        
2389     }
2390     EX_END_CATCH(SwallowAllExceptions);
2391
2392     return hr;
2393 }
2394
2395 HRESULT __stdcall WeakReferenceSource_GetWeakReference (
2396                                     IWeakReferenceSource *pRefSrc,
2397                                     IWeakReference **weakReference)
2398 {
2399     CONTRACTL
2400     {
2401         NOTHROW;
2402         GC_TRIGGERS;
2403         MODE_PREEMPTIVE;
2404         PRECONDITION(CheckPointer(pRefSrc));
2405         PRECONDITION(IsInProcCCWTearOff(pRefSrc));
2406     }
2407     CONTRACTL_END;
2408
2409     if (weakReference == NULL)
2410         return E_INVALIDARG;
2411
2412     *weakReference = NULL;
2413
2414     HRESULT hr = S_OK;
2415     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2416     {
2417         SimpleComCallWrapper *pWrap = SimpleComCallWrapper::GetWrapperFromIP(pRefSrc);
2418
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());
2422     }
2423     END_EXTERNAL_ENTRYPOINT;
2424
2425     return hr;
2426 }
2427
2428
2429 // Helper to setup IMarshal 
2430 HRESULT GetSpecialMarshaler(IMarshal* pMarsh, SimpleComCallWrapper* pSimpleWrap, ULONG dwDestContext, IMarshal **ppMarshalRet)
2431 {
2432     CONTRACTL
2433     {
2434         NOTHROW;
2435         GC_TRIGGERS;
2436         MODE_PREEMPTIVE;
2437         PRECONDITION(CheckPointer(pMarsh, NULL_OK));
2438         PRECONDITION(CheckPointer(pSimpleWrap));
2439     }
2440     CONTRACTL_END;
2441
2442     HRESULT hr = S_OK;
2443
2444
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.
2448     
2449     SafeComHolderPreemp<IUnknown> pMarshalerObj = NULL;
2450     IfFailRet(CoCreateFreeThreadedMarshaler(NULL, &pMarshalerObj));
2451     return SafeQueryInterfacePreemp(pMarshalerObj, IID_IMarshal, (IUnknown**)ppMarshalRet);
2452 }
2453
2454
2455 //------------------------------------------------------------------------------------------
2456 //      IMarshal methods for COM+ objects
2457
2458 //------------------------------------------------------------------------------------------
2459
2460 HRESULT __stdcall Marshal_GetUnmarshalClass (
2461                             IMarshal* pMarsh,
2462                             REFIID riid, void * pv, ULONG dwDestContext, 
2463                             void * pvDestContext, ULONG mshlflags, 
2464                             LPCLSID pclsid)
2465 {
2466     CONTRACTL
2467     {
2468         NOTHROW;
2469         GC_TRIGGERS;
2470         MODE_PREEMPTIVE;
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));
2476     }
2477     CONTRACTL_END;
2478
2479     HRESULT hr = S_OK;
2480
2481     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pMarsh);
2482     
2483     // Prevent access to reflection over DCOM
2484     if(dwDestContext != MSHCTX_INPROC)
2485     {
2486         if(!pSimpleWrap->GetComCallWrapperTemplate()->IsSafeTypeForMarshalling())
2487         {
2488             LogInterop(W("Unmarshal class blocked for reflection types."));
2489             hr = E_NOINTERFACE;
2490             return hr;
2491         } 
2492     }
2493
2494     SafeComHolderPreemp<IMarshal> pMsh = NULL;
2495     hr = GetSpecialMarshaler(pMarsh, pSimpleWrap, dwDestContext, (IMarshal **)&pMsh);
2496     if (FAILED(hr))
2497         return hr;
2498     
2499     if (pMsh != NULL)
2500     { 
2501         hr = pMsh->GetUnmarshalClass (riid, pv, dwDestContext, pvDestContext, mshlflags, pclsid);
2502         return hr;
2503     }
2504
2505     // Use a statically allocated singleton class to do all unmarshalling.
2506     *pclsid = CLSID_ComCallUnmarshalV4;
2507
2508     return S_OK;
2509 }
2510
2511 HRESULT __stdcall Marshal_GetMarshalSizeMax (
2512                                 IMarshal* pMarsh,
2513                                 REFIID riid, void * pv, ULONG dwDestContext, 
2514                                 void * pvDestContext, ULONG mshlflags, 
2515                                 ULONG * pSize)
2516 {
2517     CONTRACTL
2518     {
2519         NOTHROW;
2520         GC_TRIGGERS;
2521         MODE_PREEMPTIVE;
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));
2527     }
2528     CONTRACTL_END;
2529
2530     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pMarsh);
2531
2532     SafeComHolderPreemp<IMarshal> pMsh = NULL;
2533     HRESULT hr = GetSpecialMarshaler(pMarsh, pSimpleWrap, dwDestContext, (IMarshal **)&pMsh);
2534     if (FAILED(hr))
2535         return hr;
2536
2537     if (pMsh != NULL)
2538     { 
2539         HRESULT hr = pMsh->GetMarshalSizeMax (riid, pv, dwDestContext, pvDestContext, mshlflags, pSize);
2540         return hr;
2541     }
2542
2543     *pSize = sizeof (IUnknown *) + sizeof (ULONG) + sizeof(GUID);
2544
2545     return S_OK;
2546 }
2547
2548 HRESULT __stdcall Marshal_MarshalInterface ( 
2549                         IMarshal* pMarsh,
2550                         LPSTREAM pStm, REFIID riid, void * pv,
2551                         ULONG dwDestContext, LPVOID pvDestContext,
2552                         ULONG mshlflags)
2553 {
2554     CONTRACTL
2555     {
2556         NOTHROW;
2557         GC_TRIGGERS;
2558         MODE_PREEMPTIVE;
2559         PRECONDITION(CheckPointer(pMarsh));
2560         PRECONDITION(IsSimpleTearOff(pMarsh));
2561         PRECONDITION(CheckPointer(pv));
2562         PRECONDITION(CheckPointer(pvDestContext, NULL_OK));
2563     }
2564     CONTRACTL_END;
2565
2566     ULONG cbRef;
2567     HRESULT hr = S_OK;
2568         
2569     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pMarsh);
2570     
2571     // Prevent access to reflection over DCOM
2572     if(dwDestContext != MSHCTX_INPROC)
2573     {
2574         if(!pSimpleWrap->GetComCallWrapperTemplate()->IsSafeTypeForMarshalling())
2575         {
2576             LogInterop(W("Marshal interface blocked for reflection types."));
2577             hr = E_NOINTERFACE;
2578             return hr;
2579         }
2580     }
2581
2582     SafeComHolderPreemp<IMarshal> pMsh = NULL;
2583     hr = GetSpecialMarshaler(pMarsh, pSimpleWrap, dwDestContext, (IMarshal **)&pMsh);
2584     if (FAILED(hr))
2585         return hr;
2586
2587     if (pMsh != NULL)
2588     { 
2589         hr = pMsh->MarshalInterface (pStm, riid, pv, dwDestContext, pvDestContext, mshlflags);
2590         return hr;
2591     }
2592
2593     // Write the raw IP into the marshalling stream.
2594     hr = pStm->Write (&pv, sizeof (pv), 0);
2595     if (FAILED (hr))
2596         return hr;
2597
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);
2601     if (FAILED (hr))
2602         return hr;
2603
2604     // Followed by the secret, which confirms that the pointer above can be trusted
2605     // because it originated from our runtime.
2606     hr = InitUnmarshalSecret();
2607     if (FAILED(hr))
2608         return hr;
2609
2610     hr = pStm->Write(g_UnmarshalSecret, sizeof(g_UnmarshalSecret), 0);
2611     if (FAILED(hr))
2612         return hr;
2613
2614     // We have now created an additional reference to the object.
2615     cbRef = SafeAddRefPreemp((IUnknown *)pv);
2616     LogInteropAddRef((IUnknown *)pv, cbRef, "MarshalInterface");
2617     
2618     return S_OK;
2619 }
2620
2621 HRESULT __stdcall Marshal_UnmarshalInterface (
2622                         IMarshal* pMarsh,
2623                         LPSTREAM pStm, REFIID riid, 
2624                         void ** ppvObj)
2625 {
2626     CONTRACTL
2627     {
2628         NOTHROW;
2629         GC_NOTRIGGER;
2630         MODE_PREEMPTIVE;
2631         PRECONDITION(CheckPointer(pMarsh));
2632         PRECONDITION(IsSimpleTearOff(pMarsh));
2633         PRECONDITION(CheckPointer(pStm, NULL_OK));
2634         PRECONDITION(CheckPointer(ppvObj, NULL_OK));
2635     }
2636     CONTRACTL_END;
2637
2638     // Unmarshal side only.
2639     return E_NOTIMPL;
2640 }
2641
2642 HRESULT __stdcall Marshal_ReleaseMarshalData (IMarshal* pMarsh, LPSTREAM pStm)
2643 {
2644     CONTRACTL
2645     {
2646         NOTHROW;
2647         GC_NOTRIGGER;
2648         MODE_PREEMPTIVE;
2649         PRECONDITION(CheckPointer(pMarsh));
2650         PRECONDITION(IsSimpleTearOff(pMarsh));
2651         PRECONDITION(CheckPointer(pStm, NULL_OK));
2652     }
2653     CONTRACTL_END;
2654
2655     // Unmarshal side only.
2656     return E_NOTIMPL;
2657 }
2658
2659 HRESULT __stdcall Marshal_DisconnectObject (IMarshal* pMarsh, ULONG dwReserved)
2660 {
2661     CONTRACTL
2662     {
2663         NOTHROW;
2664         GC_NOTRIGGER;
2665         MODE_PREEMPTIVE;
2666         PRECONDITION(CheckPointer(pMarsh));
2667         PRECONDITION(IsSimpleTearOff(pMarsh));
2668     }
2669     CONTRACTL_END;
2670
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
2673     // Release()'s it.
2674     return S_OK;
2675 }
2676
2677 //------------------------------------------------------------------------------------------
2678 //      IConnectionPointContainer methods for COM+ objects
2679 //------------------------------------------------------------------------------------------
2680
2681 // Enumerate all the connection points supported by the component.
2682 HRESULT __stdcall ConnectionPointContainer_EnumConnectionPoints(IUnknown* pUnk, 
2683                                                                 IEnumConnectionPoints **ppEnum)
2684 {
2685     CONTRACTL
2686     {
2687         DISABLED(NOTHROW);
2688         GC_TRIGGERS;
2689         MODE_PREEMPTIVE;
2690         PRECONDITION(CheckPointer(pUnk));
2691         PRECONDITION(CheckPointer(ppEnum, NULL_OK));
2692     }
2693     CONTRACTL_END;
2694     
2695     HRESULT hr = S_OK;
2696
2697     if (!ppEnum)
2698         return E_POINTER;
2699
2700     *ppEnum = NULL;
2701
2702     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2703     {
2704         _ASSERTE(IsSimpleTearOff(pUnk));
2705         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
2706         pSimpleWrap->EnumConnectionPoints(ppEnum);
2707     }
2708     END_EXTERNAL_ENTRYPOINT;
2709
2710     return hr;
2711 }
2712
2713 // Find a specific connection point based on the IID of the event interface.
2714 HRESULT __stdcall ConnectionPointContainer_FindConnectionPoint(IUnknown* pUnk, 
2715                                                                REFIID riid,
2716                                                                IConnectionPoint **ppCP)
2717 {
2718     CONTRACTL
2719     {
2720         DISABLED(NOTHROW);
2721         GC_TRIGGERS;
2722         MODE_PREEMPTIVE;
2723         PRECONDITION(CheckPointer(pUnk));
2724         PRECONDITION(CheckPointer(ppCP, NULL_OK));
2725     }
2726     CONTRACTL_END;
2727     
2728     HRESULT hr = S_OK;
2729
2730     if (!ppCP)
2731         return E_POINTER;
2732
2733     *ppCP = NULL;
2734
2735     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2736     {
2737         _ASSERTE(IsSimpleTearOff(pUnk));
2738         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
2739         if (!pSimpleWrap->FindConnectionPoint(riid, ppCP))
2740             hr = CONNECT_E_NOCONNECTION;
2741     }
2742     END_EXTERNAL_ENTRYPOINT;
2743
2744     return hr;
2745 }
2746
2747
2748 //------------------------------------------------------------------------------------------
2749 //      IObjectSafety methods for COM+ objects
2750 //------------------------------------------------------------------------------------------
2751
2752 HRESULT __stdcall ObjectSafety_GetInterfaceSafetyOptions(IUnknown* pUnk,
2753                                                          REFIID riid,
2754                                                          DWORD *pdwSupportedOptions,
2755                                                          DWORD *pdwEnabledOptions)
2756 {
2757     CONTRACTL
2758     {
2759         NOTHROW;
2760         GC_TRIGGERS;
2761         MODE_PREEMPTIVE;
2762         PRECONDITION(CheckPointer(pUnk));
2763         PRECONDITION(IsSimpleTearOff(pUnk));
2764         PRECONDITION(CheckPointer(pdwSupportedOptions, NULL_OK));
2765         PRECONDITION(CheckPointer(pdwEnabledOptions, NULL_OK));
2766     }
2767     CONTRACTL_END;
2768
2769     if (pdwSupportedOptions == NULL || pdwEnabledOptions == NULL)
2770         return E_POINTER;
2771
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");
2776     if (SUCCEEDED(hr))
2777     {
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);
2781         return S_OK;       
2782     }
2783     else
2784     {
2785         // We don't support this interface
2786         *pdwSupportedOptions = 0;
2787         *pdwEnabledOptions   = 0;       
2788         return E_NOINTERFACE;
2789     }
2790 }
2791
2792 HRESULT __stdcall ObjectSafety_SetInterfaceSafetyOptions(IUnknown* pUnk,
2793                                                          REFIID riid,
2794                                                          DWORD dwOptionSetMask,
2795                                                          DWORD dwEnabledOptions) 
2796 {
2797     CONTRACTL
2798     {
2799         NOTHROW;
2800         GC_TRIGGERS;
2801         MODE_PREEMPTIVE;
2802         PRECONDITION(CheckPointer(pUnk));
2803         PRECONDITION(IsSimpleTearOff(pUnk));
2804     }
2805     CONTRACTL_END;
2806
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");
2811     if (FAILED(hr))
2812         return hr;
2813
2814     if ((dwEnabledOptions & ~(INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACESAFE_FOR_UNTRUSTED_CALLER)) != 0)
2815         return E_FAIL;
2816
2817     return S_OK;
2818 }
2819
2820 HRESULT __stdcall ICustomPropertyProvider_GetProperty(IUnknown *pPropertyProvider, HSTRING hstrName, IUnknown **ppProperty)
2821 {
2822     CONTRACTL
2823     {
2824         NOTHROW;
2825         GC_TRIGGERS;
2826         MODE_PREEMPTIVE;
2827         PRECONDITION(CheckPointer(pPropertyProvider));
2828         PRECONDITION(IsSimpleTearOff(pPropertyProvider));
2829         PRECONDITION(CheckPointer(ppProperty, NULL_OK));
2830     }
2831     CONTRACTL_END;
2832
2833     if (ppProperty == NULL)
2834         return E_POINTER;
2835
2836     // Initialize [out] parameters
2837     *ppProperty = NULL;
2838     
2839     HRESULT hr;
2840     
2841     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2842     {   
2843         _ASSERTE(IsSimpleTearOff(pPropertyProvider));
2844         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pPropertyProvider);
2845         
2846         GCX_COOP();
2847         
2848         struct _gc {
2849                 OBJECTREF  TargetObj;
2850                 STRINGREF  StringRef;
2851                 OBJECTREF  RetVal;
2852         } gc;
2853         ZeroMemory(&gc, sizeof(gc));
2854         
2855         GCPROTECT_BEGIN(gc);
2856
2857         gc.TargetObj = pSimpleWrap->GetObjectRef();
2858         
2859         //
2860         // Marshal HSTRING to String object
2861         // NULL HSTRINGS are equivilent to empty strings
2862         //
2863         UINT32 cchString = 0;
2864         LPCWSTR pwszString = W("");
2865         if (hstrName != NULL)
2866         {
2867             pwszString = WindowsGetStringRawBuffer(hstrName, &cchString);
2868         }
2869             
2870         gc.StringRef = StringObject::NewString(pwszString, cchString);
2871
2872         //
2873         // Call ICustomPropertyProviderImpl.CreateProperty
2874         //        
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);
2879
2880         CALL_MANAGED_METHOD_RETREF(gc.RetVal, OBJECTREF, args);
2881
2882         if (gc.RetVal != NULL)
2883         {
2884             // The object is a CustomPropertyImpl. Get the ICustomProperty implementation from CCW and return that
2885             *ppProperty = GetComIPFromObjectRef(&gc.RetVal, MscorlibBinder::GetClass(CLASS__ICUSTOMPROPERTY));
2886         }
2887         
2888         GCPROTECT_END();
2889     }
2890     END_EXTERNAL_ENTRYPOINT;
2891     
2892     // Don't fail if property can't be found - just return S_OK and NULL property
2893     return S_OK;
2894 }
2895
2896 HRESULT __stdcall ICustomPropertyProvider_GetIndexedProperty(IUnknown *pPropertyProvider, 
2897                                                              HSTRING hstrName, 
2898                                                              TypeNameNative indexedParamType,
2899                                                              /* [out, retval] */ IUnknown **ppProperty)
2900 {
2901     CONTRACTL
2902     {
2903         NOTHROW;
2904         GC_TRIGGERS;
2905         MODE_PREEMPTIVE;
2906         PRECONDITION(CheckPointer(pPropertyProvider));
2907         PRECONDITION(IsSimpleTearOff(pPropertyProvider));
2908         PRECONDITION(CheckPointer(ppProperty, NULL_OK));
2909     }
2910     CONTRACTL_END;
2911
2912     if (ppProperty == NULL)
2913         return E_POINTER;
2914
2915     // Initialize [out] parameters
2916     *ppProperty = NULL;
2917     
2918     HRESULT hr;
2919     
2920     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2921     {   
2922         _ASSERTE(IsSimpleTearOff(pPropertyProvider));
2923         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pPropertyProvider);
2924
2925         GCX_COOP();
2926         
2927         struct _gc {
2928                 OBJECTREF  TargetObj;
2929                 STRINGREF  StringRef;
2930                 OBJECTREF  RetVal;
2931         } gc;
2932         ZeroMemory(&gc, sizeof(gc));
2933         
2934         GCPROTECT_BEGIN(gc);
2935         
2936         gc.TargetObj = pSimpleWrap->GetObjectRef();
2937                
2938         //
2939         // Marshal HSTRING to String object
2940         // NULL HSTRINGS are equivilent to empty strings
2941         //
2942         UINT32 cchString = 0;
2943         LPCWSTR pwszString = W("");
2944         if (hstrName != NULL)
2945         {
2946             pwszString = WindowsGetStringRawBuffer(hstrName, &cchString);
2947         }
2948             
2949         gc.StringRef = StringObject::NewString(pwszString, cchString);
2950         
2951         //
2952         // Call ICustomPropertyProviderImpl.CreateIndexedProperty
2953         //        
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);
2959
2960         CALL_MANAGED_METHOD_RETREF(gc.RetVal, OBJECTREF, args);
2961
2962         if (gc.RetVal != NULL)
2963         {
2964             // The object is a CustomPropertyImpl. Get the ICustomProperty implementation from CCW and return that
2965             *ppProperty = GetComIPFromObjectRef(&gc.RetVal, MscorlibBinder::GetClass(CLASS__ICUSTOMPROPERTY));
2966         }
2967         
2968         GCPROTECT_END();        
2969     }
2970     END_EXTERNAL_ENTRYPOINT;
2971
2972     // Don't fail if property can't be found - just return S_OK and NULL property
2973     return S_OK;
2974 }
2975
2976 HRESULT __stdcall ICustomPropertyProvider_GetStringRepresentation(IUnknown *pPropertyProvider,
2977                                                                   /* [out, retval] */ HSTRING *phstrStringRepresentation)
2978 {
2979     CONTRACTL
2980     {
2981         NOTHROW;
2982         GC_TRIGGERS;
2983         MODE_PREEMPTIVE;
2984         PRECONDITION(CheckPointer(pPropertyProvider));
2985         PRECONDITION(IsSimpleTearOff(pPropertyProvider));
2986         PRECONDITION(CheckPointer(phstrStringRepresentation, NULL_OK));
2987     }
2988     CONTRACTL_END;
2989
2990     if (phstrStringRepresentation == NULL)
2991         return E_POINTER;
2992
2993     // Initialize [out] parameters
2994     *phstrStringRepresentation = NULL;
2995
2996     HRESULT hr;
2997     
2998     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
2999     {   
3000         _ASSERTE(IsSimpleTearOff(pPropertyProvider));
3001         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pPropertyProvider);
3002
3003         GCX_COOP();
3004         
3005         struct _gc {
3006                 OBJECTREF  TargetObj;
3007                 STRINGREF  RetVal;
3008         } gc;
3009         ZeroMemory(&gc, sizeof(gc));
3010         
3011         GCPROTECT_BEGIN(gc);
3012         
3013         gc.TargetObj = pSimpleWrap->GetObjectRef(); 
3014
3015         //
3016         // Call IStringableHelper.ToString() to get string representation either from IStringable.ToString() or ToString()
3017         //
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);
3022
3023         //
3024         // Convert managed string to HSTRING
3025         // 
3026         if (gc.RetVal == NULL)
3027             *phstrStringRepresentation = NULL;
3028         else
3029             hr = ::WindowsCreateString(gc.RetVal->GetBuffer(), gc.RetVal->GetStringLength(), phstrStringRepresentation);
3030
3031         GCPROTECT_END();
3032         
3033     }
3034     END_EXTERNAL_ENTRYPOINT;
3035     
3036     return hr;
3037 }
3038                                                                   
3039 HRESULT __stdcall ICustomPropertyProvider_GetType(IUnknown *pPropertyProvider, 
3040                                                   /* [out, retval] */ TypeNameNative *pTypeIdentifier)
3041 {
3042     CONTRACTL
3043     {
3044         NOTHROW;
3045         GC_TRIGGERS;
3046         MODE_PREEMPTIVE;
3047         PRECONDITION(CheckPointer(pPropertyProvider));
3048         PRECONDITION(IsSimpleTearOff(pPropertyProvider));
3049         PRECONDITION(CheckPointer(pTypeIdentifier));
3050     }
3051     CONTRACTL_END;
3052
3053     if (pTypeIdentifier == NULL)
3054         return E_POINTER;
3055
3056     // Initialize [out] parameters
3057     ::ZeroMemory(pTypeIdentifier, sizeof(TypeNameNative));
3058     
3059     HRESULT hr;
3060     
3061     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
3062     {   
3063         _ASSERTE(IsSimpleTearOff(pPropertyProvider));
3064         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pPropertyProvider);
3065
3066         GCX_COOP();
3067         
3068         OBJECTREF  refTargetObj = NULL;
3069         GCPROTECT_BEGIN(refTargetObj);
3070         
3071         refTargetObj = pSimpleWrap->GetObjectRef(); 
3072
3073         //
3074         // Call ICustomPropertyProviderImpl.GetType()
3075         //
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);
3080
3081         CALL_MANAGED_METHOD_NORET(args);
3082
3083         GCPROTECT_END();
3084     }
3085     END_EXTERNAL_ENTRYPOINT;
3086     
3087     return S_OK;
3088 }
3089
3090 HRESULT __stdcall IStringable_ToString(IUnknown* pStringable,
3091                                                /* [out, retval] */ HSTRING* pResult)
3092 {
3093     CONTRACTL
3094     {
3095         NOTHROW;
3096         GC_TRIGGERS;
3097         MODE_PREEMPTIVE;
3098         PRECONDITION(CheckPointer(pStringable));
3099         PRECONDITION(IsSimpleTearOff(pStringable));
3100         PRECONDITION(CheckPointer(pResult, NULL_OK));
3101     }
3102     CONTRACTL_END;
3103
3104     if (pResult == NULL)
3105         return E_POINTER;
3106
3107     // Initialize [out] parameters
3108     *pResult = NULL;
3109
3110     HRESULT hr;
3111     
3112     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
3113     {   
3114         _ASSERTE(IsSimpleTearOff(pStringable));
3115         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pStringable);
3116
3117         GCX_COOP();
3118         
3119         struct _gc {
3120                 OBJECTREF  TargetObj;
3121                 STRINGREF  RetVal;
3122         } gc;
3123         ZeroMemory(&gc, sizeof(gc));
3124         
3125         GCPROTECT_BEGIN(gc);
3126         
3127         gc.TargetObj = pSimpleWrap->GetObjectRef(); 
3128         MethodDesc* pToStringMD = NULL;
3129
3130         MethodTable* pMT = gc.TargetObj->GetMethodTable();
3131
3132
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();
3136
3137         if (pMT != NULL && pMTIStringable != NULL && pMT->ImplementsInterface(pMTIStringable))
3138         {
3139             // Find the ToString() method of the interface.
3140             pToStringMD = MemberLoader::FindMethod(
3141                 pMTIStringable, 
3142                 "ToString",
3143                 &gsig_IM_RetStr);
3144
3145             _ASSERTE(pToStringMD != NULL);
3146         }
3147         else
3148         {
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);
3152         }
3153
3154
3155
3156         PREPARE_VIRTUAL_CALLSITE_USING_METHODDESC(pToStringMD, gc.TargetObj);
3157         DECLARE_ARGHOLDER_ARRAY(args, 1);
3158         args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(gc.TargetObj);
3159
3160         CALL_MANAGED_METHOD_RETREF(gc.RetVal, STRINGREF, args);
3161         
3162         //
3163         // Convert managed string to HSTRING
3164         // 
3165         if (gc.RetVal == NULL)
3166             *pResult = NULL;
3167         else
3168             hr = ::WindowsCreateString(gc.RetVal->GetBuffer(), gc.RetVal->GetStringLength(), pResult);
3169
3170         GCPROTECT_END();
3171         
3172     }
3173     END_EXTERNAL_ENTRYPOINT;
3174     
3175     return hr;
3176
3177 }
3178
3179
3180 ULONG __stdcall
3181 ICCW_AddRefFromJupiter(IUnknown* pUnk)
3182 {
3183     CONTRACTL
3184     {
3185         NOTHROW;
3186         GC_NOTRIGGER;
3187         MODE_ANY;
3188         PRECONDITION(CheckPointer(pUnk));
3189         PRECONDITION(IsSimpleTearOff(pUnk));
3190     }
3191     CONTRACTL_END;
3192
3193     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
3194         
3195     return pSimpleWrap->AddJupiterRef();
3196 }
3197
3198 ULONG __stdcall
3199 ICCW_ReleaseFromJupiter(IUnknown* pUnk)
3200 {
3201     CONTRACTL
3202     {
3203         NOTHROW;
3204         GC_TRIGGERS;
3205         MODE_PREEMPTIVE;
3206         PRECONDITION(CheckPointer(pUnk));
3207     }
3208     CONTRACTL_END;
3209
3210     ULONG cbRef = -1;
3211
3212     HRESULT hr;
3213     BEGIN_EXTERNAL_ENTRYPOINT(&hr)
3214     {
3215         SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
3216         
3217         cbRef = pSimpleWrap->ReleaseJupiterRef();
3218     }
3219     END_EXTERNAL_ENTRYPOINT;
3220
3221     return cbRef;
3222 }
3223
3224 HRESULT __stdcall
3225 ICCW_Peg(IUnknown* pUnk)
3226 {
3227     CONTRACTL
3228     {
3229         NOTHROW;
3230         GC_NOTRIGGER;
3231         MODE_ANY;
3232         PRECONDITION(CheckPointer(pUnk));
3233     }
3234     CONTRACTL_END;
3235     
3236     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);
3237
3238     pSimpleWrap->MarkPegged();
3239
3240     STRESS_LOG1(LF_INTEROP, LL_INFO1000, "CCW 0x%p pegged\n", (ComCallWrapper *)pSimpleWrap->GetMainWrapper());
3241
3242     return S_OK;
3243 }
3244
3245 HRESULT __stdcall
3246 ICCW_Unpeg(IUnknown* pUnk)
3247 {
3248     CONTRACTL
3249     {
3250         NOTHROW;
3251         GC_NOTRIGGER;
3252         MODE_ANY;
3253         PRECONDITION(CheckPointer(pUnk));
3254     }
3255     CONTRACTL_END;
3256
3257     SimpleComCallWrapper *pSimpleWrap = SimpleComCallWrapper::GetWrapperFromIP(pUnk);    
3258     
3259     pSimpleWrap->UnMarkPegged();
3260
3261     STRESS_LOG1(LF_INTEROP, LL_INFO1000, "CCW 0x%p unpegged\n", (ComCallWrapper *)pSimpleWrap->GetMainWrapper());
3262
3263     return S_OK;
3264 }