Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/System.Private.CoreLib/ILLinkTrim.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,7 @@
<!-- Accessed via native code. -->
<type fullname="System.Runtime.InteropServices.ComTypes.IEnumerable" />
<type fullname="System.Runtime.InteropServices.CustomMarshalers.*" />
<!-- Accessed by the WinRT Host -->
<type fullname="Internal.Runtime.InteropServices.WindowsRuntime.ActivationFactoryLoader" />
</assembly>
</linker>
1 change: 1 addition & 0 deletions src/System.Private.CoreLib/System.Private.CoreLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@
</ItemGroup>
<ItemGroup Condition="'$(FeatureCominterop)' == 'true'">
<Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\WindowsRuntime\ExceptionSupport.cs" />
<Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\WindowsRuntime\ActivationFactoryLoader.cs" Condition="'$(FeatureCominteropWinRTManagedActivation)' == 'true'" />
<Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\ComActivator.cs" Condition="'$(FeatureCominteropUnmanagedActivation)' == 'true'" />
<Compile Include="$(BclSourcesRoot)\Microsoft\Win32\OAVariantLib.cs" Condition="'$(FeatureClassicCominterop)' == 'true'" />
<Compile Include="$(BclSourcesRoot)\System\__ComObject.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Runtime.Loader;

namespace Internal.Runtime.InteropServices.WindowsRuntime
{
internal static class ActivationFactoryLoader
{
// Collection of all ALCs used for WinRT activation.
// Since each of the assemblies that act as the "key" here are WinRT assemblies
// we don't need to share this dictionary with the COM activation dictionary
// since there will be no overlap.
private static Dictionary<string, AssemblyLoadContext> s_AssemblyLoadContexts = new Dictionary<string, AssemblyLoadContext>(StringComparer.InvariantCultureIgnoreCase);
Comment thread
jkoritzinsky marked this conversation as resolved.

private static AssemblyLoadContext GetALC(string assemblyPath)
{
AssemblyLoadContext alc;

lock (s_AssemblyLoadContexts)
{
if (!s_AssemblyLoadContexts.TryGetValue(assemblyPath, out alc))
{
alc = new IsolatedComponentLoadContext(assemblyPath);
s_AssemblyLoadContexts.Add(assemblyPath, alc);
}
}

return alc;
}

/// <summary>Get a WinRT activation factory for a given type name.</summary>
/// <param name="componentPath">The path to the WinRT component that the type is expected to be defined in.</param>
/// <param name="typeName">The name of the component type to activate</param>
/// <param name="activationFactory">The activation factory</param>
public unsafe static int GetActivationFactory(
char* componentPath,
[MarshalAs(UnmanagedType.HString)] string typeName,
[MarshalAs(UnmanagedType.Interface)] out IActivationFactory activationFactory)
{
activationFactory = null;
try
{
if (typeName is null)
{
throw new ArgumentNullException(nameof(typeName));
}

AssemblyLoadContext context = GetALC(Marshal.PtrToStringUni((IntPtr)componentPath));

Type winRTType = context.LoadTypeForWinRTTypeNameInContext(typeName);

if (winRTType is null || !winRTType.IsExportedToWindowsRuntime)
{
throw new TypeLoadException(typeName);
}
activationFactory = WindowsRuntimeMarshal.GetManagedActivationFactory(winRTType);
}
catch (Exception ex)
{
return ex.HResult;
}
return 0;
}
}
}
7 changes: 4 additions & 3 deletions src/System.Private.CoreLib/src/System/RtType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3364,14 +3364,15 @@ public override Guid GUID
#if FEATURE_COMINTEROP
internal override bool IsWindowsRuntimeObjectImpl() => IsWindowsRuntimeObjectType(this);

internal override bool IsExportedToWindowsRuntimeImpl() => IsTypeExportedToWindowsRuntime(this);

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool IsWindowsRuntimeObjectType(RuntimeType type);

#if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
internal override bool IsExportedToWindowsRuntimeImpl() => IsTypeExportedToWindowsRuntime(this);

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool IsTypeExportedToWindowsRuntime(RuntimeType type);

#endif // FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
#endif // FEATURE_COMINTEROP

internal bool IsDelegate() => GetBaseType() == typeof(MulticastDelegate);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,26 @@ private IntPtr GetResolvedUnmanagedDll(Assembly assembly, string unmanagedDllNam
return IntPtr.Zero;
}

[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern void LoadTypeForWinRTTypeNameInContextInternal(IntPtr ptrNativeAssemblyLoadContext, string typeName, ObjectHandleOnStack loadedType);

internal Type LoadTypeForWinRTTypeNameInContext(string typeName)
{
if (typeName is null)
{
throw new ArgumentNullException(nameof(typeName));
}

lock (_unloadLock)
{
VerifyIsAlive();

Type type = null;
LoadTypeForWinRTTypeNameInContextInternal(_nativeAssemblyLoadContext, typeName, JitHelpers.GetObjectHandleOnStack(ref type));
return type;
}
}

[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern IntPtr GetLoadContextForAssembly(RuntimeAssembly assembly);

Expand Down
3 changes: 3 additions & 0 deletions src/vm/appdomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5962,6 +5962,9 @@ PEAssembly * AppDomain::BindAssemblySpec(
hr = BindAssemblySpecForHostedBinder(pSpec, pAssemblyName, m_pWinRtBinder, &pAssembly);
if (FAILED(hr))
goto EndTry2; // Goto end of try block.

PTR_CLRPrivAssemblyWinRT assem = dac_cast<PTR_CLRPrivAssemblyWinRT>(pAssembly->GetHostAssembly());
assem->SetFallbackBinder(pSpec->GetHostBinder());
EndTry2:;
}
// The combination of this conditional catch/ the following if statement which will throw reduces the count of exceptions
Expand Down
20 changes: 20 additions & 0 deletions src/vm/assemblynative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,26 @@ void QCALLTYPE AssemblyNative::GetLocation(QCall::AssemblyHandle pAssembly, QCal
END_QCALL;
}


#ifdef FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
void QCALLTYPE AssemblyNative::LoadTypeForWinRTTypeNameInContext(INT_PTR ptrAssemblyLoadContext, LPCWSTR pwzTypeName, QCall::ObjectHandleOnStack retType)
{
QCALL_CONTRACT;

BEGIN_QCALL;

TypeHandle loadedType = WinRTTypeNameConverter::LoadManagedTypeForWinRTTypeName(pwzTypeName, (ICLRPrivBinder*)ptrAssemblyLoadContext, /* pbIsPrimitive */ nullptr);

if (!loadedType.IsNull())
{
GCX_COOP();
retType.Set(loadedType.GetManagedClassObject());
}

END_QCALL;
}
#endif

void QCALLTYPE AssemblyNative::GetType(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive)
{
CONTRACTL
Expand Down
3 changes: 3 additions & 0 deletions src/vm/assemblynative.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ class AssemblyNative
static void QCALLTYPE LoadFromInMemoryModule(INT_PTR ptrNativeAssemblyLoadContext, INT_PTR hModule, QCall::ObjectHandleOnStack retLoadedAssembly);
#endif
static Assembly* LoadFromPEImage(ICLRPrivBinder* pBinderContext, PEImage *pILImage, PEImage *pNIImage);
#ifdef FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
static void QCALLTYPE LoadTypeForWinRTTypeNameInContext(INT_PTR ptrAssemblyLoadContext, LPCWSTR pwzTypeName, QCall::ObjectHandleOnStack retType);
#endif
static INT_PTR QCALLTYPE GetLoadContextForAssembly(QCall::AssemblyHandle pAssembly);

static BOOL QCALLTYPE InternalTryGetRawMetadata(QCall::AssemblyHandle assembly, UINT8 **blobRef, INT32 *lengthRef);
Expand Down
12 changes: 11 additions & 1 deletion src/vm/assemblyspec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -870,8 +870,18 @@ ICLRPrivBinder* AssemblySpec::GetBindingContextFromParentAssembly(AppDomain *pDo
// types being referenced from Windows.Foundation.Winmd).
//
// If the AssemblySpec does not correspond to WinRT type but our parent assembly binder is a WinRT binder,
// then such an assembly will not be found by the binder. In such a case, we reset our binder reference.
// then such an assembly will not be found by the binder.
// In such a case, the parent binder should be the fallback binder for the WinRT assembly if one exists.
ICLRPrivBinder* pParentWinRTBinder = pParentAssemblyBinder;
pParentAssemblyBinder = NULL;
ReleaseHolder<ICLRPrivAssemblyID_WinRT> assembly;
if (SUCCEEDED(pParentWinRTBinder->QueryInterface<ICLRPrivAssemblyID_WinRT>(&assembly)))
{
pParentAssemblyBinder = dac_cast<PTR_CLRPrivAssemblyWinRT>(assembly.GetValue())->GetFallbackBinder();

// The fallback binder should not be a WinRT binder.
_ASSERTE(!AreSameBinderInstance(pWinRTBinder, pParentAssemblyBinder));
}
}
}
#endif // defined(FEATURE_COMINTEROP)
Expand Down
3 changes: 2 additions & 1 deletion src/vm/clrprivbinderwinrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,8 @@ CLRPrivAssemblyWinRT::CLRPrivAssemblyWinRT(
m_pIResourceNI(nullptr),
m_pIBindResult(nullptr),
m_fShareable(fShareable),
m_dwImageTypes(0)
m_dwImageTypes(0),
m_FallbackBinder(nullptr)
{
STANDARD_VM_CONTRACT;
VALIDATE_ARG_THROW((pBinder != nullptr) && (pResourceIL != nullptr) && (pIBindResult != nullptr));
Expand Down
11 changes: 11 additions & 0 deletions src/vm/clrprivbinderwinrt.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,16 @@ class CLRPrivAssemblyWinRT :
DWORD dwImageType,
DWORD * pdwImageType,
ICLRPrivResource ** ppIResource);

void SetFallbackBinder(ICLRPrivBinder* fallbackBinder)
{
m_FallbackBinder = clr::SafeAddRef(fallbackBinder);
}

ICLRPrivBinder* GetFallbackBinder()
{
return m_FallbackBinder;
}

private:
//=============================================================================================
Expand All @@ -336,4 +346,5 @@ class CLRPrivAssemblyWinRT :
ReleaseHolder<IBindResult> m_pIBindResult;
BOOL m_fShareable;
Volatile<DWORD> m_dwImageTypes;
ReleaseHolder<ICLRPrivBinder> m_FallbackBinder;
}; // class CLRPrivAssemblyWinRT
2 changes: 1 addition & 1 deletion src/vm/corhost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2420,7 +2420,7 @@ HRESULT STDMETHODCALLTYPE DllGetActivationFactoryImpl(LPCWSTR wszAssemblyName,
GCX_COOP();

bool bIsPrimitive;
TypeHandle typeHandle = WinRTTypeNameConverter::GetManagedTypeFromWinRTTypeName(wszTypeName, &bIsPrimitive);
TypeHandle typeHandle = WinRTTypeNameConverter::LoadManagedTypeForWinRTTypeName(wszTypeName, /* pLoadBinder */ nullptr, &bIsPrimitive);
if (!bIsPrimitive && !typeHandle.IsNull() && !typeHandle.IsTypeDesc() && typeHandle.AsMethodTable()->IsExportedToWinRT())
{
struct _gc {
Expand Down
3 changes: 3 additions & 0 deletions src/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,9 @@ FCFuncStart(gAssemblyLoadContextFuncs)
QCFuncElement("LoadFromPath", AssemblyNative::LoadFromPath)
QCFuncElement("InternalLoadUnmanagedDllFromPath", AssemblyNative::InternalLoadUnmanagedDllFromPath)
QCFuncElement("LoadFromStream", AssemblyNative::LoadFromStream)
#ifdef FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
QCFuncElement("LoadTypeForWinRTTypeNameInContextInternal", AssemblyNative::LoadTypeForWinRTTypeNameInContext)
#endif
#ifndef FEATURE_PAL
QCFuncElement("LoadFromInMemoryModuleInternal", AssemblyNative::LoadFromInMemoryModule)
#endif
Expand Down
8 changes: 4 additions & 4 deletions src/vm/interoputil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5103,7 +5103,7 @@ void InitializeComInterop()
}

// Try to load a WinRT type.
TypeHandle GetWinRTType(SString* ssTypeName, BOOL bThrowIfNotFound)
TypeHandle LoadWinRTType(SString* ssTypeName, BOOL bThrowIfNotFound, ICLRPrivBinder* loadBinder /* =nullptr */)
{
CONTRACT (TypeHandle)
{
Expand All @@ -5116,8 +5116,8 @@ TypeHandle GetWinRTType(SString* ssTypeName, BOOL bThrowIfNotFound)
TypeHandle typeHandle;

SString ssAssemblyName(SString::Utf8Literal, "WindowsRuntimeAssemblyName, ContentType=WindowsRuntime");
DomainAssembly *pAssembly = LoadDomainAssembly(&ssAssemblyName, NULL,
NULL,
DomainAssembly *pAssembly = LoadDomainAssembly(&ssAssemblyName, nullptr,
loadBinder,
bThrowIfNotFound, ssTypeName);
if (pAssembly != NULL)
{
Expand Down Expand Up @@ -6669,7 +6669,7 @@ TypeHandle GetClassFromIInspectable(IUnknown* pUnk, bool *pfSupportsIInspectable
EX_TRY
{
LPCWSTR pszWinRTTypeName = (ssTmpClassName.IsEmpty() ? ssClassName : ssTmpClassName);
classTypeHandle = WinRTTypeNameConverter::GetManagedTypeFromWinRTTypeName(pszWinRTTypeName, /*pbIsPrimitive = */ NULL);
classTypeHandle = WinRTTypeNameConverter::LoadManagedTypeForWinRTTypeName(pszWinRTTypeName, /* pLoadBinder */ nullptr, /*pbIsPrimitive = */ nullptr);
}
EX_CATCH
{
Expand Down
2 changes: 1 addition & 1 deletion src/vm/interoputil.h
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ MethodTable* GetClassFromIProvideClassInfo(IUnknown* pUnk);

//--------------------------------------------------------------------------------
// Try to load a WinRT type.
TypeHandle GetWinRTType(SString* ssTypeName, BOOL bThrowIfNotFound);
TypeHandle LoadWinRTType(SString* ssTypeName, BOOL bThrowIfNotFound, ICLRPrivBinder* loadBinder = nullptr);

//--------------------------------------------------------------------------------
// Try to get the class from IInspectable.
Expand Down
4 changes: 2 additions & 2 deletions src/vm/runtimecallablewrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ void WinRTClassFactory::Init()
IfFailThrow(cap.GetNonNullString(&szFactoryInterfaceName, &cbFactoryInterfaceName));

StackSString strFactoryInterface(SString::Utf8, szFactoryInterfaceName, cbFactoryInterfaceName);
MethodTable *pMTFactoryInterface = GetWinRTType(&strFactoryInterface, /* bThrowIfNotFound = */ TRUE).GetMethodTable();
MethodTable *pMTFactoryInterface = LoadWinRTType(&strFactoryInterface, /* bThrowIfNotFound = */ TRUE).GetMethodTable();

_ASSERTE(pMTFactoryInterface);
m_factoryInterfaces.Append(pMTFactoryInterface);
Expand Down Expand Up @@ -951,7 +951,7 @@ void WinRTClassFactory::Init()

// copy the name to a temporary buffer and NULL terminate it
StackSString ss(SString::Utf8, szName, cbName);
TypeHandle th = GetWinRTType(&ss, /* bThrowIfNotFound = */ TRUE);
TypeHandle th = LoadWinRTType(&ss, /* bThrowIfNotFound = */ TRUE);

MethodTable *pMTStaticInterface = th.GetMethodTable();
m_staticInterfaces.Append(pMTStaticInterface);
Expand Down
2 changes: 2 additions & 0 deletions src/vm/runtimehandles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsWindowsRuntimeObjectType, ReflectClass
}
FCIMPLEND

#ifdef FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsTypeExportedToWindowsRuntime, ReflectClassBaseObject *rtTypeUNSAFE)
{
FCALL_CONTRACT;
Expand All @@ -401,6 +402,7 @@ FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsTypeExportedToWindowsRuntime, ReflectC
FC_RETURN_BOOL(isExportedToWinRT);
}
FCIMPLEND
#endif
#endif // FEATURE_COMINTEROP

NOINLINE static MethodDesc * RestoreMethodHelper(MethodDesc * pMethod, LPVOID __me)
Expand Down
4 changes: 3 additions & 1 deletion src/vm/runtimehandles.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,10 @@ class RuntimeTypeHandle {

#ifdef FEATURE_COMINTEROP
static FCDECL1(FC_BOOL_RET, IsWindowsRuntimeObjectType, ReflectClassBaseObject *rtTypeUNSAFE);
#ifdef FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
static FCDECL1(FC_BOOL_RET, IsTypeExportedToWindowsRuntime, ReflectClassBaseObject *rtTypeUNSAFE);
#endif // FEATURE_COMINTEROP
#endif
#endif //FEATURE_COMINTEROP

static
void QCALLTYPE PrepareMemberInfoCache(EnregisteredTypeHandle pMemberInfoCache);
Expand Down
2 changes: 1 addition & 1 deletion src/vm/stdinterfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3121,7 +3121,7 @@ HRESULT __stdcall IStringable_ToString(IUnknown* pStringable,

// Get the MethodTable for Windows.Foundation.IStringable.
StackSString strIStringable(SString::Utf8, W("Windows.Foundation.IStringable"));
MethodTable *pMTIStringable = GetWinRTType(&strIStringable, /* bThrowIfNotFound = */ FALSE).GetMethodTable();
MethodTable *pMTIStringable = LoadWinRTType(&strIStringable, /* bThrowIfNotFound = */ FALSE).GetMethodTable();

if (pMT != NULL && pMTIStringable != NULL && pMT->ImplementsInterface(pMTIStringable))
{
Expand Down
8 changes: 7 additions & 1 deletion src/vm/stubhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,9 @@ FCIMPL4(IUnknown*, StubHelpers::InterfaceMarshaler__ConvertToNative, Object* pOb
// This is only called in IL stubs which are in CER, so we don't need to worry about ThreadAbort
HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_NO_THREAD_ABORT, pObj);

// We're going to be making some COM calls, better initialize COM.
EnsureComStarted();

pIntf = MarshalObjectToInterface(&pObj, pItfMT, pClsMT, dwFlags);

// No exception will be thrown here (including thread abort as it is delayed in IL stubs)
Expand All @@ -725,6 +728,9 @@ FCIMPL4(Object*, StubHelpers::InterfaceMarshaler__ConvertToManaged, IUnknown **p

OBJECTREF pObj = NULL;
HELPER_METHOD_FRAME_BEGIN_RET_1(pObj);

// We're going to be making some COM calls, better initialize COM.
EnsureComStarted();

UnmarshalObjectFromInterface(&pObj, ppUnk, pItfMT, pClsMT, dwFlags);

Expand Down Expand Up @@ -893,7 +899,7 @@ FCIMPL2(ReflectClassBaseObject *, StubHelpers::WinRTTypeNameConverter__GetTypeFr
HELPER_METHOD_FRAME_BEGIN_RET_2(refClass, refString);

bool isPrimitive;
TypeHandle th = WinRTTypeNameConverter::GetManagedTypeFromWinRTTypeName(refString->GetBuffer(), &isPrimitive);
TypeHandle th = WinRTTypeNameConverter::LoadManagedTypeForWinRTTypeName(refString->GetBuffer(), /* pLoadBinder */ nullptr, &isPrimitive);
*pbIsPrimitive = isPrimitive;

refClass = th.GetManagedClassObject();
Expand Down
Loading