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 | |
6 | |
7 | #include "common.h" |
8 | #include "appdomain.hpp" |
9 | #include "appdomainnative.hpp" |
10 | #include "vars.hpp" |
11 | #include "eeconfig.h" |
12 | #include "appdomain.inl" |
13 | #include "eventtrace.h" |
14 | #if defined(FEATURE_APPX) |
15 | #include "appxutil.h" |
16 | #endif // FEATURE_APPX |
17 | #include "../binder/inc/clrprivbindercoreclr.h" |
18 | |
19 | #include "clr/fs/path.h" |
20 | using namespace clr::fs; |
21 | |
22 | FCIMPL3(Object*, AppDomainNative::CreateDynamicAssembly, AssemblyNameBaseObject* assemblyNameUNSAFE, StackCrawlMark* stackMark, INT32 access) |
23 | { |
24 | FCALL_CONTRACT; |
25 | |
26 | ASSEMBLYREF refRetVal = NULL; |
27 | |
28 | //<TODO> |
29 | // @TODO: there MUST be a better way to do this... |
30 | //</TODO> |
31 | CreateDynamicAssemblyArgs args; |
32 | |
33 | args.assemblyName = (ASSEMBLYNAMEREF) assemblyNameUNSAFE; |
34 | args.loaderAllocator = NULL; |
35 | |
36 | args.access = access; |
37 | args.stackMark = stackMark; |
38 | |
39 | HELPER_METHOD_FRAME_BEGIN_RET_PROTECT((CreateDynamicAssemblyArgsGC&)args); |
40 | |
41 | Assembly *pAssembly = Assembly::CreateDynamic(GetAppDomain(), &args); |
42 | |
43 | refRetVal = (ASSEMBLYREF) pAssembly->GetExposedObject(); |
44 | |
45 | HELPER_METHOD_FRAME_END(); |
46 | return OBJECTREFToObject(refRetVal); |
47 | } |
48 | FCIMPLEND |
49 | |
50 | #ifdef FEATURE_APPX |
51 | // static |
52 | BOOL QCALLTYPE AppDomainNative::IsAppXProcess() |
53 | { |
54 | QCALL_CONTRACT; |
55 | |
56 | BOOL result; |
57 | |
58 | BEGIN_QCALL; |
59 | |
60 | result = AppX::IsAppXProcess(); |
61 | |
62 | END_QCALL; |
63 | |
64 | return result; |
65 | } |
66 | #endif // FEATURE_APPX |
67 | |
68 | FCIMPL0(Object*, AppDomainNative::GetLoadedAssemblies) |
69 | { |
70 | FCALL_CONTRACT; |
71 | |
72 | struct _gc |
73 | { |
74 | PTRARRAYREF AsmArray; |
75 | } gc; |
76 | |
77 | gc.AsmArray = NULL; |
78 | |
79 | HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); |
80 | |
81 | MethodTable * pAssemblyClass = MscorlibBinder::GetClass(CLASS__ASSEMBLY); |
82 | |
83 | AppDomain * pApp = GetAppDomain(); |
84 | |
85 | // Allocate an array with as many elements as there are assemblies in this |
86 | // appdomain. This will usually be correct, but there may be assemblies |
87 | // that are still loading, and those won't be included in the array of |
88 | // loaded assemblies. When that happens, the array will have some trailing |
89 | // NULL entries; those entries will need to be trimmed. |
90 | size_t nArrayElems = pApp->m_Assemblies.GetCount(pApp); |
91 | gc.AsmArray = (PTRARRAYREF) AllocateObjectArray( |
92 | (DWORD)nArrayElems, |
93 | pAssemblyClass); |
94 | |
95 | size_t numAssemblies = 0; |
96 | { |
97 | // Iterate over the loaded assemblies in the appdomain, and add each one to |
98 | // to the array. Quit when the array is full, in case assemblies have been |
99 | // loaded into this appdomain, on another thread. |
100 | AppDomain::AssemblyIterator i = pApp->IterateAssembliesEx((AssemblyIterationFlags)( |
101 | kIncludeLoaded | kIncludeExecution)); |
102 | CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly; |
103 | |
104 | while (i.Next(pDomainAssembly.This()) && (numAssemblies < nArrayElems)) |
105 | { |
106 | // Do not change this code. This is done this way to |
107 | // prevent a GC hole in the SetObjectReference() call. The compiler |
108 | // is free to pick the order of evaluation. |
109 | OBJECTREF o = (OBJECTREF)pDomainAssembly->GetExposedAssemblyObject(); |
110 | if (o == NULL) |
111 | { // The assembly was collected and is not reachable from managed code anymore |
112 | continue; |
113 | } |
114 | gc.AsmArray->SetAt(numAssemblies++, o); |
115 | // If it is a collectible assembly, it is now referenced from the managed world, so we can |
116 | // release the native reference in the holder |
117 | } |
118 | } |
119 | |
120 | // If we didn't fill the array, allocate a new array that is exactly the |
121 | // right size, and copy the data to it. |
122 | if (numAssemblies < nArrayElems) |
123 | { |
124 | PTRARRAYREF AsmArray2; |
125 | AsmArray2 = (PTRARRAYREF) AllocateObjectArray( |
126 | (DWORD)numAssemblies, |
127 | pAssemblyClass); |
128 | |
129 | for (size_t ix = 0; ix < numAssemblies; ++ix) |
130 | { |
131 | AsmArray2->SetAt(ix, gc.AsmArray->GetAt(ix)); |
132 | } |
133 | |
134 | gc.AsmArray = AsmArray2; |
135 | } |
136 | |
137 | HELPER_METHOD_FRAME_END(); |
138 | return OBJECTREFToObject(gc.AsmArray); |
139 | } // AppDomainNative::GetAssemblies |
140 | FCIMPLEND |
141 | |
142 | FCIMPL1(Object*, AppDomainNative::IsStringInterned, StringObject* pStringUNSAFE) |
143 | { |
144 | FCALL_CONTRACT; |
145 | |
146 | STRINGREF refString = ObjectToSTRINGREF(pStringUNSAFE); |
147 | STRINGREF* prefRetVal = NULL; |
148 | |
149 | HELPER_METHOD_FRAME_BEGIN_RET_1(refString); |
150 | |
151 | if (refString == NULL) |
152 | COMPlusThrow(kArgumentNullException, W("ArgumentNull_String" )); |
153 | |
154 | prefRetVal = GetAppDomain()->IsStringInterned(&refString); |
155 | |
156 | HELPER_METHOD_FRAME_END(); |
157 | |
158 | if (prefRetVal == NULL) |
159 | return NULL; |
160 | |
161 | return OBJECTREFToObject(*prefRetVal); |
162 | } |
163 | FCIMPLEND |
164 | |
165 | FCIMPL1(Object*, AppDomainNative::GetOrInternString, StringObject* pStringUNSAFE) |
166 | { |
167 | FCALL_CONTRACT; |
168 | |
169 | STRINGREF refRetVal = NULL; |
170 | STRINGREF pString = (STRINGREF) pStringUNSAFE; |
171 | |
172 | HELPER_METHOD_FRAME_BEGIN_RET_1(pString); |
173 | |
174 | if (pString == NULL) |
175 | COMPlusThrow(kArgumentNullException, W("ArgumentNull_String" )); |
176 | |
177 | STRINGREF* stringVal = GetAppDomain()->GetOrInternString(&pString); |
178 | if (stringVal != NULL) |
179 | { |
180 | refRetVal = *stringVal; |
181 | } |
182 | |
183 | HELPER_METHOD_FRAME_END(); |
184 | return OBJECTREFToObject(refRetVal); |
185 | } |
186 | FCIMPLEND |
187 | |