summaryrefslogtreecommitdiff
path: root/src/vm/appdomainnative.cpp
diff options
context:
space:
mode:
authordotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
committerdotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
commitef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch)
treedee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/vm/appdomainnative.cpp
downloadcoreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.gz
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.bz2
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.zip
Initial commit to populate CoreCLR repo
[tfs-changeset: 1407945]
Diffstat (limited to 'src/vm/appdomainnative.cpp')
-rw-r--r--src/vm/appdomainnative.cpp1778
1 files changed, 1778 insertions, 0 deletions
diff --git a/src/vm/appdomainnative.cpp b/src/vm/appdomainnative.cpp
new file mode 100644
index 0000000000..5e4656600e
--- /dev/null
+++ b/src/vm/appdomainnative.cpp
@@ -0,0 +1,1778 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+
+
+#include "common.h"
+#include "appdomain.hpp"
+#include "appdomainnative.hpp"
+#ifdef FEATURE_REMOTING
+#include "remoting.h"
+#include "appdomainhelper.h"
+#endif
+#include "security.h"
+#include "vars.hpp"
+#include "eeconfig.h"
+#include "appdomain.inl"
+#include "eventtrace.h"
+#ifndef FEATURE_CORECLR
+#include "comutilnative.h"
+#endif // !FEATURE_CORECLR
+#if defined(FEATURE_APPX)
+#include "appxutil.h"
+#endif // FEATURE_APPX
+#if defined(FEATURE_APPX_BINDER) && defined(FEATURE_HOSTED_BINDER)
+#include "clrprivbinderappx.h"
+#include "clrprivtypecachewinrt.h"
+#endif // FEATURE_APPX_BINDER && FEATURE_HOSTED_BINDER
+#ifdef FEATURE_VERSIONING
+#include "../binder/inc/clrprivbindercoreclr.h"
+#endif
+
+
+//************************************************************************
+inline AppDomain *AppDomainNative::ValidateArg(APPDOMAINREF pThis)
+{
+ CONTRACTL
+ {
+ MODE_COOPERATIVE;
+ DISABLED(GC_TRIGGERS); // can't use this in an FCALL because we're in forbid gc mode until we setup a H_M_F.
+ THROWS;
+ }
+ CONTRACTL_END;
+
+ if (pThis == NULL)
+ {
+ COMPlusThrow(kNullReferenceException, W("NullReference_This"));
+ }
+
+ // Should not get here with a Transparent proxy for the this pointer -
+ // should have always called through onto the real object
+#ifdef FEATURE_REMOTING
+ _ASSERTE(! CRemotingServices::IsTransparentProxy(OBJECTREFToObject(pThis)));
+#endif
+
+ AppDomain* pDomain = (AppDomain*)pThis->GetDomain();
+
+ if(!pDomain)
+ {
+ COMPlusThrow(kNullReferenceException, W("NullReference_This"));
+ }
+
+ // can only be accessed from within current domain
+ _ASSERTE(GetAppDomain() == pDomain);
+
+ // should not get here with an invalid appdomain. Once unload it, we won't let anyone else
+ // in and any threads that are already in will be unwound.
+ _ASSERTE(SystemDomain::GetAppDomainAtIndex(pDomain->GetIndex()) != NULL);
+ return pDomain;
+}
+
+
+#ifdef FEATURE_REMOTING
+//************************************************************************
+FCIMPL5(Object*, AppDomainNative::CreateDomain, StringObject* strFriendlyNameUNSAFE, Object* appdomainSetupUNSAFE, Object* providedEvidenceUNSAFE, Object* creatorsEvidenceUNSAFE, void* parentSecurityDescriptor)
+{
+ FCALL_CONTRACT;
+
+ struct _gc
+ {
+ OBJECTREF retVal;
+ STRINGREF strFriendlyName;
+ OBJECTREF appdomainSetup;
+ OBJECTREF providedEvidence;
+ OBJECTREF creatorsEvidence;
+ OBJECTREF entryPointProxy;
+ } gc;
+
+ ZeroMemory(&gc, sizeof(gc));
+ gc.strFriendlyName=(STRINGREF)strFriendlyNameUNSAFE;
+ gc.appdomainSetup=(OBJECTREF)appdomainSetupUNSAFE;
+ gc.providedEvidence=(OBJECTREF)providedEvidenceUNSAFE;
+ gc.creatorsEvidence=(OBJECTREF)creatorsEvidenceUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
+
+ CreateDomainHelper(&gc.strFriendlyName, &gc.appdomainSetup, &gc.providedEvidence, &gc.creatorsEvidence, parentSecurityDescriptor, &gc.entryPointProxy, &gc.retVal);
+
+ HELPER_METHOD_FRAME_END();
+ return OBJECTREFToObject(gc.retVal);
+}
+FCIMPLEND
+
+FCIMPL5(Object*, AppDomainNative::CreateInstance, StringObject* strFriendlyNameUNSAFE, Object* appdomainSetupUNSAFE, Object* providedEvidenceUNSAFE, Object* creatorsEvidenceUNSAFE, void* parentSecurityDescriptor)
+{
+ FCALL_CONTRACT;
+
+ struct _gc
+ {
+ OBJECTREF retVal;
+ STRINGREF strFriendlyName;
+ OBJECTREF appdomainSetup;
+ OBJECTREF providedEvidence;
+ OBJECTREF creatorsEvidence;
+ OBJECTREF entryPointProxy;
+ } gc;
+
+ ZeroMemory(&gc, sizeof(gc));
+ gc.strFriendlyName=(STRINGREF)strFriendlyNameUNSAFE;
+ gc.appdomainSetup=(OBJECTREF)appdomainSetupUNSAFE;
+ gc.providedEvidence=(OBJECTREF)providedEvidenceUNSAFE;
+ gc.creatorsEvidence=(OBJECTREF)creatorsEvidenceUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
+
+ CreateDomainHelper(&gc.strFriendlyName, &gc.appdomainSetup, &gc.providedEvidence, &gc.creatorsEvidence, parentSecurityDescriptor, &gc.entryPointProxy, &gc.retVal);
+
+ HELPER_METHOD_FRAME_END();
+ return OBJECTREFToObject(gc.entryPointProxy);
+}
+FCIMPLEND
+
+void AppDomainNative::CreateDomainHelper (STRINGREF* ppFriendlyName, OBJECTREF* ppAppdomainSetup, OBJECTREF* ppProvidedEvidence, OBJECTREF* ppCreatorsEvidence, void* parentSecurityDescriptor, OBJECTREF* pEntryPointProxy, OBJECTREF* pRetVal)
+{
+ CONTRACTL
+ {
+ MODE_COOPERATIVE;
+ GC_TRIGGERS;
+ THROWS;
+ PRECONDITION(IsProtectedByGCFrame(ppFriendlyName));
+ PRECONDITION(IsProtectedByGCFrame(ppAppdomainSetup));
+ PRECONDITION(IsProtectedByGCFrame(ppProvidedEvidence));
+ PRECONDITION(IsProtectedByGCFrame(ppCreatorsEvidence));
+ PRECONDITION(IsProtectedByGCFrame(pEntryPointProxy));
+ PRECONDITION(IsProtectedByGCFrame(pRetVal));
+ }
+ CONTRACTL_END;
+
+
+ AppDomainCreationHolder<AppDomain> pDomain;
+
+ // This helper will send the AppDomain creation notifications for profiler / debugger.
+ // If it throws, its backout code will also send a notification.
+ // If it succeeds, then we still need to send a AppDomainCreateFinished notification.
+ AppDomain::CreateUnmanagedObject(pDomain);
+
+#ifdef PROFILING_SUPPORTED
+ EX_TRY
+#endif
+ {
+ OBJECTREF setupInfo=NULL;
+ GCPROTECT_BEGIN(setupInfo);
+
+ MethodDescCallSite prepareDataForSetup(METHOD__APP_DOMAIN__PREPARE_DATA_FOR_SETUP);
+
+ ARG_SLOT args[8];
+ args[0]=ObjToArgSlot(*ppFriendlyName);
+ args[1]=ObjToArgSlot(*ppAppdomainSetup);
+ args[2]=ObjToArgSlot(*ppProvidedEvidence);
+ args[3]=ObjToArgSlot(*ppCreatorsEvidence);
+ args[4]=PtrToArgSlot(parentSecurityDescriptor);
+ args[5]=PtrToArgSlot(NULL);
+ args[6]=PtrToArgSlot(NULL);
+ args[7]=PtrToArgSlot(NULL);
+
+ setupInfo = prepareDataForSetup.Call_RetOBJECTREF(args);
+
+#ifndef FEATURE_CORECLR
+ // We need to setup domain sorting before any other managed code runs in the domain, since that code
+ // could end up caching data based on the sorting mode of the domain.
+ pDomain->InitializeSorting(ppAppdomainSetup);
+ pDomain->InitializeHashing(ppAppdomainSetup);
+#endif
+
+ // We need to ensure that the AppDomainProxy is generated before we call into DoSetup, since
+ // GetAppDomainProxy will ensure that remoting is correctly configured in the domain. DoSetup can
+ // end up loading user assemblies into the domain, and those assemblies may require that remoting be
+ // setup already. For instance, C++/CLI applications may trigger the CRT to try to marshal a
+ // reference to the default domain into the current domain, which won't work correctly without this
+ // setup being done.
+ *pRetVal = pDomain->GetAppDomainProxy();
+
+ *pEntryPointProxy=pDomain->DoSetup(&setupInfo);
+
+
+ GCPROTECT_END();
+
+ pDomain->CacheStringsForDAC();
+ }
+
+#ifdef PROFILING_SUPPORTED
+ EX_HOOK
+ {
+ // Need the first assembly loaded in to get any data on an app domain.
+ {
+ BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+ GCX_PREEMP();
+ g_profControlBlock.pProfInterface->AppDomainCreationFinished((AppDomainID)(AppDomain *) pDomain, GET_EXCEPTION()->GetHR());
+ END_PIN_PROFILER();
+ }
+ }
+ EX_END_HOOK;
+
+ // Need the first assembly loaded in to get any data on an app domain.
+ {
+ BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
+ GCX_PREEMP();
+ g_profControlBlock.pProfInterface->AppDomainCreationFinished((AppDomainID)(AppDomain*) pDomain, S_OK);
+ END_PIN_PROFILER();
+ }
+#endif // PROFILING_SUPPORTED
+
+ ETW::LoaderLog::DomainLoad(pDomain, (LPWSTR)(*ppFriendlyName)->GetBuffer());
+
+ // DoneCreating releases ownership of AppDomain. After this call, there should be no access to pDomain.
+ pDomain.DoneCreating();
+}
+#endif // FEATURE_REMOTING
+
+void QCALLTYPE AppDomainNative::SetupDomainSecurity(QCall::AppDomainHandle pDomain,
+ QCall::ObjectHandleOnStack ohEvidence,
+ IApplicationSecurityDescriptor *pParentSecurityDescriptor,
+ BOOL fPublishAppDomain)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ struct
+ {
+ OBJECTREF orEvidence;
+ }
+ gc;
+ ZeroMemory(&gc, sizeof(gc));
+
+ GCX_COOP();
+ GCPROTECT_BEGIN(gc)
+ if (ohEvidence.m_ppObject != NULL)
+ {
+ gc.orEvidence = ObjectToOBJECTREF(*ohEvidence.m_ppObject);
+ }
+
+
+ // Set up the default AppDomain property.
+ IApplicationSecurityDescriptor *pSecDesc = pDomain->GetSecurityDescriptor();
+
+ if (!pSecDesc->IsHomogeneous() && pDomain->IsDefaultDomain())
+ {
+ Security::SetDefaultAppDomainProperty(pSecDesc);
+ }
+ // Set up the evidence property in the VM side.
+ else
+ {
+ // If there is no provided evidence then this new appdomain gets the same evidence as the creator.
+ //
+ // If there is no provided evidence and this AppDomain is not homogeneous, then it automatically
+ // is also a default appdomain (for security grant set purposes)
+ //
+ //
+ // If evidence is provided, the new appdomain is not a default appdomain and
+ // we simply use the provided evidence.
+
+ if (gc.orEvidence == NULL)
+ {
+ _ASSERTE(pParentSecurityDescriptor == NULL || pParentSecurityDescriptor->IsDefaultAppDomainEvidence());
+
+ if (pSecDesc->IsHomogeneous())
+ {
+ // New domain gets default AD evidence
+ Security::SetDefaultAppDomainEvidenceProperty(pSecDesc);
+ }
+ else
+ {
+ // New domain gets to be a default AD
+ Security::SetDefaultAppDomainProperty(pSecDesc);
+ }
+ }
+ }
+
+#ifdef FEATURE_CAS_POLICY
+ if (gc.orEvidence != NULL)
+ {
+ pSecDesc->SetEvidence(gc.orEvidence);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ // We need to downgrade sharing level if the AppDomain is homogeneous and not fully trusted, or the
+ // AppDomain is in legacy mode. Effectively, we need to be sure that all assemblies loaded into the
+ // domain must be fully trusted in order to allow non-GAC sharing.
+#ifdef FEATURE_FUSION
+ if (pDomain->GetSharePolicy() == AppDomain::SHARE_POLICY_ALWAYS)
+ {
+ bool fSandboxedHomogenousDomain = false;
+ if (pSecDesc->IsHomogeneous())
+ {
+ pSecDesc->Resolve();
+ fSandboxedHomogenousDomain = !pSecDesc->IsFullyTrusted();
+ }
+
+ if (fSandboxedHomogenousDomain || pSecDesc->IsLegacyCasPolicyEnabled())
+ {
+ // We may not be able to reduce sharing policy at this point, if we have already loaded
+ // some non-GAC assemblies as domain neutral. For this case we must regrettably fail
+ // the whole operation.
+ if (!pDomain->ReduceSharePolicyFromAlways())
+ {
+ ThrowHR(COR_E_CANNOT_SET_POLICY);
+ }
+ }
+ }
+#endif
+
+ // Now finish the initialization.
+ pSecDesc->FinishInitialization();
+
+ // once domain is loaded it is publically available so if you have anything
+ // that a list interrogator might need access to if it gets a hold of the
+ // appdomain, then do it above the LoadDomain.
+ if (fPublishAppDomain)
+ SystemDomain::LoadDomain(pDomain);
+
+#ifdef _DEBUG
+ LOG((LF_APPDOMAIN, LL_INFO100, "AppDomainNative::CreateDomain domain [%d] %p %S\n", pDomain->GetIndex().m_dwIndex, (AppDomain*)pDomain, pDomain->GetFriendlyName()));
+#endif
+
+ GCPROTECT_END();
+
+ END_QCALL;
+}
+
+FCIMPL2(void, AppDomainNative::SetupFriendlyName, AppDomainBaseObject* refThisUNSAFE, StringObject* strFriendlyNameUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ struct _gc
+ {
+ APPDOMAINREF refThis;
+ STRINGREF strFriendlyName;
+ } gc;
+
+ gc.refThis = (APPDOMAINREF) refThisUNSAFE;
+ gc.strFriendlyName = (STRINGREF) strFriendlyNameUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_PROTECT(gc)
+
+ AppDomainRefHolder pDomain(ValidateArg(gc.refThis));
+ pDomain->AddRef();
+
+ // If the user created this domain, need to know this so the debugger doesn't
+ // go and reset the friendly name that was provided.
+ pDomain->SetIsUserCreatedDomain();
+
+ WCHAR* pFriendlyName = NULL;
+ Thread *pThread = GetThread();
+
+ CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
+ if (gc.strFriendlyName != NULL) {
+ WCHAR* pString = NULL;
+ int iString;
+ gc.strFriendlyName->RefInterpretGetStringValuesDangerousForGC(&pString, &iString);
+ if (ClrSafeInt<int>::addition(iString, 1, iString))
+ {
+ pFriendlyName = new (&pThread->m_MarshalAlloc) WCHAR[(iString)];
+
+ // Check for a valid string allocation
+ if (pFriendlyName == (WCHAR*)-1)
+ pFriendlyName = NULL;
+ else
+ memcpy(pFriendlyName, pString, iString*sizeof(WCHAR));
+ }
+ }
+
+ pDomain->SetFriendlyName(pFriendlyName);
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+#if FEATURE_COMINTEROP
+
+FCIMPL1(void, AppDomainNative::SetDisableInterfaceCache, AppDomainBaseObject* refThisUNSAFE)
+{
+ CONTRACTL
+ {
+ MODE_COOPERATIVE;
+ DISABLED(GC_TRIGGERS); // can't use this in an FCALL because we're in forbid gc mode until we setup a H_M_F.
+ SO_TOLERANT;
+ THROWS;
+ }
+ CONTRACTL_END;
+
+ struct _gc
+ {
+ APPDOMAINREF refThis;
+ } gc;
+
+ gc.refThis = (APPDOMAINREF) refThisUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_PROTECT(gc)
+
+ AppDomainRefHolder pDomain(ValidateArg(gc.refThis));
+ pDomain->AddRef();
+
+ pDomain->SetDisableInterfaceCache();
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+#endif // FEATURE_COMINTEROP
+
+#ifdef FEATURE_FUSION
+FCIMPL1(LPVOID, AppDomainNative::GetFusionContext, AppDomainBaseObject* refThis)
+{
+ FCALL_CONTRACT;
+
+ LPVOID rv = NULL;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(rv);
+
+ AppDomain* pApp = ValidateArg((APPDOMAINREF)refThis);
+
+ rv = pApp->CreateFusionContext();
+
+ HELPER_METHOD_FRAME_END();
+
+ return rv;
+}
+FCIMPLEND
+#endif
+
+FCIMPL1(void*, AppDomainNative::GetSecurityDescriptor, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ void* pvRetVal = NULL;
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
+
+
+ pvRetVal = ValidateArg(refThis)->GetSecurityDescriptor();
+
+ HELPER_METHOD_FRAME_END();
+ return pvRetVal;
+}
+FCIMPLEND
+
+#ifdef FEATURE_LOADER_OPTIMIZATION
+FCIMPL2(void, AppDomainNative::UpdateLoaderOptimization, AppDomainBaseObject* refThisUNSAFE, DWORD optimization)
+{
+ FCALL_CONTRACT;
+
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_1(refThis);
+
+ ValidateArg(refThis)->SetSharePolicy((AppDomain::SharePolicy) (optimization & AppDomain::SHARE_POLICY_MASK));
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+#endif // FEATURE_LOADER_OPTIMIZATION
+
+#ifdef FEATURE_FUSION
+FCIMPL3(void, AppDomainNative::UpdateContextProperty, LPVOID fusionContext, StringObject* keyUNSAFE, Object* valueUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ struct _gc
+ {
+ STRINGREF key;
+ OBJECTREF value;
+ } gc;
+
+ gc.key = ObjectToSTRINGREF(keyUNSAFE);
+ gc.value = ObjectToOBJECTREF(valueUNSAFE);
+ _ASSERTE(gc.key != NULL);
+
+ HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
+
+ IApplicationContext* pContext = (IApplicationContext*) fusionContext;
+
+ BOOL fFXOnly;
+ DWORD size = sizeof(fFXOnly);
+ HRESULT hr = pContext->Get(ACTAG_FX_ONLY, &fFXOnly, &size, 0);
+ if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
+ {
+ fFXOnly = FALSE;
+ hr = S_FALSE;
+ }
+ IfFailThrow(hr);
+
+ if (!fFXOnly)
+ {
+ DWORD lgth = gc.key->GetStringLength();
+ CQuickBytes qb;
+ LPWSTR key = (LPWSTR) qb.AllocThrows((lgth+1)*sizeof(WCHAR));
+ memcpy(key, gc.key->GetBuffer(), lgth*sizeof(WCHAR));
+ key[lgth] = W('\0');
+
+ AppDomain::SetContextProperty(pContext, key, &gc.value);
+ }
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+#endif // FEATURE_FUSION
+
+/* static */
+INT32 AppDomainNative::ExecuteAssemblyHelper(Assembly* pAssembly,
+ BOOL bCreatedConsole,
+ PTRARRAYREF *pStringArgs)
+{
+ STATIC_CONTRACT_THROWS;
+
+ struct Param
+ {
+ Assembly* pAssembly;
+ PTRARRAYREF *pStringArgs;
+ INT32 iRetVal;
+ } param;
+ param.pAssembly = pAssembly;
+ param.pStringArgs = pStringArgs;
+ param.iRetVal = 0;
+
+ EE_TRY_FOR_FINALLY(Param *, pParam, &param)
+ {
+ pParam->iRetVal = pParam->pAssembly->ExecuteMainMethod(pParam->pStringArgs);
+ }
+ EE_FINALLY
+ {
+#ifndef FEATURE_PAL
+ if(bCreatedConsole)
+ FreeConsole();
+#endif // !FEATURE_PAL
+ }
+ EE_END_FINALLY
+
+ return param.iRetVal;
+}
+
+static void UpgradeLinkTimeCheckToLateBoundDemand(MethodDesc* pMeth)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+ BOOL isEveryoneFullyTrusted = FALSE;
+
+ struct _gc
+ {
+ OBJECTREF refClassNonCasDemands;
+ OBJECTREF refClassCasDemands;
+ OBJECTREF refMethodNonCasDemands;
+ OBJECTREF refMethodCasDemands;
+ OBJECTREF refThrowable;
+ } gc;
+ ZeroMemory(&gc, sizeof(gc));
+
+ GCPROTECT_BEGIN(gc);
+
+ isEveryoneFullyTrusted = Security::AllDomainsOnStackFullyTrusted();
+
+ // If all assemblies in the domain are fully trusted then we are not
+ // going to do any security checks anyway..
+ if (isEveryoneFullyTrusted)
+ {
+ goto Exit1;
+ }
+
+
+ if (pMeth->RequiresLinktimeCheck())
+ {
+ // Fetch link demand sets from all the places in metadata where we might
+ // find them (class and method). These might be split into CAS and non-CAS
+ // sets as well.
+ Security::RetrieveLinktimeDemands(pMeth,
+ &gc.refClassCasDemands,
+ &gc.refClassNonCasDemands,
+ &gc.refMethodCasDemands,
+ &gc.refMethodNonCasDemands);
+
+ if (gc.refClassCasDemands == NULL && gc.refClassNonCasDemands == NULL &&
+ gc.refMethodCasDemands == NULL && gc.refMethodNonCasDemands == NULL &&
+ isEveryoneFullyTrusted)
+ {
+ // All code access security demands will pass anyway.
+ goto Exit1;
+ }
+
+ // The following logic turns link demands on the target method into full
+ // stack walks in order to close security holes in poorly written
+ // reflection users.
+
+#ifdef FEATURE_APTCA
+ if (Security::IsUntrustedCallerCheckNeeded(pMeth) )
+ {
+ // Check for untrusted caller
+ // It is possible that wrappers like VBHelper libraries that are
+ // fully trusted, make calls to public methods that do not have
+ // safe for Untrusted caller custom attribute set.
+ // Like all other link demand that gets transformed to a full stack
+ // walk for reflection, calls to public methods also gets
+ // converted to full stack walk
+
+ // NOTE: this will always do the APTCA check, regardless of method caller
+ Security::DoUntrustedCallerChecks(NULL, pMeth, TRUE);
+ }
+#endif
+
+ // CAS Link Demands
+ if (gc.refClassCasDemands != NULL)
+ Security::DemandSet(SSWT_LATEBOUND_LINKDEMAND, gc.refClassCasDemands);
+
+ if (gc.refMethodCasDemands != NULL)
+ Security::DemandSet(SSWT_LATEBOUND_LINKDEMAND, gc.refMethodCasDemands);
+
+ // Non-CAS demands are not applied against a grant
+ // set, they're standalone.
+ if (gc.refClassNonCasDemands != NULL)
+ Security::CheckNonCasDemand(&gc.refClassNonCasDemands);
+
+ if (gc.refMethodNonCasDemands != NULL)
+ Security::CheckNonCasDemand(&gc.refMethodNonCasDemands);
+ }
+
+Exit1:;
+ GCPROTECT_END();
+}
+
+FCIMPL3(INT32, AppDomainNative::ExecuteAssembly, AppDomainBaseObject* refThisUNSAFE,
+ AssemblyBaseObject* assemblyNameUNSAFE, PTRArray* stringArgsUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ INT32 iRetVal = 0;
+
+ struct _gc
+ {
+ APPDOMAINREF refThis;
+ ASSEMBLYREF assemblyName;
+ PTRARRAYREF stringArgs;
+ } gc;
+
+ gc.refThis = (APPDOMAINREF) refThisUNSAFE;
+ gc.assemblyName = (ASSEMBLYREF) assemblyNameUNSAFE;
+ gc.stringArgs = (PTRARRAYREF) stringArgsUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
+
+ AppDomain* pDomain = ValidateArg(gc.refThis);
+
+ if (gc.assemblyName == NULL)
+ COMPlusThrow(kArgumentNullException, W("ArgumentNull_Generic"));
+
+ if((BaseDomain*) pDomain == SystemDomain::System())
+ COMPlusThrow(kUnauthorizedAccessException, W("UnauthorizedAccess_SystemDomain"));
+
+ Assembly* pAssembly = (Assembly*) gc.assemblyName->GetAssembly();
+
+ if (!pDomain->m_pRootAssembly)
+ pDomain->m_pRootAssembly = pAssembly;
+
+ MethodDesc *pEntryPointMethod;
+ {
+ pEntryPointMethod = pAssembly->GetEntryPoint();
+ if (pEntryPointMethod)
+ {
+ UpgradeLinkTimeCheckToLateBoundDemand(pEntryPointMethod);
+ }
+ }
+
+ BOOL bCreatedConsole = FALSE;
+
+#ifndef FEATURE_PAL
+ if (pAssembly->GetManifestFile()->GetSubsystem() == IMAGE_SUBSYSTEM_WINDOWS_CUI)
+ {
+ {
+ GCX_COOP();
+ Security::CheckBeforeAllocConsole(pDomain, pAssembly);
+ }
+ bCreatedConsole = AllocConsole();
+ StackSString codebase;
+ pAssembly->GetManifestFile()->GetCodeBase(codebase);
+ SetConsoleTitle(codebase);
+ }
+#endif // !FEATURE_PAL
+
+ // This helper will call FreeConsole()
+ iRetVal = ExecuteAssemblyHelper(pAssembly, bCreatedConsole, &gc.stringArgs);
+
+ HELPER_METHOD_FRAME_END();
+
+ return iRetVal;
+}
+FCIMPLEND
+
+#ifdef FEATURE_VERSIONING
+FCIMPL1(void,
+ AppDomainNative::CreateContext,
+ AppDomainBaseObject *refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ struct _gc
+ {
+ APPDOMAINREF refThis;
+ } gc;
+
+ gc.refThis = (APPDOMAINREF) refThisUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
+
+ AppDomain* pDomain = ValidateArg(gc.refThis);
+
+ if((BaseDomain*) pDomain == SystemDomain::System())
+ {
+ COMPlusThrow(kUnauthorizedAccessException, W("UnauthorizedAccess_SystemDomain"));
+ }
+
+ pDomain->CreateFusionContext();
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+void QCALLTYPE AppDomainNative::SetupBindingPaths(__in_z LPCWSTR wszTrustedPlatformAssemblies, __in_z LPCWSTR wszPlatformResourceRoots, __in_z LPCWSTR wszAppPaths, __in_z LPCWSTR wszAppNiPaths, __in_z LPCWSTR appLocalWinMD)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ AppDomain* pDomain = GetAppDomain();
+
+ SString sTrustedPlatformAssemblies(wszTrustedPlatformAssemblies);
+ SString sPlatformResourceRoots(wszPlatformResourceRoots);
+ SString sAppPaths(wszAppPaths);
+ SString sAppNiPaths(wszAppNiPaths);
+ SString sappLocalWinMD(appLocalWinMD);
+
+ CLRPrivBinderCoreCLR *pBinder = pDomain->GetTPABinderContext();
+ _ASSERTE(pBinder != NULL);
+ IfFailThrow(pBinder->SetupBindingPaths(sTrustedPlatformAssemblies,
+ sPlatformResourceRoots,
+ sAppPaths,
+ sAppNiPaths));
+
+#ifdef FEATURE_COMINTEROP
+ pDomain->SetWinrtApplicationContext(sappLocalWinMD);
+#endif
+
+ END_QCALL;
+}
+
+#endif // FEATURE_VERSIONING
+
+FCIMPL12(Object*, AppDomainNative::CreateDynamicAssembly, AppDomainBaseObject* refThisUNSAFE, AssemblyNameBaseObject* assemblyNameUNSAFE, Object* identityUNSAFE, StackCrawlMark* stackMark, Object* requiredPsetUNSAFE, Object* optionalPsetUNSAFE, Object* refusedPsetUNSAFE, U1Array *securityRulesBlobUNSAFE, U1Array *aptcaBlobUNSAFE, INT32 access, INT32 dwFlags, SecurityContextSource securityContextSource)
+{
+ FCALL_CONTRACT;
+
+ ASSEMBLYREF refRetVal = NULL;
+
+ //<TODO>
+ // @TODO: there MUST be a better way to do this...
+ //</TODO>
+ CreateDynamicAssemblyArgs args;
+
+ args.refThis = (APPDOMAINREF) refThisUNSAFE;
+ args.assemblyName = (ASSEMBLYNAMEREF) assemblyNameUNSAFE;
+ args.identity = (OBJECTREF) identityUNSAFE;
+ args.requiredPset = (OBJECTREF) requiredPsetUNSAFE;
+ args.optionalPset = (OBJECTREF) optionalPsetUNSAFE;
+ args.refusedPset = (OBJECTREF) refusedPsetUNSAFE;
+ args.securityRulesBlob = (U1ARRAYREF) securityRulesBlobUNSAFE;
+ args.aptcaBlob = (U1ARRAYREF) aptcaBlobUNSAFE;
+ args.loaderAllocator = NULL;
+
+ args.access = access;
+ args.flags = static_cast<DynamicAssemblyFlags>(dwFlags);
+ args.stackMark = stackMark;
+ args.securityContextSource = securityContextSource;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT((CreateDynamicAssemblyArgsGC&)args);
+
+ AppDomain* pAppDomain = ValidateArg(args.refThis);
+
+ Assembly *pAssembly = Assembly::CreateDynamic(pAppDomain, &args);
+
+ refRetVal = (ASSEMBLYREF) pAssembly->GetExposedObject();
+
+ HELPER_METHOD_FRAME_END();
+ return OBJECTREFToObject(refRetVal);
+}
+FCIMPLEND
+
+//---------------------------------------------------------------------------------------
+//
+// Returns true if the DisableFusionUpdatesFromADManager config switch is turned on.
+//
+// Arguments:
+// adhTarget - AppDomain to get domain manager information about
+//
+
+// static
+BOOL QCALLTYPE AppDomainNative::DisableFusionUpdatesFromADManager(QCall::AppDomainHandle adhTarget)
+{
+ QCALL_CONTRACT;
+
+ BOOL bUpdatesDisabled = FALSE;
+
+ BEGIN_QCALL;
+
+ bUpdatesDisabled = !!(g_pConfig->DisableFusionUpdatesFromADManager());
+
+ END_QCALL;
+
+ return bUpdatesDisabled;
+}
+
+#ifdef FEATURE_APPX
+
+//
+// Keep in sync with bcl\system\appdomain.cs
+//
+enum
+{
+ APPX_FLAGS_INITIALIZED = 0x01,
+
+ APPX_FLAGS_APPX_MODEL = 0x02,
+ APPX_FLAGS_APPX_DESIGN_MODE = 0x04,
+ APPX_FLAGS_APPX_NGEN = 0x08,
+ APPX_FLAGS_APPX_MASK = APPX_FLAGS_APPX_MODEL |
+ APPX_FLAGS_APPX_DESIGN_MODE |
+ APPX_FLAGS_APPX_NGEN,
+
+ APPX_FLAGS_API_CHECK = 0x10,
+};
+
+// static
+INT32 QCALLTYPE AppDomainNative::GetAppXFlags()
+{
+ QCALL_CONTRACT;
+
+ UINT32 flags = APPX_FLAGS_INITIALIZED;
+
+ BEGIN_QCALL;
+
+ if (AppX::IsAppXProcess())
+ {
+ flags |= APPX_FLAGS_APPX_MODEL;
+
+ if (AppX::IsAppXDesignMode())
+ flags |= APPX_FLAGS_APPX_DESIGN_MODE;
+ else
+ flags |= APPX_FLAGS_API_CHECK;
+
+ if (AppX::IsAppXNGen())
+ flags |= APPX_FLAGS_APPX_NGEN;
+ }
+
+ //
+ // 0: normal (only check in non-dev-mode APPX)
+ // 1: always check
+ // 2: never check
+ //
+ switch (g_pConfig->GetWindows8ProfileAPICheckFlag())
+ {
+ case 1:
+ flags |= APPX_FLAGS_API_CHECK;
+ break;
+ case 2:
+ flags &= ~APPX_FLAGS_API_CHECK;
+ break;
+ default:
+ break;
+ }
+
+ END_QCALL;
+
+ return flags;
+}
+
+#endif // FEATURE_APPX
+
+//---------------------------------------------------------------------------------------
+//
+// Get the assembly and type containing the AppDomainManager used for the current domain
+//
+// Arguments:
+// adhTarget - AppDomain to get domain manager information about
+// retAssembly - [out] assembly which contains the AppDomainManager
+// retType - [out] AppDomainManger for the domain
+//
+// Notes:
+// If the AppDomain does not have an AppDomainManager, retAssembly and retType will be null on return.
+//
+
+// static
+void QCALLTYPE AppDomainNative::GetAppDomainManagerType(QCall::AppDomainHandle adhTarget,
+ QCall::StringHandleOnStack shRetAssembly,
+ QCall::StringHandleOnStack shRetType)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ if (adhTarget->HasAppDomainManagerInfo())
+ {
+ shRetAssembly.Set(adhTarget->GetAppDomainManagerAsm());
+ shRetType.Set(adhTarget->GetAppDomainManagerType());
+ }
+ else
+ {
+ shRetAssembly.Set(static_cast<LPCWSTR>(NULL));
+ shRetType.Set(static_cast<LPCWSTR>(NULL));
+ }
+
+ END_QCALL;
+}
+
+//---------------------------------------------------------------------------------------
+//
+// Set the assembly and type containing the AppDomainManager to be used for the current domain
+//
+// Arguments:
+// adhTarget - AppDomain to set domain manager information for
+// wszAssembly - assembly which contains the AppDomainManager
+// wszType - AppDomainManger for the domain
+//
+
+// static
+void QCALLTYPE AppDomainNative::SetAppDomainManagerType(QCall::AppDomainHandle adhTarget,
+ __in_z LPCWSTR wszAssembly,
+ __in_z LPCWSTR wszType)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(wszAssembly));
+ PRECONDITION(CheckPointer(wszType));
+ PRECONDITION(!GetAppDomain()->HasAppDomainManagerInfo());
+ }
+ CONTRACTL_END;
+
+ BEGIN_QCALL;
+
+ // If the AppDomainManager type is the same as the domain manager setup by the CLR host, then we can
+ // propagate the host's initialization flags to the new domain as well;
+ EInitializeNewDomainFlags initializationFlags = eInitializeNewDomainFlags_None;
+ if (CorHost2::HasAppDomainManagerInfo())
+ {
+ if (wcscmp(CorHost2::GetAppDomainManagerAsm(), wszAssembly) == 0 &&
+ wcscmp(CorHost2::GetAppDomainManagerType(), wszType) == 0)
+ {
+ initializationFlags = CorHost2::GetAppDomainManagerInitializeNewDomainFlags();
+ }
+ }
+
+ adhTarget->SetAppDomainManagerInfo(wszAssembly, wszType, initializationFlags);
+
+ // If the initialization flags promise that the domain manager isn't going to modify security, then do a
+ // pre-resolution of the domain now so that we can do some basic verification of the state later. We
+ // don't care about the actual result now, just that the resolution took place to compare against later.
+ if (initializationFlags & eInitializeNewDomainFlags_NoSecurityChanges)
+ {
+ BOOL fIsFullyTrusted;
+ BOOL fIsHomogeneous;
+ adhTarget->GetSecurityDescriptor()->PreResolve(&fIsFullyTrusted, &fIsHomogeneous);
+ }
+
+ END_QCALL;
+}
+
+#ifdef FEATURE_APPDOMAINMANAGER_INITOPTIONS
+
+FCIMPL0(FC_BOOL_RET, AppDomainNative::HasHost)
+{
+ FCALL_CONTRACT;
+ FC_RETURN_BOOL(CorHost2::GetHostControl() != NULL);
+}
+FCIMPLEND
+
+//
+// Callback to the CLR host to register an AppDomainManager->AppDomain ID pair with it.
+//
+// Arguments:
+// punkAppDomainManager - COM reference to the AppDomainManager being registered with the host
+//
+
+// static
+void QCALLTYPE AppDomainNative::RegisterWithHost(IUnknown *punkAppDomainManager)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(punkAppDomainManager));
+ PRECONDITION(CheckPointer(CorHost2::GetHostControl()));
+ }
+ CONTRACTL_END;
+
+ BEGIN_QCALL;
+
+ EnsureComStarted();
+
+ IHostControl *pHostControl = CorHost2::GetHostControl();
+ ADID dwDomainId = SystemDomain::GetCurrentDomain()->GetId();
+ HRESULT hr = S_OK;
+
+ BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread());
+ hr = pHostControl->SetAppDomainManager(dwDomainId.m_dwId, punkAppDomainManager);
+ END_SO_TOLERANT_CODE_CALLING_HOST;
+
+ if (FAILED(hr))
+ {
+ ThrowHR(hr);
+ }
+
+ END_QCALL;
+}
+#endif // FEATURE_APPDOMAINMANAGER_INITOPTIONS
+
+FCIMPL1(void, AppDomainNative::SetHostSecurityManagerFlags, DWORD dwFlags);
+{
+ FCALL_CONTRACT;
+
+ HELPER_METHOD_FRAME_BEGIN_0();
+
+ GetThread()->GetDomain()->GetSecurityDescriptor()->SetHostSecurityManagerFlags(dwFlags);
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+// static
+void QCALLTYPE AppDomainNative::SetSecurityHomogeneousFlag(QCall::AppDomainHandle adhTarget,
+ BOOL fRuntimeSuppliedHomogenousGrantSet)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ IApplicationSecurityDescriptor *pAppSecDesc = adhTarget->GetSecurityDescriptor();
+ pAppSecDesc->SetHomogeneousFlag(fRuntimeSuppliedHomogenousGrantSet);
+
+ END_QCALL;
+}
+
+#ifdef FEATURE_CAS_POLICY
+
+// static
+void QCALLTYPE AppDomainNative::SetLegacyCasPolicyEnabled(QCall::AppDomainHandle adhTarget)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ IApplicationSecurityDescriptor *pAppSecDesc = adhTarget->GetSecurityDescriptor();
+ pAppSecDesc->SetLegacyCasPolicyEnabled();
+
+ END_QCALL;
+}
+
+// static
+BOOL QCALLTYPE AppDomainNative::IsLegacyCasPolicyEnabled(QCall::AppDomainHandle adhTarget)
+{
+ QCALL_CONTRACT;
+
+ BOOL fLegacyCasPolicy = FALSE;
+
+ BEGIN_QCALL;
+
+ IApplicationSecurityDescriptor *pAppSecDesc = adhTarget->GetSecurityDescriptor();
+ fLegacyCasPolicy = !!pAppSecDesc->IsLegacyCasPolicyEnabled();
+
+ END_QCALL;
+
+ return fLegacyCasPolicy;
+}
+
+#endif // FEATURE_CAS_POLICY
+
+#ifdef FEATURE_APTCA
+
+// static
+void QCALLTYPE AppDomainNative::SetCanonicalConditionalAptcaList(QCall::AppDomainHandle adhTarget,
+ LPCWSTR wszCanonicalConditionalAptcaList)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ IApplicationSecurityDescriptor *pAppSecDesc = adhTarget->GetSecurityDescriptor();
+
+ GCX_COOP();
+ pAppSecDesc->SetCanonicalConditionalAptcaList(wszCanonicalConditionalAptcaList);
+
+ END_QCALL;
+}
+
+#endif // FEATURE_APTCA
+
+FCIMPL1(Object*, AppDomainNative::GetFriendlyName, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ STRINGREF str = NULL;
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
+
+ AppDomain* pApp = ValidateArg(refThis);
+
+ LPCWSTR wstr = pApp->GetFriendlyName();
+ if (wstr)
+ str = StringObject::NewString(wstr);
+
+ HELPER_METHOD_FRAME_END();
+ return OBJECTREFToObject(str);
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, AppDomainNative::IsDefaultAppDomainForEvidence, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ BOOL retVal = FALSE;
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
+
+ AppDomain* pApp = ValidateArg((APPDOMAINREF) refThisUNSAFE);
+ retVal = pApp->GetSecurityDescriptor()->IsDefaultAppDomainEvidence();
+
+ HELPER_METHOD_FRAME_END();
+ FC_RETURN_BOOL(retVal);
+}
+FCIMPLEND
+
+FCIMPL2(Object*, AppDomainNative::GetAssemblies, AppDomainBaseObject* refThisUNSAFE, CLR_BOOL forIntrospection);
+{
+ FCALL_CONTRACT;
+
+ struct _gc
+ {
+ PTRARRAYREF AsmArray;
+ APPDOMAINREF refThis;
+ } gc;
+
+ gc.AsmArray = NULL;
+ gc.refThis = (APPDOMAINREF) refThisUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
+
+ MethodTable * pAssemblyClass = MscorlibBinder::GetClass(CLASS__ASSEMBLY);
+
+ AppDomain * pApp = ValidateArg(gc.refThis);
+
+ // Allocate an array with as many elements as there are assemblies in this
+ // appdomain. This will usually be correct, but there may be assemblies
+ // that are still loading, and those won't be included in the array of
+ // loaded assemblies. When that happens, the array will have some trailing
+ // NULL entries; those entries will need to be trimmed.
+ size_t nArrayElems = pApp->m_Assemblies.GetCount(pApp);
+ gc.AsmArray = (PTRARRAYREF) AllocateObjectArray(
+ (DWORD)nArrayElems,
+ pAssemblyClass);
+
+ size_t numAssemblies = 0;
+ {
+ // Iterate over the loaded assemblies in the appdomain, and add each one to
+ // to the array. Quit when the array is full, in case assemblies have been
+ // loaded into this appdomain, on another thread.
+ AppDomain::AssemblyIterator i = pApp->IterateAssembliesEx((AssemblyIterationFlags)(
+ kIncludeLoaded |
+ (forIntrospection ? kIncludeIntrospection : kIncludeExecution)));
+ CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
+
+ while (i.Next(pDomainAssembly.This()) && (numAssemblies < nArrayElems))
+ {
+ // Do not change this code. This is done this way to
+ // prevent a GC hole in the SetObjectReference() call. The compiler
+ // is free to pick the order of evaluation.
+ OBJECTREF o = (OBJECTREF)pDomainAssembly->GetExposedAssemblyObject();
+ if (o == NULL)
+ { // The assembly was collected and is not reachable from managed code anymore
+ continue;
+ }
+ gc.AsmArray->SetAt(numAssemblies++, o);
+ // If it is a collectible assembly, it is now referenced from the managed world, so we can
+ // release the native reference in the holder
+ }
+ }
+
+ // If we didn't fill the array, allocate a new array that is exactly the
+ // right size, and copy the data to it.
+ if (numAssemblies < nArrayElems)
+ {
+ PTRARRAYREF AsmArray2;
+ AsmArray2 = (PTRARRAYREF) AllocateObjectArray(
+ (DWORD)numAssemblies,
+ pAssemblyClass);
+
+ for (size_t ix = 0; ix < numAssemblies; ++ix)
+ {
+ AsmArray2->SetAt(ix, gc.AsmArray->GetAt(ix));
+ }
+
+ gc.AsmArray = AsmArray2;
+ }
+
+ HELPER_METHOD_FRAME_END();
+ return OBJECTREFToObject(gc.AsmArray);
+} // AppDomainNative::GetAssemblies
+FCIMPLEND
+
+
+FCIMPL1(void, AppDomainNative::Unload, INT32 dwId)
+{
+ FCALL_CONTRACT;
+
+ HELPER_METHOD_FRAME_BEGIN_0();
+
+ IfFailThrow(AppDomain::UnloadById(ADID(dwId),TRUE));
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, AppDomainNative::IsDomainIdValid, INT32 dwId)
+{
+ FCALL_CONTRACT;
+
+ BOOL retVal = FALSE;
+ HELPER_METHOD_FRAME_BEGIN_RET_0()
+
+ AppDomainFromIDHolder ad((ADID)dwId, TRUE);
+ retVal=!ad.IsUnloaded();
+ HELPER_METHOD_FRAME_END();
+ FC_RETURN_BOOL(retVal);
+}
+FCIMPLEND
+
+#ifdef FEATURE_REMOTING
+FCIMPL0(Object*, AppDomainNative::GetDefaultDomain)
+{
+ FCALL_CONTRACT;
+
+ APPDOMAINREF rv = NULL;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(rv);
+
+ if (GetThread()->GetDomain()->IsDefaultDomain())
+ rv = (APPDOMAINREF) SystemDomain::System()->DefaultDomain()->GetExposedObject();
+ else
+ rv = (APPDOMAINREF) SystemDomain::System()->DefaultDomain()->GetAppDomainProxy();
+
+ HELPER_METHOD_FRAME_END();
+ return OBJECTREFToObject(rv);
+}
+FCIMPLEND
+#endif
+
+FCIMPL1(INT32, AppDomainNative::GetId, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ INT32 iRetVal = 0;
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
+
+ AppDomain* pApp = ValidateArg(refThis);
+ // can only be accessed from within current domain
+ _ASSERTE(GetThread()->GetDomain() == pApp);
+
+ iRetVal = pApp->GetId().m_dwId;
+
+ HELPER_METHOD_FRAME_END();
+ return iRetVal;
+}
+FCIMPLEND
+
+FCIMPL1(void, AppDomainNative::ChangeSecurityPolicy, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+ HELPER_METHOD_FRAME_BEGIN_1(refThis);
+ AppDomain* pApp = ValidateArg(refThis);
+
+#ifdef FEATURE_FUSION
+
+ // We do not support sharing behavior of ALWAYS when using app-domain local security config
+ if (pApp->GetSharePolicy() == AppDomain::SHARE_POLICY_ALWAYS)
+ {
+ // We may not be able to reduce sharing policy at this point, if we have already loaded
+ // some non-GAC assemblies as domain neutral. For this case we must regrettably fail
+ // the whole operation.
+ if (!pApp->ReduceSharePolicyFromAlways())
+ ThrowHR(COR_E_CANNOT_SET_POLICY);
+ }
+#endif
+ pApp->GetSecurityDescriptor()->SetPolicyLevelFlag();
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+
+FCIMPL2(Object*, AppDomainNative::IsStringInterned, AppDomainBaseObject* refThisUNSAFE, StringObject* pStringUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ APPDOMAINREF refThis = (APPDOMAINREF)ObjectToOBJECTREF(refThisUNSAFE);
+ STRINGREF refString = ObjectToSTRINGREF(pStringUNSAFE);
+ STRINGREF* prefRetVal = NULL;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_2(refThis, refString);
+
+ ValidateArg(refThis);
+
+ if (refString == NULL)
+ COMPlusThrow(kArgumentNullException, W("ArgumentNull_String"));
+
+ prefRetVal = refThis->GetDomain()->IsStringInterned(&refString);
+
+ HELPER_METHOD_FRAME_END();
+
+ if (prefRetVal == NULL)
+ return NULL;
+
+ return OBJECTREFToObject(*prefRetVal);
+}
+FCIMPLEND
+
+FCIMPL2(Object*, AppDomainNative::GetOrInternString, AppDomainBaseObject* refThisUNSAFE, StringObject* pStringUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ STRINGREF refRetVal = NULL;
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+ STRINGREF pString = (STRINGREF) pStringUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_2(refThis, pString);
+
+ ValidateArg(refThis);
+
+ if (pString == NULL)
+ COMPlusThrow(kArgumentNullException, W("ArgumentNull_String"));
+
+ STRINGREF* stringVal = refThis->GetDomain()->GetOrInternString(&pString);
+ if (stringVal != NULL)
+ {
+ refRetVal = *stringVal;
+ }
+
+ HELPER_METHOD_FRAME_END();
+ return OBJECTREFToObject(refRetVal);
+}
+FCIMPLEND
+
+
+FCIMPL1(Object*, AppDomainNative::GetDynamicDir, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ STRINGREF str = NULL;
+#ifdef FEATURE_FUSION
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
+
+ AppDomain *pDomain = ValidateArg(refThis);
+ str = StringObject::NewString(pDomain->GetDynamicDir());
+ HELPER_METHOD_FRAME_END();
+#endif
+ return OBJECTREFToObject(str);
+}
+FCIMPLEND
+
+// static
+void QCALLTYPE AppDomainNative::GetGrantSet(QCall::AppDomainHandle adhTarget,
+ QCall::ObjectHandleOnStack retGrantSet)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ IApplicationSecurityDescriptor *pSecDesc = adhTarget->GetSecurityDescriptor();
+
+ GCX_COOP();
+ pSecDesc->Resolve();
+ retGrantSet.Set(pSecDesc->GetGrantedPermissionSet());
+
+ END_QCALL;
+}
+
+
+FCIMPL1(FC_BOOL_RET, AppDomainNative::IsUnloadingForcedFinalize, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ BOOL retVal = FALSE;
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
+
+ AppDomain* pApp = ValidateArg((APPDOMAINREF)refThis);
+ retVal = pApp->IsFinalized();
+
+ HELPER_METHOD_FRAME_END();
+ FC_RETURN_BOOL(retVal);
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, AppDomainNative::IsFinalizingForUnload, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ BOOL retVal = FALSE;
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
+
+ AppDomain* pApp = ValidateArg(refThis);
+ retVal = pApp->IsFinalizing();
+
+ HELPER_METHOD_FRAME_END();
+ FC_RETURN_BOOL(retVal);
+}
+FCIMPLEND
+
+FCIMPL2(StringObject*, AppDomainNative::nApplyPolicy, AppDomainBaseObject* refThisUNSAFE, AssemblyNameBaseObject* refAssemblyNameUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ struct _gc
+ {
+ APPDOMAINREF refThis;
+ ASSEMBLYNAMEREF assemblyName;
+ STRINGREF rv;
+ } gc;
+
+ gc.refThis = (APPDOMAINREF)refThisUNSAFE;
+ gc.assemblyName = (ASSEMBLYNAMEREF) refAssemblyNameUNSAFE;
+ gc.rv = NULL;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
+
+ AppDomain* pDomain;
+ pDomain = ValidateArg(gc.refThis);
+
+ if (gc.assemblyName == NULL)
+ {
+ COMPlusThrow(kArgumentNullException, W("ArgumentNull_AssemblyName"));
+ }
+ if( (gc.assemblyName->GetSimpleName() == NULL) )
+ {
+ COMPlusThrow(kArgumentException, W("Format_StringZeroLength"));
+ }
+ Thread *pThread = GetThread();
+ CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
+
+ // Initialize spec
+ AssemblySpec spec;
+ spec.InitializeSpec(&(pThread->m_MarshalAlloc),
+ &gc.assemblyName,
+ FALSE, /*fIsStringized*/
+ FALSE /*fForIntrospection*/
+ );
+
+ StackSString sDisplayName;
+
+#ifdef FEATURE_FUSION
+ {
+ GCX_PREEMP();
+
+ SafeComHolderPreemp<IAssemblyName> pAssemblyName(NULL);
+ SafeComHolderPreemp<IAssemblyName> pBoundName(NULL);
+ IfFailThrow(spec.CreateFusionName(&pAssemblyName));
+ HRESULT hr = PreBindAssembly(pDomain->GetFusionContext(),
+ pAssemblyName,
+ NULL, // pAsmParent (only needed to see if parent is loadfrom - in this case, we always want it to load in the normal ctx)
+ &pBoundName,
+ NULL // pvReserved
+ );
+ if (FAILED(hr) && hr != FUSION_E_REF_DEF_MISMATCH)
+ {
+ ThrowHR(hr);
+ }
+
+ FusionBind::GetAssemblyNameDisplayName(pBoundName, /*modifies*/sDisplayName, 0 /*flags*/);
+ }
+#else
+ spec.GetFileOrDisplayName(0,sDisplayName);
+#endif
+
+ gc.rv = StringObject::NewString(sDisplayName);
+
+ HELPER_METHOD_FRAME_END();
+ return (StringObject*)OBJECTREFToObject(gc.rv);
+}
+FCIMPLEND
+
+FCIMPL1(UINT32, AppDomainNative::GetAppDomainId, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ FCUnique(0x91);
+
+ UINT32 retVal = 0;
+ APPDOMAINREF domainRef = (APPDOMAINREF) refThisUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(domainRef);
+
+ AppDomain* pDomain = ValidateArg(domainRef);
+ retVal = pDomain->GetId().m_dwId;
+
+ HELPER_METHOD_FRAME_END();
+ return retVal;
+}
+FCIMPLEND
+
+FCIMPL1(void , AppDomainNative::PublishAnonymouslyHostedDynamicMethodsAssembly, AssemblyBaseObject * pAssemblyUNSAFE);
+{
+ CONTRACTL
+ {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
+ if (refAssembly == NULL)
+ FCThrowResVoid(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ DomainAssembly* pDomainAssembly = refAssembly->GetDomainAssembly();
+
+ pDomainAssembly->GetAppDomain()->SetAnonymouslyHostedDynamicMethodsAssembly(pDomainAssembly);
+}
+FCIMPLEND
+
+#ifdef FEATURE_CORECLR
+
+void QCALLTYPE AppDomainNative::SetNativeDllSearchDirectories(__in_z LPCWSTR wszNativeDllSearchDirectories)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(wszNativeDllSearchDirectories));
+ }
+ CONTRACTL_END;
+
+ BEGIN_QCALL;
+ AppDomain *pDomain = GetAppDomain();
+
+ SString sDirectories(wszNativeDllSearchDirectories);
+
+ if(sDirectories.GetCount() > 0)
+ {
+ SString::CIterator start = sDirectories.Begin();
+ SString::CIterator itr = sDirectories.Begin();
+ SString::CIterator end = sDirectories.End();
+ SString qualifiedPath;
+
+ while (itr != end)
+ {
+ start = itr;
+ BOOL found = sDirectories.Find(itr, W(';'));
+ if (!found)
+ {
+ itr = end;
+ }
+
+ SString qualifiedPath(sDirectories,start,itr);
+
+ if (found)
+ {
+ itr++;
+ }
+
+ unsigned len = qualifiedPath.GetCount();
+
+ if (len > 0)
+ {
+ if (qualifiedPath[len-1]!='\\')
+ {
+ qualifiedPath.Append('\\');
+ }
+
+ NewHolder<SString> stringHolder (new SString(qualifiedPath));
+ IfFailThrow(pDomain->m_NativeDllSearchDirectories.Append(stringHolder.GetValue()));
+ stringHolder.SuppressRelease();
+ }
+ }
+ }
+ END_QCALL;
+}
+
+#endif // FEATURE_CORECLR
+
+#ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
+FCIMPL0(void, AppDomainNative::EnableMonitoring)
+{
+ FCALL_CONTRACT;
+
+ HELPER_METHOD_FRAME_BEGIN_0();
+
+ EnableARM();
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+FCIMPL0(FC_BOOL_RET, AppDomainNative::MonitoringIsEnabled)
+{
+ FCALL_CONTRACT;
+
+ FC_GC_POLL_NOT_NEEDED();
+
+ FC_RETURN_BOOL(g_fEnableARM);
+}
+FCIMPLEND
+
+FCIMPL1(INT64, AppDomainNative::GetTotalProcessorTime, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ INT64 i64RetVal = -1;
+
+ if (g_fEnableARM)
+ {
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
+
+ AppDomain* pDomain = ValidateArg(refThis);
+ // can only be accessed from within current domain
+ _ASSERTE(GetThread()->GetDomain() == pDomain);
+
+ i64RetVal = (INT64)pDomain->QueryProcessorUsage();
+
+ HELPER_METHOD_FRAME_END();
+ }
+
+ return i64RetVal;
+}
+FCIMPLEND
+
+FCIMPL1(INT64, AppDomainNative::GetTotalAllocatedMemorySize, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ INT64 i64RetVal = -1;
+
+ if (g_fEnableARM)
+ {
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
+
+ AppDomain* pDomain = ValidateArg(refThis);
+ // can only be accessed from within current domain
+ _ASSERTE(GetThread()->GetDomain() == pDomain);
+
+ i64RetVal = (INT64)pDomain->GetAllocBytes();
+
+ HELPER_METHOD_FRAME_END();
+ }
+
+ return i64RetVal;
+}
+FCIMPLEND
+
+FCIMPL1(INT64, AppDomainNative::GetLastSurvivedMemorySize, AppDomainBaseObject* refThisUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ INT64 i64RetVal = -1;
+
+ if (g_fEnableARM)
+ {
+ APPDOMAINREF refThis = (APPDOMAINREF) refThisUNSAFE;
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
+
+ AppDomain* pDomain = ValidateArg(refThis);
+ // can only be accessed from within current domain
+ _ASSERTE(GetThread()->GetDomain() == pDomain);
+
+ i64RetVal = (INT64)pDomain->GetSurvivedBytes();
+
+ HELPER_METHOD_FRAME_END();
+ }
+
+ return i64RetVal;
+}
+FCIMPLEND
+
+FCIMPL0(INT64, AppDomainNative::GetLastSurvivedProcessMemorySize)
+{
+ FCALL_CONTRACT;
+
+ INT64 i64RetVal = -1;
+
+ if (g_fEnableARM)
+ {
+ i64RetVal = SystemDomain::GetTotalSurvivedBytes();
+ }
+
+ return i64RetVal;
+
+
+}
+FCIMPLEND
+#endif // FEATURE_APPDOMAIN_RESOURCE_MONITORING
+
+#if defined(FEATURE_HOSTED_BINDER) && defined(FEATURE_APPX_BINDER)
+ICLRPrivBinder * QCALLTYPE AppDomainNative::CreateDesignerContext(LPCWSTR *rgPaths,
+ UINT cPaths,
+ BOOL fShared)
+{
+ QCALL_CONTRACT;
+
+ ICLRPrivBinder *pRetVal = nullptr;
+
+ BEGIN_QCALL;
+ ReleaseHolder<ICLRPrivBinder> pBinder;
+
+ // The runtime check is done on the managed side to enable the debugger to use
+ // FuncEval to create designer contexts outside of DesignMode.
+ _ASSERTE(AppX::IsAppXDesignMode() || (AppX::IsAppXProcess() && CORDebuggerAttached()));
+
+ AppDomain *pAppDomain = GetAppDomain();
+
+ pBinder = CLRPrivBinderAppX::CreateParentedBinder(fShared ? pAppDomain->GetLoadContextHostBinder() : pAppDomain->GetSharedContextHostBinder(), CLRPrivTypeCacheWinRT::GetOrCreateTypeCache(), rgPaths, cPaths, fShared /* fCanUseNativeImages */);
+
+ {
+ BaseDomain::LockHolder lh(pAppDomain);
+ pAppDomain->AppDomainInterfaceReleaseList.Append(pRetVal);
+ }
+ pBinder.SuppressRelease();
+ pRetVal = pBinder;
+
+ END_QCALL;
+
+ return pRetVal;
+}
+
+void QCALLTYPE AppDomainNative::SetCurrentDesignerContext(BOOL fDesignerContext, ICLRPrivBinder *newContext)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ if (fDesignerContext)
+ {
+ GetAppDomain()->SetCurrentContextHostBinder(newContext);
+ }
+ else
+ {
+ // Managed code is responsible for ensuring this isn't called more than once per AppDomain.
+ GetAppDomain()->SetSharedContextHostBinder(newContext);
+ }
+
+ END_QCALL;
+}
+#endif // defined(FEATURE_HOSTED_BINDER) && defined(FEATURE_APPX_BINDER)
+