summaryrefslogtreecommitdiff
path: root/src/vm/clrprivtypecachewinrt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/clrprivtypecachewinrt.cpp')
-rw-r--r--src/vm/clrprivtypecachewinrt.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/src/vm/clrprivtypecachewinrt.cpp b/src/vm/clrprivtypecachewinrt.cpp
new file mode 100644
index 0000000000..004d14e88c
--- /dev/null
+++ b/src/vm/clrprivtypecachewinrt.cpp
@@ -0,0 +1,246 @@
+// 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.
+//
+
+//
+// Contains VM implementation of WinRT type cache for code:CLRPrivBinderWinRT binder.
+//
+//=====================================================================================================================
+
+#include "common.h" // precompiled header
+#include "clrprivtypecachewinrt.h"
+
+#ifndef DACCESS_COMPILE
+
+//=====================================================================================================================
+// S_OK - pAssembly contains type wszTypeName
+// S_FALSE - pAssembly does not contain type wszTypeName
+//
+HRESULT
+CLRPrivTypeCacheWinRT::ContainsType(
+ ICLRPrivAssembly * pPrivAssembly,
+ LPCWSTR wszTypeName)
+{
+ STANDARD_VM_CONTRACT;
+
+ HRESULT hr = S_OK;
+
+ AppDomain * pAppDomain = AppDomain::GetCurrentDomain();
+
+ ReleaseHolder<PEAssembly> pPEAssembly;
+ IfFailGo(pAppDomain->BindHostedPrivAssembly(nullptr, pPrivAssembly, nullptr, &pPEAssembly));
+ _ASSERTE(pPEAssembly != nullptr);
+
+ {
+ // Find DomainAssembly * (can be cached if this is too slow to call always)
+ DomainAssembly * pDomainAssembly = pAppDomain->LoadDomainAssembly(
+ nullptr, // pIdentity
+ pPEAssembly,
+ FILE_LOAD_DELIVER_EVENTS,
+ nullptr); // pLoadSecurity
+
+ // Convert the type name into namespace and class name in UTF8
+ StackSString ssTypeNameWCHAR(wszTypeName);
+
+ StackSString ssTypeName;
+ ssTypeNameWCHAR.ConvertToUTF8(ssTypeName);
+ LPUTF8 szTypeName = (LPUTF8)ssTypeName.GetUTF8NoConvert();
+
+ LPCUTF8 szNamespace;
+ LPCUTF8 szClassName;
+ ns::SplitInline(szTypeName, szNamespace, szClassName);
+
+ hr = ContainsTypeHelper(pDomainAssembly->GetAssembly(), szNamespace, szClassName);
+ _ASSERTE((hr == S_OK) || (hr == S_FALSE));
+ return hr;
+ }
+
+ErrExit:
+ return hr;
+} // CLRPrivTypeCacheWinRT::ContainsType
+
+#endif //!DACCESS_COMPILE
+
+//=====================================================================================================================
+//
+// Checks if the type (szNamespace/szClassName) is present in the assembly pAssembly.
+//
+// Return value:
+// S_OK - Type is present in the assembly.
+// S_FALSE - Type is not present.
+// No other error codes or success codes
+//
+HRESULT
+CLRPrivTypeCacheWinRT::ContainsTypeHelper(
+ PTR_Assembly pAssembly,
+ LPCUTF8 szNamespace,
+ LPCUTF8 szClassName)
+{
+ CONTRACTL
+ {
+ if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
+ if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
+ MODE_ANY;
+ SUPPORTS_DAC;
+ }
+ CONTRACTL_END
+
+ NameHandle typeName(szNamespace, szClassName);
+
+ // Find the type in the assembly (use existing hash of all type names defined in the assembly)
+ TypeHandle thType;
+ mdToken tkType;
+ Module * pTypeModule;
+ mdToken tkExportedType;
+
+ if (pAssembly->GetLoader()->FindClassModuleThrowing(
+ &typeName,
+ &thType,
+ &tkType,
+ &pTypeModule,
+ &tkExportedType,
+ nullptr, // pFoundEntry
+ nullptr, // pLookInThisModuleOnly
+ Loader::DontLoad))
+ {
+ return S_OK;
+ }
+ else
+ {
+ return S_FALSE;
+ }
+} // CLRPrivTypeCacheWinRT::ContainsTypeHelper
+
+//=====================================================================================================================
+//
+// Checks if the assembly pPrivAssembly (referenced from assembly in pAppDomain) contains type (szNamespace/szClassName).
+// Fills *ppAssembly if it contains the type.
+//
+// Return value:
+// S_OK - Contains type (fills *ppAssembly).
+// S_FALSE - Does not contain the type (*ppAssembly is not filled).
+// E_FAIL - Assembly is not loaded.
+//
+HRESULT
+CLRPrivTypeCacheWinRT::ContainsTypeIfLoaded(
+ PTR_AppDomain pAppDomain,
+ PTR_ICLRPrivAssembly pPrivAssembly,
+ LPCUTF8 szNamespace,
+ LPCUTF8 szClassName,
+ PTR_Assembly * ppAssembly)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ FORBID_FAULT;
+ MODE_ANY;
+ SUPPORTS_DAC;
+ }
+ CONTRACTL_END
+
+ HRESULT hr;
+
+ PTR_DomainAssembly pDomainAssembly = pAppDomain->FindAssembly(pPrivAssembly);
+ if (pDomainAssembly == nullptr || !pDomainAssembly->IsLoaded())
+ { // The assembly is not loaded into the AppDomain
+ return E_FAIL;
+ }
+ PTR_Assembly pAssembly = dac_cast<PTR_Assembly>(pDomainAssembly->GetLoadedAssembly());
+ if (pAssembly == nullptr)
+ { // The assembly failed to load earlier (exception is cached on pDomainAssembly)
+ return E_FAIL;
+ }
+
+ hr = ContainsTypeHelper(pAssembly, szNamespace, szClassName);
+ _ASSERTE((hr == S_OK) || (hr == S_FALSE));
+ if (hr == S_OK)
+ { // The type is present in the assembly
+ *ppAssembly = pAssembly;
+ }
+ return hr;
+} // CLRPrivTypeCacheWinRT::ContainsTypeIfLoaded
+
+#ifndef DACCESS_COMPILE
+
+#ifndef CROSSGEN_COMPILE
+//=====================================================================================================================
+// Raises user event DesignerNamespaceResolveEvent to get a list of files for this namespace.
+//
+void
+CLRPrivTypeCacheWinRT::RaiseDesignerNamespaceResolveEvent(
+ LPCWSTR wszNamespace,
+ CLRPrivBinderUtil::WStringListHolder * pFileNameList)
+{
+ STANDARD_VM_CONTRACT;
+
+ _ASSERTE(pFileNameList != nullptr);
+
+ AppDomain * pAppDomain = AppDomain::GetCurrentDomain();
+
+ GCX_COOP();
+
+ struct _gc {
+ OBJECTREF AppDomainRef;
+ STRINGREF str;
+ } gc;
+ ZeroMemory(&gc, sizeof(gc));
+
+ GCPROTECT_BEGIN(gc);
+ if ((gc.AppDomainRef = pAppDomain->GetRawExposedObject()) != NULL)
+ {
+ MethodDescCallSite onNamespaceResolve(METHOD__APP_DOMAIN__ON_DESIGNER_NAMESPACE_RESOLVE, &gc.AppDomainRef);
+ gc.str = StringObject::NewString(wszNamespace);
+ ARG_SLOT args[2] =
+ {
+ ObjToArgSlot(gc.AppDomainRef),
+ ObjToArgSlot(gc.str)
+ };
+ PTRARRAYREF ResultingFileNameArrayRef = (PTRARRAYREF) onNamespaceResolve.Call_RetOBJECTREF(args);
+ if (ResultingFileNameArrayRef != NULL)
+ {
+ for (DWORD i = 0; i < ResultingFileNameArrayRef->GetNumComponents(); i++)
+ {
+ STRINGREF ResultingFileNameRef = (STRINGREF) ResultingFileNameArrayRef->GetAt(i);
+ _ASSERTE(ResultingFileNameRef != NULL); // Verified in the managed code OnDesignerNamespaceResolveEvent
+
+ SString sFileName;
+ ResultingFileNameRef->GetSString(sFileName);
+ _ASSERTE(!sFileName.IsEmpty()); // Verified in the managed code OnDesignerNamespaceResolveEvent
+
+ pFileNameList->InsertTail(sFileName.GetUnicode());
+ }
+ }
+ }
+ GCPROTECT_END();
+} // CLRPrivTypeCacheWinRT::RaiseDesignerNamespaceResolveEvent
+
+//=====================================================================================================================
+#endif // CROSSGEN_COMPILE
+
+CLRPrivTypeCacheWinRT * CLRPrivTypeCacheWinRT::s_pSingleton = nullptr;
+
+//=====================================================================================================================
+CLRPrivTypeCacheWinRT *
+CLRPrivTypeCacheWinRT::GetOrCreateTypeCache()
+{
+ STANDARD_VM_CONTRACT;
+
+ if (s_pSingleton == nullptr)
+ {
+ ReleaseHolder<CLRPrivTypeCacheWinRT> pTypeCache;
+ pTypeCache = clr::SafeAddRef(new CLRPrivTypeCacheWinRT());
+
+ if (InterlockedCompareExchangeT<decltype(s_pSingleton)>(&s_pSingleton, pTypeCache, nullptr) == nullptr)
+ {
+ pTypeCache.SuppressRelease();
+ }
+ }
+
+ return s_pSingleton;
+}
+
+//=====================================================================================================================
+
+#endif //!DACCESS_COMPILE