Remove always defined FEATURE_CORECLR
[platform/upstream/coreclr.git] / src / vm / pefile.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 // PEFile.cpp
6 // 
7
8 // --------------------------------------------------------------------------------
9
10
11 #include "common.h"
12 #include "pefile.h"
13 #include "strongname.h"
14 #include "corperm.h"
15 #include "eecontract.h"
16 #include "apithreadstress.h"
17 #include "eeconfig.h"
18 #ifdef FEATURE_FUSION
19 #include "fusionpriv.h"
20 #include "shlwapi.h"
21 #endif
22 #include "product_version.h"
23 #include "eventtrace.h"
24 #include "security.h"
25 #include "corperm.h"
26 #include "dbginterface.h"
27 #include "peimagelayout.inl"
28 #include "dlwrap.h"
29 #include "invokeutil.h"
30 #ifdef FEATURE_PREJIT
31 #include "compile.h"
32 #endif
33 #include "strongnameinternal.h"
34
35 #ifdef FEATURE_VERSIONING
36 #include "../binder/inc/applicationcontext.hpp"
37 #endif
38
39 #ifndef FEATURE_FUSION
40 #include "clrprivbinderutil.h"
41 #include "../binder/inc/coreclrbindercommon.h"
42 #endif
43
44 #ifdef FEATURE_CAS_POLICY
45 #include <wintrust.h>
46 #endif
47
48 #ifdef FEATURE_PREJIT
49 #include "compile.h"
50
51 #ifdef DEBUGGING_SUPPORTED
52 SVAL_IMPL_INIT(DWORD, PEFile, s_NGENDebugFlags, 0);
53 #endif
54 #endif
55
56 #include "sha1.h"
57
58 #if defined(FEATURE_FUSION)
59 #include "clrprivbinderfusion.h"
60 #include "clrprivbinderappx.h"
61 #include "clrprivbinderloadfile.h" 
62 #endif
63
64 #ifndef DACCESS_COMPILE
65
66 // ================================================================================
67 // PEFile class - this is an abstract base class for PEModule and PEAssembly
68 // <TODO>@todo: rename TargetFile</TODO>
69 // ================================================================================
70
71 PEFile::PEFile(PEImage *identity, BOOL fCheckAuthenticodeSignature/*=TRUE*/) :
72 #if _DEBUG
73     m_pDebugName(NULL),
74 #endif
75     m_identity(NULL),
76     m_openedILimage(NULL),
77 #ifdef FEATURE_PREJIT    
78     m_nativeImage(NULL),
79     m_fCanUseNativeImage(TRUE),
80 #endif
81     m_MDImportIsRW_Debugger_Use_Only(FALSE),
82     m_bHasPersistentMDImport(FALSE),
83     m_pMDImport(NULL),
84     m_pImporter(NULL),
85     m_pEmitter(NULL),
86     m_pMetadataLock(::new SimpleRWLock(PREEMPTIVE, LOCK_TYPE_DEFAULT)),
87     m_refCount(1),
88     m_hash(NULL),
89     m_flags(0),
90     m_fStrongNameVerified(FALSE)
91 #ifdef FEATURE_CAS_POLICY
92     ,m_certificate(NULL),
93     m_fCheckedCertificate(FALSE)
94     ,m_pSecurityManager(NULL)
95     ,m_securityManagerLock(CrstPEFileSecurityManager)
96 #endif // FEATURE_CAS_POLICY
97     ,m_pHostAssembly(nullptr)
98 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
99     ,m_pFallbackLoadContextBinder(nullptr)
100 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
101 {
102     CONTRACTL
103     {
104         CONSTRUCTOR_CHECK;
105         THROWS;
106         GC_TRIGGERS;
107         MODE_ANY;
108     }
109     CONTRACTL_END;
110
111     if (identity)
112     {
113         identity->AddRef();
114         m_identity = identity;
115
116         if(identity->IsOpened())
117         {
118             //already opened, prepopulate
119             identity->AddRef();
120             m_openedILimage = identity;
121         }
122     }
123
124
125 #ifdef FEATURE_CAS_POLICY
126     if (fCheckAuthenticodeSignature)
127     {
128         CheckAuthenticodeSignature();
129     }
130 #endif // FEATURE_CAS_POLICY
131 }
132
133
134
135 PEFile::~PEFile()
136 {
137     CONTRACTL
138     {
139         DESTRUCTOR_CHECK;
140         NOTHROW;
141         GC_TRIGGERS;
142         MODE_ANY;
143     }
144     CONTRACTL_END;
145     
146     ReleaseMetadataInterfaces(TRUE);
147     
148     if (m_hash != NULL)
149         delete m_hash;
150
151 #ifdef FEATURE_PREJIT
152     if (m_nativeImage != NULL)
153     {
154         MarkNativeImageInvalidIfOwned();
155
156         m_nativeImage->Release();
157     }
158 #endif //FEATURE_PREJIT
159
160
161     if (m_openedILimage != NULL)
162         m_openedILimage->Release();
163     if (m_identity != NULL)
164         m_identity->Release();
165     if (m_pMetadataLock)
166         delete m_pMetadataLock;
167 #ifdef FEATURE_CAS_POLICY
168     if (m_pSecurityManager) {
169         m_pSecurityManager->Release();
170         m_pSecurityManager = NULL;
171     }
172     if (m_certificate && !g_pCertificateCache->Contains(m_certificate))
173         CoTaskMemFree(m_certificate);
174 #endif // FEATURE_CAS_POLICY
175
176     if (m_pHostAssembly != NULL)
177     {
178         m_pHostAssembly->Release();
179     }
180 }
181
182 #ifndef  DACCESS_COMPILE
183 void PEFile::ReleaseIL()
184 {
185     WRAPPER_NO_CONTRACT;
186     if (m_openedILimage!=NULL )
187     {
188         ReleaseMetadataInterfaces(TRUE, TRUE);
189         if (m_identity != NULL)
190         {
191             m_identity->Release();
192             m_identity=NULL;
193         }
194         m_openedILimage->Release();
195         m_openedILimage = NULL;
196     }
197 }
198 #endif
199
200 /* static */
201 PEFile *PEFile::Open(PEImage *image)
202 {
203     CONTRACT(PEFile *)
204     {
205         PRECONDITION(image != NULL);
206         PRECONDITION(image->CheckFormat());
207         POSTCONDITION(RETVAL != NULL);
208         POSTCONDITION(!RETVAL->IsModule());
209         POSTCONDITION(!RETVAL->IsAssembly());
210         THROWS;
211         GC_TRIGGERS;
212         MODE_ANY;
213         INJECT_FAULT(COMPlusThrowOM(););
214     }
215     CONTRACT_END;
216
217     PEFile *pFile = new PEFile(image, FALSE);
218
219     if (image->HasNTHeaders() && image->HasCorHeader())
220         pFile->OpenMDImport_Unsafe(); //no one else can see the object yet
221
222 #if _DEBUG
223     pFile->m_debugName = image->GetPath();
224     pFile->m_debugName.Normalize();
225     pFile->m_pDebugName = pFile->m_debugName;
226 #endif
227
228     RETURN pFile;
229 }
230
231 // ------------------------------------------------------------
232 // Loader support routines
233 // ------------------------------------------------------------
234
235 template<class T> void CoTaskFree(T *p)
236 {
237     if (p != NULL)
238     {
239         p->T::~T();
240
241         CoTaskMemFree(p);
242     }
243 }
244
245
246 NEW_WRAPPER_TEMPLATE1(CoTaskNewHolder, CoTaskFree<_TYPE>);
247
248 BOOL PEFile::CanLoadLibrary()
249 {
250     WRAPPER_NO_CONTRACT;
251
252     // Dynamic and resource modules don't need LoadLibrary.
253     if (IsDynamic() || IsResource()||IsLoaded())
254         return TRUE;
255
256     // If we're been granted skip verification, OK
257     if (HasSkipVerification())
258         return TRUE;
259
260     // Otherwise, we can only load if IL only.
261     return IsILOnly();
262 }
263
264 #ifdef FEATURE_MIXEDMODE
265
266 #ifndef CROSSGEN_COMPILE
267
268 // Returns TRUE if this file references managed CRT (msvcmNN*).
269 BOOL PEFile::ReferencesManagedCRT()
270 {
271     STANDARD_VM_CONTRACT;
272
273     IMDInternalImportHolder pImport = GetMDImport();
274     MDEnumHolder hEnum(pImport);
275
276     IfFailThrow(pImport->EnumInit(mdtModuleRef, mdTokenNil, &hEnum));
277
278     mdModuleRef tk;
279     while (pImport->EnumNext(&hEnum, &tk))
280     {
281         // we are looking for "msvcmNN*"
282         LPCSTR szName;
283         IfFailThrow(pImport->GetModuleRefProps(tk, &szName));
284         
285         if (_strnicmp(szName, "msvcm", 5) == 0 && isdigit(szName[5]) && isdigit(szName[6]))
286         {
287             return TRUE;
288         }
289     }
290
291     return FALSE;
292 }
293
294 void PEFile::CheckForDisallowedInProcSxSLoadWorker()
295 {
296     STANDARD_VM_CONTRACT;
297
298     // provide an opt-out switch for now
299     if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_DisableIJWVersionCheck) != 0)
300         return;
301
302     // ************************************************************************************************
303     // 1. See if this file should be checked
304     // The following checks filter out non-mixed mode assemblies that don't reference msvcmNN*. We only
305     // care about non-ILONLY images (IJW) or 2.0 C++/CLI pure images.
306     if (IsResource() || IsDynamic())
307         return;
308
309     // check the metadata version string
310     COUNT_T size;
311     PVOID pMetaData = (PVOID)GetMetadata(&size);
312     if (!pMetaData)
313     {
314         // No metadata section? Well somebody should have caught this earlier so report as
315         // ExecutionEngine rather than BIF.
316         EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
317     }
318
319     LPCSTR pVersion = NULL;
320     IfFailThrow(GetImageRuntimeVersionString(pMetaData, &pVersion));
321
322     char chV;
323     unsigned uiMajor, uiMinor;
324     BOOL fLegacyImage = (sscanf_s(pVersion, "%c%u.%u", &chV, 1, &uiMajor, &uiMinor) == 3 && (chV == W('v') || chV == W('V')) && uiMajor <= 2);
325
326     // Note that having VTFixups properly working really is limited to non-ILONLY images. In particular,
327     // the shim does not even attempt to patch ILONLY images in any way with bootstrap thunks.
328     if (IsILOnly())
329     {
330         // all >2.0 ILONLY images are fine because >2.0 managed CRTs can be loaded in multiple runtimes
331         if (!fLegacyImage)
332             return;
333
334         // legacy ILONLY images that don't reference the managed CRT are fine
335         if (!ReferencesManagedCRT())
336             return;
337     }
338
339     // get the version of this runtime
340     WCHAR wzThisRuntimeVersion[_MAX_PATH];
341     DWORD cchVersion = COUNTOF(wzThisRuntimeVersion);
342     IfFailThrow(g_pCLRRuntime->GetVersionString(wzThisRuntimeVersion, &cchVersion));
343     
344     // ************************************************************************************************
345     // 2. For legacy assemblies, verify that legacy APIs are/would be bound to this runtime
346     if (fLegacyImage)
347     {
348         WCHAR wzAPIVersion[_MAX_PATH];
349         bool fLegacyAPIsAreBound = false;
350      
351         {   // Check if the legacy APIs have already been bound to us using the new hosting APIs.
352             ReleaseHolder<ICLRMetaHost> pMetaHost;
353             IfFailThrow(CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost));
354
355             ReleaseHolder<ICLRRuntimeInfo> pInfo;
356             // Returns S_FALSE when no runtime is currently bound, S_OK when one is.
357             HRESULT hr = pMetaHost->QueryLegacyV2RuntimeBinding(IID_ICLRRuntimeInfo, (LPVOID*)&pInfo);
358             IfFailThrow(hr);
359
360             if (hr == S_OK)
361             {   // Legacy APIs are bound, now check if they are bound to us.
362                 fLegacyAPIsAreBound = true;
363
364                 cchVersion = COUNTOF(wzAPIVersion);
365                 IfFailThrow(pInfo->GetVersionString(wzAPIVersion, &cchVersion));
366
367                 if (SString::_wcsicmp(wzThisRuntimeVersion, wzAPIVersion) == 0)
368                 {   // This runtime is the one bound to the legacy APIs, ok to load legacy assembly.
369                     return;
370                 }
371             }
372         }
373
374 #ifdef _MSC_VER
375 #pragma warning(push)
376 #pragma warning(disable : 4996) // we are going to call deprecated APIs
377 #endif
378         // We need the above QueryLegacyV2RuntimeBinding check because GetRequestedRuntimeInfo will not take into
379         // account the current binding, which could have been set by the host rather than through an EXE config.
380         // If, however, the legacy APIs are not bound (indicated in fLegacyAPIsAreBound) then we can assume that
381         // the legacy APIs would bind using the equivalent of CorBindToRuntime(NULL) as a result of loading this
382         // legacy IJW assembly, and so we use GetRequestedRuntimeInfo to check without actually causing the bind.
383         // By avoiding causing the bind, we avoid a binding side effect in the failure case.
384         if (!fLegacyAPIsAreBound &&
385             SUCCEEDED(GetRequestedRuntimeInfo(NULL, NULL, NULL, 0,       // pExe, pwszVersion, pConfigurationFile, startupFlags
386                       RUNTIME_INFO_UPGRADE_VERSION | RUNTIME_INFO_DONT_RETURN_DIRECTORY | RUNTIME_INFO_DONT_SHOW_ERROR_DIALOG,
387                       NULL, 0, NULL,                                     // pDirectory, dwDirectory, pdwDirectoryLength
388                       wzAPIVersion, COUNTOF(wzAPIVersion), &cchVersion)))  // pVersion, cchBuffer, pdwLength
389         {
390             if (SString::_wcsicmp(wzThisRuntimeVersion, wzAPIVersion) == 0)
391             {
392                 // it came back as this version - call CorBindToRuntime to actually bind it
393                 ReleaseHolder<ICLRRuntimeHost> pHost;
394                 IfFailThrow(CorBindToRuntime(wzAPIVersion, NULL, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID *)&pHost));
395
396                 // and verify that nobody beat us to it
397                 IfFailThrow(GetCORVersion(wzAPIVersion, COUNTOF(wzAPIVersion), &cchVersion));
398
399                 if (SString::_wcsicmp(wzThisRuntimeVersion, wzAPIVersion) == 0)
400                 {
401                     // we have verified that when the assembly calls CorBindToRuntime(NULL),
402                     // it will get this runtime, so we allow it to be loaded
403                     return;
404                 }
405             }
406         }
407 #ifdef _MSC_VER
408 #pragma warning(pop)
409 #endif
410
411         MAKE_WIDEPTR_FROMUTF8(pwzVersion, pVersion);
412
413         ExternalLog(LF_LOADER, LL_ERROR, W("ERR: Rejecting IJW module built against %s because it could be loaded into another runtime in this process."), pwzVersion);
414         COMPlusThrow(kFileLoadException, IDS_EE_IJWLOAD_CROSSVERSION_DISALLOWED, pwzVersion, QUOTE_MACRO_L(VER_MAJORVERSION.VER_MINORVERSION));
415     }
416
417     // ************************************************************************************************
418     // 3. For 4.0+ assemblies, verify that it hasn't been loaded into another runtime
419     ReleaseHolder<ICLRRuntimeHostInternal> pRuntimeHostInternal;
420     IfFailThrow(g_pCLRRuntime->GetInterface(CLSID_CLRRuntimeHostInternal,
421                                             IID_ICLRRuntimeHostInternal,
422                                             &pRuntimeHostInternal));
423
424     PTR_VOID pModuleBase = GetLoadedIL()->GetBase();
425
426     ReleaseHolder<ICLRRuntimeInfo> pRuntimeInfo;
427     HRESULT hr = pRuntimeHostInternal->LockModuleForRuntime((BYTE *)pModuleBase, IID_ICLRRuntimeInfo, &pRuntimeInfo);
428     
429     IfFailThrow(hr);
430
431     if (hr == S_OK)
432     {
433         // this runtime was the first one to lock the module
434         return;
435     }
436
437     // another runtime has loaded this module so we have to block the load
438     WCHAR wzLoadedRuntimeVersion[_MAX_PATH];
439     cchVersion = COUNTOF(wzLoadedRuntimeVersion);
440     IfFailThrow(pRuntimeInfo->GetVersionString(wzLoadedRuntimeVersion, &cchVersion));
441
442     ExternalLog(LF_LOADER, LL_ERROR, W("ERR: Rejecting IJW module because it is already loaded into runtime version %s in this process."), wzLoadedRuntimeVersion);
443     COMPlusThrow(kFileLoadException, IDS_EE_IJWLOAD_MULTIRUNTIME_DISALLOWED, wzThisRuntimeVersion, wzLoadedRuntimeVersion);
444 }
445
446 // We don't allow loading IJW and C++/CLI pure images built against <=2.0 if legacy APIs are not bound to this
447 // runtime. For IJW images built against >2.0, we don't allow the load if the image has already been loaded by
448 // another runtime in this process.
449 void PEFile::CheckForDisallowedInProcSxSLoad()
450 {
451     STANDARD_VM_CONTRACT;
452
453     // have we checked this one before?
454     if (!IsInProcSxSLoadVerified())
455     {
456         CheckForDisallowedInProcSxSLoadWorker();
457
458         // if no exception was thrown, remember the fact that we don't have to do the check again
459         SetInProcSxSLoadVerified();
460     }
461 }
462
463 #else // CROSSGEN_COMPILE
464
465 void PEFile::CheckForDisallowedInProcSxSLoad()
466 {
467     // Noop for crossgen
468 }
469
470 #endif // CROSSGEN_COMPILE
471
472 #endif // FEATURE_MIXEDMODE
473
474
475 //-----------------------------------------------------------------------------------------------------
476 // Catch attempts to load x64 assemblies on x86, etc.
477 //-----------------------------------------------------------------------------------------------------
478 static void ValidatePEFileMachineType(PEFile *peFile)
479 {
480     STANDARD_VM_CONTRACT;
481
482     if (peFile->IsIntrospectionOnly())
483         return;    // ReflectionOnly assemblies permitted to violate CPU restrictions
484
485     if (peFile->IsDynamic())
486         return;    // PEFiles for ReflectionEmit assemblies don't cache the machine type.
487
488     if (peFile->IsResource())
489         return;    // PEFiles for resource assemblies don't cache the machine type.
490
491     if (peFile->HasNativeImage())
492         return;    // If it passed the native binder, no need to do the check again esp. at the risk of inviting an IL page-in.
493
494     DWORD peKind;
495     DWORD actualMachineType;
496     peFile->GetPEKindAndMachine(&peKind, &actualMachineType);
497
498     if (actualMachineType == IMAGE_FILE_MACHINE_I386 && ((peKind & (peILonly | pe32BitRequired)) == peILonly))
499         return;    // Image is marked CPU-agnostic.
500
501     if (actualMachineType != IMAGE_FILE_MACHINE_NATIVE && actualMachineType != IMAGE_FILE_MACHINE_NATIVE_NI)
502     {
503 #ifdef _TARGET_AMD64_
504         // v4.0 64-bit compatibility workaround. The 64-bit v4.0 CLR's Reflection.Load(byte[]) api does not detect cpu-matches. We should consider fixing that in
505         // the next SxS release. In the meantime, this bypass will retain compat for 64-bit v4.0 CLR for target platforms that existed at the time.
506         //
507         // Though this bypass kicks in for all Load() flavors, the other Load() flavors did detect cpu-matches through various other code paths that still exist.
508         // Or to put it another way, this #ifdef makes the (4.5 only) ValidatePEFileMachineType() a NOP for x64, hence preserving 4.0 compatibility.
509         if (actualMachineType == IMAGE_FILE_MACHINE_I386 || actualMachineType == IMAGE_FILE_MACHINE_IA64)
510             return;
511 #endif // _WIN64_
512
513         // Image has required machine that doesn't match the CLR.
514         StackSString name;
515         if (peFile->IsAssembly())
516             ((PEAssembly*)peFile)->GetDisplayName(name);
517         else
518             name = StackSString(SString::Utf8, peFile->GetSimpleName());
519
520         COMPlusThrow(kBadImageFormatException, IDS_CLASSLOAD_WRONGCPU, name.GetUnicode());
521     }
522
523     return;   // If we got here, all is good.
524 }
525
526 void PEFile::LoadLibrary(BOOL allowNativeSkip/*=TRUE*/) // if allowNativeSkip==FALSE force IL image load
527 {
528     CONTRACT_VOID
529     {
530         INSTANCE_CHECK;
531         POSTCONDITION(CheckLoaded());
532         STANDARD_VM_CHECK;
533     }
534     CONTRACT_END;
535
536     // Catch attempts to load x64 assemblies on x86, etc.
537     ValidatePEFileMachineType(this);
538
539     // See if we've already loaded it.
540     if (CheckLoaded(allowNativeSkip))
541     {
542 #ifdef FEATURE_MIXEDMODE
543         // Prevent loading C++/CLI images into multiple runtimes in the same process. Note that if ILOnly images
544         // stop being LoadLibrary'ed, the check for pure 2.0 C++/CLI images will need to be done somewhere else.
545         if (!IsIntrospectionOnly())
546             CheckForDisallowedInProcSxSLoad();
547 #endif // FEATURE_MIXEDMODE
548         RETURN;
549     }
550
551     // Note that we may be racing other threads here, in the case of domain neutral files
552
553     // Resource images are always flat.
554     if (IsResource())
555     {
556         GetILimage()->LoadNoMetaData(IsIntrospectionOnly());
557         RETURN;
558     }
559
560 #if !defined(_WIN64)
561     if (!HasNativeImage() && (!GetILimage()->Has32BitNTHeaders()) && !IsIntrospectionOnly())
562     {
563         // Tried to load 64-bit assembly on 32-bit platform.
564         EEFileLoadException::Throw(this, COR_E_BADIMAGEFORMAT, NULL);
565     }
566 #endif
567
568     // Don't do this if we are unverifiable
569     if (!CanLoadLibrary())
570         ThrowHR(SECURITY_E_UNVERIFIABLE);
571
572
573     // We need contents now
574     if (!HasNativeImage())
575     {
576         EnsureImageOpened();
577     }
578
579     if (IsIntrospectionOnly())
580     {
581         GetILimage()->LoadForIntrospection();
582         RETURN;
583     }
584
585
586     //---- Below this point, only do the things necessary for execution ----
587     _ASSERTE(!IsIntrospectionOnly());
588
589 #ifdef FEATURE_PREJIT
590     // For on-disk Dlls, we can call LoadLibrary
591     if (IsDll() && !((HasNativeImage()?m_nativeImage:GetILimage())->GetPath().IsEmpty()))
592     {
593         // Note that we may get a DllMain notification inside here.
594         if (allowNativeSkip && HasNativeImage())
595         {
596             m_nativeImage->Load();
597             if(!m_nativeImage->IsNativeILILOnly())
598                 GetILimage()->Load();             // For IJW we have to load IL also...
599         }
600         else
601             GetILimage()->Load();
602     }
603     else
604 #endif // FEATURE_PREJIT
605     {
606
607         // Since we couldn't call LoadLibrary, we must be an IL only image
608         // or the image may still contain unfixed up stuff
609         // Note that we make an exception for CompilationDomains, since PEImage
610         // will map non-ILOnly images in a compilation domain.
611         if (!GetILimage()->IsILOnly() && !GetAppDomain()->IsCompilationDomain())
612         {
613             if (!GetILimage()->HasV1Metadata())
614                 ThrowHR(COR_E_FIXUPSINEXE); // <TODO>@todo: better error</TODO>            
615         }
616
617
618
619         // If we are already mapped, we can just use the current image.
620 #ifdef FEATURE_PREJIT
621         if (allowNativeSkip && HasNativeImage())
622         {
623             m_nativeImage->LoadFromMapped();
624
625             if( !m_nativeImage->IsNativeILILOnly())
626                 GetILimage()->LoadFromMapped();        // For IJW we have to load IL also...
627         }
628         else
629 #endif
630         {
631             if (GetILimage()->IsFile())
632                 GetILimage()->LoadFromMapped();
633             else
634                 GetILimage()->LoadNoFile();
635         }
636     }
637
638 #ifdef FEATURE_MIXEDMODE
639     // Prevent loading C++/CLI images into multiple runtimes in the same process. Note that if ILOnly images
640     // stop being LoadLibrary'ed, the check for pure 2.0 C++/CLI images will need to be done somewhere else.
641     CheckForDisallowedInProcSxSLoad();
642 #endif // FEATURE_MIXEDMODE
643
644     RETURN;
645 }
646
647 void PEFile::SetLoadedHMODULE(HMODULE hMod)
648 {
649     CONTRACT_VOID
650     {
651         INSTANCE_CHECK;
652         PRECONDITION(CheckPointer(hMod));
653         PRECONDITION(CanLoadLibrary());
654         POSTCONDITION(CheckLoaded());
655         THROWS;
656         GC_TRIGGERS;
657         MODE_ANY;
658         INJECT_FAULT(COMPlusThrowOM(););
659     }
660     CONTRACT_END;
661
662     // See if the image is an internal PEImage.
663     GetILimage()->SetLoadedHMODULE(hMod);
664
665     RETURN;
666 }
667
668 /* static */
669 void PEFile::DefineEmitScope(
670     GUID   iid, 
671     void **ppEmit)
672 {
673     CONTRACT_VOID
674     {
675         PRECONDITION(CheckPointer(ppEmit));
676         POSTCONDITION(CheckPointer(*ppEmit));
677         THROWS;
678         GC_TRIGGERS;
679         MODE_ANY;
680         INJECT_FAULT(COMPlusThrowOM(););
681     }
682     CONTRACT_END;
683     
684     SafeComHolder<IMetaDataDispenserEx> pDispenser;
685     
686     // Get the Dispenser interface.
687     MetaDataGetDispenser(
688         CLSID_CorMetaDataDispenser, 
689         IID_IMetaDataDispenserEx, 
690         (void **)&pDispenser);
691     if (pDispenser == NULL)
692     {
693         ThrowOutOfMemory();
694     }
695     
696     // Set the option on the dispenser turn on duplicate check for TypeDef and moduleRef
697     VARIANT varOption;
698     V_VT(&varOption) = VT_UI4;
699     V_I4(&varOption) = MDDupDefault | MDDupTypeDef | MDDupModuleRef | MDDupExportedType | MDDupAssemblyRef | MDDupPermission | MDDupFile;
700     IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor, &varOption));
701     
702     // Set minimal MetaData size
703     V_VT(&varOption) = VT_UI4;
704     V_I4(&varOption) = MDInitialSizeMinimal;
705     IfFailThrow(pDispenser->SetOption(MetaDataInitialSize, &varOption));
706     
707     // turn on the thread safety!
708     V_I4(&varOption) = MDThreadSafetyOn;
709     IfFailThrow(pDispenser->SetOption(MetaDataThreadSafetyOptions, &varOption));
710     
711     IfFailThrow(pDispenser->DefineScope(CLSID_CorMetaDataRuntime, 0, iid, (IUnknown **)ppEmit));
712     
713     RETURN;
714 } // PEFile::DefineEmitScope
715
716 // ------------------------------------------------------------
717 // Identity
718 // ------------------------------------------------------------
719
720 BOOL PEFile::Equals(PEFile *pFile)
721 {
722     CONTRACTL
723     {
724         INSTANCE_CHECK;
725         PRECONDITION(CheckPointer(pFile));
726         GC_NOTRIGGER;
727         NOTHROW;
728         CANNOT_TAKE_LOCK;
729         MODE_ANY;
730     }
731     CONTRACTL_END;
732
733     // Same object is equal
734     if (pFile == this)
735         return TRUE;
736
737
738     // Execution and introspection files are NOT equal
739     if ( (!IsIntrospectionOnly()) != !(pFile->IsIntrospectionOnly()) )
740     {
741         return FALSE;
742     }
743
744     // Different host assemblies cannot be equal unless they are associated with the same host binder
745     // It's ok if only one has a host binder because multiple threads can race to load the same assembly
746     // and that may cause temporary candidate PEAssembly objects that never get bound to a host assembly
747     // because another thread beats it; the losing thread will pick up the PEAssembly in the cache.
748     if (pFile->HasHostAssembly() && this->HasHostAssembly())
749     {
750         UINT_PTR fileBinderId = 0;
751         if (FAILED(pFile->GetHostAssembly()->GetBinderID(&fileBinderId)))
752             return FALSE;
753
754         UINT_PTR thisBinderId = 0;
755         if (FAILED(this->GetHostAssembly()->GetBinderID(&thisBinderId)))
756             return FALSE;
757
758         if (fileBinderId != thisBinderId)
759             return FALSE;
760
761     }
762
763     // Same identity is equal
764     if (m_identity != NULL && pFile->m_identity != NULL
765         && m_identity->Equals(pFile->m_identity))
766         return TRUE;
767
768     // Same image is equal
769     if (m_openedILimage != NULL && pFile->m_openedILimage != NULL
770         && m_openedILimage->Equals(pFile->m_openedILimage))
771         return TRUE;
772
773     return FALSE;
774 }
775
776 BOOL PEFile::Equals(PEImage *pImage)
777 {
778     CONTRACTL
779     {
780         INSTANCE_CHECK;
781         PRECONDITION(CheckPointer(pImage));
782         GC_NOTRIGGER;
783         NOTHROW;
784         MODE_ANY;
785     }
786     CONTRACTL_END;
787
788     // Same object is equal
789     if (pImage == m_identity || pImage == m_openedILimage)
790         return TRUE;
791
792 #ifdef FEATURE_PREJIT
793     if(pImage == m_nativeImage)
794         return TRUE;
795 #endif    
796     // Same identity is equal
797     if (m_identity != NULL
798         && m_identity->Equals(pImage))
799         return TRUE;
800
801     // Same image is equal
802     if (m_openedILimage != NULL
803         && m_openedILimage->Equals(pImage))
804         return TRUE;
805
806
807     return FALSE;
808 }
809
810 // ------------------------------------------------------------
811 // Descriptive strings
812 // ------------------------------------------------------------
813
814 void PEFile::GetCodeBaseOrName(SString &result)
815 {
816     CONTRACTL
817     {
818         INSTANCE_CHECK;
819         THROWS;
820         GC_TRIGGERS;
821         MODE_ANY;
822         INJECT_FAULT(COMPlusThrowOM(););
823     }
824     CONTRACTL_END;
825
826     if (m_identity != NULL && !m_identity->GetPath().IsEmpty())
827     {
828         result.Set(m_identity->GetPath());
829     }
830     else if (IsAssembly())
831     {
832         ((PEAssembly*)this)->GetCodeBase(result);
833     }
834     else
835         result.SetUTF8(GetSimpleName());
836 }
837
838 #ifdef FEATURE_CAS_POLICY
839
840 // Returns security information for the assembly based on the codebase
841 void PEFile::GetSecurityIdentity(SString &codebase, SecZone *pdwZone, DWORD dwFlags, BYTE *pbUniqueID, DWORD *pcbUniqueID)
842 {
843     CONTRACTL
844     {
845         INSTANCE_CHECK;
846         THROWS;
847         MODE_ANY;
848         PRECONDITION(CheckPointer(pdwZone));
849         PRECONDITION(CheckPointer(pbUniqueID));
850         PRECONDITION(CheckPointer(pcbUniqueID));
851     }
852     CONTRACTL_END;
853
854     if (IsAssembly())
855     {
856         ((PEAssembly*)this)->GetCodeBase(codebase);
857     }
858     else if (m_identity != NULL && !m_identity->GetPath().IsEmpty())
859     {
860         codebase.Set(W("file:///"));
861         codebase.Append(m_identity->GetPath());
862     }
863     else
864     {
865         _ASSERTE( !"Unable to determine security identity" );
866     }
867
868     GCX_PREEMP();
869
870     if(!codebase.IsEmpty())
871     {
872         *pdwZone = NoZone;
873
874         InitializeSecurityManager();
875
876         // We have a class name, return a class factory for it
877         _ASSERTE(sizeof(SecZone) == sizeof(DWORD));
878         IfFailThrow(m_pSecurityManager->MapUrlToZone(codebase,
879                                                      reinterpret_cast<DWORD *>(pdwZone),
880                                                      dwFlags));
881
882         if (*pdwZone>=NumZones)            
883             IfFailThrow(SecurityPolicy::ApplyCustomZoneOverride(pdwZone));
884         
885         IfFailThrow(m_pSecurityManager->GetSecurityId(codebase,
886                                                       pbUniqueID,
887                                                       pcbUniqueID,
888                                                       0));
889     }
890 }
891
892 void PEFile::InitializeSecurityManager()
893 {
894     CONTRACTL
895     {
896         INSTANCE_CHECK;
897         THROWS;
898         CAN_TAKE_LOCK;
899         MODE_PREEMPTIVE;
900         INJECT_FAULT(COMPlusThrowOM(););
901     }
902     CONTRACTL_END;
903
904     HRESULT hr = S_OK;
905     if(m_pSecurityManager == NULL)
906     {
907         CrstHolder holder(&m_securityManagerLock);
908         if (m_pSecurityManager == NULL)
909         {
910                 IfFailThrow(CoInternetCreateSecurityManager(NULL,
911                                                             &m_pSecurityManager,
912                                                             0));
913         }
914     }
915 }
916
917 #endif // FEATURE_CAS_POLICY
918
919 // ------------------------------------------------------------
920 // Checks
921 // ------------------------------------------------------------
922
923
924
925 CHECK PEFile::CheckLoaded(BOOL bAllowNativeSkip/*=TRUE*/)
926 {
927     CONTRACT_CHECK
928     {
929         INSTANCE_CHECK;
930         NOTHROW;
931         GC_NOTRIGGER;
932         SO_TOLERANT;
933         MODE_ANY;
934     }
935     CONTRACT_CHECK_END;
936
937     CHECK(IsLoaded(bAllowNativeSkip)
938           // We are allowed to skip LoadLibrary in most cases for ngen'ed IL only images
939           || (bAllowNativeSkip && HasNativeImage() && IsILOnly()));
940
941     CHECK_OK;
942 }
943
944
945 // ------------------------------------------------------------
946 // Metadata access
947 // ------------------------------------------------------------
948
949 PTR_CVOID PEFile::GetMetadata(COUNT_T *pSize)
950 {
951     CONTRACT(PTR_CVOID)
952     {
953         INSTANCE_CHECK;
954         POSTCONDITION(CheckPointer(pSize, NULL_OK));
955         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
956         THROWS;
957         GC_TRIGGERS;
958         MODE_ANY;
959         SUPPORTS_DAC;
960     }
961     CONTRACT_END;
962
963 #ifdef FEATURE_PREJIT
964     if (HasNativeImageMetadata())
965     {
966         RETURN m_nativeImage->GetMetadata(pSize);
967     }
968 #endif
969
970     if (IsDynamic()
971          || !GetILimage()->HasNTHeaders()
972          || !GetILimage()->HasCorHeader())
973     {
974         if (pSize != NULL)
975             *pSize = 0;
976         RETURN NULL;
977     }
978     else
979     {
980         RETURN GetILimage()->GetMetadata(pSize);
981     }
982 }
983 #endif // #ifndef DACCESS_COMPILE
984
985 PTR_CVOID PEFile::GetLoadedMetadata(COUNT_T *pSize)
986 {
987     CONTRACT(PTR_CVOID)
988     {
989         INSTANCE_CHECK;
990         POSTCONDITION(CheckPointer(pSize, NULL_OK));
991         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
992         NOTHROW;
993         GC_NOTRIGGER;
994         MODE_ANY;
995         SUPPORTS_DAC;
996     }
997     CONTRACT_END;
998
999 #ifdef FEATURE_PREJIT
1000     if (HasNativeImageMetadata())
1001     {
1002         RETURN GetLoadedNative()->GetMetadata(pSize);
1003     }
1004 #endif
1005
1006     if (!HasLoadedIL() 
1007          || !GetLoadedIL()->HasNTHeaders()
1008          || !GetLoadedIL()->HasCorHeader())
1009     {
1010         if (pSize != NULL)
1011             *pSize = 0;
1012         RETURN NULL;
1013     }
1014     else
1015     {
1016         RETURN GetLoadedIL()->GetMetadata(pSize);
1017     }
1018 }
1019
1020 TADDR PEFile::GetIL(RVA il)
1021 {
1022     CONTRACT(TADDR)
1023     {
1024         INSTANCE_CHECK;
1025         PRECONDITION(il != 0);
1026         PRECONDITION(!IsDynamic());
1027         PRECONDITION(!IsResource());
1028 #ifndef DACCESS_COMPILE
1029         PRECONDITION(CheckLoaded());
1030 #endif
1031         POSTCONDITION(RETVAL != NULL);
1032         THROWS;
1033         GC_NOTRIGGER;
1034         MODE_ANY;
1035         SUPPORTS_DAC;
1036     }
1037     CONTRACT_END;
1038
1039     PEImageLayout *image = NULL;
1040
1041 #ifdef FEATURE_PREJIT
1042     // Note it is important to get the IL from the native image if 
1043     // available, since we are using the metadata from the native image
1044     // which has different IL rva's.
1045     if (HasNativeImageMetadata())
1046     {
1047         image = GetLoadedNative();
1048
1049 #ifndef DACCESS_COMPILE
1050         // NGen images are trusted to be well-formed.
1051         _ASSERTE(image->CheckILMethod(il));
1052 #endif
1053     }
1054     else
1055 #endif // FEATURE_PREJIT
1056     {
1057         image = GetLoadedIL();
1058
1059 #ifndef DACCESS_COMPILE
1060         // Verify that the IL blob is valid before giving it out
1061         if (!image->CheckILMethod(il))
1062             COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL_RANGE);
1063 #endif
1064     }
1065
1066     RETURN image->GetRvaData(il);
1067 }
1068
1069 #ifndef DACCESS_COMPILE
1070
1071 void PEFile::OpenImporter()
1072 {
1073     CONTRACTL
1074     {
1075         INSTANCE_CHECK;
1076         THROWS;
1077         GC_NOTRIGGER;
1078         MODE_ANY;
1079         INJECT_FAULT(COMPlusThrowOM(););
1080     } 
1081     CONTRACTL_END;
1082
1083     // Make sure internal MD is in RW format.
1084     ConvertMDInternalToReadWrite();
1085  
1086     IMetaDataImport2 *pIMDImport = NULL;
1087     IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetPersistentMDImport(), 
1088                                                        IID_IMetaDataImport2, 
1089                                                        (void **)&pIMDImport));
1090
1091     // Atomically swap it into the field (release it if we lose the race)
1092     if (FastInterlockCompareExchangePointer(&m_pImporter, pIMDImport, NULL) != NULL)
1093         pIMDImport->Release();
1094 }
1095
1096 void PEFile::ConvertMDInternalToReadWrite()
1097 {
1098     CONTRACTL
1099     {
1100         INSTANCE_CHECK;
1101         THROWS;
1102         GC_NOTRIGGER;
1103         MODE_ANY;
1104         INJECT_FAULT(EX_THROW(EEMessageException, (E_OUTOFMEMORY)););
1105     }
1106     CONTRACTL_END;
1107
1108     IMDInternalImport *pOld;            // Old (current RO) value of internal import.
1109     IMDInternalImport *pNew = NULL;     // New (RW) value of internal import.
1110
1111     // Take a local copy of *ppImport.  This may be a pointer to an RO
1112     //  or to an RW MDInternalXX.
1113     pOld = m_pMDImport;
1114     IMetaDataImport *pIMDImport = m_pImporter;
1115     if (pIMDImport != NULL)
1116     {
1117         HRESULT hr = GetMetaDataInternalInterfaceFromPublic(pIMDImport, IID_IMDInternalImport, (void **)&pNew);
1118         if (FAILED(hr))
1119         {
1120             EX_THROW(EEMessageException, (hr));
1121         }
1122         if (pNew == pOld)
1123         {
1124             pNew->Release();
1125             return;
1126         }
1127     }
1128     else
1129     {
1130         // If an RO, convert to an RW, return S_OK.  If already RW, no conversion
1131         //  needed, return S_FALSE.
1132         HRESULT hr = ConvertMDInternalImport(pOld, &pNew);
1133
1134         if (FAILED(hr))
1135         {
1136             EX_THROW(EEMessageException, (hr));
1137         }
1138
1139         // If no conversion took place, don't change pointers.
1140         if (hr == S_FALSE)
1141             return;
1142     }
1143
1144     // Swap the pointers in a thread safe manner.  If the contents of *ppImport
1145     //  equals pOld then no other thread got here first, and the old contents are
1146     //  replaced with pNew.  The old contents are returned.
1147     _ASSERTE(m_bHasPersistentMDImport);
1148     if (FastInterlockCompareExchangePointer(&m_pMDImport, pNew, pOld) == pOld)
1149     {   
1150         //if the debugger queries, it will now see that we have RW metadata
1151         m_MDImportIsRW_Debugger_Use_Only = TRUE;
1152
1153         // Swapped -- get the metadata to hang onto the old Internal import.
1154         HRESULT hr=m_pMDImport->SetUserContextData(pOld);
1155         _ASSERTE(SUCCEEDED(hr)||!"Leaking old MDImport");
1156         IfFailThrow(hr);
1157     }
1158     else
1159     {   // Some other thread finished first.  Just free the results of this conversion.
1160         pNew->Release();
1161     }
1162 }
1163
1164 void PEFile::ConvertMetadataToRWForEnC()
1165 {
1166     CONTRACTL
1167     {
1168         THROWS;
1169         GC_NOTRIGGER;
1170         SO_INTOLERANT;
1171         MODE_ANY;
1172     }
1173     CONTRACTL_END;
1174
1175     // This should only ever be called on EnC capable files.
1176     // One can check this using Module::IsEditAndContinueCapable().
1177     
1178     // This should only be called if we're debugging, stopped, and on the helper thread.
1179     _ASSERTE(CORDebuggerAttached());
1180     _ASSERTE((g_pDebugInterface != NULL) && g_pDebugInterface->ThisIsHelperThread());
1181     _ASSERTE((g_pDebugInterface != NULL) && g_pDebugInterface->IsStopped());
1182
1183     // Convert the metadata to RW for Edit and Continue, properly replacing the metadata import interface pointer and 
1184     // properly preserving the old importer. This will be called before the EnC system tries to apply a delta to the module's 
1185     // metadata. ConvertMDInternalToReadWrite() does that quite nicely for us.
1186     ConvertMDInternalToReadWrite();
1187 }
1188
1189 void PEFile::OpenMDImport_Unsafe()
1190 {
1191     CONTRACTL
1192     {
1193         INSTANCE_CHECK;
1194         THROWS;
1195         GC_TRIGGERS;
1196         MODE_ANY;
1197         INJECT_FAULT(COMPlusThrowOM(););
1198     }
1199     CONTRACTL_END;
1200
1201     if (m_pMDImport != NULL)
1202         return;
1203 #ifdef FEATURE_PREJIT    
1204     if (m_nativeImage != NULL
1205         && m_nativeImage->GetMDImport() != NULL
1206         )
1207     {
1208         // Use native image for metadata
1209         m_flags |= PEFILE_HAS_NATIVE_IMAGE_METADATA;
1210         m_pMDImport=m_nativeImage->GetMDImport();
1211     }
1212     else
1213 #endif
1214     {
1215 #ifdef FEATURE_PREJIT        
1216         m_flags &= ~PEFILE_HAS_NATIVE_IMAGE_METADATA;
1217 #endif
1218         if (!IsDynamic()
1219            && GetILimage()->HasNTHeaders()
1220              && GetILimage()->HasCorHeader())
1221         {
1222             m_pMDImport=GetILimage()->GetMDImport();
1223         }
1224         else
1225             ThrowHR(COR_E_BADIMAGEFORMAT);
1226
1227         m_bHasPersistentMDImport=TRUE;
1228     }
1229     _ASSERTE(m_pMDImport);
1230     m_pMDImport->AddRef();
1231 }
1232
1233 void PEFile::OpenEmitter()
1234 {
1235     CONTRACTL
1236     {
1237         INSTANCE_CHECK;
1238         THROWS;
1239         GC_NOTRIGGER;
1240         MODE_ANY;
1241         INJECT_FAULT(COMPlusThrowOM(););
1242     }
1243     CONTRACTL_END;
1244
1245     // Make sure internal MD is in RW format.
1246     ConvertMDInternalToReadWrite();
1247
1248     IMetaDataEmit *pIMDEmit = NULL;
1249     IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetPersistentMDImport(),
1250                                                        IID_IMetaDataEmit,
1251                                                        (void **)&pIMDEmit));
1252
1253     // Atomically swap it into the field (release it if we lose the race)
1254     if (FastInterlockCompareExchangePointer(&m_pEmitter, pIMDEmit, NULL) != NULL)
1255         pIMDEmit->Release();
1256 }
1257
1258
1259 void PEFile::ReleaseMetadataInterfaces(BOOL bDestructor, BOOL bKeepNativeData/*=FALSE*/)
1260 {
1261     CONTRACTL
1262     {
1263         INSTANCE_CHECK;
1264         NOTHROW;
1265         GC_NOTRIGGER;
1266         MODE_ANY;
1267         PRECONDITION(bDestructor||m_pMetadataLock->IsWriterLock());
1268     }
1269     CONTRACTL_END;
1270     _ASSERTE(bDestructor || !m_bHasPersistentMDImport);
1271
1272     if (m_pImporter != NULL)
1273     {
1274         m_pImporter->Release();
1275         m_pImporter = NULL;
1276     }
1277     if (m_pEmitter != NULL)
1278     {
1279         m_pEmitter->Release();
1280         m_pEmitter = NULL;
1281     }
1282
1283     if (m_pMDImport != NULL && (!bKeepNativeData || !HasNativeImage()))
1284     {
1285         m_pMDImport->Release();
1286         m_pMDImport=NULL;
1287      }
1288 }
1289
1290 #ifdef FEATURE_CAS_POLICY
1291
1292 void PEFile::CheckAuthenticodeSignature()
1293 {
1294     CONTRACTL
1295     {
1296         INSTANCE_CHECK;
1297         THROWS;
1298         GC_TRIGGERS;
1299         MODE_ANY;
1300         INJECT_FAULT(COMPlusThrowOM(););
1301     }
1302     CONTRACTL_END;
1303
1304     // Check any security signature in the header.
1305
1306     // This publisher data can potentially be cached and passed back in via
1307     // PEAssembly::CreateDelayed.
1308     //
1309     // HOWEVER - even if we cache it, the certificate still may need to be verified at
1310     // load time.  The only real caching can be done when the COR_TRUST certificate is
1311     // ABSENT.
1312     //
1313     // (In the case where it is present, we could still theoretically
1314     // cache the certificate and re-verify it and at least avoid touching the image
1315     // again, however this path is not implemented yet, so this is TBD if we decide
1316     // it is an important case to optimize for.)
1317
1318     if (!HasSecurityDirectory())
1319     {
1320         LOG((LF_SECURITY, LL_INFO1000, "No certificates found in module\n"));
1321     }
1322     else if(g_pConfig->GeneratePublisherEvidence())
1323     {
1324         // <TODO>@todo: Just because we don't have a file path, doesn't mean we can't have a certicate (does it?)</TODO>
1325         if (!GetPath().IsEmpty())
1326         {
1327             GCX_PREEMP();
1328
1329             // Ignore any errors here - if we fail to validate a certificate, we just don't
1330             // include it as evidence.
1331
1332             DWORD size;
1333             CoTaskNewHolder<COR_TRUST> pCor = NULL;
1334             // Failing to find a signature is OK.
1335             LPWSTR pFileName = (LPWSTR) GetPath().GetUnicode();
1336             DWORD dwAuthFlags = COR_NOUI|COR_NOPOLICY;
1337
1338             HRESULT hr = ::GetPublisher(pFileName,
1339                                           NULL,
1340                                           dwAuthFlags,
1341                                           &pCor,
1342                                           &size);
1343
1344
1345             if( SUCCEEDED(hr) ) { 
1346                 DWORD index = 0;
1347                 EnumCertificateAdditionFlags dwFlags = g_pCertificateCache->AddEntry(pCor, &index);
1348                 switch (dwFlags) {
1349                 case CacheSaturated:
1350                     pCor.SuppressRelease();
1351                     m_certificate = pCor.GetValue();
1352                     break;
1353
1354                 case Success:
1355                     pCor.SuppressRelease();
1356                     // falling through
1357                 case AlreadyExists:
1358                     m_certificate = g_pCertificateCache->GetEntry(index);
1359                     _ASSERTE(m_certificate);
1360                     break;
1361                 }
1362             }
1363         }
1364     }
1365     else 
1366     {
1367         LOG((LF_SECURITY, LL_INFO1000, "Assembly has an Authenticode signature, but Publisher evidence has been disabled.\n"));
1368     }
1369
1370     m_fCheckedCertificate = TRUE;
1371 }
1372
1373 HRESULT STDMETHODCALLTYPE
1374 GetPublisher(__in __in_z IN LPWSTR pwsFileName,      // File name, this is required even with the handle
1375              IN HANDLE hFile,            // Optional file name
1376              IN DWORD  dwFlags,          // COR_NOUI or COR_NOPOLICY
1377              OUT PCOR_TRUST *pInfo,      // Returns a PCOR_TRUST (Use FreeM)
1378              OUT DWORD      *dwInfo)     // Size of pInfo.                           
1379 {
1380     CONTRACTL
1381     {
1382         THROWS;
1383         GC_TRIGGERS;
1384         MODE_ANY;
1385     }
1386     CONTRACTL_END;
1387
1388     HRESULT hr = S_OK;
1389     
1390     GUID gV2 = COREE_POLICY_PROVIDER;
1391     COR_POLICY_PROVIDER sCorPolicy;
1392     
1393     WINTRUST_DATA      sWTD;
1394     WINTRUST_FILE_INFO sWTFI;
1395     
1396     // Set up the COR trust provider
1397     memset(&sCorPolicy, 0, sizeof(COR_POLICY_PROVIDER));
1398     sCorPolicy.cbSize = sizeof(COR_POLICY_PROVIDER);
1399     
1400     // Set up the winverify provider structures
1401     memset(&sWTD, 0x00, sizeof(WINTRUST_DATA));
1402     memset(&sWTFI, 0x00, sizeof(WINTRUST_FILE_INFO));
1403     
1404     sWTFI.cbStruct      = sizeof(WINTRUST_FILE_INFO);
1405     sWTFI.hFile         = hFile;
1406     sWTFI.pcwszFilePath = pwsFileName;
1407     
1408     sWTD.cbStruct       = sizeof(WINTRUST_DATA);
1409     sWTD.pPolicyCallbackData = &sCorPolicy; // Add in the cor trust information!!
1410     if (dwFlags & COR_NOUI)
1411     {
1412         sWTD.dwUIChoice     = WTD_UI_NONE;        // No bad UI is overridden in COR TRUST provider
1413     }
1414     else
1415     {
1416         sWTD.dwUIChoice     = WTD_UI_ALL;        // No bad UI is overridden in COR TRUST provider
1417     }
1418     sWTD.dwUnionChoice  = WTD_CHOICE_FILE;
1419     sWTD.pFile          = &sWTFI;
1420     
1421     // Set the policies for the VM (we have stolen VMBased and use it like a flag)
1422     if (dwFlags != 0)
1423         sCorPolicy.VMBased = dwFlags;
1424     
1425     LeaveRuntimeHolder holder((size_t)WinVerifyTrust);
1426     
1427     // WinVerifyTrust calls mscorsecimpl.dll to do the policy check
1428     hr = WinVerifyTrust(GetFocus(), &gV2, &sWTD);
1429     
1430     *pInfo  = sCorPolicy.pbCorTrust;
1431     *dwInfo = sCorPolicy.cbCorTrust;
1432     
1433     return hr;
1434 } // GetPublisher
1435
1436 #endif // FEATURE_CAS_POLICY
1437
1438 // ------------------------------------------------------------
1439 // PE file access
1440 // ------------------------------------------------------------
1441
1442 // Note that most of these APIs are currently passed through
1443 // to the main image.  However, in the near future they will
1444 // be rerouted to the native image in the prejitted case so
1445 // we can avoid using the original IL image.
1446
1447 #endif //!DACCESS_COMPILE
1448
1449 #ifdef FEATURE_PREJIT
1450 #ifndef DACCESS_COMPILE
1451 // ------------------------------------------------------------
1452 // Native image access
1453 // ------------------------------------------------------------
1454
1455 void PEFile::SetNativeImage(PEImage *image)
1456 {
1457     CONTRACT_VOID
1458     {
1459         INSTANCE_CHECK;
1460         PRECONDITION(!HasNativeImage());
1461         STANDARD_VM_CHECK;
1462     }
1463     CONTRACT_END;
1464
1465     _ASSERTE(image != NULL);
1466     PREFIX_ASSUME(image != NULL);
1467
1468     if (image->GetLoadedLayout()->GetBase() != image->GetLoadedLayout()->GetPreferredBase())
1469     {
1470         ExternalLog(LL_WARNING,
1471                     W("Native image loaded at base address") LFMT_ADDR
1472                     W("rather than preferred address:") LFMT_ADDR ,
1473                     DBG_ADDR(image->GetLoadedLayout()->GetBase()),
1474                     DBG_ADDR(image->GetLoadedLayout()->GetPreferredBase()));
1475     }
1476
1477 #ifdef FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
1478     // In Apollo, first ask if we're supposed to be ignoring the prejitted code &
1479     // structures in NGENd images. If so, bail now and do not set m_nativeImage. We've
1480     // already set m_identity & m_openedILimage (possibly even pointing to the
1481     // NGEN/Triton image), and will use those PEImages to find and JIT IL (even if they
1482     // point to an NGENd/Tritonized image).
1483     if (ShouldTreatNIAsMSIL())
1484         RETURN;
1485 #endif
1486
1487     m_nativeImage = image;
1488     m_nativeImage->AddRef();
1489     m_nativeImage->Load();
1490     m_nativeImage->AllocateLazyCOWPages();
1491
1492 #if defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE)
1493     static ConfigDWORD configNGenReserveForJumpStubs;
1494     int percentReserveForJumpStubs = configNGenReserveForJumpStubs.val(CLRConfig::INTERNAL_NGenReserveForJumpStubs);
1495     if (percentReserveForJumpStubs != 0)
1496     {
1497         PEImageLayout * pLayout = image->GetLoadedLayout();
1498         ExecutionManager::GetEEJitManager()->EnsureJumpStubReserve((BYTE *)pLayout->GetBase(), pLayout->GetVirtualSize(),
1499             percentReserveForJumpStubs * (pLayout->GetVirtualSize() / 100));
1500     }
1501 #endif
1502
1503     ExternalLog(LL_INFO100, W("Attempting to use native image %s."), image->GetPath().GetUnicode());
1504     RETURN;
1505 }
1506
1507 void PEFile::ClearNativeImage()
1508 {
1509     CONTRACT_VOID
1510     {
1511         INSTANCE_CHECK;
1512         PRECONDITION(HasNativeImage());
1513         POSTCONDITION(!HasNativeImage());
1514         THROWS;
1515         GC_TRIGGERS;
1516         MODE_ANY;
1517         INJECT_FAULT(COMPlusThrowOM(););
1518     }
1519     CONTRACT_END;
1520
1521     ExternalLog(LL_WARNING, "Discarding native image.");
1522
1523
1524     MarkNativeImageInvalidIfOwned();
1525
1526     {
1527         GCX_PREEMP();
1528         SafeComHolderPreemp<IMDInternalImport> pOldImport=GetMDImportWithRef();
1529         SimpleWriteLockHolder lock(m_pMetadataLock);
1530
1531         EX_TRY
1532         {
1533             ReleaseMetadataInterfaces(FALSE);
1534             m_flags &= ~PEFILE_HAS_NATIVE_IMAGE_METADATA;
1535             if (m_nativeImage)
1536                 m_nativeImage->Release();
1537             m_nativeImage = NULL;
1538             // Make sure our normal image is open
1539             EnsureImageOpened();
1540
1541             // Reopen metadata from normal image
1542             OpenMDImport();
1543         }
1544         EX_HOOK
1545         {
1546             RestoreMDImport(pOldImport);
1547         }
1548         EX_END_HOOK;
1549     }
1550
1551     RETURN;
1552 }
1553
1554
1555 extern DWORD g_dwLogLevel;
1556
1557 //===========================================================================================================
1558 // Encapsulates CLR and Fusion logging for runtime verification of native images.
1559 //===========================================================================================================
1560 static void RuntimeVerifyVLog(DWORD level, LoggableAssembly *pLogAsm, const WCHAR *fmt, va_list args)
1561 {
1562     STANDARD_VM_CONTRACT;
1563
1564     BOOL fOutputToDebugger = (level == LL_ERROR && IsDebuggerPresent());
1565     BOOL fOutputToLogging = LoggingOn(LF_ZAP, level);
1566
1567     StackSString message;
1568     message.VPrintf(fmt, args);
1569
1570     if (fOutputToLogging)
1571     {
1572         SString displayString = pLogAsm->DisplayString();
1573         LOG((LF_ZAP, level, "%s: \"%S\"\n", "ZAP", displayString.GetUnicode()));
1574         LOG((LF_ZAP, level, "%S", message.GetUnicode()));
1575         LOG((LF_ZAP, level, "\n"));
1576     }
1577
1578     if (fOutputToDebugger)
1579     {
1580         SString displayString = pLogAsm->DisplayString();
1581         WszOutputDebugString(W("CLR:("));
1582         WszOutputDebugString(displayString.GetUnicode());
1583         WszOutputDebugString(W(") "));
1584         WszOutputDebugString(message);
1585         WszOutputDebugString(W("\n"));
1586     }
1587
1588 #ifdef FEATURE_FUSION
1589     IFusionBindLog *pFusionBindLog = pLogAsm->FusionBindLog();
1590     if (pFusionBindLog)
1591     {
1592         pFusionBindLog->LogMessage(0, FUSION_BIND_LOG_CATEGORY_NGEN, message);
1593
1594         if (level == LL_ERROR) {
1595             pFusionBindLog->SetResultCode(FUSION_BIND_LOG_CATEGORY_NGEN, E_FAIL);
1596             pFusionBindLog->Flush(g_dwLogLevel, FUSION_BIND_LOG_CATEGORY_NGEN);
1597             pFusionBindLog->Flush(g_dwLogLevel, FUSION_BIND_LOG_CATEGORY_DEFAULT);
1598         }
1599     }
1600 #endif //FEATURE_FUSION
1601 }
1602
1603
1604 //===========================================================================================================
1605 // Encapsulates CLR and Fusion logging for runtime verification of native images.
1606 //===========================================================================================================
1607 static void RuntimeVerifyLog(DWORD level, LoggableAssembly *pLogAsm, const WCHAR *fmt, ...)
1608 {
1609     STANDARD_VM_CONTRACT;
1610
1611     // Avoid calling RuntimeVerifyVLog unless logging is on
1612     if (   ((level == LL_ERROR) && IsDebuggerPresent()) 
1613         || LoggingOn(LF_ZAP, level)
1614 #ifdef FEATURE_FUSION
1615         || (pLogAsm->FusionBindLog() != NULL)
1616 #endif
1617        ) 
1618     {
1619         va_list args;
1620         va_start(args, fmt);
1621
1622         RuntimeVerifyVLog(level, pLogAsm, fmt, args);
1623
1624         va_end(args);
1625     }
1626 }
1627
1628 //==============================================================================
1629
1630 static const LPCWSTR CorCompileRuntimeDllNames[NUM_RUNTIME_DLLS] =
1631 {
1632     MAKEDLLNAME_W(W("coreclr")),
1633     MAKEDLLNAME_W(W("clrjit"))
1634 };
1635
1636
1637 LPCWSTR CorCompileGetRuntimeDllName(CorCompileRuntimeDlls id)
1638 {
1639     CONTRACTL
1640     {
1641         THROWS;
1642         GC_TRIGGERS;
1643         MODE_ANY;
1644         SO_INTOLERANT;
1645         INJECT_FAULT(COMPlusThrowOM(););
1646     }
1647     CONTRACTL_END;
1648
1649
1650     return CorCompileRuntimeDllNames[id];
1651 }
1652
1653 #ifndef CROSSGEN_COMPILE
1654
1655 //==============================================================================
1656 // Will always return a valid HMODULE for CLR_INFO, but will return NULL for NGEN_COMPILER_INFO
1657 // if the DLL has not yet been loaded (it does not try to cause a load).
1658
1659 // Gets set by IJitManager::LoadJit (yes, this breaks the abstraction boundary).
1660 HMODULE s_ngenCompilerDll = NULL;
1661
1662 extern HMODULE CorCompileGetRuntimeDll(CorCompileRuntimeDlls id)
1663 {
1664     CONTRACTL
1665     {
1666         THROWS;
1667         GC_NOTRIGGER;
1668         MODE_ANY;
1669         SO_INTOLERANT;
1670         INJECT_FAULT(COMPlusThrowOM(););
1671     }
1672     CONTRACTL_END;
1673
1674     // Currently special cased for every entry.
1675     static_assert_no_msg(NUM_RUNTIME_DLLS == 2);
1676     static_assert_no_msg(CORECLR_INFO == 0);
1677
1678     HMODULE hMod = NULL;
1679
1680     // Try to load the correct DLL
1681     switch (id)
1682     {
1683     case CORECLR_INFO:
1684         hMod = GetCLRModule();
1685         break;
1686
1687     default:
1688         COMPlusThrowNonLocalized(kExecutionEngineException,
1689             W("Invalid runtime DLL ID"));
1690         break;
1691     }
1692
1693     return hMod;
1694 }
1695 #endif // CROSSGEN_COMPILE
1696
1697 //===========================================================================================================
1698 // Helper for RuntimeVerifyNativeImageVersion(). Compares the loaded clr.dll and clrjit.dll's against
1699 // the ones the native image was compiled against.
1700 //===========================================================================================================
1701 static BOOL RuntimeVerifyNativeImageTimestamps(const CORCOMPILE_VERSION_INFO *info, LoggableAssembly *pLogAsm)
1702 {
1703     STANDARD_VM_CONTRACT;
1704
1705
1706     return TRUE;
1707 }
1708
1709 //===========================================================================================================
1710 // Validates that an NI matches the running CLR, OS, CPU, etc. This is the entrypoint used by the CLR loader.
1711 //
1712 //===========================================================================================================
1713 BOOL PEAssembly::CheckNativeImageVersion(PEImage *peimage)
1714 {
1715     STANDARD_VM_CONTRACT;
1716
1717     //
1718     // Get the zap version header. Note that modules will not have version
1719     // headers - they add no additional versioning constraints from their
1720     // assemblies.
1721     //
1722     PEImageLayoutHolder image=peimage->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED);
1723
1724     if (!image->HasNativeHeader())
1725         return FALSE;
1726
1727     if (!image->CheckNativeHeaderVersion())
1728     {
1729         // Wrong native image version is fatal error on CoreCLR
1730         ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1731     }
1732
1733     CORCOMPILE_VERSION_INFO *info = image->GetNativeVersionInfo();
1734     if (info == NULL)
1735         return FALSE;
1736
1737     LoggablePEAssembly logAsm(this);
1738     if (!RuntimeVerifyNativeImageVersion(info, &logAsm))
1739     {
1740         // Wrong native image version is fatal error on CoreCLR
1741         ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1742     }
1743
1744     CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
1745
1746     if (IsSystem())
1747     {
1748         // Require instrumented flags for mscorlib when collecting IBC data
1749         CorCompileConfigFlags instrumentationConfigFlags = (CorCompileConfigFlags) (configFlags & CORCOMPILE_CONFIG_INSTRUMENTATION);
1750         if ((info->wConfigFlags & instrumentationConfigFlags) != instrumentationConfigFlags)
1751         {
1752             ExternalLog(LL_ERROR, "Instrumented native image for System.Private.CoreLib.dll expected.");
1753             ThrowHR(COR_E_NI_AND_RUNTIME_VERSION_MISMATCH);
1754         }
1755     }
1756
1757     // Otherwise, match regardless of the instrumentation flags
1758     configFlags = (CorCompileConfigFlags) (configFlags & ~(CORCOMPILE_CONFIG_INSTRUMENTATION_NONE | CORCOMPILE_CONFIG_INSTRUMENTATION));
1759
1760     if ((info->wConfigFlags & configFlags) != configFlags)
1761     {
1762         return FALSE;
1763     }
1764
1765     return TRUE;
1766 }
1767
1768
1769 //===========================================================================================================
1770 // Validates that an NI matches the running CLR, OS, CPU, etc.
1771 //
1772 // For historial reasons, some versions of the runtime perform this check at native bind time (preferrred),
1773 // while others check at CLR load time.
1774 //
1775 // This is the common funnel for both versions and is agnostic to whether the "assembly" is represented
1776 // by a CLR object or Fusion object.
1777 //===========================================================================================================
1778 BOOL RuntimeVerifyNativeImageVersion(const CORCOMPILE_VERSION_INFO *info, LoggableAssembly *pLogAsm)
1779 {
1780     STANDARD_VM_CONTRACT;
1781
1782     if (!RuntimeVerifyNativeImageTimestamps(info, pLogAsm))
1783         return FALSE;
1784
1785     //
1786     // Check that the EE version numbers are the same.
1787     //
1788  
1789     if (info->wVersionMajor != VER_MAJORVERSION
1790         || info->wVersionMinor != VER_MINORVERSION
1791         || info->wVersionBuildNumber != VER_PRODUCTBUILD
1792         || info->wVersionPrivateBuildNumber != VER_PRODUCTBUILD_QFE)
1793     {
1794         RuntimeVerifyLog(LL_ERROR, pLogAsm, W("CLR version recorded in native image doesn't match the current CLR."));
1795         return FALSE;
1796     }
1797
1798     //
1799     // Check checked/free status
1800     //
1801
1802     if (info->wBuild !=
1803 #if _DEBUG
1804         CORCOMPILE_BUILD_CHECKED
1805 #else
1806         CORCOMPILE_BUILD_FREE
1807 #endif
1808         )
1809     {
1810         RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Checked/free mismatch with native image."));
1811         return FALSE;
1812     }
1813
1814     //
1815     // Check processor
1816     //
1817
1818     if (info->wMachine != IMAGE_FILE_MACHINE_NATIVE_NI)
1819     {
1820         RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Processor type recorded in native image doesn't match this machine's processor."));
1821         return FALSE;
1822     }
1823
1824 #ifndef CROSSGEN_COMPILE
1825     //
1826     // Check the processor specific ID
1827     //
1828
1829     CORINFO_CPU cpuInfo;
1830     GetSpecificCpuInfo(&cpuInfo);
1831
1832     if (!IsCompatibleCpuInfo(&cpuInfo, &info->cpuInfo))
1833     {
1834         RuntimeVerifyLog(LL_ERROR, pLogAsm, W("Required CPU features recorded in native image don't match this machine's processor."));
1835         return FALSE;
1836     }
1837 #endif // CROSSGEN_COMPILE
1838
1839
1840     //
1841     // The zap is up to date.
1842     //
1843
1844     RuntimeVerifyLog(LL_INFO100, pLogAsm, W("Native image has correct version information."));
1845     return TRUE;
1846 }
1847
1848 #endif // !DACCESS_COMPILE
1849
1850 /* static */
1851 CorCompileConfigFlags PEFile::GetNativeImageConfigFlags(BOOL fForceDebug/*=FALSE*/,
1852                                                         BOOL fForceProfiling/*=FALSE*/,
1853                                                         BOOL fForceInstrument/*=FALSE*/)
1854 {
1855     LIMITED_METHOD_DAC_CONTRACT;
1856
1857     CorCompileConfigFlags result = (CorCompileConfigFlags)0;
1858
1859     // Debugging
1860
1861 #ifdef DEBUGGING_SUPPORTED
1862     // if these have been set, the take precedence over anything else
1863     if (s_NGENDebugFlags)
1864     {
1865         if ((s_NGENDebugFlags & CORCOMPILE_CONFIG_DEBUG_NONE) != 0)
1866         {
1867             result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG_NONE);
1868         }
1869         else
1870         {
1871             if ((s_NGENDebugFlags & CORCOMPILE_CONFIG_DEBUG) != 0)
1872             {
1873                 result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG);
1874             }
1875         }
1876     }
1877     else
1878 #endif // DEBUGGING_SUPPORTED
1879     {
1880         if (fForceDebug)
1881         {
1882             result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG);
1883         }
1884         else
1885         {
1886             result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_DEBUG_DEFAULT);
1887         }
1888     }
1889
1890     // Profiling
1891
1892 #ifdef PROFILING_SUPPORTED
1893     if (fForceProfiling || CORProfilerUseProfileImages())
1894     {
1895         result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_PROFILING);
1896
1897         result = (CorCompileConfigFlags) (result & ~(CORCOMPILE_CONFIG_DEBUG_NONE|
1898                                                      CORCOMPILE_CONFIG_DEBUG|
1899                                                      CORCOMPILE_CONFIG_DEBUG_DEFAULT));
1900     }
1901     else
1902 #endif //PROFILING_SUPPORTED
1903         result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_PROFILING_NONE);
1904
1905     // Instrumentation
1906 #ifndef DACCESS_COMPILE
1907     BOOL instrumented = (!IsCompilationProcess() && g_pConfig->GetZapBBInstr());
1908 #else
1909     BOOL instrumented = FALSE;
1910 #endif
1911     if (instrumented || fForceInstrument)
1912     {
1913         result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_INSTRUMENTATION);
1914     }
1915     else
1916     {
1917         result = (CorCompileConfigFlags) (result|CORCOMPILE_CONFIG_INSTRUMENTATION_NONE);
1918     }
1919
1920     // NOTE: Right now we are not taking instrumentation into account when binding.
1921
1922     return result;
1923 }
1924
1925 CorCompileConfigFlags PEFile::GetNativeImageConfigFlagsWithOverrides()
1926 {
1927     LIMITED_METHOD_DAC_CONTRACT;
1928
1929     BOOL fForceDebug, fForceProfiling, fForceInstrument;
1930     SystemDomain::GetCompilationOverrides(&fForceDebug,
1931                                           &fForceProfiling,
1932                                           &fForceInstrument);
1933     return PEFile::GetNativeImageConfigFlags(fForceDebug,
1934                                              fForceProfiling,
1935                                              fForceInstrument);
1936 }
1937
1938 #ifndef DACCESS_COMPILE
1939
1940
1941
1942 //===========================================================================================================
1943 // Validates that a hard-dep matches the a parent NI's compile-time hard-dep.
1944 //
1945 // For historial reasons, some versions of the runtime perform this check at native bind time (preferrred),
1946 // while others check at CLR load time.
1947 //
1948 // This is the common funnel for both versions and is agnostic to whether the "assembly" is represented
1949 // by a CLR object or Fusion object.
1950 //
1951 //===========================================================================================================
1952 BOOL RuntimeVerifyNativeImageDependency(const CORCOMPILE_NGEN_SIGNATURE &ngenSigExpected,
1953                                         const CORCOMPILE_VERSION_INFO *pActual,
1954                                         LoggableAssembly              *pLogAsm)
1955 {
1956     STANDARD_VM_CONTRACT;
1957
1958     if (ngenSigExpected != pActual->signature)
1959     {
1960         // Signature did not match
1961         SString displayString = pLogAsm->DisplayString();
1962         RuntimeVerifyLog(LL_ERROR,
1963                          pLogAsm,
1964                          W("Rejecting native image because native image dependency %s ")
1965                          W("had a different identity than expected"),
1966                          displayString.GetUnicode());
1967 #if (defined FEATURE_PREJIT) && (defined FEATURE_FUSION)
1968         if (pLogAsm->FusionBindLog())
1969         {
1970             if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_PRIVATEFUSION_KEYWORD))
1971             { 
1972                 pLogAsm->FusionBindLog()->ETWTraceLogMessage(ETW::BinderLog::BinderStructs::NGEN_BIND_DEPENDENCY_HAS_DIFFERENT_IDENTITY, pLogAsm->FusionAssemblyName());
1973             }
1974         }
1975 #endif
1976
1977         return FALSE;
1978     }
1979     return TRUE;
1980 }
1981 // Wrapper function for use by parts of the runtime that actually have a CORCOMPILE_DEPENDENCY to work with.
1982 BOOL RuntimeVerifyNativeImageDependency(const CORCOMPILE_DEPENDENCY   *pExpected,
1983                                         const CORCOMPILE_VERSION_INFO *pActual,
1984                                         LoggableAssembly              *pLogAsm)
1985 {
1986     WRAPPER_NO_CONTRACT;
1987
1988     return RuntimeVerifyNativeImageDependency(pExpected->signNativeImage,
1989                                               pActual,
1990                                               pLogAsm);
1991 }
1992
1993 #endif // !DACCESS_COMPILE
1994
1995 #ifdef DEBUGGING_SUPPORTED
1996 //
1997 // Called through ICorDebugAppDomain2::SetDesiredNGENCompilerFlags to specify
1998 // which kinds of ngen'd images fusion should load wrt debugging support
1999 // Overrides any previous settings
2000 //
2001 void PEFile::SetNGENDebugFlags(BOOL fAllowOpt)
2002 {
2003     CONTRACTL
2004     {
2005         GC_NOTRIGGER;
2006         NOTHROW;
2007         MODE_ANY;
2008         SUPPORTS_DAC;
2009     }
2010     CONTRACTL_END;
2011
2012     if (fAllowOpt)
2013         s_NGENDebugFlags = CORCOMPILE_CONFIG_DEBUG_NONE;
2014     else
2015         s_NGENDebugFlags = CORCOMPILE_CONFIG_DEBUG;
2016     }
2017
2018 //
2019 // Called through ICorDebugAppDomain2::GetDesiredNGENCompilerFlags to determine
2020 // which kinds of ngen'd images fusion should load wrt debugging support
2021 //
2022 void PEFile::GetNGENDebugFlags(BOOL *fAllowOpt)
2023 {
2024     CONTRACTL
2025     {
2026         GC_NOTRIGGER;
2027         NOTHROW;
2028         MODE_ANY;
2029         SUPPORTS_DAC;
2030     }
2031     CONTRACTL_END;
2032
2033     CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
2034
2035     *fAllowOpt = ((configFlags & CORCOMPILE_CONFIG_DEBUG) == 0);
2036 }
2037 #endif // DEBUGGING_SUPPORTED
2038
2039
2040
2041 #ifndef DACCESS_COMPILE
2042 #ifdef FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
2043
2044 //---------------------------------------------------------------------------------------
2045 //
2046 // Used in Apollo, this method determines whether profiling or debugging has requested
2047 // the runtime to provide debuggable / profileable code. In other CLR builds, this would
2048 // normally result in requiring the appropriate NGEN scenario be loaded (/Debug or
2049 // /Profile) and to JIT if unavailable. In Apollo, however, these NGEN scenarios are
2050 // never available, and even MSIL assemblies are often not available. So this function
2051 // tells its caller to use the NGENd assembly as if it were an MSIL assembly--ignore the
2052 // prejitted code and prebaked structures, and just JIT code and load classes from
2053 // scratch.
2054 //
2055 // Return Value:
2056 //      nonzero iff NGENd images should be treated as MSIL images.
2057 //
2058
2059 // static
2060 BOOL PEFile::ShouldTreatNIAsMSIL()
2061 {
2062     LIMITED_METHOD_CONTRACT;
2063
2064     // Never use fragile native image content during ReadyToRun compilation. It would
2065     // produces non-version resilient images because of wrong cached values for 
2066     // MethodTable::IsLayoutFixedInCurrentVersionBubble, etc.
2067     if (IsReadyToRunCompilation())
2068         return TRUE;
2069
2070     // Ask profiling API & config vars whether NGENd images should be avoided
2071     // completely.
2072     if (!NGENImagesAllowed())
2073         return TRUE;
2074
2075     // Ask profiling and debugging if they're requesting us to use ngen /Debug or
2076     // /Profile images (which aren't available under Apollo)
2077
2078     CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
2079
2080     if ((configFlags & (CORCOMPILE_CONFIG_DEBUG | CORCOMPILE_CONFIG_PROFILING)) != 0)
2081         return TRUE;
2082
2083     return FALSE;
2084 }
2085
2086 #endif // FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
2087
2088 #endif  //!DACCESS_COMPILE
2089 #endif  // FEATURE_PREJIT
2090
2091 #ifndef DACCESS_COMPILE
2092
2093 // ------------------------------------------------------------
2094 // Resource access
2095 // ------------------------------------------------------------
2096
2097 void PEFile::GetEmbeddedResource(DWORD dwOffset, DWORD *cbResource, PBYTE *pbInMemoryResource)
2098 {
2099     CONTRACTL
2100     {
2101         INSTANCE_CHECK;
2102         THROWS;
2103         GC_TRIGGERS;
2104         MODE_ANY;
2105         INJECT_FAULT(ThrowOutOfMemory(););
2106     }
2107     CONTRACTL_END;
2108
2109     // NOTE: it's not clear whether to load this from m_image or m_loadedImage.
2110     // m_loadedImage is probably preferable, but this may be called by security
2111     // before the image is loaded.
2112
2113     PEImage *image;
2114
2115 #ifdef FEATURE_PREJIT
2116     if (m_nativeImage != NULL)
2117         image = m_nativeImage;
2118     else 
2119 #endif    
2120     {
2121         EnsureImageOpened();
2122         image = GetILimage();
2123     }
2124
2125     PEImageLayoutHolder theImage(image->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED));
2126     if (!theImage->CheckResource(dwOffset))
2127         ThrowHR(COR_E_BADIMAGEFORMAT);
2128
2129     COUNT_T size;
2130     const void *resource = theImage->GetResource(dwOffset, &size);
2131
2132     *cbResource = size;
2133     *pbInMemoryResource = (PBYTE) resource;
2134 }
2135
2136 // ------------------------------------------------------------
2137 // File loading
2138 // ------------------------------------------------------------
2139
2140 PEAssembly * 
2141 PEFile::LoadAssembly(
2142     mdAssemblyRef       kAssemblyRef,
2143     IMDInternalImport * pImport,                // = NULL
2144     LPCUTF8             szWinRtTypeNamespace,   // = NULL
2145     LPCUTF8             szWinRtTypeClassName)   // = NULL
2146 {
2147     CONTRACT(PEAssembly *)
2148     {
2149         INSTANCE_CHECK;
2150         THROWS;
2151         GC_TRIGGERS;
2152         MODE_ANY;
2153         POSTCONDITION(CheckPointer(RETVAL));
2154         INJECT_FAULT(COMPlusThrowOM(););
2155     }
2156     CONTRACT_END;
2157
2158     if (pImport == NULL)
2159         pImport = GetPersistentMDImport();
2160
2161     if (((TypeFromToken(kAssemblyRef) != mdtAssembly) && 
2162          (TypeFromToken(kAssemblyRef) != mdtAssemblyRef)) || 
2163         (!pImport->IsValidToken(kAssemblyRef)))
2164     {
2165         ThrowHR(COR_E_BADIMAGEFORMAT);
2166     }
2167     
2168     AssemblySpec spec;
2169     
2170     spec.InitializeSpec(kAssemblyRef, pImport, GetAppDomain()->FindAssembly(GetAssembly()), IsIntrospectionOnly());
2171     if (szWinRtTypeClassName != NULL)
2172         spec.SetWindowsRuntimeType(szWinRtTypeNamespace, szWinRtTypeClassName);
2173     
2174     RETURN GetAppDomain()->BindAssemblySpec(&spec, TRUE, IsIntrospectionOnly());
2175 }
2176
2177 // ------------------------------------------------------------
2178 // Logging
2179 // ------------------------------------------------------------
2180 #ifdef FEATURE_PREJIT
2181 void PEFile::ExternalLog(DWORD facility, DWORD level, const WCHAR *fmt, ...)
2182 {
2183     WRAPPER_NO_CONTRACT;
2184
2185     va_list args;
2186     va_start(args, fmt);
2187
2188     ExternalVLog(facility, level, fmt, args);
2189
2190     va_end(args);
2191 }
2192
2193 void PEFile::ExternalLog(DWORD level, const WCHAR *fmt, ...)
2194 {
2195     WRAPPER_NO_CONTRACT;
2196
2197     va_list args;
2198     va_start(args, fmt);
2199
2200     ExternalVLog(LF_ZAP, level, fmt, args);
2201
2202     va_end(args);
2203 }
2204
2205 void PEFile::ExternalLog(DWORD level, const char *msg)
2206 {
2207     WRAPPER_NO_CONTRACT;
2208
2209     // It is OK to use %S here. We know that msg is ASCII-only.
2210     ExternalLog(level, W("%S"), msg);
2211 }
2212
2213 void PEFile::ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args)
2214 {
2215     CONTRACT_VOID
2216     {
2217         THROWS;
2218         GC_TRIGGERS;
2219     }
2220     CONTRACT_END;
2221
2222     BOOL fOutputToDebugger = (level == LL_ERROR && IsDebuggerPresent());
2223     BOOL fOutputToLogging = LoggingOn(facility, level);
2224
2225     if (!fOutputToDebugger && !fOutputToLogging)
2226         return;
2227
2228     StackSString message;
2229     message.VPrintf(fmt, args);
2230
2231     if (fOutputToLogging)
2232     {
2233         if (GetMDImport() != NULL)
2234             LOG((facility, level, "%s: \"%s\"\n", (facility == LF_ZAP ? "ZAP" : "LOADER"), GetSimpleName()));
2235         else
2236             LOG((facility, level, "%s: \"%S\"\n", (facility == LF_ZAP ? "ZAP" : "LOADER"), ((const WCHAR *)GetPath())));
2237
2238         LOG((facility, level, "%S", message.GetUnicode()));
2239         LOG((facility, level, "\n"));
2240     }
2241
2242     if (fOutputToDebugger)
2243     {
2244         WszOutputDebugString(W("CLR:("));
2245
2246         StackSString codebase;
2247         GetCodeBaseOrName(codebase);
2248         WszOutputDebugString(codebase);
2249
2250         WszOutputDebugString(W(") "));
2251
2252         WszOutputDebugString(message);
2253         WszOutputDebugString(W("\n"));
2254     }
2255
2256     RETURN;
2257 }
2258
2259 void PEFile::FlushExternalLog()
2260 {
2261     LIMITED_METHOD_CONTRACT;
2262 }
2263 #endif
2264
2265 BOOL PEFile::GetResource(LPCSTR szName, DWORD *cbResource,
2266                                  PBYTE *pbInMemoryResource, DomainAssembly** pAssemblyRef,
2267                                  LPCSTR *szFileName, DWORD *dwLocation,
2268                                  StackCrawlMark *pStackMark, BOOL fSkipSecurityCheck,
2269                                  BOOL fSkipRaiseResolveEvent, DomainAssembly* pDomainAssembly, AppDomain* pAppDomain)
2270 {
2271     CONTRACTL
2272     {
2273         INSTANCE_CHECK;
2274         THROWS;
2275         MODE_ANY;
2276         INJECT_FAULT(COMPlusThrowOM(););
2277         WRAPPER(GC_TRIGGERS);
2278     }
2279     CONTRACTL_END;
2280
2281
2282     mdToken            mdLinkRef;
2283     DWORD              dwResourceFlags;
2284     DWORD              dwOffset;
2285     mdManifestResource mdResource;
2286     Assembly*          pAssembly = NULL;
2287     PEFile*            pPEFile = NULL;
2288     ReleaseHolder<IMDInternalImport> pImport (GetMDImportWithRef());
2289     if (SUCCEEDED(pImport->FindManifestResourceByName(szName, &mdResource)))
2290     {
2291         pPEFile = this;
2292         IfFailThrow(pImport->GetManifestResourceProps(
2293             mdResource, 
2294             NULL,           //&szName,
2295             &mdLinkRef, 
2296             &dwOffset, 
2297             &dwResourceFlags));
2298     }
2299     else
2300     {
2301         if (fSkipRaiseResolveEvent || pAppDomain == NULL)
2302             return FALSE;
2303
2304         DomainAssembly* pParentAssembly = GetAppDomain()->FindAssembly(GetAssembly());
2305         pAssembly = pAppDomain->RaiseResourceResolveEvent(pParentAssembly, szName);
2306         if (pAssembly == NULL)
2307             return FALSE;
2308
2309         pDomainAssembly = pAssembly->GetDomainAssembly(pAppDomain);
2310         pPEFile = pDomainAssembly->GetFile();
2311
2312         if (FAILED(pAssembly->GetManifestImport()->FindManifestResourceByName(
2313             szName,
2314             &mdResource)))
2315         {
2316             return FALSE;
2317         }
2318         
2319         if (dwLocation != 0)
2320         {
2321             if (pAssemblyRef != NULL)
2322                 *pAssemblyRef = pDomainAssembly;
2323             
2324             *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly
2325         }
2326         IfFailThrow(pPEFile->GetPersistentMDImport()->GetManifestResourceProps(
2327             mdResource, 
2328             NULL,           //&szName,
2329             &mdLinkRef, 
2330             &dwOffset, 
2331             &dwResourceFlags));
2332     }
2333     
2334     
2335     switch(TypeFromToken(mdLinkRef)) {
2336     case mdtAssemblyRef:
2337         {
2338             if (pDomainAssembly == NULL)
2339                 return FALSE;
2340
2341             AssemblySpec spec;
2342             spec.InitializeSpec(mdLinkRef, GetPersistentMDImport(), pDomainAssembly, pDomainAssembly->GetFile()->IsIntrospectionOnly());
2343             pDomainAssembly = spec.LoadDomainAssembly(FILE_LOADED);
2344
2345             if (dwLocation) {
2346                 if (pAssemblyRef)
2347                     *pAssemblyRef = pDomainAssembly;
2348
2349                 *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly
2350             }
2351
2352             return pDomainAssembly->GetResource(szName,
2353                                                 cbResource,
2354                                                 pbInMemoryResource,
2355                                                 pAssemblyRef,
2356                                                 szFileName,
2357                                                 dwLocation,
2358                                                 pStackMark,
2359                                                 fSkipSecurityCheck,
2360                                                 fSkipRaiseResolveEvent);
2361         }
2362
2363     case mdtFile:
2364         if (mdLinkRef == mdFileNil)
2365         {
2366             // The resource is embedded in the manifest file
2367
2368 #ifndef CROSSGEN_COMPILE
2369             if (!IsMrPublic(dwResourceFlags) && pStackMark && !fSkipSecurityCheck)
2370             {
2371                 Assembly *pCallersAssembly = SystemDomain::GetCallersAssembly(pStackMark);
2372
2373                 if (pCallersAssembly &&  // full trust for interop
2374                     (!pCallersAssembly->GetManifestFile()->Equals(this)))
2375                 {
2376                     RefSecContext sCtx(AccessCheckOptions::kMemberAccess);
2377
2378                     AccessCheckOptions accessCheckOptions(
2379                         AccessCheckOptions::kMemberAccess,  /*accessCheckType*/
2380                         NULL,                               /*pAccessContext*/
2381                         FALSE,                              /*throwIfTargetIsInaccessible*/
2382                         (MethodTable *) NULL                /*pTargetMT*/
2383                         );
2384
2385                     // SL: return TRUE only if the caller is critical
2386                     // Desktop: return TRUE only if demanding MemberAccess succeeds
2387                     if (!accessCheckOptions.DemandMemberAccessOrFail(&sCtx, NULL, TRUE /*visibilityCheck*/))
2388                         return FALSE;
2389                 }
2390             }
2391 #endif // CROSSGEN_COMPILE
2392
2393             if (dwLocation) {
2394                 *dwLocation = *dwLocation | 5; // ResourceLocation.embedded |
2395
2396                                                // ResourceLocation.containedInManifestFile
2397                 return TRUE;
2398             }
2399
2400             pPEFile->GetEmbeddedResource(dwOffset, cbResource, pbInMemoryResource);
2401
2402             return TRUE;
2403         }
2404 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
2405         // The resource is either linked or embedded in a non-manifest-containing file
2406         if (pDomainAssembly == NULL)
2407             return FALSE;
2408
2409         return pDomainAssembly->GetModuleResource(mdLinkRef, szName, cbResource,
2410                                                   pbInMemoryResource, szFileName,
2411                                                   dwLocation, IsMrPublic(dwResourceFlags),
2412                                                   pStackMark, fSkipSecurityCheck);
2413 #else
2414         return FALSE;
2415 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
2416
2417     default:
2418         ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_IN_MANIFESTRES);
2419     }
2420 }
2421
2422 void PEFile::GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine)
2423 {
2424     WRAPPER_NO_CONTRACT;
2425
2426     if (IsResource() || IsDynamic())
2427     {
2428         if (pdwKind)
2429             *pdwKind = 0;
2430         if (pdwMachine)
2431             *pdwMachine = 0;
2432         return;
2433     }
2434
2435 #ifdef FEATURE_PREJIT
2436     if (IsNativeLoaded())
2437     {
2438         CONSISTENCY_CHECK(HasNativeImage());
2439
2440         m_nativeImage->GetNativeILPEKindAndMachine(pdwKind, pdwMachine);
2441         return;
2442     }
2443 #ifndef DACCESS_COMPILE
2444     if (!HasOpenedILimage())
2445     {
2446         //don't want to touch the IL image unless we already have
2447         ReleaseHolder<PEImage> pNativeImage = GetNativeImageWithRef();
2448         if (pNativeImage)
2449         {
2450             pNativeImage->GetNativeILPEKindAndMachine(pdwKind, pdwMachine);
2451             return;
2452         }
2453     }
2454 #endif // DACCESS_COMPILE        
2455 #endif // FEATURE_PREJIT
2456
2457     GetILimage()->GetPEKindAndMachine(pdwKind, pdwMachine);
2458     return;
2459 }
2460
2461 ULONG PEFile::GetILImageTimeDateStamp()
2462 {
2463     CONTRACTL
2464     {
2465         NOTHROW;
2466         GC_NOTRIGGER;
2467         MODE_ANY;
2468     }
2469     CONTRACTL_END;
2470
2471 #ifdef FEATURE_PREJIT
2472     if (IsNativeLoaded())
2473     {
2474         CONSISTENCY_CHECK(HasNativeImage());
2475
2476         // The IL image's time stamp is copied to the native image.
2477         CORCOMPILE_VERSION_INFO* pVersionInfo = GetLoadedNative()->GetNativeVersionInfoMaybeNull();
2478         if (pVersionInfo == NULL)
2479         {
2480             return 0;
2481         }
2482         else
2483         {
2484             return pVersionInfo->sourceAssembly.timeStamp;
2485         }
2486     }
2487 #endif // FEATURE_PREJIT
2488
2489     return GetLoadedIL()->GetTimeDateStamp();
2490 }
2491
2492 #ifdef FEATURE_CAS_POLICY
2493
2494 //---------------------------------------------------------------------------------------
2495 //
2496 // Get a SafePEFileHandle for this PEFile
2497 //
2498
2499 SAFEHANDLE PEFile::GetSafeHandle()
2500 {
2501     CONTRACTL
2502     {
2503         THROWS;
2504         GC_TRIGGERS;
2505         MODE_COOPERATIVE;
2506     }
2507     CONTRACTL_END;
2508
2509     SAFEHANDLE objSafeHandle = NULL;
2510
2511     GCPROTECT_BEGIN(objSafeHandle);
2512
2513     objSafeHandle = (SAFEHANDLE)AllocateObject(MscorlibBinder::GetClass(CLASS__SAFE_PEFILE_HANDLE));
2514     CallDefaultConstructor(objSafeHandle);
2515
2516     this->AddRef();
2517     objSafeHandle->SetHandle(this);
2518
2519     GCPROTECT_END();
2520
2521     return objSafeHandle;
2522 }
2523
2524 #endif // FEATURE_CAS_POLICY
2525
2526 // ================================================================================
2527 // PEAssembly class - a PEFile which represents an assembly
2528 // ================================================================================
2529
2530 // Statics initialization.
2531 /* static */
2532 void PEAssembly::Attach()
2533 {
2534     STANDARD_VM_CONTRACT;
2535 }
2536
2537 #ifdef FEATURE_FUSION
2538 PEAssembly::PEAssembly(PEImage *image,
2539                        IMetaDataEmit *pEmit,
2540                        IAssembly *pIAssembly,
2541                        IBindResult *pNativeFusionAssembly,
2542                        PEImage *pPEImageNI,
2543                        IFusionBindLog *pFusionLog,
2544                        IHostAssembly *pIHostAssembly,
2545                        PEFile *creator,
2546                        BOOL system,
2547                        BOOL introspectionOnly/*=FALSE*/,
2548                        ICLRPrivAssembly * pHostAssembly)
2549       : PEFile(image, FALSE),
2550         m_creator(NULL),
2551         m_pFusionAssemblyName(NULL),
2552         m_pFusionAssembly(NULL),
2553         m_pFusionLog(NULL),
2554         m_bFusionLogEnabled(TRUE),
2555         m_pIHostAssembly(NULL),
2556         m_pNativeAssemblyLocation(NULL),
2557         m_pNativeImageClosure(NULL),
2558         m_fStrongNameBypassed(FALSE)
2559 {
2560     CONTRACTL
2561     {
2562         CONSTRUCTOR_CHECK;
2563         PRECONDITION(CheckPointer(image, NULL_OK));
2564         PRECONDITION(CheckPointer(pEmit, NULL_OK));
2565         PRECONDITION(image != NULL || pEmit != NULL);
2566         PRECONDITION(CheckPointer(pIAssembly, NULL_OK));
2567         PRECONDITION(CheckPointer(pFusionLog, NULL_OK));
2568         PRECONDITION(CheckPointer(pIHostAssembly, NULL_OK));
2569         PRECONDITION(CheckPointer(creator, NULL_OK));
2570         STANDARD_VM_CHECK;
2571     }
2572     CONTRACTL_END;    
2573
2574     if (introspectionOnly)
2575     {
2576         if (!system)  // Implementation restriction: mscorlib.dll cannot be loaded as introspection. The architecture depends on there being exactly one mscorlib.
2577         {
2578             m_flags |= PEFILE_INTROSPECTIONONLY;
2579 #ifdef FEATURE_PREJIT
2580             SetCannotUseNativeImage();
2581 #endif // FEATURE_PREJIT
2582         }
2583     }
2584
2585     if (pIAssembly)
2586     {
2587         m_pFusionAssembly = pIAssembly;
2588         pIAssembly->AddRef();
2589
2590         IfFailThrow(pIAssembly->GetAssemblyNameDef(&m_pFusionAssemblyName));
2591     }
2592     else if (pIHostAssembly)
2593     {
2594         m_flags |= PEFILE_ISTREAM;
2595 #ifdef FEATURE_PREJIT
2596         m_fCanUseNativeImage = FALSE;
2597 #endif // FEATURE_PREJIT
2598
2599         m_pIHostAssembly = pIHostAssembly;
2600         pIHostAssembly->AddRef();
2601
2602         IfFailThrow(pIHostAssembly->GetAssemblyNameDef(&m_pFusionAssemblyName));
2603     }
2604
2605     if (pFusionLog)
2606     {
2607         m_pFusionLog = pFusionLog;
2608         pFusionLog->AddRef();
2609     }
2610
2611     if (creator)
2612     {
2613         m_creator = creator;
2614         creator->AddRef();
2615     }
2616
2617     m_flags |= PEFILE_ASSEMBLY;
2618     if (system)
2619         m_flags |= PEFILE_SYSTEM;
2620
2621 #ifdef FEATURE_PREJIT
2622     // Find the native image
2623     if (pIAssembly)
2624     {
2625         if (pNativeFusionAssembly != NULL)
2626             SetNativeImage(pNativeFusionAssembly);
2627     }
2628     // Only one of pNativeFusionAssembly and pPEImageNI may be set.
2629     _ASSERTE(!(pNativeFusionAssembly && pPEImageNI));
2630
2631     if (pPEImageNI != NULL)
2632         this->PEFile::SetNativeImage(pPEImageNI);
2633 #endif  // FEATURE_PREJIT
2634
2635     // If we have no native image, we require a mapping for the file.
2636     if (!HasNativeImage() || !IsILOnly())
2637         EnsureImageOpened();
2638
2639     // Open metadata eagerly to minimize failure windows
2640     if (pEmit == NULL)
2641         OpenMDImport_Unsafe(); //constructor, cannot race with anything
2642     else
2643     {
2644         _ASSERTE(!m_bHasPersistentMDImport);
2645         IfFailThrow(GetMetaDataInternalInterfaceFromPublic(pEmit, IID_IMDInternalImport,
2646                                                            (void **)&m_pMDImport));
2647         m_pEmitter = pEmit;
2648         pEmit->AddRef();
2649         m_bHasPersistentMDImport=TRUE;
2650         m_MDImportIsRW_Debugger_Use_Only = TRUE;
2651     }
2652
2653     // m_pMDImport can be external
2654     // Make sure this is an assembly
2655     if (!m_pMDImport->IsValidToken(TokenFromRid(1, mdtAssembly)))
2656         ThrowHR(COR_E_ASSEMBLYEXPECTED);
2657
2658     // Make sure we perform security checks after we've obtained IMDInternalImport interface
2659     DoLoadSignatureChecks();
2660
2661     // Verify name eagerly
2662     LPCUTF8 szName = GetSimpleName();
2663     if (!*szName)
2664     {
2665         ThrowHR(COR_E_BADIMAGEFORMAT, BFA_EMPTY_ASSEMDEF_NAME);
2666     }
2667
2668 #ifdef FEATURE_PREJIT
2669     if (IsResource() || IsDynamic())
2670         m_fCanUseNativeImage = FALSE;
2671 #endif // FEATURE_PREJIT
2672
2673     if (m_pFusionAssembly)
2674     {
2675         m_loadContext = m_pFusionAssembly->GetFusionLoadContext();
2676         m_pFusionAssembly->GetAssemblyLocation(&m_dwLocationFlags);
2677     }
2678     else if (pHostAssembly != nullptr)
2679     {
2680         m_loadContext = LOADCTX_TYPE_HOSTED;
2681         m_dwLocationFlags = ASMLOC_UNKNOWN;
2682         m_pHostAssembly = clr::SafeAddRef(pHostAssembly); // Should use SetHostAssembly(pHostAssembly) here
2683     }
2684     else
2685     {
2686         m_loadContext = LOADCTX_TYPE_UNKNOWN;
2687         m_dwLocationFlags = ASMLOC_UNKNOWN;
2688     }
2689
2690     TESTHOOKCALL(CompletedNativeImageBind(image,szName,HasNativeImage()));
2691
2692 #if _DEBUG
2693     GetCodeBaseOrName(m_debugName);
2694     m_debugName.Normalize();
2695     m_pDebugName = m_debugName;
2696 #endif
2697 }
2698
2699 #else // FEATURE_FUSION
2700
2701 PEAssembly::PEAssembly(
2702                 CoreBindResult* pBindResultInfo, 
2703                 IMetaDataEmit* pEmit, 
2704                 PEFile *creator, 
2705                 BOOL system,
2706                 BOOL introspectionOnly/*=FALSE*/,
2707                 PEImage * pPEImageIL /*= NULL*/,
2708                 PEImage * pPEImageNI /*= NULL*/,
2709                 ICLRPrivAssembly * pHostAssembly /*= NULL*/)
2710
2711   : PEFile(pBindResultInfo ? (pBindResultInfo->GetPEImage() ? pBindResultInfo->GetPEImage() : 
2712                                                               (pBindResultInfo->HasNativeImage() ? pBindResultInfo->GetNativeImage() : NULL)
2713                               ): pPEImageIL? pPEImageIL:(pPEImageNI? pPEImageNI:NULL), FALSE),
2714     m_creator(clr::SafeAddRef(creator)),
2715     m_bIsFromGAC(FALSE),
2716     m_bIsOnTpaList(FALSE)
2717     ,m_fProfileAssembly(0)
2718 {
2719     CONTRACTL
2720     {
2721         CONSTRUCTOR_CHECK;
2722         PRECONDITION(CheckPointer(pEmit, NULL_OK));
2723         PRECONDITION(CheckPointer(creator, NULL_OK));
2724         PRECONDITION(pBindResultInfo == NULL || (pPEImageIL == NULL && pPEImageNI == NULL));
2725         STANDARD_VM_CHECK;
2726     }
2727     CONTRACTL_END;
2728
2729     if (introspectionOnly)
2730     {
2731         if (!system)  // Implementation restriction: mscorlib.dll cannot be loaded as introspection. The architecture depends on there being exactly one mscorlib.
2732         {
2733             m_flags |= PEFILE_INTROSPECTIONONLY;
2734         }
2735     }
2736
2737     m_flags |= PEFILE_ASSEMBLY;
2738     if (system)
2739         m_flags |= PEFILE_SYSTEM;
2740
2741     // We check the precondition above that either pBindResultInfo is null or both pPEImageIL and pPEImageNI are,
2742     // so we'll only get a max of one native image passed in.
2743     if (pPEImageNI != NULL)
2744     {
2745         SetNativeImage(pPEImageNI);
2746     }
2747
2748 #ifdef FEATURE_PREJIT
2749     if (pBindResultInfo && pBindResultInfo->HasNativeImage())
2750         SetNativeImage(pBindResultInfo->GetNativeImage());
2751 #endif
2752
2753     // If we have no native image, we require a mapping for the file.
2754     if (!HasNativeImage() || !IsILOnly())
2755         EnsureImageOpened();
2756
2757     // Initialize the status of the assembly being in the GAC, or being part of the TPA list, before
2758     // we start to do work (like strong name verification) that relies on those states to be valid.
2759     if(pBindResultInfo != nullptr)
2760     {
2761         m_bIsFromGAC = pBindResultInfo->IsFromGAC();
2762         m_bIsOnTpaList = pBindResultInfo->IsOnTpaList();
2763     }
2764
2765     // Check security related stuff
2766     VerifyStrongName();
2767
2768     // Open metadata eagerly to minimize failure windows
2769     if (pEmit == NULL)
2770         OpenMDImport_Unsafe(); //constructor, cannot race with anything
2771     else
2772     {
2773         _ASSERTE(!m_bHasPersistentMDImport);
2774         IfFailThrow(GetMetaDataInternalInterfaceFromPublic(pEmit, IID_IMDInternalImport,
2775                                                            (void **)&m_pMDImport));
2776         m_pEmitter = pEmit;
2777         pEmit->AddRef();
2778         m_bHasPersistentMDImport=TRUE;
2779         m_MDImportIsRW_Debugger_Use_Only = TRUE;
2780     }
2781
2782     // m_pMDImport can be external
2783     // Make sure this is an assembly
2784     if (!m_pMDImport->IsValidToken(TokenFromRid(1, mdtAssembly)))
2785         ThrowHR(COR_E_ASSEMBLYEXPECTED);
2786
2787     // Verify name eagerly
2788     LPCUTF8 szName = GetSimpleName();
2789     if (!*szName)
2790     {
2791         ThrowHR(COR_E_BADIMAGEFORMAT, BFA_EMPTY_ASSEMDEF_NAME);
2792     }
2793
2794     // Set the host assembly and binding context as the AssemblySpec initialization
2795     // for CoreCLR will expect to have it set.
2796     if (pHostAssembly != nullptr)
2797     {
2798         m_pHostAssembly = clr::SafeAddRef(pHostAssembly);
2799     }
2800
2801     if(pBindResultInfo != nullptr)
2802     {
2803         // Cannot have both pHostAssembly and a coreclr based bind
2804         _ASSERTE(pHostAssembly == nullptr);
2805         pBindResultInfo->GetBindAssembly(&m_pHostAssembly);
2806     }
2807     
2808 #if _DEBUG
2809     GetCodeBaseOrName(m_debugName);
2810     m_debugName.Normalize();
2811     m_pDebugName = m_debugName;
2812
2813     AssemblySpec spec;
2814     spec.InitializeSpec(this);
2815
2816     spec.GetFileOrDisplayName(ASM_DISPLAYF_VERSION |
2817                               ASM_DISPLAYF_CULTURE |
2818                               ASM_DISPLAYF_PUBLIC_KEY_TOKEN,
2819                               m_sTextualIdentity);
2820 #endif
2821 }
2822 #endif // FEATURE_FUSION
2823
2824
2825 #ifdef FEATURE_FUSION
2826
2827 PEAssembly *PEAssembly::Open(
2828     PEAssembly *pParentAssembly,
2829     PEImage *pPEImageIL,
2830     BOOL isIntrospectionOnly)
2831 {
2832     STANDARD_VM_CONTRACT;
2833     PEAssembly * pPEAssembly = new PEAssembly(
2834         pPEImageIL, // PEImage
2835         nullptr,    // IMetaDataEmit
2836         nullptr,    // IAssembly
2837         nullptr,    // IBindResult pNativeFusionAssembly
2838         nullptr,    // PEImage *pNIImage
2839         nullptr,    // IFusionBindLog
2840         nullptr,    // IHostAssembly
2841         pParentAssembly,    // creator
2842         FALSE,      // isSystem
2843         isIntrospectionOnly,      // isIntrospectionOnly
2844         NULL);
2845
2846     return pPEAssembly;
2847 }
2848
2849 PEAssembly *PEAssembly::Open(
2850     PEAssembly *       pParent,
2851     PEImage *          pPEImageIL, 
2852     PEImage *          pPEImageNI, 
2853     ICLRPrivAssembly * pHostAssembly, 
2854     BOOL               fIsIntrospectionOnly)
2855 {
2856     STANDARD_VM_CONTRACT;
2857     PEAssembly * pPEAssembly = new PEAssembly(
2858         pPEImageIL, // PEImage
2859         nullptr,    // IMetaDataEmit
2860         nullptr,    // IAssembly
2861         nullptr,    // IBindResult pNativeFusionAssembly
2862         pPEImageNI, // Native Image PEImage
2863         nullptr,    // IFusionBindLog
2864         nullptr,    // IHostAssembly
2865         pParent,    // creator
2866         FALSE,      // isSystem
2867         fIsIntrospectionOnly, 
2868         pHostAssembly);
2869
2870     return pPEAssembly;
2871 }
2872
2873 #else //FEATURE_FUSION
2874
2875 PEAssembly *PEAssembly::Open(
2876     PEAssembly *       pParent,
2877     PEImage *          pPEImageIL, 
2878     PEImage *          pPEImageNI, 
2879     ICLRPrivAssembly * pHostAssembly, 
2880     BOOL               fIsIntrospectionOnly)
2881 {
2882     STANDARD_VM_CONTRACT;
2883
2884     PEAssembly * pPEAssembly = new PEAssembly(
2885         nullptr,        // BindResult
2886         nullptr,        // IMetaDataEmit
2887         pParent,        // PEFile creator
2888         FALSE,          // isSystem
2889         fIsIntrospectionOnly,
2890         pPEImageIL,
2891         pPEImageNI,
2892         pHostAssembly);
2893
2894     return pPEAssembly;
2895 }
2896
2897 #endif // FEATURE_FUSION
2898
2899 PEAssembly::~PEAssembly()
2900 {
2901     CONTRACTL
2902     {
2903         DESTRUCTOR_CHECK;
2904         NOTHROW;
2905         GC_TRIGGERS; // Fusion uses crsts on AddRef/Release
2906         MODE_ANY;
2907     }
2908     CONTRACTL_END;
2909
2910     GCX_PREEMP();
2911 #ifdef FEATURE_FUSION    
2912     if (m_pFusionAssemblyName != NULL)
2913         m_pFusionAssemblyName->Release();
2914     if (m_pFusionAssembly != NULL)
2915         m_pFusionAssembly->Release();
2916     if (m_pIHostAssembly != NULL)
2917         m_pIHostAssembly->Release();
2918     if (m_pNativeAssemblyLocation != NULL)
2919     {
2920         m_pNativeAssemblyLocation->Release();
2921     }
2922     if (m_pNativeImageClosure!=NULL)
2923         m_pNativeImageClosure->Release();
2924     if (m_pFusionLog != NULL)
2925         m_pFusionLog->Release();
2926 #endif // FEATURE_FUSION
2927     if (m_creator != NULL)
2928         m_creator->Release();
2929
2930 }
2931
2932 #ifndef  DACCESS_COMPILE
2933 void PEAssembly::ReleaseIL()
2934 {
2935     CONTRACTL
2936     {
2937         INSTANCE_CHECK;
2938         NOTHROW;
2939         GC_TRIGGERS; 
2940         MODE_ANY;
2941     }
2942     CONTRACTL_END;
2943
2944     GCX_PREEMP();
2945 #ifdef FEATURE_FUSION
2946     if (m_pFusionAssemblyName != NULL)
2947     {
2948         m_pFusionAssemblyName->Release();
2949         m_pFusionAssemblyName=NULL;
2950     }
2951     if (m_pFusionAssembly != NULL)
2952     {
2953         m_pFusionAssembly->Release();
2954         m_pFusionAssembly=NULL;
2955     }
2956     if (m_pIHostAssembly != NULL)
2957     {
2958         m_pIHostAssembly->Release();
2959         m_pIHostAssembly=NULL;
2960     }
2961     if (m_pNativeAssemblyLocation != NULL)
2962     {
2963         m_pNativeAssemblyLocation->Release();
2964         m_pNativeAssemblyLocation=NULL;
2965     }
2966     _ASSERTE(m_pNativeImageClosure==NULL);
2967     
2968     if (m_pFusionLog != NULL)
2969     {
2970         m_pFusionLog->Release();
2971         m_pFusionLog=NULL;
2972     }
2973 #endif // FEATURE_FUSION
2974     if (m_creator != NULL)
2975     {
2976         m_creator->Release();
2977         m_creator=NULL;
2978     }
2979
2980     PEFile::ReleaseIL();
2981 }
2982 #endif 
2983
2984 /* static */
2985
2986 #ifdef FEATURE_FUSION
2987 PEAssembly *PEAssembly::OpenSystem(IApplicationContext * pAppCtx)
2988 #else
2989 PEAssembly *PEAssembly::OpenSystem(IUnknown * pAppCtx)
2990 #endif
2991 {
2992     STANDARD_VM_CONTRACT;
2993
2994     PEAssembly *result = NULL;
2995
2996     EX_TRY
2997     {
2998         result = DoOpenSystem(pAppCtx);
2999     }
3000     EX_HOOK
3001     {
3002         Exception *ex = GET_EXCEPTION();
3003
3004         // Rethrow non-transient exceptions as file load exceptions with proper
3005         // context
3006
3007         if (!ex->IsTransient())
3008             EEFileLoadException::Throw(SystemDomain::System()->BaseLibrary(), ex->GetHR(), ex);
3009     }
3010     EX_END_HOOK;
3011     return result;
3012 }
3013
3014 /* static */
3015 #ifdef FEATURE_FUSION
3016 PEAssembly *PEAssembly::DoOpenSystem(IApplicationContext * pAppCtx)
3017 #else
3018 PEAssembly *PEAssembly::DoOpenSystem(IUnknown * pAppCtx)
3019 #endif
3020 {
3021     CONTRACT(PEAssembly *)
3022     {
3023         POSTCONDITION(CheckPointer(RETVAL));
3024         STANDARD_VM_CHECK;
3025     }
3026     CONTRACT_END;
3027
3028 #ifdef FEATURE_FUSION
3029     SafeComHolder<IAssemblyName> pName;
3030     IfFailThrow(CreateAssemblyNameObject(&pName, W("mscorlib"), 0, NULL));
3031
3032     UINT64 publicKeyValue = I64(CONCAT_MACRO(0x, VER_ECMA_PUBLICKEY));
3033     BYTE publicKeyToken[8] =
3034         {
3035             (BYTE) (publicKeyValue>>56),
3036             (BYTE) (publicKeyValue>>48),
3037             (BYTE) (publicKeyValue>>40),
3038             (BYTE) (publicKeyValue>>32),
3039             (BYTE) (publicKeyValue>>24),
3040             (BYTE) (publicKeyValue>>16),
3041             (BYTE) (publicKeyValue>>8),
3042             (BYTE) (publicKeyValue),
3043         };
3044
3045     IfFailThrow(pName->SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, publicKeyToken, sizeof(publicKeyToken)));
3046
3047     USHORT version = VER_ASSEMBLYMAJORVERSION;
3048     IfFailThrow(pName->SetProperty(ASM_NAME_MAJOR_VERSION, &version, sizeof(version)));
3049     version = VER_ASSEMBLYMINORVERSION;
3050     IfFailThrow(pName->SetProperty(ASM_NAME_MINOR_VERSION, &version, sizeof(version)));
3051     version = VER_ASSEMBLYBUILD;
3052     IfFailThrow(pName->SetProperty(ASM_NAME_BUILD_NUMBER, &version, sizeof(version)));
3053     version = VER_ASSEMBLYBUILD_QFE;
3054     IfFailThrow(pName->SetProperty(ASM_NAME_REVISION_NUMBER, &version, sizeof(version)));
3055
3056     IfFailThrow(pName->SetProperty(ASM_NAME_CULTURE, W(""), sizeof(WCHAR)));
3057
3058 #ifdef FEATURE_PREJIT
3059 #ifdef PROFILING_SUPPORTED
3060     if (NGENImagesAllowed())
3061     {
3062         // Binding flags, zap string
3063         CorCompileConfigFlags configFlags = PEFile::GetNativeImageConfigFlagsWithOverrides();
3064         IfFailThrow(pName->SetProperty(ASM_NAME_CONFIG_MASK, &configFlags, sizeof(configFlags)));
3065
3066         LPCWSTR configString = g_pConfig->ZapSet();
3067         IfFailThrow(pName->SetProperty(ASM_NAME_CUSTOM, (PVOID)configString,
3068                                         (DWORD) (wcslen(configString)+1)*sizeof(WCHAR)));
3069
3070         // @TODO: Need some fuslogvw logging here
3071     }
3072 #endif //PROFILING_SUPPORTED
3073 #endif // FEATURE_PREJIT
3074
3075     SafeComHolder<IAssembly> pIAssembly;
3076     SafeComHolder<IBindResult> pNativeFusionAssembly;
3077     SafeComHolder<IFusionBindLog> pFusionLog;
3078
3079     {
3080         ETWOnStartup (FusionBinding_V1, FusionBindingEnd_V1);
3081         IfFailThrow(BindToSystem(pName, SystemDomain::System()->SystemDirectory(), NULL, pAppCtx, &pIAssembly, &pNativeFusionAssembly, &pFusionLog));
3082     }
3083
3084     StackSString path;
3085     FusionBind::GetAssemblyManifestModulePath(pIAssembly, path);
3086
3087     // Open the image with no required mapping.  This will be
3088     // promoted to a real open if we don't have a native image.
3089     PEImageHolder image (PEImage::OpenImage(path));
3090
3091     PEAssembly* pPEAssembly = new PEAssembly(image, NULL, pIAssembly,pNativeFusionAssembly, NULL, pFusionLog, NULL, NULL, TRUE, FALSE);
3092
3093 #ifdef FEATURE_APPX_BINDER
3094     if (AppX::IsAppXProcess())
3095     {
3096         // Since mscorlib is loaded as a special case, create and assign an ICLRPrivAssembly for the new PEAssembly here.
3097         CLRPrivBinderAppX *   pBinder = CLRPrivBinderAppX::GetOrCreateBinder();
3098         CLRPrivBinderFusion * pFusionBinder = pBinder->GetFusionBinder();
3099         
3100         pFusionBinder->BindMscorlib(pPEAssembly);
3101     }
3102 #endif
3103     
3104     RETURN pPEAssembly;
3105 #else // FEATURE_FUSION
3106     ETWOnStartup (FusionBinding_V1, FusionBindingEnd_V1);
3107     CoreBindResult bindResult;
3108     ReleaseHolder<ICLRPrivAssembly> pPrivAsm;
3109     IfFailThrow(CCoreCLRBinderHelper::BindToSystem(&pPrivAsm, !IsCompilationProcess() || g_fAllowNativeImages));
3110     if(pPrivAsm != NULL)
3111     {
3112         bindResult.Init(pPrivAsm, TRUE, TRUE);
3113     }
3114
3115     RETURN new PEAssembly(&bindResult, NULL, NULL, TRUE, FALSE);
3116 #endif // FEATURE_FUSION
3117 }
3118
3119 #ifdef FEATURE_FUSION
3120 /* static */
3121 PEAssembly *PEAssembly::Open(IAssembly *pIAssembly,
3122                              IBindResult *pNativeFusionAssembly,
3123                              IFusionBindLog *pFusionLog/*=NULL*/,
3124                              BOOL isSystemAssembly/*=FALSE*/,
3125                              BOOL isIntrospectionOnly/*=FALSE*/)
3126 {
3127     STANDARD_VM_CONTRACT;
3128
3129     PEAssembly *result = NULL;
3130     EX_TRY
3131     {
3132         result = DoOpen(pIAssembly, pNativeFusionAssembly, pFusionLog, isSystemAssembly, isIntrospectionOnly);
3133     }
3134     EX_HOOK
3135     {
3136         Exception *ex = GET_EXCEPTION();
3137
3138         // Rethrow non-transient exceptions as file load exceptions with proper
3139         // context
3140         if (!ex->IsTransient())
3141             EEFileLoadException::Throw(pIAssembly, NULL, ex->GetHR(), ex);
3142     }
3143     EX_END_HOOK;
3144
3145     return result;
3146 }
3147
3148 // Thread stress
3149 class DoOpenIAssemblyStress : APIThreadStress
3150 {
3151 public:
3152     IAssembly *pIAssembly;
3153     IBindResult *pNativeFusionAssembly;
3154     IFusionBindLog *pFusionLog;
3155     DoOpenIAssemblyStress(IAssembly *pIAssembly, IBindResult *pNativeFusionAssembly, IFusionBindLog *pFusionLog)
3156           : pIAssembly(pIAssembly), pNativeFusionAssembly(pNativeFusionAssembly),pFusionLog(pFusionLog) {LIMITED_METHOD_CONTRACT;}
3157     void Invoke()
3158     {
3159         WRAPPER_NO_CONTRACT;
3160         PEAssemblyHolder result (PEAssembly::Open(pIAssembly, pNativeFusionAssembly, pFusionLog, FALSE, FALSE));
3161     }
3162 };
3163
3164 /* static */
3165 PEAssembly *PEAssembly::DoOpen(IAssembly *pIAssembly,
3166                                IBindResult *pNativeFusionAssembly,
3167                                IFusionBindLog *pFusionLog,
3168                                BOOL isSystemAssembly,
3169                                BOOL isIntrospectionOnly/*=FALSE*/)
3170 {
3171     CONTRACT(PEAssembly *)
3172     {
3173         PRECONDITION(CheckPointer(pIAssembly));
3174         POSTCONDITION(CheckPointer(RETVAL));
3175         STANDARD_VM_CHECK;
3176     }
3177     CONTRACT_END;
3178
3179     DoOpenIAssemblyStress ts(pIAssembly,pNativeFusionAssembly,pFusionLog);
3180
3181     PEImageHolder image;
3182
3183     StackSString path;
3184     FusionBind::GetAssemblyManifestModulePath(pIAssembly, path);
3185
3186     // Open the image with no required mapping.  This will be
3187     // promoted to a real open if we don't have a native image.
3188     image = PEImage::OpenImage(path, MDInternalImport_NoCache); // "identity" does not need to be cached 
3189
3190     PEAssemblyHolder assembly (new PEAssembly(image, NULL, pIAssembly, pNativeFusionAssembly, NULL, pFusionLog,
3191                                                NULL, NULL, isSystemAssembly, isIntrospectionOnly));
3192
3193     RETURN assembly.Extract();
3194 }
3195
3196 /* static */
3197 PEAssembly *PEAssembly::Open(IHostAssembly *pIHostAssembly, BOOL isSystemAssembly, BOOL isIntrospectionOnly)
3198 {
3199     STANDARD_VM_CONTRACT;
3200
3201     PEAssembly *result = NULL;
3202
3203     EX_TRY
3204     {
3205         result = DoOpen(pIHostAssembly, isSystemAssembly, isIntrospectionOnly);
3206     }
3207     EX_HOOK
3208     {
3209         Exception *ex = GET_EXCEPTION();
3210
3211         // Rethrow non-transient exceptions as file load exceptions with proper
3212         // context
3213
3214         if (!ex->IsTransient())
3215             EEFileLoadException::Throw(NULL, pIHostAssembly, ex->GetHR(), ex);
3216     }
3217     EX_END_HOOK;
3218     return result;
3219 }
3220
3221 // Thread stress
3222 class DoOpenIHostAssemblyStress : APIThreadStress
3223 {
3224 public:
3225     IHostAssembly *pIHostAssembly;
3226     DoOpenIHostAssemblyStress(IHostAssembly *pIHostAssembly) :
3227         pIHostAssembly(pIHostAssembly) {LIMITED_METHOD_CONTRACT;}
3228     void Invoke()
3229     {
3230         WRAPPER_NO_CONTRACT;
3231         PEAssemblyHolder result (PEAssembly::Open(pIHostAssembly, FALSE, FALSE));
3232     }
3233 };
3234
3235 /* static */
3236 PEAssembly *PEAssembly::DoOpen(IHostAssembly *pIHostAssembly, BOOL isSystemAssembly,
3237                                BOOL isIntrospectionOnly)
3238 {
3239     CONTRACT(PEAssembly *)
3240     {
3241         PRECONDITION(CheckPointer(pIHostAssembly));
3242         POSTCONDITION(CheckPointer(RETVAL));
3243         THROWS;
3244         GC_TRIGGERS;
3245         MODE_ANY;
3246         INJECT_FAULT(COMPlusThrowOM(););
3247     }
3248     CONTRACT_END;
3249
3250     DoOpenIHostAssemblyStress ts(pIHostAssembly);
3251
3252     UINT64 AssemblyId;
3253     IfFailThrow(pIHostAssembly->GetAssemblyId(&AssemblyId));
3254
3255     PEImageHolder image(PEImage::FindById(AssemblyId, 0));
3256
3257     PEAssemblyHolder assembly (new PEAssembly(image, NULL, NULL, NULL, NULL, NULL,
3258                                               pIHostAssembly, NULL, isSystemAssembly, isIntrospectionOnly));
3259
3260     RETURN assembly.Extract();
3261 }
3262 #endif // FEATURE_FUSION
3263
3264 #ifndef CROSSGEN_COMPILE
3265 /* static */
3266 PEAssembly *PEAssembly::OpenMemory(PEAssembly *pParentAssembly,
3267                                    const void *flat, COUNT_T size,
3268                                    BOOL isIntrospectionOnly/*=FALSE*/,
3269                                    CLRPrivBinderLoadFile* pBinderToUse)
3270 {
3271     STANDARD_VM_CONTRACT;
3272
3273     PEAssembly *result = NULL;
3274
3275     EX_TRY
3276     {
3277         result = DoOpenMemory(pParentAssembly, flat, size, isIntrospectionOnly, pBinderToUse);
3278     }
3279     EX_HOOK
3280     {
3281         Exception *ex = GET_EXCEPTION();
3282
3283         // Rethrow non-transient exceptions as file load exceptions with proper
3284         // context
3285
3286         if (!ex->IsTransient())
3287             EEFileLoadException::Throw(pParentAssembly, flat, size, ex->GetHR(), ex);
3288     }
3289     EX_END_HOOK;
3290
3291     return result;
3292 }
3293
3294
3295 // Thread stress
3296
3297 class DoOpenFlatStress : APIThreadStress
3298 {
3299 public:
3300     PEAssembly *pParentAssembly;
3301     const void *flat;
3302     COUNT_T size;
3303     DoOpenFlatStress(PEAssembly *pParentAssembly, const void *flat, COUNT_T size)
3304         : pParentAssembly(pParentAssembly), flat(flat), size(size) {LIMITED_METHOD_CONTRACT;}
3305     void Invoke()
3306     {
3307         WRAPPER_NO_CONTRACT;
3308         PEAssemblyHolder result(PEAssembly::OpenMemory(pParentAssembly, flat, size, FALSE));
3309     }
3310 };
3311
3312 /* static */
3313 PEAssembly *PEAssembly::DoOpenMemory(
3314     PEAssembly *pParentAssembly,
3315     const void *flat,
3316     COUNT_T size,
3317     BOOL isIntrospectionOnly,
3318     CLRPrivBinderLoadFile* pBinderToUse)
3319 {
3320     CONTRACT(PEAssembly *)
3321     {
3322         PRECONDITION(CheckPointer(flat));
3323         PRECONDITION(CheckOverflow(flat, size));
3324         PRECONDITION(CheckPointer(pParentAssembly));
3325         STANDARD_VM_CHECK;
3326         POSTCONDITION(CheckPointer(RETVAL));
3327     }
3328     CONTRACT_END;
3329
3330     // Thread stress
3331     DoOpenFlatStress ts(pParentAssembly, flat, size);
3332
3333     // Note that we must have a flat image stashed away for two reasons.
3334     // First, we need a private copy of the data which we can verify
3335     // before doing the mapping.  And secondly, we can only compute
3336     // the strong name hash on a flat image.
3337
3338     PEImageHolder image(PEImage::LoadFlat(flat, size));
3339
3340     // Need to verify that this is a CLR assembly
3341     if (!image->CheckILFormat())
3342         ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);
3343
3344
3345 #ifdef FEATURE_FUSION    
3346     RETURN new PEAssembly(image, NULL, NULL, NULL, NULL, NULL, NULL, pParentAssembly, FALSE, isIntrospectionOnly);
3347 #else
3348     CoreBindResult bindResult;
3349     ReleaseHolder<ICLRPrivAssembly> assembly;
3350     IfFailThrow(CCoreCLRBinderHelper::GetAssemblyFromImage(image, NULL, &assembly));
3351     bindResult.Init(assembly,FALSE,FALSE);
3352
3353     RETURN new PEAssembly(&bindResult, NULL, pParentAssembly, FALSE, isIntrospectionOnly);
3354 #endif
3355 }
3356 #endif // !CROSSGEN_COMPILE
3357
3358 #if defined(FEATURE_MIXEDMODE) && !defined(CROSSGEN_COMPILE)
3359 // Use for main exe loading
3360 // This is also used for "spontaneous" (IJW) dll loading where
3361 // we need to deliver DllMain callbacks, but we should eliminate this case
3362
3363 /* static */
3364 PEAssembly *PEAssembly::OpenHMODULE(HMODULE hMod,
3365                                     IAssembly *pFusionAssembly,
3366                                     IBindResult *pNativeFusionAssembly,
3367                                     IFusionBindLog *pFusionLog/*=NULL*/,
3368                                     BOOL isIntrospectionOnly/*=FALSE*/)
3369 {
3370     STANDARD_VM_CONTRACT;
3371
3372     PEAssembly *result = NULL;
3373
3374     ETWOnStartup (OpenHModule_V1, OpenHModuleEnd_V1);
3375
3376     EX_TRY
3377     {
3378         result = DoOpenHMODULE(hMod, pFusionAssembly, pNativeFusionAssembly, pFusionLog, isIntrospectionOnly);
3379     }
3380     EX_HOOK
3381     {
3382         Exception *ex = GET_EXCEPTION();
3383
3384         // Rethrow non-transient exceptions as file load exceptions with proper
3385         // context
3386         if (!ex->IsTransient())
3387             EEFileLoadException::Throw(pFusionAssembly, NULL, ex->GetHR(), ex);
3388     }
3389     EX_END_HOOK;
3390     return result;
3391 }
3392
3393 // Thread stress
3394 class DoOpenHMODULEStress : APIThreadStress
3395 {
3396 public:
3397     HMODULE hMod;
3398     IAssembly *pFusionAssembly;
3399     IBindResult *pNativeFusionAssembly;    
3400     IFusionBindLog *pFusionLog;
3401     DoOpenHMODULEStress(HMODULE hMod, IAssembly *pFusionAssembly, IBindResult *pNativeFusionAssembly, IFusionBindLog *pFusionLog)
3402       : hMod(hMod), pFusionAssembly(pFusionAssembly), pNativeFusionAssembly(pNativeFusionAssembly),pFusionLog(pFusionLog) {LIMITED_METHOD_CONTRACT;}
3403     void Invoke()
3404     {
3405         WRAPPER_NO_CONTRACT;
3406         PEAssemblyHolder result(PEAssembly::OpenHMODULE(hMod, pFusionAssembly,pNativeFusionAssembly, pFusionLog, FALSE));
3407     }
3408 };
3409
3410 /* static */
3411 PEAssembly *PEAssembly::DoOpenHMODULE(HMODULE hMod,
3412                                       IAssembly *pFusionAssembly,
3413                                       IBindResult *pNativeFusionAssembly,
3414                                       IFusionBindLog *pFusionLog,
3415                                       BOOL isIntrospectionOnly/*=FALSE*/)
3416 {
3417     CONTRACT(PEAssembly *)
3418     {
3419         PRECONDITION(CheckPointer(hMod));
3420         PRECONDITION(CheckPointer(pFusionAssembly));
3421         PRECONDITION(CheckPointer(pNativeFusionAssembly,NULL_OK));        
3422         POSTCONDITION(CheckPointer(RETVAL));
3423         THROWS;
3424         GC_TRIGGERS;
3425         MODE_ANY;
3426         INJECT_FAULT(COMPlusThrowOM(););
3427     }
3428     CONTRACT_END;
3429
3430     DoOpenHMODULEStress ts(hMod, pFusionAssembly, pNativeFusionAssembly, pFusionLog);
3431
3432     PEImageHolder image(PEImage::LoadImage(hMod));
3433
3434     RETURN new PEAssembly(image, NULL, pFusionAssembly, pNativeFusionAssembly, NULL, pFusionLog, NULL, NULL, FALSE, isIntrospectionOnly);
3435 }
3436 #endif // FEATURE_MIXEDMODE && !CROSSGEN_COMPILE
3437
3438
3439 #ifndef FEATURE_FUSION
3440 PEAssembly* PEAssembly::Open(CoreBindResult* pBindResult,
3441                                    BOOL isSystem, BOOL isIntrospectionOnly)
3442 {
3443
3444     return new PEAssembly(pBindResult,NULL,NULL,isSystem,isIntrospectionOnly);
3445
3446 };
3447 #endif
3448
3449 /* static */
3450 PEAssembly *PEAssembly::Create(PEAssembly *pParentAssembly,
3451                                IMetaDataAssemblyEmit *pAssemblyEmit,
3452                                BOOL bIsIntrospectionOnly)
3453 {
3454     CONTRACT(PEAssembly *)
3455     {
3456         PRECONDITION(CheckPointer(pParentAssembly));
3457         PRECONDITION(CheckPointer(pAssemblyEmit));
3458         STANDARD_VM_CHECK; 
3459         POSTCONDITION(CheckPointer(RETVAL));
3460     }
3461     CONTRACT_END;
3462
3463     // Set up the metadata pointers in the PEAssembly. (This is the only identity
3464     // we have.)
3465     SafeComHolder<IMetaDataEmit> pEmit;
3466     pAssemblyEmit->QueryInterface(IID_IMetaDataEmit, (void **)&pEmit);
3467 #ifdef FEATURE_FUSION
3468     ReleaseHolder<ICLRPrivAssembly> pPrivAssembly;
3469     if (pParentAssembly->HasHostAssembly())
3470     {
3471         // Dynamic assemblies in AppX use their parent's ICLRPrivAssembly as the binding context.
3472         pPrivAssembly = clr::SafeAddRef(new CLRPrivBinderUtil::CLRPrivBinderAsAssemblyWrapper(
3473             pParentAssembly->GetHostAssembly()));
3474     }
3475
3476     PEAssemblyHolder pFile(new PEAssembly(
3477         NULL, pEmit, NULL, NULL, NULL, NULL, NULL, pParentAssembly,
3478         FALSE, bIsIntrospectionOnly,
3479         pPrivAssembly));
3480 #else
3481     PEAssemblyHolder pFile(new PEAssembly(NULL, pEmit, pParentAssembly, FALSE, bIsIntrospectionOnly));
3482 #endif
3483     RETURN pFile.Extract();
3484 }
3485
3486
3487 #ifdef FEATURE_PREJIT
3488
3489 #ifdef FEATURE_FUSION
3490 BOOL PEAssembly::HasEqualNativeClosure(DomainAssembly * pDomainAssembly)
3491 {
3492     CONTRACTL
3493     {
3494         GC_TRIGGERS;
3495         THROWS;
3496         MODE_ANY;
3497         PRECONDITION(CheckPointer(pDomainAssembly));
3498     }
3499     CONTRACTL_END;
3500     if (IsSystem())
3501         return TRUE;
3502     HRESULT hr = S_OK;
3503
3504
3505     if (m_pNativeImageClosure == NULL)
3506         return FALSE;
3507
3508     // ensure theclosures are walked
3509     IAssemblyBindingClosure * pClosure = pDomainAssembly->GetAssemblyBindingClosure(LEVEL_COMPLETE);
3510     _ASSERTE(pClosure != NULL);
3511
3512     if (m_pNativeImageClosure->HasBeenWalked(LEVEL_COMPLETE) != S_OK )
3513     {
3514         GCX_COOP();
3515
3516         ENTER_DOMAIN_PTR(SystemDomain::System()->DefaultDomain(),ADV_DEFAULTAD);
3517         {
3518             GCX_PREEMP();
3519             IfFailThrow(m_pNativeImageClosure->EnsureWalked(GetFusionAssembly(),GetAppDomain()->GetFusionContext(),LEVEL_COMPLETE));
3520         }
3521         END_DOMAIN_TRANSITION;
3522     }
3523
3524
3525     hr = pClosure->IsEqual(m_pNativeImageClosure);
3526     IfFailThrow(hr);
3527     return (hr == S_OK);
3528 }
3529 #endif //FEATURE_FUSION
3530
3531 #ifdef FEATURE_FUSION
3532 void PEAssembly::SetNativeImage(IBindResult *pNativeFusionAssembly)
3533 {
3534     CONTRACTL
3535     {
3536         INSTANCE_CHECK;
3537         STANDARD_VM_CHECK;
3538     }
3539     CONTRACTL_END;
3540
3541     StackSString path;
3542     WCHAR pwzPath[MAX_LONGPATH];
3543     DWORD dwCCPath = MAX_LONGPATH;
3544     ReleaseHolder<IAssemblyLocation> pIAssemblyLocation;
3545
3546     IfFailThrow(pNativeFusionAssembly->GetAssemblyLocation(&pIAssemblyLocation));
3547     IfFailThrow(pIAssemblyLocation->GetPath(pwzPath, &dwCCPath));
3548     path.Set(pwzPath);
3549
3550     PEImageHolder image(PEImage::OpenImage(path));
3551     image->Load();
3552
3553     // For desktop dev11, this verification is now done at native binding time.
3554     _ASSERTE(CheckNativeImageVersion(image));
3555
3556     PEFile::SetNativeImage(image);
3557     IfFailThrow(pNativeFusionAssembly->GetAssemblyLocation(&m_pNativeAssemblyLocation));
3558 }
3559 #else //FEATURE_FUSION
3560 void PEAssembly::SetNativeImage(PEImage * image)
3561 {
3562     CONTRACTL
3563     {
3564         INSTANCE_CHECK;
3565         STANDARD_VM_CHECK;
3566     }
3567     CONTRACTL_END;
3568
3569     image->Load();
3570
3571     if (CheckNativeImageVersion(image))
3572     {
3573         PEFile::SetNativeImage(image);
3574 #if 0
3575         //Enable this code if you want to make sure we never touch the flat layout in the presence of the
3576         //ngen image.
3577 //#if defined(_DEBUG)
3578         //find all the layouts in the il image and make sure we never touch them.
3579         unsigned ignored = 0;
3580         PTR_PEImageLayout layout = m_ILimage->GetLayout(PEImageLayout::LAYOUT_FLAT, 0);
3581         if (layout != NULL)
3582         {
3583             //cache a bunch of PE metadata in the PEDecoder
3584             m_ILimage->CheckILFormat();
3585
3586             //we also need some of metadata (for the public key), so cache this too
3587             DWORD verifyOutputFlags;
3588             m_ILimage->VerifyStrongName(&verifyOutputFlags);
3589             //fudge this by a few pages to make sure we can still mess with the PE headers
3590             const size_t fudgeSize = 4096 * 4;
3591             ClrVirtualProtect((void*)(((char *)layout->GetBase()) + fudgeSize),
3592                               layout->GetSize() - fudgeSize, 0, &ignored);
3593             layout->Release();
3594         }
3595 #endif
3596     }
3597     else
3598     {
3599         ExternalLog(LL_WARNING, "Native image is not correct version.");
3600     }
3601 }
3602 #endif //FEATURE_FUSION
3603
3604 #ifdef FEATURE_FUSION
3605 void PEAssembly::ClearNativeImage()
3606 {
3607     CONTRACT_VOID
3608     {
3609         INSTANCE_CHECK;
3610         PRECONDITION(HasNativeImage());
3611         POSTCONDITION(!HasNativeImage());
3612         THROWS;
3613         GC_TRIGGERS;
3614         MODE_ANY;
3615         INJECT_FAULT(COMPlusThrowOM(););
3616     }
3617     CONTRACT_END;
3618
3619     PEFile::ClearNativeImage();
3620
3621     if (m_pNativeAssemblyLocation != NULL)
3622         m_pNativeAssemblyLocation->Release();
3623     m_pNativeAssemblyLocation = NULL;
3624     if (m_pNativeImageClosure != NULL)
3625         m_pNativeImageClosure->Release();
3626     m_pNativeImageClosure = NULL;
3627     RETURN;
3628 }
3629 #endif //FEATURE_FUSION
3630 #endif  // FEATURE_PREJIT
3631
3632
3633 #ifdef FEATURE_FUSION
3634 BOOL PEAssembly::IsBindingCodeBase()
3635 {
3636     CONTRACTL
3637     {
3638         INSTANCE_CHECK;
3639         THROWS;
3640         GC_TRIGGERS;
3641         MODE_ANY;
3642         INJECT_FAULT(COMPlusThrowOM(););
3643     }
3644     CONTRACTL_END;
3645
3646     if (m_pIHostAssembly != NULL)
3647         return FALSE;
3648
3649     if (m_pFusionAssembly == NULL)
3650         return (!GetPath().IsEmpty());
3651
3652     if (m_dwLocationFlags == ASMLOC_UNKNOWN)
3653         return FALSE;
3654
3655     return ((m_dwLocationFlags & ASMLOC_CODEBASE_HINT) != 0);
3656 }
3657
3658 BOOL PEAssembly::IsSourceGAC()
3659 {
3660     LIMITED_METHOD_CONTRACT;
3661
3662     if ((m_pIHostAssembly != NULL) || (m_pFusionAssembly == NULL))
3663     {
3664         return FALSE;
3665     }
3666
3667     return ((m_dwLocationFlags & ASMLOC_LOCATION_MASK) == ASMLOC_GAC);
3668 }
3669
3670 BOOL PEAssembly::IsSourceDownloadCache()
3671 {
3672     LIMITED_METHOD_CONTRACT;
3673
3674     if ((m_pIHostAssembly != NULL) || (m_pFusionAssembly == NULL))
3675     {
3676         return FALSE;
3677     }
3678     
3679     return ((m_dwLocationFlags & ASMLOC_LOCATION_MASK) == ASMLOC_DOWNLOAD_CACHE);
3680 }
3681
3682 #else // FEATURE_FUSION
3683 BOOL PEAssembly::IsSourceGAC()
3684 {
3685     WRAPPER_NO_CONTRACT;
3686     return m_bIsFromGAC;
3687 };
3688
3689 #endif // FEATURE_FUSION
3690
3691 #endif // #ifndef DACCESS_COMPILE
3692
3693 #ifdef FEATURE_FUSION
3694 BOOL PEAssembly::IsContextLoad()
3695 {
3696     LIMITED_METHOD_CONTRACT;
3697     if ((m_pIHostAssembly != NULL) || (m_pFusionAssembly == NULL))
3698     {
3699         return FALSE;
3700     }
3701     return (IsSystem() || (m_loadContext == LOADCTX_TYPE_DEFAULT));
3702 }
3703
3704 LOADCTX_TYPE PEAssembly::GetLoadContext()
3705 {
3706     LIMITED_METHOD_CONTRACT;
3707
3708     return m_loadContext;
3709 }
3710
3711 DWORD PEAssembly::GetLocationFlags()
3712 {
3713     LIMITED_METHOD_CONTRACT;
3714
3715     return m_dwLocationFlags;
3716 }
3717
3718 #endif
3719
3720
3721 #ifndef DACCESS_COMPILE
3722
3723 #ifdef FEATURE_FUSION
3724 PEKIND PEAssembly::GetFusionProcessorArchitecture()
3725 {
3726     CONTRACTL
3727     {
3728         THROWS;
3729         MODE_ANY;
3730         GC_TRIGGERS;
3731     }
3732     CONTRACTL_END;
3733
3734     PEImage * pImage = NULL;
3735
3736 #ifdef FEATURE_PREJIT 
3737     pImage = m_nativeImage;
3738 #endif
3739
3740     if (pImage == NULL)
3741         pImage = GetILimage();
3742
3743     return pImage->GetFusionProcessorArchitecture();
3744 }
3745
3746 IAssemblyName * PEAssembly::GetFusionAssemblyName()
3747 {
3748     CONTRACT(IAssemblyName *)
3749     {
3750         INSTANCE_CHECK;
3751         POSTCONDITION(CheckPointer(RETVAL));
3752         THROWS;
3753         GC_TRIGGERS;
3754         MODE_ANY;
3755         INJECT_FAULT(COMPlusThrowOM(););
3756     }
3757     CONTRACT_END;
3758
3759     if (m_pFusionAssemblyName == NULL)
3760     {
3761         AssemblySpec spec;
3762         spec.InitializeSpec(this);
3763         PEImage * pImage = GetILimage();
3764
3765 #ifdef FEATURE_PREJIT 
3766         if ((pImage != NULL) && !pImage->MDImportLoaded())
3767             pImage = m_nativeImage;
3768 #endif
3769
3770         if (pImage != NULL)
3771         {
3772             spec.SetPEKIND(pImage->GetFusionProcessorArchitecture());
3773         }
3774
3775         GCX_PREEMP();
3776
3777         IfFailThrow(spec.CreateFusionName(&m_pFusionAssemblyName, FALSE));
3778     }
3779
3780     RETURN m_pFusionAssemblyName;
3781 }
3782
3783 // This version of GetFusionAssemlyName that can be used to return the reference in a
3784 // NOTHROW/NOTRIGGER fashion. This is useful for scenarios where you dont want to invoke the THROWS/GCTRIGGERS
3785 // version when you know the name would have been created and is available.
3786 IAssemblyName * PEAssembly::GetFusionAssemblyNameNoCreate()
3787 {
3788     LIMITED_METHOD_CONTRACT;
3789
3790     return m_pFusionAssemblyName;
3791 }
3792
3793 IAssembly *PEAssembly::GetFusionAssembly()
3794 {
3795     CONTRACT(IAssembly *)
3796     {
3797         INSTANCE_CHECK;
3798         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
3799         NOTHROW;
3800         GC_NOTRIGGER;
3801         MODE_ANY;
3802     }
3803     CONTRACT_END;
3804
3805     RETURN m_pFusionAssembly;
3806 }
3807
3808 IHostAssembly *PEAssembly::GetIHostAssembly()
3809 {
3810     CONTRACT(IHostAssembly *)
3811     {
3812         INSTANCE_CHECK;
3813         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
3814         NOTHROW;
3815         GC_NOTRIGGER;
3816         MODE_ANY;
3817     }
3818     CONTRACT_END;
3819
3820     RETURN m_pIHostAssembly;
3821 }
3822
3823 IAssemblyLocation *PEAssembly::GetNativeAssemblyLocation()
3824 {
3825     CONTRACT(IAssemblyLocation *)
3826     {
3827         INSTANCE_CHECK;
3828         PRECONDITION(HasNativeImage());
3829         POSTCONDITION(CheckPointer(RETVAL));
3830         NOTHROW;
3831         GC_NOTRIGGER;
3832         MODE_ANY;
3833     }
3834     CONTRACT_END;
3835
3836     RETURN m_pNativeAssemblyLocation;
3837 }
3838 #endif // FEATURE_FUSION
3839
3840 // ------------------------------------------------------------
3841 // Hash support
3842 // ------------------------------------------------------------
3843
3844 void PEAssembly::VerifyStrongName()
3845 {
3846     CONTRACTL
3847     {
3848         INSTANCE_CHECK;
3849         THROWS;
3850         GC_TRIGGERS;
3851         MODE_ANY;
3852         INJECT_FAULT(COMPlusThrowOM(););
3853     }
3854     CONTRACTL_END;
3855
3856     // If we've already done the signature checks, we don't need to do them again.
3857     if (m_fStrongNameVerified)
3858     {
3859         return;
3860     }
3861
3862 #ifdef FEATURE_FUSION
3863     // System and dynamic assemblies don't need hash checks
3864     if (IsSystem() || IsDynamic())
3865 #else
3866     // Without FUSION/GAC, we need to verify SN on all assemblies, except dynamic assemblies.
3867     if (IsDynamic())
3868 #endif
3869     {
3870
3871         m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
3872         m_fStrongNameVerified = TRUE;
3873         return;
3874     }
3875
3876     // Next, verify the strong name, if necessary
3877 #ifdef FEATURE_FUSION
3878     // See if the assembly comes from a secure location
3879     IAssembly *pFusionAssembly = GetAssembly()->GetFusionAssembly();
3880     if (pFusionAssembly)
3881     {
3882         DWORD dwLocation;
3883         IfFailThrow(pFusionAssembly->GetAssemblyLocation(&dwLocation));
3884
3885         switch (dwLocation & ASMLOC_LOCATION_MASK)
3886         {
3887         case ASMLOC_GAC:
3888         case ASMLOC_DOWNLOAD_CACHE:
3889         case ASMLOC_DEV_OVERRIDE:
3890             // Assemblies from the GAC or download cache have
3891             // already been verified by Fusion.
3892             m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
3893             m_fStrongNameVerified = TRUE;
3894             return;
3895
3896         case ASMLOC_RUN_FROM_SOURCE:
3897         case ASMLOC_UNKNOWN:
3898             // For now, just verify these every time, we need to
3899             // cache the fact that at least one verification has
3900             // been performed (if strong name policy permits
3901             // caching of verification results)
3902             break;
3903
3904         default:
3905             UNREACHABLE();
3906         }
3907     }
3908 #endif
3909
3910     // Check format of image. Note we must delay this until after the GAC status has been
3911     // checked, to handle the case where we are not loading m_image.
3912     EnsureImageOpened();
3913
3914
3915     if (m_nativeImage == NULL && !GetILimage()->IsTrustedNativeImage())
3916     {
3917         if (!GetILimage()->CheckILFormat())
3918             ThrowHR(COR_E_BADIMAGEFORMAT);
3919     }
3920
3921     // Check the strong name if present.
3922     if (IsIntrospectionOnly())
3923     {
3924         // For introspection assemblies, we don't need to check strong names and we don't
3925         // need to do module hash checks.
3926         m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
3927     }
3928     else
3929     {
3930         // Runtime policy on CoreCLR is to skip verification of ALL assemblies
3931         m_flags |= PEFILE_SKIP_MODULE_HASH_CHECKS;
3932         m_fStrongNameVerified = TRUE;
3933     }
3934
3935     m_fStrongNameVerified = TRUE;
3936 }
3937
3938 BOOL PEAssembly::IsProfileAssembly()
3939 {
3940     CONTRACTL
3941     {
3942         THROWS;
3943         GC_TRIGGERS;
3944         MODE_ANY;
3945     }
3946     CONTRACTL_END;
3947
3948     //
3949     // For now, cache the result of the check below. This cache should be removed once/if the check below 
3950     // becomes cheap (e.g. does not access metadata anymore).
3951     //
3952     if (VolatileLoadWithoutBarrier(&m_fProfileAssembly) != 0)
3953     {
3954         return m_fProfileAssembly > 0;
3955     }
3956
3957     //
3958     // In order to be a platform (profile) assembly, you must be from a trusted location (TPA list)
3959     // If we are binding by TPA list and this assembly is on it, IsSourceGAC is true => Assembly is Profile
3960     // If the assembly is a WinMD, it is automatically trusted since all WinMD scenarios are full trust scenarios.
3961     //
3962     // The check for Silverlight strongname platform assemblies is legacy backdoor. It was introduced by accidental abstraction leak
3963     // from the old Silverlight binder, people took advantage of it and we cannot easily get rid of it now. See DevDiv #710462.
3964     //
3965     BOOL bProfileAssembly = IsSourceGAC() && (IsSystem() || m_bIsOnTpaList);
3966
3967     m_fProfileAssembly = bProfileAssembly ? 1 : -1;
3968     return bProfileAssembly;
3969 }
3970
3971 // ------------------------------------------------------------
3972 // Descriptive strings
3973 // ------------------------------------------------------------
3974
3975 // Effective path is the path of nearest parent (creator) assembly which has a nonempty path.
3976
3977 const SString &PEAssembly::GetEffectivePath()
3978 {
3979     CONTRACTL
3980     {
3981         INSTANCE_CHECK;
3982         NOTHROW;
3983         GC_NOTRIGGER;
3984         MODE_ANY;
3985     }
3986     CONTRACTL_END;
3987
3988     PEAssembly *pAssembly = this;
3989
3990     while (pAssembly->m_identity == NULL
3991            || pAssembly->m_identity->GetPath().IsEmpty())
3992     {
3993         if (pAssembly->m_creator)
3994             pAssembly = pAssembly->m_creator->GetAssembly();
3995         else // Unmanaged exe which loads byte[]/IStream assemblies
3996             return SString::Empty();
3997     }
3998
3999     return pAssembly->m_identity->GetPath();
4000 }
4001
4002
4003 // Codebase is the fusion codebase or path for the assembly.  It is in URL format.
4004 // Note this may be obtained from the parent PEFile if we don't have a path or fusion
4005 // assembly.
4006 //
4007 // fCopiedName means to get the "shadow copied" path rather than the original path, if applicable
4008 void PEAssembly::GetCodeBase(SString &result, BOOL fCopiedName/*=FALSE*/)
4009 {
4010     CONTRACTL
4011     {
4012         INSTANCE_CHECK;
4013         THROWS;
4014         GC_TRIGGERS;
4015         MODE_ANY;
4016         INJECT_FAULT(COMPlusThrowOM(););
4017     }
4018     CONTRACTL_END;
4019 #ifdef FEATURE_FUSION
4020     // For a copied name, we always use the actual file path rather than the fusion info
4021     if (!fCopiedName && m_pFusionAssembly)
4022     {
4023         if ( ((m_dwLocationFlags & ASMLOC_LOCATION_MASK) == ASMLOC_RUN_FROM_SOURCE) ||
4024              ((m_dwLocationFlags & ASMLOC_LOCATION_MASK) == ASMLOC_DOWNLOAD_CACHE) )
4025         {
4026             // Assemblies in the download cache or run from source should have
4027             // a proper codebase set in them.
4028             FusionBind::GetAssemblyNameStringProperty(GetFusionAssemblyName(),
4029                                                       ASM_NAME_CODEBASE_URL,
4030                                                       result);
4031             return;
4032         }
4033     }
4034     else if (m_pIHostAssembly)
4035     {
4036         FusionBind::GetAssemblyNameStringProperty(GetFusionAssemblyName(),
4037                                                   ASM_NAME_CODEBASE_URL,
4038                                                   result);
4039         return;
4040     }
4041 #endif    
4042
4043     // All other cases use the file path.
4044     result.Set(GetEffectivePath());
4045     if (!result.IsEmpty())
4046         PathToUrl(result);
4047 }
4048
4049 /* static */
4050 void PEAssembly::PathToUrl(SString &string)
4051 {
4052     CONTRACTL
4053     {
4054         PRECONDITION(PEImage::CheckCanonicalFullPath(string));
4055         THROWS;
4056         GC_NOTRIGGER;
4057         MODE_ANY;
4058         INJECT_FAULT(COMPlusThrowOM(););
4059     }
4060     CONTRACTL_END;
4061
4062     SString::Iterator i = string.Begin();
4063
4064 #if !defined(PLATFORM_UNIX)
4065     if (i[0] == W('\\'))
4066     {
4067         // Network path
4068         string.Insert(i, SL("file://"));
4069         string.Skip(i, SL("file://"));
4070     }
4071     else
4072     {
4073         // Disk path
4074         string.Insert(i, SL("file:///"));
4075         string.Skip(i, SL("file:///"));
4076     }
4077 #else
4078     // Unix doesn't have a distinction between a network or a local path
4079     _ASSERTE( i[0] == W('\\') || i[0] == W('/'));
4080     SString sss(SString::Literal, W("file://"));
4081     string.Insert(i, sss);
4082     string.Skip(i, sss);
4083 #endif
4084
4085     while (string.Find(i, W('\\')))
4086     {
4087         string.Replace(i, W('/'));
4088     }
4089 }
4090
4091 void PEAssembly::UrlToPath(SString &string)
4092 {
4093     CONTRACT_VOID
4094     {
4095         THROWS;
4096         GC_NOTRIGGER;
4097     }
4098     CONTRACT_END;
4099
4100     SString::Iterator i = string.Begin();
4101
4102     SString sss2(SString::Literal, W("file://"));
4103 #if !defined(PLATFORM_UNIX)
4104     SString sss3(SString::Literal, W("file:///"));
4105     if (string.MatchCaseInsensitive(i, sss3))
4106         string.Delete(i, 8);
4107     else
4108 #endif
4109     if (string.MatchCaseInsensitive(i, sss2))
4110         string.Delete(i, 7);
4111
4112     while (string.Find(i, W('/')))
4113     {
4114         string.Replace(i, W('\\'));
4115     }
4116
4117     RETURN;
4118 }
4119
4120 BOOL PEAssembly::FindLastPathSeparator(const SString &path, SString::Iterator &i)
4121 {
4122 #ifdef PLATFORM_UNIX
4123     SString::Iterator slash = i;
4124     SString::Iterator backSlash = i;
4125     BOOL foundSlash = path.FindBack(slash, '/');
4126     BOOL foundBackSlash = path.FindBack(backSlash, '\\');
4127     if (!foundSlash && !foundBackSlash)
4128         return FALSE;
4129     else if (foundSlash && !foundBackSlash)
4130         i = slash;
4131     else if (!foundSlash && foundBackSlash)
4132         i = backSlash;
4133     else
4134         i = (backSlash > slash) ? backSlash : slash;
4135     return TRUE;
4136 #else
4137     return path.FindBack(i, '\\');
4138 #endif //PLATFORM_UNIX
4139 }
4140
4141
4142 // ------------------------------------------------------------
4143 // Logging
4144 // ------------------------------------------------------------
4145 #ifdef FEATURE_PREJIT
4146 void PEAssembly::ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args)
4147 {
4148     CONTRACT_VOID
4149     {
4150         THROWS;
4151         GC_TRIGGERS;
4152     }
4153     CONTRACT_END;
4154
4155     PEFile::ExternalVLog(facility, level, fmt, args);
4156
4157 #ifdef FEATURE_FUSION
4158     if (FusionLoggingEnabled())
4159     {
4160         DWORD dwLogCategory = (facility == LF_ZAP ? FUSION_BIND_LOG_CATEGORY_NGEN : FUSION_BIND_LOG_CATEGORY_DEFAULT);
4161
4162         StackSString message;
4163         message.VPrintf(fmt, args);
4164         m_pFusionLog->LogMessage(0, dwLogCategory, message);
4165
4166         if (level == LL_ERROR) {
4167             m_pFusionLog->SetResultCode(dwLogCategory, E_FAIL);
4168             FlushExternalLog();
4169         }
4170     }
4171 #endif //FEATURE_FUSION
4172
4173     RETURN;
4174 }
4175
4176 void PEAssembly::FlushExternalLog()
4177 {
4178     CONTRACT_VOID
4179     {
4180         THROWS;
4181         GC_TRIGGERS;
4182     }
4183     CONTRACT_END;
4184
4185 #ifdef FEATURE_FUSION
4186     if (FusionLoggingEnabled()) {
4187         m_pFusionLog->Flush(g_dwLogLevel,  FUSION_BIND_LOG_CATEGORY_NGEN);
4188         m_pFusionLog->Flush(g_dwLogLevel,  FUSION_BIND_LOG_CATEGORY_DEFAULT);
4189     }
4190 #endif //FEATURE_FUSION
4191
4192     RETURN;
4193 }
4194 #endif //FEATURE_PREJIT
4195 // ------------------------------------------------------------
4196 // Metadata access
4197 // ------------------------------------------------------------
4198
4199 HRESULT PEFile::GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision)
4200 {
4201     CONTRACTL
4202     {
4203         INSTANCE_CHECK;
4204         PRECONDITION(CheckPointer(pMajor, NULL_OK));
4205         PRECONDITION(CheckPointer(pMinor, NULL_OK));
4206         PRECONDITION(CheckPointer(pBuild, NULL_OK));
4207         PRECONDITION(CheckPointer(pRevision, NULL_OK));
4208         NOTHROW;
4209         WRAPPER(GC_TRIGGERS);
4210         MODE_ANY;
4211     }
4212     CONTRACTL_END;
4213
4214     AssemblyMetaDataInternal md;
4215     HRESULT hr = S_OK;;
4216     if (m_bHasPersistentMDImport)
4217     {
4218         _ASSERTE(GetPersistentMDImport()->IsValidToken(TokenFromRid(1, mdtAssembly)));
4219         IfFailRet(GetPersistentMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL));
4220     }
4221     else
4222     {
4223         ReleaseHolder<IMDInternalImport> pImport(GetMDImportWithRef());
4224         _ASSERTE(pImport->IsValidToken(TokenFromRid(1, mdtAssembly)));
4225         IfFailRet(pImport->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL));
4226     }
4227     
4228     if (pMajor != NULL)
4229         *pMajor = md.usMajorVersion;
4230     if (pMinor != NULL)
4231         *pMinor = md.usMinorVersion;
4232     if (pBuild != NULL)
4233         *pBuild = md.usBuildNumber;
4234     if (pRevision != NULL)
4235         *pRevision = md.usRevisionNumber;
4236
4237     return hr;
4238 }
4239
4240 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
4241 // ================================================================================
4242 // PEModule class - a PEFile which represents a satellite module
4243 // ================================================================================
4244
4245 PEModule::PEModule(PEImage *image, PEAssembly *assembly, mdFile token, IMetaDataEmit *pEmit)
4246   : PEFile(image),
4247     m_assembly(NULL),
4248     m_token(token),
4249     m_bIsResource(-1)
4250 {
4251     CONTRACTL
4252     {
4253         PRECONDITION(CheckPointer(image, NULL_OK));
4254         PRECONDITION(CheckPointer(assembly));
4255         PRECONDITION(!IsNilToken(token));
4256         PRECONDITION(CheckPointer(pEmit, NULL_OK));
4257         PRECONDITION(image != NULL || pEmit != NULL);
4258         CONSTRUCTOR_CHECK;
4259         STANDARD_VM_CHECK;
4260     }
4261     CONTRACTL_END;
4262     
4263     DWORD flags;
4264     
4265     // get only the data which is required, here - flags
4266     // this helps avoid unnecessary memory touches
4267     IfFailThrow(assembly->GetPersistentMDImport()->GetFileProps(token, NULL, NULL, NULL, &flags));
4268     
4269     if (image != NULL)
4270     {
4271         if (IsFfContainsMetaData(flags) && !image->CheckILFormat())
4272             ThrowHR(COR_E_BADIMAGEFORMAT);
4273         
4274         if (assembly->IsIStream())
4275         {
4276             m_flags |= PEFILE_ISTREAM;
4277 #ifdef FEATURE_PREJIT            
4278             m_fCanUseNativeImage = FALSE;
4279 #endif
4280         }
4281     }
4282     
4283     assembly->AddRef();
4284     
4285     m_assembly = assembly;
4286     
4287     m_flags |= PEFILE_MODULE;
4288     if (assembly->IsSystem())
4289     {
4290         m_flags |= PEFILE_SYSTEM;
4291     }
4292     else
4293     {
4294         if (assembly->IsIntrospectionOnly())
4295         {
4296             m_flags |= PEFILE_INTROSPECTIONONLY;
4297 #ifdef FEATURE_PREJIT            
4298             SetCannotUseNativeImage();        
4299 #endif
4300         }
4301     }
4302     
4303     
4304     // Verify module format.  Note that some things have already happened:
4305     // - Fusion has verified the name matches the metadata
4306     // - PEimage has performed PE file format validation
4307
4308     if (assembly->NeedsModuleHashChecks())
4309     {
4310         ULONG size;
4311         const void *hash;
4312         IfFailThrow(assembly->GetPersistentMDImport()->GetFileProps(token, NULL, &hash, &size, NULL));
4313         
4314         if (!CheckHash(assembly->GetHashAlgId(), hash, size))
4315             ThrowHR(COR_E_MODULE_HASH_CHECK_FAILED);
4316     }
4317     
4318 #if defined(FEATURE_PREJIT) && !defined(CROSSGEN_COMPILE)
4319     // Find the native image
4320     if (IsFfContainsMetaData(flags)
4321         && m_fCanUseNativeImage
4322         && assembly->HasNativeImage()
4323         && assembly->GetFusionAssembly() != NULL)
4324     {
4325         IAssemblyLocation *pIAssemblyLocation = assembly->GetNativeAssemblyLocation();
4326
4327         WCHAR wzPath[MAX_LONGPATH];
4328         WCHAR *pwzTemp = NULL;
4329         DWORD dwCCPath = MAX_LONGPATH;
4330         SString path;
4331         SString moduleName(SString::Utf8, GetSimpleName());
4332
4333         // Compute the module path from the manifest module path
4334         IfFailThrow(pIAssemblyLocation->GetPath(wzPath, &dwCCPath));
4335         pwzTemp = PathFindFileName(wzPath);
4336         *pwzTemp = (WCHAR) 0x00;
4337
4338         // <TODO>@todo: GetAppDomain????</TODO>
4339         path.Set(wzPath);
4340         path.Append((LPCWSTR) moduleName);
4341
4342         SetNativeImage(path);
4343     }
4344 #endif  // FEATURE_PREJIT && !CROSSGEN_COMPILE
4345
4346 #if _DEBUG
4347     GetCodeBaseOrName(m_debugName);
4348     m_pDebugName = m_debugName;
4349 #endif
4350     
4351     if (IsFfContainsMetaData(flags))
4352     {
4353         if (image != NULL)
4354         {
4355             OpenMDImport_Unsafe(); //constructor. cannot race with anything
4356         }
4357         else
4358         {
4359             _ASSERTE(!m_bHasPersistentMDImport);
4360             IfFailThrow(GetMetaDataInternalInterfaceFromPublic(pEmit, IID_IMDInternalImport,
4361                                                                (void **)&m_pMDImport));
4362             m_pEmitter = pEmit;
4363             pEmit->AddRef();
4364             m_bHasPersistentMDImport=TRUE;
4365             m_MDImportIsRW_Debugger_Use_Only = TRUE;
4366         }
4367         
4368         // Fusion probably checks this, but we need to check this ourselves if
4369         // this file didn't come from Fusion
4370         if (!m_pMDImport->IsValidToken(m_pMDImport->GetModuleFromScope()))
4371             COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
4372     }
4373     else
4374     {
4375         // Go ahead and "load" image since it is essentially a noop, but will enable
4376         // more operations on the module earlier in the loading process.
4377         LoadLibrary();
4378     }
4379 #ifdef FEATURE_PREJIT
4380     if (IsResource() || IsDynamic())
4381         m_fCanUseNativeImage = FALSE;
4382 #endif    
4383 }
4384
4385 PEModule::~PEModule()
4386 {
4387     CONTRACTL
4388     {
4389         DESTRUCTOR_CHECK;
4390         NOTHROW;
4391         MODE_ANY;
4392     }
4393     CONTRACTL_END;
4394
4395     m_assembly->Release();
4396 }
4397
4398 /* static */
4399 PEModule *PEModule::Open(PEAssembly *assembly, mdFile token,
4400                          const SString &fileName)
4401 {
4402     STANDARD_VM_CONTRACT;
4403
4404     PEModule *result = NULL;
4405
4406     EX_TRY
4407     {
4408         result = DoOpen(assembly, token, fileName);
4409     }
4410     EX_HOOK
4411     {
4412         Exception *ex = GET_EXCEPTION();
4413
4414         // Rethrow non-transient exceptions as file load exceptions with proper
4415         // context
4416
4417         if (!ex->IsTransient())
4418             EEFileLoadException::Throw(fileName, ex->GetHR(), ex);
4419     }
4420     EX_END_HOOK;
4421
4422     return result;
4423 }
4424 // Thread stress
4425 class DoOpenPathStress : APIThreadStress
4426 {
4427 public:
4428     PEAssembly *assembly;
4429     mdFile token;
4430     const SString &fileName;
4431     DoOpenPathStress(PEAssembly *assembly, mdFile token,
4432            const SString &fileName)
4433         : assembly(assembly), token(token), fileName(fileName)
4434     {
4435         WRAPPER_NO_CONTRACT;
4436         fileName.Normalize();
4437     }
4438     void Invoke()
4439     {
4440         WRAPPER_NO_CONTRACT;
4441         PEModuleHolder result(PEModule::Open(assembly, token, fileName));
4442     }
4443 };
4444
4445 /* static */
4446 PEModule *PEModule::DoOpen(PEAssembly *assembly, mdFile token,
4447                            const SString &fileName)
4448 {
4449     CONTRACT(PEModule *)
4450     {
4451         PRECONDITION(CheckPointer(assembly));
4452         PRECONDITION(CheckValue(fileName));
4453         PRECONDITION(!IsNilToken(token));
4454         PRECONDITION(!fileName.IsEmpty());
4455         POSTCONDITION(CheckPointer(RETVAL));
4456         STANDARD_VM_CHECK;
4457     }
4458     CONTRACT_END;
4459     
4460     DoOpenPathStress ts(assembly, token, fileName);
4461     
4462     // If this is a resource module, we must explicitly request a flat mapping
4463     DWORD flags;
4464     IfFailThrow(assembly->GetPersistentMDImport()->GetFileProps(token, NULL, NULL, NULL, &flags));
4465     
4466     PEImageHolder image;
4467 #ifdef FEATURE_FUSION
4468     if (assembly->IsIStream())
4469     {
4470         SafeComHolder<IHostAssemblyModuleImport> pModuleImport;
4471         IfFailThrow(assembly->GetIHostAssembly()->GetModuleByName(fileName, &pModuleImport));
4472         
4473         SafeComHolder<IStream> pIStream;
4474         IfFailThrow(pModuleImport->GetModuleStream(&pIStream));
4475         
4476         DWORD dwModuleId;
4477         IfFailThrow(pModuleImport->GetModuleId(&dwModuleId));
4478         image = PEImage::OpenImage(pIStream, assembly->m_identity->m_StreamAsmId,
4479                                    dwModuleId, (flags & ffContainsNoMetaData));
4480     }
4481     else
4482 #endif
4483     {
4484         image = PEImage::OpenImage(fileName);
4485     }
4486     
4487     if (flags & ffContainsNoMetaData)
4488         image->LoadNoMetaData(assembly->IsIntrospectionOnly());
4489     
4490     PEModuleHolder module(new PEModule(image, assembly, token, NULL));
4491
4492     RETURN module.Extract();
4493 }
4494
4495 /* static */
4496 PEModule *PEModule::OpenMemory(PEAssembly *assembly, mdFile token,
4497                                const void *flat, COUNT_T size)
4498 {
4499     STANDARD_VM_CONTRACT;
4500
4501     PEModule *result = NULL;
4502
4503     EX_TRY
4504     {
4505         result = DoOpenMemory(assembly, token, flat, size);
4506     }
4507     EX_HOOK
4508     {
4509         Exception *ex = GET_EXCEPTION();
4510
4511         // Rethrow non-transient exceptions as file load exceptions with proper
4512         // context
4513         if (!ex->IsTransient())
4514             EEFileLoadException::Throw(assembly, flat, size, ex->GetHR(), ex);
4515     }
4516     EX_END_HOOK;
4517     return result;
4518 }
4519
4520 // Thread stress
4521 class DoOpenTokenStress : APIThreadStress
4522 {
4523 public:
4524     PEAssembly *assembly;
4525     mdFile token;
4526     const void *flat;
4527     COUNT_T size;
4528     DoOpenTokenStress(PEAssembly *assembly, mdFile token,
4529            const void *flat, COUNT_T size)
4530         : assembly(assembly), token(token), flat(flat), size(size) {LIMITED_METHOD_CONTRACT;}
4531     void Invoke()
4532     {
4533         WRAPPER_NO_CONTRACT;
4534         PEModuleHolder result(PEModule::OpenMemory(assembly, token, flat, size));
4535     }
4536 };
4537
4538 // REVIEW: do we need to know the creator module which emitted the module (separately
4539 // from the assembly parent) for security reasons?
4540 /* static */
4541 PEModule *PEModule::DoOpenMemory(PEAssembly *assembly, mdFile token,
4542                                  const void *flat, COUNT_T size)
4543 {
4544     CONTRACT(PEModule *)
4545     {
4546         PRECONDITION(CheckPointer(assembly));
4547         PRECONDITION(!IsNilToken(token));
4548         PRECONDITION(CheckPointer(flat));
4549         POSTCONDITION(CheckPointer(RETVAL));
4550         THROWS;
4551         GC_TRIGGERS;
4552         MODE_ANY;
4553         INJECT_FAULT(COMPlusThrowOM(););
4554     }
4555     CONTRACT_END;
4556
4557     DoOpenTokenStress ts(assembly, token, flat, size);
4558
4559     PEImageHolder image(PEImage::LoadFlat(flat, size));
4560
4561     RETURN new PEModule(image, assembly, token, NULL);
4562 }
4563
4564 /* static */
4565 PEModule *PEModule::Create(PEAssembly *assembly, mdFile token, IMetaDataEmit *pEmit)
4566 {
4567     CONTRACT(PEModule *)
4568     {
4569         PRECONDITION(CheckPointer(assembly));
4570         PRECONDITION(!IsNilToken(token));
4571         STANDARD_VM_CHECK; 
4572         POSTCONDITION(CheckPointer(RETVAL));
4573     }
4574     CONTRACT_END;
4575
4576     RETURN new PEModule(NULL, assembly, token, pEmit);
4577 }
4578
4579 // ------------------------------------------------------------
4580 // Logging
4581 // ------------------------------------------------------------
4582 #ifdef FEATURE_PREJIT
4583 void PEModule::ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args)
4584 {
4585     CONTRACT_VOID
4586     {
4587         THROWS;
4588         GC_TRIGGERS;
4589     }
4590     CONTRACT_END;
4591
4592     m_assembly->ExternalVLog(facility, level, fmt, args);
4593
4594     RETURN;
4595 }
4596
4597 void PEModule::FlushExternalLog()
4598 {
4599     CONTRACT_VOID
4600     {
4601         THROWS;
4602         GC_TRIGGERS;
4603     }
4604     CONTRACT_END;
4605
4606     m_assembly->FlushExternalLog();
4607
4608     RETURN;
4609 }
4610
4611 // ------------------------------------------------------------
4612 // Loader support routines
4613 // ------------------------------------------------------------
4614 void PEModule::SetNativeImage(const SString &fullPath)
4615 {
4616     CONTRACTL
4617     {
4618         INSTANCE_CHECK;
4619         PRECONDITION(CheckValue(fullPath));
4620         PRECONDITION(!fullPath.IsEmpty());
4621         STANDARD_VM_CHECK;
4622     }
4623     CONTRACTL_END;
4624
4625     PEImageHolder image(PEImage::OpenImage(fullPath));
4626     image->Load();
4627
4628     PEFile::SetNativeImage(image);
4629 }
4630 #endif  // FEATURE_PREJIT
4631
4632 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
4633
4634
4635 void PEFile::EnsureImageOpened()
4636 {
4637     WRAPPER_NO_CONTRACT;
4638     if (IsDynamic())
4639         return;
4640 #ifdef FEATURE_PREJIT    
4641     if(HasNativeImage())
4642         m_nativeImage->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)->Release();
4643     else
4644 #endif        
4645         GetILimage()->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)->Release();
4646 }
4647
4648 #endif // #ifndef DACCESS_COMPILE
4649
4650 #ifdef DACCESS_COMPILE
4651
4652 void
4653 PEFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
4654 {
4655     WRAPPER_NO_CONTRACT;
4656     SUPPORTS_DAC;
4657
4658     // sizeof(PEFile) == 0xb8
4659     DAC_ENUM_VTHIS();
4660     EMEM_OUT(("MEM: %p PEFile\n", dac_cast<TADDR>(this)));
4661
4662 #ifdef _DEBUG
4663     // Not a big deal if it's NULL or fails.
4664     m_debugName.EnumMemoryRegions(flags);
4665 #endif
4666
4667     if (m_identity.IsValid())
4668     {
4669         m_identity->EnumMemoryRegions(flags);
4670     }
4671     if (GetILimage().IsValid())
4672     {
4673         GetILimage()->EnumMemoryRegions(flags);
4674     }
4675 #ifdef FEATURE_PREJIT
4676     if (m_nativeImage.IsValid())
4677     {
4678         m_nativeImage->EnumMemoryRegions(flags);
4679         DacEnumHostDPtrMem(m_nativeImage->GetLoadedLayout()->GetNativeVersionInfo());
4680     }
4681 #endif
4682 }
4683
4684 void
4685 PEAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
4686 {
4687     WRAPPER_NO_CONTRACT;
4688
4689     PEFile::EnumMemoryRegions(flags);
4690
4691     if (m_creator.IsValid())
4692     {
4693         m_creator->EnumMemoryRegions(flags);
4694     }
4695 }
4696
4697 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
4698 void
4699 PEModule::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
4700 {
4701     WRAPPER_NO_CONTRACT;
4702
4703     PEFile::EnumMemoryRegions(flags);
4704
4705     if (m_assembly.IsValid())
4706     {
4707         m_assembly->EnumMemoryRegions(flags);
4708     }
4709 }
4710 #endif // FEATURE_MULTIMODULE_ASSEMBLIES
4711 #endif // #ifdef DACCESS_COMPILE
4712
4713
4714 //-------------------------------------------------------------------------------
4715 // Make best-case effort to obtain an image name for use in an error message.
4716 //
4717 // This routine must expect to be called before the this object is fully loaded.
4718 // It can return an empty if the name isn't available or the object isn't initialized
4719 // enough to get a name, but it mustn't crash.
4720 //-------------------------------------------------------------------------------
4721 LPCWSTR PEFile::GetPathForErrorMessages()
4722 {
4723     CONTRACTL
4724     {
4725         THROWS;
4726         GC_TRIGGERS;
4727         INJECT_FAULT(COMPlusThrowOM(););
4728         SUPPORTS_DAC_HOST_ONLY;
4729     }
4730     CONTRACTL_END
4731
4732     if (!IsDynamic())
4733     {
4734         return m_identity->GetPathForErrorMessages();
4735     }
4736     else
4737     {
4738         return W("");
4739     }
4740 }
4741
4742
4743 #ifdef DACCESS_COMPILE
4744 TADDR PEFile::GetMDInternalRWAddress()
4745 {
4746     if (!m_MDImportIsRW_Debugger_Use_Only)
4747         return 0;
4748     else
4749     {
4750         // This line of code is a bit scary, but it is correct for now at least...
4751         // 1) We are using 'm_pMDImport_Use_Accessor' directly, and not the accessor. The field is
4752         //    named this way to prevent debugger code that wants a host implementation of IMDInternalImport
4753         //    from accidentally trying to use this pointer. This pointer is a target pointer, not
4754         //    a host pointer. However in this function we do want the target pointer, so the usage is
4755         //    accurate.
4756         // 2) ASSUMPTION: We are assuming that the only valid implementation of RW metadata is 
4757         //    MDInternalRW. If that ever changes we would need some way to disambiguate, and
4758         //    probably this entire code path would need to be redesigned. 
4759         // 3) ASSUMPTION: We are assuming that no pointer adjustment is required to convert between
4760         //    IMDInternalImport*, IMDInternalImportENC* and MDInternalRW*. Ideally I was hoping to do this with a
4761         //    static_cast<> but the compiler complains that the ENC<->RW is an unrelated conversion.
4762         return (TADDR) m_pMDImport_UseAccessor;
4763     }
4764 }
4765 #endif
4766
4767 // Returns the ICLRPrivBinder* instance associated with the PEFile
4768 PTR_ICLRPrivBinder PEFile::GetBindingContext()
4769 {
4770     LIMITED_METHOD_CONTRACT;
4771     
4772     PTR_ICLRPrivBinder pBindingContext = NULL;
4773     
4774     // Mscorlib is always bound in context of the TPA Binder. However, since it gets loaded and published
4775     // during EEStartup *before* TPAbinder is initialized, we dont have a binding context to publish against.
4776     // Thus, we will always return NULL for its binding context.
4777     if (!IsSystem())
4778     {
4779         pBindingContext = dac_cast<PTR_ICLRPrivBinder>(GetHostAssembly());
4780     }
4781     
4782     return pBindingContext;
4783 }