// 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. #include "common.h" #include "appdomain.hpp" #include "appdomainnative.hpp" #include "vars.hpp" #include "eeconfig.h" #include "appdomain.inl" #include "eventtrace.h" #if defined(FEATURE_APPX) #include "appxutil.h" #endif // FEATURE_APPX #include "../binder/inc/clrprivbindercoreclr.h" #include "clr/fs/path.h" using namespace clr::fs; FCIMPL3(Object*, AppDomainNative::CreateDynamicAssembly, AssemblyNameBaseObject* assemblyNameUNSAFE, StackCrawlMark* stackMark, INT32 access) { FCALL_CONTRACT; ASSEMBLYREF refRetVal = NULL; // // @TODO: there MUST be a better way to do this... // CreateDynamicAssemblyArgs args; args.assemblyName = (ASSEMBLYNAMEREF) assemblyNameUNSAFE; args.loaderAllocator = NULL; args.access = access; args.stackMark = stackMark; HELPER_METHOD_FRAME_BEGIN_RET_PROTECT((CreateDynamicAssemblyArgsGC&)args); Assembly *pAssembly = Assembly::CreateDynamic(GetAppDomain(), &args); refRetVal = (ASSEMBLYREF) pAssembly->GetExposedObject(); HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(refRetVal); } FCIMPLEND #ifdef FEATURE_APPX // static BOOL QCALLTYPE AppDomainNative::IsAppXProcess() { QCALL_CONTRACT; BOOL result; BEGIN_QCALL; result = AppX::IsAppXProcess(); END_QCALL; return result; } #endif // FEATURE_APPX FCIMPL0(Object*, AppDomainNative::GetLoadedAssemblies) { FCALL_CONTRACT; struct _gc { PTRARRAYREF AsmArray; } gc; gc.AsmArray = NULL; HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); MethodTable * pAssemblyClass = MscorlibBinder::GetClass(CLASS__ASSEMBLY); AppDomain * pApp = GetAppDomain(); // 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 | kIncludeExecution)); CollectibleAssemblyHolder 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(Object*, AppDomainNative::IsStringInterned, StringObject* pStringUNSAFE) { FCALL_CONTRACT; STRINGREF refString = ObjectToSTRINGREF(pStringUNSAFE); STRINGREF* prefRetVal = NULL; HELPER_METHOD_FRAME_BEGIN_RET_1(refString); if (refString == NULL) COMPlusThrow(kArgumentNullException, W("ArgumentNull_String")); prefRetVal = GetAppDomain()->IsStringInterned(&refString); HELPER_METHOD_FRAME_END(); if (prefRetVal == NULL) return NULL; return OBJECTREFToObject(*prefRetVal); } FCIMPLEND FCIMPL1(Object*, AppDomainNative::GetOrInternString, StringObject* pStringUNSAFE) { FCALL_CONTRACT; STRINGREF refRetVal = NULL; STRINGREF pString = (STRINGREF) pStringUNSAFE; HELPER_METHOD_FRAME_BEGIN_RET_1(pString); if (pString == NULL) COMPlusThrow(kArgumentNullException, W("ArgumentNull_String")); STRINGREF* stringVal = GetAppDomain()->GetOrInternString(&pString); if (stringVal != NULL) { refRetVal = *stringVal; } HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(refRetVal); } FCIMPLEND