Merge pull request #14619 from briansull/emitter-cleanup
[platform/upstream/coreclr.git] / src / vm / assemblynative.cpp
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 ** Header:  AssemblyNative.cpp
8 **
9 ** Purpose: Implements AssemblyNative (loader domain) architecture
10 **
11 **
12
13
14 **
15 ===========================================================*/
16
17 #include "common.h"
18
19 #include <shlwapi.h>
20 #include <stdlib.h>
21 #include "assemblynative.hpp"
22 #include "dllimport.h"
23 #include "field.h"
24 #include "assemblyname.hpp"
25 #include "eeconfig.h"
26 #include "strongname.h"
27 #include "interoputil.h"
28 #include "frames.h"
29 #include "typeparse.h"
30 #include "stackprobe.h"
31
32 #include "appdomainnative.hpp"
33 #include "../binder/inc/clrprivbindercoreclr.h"
34
35
36
37 FCIMPL7(Object*, AssemblyNative::Load, AssemblyNameBaseObject* assemblyNameUNSAFE, 
38         StringObject* codeBaseUNSAFE, 
39         AssemblyBaseObject* requestingAssemblyUNSAFE,
40         StackCrawlMark* stackMark,
41         ICLRPrivBinder * pPrivHostBinder,
42         CLR_BOOL fThrowOnFileNotFound,
43         INT_PTR ptrLoadContextBinder)
44 {
45     FCALL_CONTRACT;
46
47     struct _gc
48     {
49         ASSEMBLYNAMEREF assemblyName;
50         STRINGREF       codeBase;
51         ASSEMBLYREF     requestingAssembly; 
52         ASSEMBLYREF     rv;
53     } gc;
54
55     gc.assemblyName    = (ASSEMBLYNAMEREF) assemblyNameUNSAFE;
56     gc.codeBase        = (STRINGREF)       codeBaseUNSAFE;
57     gc.requestingAssembly    = (ASSEMBLYREF)     requestingAssemblyUNSAFE;
58     gc.rv              = NULL;
59
60     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
61
62     if (gc.assemblyName == NULL)
63         COMPlusThrow(kArgumentNullException, W("ArgumentNull_AssemblyName"));
64
65     Thread * pThread = GetThread();
66     CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
67
68     DomainAssembly * pParentAssembly = NULL;
69     Assembly * pRefAssembly = NULL;
70
71     if(gc.assemblyName->GetSimpleName() == NULL)
72     {
73         if (gc.codeBase == NULL)
74             COMPlusThrow(kArgumentException, W("Format_StringZeroLength"));
75     }
76     else
77     {
78         // name specified, if immersive ignore the codebase
79         if (GetThread()->GetDomain()->HasLoadContextHostBinder())
80             gc.codeBase = NULL;
81
82         // Compute parent assembly
83         if (gc.requestingAssembly == NULL)
84         {
85             pRefAssembly = SystemDomain::GetCallersAssembly(stackMark);
86         
87             // Cross-appdomain callers aren't allowed as the parent
88             if (pRefAssembly &&
89                 (pRefAssembly->GetDomain() != pThread->GetDomain()))
90             {
91                 pRefAssembly = NULL;
92             }
93         }
94         else
95             pRefAssembly = gc.requestingAssembly->GetAssembly();
96         
97         // Shared or collectible assemblies should not be used for the parent in the
98         // late-bound case.
99         if (pRefAssembly && (!pRefAssembly->IsDomainNeutral()) && (!pRefAssembly->IsCollectible()))
100         {
101             pParentAssembly= pRefAssembly->GetDomainAssembly();
102         }
103
104     }
105
106     // Initialize spec
107     AssemblySpec spec;
108     spec.InitializeSpec(&(pThread->m_MarshalAlloc), 
109                         &gc.assemblyName,
110                         FALSE,
111                         FALSE);
112     
113     if (!spec.HasUniqueIdentity())
114     {   // Insuficient assembly name for binding (e.g. ContentType=WindowsRuntime cannot bind by assembly name)
115         EEFileLoadException::Throw(&spec, COR_E_NOTSUPPORTED);
116     }
117     
118     if (pPrivHostBinder != NULL)
119     {
120         pParentAssembly = NULL;
121         spec.SetHostBinder(pPrivHostBinder);
122     }
123     
124     if (gc.codeBase != NULL)
125         spec.SetCodeBase(&(pThread->m_MarshalAlloc), &gc.codeBase);
126
127     if (pParentAssembly != NULL)
128         spec.SetParentAssembly(pParentAssembly);
129
130     // Have we been passed the reference to the binder against which this load should be triggered?
131     // If so, then use it to set the fallback load context binder.
132     if (ptrLoadContextBinder != NULL)
133     {
134         spec.SetFallbackLoadContextBinderForRequestingAssembly(reinterpret_cast<ICLRPrivBinder *>(ptrLoadContextBinder));
135         spec.SetPreferFallbackLoadContextBinder();
136     }
137     else if (pRefAssembly != NULL)
138     {
139         // If the requesting assembly has Fallback LoadContext binder available,
140         // then set it up in the AssemblySpec.
141         PEFile *pRefAssemblyManifestFile = pRefAssembly->GetManifestFile();
142         spec.SetFallbackLoadContextBinderForRequestingAssembly(pRefAssemblyManifestFile->GetFallbackLoadContextBinder());
143     }
144
145     Assembly *pAssembly;
146     
147     {
148         GCX_PREEMP();
149         pAssembly = spec.LoadAssembly(FILE_LOADED, fThrowOnFileNotFound, FALSE /*fRaisePrebindEvents*/, stackMark);
150     }
151
152     if (pAssembly != NULL)
153         gc.rv = (ASSEMBLYREF) pAssembly->GetExposedObject();
154     
155     HELPER_METHOD_FRAME_END();
156
157     return OBJECTREFToObject(gc.rv);
158 }
159 FCIMPLEND
160
161 /* static */
162 Assembly* AssemblyNative::LoadFromPEImage(ICLRPrivBinder* pBinderContext, PEImage *pILImage, PEImage *pNIImage)
163 {
164     CONTRACT(Assembly*)
165     {
166         STANDARD_VM_CHECK;
167         PRECONDITION(CheckPointer(pBinderContext));
168         POSTCONDITION(CheckPointer(RETVAL));
169     }
170     CONTRACT_END;
171     
172     Assembly *pLoadedAssembly = NULL;
173     
174     ReleaseHolder<ICLRPrivAssembly> pAssembly;
175     
176     // Get the correct PEImage to work with.
177     BOOL fIsNativeImage = TRUE;
178     PEImage *pImage = pNIImage;
179     if (pNIImage == NULL)
180     {
181         // Since we do not have a NI image, we are working with IL assembly
182         pImage = pILImage;
183         fIsNativeImage = FALSE;
184     }
185     _ASSERTE(pImage != NULL);
186     
187     BOOL fHadLoadFailure = FALSE;
188
189     // Force the image to be loaded and mapped so that subsequent loads do not
190     // map a duplicate copy.
191     if (pImage->IsFile())
192     {
193         pImage->Load();
194     }
195     else
196     {
197         pImage->LoadNoFile();
198     }
199     
200     DWORD dwMessageID = IDS_EE_FILELOAD_ERROR_GENERIC;
201     
202     // Set the caller's assembly to be mscorlib
203     DomainAssembly *pCallersAssembly = SystemDomain::System()->SystemAssembly()->GetDomainAssembly();
204     PEAssembly *pParentAssembly = pCallersAssembly->GetFile();
205     
206     // Initialize the AssemblySpec
207     AssemblySpec spec;
208     spec.InitializeSpec(TokenFromRid(1, mdtAssembly), pImage->GetMDImport(), pCallersAssembly);
209     spec.SetBindingContext(pBinderContext);
210     
211     HRESULT hr = S_OK;
212     PTR_AppDomain pCurDomain = GetAppDomain();
213     CLRPrivBinderCoreCLR *pTPABinder = pCurDomain->GetTPABinderContext();
214     if (!AreSameBinderInstance(pTPABinder, pBinderContext))
215     {
216         // We are working with custom Assembly Load Context so bind the assembly using it.
217         CLRPrivBinderAssemblyLoadContext *pBinder = reinterpret_cast<CLRPrivBinderAssemblyLoadContext *>(pBinderContext);
218         hr = pBinder->BindUsingPEImage(pImage, fIsNativeImage, &pAssembly);
219     }
220     else
221     {
222         // Bind the assembly using TPA binder
223         hr = pTPABinder->BindUsingPEImage(pImage, fIsNativeImage, &pAssembly);
224     }
225
226     if (hr != S_OK)
227     {
228         // Give a more specific message for the case when we found the assembly with the same name already loaded.
229         if (hr == COR_E_FILELOAD)
230         {
231             dwMessageID = IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT;
232         }
233         
234         StackSString name;
235         spec.GetFileOrDisplayName(0, name);
236         COMPlusThrowHR(COR_E_FILELOAD, dwMessageID, name);
237     }
238
239     BINDER_SPACE::Assembly* assem;
240     assem = BINDER_SPACE::GetAssemblyFromPrivAssemblyFast(pAssembly);
241     
242     PEAssemblyHolder pPEAssembly(PEAssembly::Open(pParentAssembly, assem->GetPEImage(), assem->GetNativePEImage(), pAssembly, FALSE));
243
244     DomainAssembly *pDomainAssembly = pCurDomain->LoadDomainAssembly(&spec, pPEAssembly, FILE_LOADED);
245     RETURN pDomainAssembly->GetAssembly();
246 }
247
248 /* static */
249 void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly)
250 {
251     QCALL_CONTRACT;
252
253     BEGIN_QCALL;
254     
255     PTR_AppDomain pCurDomain = GetAppDomain();
256
257     // Get the binder context in which the assembly will be loaded.
258     ICLRPrivBinder *pBinderContext = reinterpret_cast<ICLRPrivBinder*>(ptrNativeAssemblyLoadContext);
259     _ASSERTE(pBinderContext != NULL);
260         
261     // Form the PEImage for the ILAssembly. Incase of an exception, the holders will ensure
262     // the release of the image.
263     PEImageHolder pILImage, pNIImage;
264     
265     if (pwzILPath != NULL)
266     {
267         pILImage = PEImage::OpenImage(pwzILPath);
268         
269         // Need to verify that this is a valid CLR assembly. 
270         if (!pILImage->CheckILFormat())
271             ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);
272     }
273     
274     // Form the PEImage for the NI assembly, if specified
275     if (pwzNIPath != NULL)
276     {
277         pNIImage = PEImage::OpenImage(pwzNIPath, MDInternalImport_TrustedNativeImage);
278
279         if (pNIImage->HasReadyToRunHeader())
280         {
281             // ReadyToRun images are treated as IL images by the rest of the system
282             if (!pNIImage->CheckILFormat())
283                 ThrowHR(COR_E_BADIMAGEFORMAT);
284
285             pILImage = pNIImage.Extract();
286             pNIImage = NULL;
287         }
288         else
289         {
290             if (!pNIImage->CheckNativeFormat())
291                 ThrowHR(COR_E_BADIMAGEFORMAT);
292         }
293     }
294     
295     Assembly *pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinderContext, pILImage, pNIImage);
296     
297     {
298         GCX_COOP();
299         retLoadedAssembly.Set(pLoadedAssembly->GetExposedObject());
300     }
301
302     LOG((LF_CLASSLOADER, 
303             LL_INFO100, 
304             "\tLoaded assembly from a file\n"));
305     
306     END_QCALL;
307 }
308
309 // static
310 INT_PTR QCALLTYPE AssemblyNative::InternalLoadUnmanagedDllFromPath(LPCWSTR unmanagedLibraryPath)
311 {
312     QCALL_CONTRACT;
313
314     HMODULE moduleHandle = nullptr;
315
316     BEGIN_QCALL;
317
318     moduleHandle = NDirect::LoadLibraryFromPath(unmanagedLibraryPath);
319
320     END_QCALL;
321
322     return reinterpret_cast<INT_PTR>(moduleHandle);
323 }
324
325 /*static */
326 void QCALLTYPE AssemblyNative::LoadFromStream(INT_PTR ptrNativeAssemblyLoadContext, INT_PTR ptrAssemblyArray, 
327                                               INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, 
328                                               QCall::ObjectHandleOnStack retLoadedAssembly)
329 {
330     QCALL_CONTRACT;
331     
332     BEGIN_QCALL;
333     
334     // Ensure that the invariants are in place
335     _ASSERTE(ptrNativeAssemblyLoadContext != NULL);
336     _ASSERTE((ptrAssemblyArray != NULL) && (cbAssemblyArrayLength > 0));
337     _ASSERTE((ptrSymbolArray == NULL) || (cbSymbolArrayLength > 0));
338
339     // We must have a flat image stashed away since we need a private 
340     // copy of the data which we can verify before doing the mapping.
341     PVOID pAssemblyArray = reinterpret_cast<PVOID>(ptrAssemblyArray);
342
343     PEImageHolder pILImage(PEImage::LoadFlat(pAssemblyArray, (COUNT_T)cbAssemblyArrayLength));
344     
345     // Need to verify that this is a valid CLR assembly. 
346     if (!pILImage->CheckILFormat())
347         ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);
348     
349     // Get the binder context in which the assembly will be loaded
350     ICLRPrivBinder *pBinderContext = reinterpret_cast<ICLRPrivBinder*>(ptrNativeAssemblyLoadContext);
351     
352     // Pass the stream based assembly as IL and NI in an attempt to bind and load it
353     Assembly* pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinderContext, pILImage, NULL); 
354     {
355         GCX_COOP();
356         retLoadedAssembly.Set(pLoadedAssembly->GetExposedObject());
357     }
358
359     LOG((LF_CLASSLOADER, 
360             LL_INFO100, 
361             "\tLoaded assembly from a file\n"));
362             
363     // In order to assign the PDB image (if present),
364     // the resulting assembly's image needs to be exactly the one
365     // we created above. We need pointer comparison instead of pe image equivalence
366     // to avoid mixed binaries/PDB pairs of other images.
367     // This applies to both Desktop CLR and CoreCLR, with or without fusion.
368     BOOL fIsSameAssembly = (pLoadedAssembly->GetManifestFile()->GetILimage() == pILImage); 
369
370     // Setting the PDB info is only applicable for our original assembly.
371     // This applies to both Desktop CLR and CoreCLR, with or without fusion.
372     if (fIsSameAssembly)
373     {
374 #ifdef DEBUGGING_SUPPORTED
375         // If we were given symbols, save a copy of them.
376         if (ptrSymbolArray != NULL)
377         {
378             PBYTE pSymbolArray = reinterpret_cast<PBYTE>(ptrSymbolArray);
379             pLoadedAssembly->GetManifestModule()->SetSymbolBytes(pSymbolArray, (DWORD)cbSymbolArrayLength);
380         }
381 #endif // DEBUGGING_SUPPORTED
382     }
383
384     END_QCALL;
385 }
386
387 void QCALLTYPE AssemblyNative::GetLocation(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retString)
388 {
389     QCALL_CONTRACT;
390
391     BEGIN_QCALL;
392
393     {
394         retString.Set(pAssembly->GetFile()->GetPath());
395     }
396     
397     END_QCALL;
398 }
399
400 void QCALLTYPE AssemblyNative::GetType(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive)
401 {
402     CONTRACTL
403     {
404         QCALL_CHECK;
405         PRECONDITION(CheckPointer(wszName));
406     }
407     CONTRACTL_END;
408
409     TypeHandle retTypeHandle;
410
411     BEGIN_QCALL;
412
413     if (!wszName)
414         COMPlusThrowArgumentNull(W("name"), W("ArgumentNull_String"));
415
416     BOOL prohibitAsmQualifiedName = TRUE;
417
418     // Load the class from this assembly (fail if it is in a different one).
419     retTypeHandle = TypeName::GetTypeManaged(wszName, pAssembly, bThrowOnError, bIgnoreCase, pAssembly->IsIntrospectionOnly(), prohibitAsmQualifiedName, NULL, FALSE, (OBJECTREF*)keepAlive.m_ppObject);
420
421     if (!retTypeHandle.IsNull())
422     {
423          GCX_COOP();
424          retType.Set(retTypeHandle.GetManagedClassObject());
425     }
426
427     END_QCALL;
428
429     return;
430 }
431
432 void QCALLTYPE AssemblyNative::GetForwardedType(QCall::AssemblyHandle pAssembly, mdToken mdtExternalType, QCall::ObjectHandleOnStack retType)
433 {
434     CONTRACTL
435     {
436         QCALL_CHECK;
437     }
438     CONTRACTL_END;
439
440     BEGIN_QCALL;
441
442     HRESULT hr;
443     LPCSTR pszNameSpace;
444     LPCSTR pszClassName;
445     mdToken mdImpl;
446
447     Assembly * pAsm = pAssembly->GetAssembly();
448     Module *pManifestModule = pAsm->GetManifestModule();
449     IfFailThrow(pManifestModule->GetMDImport()->GetExportedTypeProps(mdtExternalType, &pszNameSpace, &pszClassName, &mdImpl, NULL, NULL));
450     if (TypeFromToken(mdImpl) == mdtAssemblyRef)
451     {
452         NameHandle typeName(pszNameSpace, pszClassName);
453         typeName.SetTypeToken(pManifestModule, mdtExternalType);
454         TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName);
455         {
456             GCX_COOP();
457             retType.Set(typeHnd.GetManagedClassObject());
458         }
459     }
460
461     END_QCALL;
462
463     return;
464 }
465
466 FCIMPL1(FC_BOOL_RET, AssemblyNative::IsDynamic, AssemblyBaseObject* pAssemblyUNSAFE)
467 {
468     FCALL_CONTRACT;
469
470     ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
471     
472     if (refAssembly == NULL)
473         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
474
475     FC_RETURN_BOOL(refAssembly->GetDomainAssembly()->GetFile()->IsDynamic());
476 }
477 FCIMPLEND
478
479 void QCALLTYPE AssemblyNative::GetVersion(QCall::AssemblyHandle pAssembly, INT32* pMajorVersion, INT32* pMinorVersion, INT32*pBuildNumber, INT32* pRevisionNumber)
480 {
481     QCALL_CONTRACT;
482
483     BEGIN_QCALL;
484
485     UINT16 major=0xffff, minor=0xffff, build=0xffff, revision=0xffff;
486
487     pAssembly->GetFile()->GetVersion(&major, &minor, &build, &revision);
488
489     *pMajorVersion = major;
490     *pMinorVersion = minor;
491     *pBuildNumber = build;
492     *pRevisionNumber = revision; 
493
494     END_QCALL;
495 }
496
497 void QCALLTYPE AssemblyNative::GetPublicKey(QCall::AssemblyHandle pAssembly, QCall::ObjectHandleOnStack retPublicKey)
498 {
499     QCALL_CONTRACT;
500
501     BEGIN_QCALL;
502
503     DWORD cbPublicKey = 0;
504     const void *pbPublicKey = pAssembly->GetFile()->GetPublicKey(&cbPublicKey);
505     retPublicKey.SetByteArray((BYTE *)pbPublicKey, cbPublicKey);
506
507     END_QCALL;
508 }
509
510 void QCALLTYPE AssemblyNative::GetSimpleName(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retSimpleName)
511 {
512     QCALL_CONTRACT;
513
514     BEGIN_QCALL;
515     retSimpleName.Set(pAssembly->GetSimpleName());
516     END_QCALL;    
517 }
518
519 void QCALLTYPE AssemblyNative::GetLocale(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retString)
520 {
521     QCALL_CONTRACT;
522
523     BEGIN_QCALL;
524
525     LPCUTF8 pLocale = pAssembly->GetFile()->GetLocale();
526     if(pLocale)
527     {
528         retString.Set(pLocale);
529     }
530     
531     END_QCALL;
532 }
533
534 void QCALLTYPE AssemblyNative::GetCodeBase(QCall::AssemblyHandle pAssembly, BOOL fCopiedName, QCall::StringHandleOnStack retString)
535 {
536     QCALL_CONTRACT;
537
538     BEGIN_QCALL;
539
540     StackSString codebase;
541
542     {
543         pAssembly->GetFile()->GetCodeBase(codebase);
544     }
545
546     retString.Set(codebase);
547
548     END_QCALL;
549 }
550
551 INT32 QCALLTYPE AssemblyNative::GetHashAlgorithm(QCall::AssemblyHandle pAssembly)
552 {
553     QCALL_CONTRACT;
554
555     INT32 retVal=0;
556     BEGIN_QCALL;
557     retVal = pAssembly->GetFile()->GetHashAlgId();
558     END_QCALL;
559     return retVal;
560 }
561
562 INT32 QCALLTYPE AssemblyNative::GetFlags(QCall::AssemblyHandle pAssembly)
563 {
564     QCALL_CONTRACT;
565
566     INT32 retVal=0;
567     BEGIN_QCALL;
568     retVal = pAssembly->GetFile()->GetFlags();
569     END_QCALL;
570     return retVal;
571 }
572
573 BYTE * QCALLTYPE AssemblyNative::GetResource(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, UINT64 * length, QCall::StackCrawlMarkHandle stackMark, BOOL skipSecurityCheck)
574 {
575     QCALL_CONTRACT;
576
577     PBYTE       pbInMemoryResource  = NULL;
578
579     BEGIN_QCALL;
580
581     if (wszName == NULL)
582         COMPlusThrow(kArgumentNullException, W("ArgumentNull_String"));
583
584     // Get the name in UTF8
585     SString name(SString::Literal, wszName);
586
587     StackScratchBuffer scratch;
588     LPCUTF8 pNameUTF8 = name.GetUTF8(scratch);
589
590     if (*pNameUTF8 == '\0')
591         COMPlusThrow(kArgumentException, W("Format_StringZeroLength"));
592
593     DWORD  cbResource;
594     if (pAssembly->GetResource(pNameUTF8, &cbResource,
595                                &pbInMemoryResource, NULL, NULL,
596                                NULL, stackMark, skipSecurityCheck, FALSE))
597     {
598         *length = cbResource;
599     }
600
601     END_QCALL;
602
603     // Can return null if resource file is zero-length
604     return pbInMemoryResource;
605 }
606
607 INT32 QCALLTYPE AssemblyNative::GetManifestResourceInfo(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, QCall::ObjectHandleOnStack retAssembly, QCall::StringHandleOnStack retFileName, QCall::StackCrawlMarkHandle stackMark)
608 {
609     QCALL_CONTRACT;
610
611     INT32 rv = -1;
612
613     BEGIN_QCALL;
614
615     if (wszName == NULL)
616         COMPlusThrow(kArgumentNullException, W("ArgumentNull_String"));
617
618     // Get the name in UTF8
619     SString name(SString::Literal, wszName);
620
621     StackScratchBuffer scratch;
622     LPCUTF8 pNameUTF8 = name.GetUTF8(scratch);
623
624     if (*pNameUTF8 == '\0')
625         COMPlusThrow(kArgumentException, W("Format_StringZeroLength"));
626
627     DomainAssembly * pReferencedAssembly = NULL;
628     LPCSTR pFileName = NULL;
629     DWORD dwLocation = 0;
630
631     if (pAssembly->GetResource(pNameUTF8, NULL, NULL, &pReferencedAssembly, &pFileName,
632                               &dwLocation, stackMark, FALSE, FALSE))
633     {
634         if (pFileName)
635             retFileName.Set(pFileName);
636
637         GCX_COOP();
638
639         if (pReferencedAssembly)
640             retAssembly.Set(pReferencedAssembly->GetExposedAssemblyObject());
641
642         rv = dwLocation;
643     }
644
645     END_QCALL;
646
647     return rv;
648 }
649
650 void QCALLTYPE AssemblyNative::GetModules(QCall::AssemblyHandle pAssembly, BOOL fLoadIfNotFound, BOOL fGetResourceModules, QCall::ObjectHandleOnStack retModules)
651 {
652     QCALL_CONTRACT;
653
654     BEGIN_QCALL;
655
656     HENUMInternalHolder phEnum(pAssembly->GetMDImport());
657     phEnum.EnumInit(mdtFile, mdTokenNil);
658
659     InlineSArray<DomainFile *, 8> modules;
660
661     modules.Append(pAssembly);
662
663     ReflectionModule *pOnDiskManifest = NULL;
664     if (pAssembly->GetAssembly()->NeedsToHideManifestForEmit())
665         pOnDiskManifest = pAssembly->GetAssembly()->GetOnDiskManifestModule();
666
667     mdFile mdFile;
668     while (pAssembly->GetMDImport()->EnumNext(&phEnum, &mdFile))
669     {
670         DomainFile *pModule = pAssembly->GetModule()->LoadModule(GetAppDomain(), mdFile, fGetResourceModules, !fLoadIfNotFound);
671
672         if (pModule && pModule->GetModule() != pOnDiskManifest) {
673             modules.Append(pModule);
674         }
675     }
676     
677     {
678         GCX_COOP();
679
680         PTRARRAYREF orModules = NULL;
681         
682         GCPROTECT_BEGIN(orModules);
683
684         // Return the modules
685         orModules = (PTRARRAYREF)AllocateObjectArray(modules.GetCount(), MscorlibBinder::GetClass(CLASS__MODULE));
686
687         for(COUNT_T i = 0; i < modules.GetCount(); i++)
688         {
689             DomainFile * pModule = modules[i];
690
691             OBJECTREF o = pModule->GetExposedModuleObject();
692             orModules->SetAt(i, o);
693         }
694
695         retModules.Set(orModules);
696
697         GCPROTECT_END();
698     }
699
700     END_QCALL;
701 }
702
703 BOOL QCALLTYPE AssemblyNative::GetNeutralResourcesLanguageAttribute(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack cultureName, INT16& outFallbackLocation)
704 {
705     CONTRACTL {
706         QCALL_CHECK;
707     } CONTRACTL_END;
708
709     BOOL retVal = FALSE;
710     BEGIN_QCALL;
711
712     _ASSERTE(pAssembly);
713     Assembly * pAsm = pAssembly->GetAssembly();
714     _ASSERTE(pAsm);
715     Module * pModule = pAsm->GetManifestModule();
716     _ASSERTE(pModule);
717
718     LPCUTF8 pszCultureName = NULL;
719     ULONG cultureNameLength = 0;
720     INT16 fallbackLocation = 0;
721
722     // find the attribute if it exists
723     if (pModule->GetNeutralResourcesLanguage(&pszCultureName, &cultureNameLength, &fallbackLocation, FALSE)) {
724         StackSString culture(SString::Utf8, pszCultureName, cultureNameLength);
725         cultureName.Set(culture);
726         outFallbackLocation = fallbackLocation;
727         retVal = TRUE;
728     }
729
730     END_QCALL;
731
732     return retVal;
733 }
734
735 void QCALLTYPE AssemblyNative::GetModule(QCall::AssemblyHandle pAssembly, LPCWSTR wszFileName, QCall::ObjectHandleOnStack retModule)
736 {
737     QCALL_CONTRACT;
738
739     BEGIN_QCALL;
740
741     Module * pModule = NULL;
742     
743     CQuickBytes qbLC;
744
745     if (wszFileName == NULL)
746         COMPlusThrow(kArgumentNullException, W("ArgumentNull_FileName"));
747     if (wszFileName[0] == W('\0'))
748         COMPlusThrow(kArgumentException, W("Argument_EmptyFileName"));
749
750
751     MAKE_UTF8PTR_FROMWIDE(szModuleName, wszFileName);
752
753
754     LPCUTF8 pModuleName = NULL;
755
756     if SUCCEEDED(pAssembly->GetDomainAssembly()->GetModule()->GetScopeName(&pModuleName))
757     {
758         if (::SString::_stricmp(pModuleName, szModuleName) == 0)
759             pModule = pAssembly->GetDomainAssembly()->GetModule();
760     }
761
762
763     if (pModule != NULL)
764     {
765         GCX_COOP();
766         retModule.Set(pModule->GetExposedObject());
767     }
768
769     END_QCALL;
770
771     return;
772 }
773
774 void QCALLTYPE AssemblyNative::GetExportedTypes(QCall::AssemblyHandle pAssembly, QCall::ObjectHandleOnStack retTypes)
775 {
776     QCALL_CONTRACT;
777
778     BEGIN_QCALL;
779
780     InlineSArray<TypeHandle, 20> types;
781
782     Assembly * pAsm = pAssembly->GetAssembly();
783     
784     IMDInternalImport *pImport = pAsm->GetManifestImport();
785
786     {
787         HENUMTypeDefInternalHolder phTDEnum(pImport);
788         phTDEnum.EnumTypeDefInit();
789
790         mdTypeDef mdTD;
791         while(pImport->EnumNext(&phTDEnum, &mdTD))
792         {
793             DWORD dwFlags;            
794             IfFailThrow(pImport->GetTypeDefProps(
795                 mdTD,
796                 &dwFlags,
797                 NULL));
798             
799             // nested type
800             mdTypeDef mdEncloser = mdTD;
801             while (SUCCEEDED(pImport->GetNestedClassProps(mdEncloser, &mdEncloser)) &&
802                    IsTdNestedPublic(dwFlags))
803             {
804                 IfFailThrow(pImport->GetTypeDefProps(
805                     mdEncloser, 
806                     &dwFlags, 
807                     NULL));
808             }
809             
810             if (IsTdPublic(dwFlags))
811             {
812                 TypeHandle typeHnd = ClassLoader::LoadTypeDefThrowing(pAsm->GetManifestModule(), mdTD, 
813                                                                       ClassLoader::ThrowIfNotFound, 
814                                                                       ClassLoader::PermitUninstDefOrRef);
815                 types.Append(typeHnd);
816             }
817         }
818     }
819
820     {
821         HENUMInternalHolder phCTEnum(pImport);
822         phCTEnum.EnumInit(mdtExportedType, mdTokenNil);
823
824         // Now get the ExportedTypes that don't have TD's in the manifest file
825         mdExportedType mdCT;
826         while(pImport->EnumNext(&phCTEnum, &mdCT))
827         {
828             mdToken mdImpl;
829             LPCSTR pszNameSpace;
830             LPCSTR pszClassName;
831             DWORD dwFlags;
832
833             IfFailThrow(pImport->GetExportedTypeProps(
834                 mdCT, 
835                 &pszNameSpace, 
836                 &pszClassName, 
837                 &mdImpl, 
838                 NULL,           //binding
839                 &dwFlags));
840             
841             // nested type
842             while ((TypeFromToken(mdImpl) == mdtExportedType) &&
843                    (mdImpl != mdExportedTypeNil) &&
844                    IsTdNestedPublic(dwFlags))
845             {
846                 IfFailThrow(pImport->GetExportedTypeProps(
847                     mdImpl, 
848                     NULL,       //namespace
849                     NULL,       //name
850                     &mdImpl, 
851                     NULL,       //binding
852                     &dwFlags));
853             }
854             
855             if ((TypeFromToken(mdImpl) == mdtFile) &&
856                 (mdImpl != mdFileNil) &&
857                 IsTdPublic(dwFlags))
858             {                
859                 NameHandle typeName(pszNameSpace, pszClassName);
860                 typeName.SetTypeToken(pAsm->GetManifestModule(), mdCT);
861                 TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName);
862
863                 types.Append(typeHnd);
864             }
865         }
866     }
867
868     {
869         GCX_COOP();
870
871         PTRARRAYREF orTypes = NULL;
872
873         GCPROTECT_BEGIN(orTypes);
874
875         // Return the types
876         orTypes = (PTRARRAYREF)AllocateObjectArray(types.GetCount(), MscorlibBinder::GetClass(CLASS__TYPE));
877
878         for(COUNT_T i = 0; i < types.GetCount(); i++)
879         {
880             TypeHandle typeHnd = types[i];
881
882             OBJECTREF o = typeHnd.GetManagedClassObject();
883             orTypes->SetAt(i, o);
884         }
885
886         retTypes.Set(orTypes);
887
888         GCPROTECT_END();
889     }
890
891     END_QCALL;
892 }
893
894 void QCALLTYPE AssemblyNative::GetForwardedTypes(QCall::AssemblyHandle pAssembly, QCall::ObjectHandleOnStack retTypes)
895 {
896     QCALL_CONTRACT;
897
898     BEGIN_QCALL;
899
900     InlineSArray<TypeHandle, 8> types;
901
902     Assembly * pAsm = pAssembly->GetAssembly();
903     
904     IMDInternalImport *pImport = pAsm->GetManifestImport();
905
906     // enumerate the ExportedTypes table
907     {
908         HENUMInternalHolder phCTEnum(pImport);
909         phCTEnum.EnumInit(mdtExportedType, mdTokenNil);
910
911         // Now get the ExportedTypes that don't have TD's in the manifest file
912         mdExportedType mdCT;
913         while(pImport->EnumNext(&phCTEnum, &mdCT))
914         {
915             mdToken mdImpl;
916             LPCSTR pszNameSpace;
917             LPCSTR pszClassName;
918             DWORD dwFlags;
919
920             IfFailThrow(pImport->GetExportedTypeProps(mdCT,
921                 &pszNameSpace,
922                 &pszClassName,
923                 &mdImpl,
924                 NULL, //binding
925                 &dwFlags));
926
927             if ((TypeFromToken(mdImpl) == mdtAssemblyRef) && (mdImpl != mdAssemblyRefNil))
928             {                
929                 NameHandle typeName(pszNameSpace, pszClassName);
930                 typeName.SetTypeToken(pAsm->GetManifestModule(), mdCT);
931                 TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName);
932
933                 types.Append(typeHnd);
934             }
935         }
936     }
937
938     // Populate retTypes
939     {
940         GCX_COOP();
941
942         PTRARRAYREF orTypes = NULL;
943
944         GCPROTECT_BEGIN(orTypes);
945
946         // Return the types
947         orTypes = (PTRARRAYREF)AllocateObjectArray(types.GetCount(), MscorlibBinder::GetClass(CLASS__TYPE));
948
949         for(COUNT_T i = 0; i < types.GetCount(); i++)
950         {
951             TypeHandle typeHnd = types[i];
952
953             OBJECTREF o = typeHnd.GetManagedClassObject();
954             orTypes->SetAt(i, o);
955         }
956
957         retTypes.Set(orTypes);
958
959         GCPROTECT_END();
960     }
961
962     END_QCALL;
963 }
964
965 FCIMPL1(Object*, AssemblyNative::GetManifestResourceNames, AssemblyBaseObject * pAssemblyUNSAFE)
966 {
967     FCALL_CONTRACT;
968
969     ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
970     
971     if (refAssembly == NULL)
972         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
973
974     DomainAssembly *pAssembly = refAssembly->GetDomainAssembly();
975     PTRARRAYREF rv = NULL;
976
977     HELPER_METHOD_FRAME_BEGIN_RET_2(rv, refAssembly);
978
979     IMDInternalImport *pImport = pAssembly->GetMDImport();
980
981     HENUMInternalHolder phEnum(pImport);
982     DWORD dwCount;
983
984     phEnum.EnumInit(mdtManifestResource, mdTokenNil);
985         dwCount = pImport->EnumGetCount(&phEnum);
986
987     PTRARRAYREF ItemArray = (PTRARRAYREF) AllocateObjectArray(dwCount, g_pStringClass);
988
989     mdManifestResource mdResource;
990
991     GCPROTECT_BEGIN(ItemArray);
992     for(DWORD i = 0;  i < dwCount; i++) {
993         pImport->EnumNext(&phEnum, &mdResource);
994         LPCSTR pszName = NULL;
995         
996         IfFailThrow(pImport->GetManifestResourceProps(
997             mdResource, 
998             &pszName,   // name
999             NULL,       // linkref
1000             NULL,       // offset
1001             NULL));     //flags
1002         
1003         OBJECTREF o = (OBJECTREF) StringObject::NewString(pszName);
1004         ItemArray->SetAt(i, o);
1005     }
1006     
1007     rv = ItemArray;
1008     GCPROTECT_END();
1009     
1010     HELPER_METHOD_FRAME_END();
1011     
1012     return OBJECTREFToObject(rv);
1013 }
1014 FCIMPLEND
1015
1016 FCIMPL1(Object*, AssemblyNative::GetReferencedAssemblies, AssemblyBaseObject * pAssemblyUNSAFE)
1017 {
1018     FCALL_CONTRACT;
1019
1020     struct _gc {
1021         PTRARRAYREF ItemArray;
1022         ASSEMBLYNAMEREF pObj;
1023         ASSEMBLYREF refAssembly;
1024     } gc;
1025     ZeroMemory(&gc, sizeof(gc));
1026
1027     gc.refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
1028
1029     if (gc.refAssembly == NULL)
1030         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1031
1032     DomainAssembly *pAssembly = gc.refAssembly->GetDomainAssembly();
1033
1034     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
1035
1036     IMDInternalImport *pImport = pAssembly->GetAssembly()->GetManifestImport();
1037
1038     MethodTable* pAsmNameClass = MscorlibBinder::GetClass(CLASS__ASSEMBLY_NAME);
1039
1040     HENUMInternalHolder phEnum(pImport);
1041     DWORD dwCount = 0;
1042
1043     phEnum.EnumInit(mdtAssemblyRef, mdTokenNil);
1044
1045     dwCount = pImport->EnumGetCount(&phEnum);
1046
1047     mdAssemblyRef mdAssemblyRef;
1048
1049     gc.ItemArray = (PTRARRAYREF) AllocateObjectArray(dwCount, pAsmNameClass);
1050     
1051     for(DWORD i = 0; i < dwCount; i++) 
1052     {
1053         pImport->EnumNext(&phEnum, &mdAssemblyRef);
1054     
1055         AssemblySpec spec;
1056         spec.InitializeSpec(mdAssemblyRef, pImport);                                             
1057
1058         gc.pObj = (ASSEMBLYNAMEREF) AllocateObject(pAsmNameClass);
1059         spec.AssemblyNameInit(&gc.pObj,NULL);
1060
1061         gc.ItemArray->SetAt(i, (OBJECTREF) gc.pObj);
1062     }
1063
1064     HELPER_METHOD_FRAME_END();
1065
1066     return OBJECTREFToObject(gc.ItemArray);
1067 }
1068 FCIMPLEND
1069
1070 void QCALLTYPE AssemblyNative::GetEntryPoint(QCall::AssemblyHandle pAssembly, QCall::ObjectHandleOnStack retMethod)
1071 {
1072     QCALL_CONTRACT;
1073
1074     MethodDesc* pMeth = NULL;
1075
1076     BEGIN_QCALL;
1077
1078     pMeth = pAssembly->GetAssembly()->GetEntryPoint();
1079     if (pMeth != NULL)
1080     {
1081         GCX_COOP();
1082         retMethod.Set(pMeth->GetStubMethodInfo());
1083     }
1084
1085     END_QCALL;
1086
1087     return;
1088 }
1089
1090 //---------------------------------------------------------------------------------------
1091 //
1092 // Get the raw bytes making up this assembly
1093 //
1094 // Arguments:
1095 //    pAssembly   - Assembly to get the data of
1096 //    retRawBytes - [out] raw bytes of the assembly
1097 //
1098
1099 // static
1100 void QCALLTYPE AssemblyNative::GetRawBytes(QCall::AssemblyHandle pAssembly,
1101                                            QCall::ObjectHandleOnStack retRawBytes)
1102 {
1103     QCALL_CONTRACT;
1104     BEGIN_QCALL;
1105
1106     PEFile *pPEFile = pAssembly->GetFile();
1107     if (pPEFile != NULL)
1108     {
1109         PEImage *pPEImage = pPEFile->GetILimage();
1110
1111         if (pPEImage != NULL)
1112         {
1113             SBuffer dataBuffer;
1114             pPEImage->GetImageBits(PEImageLayout::LAYOUT_FLAT, dataBuffer);
1115
1116             if (dataBuffer.GetSize() > 0)
1117             {
1118                 retRawBytes.SetByteArray(dataBuffer, dataBuffer.GetSize());
1119             }
1120         }
1121     }
1122     
1123     END_QCALL;
1124 }
1125
1126 //---------------------------------------------------------------------------------------
1127 //
1128 // Release QCALL for System.SafePEFileHandle
1129 //
1130 //
1131
1132 // static
1133 void QCALLTYPE AssemblyNative::ReleaseSafePEFileHandle(PEFile *pPEFile)
1134 {
1135     CONTRACTL
1136     {
1137         QCALL_CHECK;
1138         PRECONDITION(CheckPointer(pPEFile));
1139     }
1140     CONTRACTL_END;
1141
1142     BEGIN_QCALL;
1143
1144     pPEFile->Release();
1145
1146     END_QCALL;
1147 }
1148
1149 // save the manifest to disk!
1150 extern void ManagedBitnessFlagsToUnmanagedBitnessFlags(
1151     INT32 portableExecutableKind, INT32 imageFileMachine,
1152     DWORD* pPeFlags, DWORD* pCorhFlags);
1153
1154 void QCALLTYPE AssemblyNative::GetFullName(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retString)
1155 {
1156     QCALL_CONTRACT;
1157
1158     BEGIN_QCALL;
1159
1160     StackSString name;
1161     pAssembly->GetFile()->GetDisplayName(name);
1162     retString.Set(name);
1163
1164     END_QCALL;
1165 }
1166
1167 void QCALLTYPE AssemblyNative::GetExecutingAssembly(QCall::StackCrawlMarkHandle stackMark, QCall::ObjectHandleOnStack retAssembly)
1168 {
1169     QCALL_CONTRACT;
1170
1171     DomainAssembly * pExecutingAssembly = NULL;
1172     
1173     BEGIN_QCALL;
1174
1175     Assembly* pAssembly = SystemDomain::GetCallersAssembly(stackMark);
1176     if(pAssembly)
1177     {
1178         pExecutingAssembly = pAssembly->GetDomainAssembly();
1179         GCX_COOP();
1180         retAssembly.Set(pExecutingAssembly->GetExposedAssemblyObject());
1181     }
1182
1183     END_QCALL;
1184     return;
1185 }
1186
1187 void QCALLTYPE AssemblyNative::GetEntryAssembly(QCall::ObjectHandleOnStack retAssembly)
1188 {
1189     QCALL_CONTRACT;
1190
1191     BEGIN_QCALL;
1192
1193     DomainAssembly * pRootAssembly = NULL;
1194     Assembly * pAssembly = GetAppDomain()->m_pRootAssembly;
1195     
1196     if (pAssembly)
1197     {
1198         pRootAssembly = pAssembly->GetDomainAssembly();
1199         GCX_COOP();
1200         retAssembly.Set(pRootAssembly->GetExposedAssemblyObject());
1201     }
1202
1203     END_QCALL;
1204
1205     return;
1206 }
1207
1208 // return the on disk assembly module for reflection emit. This only works for dynamic assembly.
1209 FCIMPL1(ReflectModuleBaseObject *, AssemblyNative::GetOnDiskAssemblyModule, AssemblyBaseObject* pAssemblyUNSAFE)
1210 {
1211     FCALL_CONTRACT;
1212
1213     ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
1214     
1215     if (refAssembly == NULL)
1216         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1217
1218     DomainAssembly *pAssembly = refAssembly->GetDomainAssembly();
1219
1220     FC_RETURN_MODULE_OBJECT(pAssembly->GetCurrentAssembly()->GetOnDiskManifestModule(), refAssembly);
1221 }
1222 FCIMPLEND
1223
1224 // return the in memory assembly module for reflection emit. This only works for dynamic assembly.
1225 FCIMPL1(ReflectModuleBaseObject *, AssemblyNative::GetInMemoryAssemblyModule, AssemblyBaseObject* pAssemblyUNSAFE)
1226 {
1227     FCALL_CONTRACT;
1228
1229
1230     ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
1231     
1232     if (refAssembly == NULL)
1233         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1234
1235     DomainAssembly *pAssembly = refAssembly->GetDomainAssembly();
1236
1237     FC_RETURN_MODULE_OBJECT(pAssembly->GetCurrentModule(), refAssembly);
1238 }
1239 FCIMPLEND
1240
1241 void QCALLTYPE AssemblyNative::GetImageRuntimeVersion(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retString)
1242 {
1243     QCALL_CONTRACT;
1244
1245     BEGIN_QCALL;
1246
1247     // Retrieve the PEFile from the assembly.
1248     PEFile* pPEFile = pAssembly->GetFile();
1249     PREFIX_ASSUME(pPEFile!=NULL);
1250
1251     LPCSTR pszVersion = NULL;
1252     IfFailThrow(pPEFile->GetMDImport()->GetVersionString(&pszVersion));
1253
1254     SString version(SString::Utf8, pszVersion);
1255
1256     // Allocate a managed string that contains the version and return it.
1257     retString.Set(version);
1258
1259     END_QCALL;
1260 }
1261
1262
1263
1264 #ifdef FEATURE_APPX
1265 /*static*/
1266 BOOL QCALLTYPE AssemblyNative::IsDesignerBindingContext(QCall::AssemblyHandle pAssembly)
1267 {
1268     QCALL_CONTRACT;
1269
1270     BOOL fRet = FALSE;
1271
1272     BEGIN_QCALL;
1273
1274     PEFile *pPEFile = pAssembly->GetFile();
1275     fRet = pPEFile->IsDesignerBindingContext();
1276
1277     END_QCALL;
1278
1279     return fRet;
1280 }
1281 #endif // FEATURE_APPX
1282
1283 /*static*/
1284 INT_PTR QCALLTYPE AssemblyNative::InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext)
1285 {
1286     QCALL_CONTRACT;
1287
1288     INT_PTR ptrNativeAssemblyLoadContext = NULL;
1289     
1290     BEGIN_QCALL;
1291     
1292     // We do not need to take a lock since this method is invoked from the ctor of AssemblyLoadContext managed type and
1293     // only one thread is ever executing a ctor for a given instance.
1294     //
1295     
1296     // Initialize the assembly binder instance in the VM
1297     PTR_AppDomain pCurDomain = AppDomain::GetCurrentDomain();
1298     CLRPrivBinderCoreCLR *pTPABinderContext = pCurDomain->GetTPABinderContext();
1299     if (!fRepresentsTPALoadContext)
1300     {
1301         // Initialize a custom Assembly Load Context
1302         CLRPrivBinderAssemblyLoadContext *pBindContext = NULL;
1303         IfFailThrow(CLRPrivBinderAssemblyLoadContext::SetupContext(pCurDomain->GetId().m_dwId, pTPABinderContext, ptrManagedAssemblyLoadContext, &pBindContext));
1304         ptrNativeAssemblyLoadContext = reinterpret_cast<INT_PTR>(pBindContext);
1305     }
1306     else
1307     {
1308         // We are initializing the managed instance of Assembly Load Context that would represent the TPA binder.
1309         // First, confirm we do not have an existing managed ALC attached to the TPA binder.
1310         INT_PTR ptrTPAAssemblyLoadContext = pTPABinderContext->GetManagedAssemblyLoadContext();
1311         if ((ptrTPAAssemblyLoadContext != NULL) && (ptrTPAAssemblyLoadContext != ptrManagedAssemblyLoadContext))
1312         {
1313             COMPlusThrow(kInvalidOperationException, IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_TPA_BINDING_CONTEXT);
1314         }
1315
1316         // Attach the managed TPA binding context with the native one.
1317         pTPABinderContext->SetManagedAssemblyLoadContext(ptrManagedAssemblyLoadContext);
1318         ptrNativeAssemblyLoadContext = reinterpret_cast<INT_PTR>(pTPABinderContext);
1319     }
1320    
1321     END_QCALL;
1322     
1323     return ptrNativeAssemblyLoadContext;
1324 }
1325
1326 /*static*/
1327 BOOL QCALLTYPE AssemblyNative::OverrideDefaultAssemblyLoadContextForCurrentDomain(INT_PTR ptrNativeAssemblyLoadContext)
1328 {
1329     QCALL_CONTRACT;
1330     
1331     BOOL fOverrodeDefaultLoadContext = FALSE;
1332     
1333     BEGIN_QCALL;
1334     
1335     AppDomain *pCurDomain = AppDomain::GetCurrentDomain();
1336     
1337     if (pCurDomain->LockBindingModel())
1338     {
1339         // Only one thread will ever enter here - it will be the ones that actually locked the binding model
1340         //
1341         // AssemblyLoadContext should have a binder associated with it
1342         IUnknown *pOverrideBinder = reinterpret_cast<IUnknown *>(ptrNativeAssemblyLoadContext);
1343         _ASSERTE(pOverrideBinder != NULL);
1344         
1345         // Get reference to the current default context binder
1346         
1347         IUnknown * pCurrentDefaultContextBinder = pCurDomain->GetFusionContext();
1348         
1349         // The default context binder can never be null since the runtime always sets one up
1350         _ASSERTE(pCurrentDefaultContextBinder != NULL);
1351         
1352         // The default context should also be the same as TPABinder context
1353         _ASSERTE(pCurrentDefaultContextBinder == pCurDomain->GetTPABinderContext());
1354         
1355         // Override the default context binder in the VM
1356         pCurDomain->OverrideDefaultContextBinder(pOverrideBinder);
1357         
1358         fOverrodeDefaultLoadContext = TRUE;
1359     }
1360     
1361     END_QCALL;
1362     
1363     return fOverrodeDefaultLoadContext;
1364 }
1365
1366 BOOL QCALLTYPE AssemblyNative::CanUseAppPathAssemblyLoadContextInCurrentDomain()
1367 {
1368     QCALL_CONTRACT;
1369     
1370     BOOL fCanUseAppPathAssemblyLoadContext = FALSE;
1371     
1372     BEGIN_QCALL;
1373
1374     AppDomain *pCurDomain = AppDomain::GetCurrentDomain();
1375
1376     pCurDomain->LockBindingModel();
1377         
1378     fCanUseAppPathAssemblyLoadContext = !pCurDomain->IsHostAssemblyResolverInUse();
1379
1380     END_QCALL;
1381     
1382     return fCanUseAppPathAssemblyLoadContext;
1383 }
1384
1385 /*static*/
1386 INT_PTR QCALLTYPE AssemblyNative::GetLoadContextForAssembly(QCall::AssemblyHandle pAssembly)
1387 {
1388     QCALL_CONTRACT;
1389
1390     INT_PTR ptrManagedAssemblyLoadContext = NULL;
1391     
1392     BEGIN_QCALL;
1393     
1394     // Get the PEAssembly for the RuntimeAssembly
1395     PEFile *pPEFile = pAssembly->GetFile();
1396     PTR_PEAssembly pPEAssembly = pPEFile->AsAssembly();
1397     _ASSERTE(pAssembly != NULL);
1398    
1399     // Platform assemblies are semantically bound against the "Default" binder which could be the TPA Binder or
1400     // the overridden binder. In either case, the reference to the same will be returned when this QCall returns.
1401     if (!pPEAssembly->IsProfileAssembly())
1402     {
1403         // Get the binding context for the assembly.
1404         //
1405         ICLRPrivBinder *pOpaqueBinder = nullptr;
1406         AppDomain *pCurDomain = AppDomain::GetCurrentDomain();
1407         CLRPrivBinderCoreCLR *pTPABinder = pCurDomain->GetTPABinderContext();
1408
1409         
1410         // GetBindingContext returns a ICLRPrivAssembly which can be used to get access to the
1411         // actual ICLRPrivBinder instance in which the assembly was loaded.
1412         PTR_ICLRPrivBinder pBindingContext = pPEAssembly->GetBindingContext();
1413         UINT_PTR assemblyBinderID = 0;
1414         IfFailThrow(pBindingContext->GetBinderID(&assemblyBinderID));
1415
1416         // If the assembly was bound using the TPA binder,
1417         // then we will return the reference to "Default" binder from the managed implementation when this QCall returns.
1418         //
1419         // See earlier comment about "Default" binder for additional context.
1420         pOpaqueBinder = reinterpret_cast<ICLRPrivBinder *>(assemblyBinderID);
1421         
1422         // We should have a load context binder at this point.
1423         _ASSERTE(pOpaqueBinder != nullptr);
1424
1425         if (!AreSameBinderInstance(pTPABinder, pOpaqueBinder))
1426         {
1427             // Only CLRPrivBinderAssemblyLoadContext instance contains the reference to its
1428             // corresponding managed instance.
1429             CLRPrivBinderAssemblyLoadContext *pBinder = (CLRPrivBinderAssemblyLoadContext *)(pOpaqueBinder);
1430             
1431             // Fetch the managed binder reference from the native binder instance
1432             ptrManagedAssemblyLoadContext = pBinder->GetManagedAssemblyLoadContext();
1433             _ASSERTE(ptrManagedAssemblyLoadContext != NULL);
1434         }
1435     }
1436     
1437     END_QCALL;
1438     
1439     return ptrManagedAssemblyLoadContext;
1440 }
1441
1442 // static
1443 BOOL QCALLTYPE AssemblyNative::InternalTryGetRawMetadata(
1444     QCall::AssemblyHandle assembly,
1445     UINT8 **blobRef,
1446     INT32 *lengthRef)
1447 {
1448     QCALL_CONTRACT;
1449
1450     PTR_CVOID metadata = nullptr;
1451
1452     BEGIN_QCALL;
1453
1454     _ASSERTE(assembly != nullptr);
1455     _ASSERTE(blobRef != nullptr);
1456     _ASSERTE(lengthRef != nullptr);
1457
1458     static_assert_no_msg(sizeof(*lengthRef) == sizeof(COUNT_T));
1459     metadata = assembly->GetFile()->GetLoadedMetadata(reinterpret_cast<COUNT_T *>(lengthRef));
1460     *blobRef = reinterpret_cast<UINT8 *>(const_cast<PTR_VOID>(metadata));
1461     _ASSERTE(*lengthRef >= 0);
1462
1463     END_QCALL;
1464
1465     return metadata != nullptr;
1466 }