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