1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*============================================================
6**
7** Header: Assembly.hpp
8**
9
10**
11** Purpose: Implements assembly (loader domain) architecture
12**
13**
14===========================================================*/
15#ifndef _ASSEMBLY_H
16#define _ASSEMBLY_H
17
18#include "ceeload.h"
19#include "exceptmacros.h"
20#include "clsload.hpp"
21#include "eehash.h"
22#include "listlock.h"
23#include "iceefilegen.h"
24#include "cordbpriv.h"
25#include "assemblyspec.hpp"
26
27// A helper macro for the assembly's module hash (m_pAllowedFiles).
28#define UTF8_TO_LOWER_CASE(str, qb) \
29{ \
30 WRAPPER_NO_CONTRACT; \
31 INT32 allocBytes = InternalCasingHelper::InvariantToLower(NULL, 0, str); \
32 qb.AllocThrows(allocBytes); \
33 InternalCasingHelper::InvariantToLower((LPUTF8) qb.Ptr(), allocBytes, str); \
34}
35
36
37class BaseDomain;
38class AppDomain;
39class DomainAssembly;
40class DomainModule;
41class SystemDomain;
42class ClassLoader;
43class ComDynamicWrite;
44class AssemblySink;
45class AssemblyNative;
46class AssemblySpec;
47class ISharedSecurityDescriptor;
48class SecurityTransparencyBehavior;
49class Pending;
50class AllocMemTracker;
51class FriendAssemblyDescriptor;
52
53// Bits in m_dwDynamicAssemblyAccess (see System.Reflection.Emit.AssemblyBuilderAccess.cs)
54#define ASSEMBLY_ACCESS_RUN 0x01
55#define ASSEMBLY_ACCESS_SAVE 0x02
56#define ASSEMBLY_ACCESS_COLLECT 0x8
57
58struct CreateDynamicAssemblyArgsGC
59{
60 ASSEMBLYNAMEREF assemblyName;
61 LOADERALLOCATORREF loaderAllocator;
62};
63
64struct CreateDynamicAssemblyArgs : CreateDynamicAssemblyArgsGC
65{
66 INT32 access;
67 StackCrawlMark* stackMark;
68};
69
70// An assembly is the unit of deployment for managed code. Typically Assemblies are one to one with files
71// (Modules), however this is not necessary, as an assembly can contain serveral files (typically you only
72// do this so that you can resource-only modules that are national language specific)
73//
74// Conceptually Assemblies are loaded into code:AppDomain
75//
76// So in general an assemly is a list of code:Module, where a code:Module is 1-1 with a DLL or EXE file.
77//
78// One of the modules the code:Assembly.m_pManifest is special in that it knows about all the other
79// modules in an assembly (often it is the only one).
80//
81class Assembly
82{
83 friend class BaseDomain;
84 friend class SystemDomain;
85 friend class ClassLoader;
86 friend class AssemblyNative;
87 friend class AssemblySpec;
88 friend class NDirect;
89 friend class AssemblyNameNative;
90 friend class ClrDataAccess;
91
92public:
93 Assembly(BaseDomain *pDomain, PEAssembly *pFile, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible);
94 void Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocator);
95
96 void StartUnload();
97 void Terminate( BOOL signalProfiler = TRUE );
98
99 static Assembly *Create(BaseDomain *pDomain, PEAssembly *pFile, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible, AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocator);
100
101 BOOL IsSystem() { WRAPPER_NO_CONTRACT; return m_pManifestFile->IsSystem(); }
102
103 static Assembly *CreateDynamic(AppDomain *pDomain, CreateDynamicAssemblyArgs *args);
104
105 MethodDesc *GetEntryPoint();
106
107 //****************************************************************************************
108 //
109 // Additional init tasks for Modules. This should probably be part of Module::Initialize()
110 // but there's at least one call to ReflectionModule::Create that is *not* followed by a
111 // PrepareModule call.
112 void PrepareModuleForAssembly(Module* module, AllocMemTracker *pamTracker);
113
114 // This is the final step of publishing a Module into an Assembly. This step cannot fail.
115 void PublishModuleIntoAssembly(Module *module);
116
117#ifndef DACCESS_COMPILE
118 void SetIsTenured()
119 {
120 WRAPPER_NO_CONTRACT;
121 m_pManifest->SetIsTenured();
122 }
123
124 // CAUTION: This should only be used as backout code if an assembly is unsuccessfully
125 // added to the shared domain assembly map.
126 void UnsetIsTenured()
127 {
128 WRAPPER_NO_CONTRACT;
129 m_pManifest->UnsetIsTenured();
130 }
131#endif // DACCESS_COMPILE
132
133 //****************************************************************************************
134 //
135 // Returns the class loader associated with the assembly.
136 ClassLoader* GetLoader()
137 {
138 LIMITED_METHOD_CONTRACT;
139 SUPPORTS_DAC;
140 return m_pClassLoader;
141 }
142
143 // ------------------------------------------------------------
144 // Modules
145 // ------------------------------------------------------------
146
147 class ModuleIterator
148 {
149 Module* m_pManifest;
150 DWORD m_i;
151
152 public:
153 // The preferred constructor. If you use this, you don't have to
154 // call Start() yourself
155 ModuleIterator(Assembly *pAssembly)
156 {
157 WRAPPER_NO_CONTRACT;
158 Start(pAssembly);
159 }
160
161 // When you don't have the Assembly at contruction time, use this
162 // constructor, and explicitly call Start() to begin the iteration.
163 ModuleIterator()
164 {
165 LIMITED_METHOD_CONTRACT;
166 SUPPORTS_DAC;
167
168 m_pManifest = NULL;
169 m_i = (DWORD) -1;
170 }
171
172 void Start(Assembly * pAssembly)
173 {
174 LIMITED_METHOD_CONTRACT;
175 SUPPORTS_DAC;
176
177 m_pManifest = pAssembly->GetManifestModule();
178 m_i = (DWORD) -1;
179 }
180
181 BOOL Next()
182 {
183 LIMITED_METHOD_CONTRACT;
184 SUPPORTS_DAC;
185 while (++m_i <= m_pManifest->GetFileMax())
186 {
187 if (GetModule() != NULL)
188 return TRUE;
189 }
190 return FALSE;
191 }
192
193 Module *GetModule()
194 {
195 LIMITED_METHOD_CONTRACT;
196 SUPPORTS_DAC;
197 return m_pManifest->LookupFile(TokenFromRid(m_i, mdtFile));
198 }
199 };
200
201 ModuleIterator IterateModules()
202 {
203 WRAPPER_NO_CONTRACT;
204 SUPPORTS_DAC;
205 return ModuleIterator(this);
206 }
207
208
209 //****************************************************************************************
210 //
211 // Get the domain the assembly lives in.
212 PTR_BaseDomain Parent()
213 {
214 LIMITED_METHOD_CONTRACT;
215 return m_pDomain;
216 }
217
218 // Sets the assemblies domain.
219 void SetParent(BaseDomain* pParent);
220
221 //-----------------------------------------------------------------------------------------
222 // EnsureActive ensures that the assembly is properly prepped in the current app domain
223 // for active uses like code execution, static field access, and instance allocation
224 //-----------------------------------------------------------------------------------------
225#ifndef DACCESS_COMPILE
226 VOID EnsureActive();
227#endif
228
229 //-----------------------------------------------------------------------------------------
230 // CheckActivated is a check predicate which should be used in active use paths like code
231 // execution, static field access, and instance allocation
232 //-----------------------------------------------------------------------------------------
233 CHECK CheckActivated();
234
235 // Returns the parent domain if it is not the system area. Returns NULL if it is the
236 // system domain
237 PTR_BaseDomain GetDomain();
238 PTR_LoaderAllocator GetLoaderAllocator() { LIMITED_METHOD_DAC_CONTRACT; return m_pLoaderAllocator; }
239
240 BOOL GetModuleZapFile(LPCWSTR name, SString &path);
241
242#ifdef LOGGING
243 LPCWSTR GetDebugName()
244 {
245 WRAPPER_NO_CONTRACT;
246 return GetManifestFile()->GetDebugName();
247 }
248#endif
249
250 LPCUTF8 GetSimpleName()
251 {
252 WRAPPER_NO_CONTRACT;
253 return GetManifestFile()->GetSimpleName();
254 }
255
256 BOOL IsStrongNamed()
257 {
258 WRAPPER_NO_CONTRACT;
259 return GetManifestFile()->IsStrongNamed();
260 }
261
262 const void *GetPublicKey(DWORD *pcbPK)
263 {
264 WRAPPER_NO_CONTRACT;
265 return GetManifestFile()->GetPublicKey(pcbPK);
266 }
267
268 ULONG GetHashAlgId()
269 {
270 WRAPPER_NO_CONTRACT;
271 return GetManifestFile()->GetHashAlgId();
272 }
273
274 HRESULT GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision)
275 {
276 WRAPPER_NO_CONTRACT;
277 return GetManifestFile()->GetVersion(pMajor, pMinor, pBuild, pRevision);
278 }
279
280 LPCUTF8 GetLocale()
281 {
282 WRAPPER_NO_CONTRACT;
283 return GetManifestFile()->GetLocale();
284 }
285
286 DWORD GetFlags()
287 {
288 WRAPPER_NO_CONTRACT;
289 return GetManifestFile()->GetFlags();
290 }
291
292 PTR_LoaderHeap GetLowFrequencyHeap();
293 PTR_LoaderHeap GetHighFrequencyHeap();
294 PTR_LoaderHeap GetStubHeap();
295
296 PTR_Module GetManifestModule()
297 {
298 LIMITED_METHOD_CONTRACT;
299 SUPPORTS_DAC;
300 return m_pManifest;
301 }
302
303 PTR_PEAssembly GetManifestFile()
304 {
305 LIMITED_METHOD_CONTRACT;
306 SUPPORTS_DAC;
307 return m_pManifestFile;
308 }
309
310 IMDInternalImport* GetManifestImport()
311 {
312 WRAPPER_NO_CONTRACT;
313 SUPPORTS_DAC;
314 return m_pManifestFile->GetPersistentMDImport();
315 }
316
317#ifndef DACCESS_COMPILE
318 IMetaDataAssemblyImport* GetManifestAssemblyImporter()
319 {
320 WRAPPER_NO_CONTRACT;
321 return m_pManifestFile->GetAssemblyImporter();
322 }
323#endif // DACCESS_COMPILE
324
325 mdAssembly GetManifestToken()
326 {
327 LIMITED_METHOD_CONTRACT;
328
329 return TokenFromRid(1, mdtAssembly);
330 }
331
332#ifndef DACCESS_COMPILE
333 void GetDisplayName(SString &result, DWORD flags = 0)
334 {
335 WRAPPER_NO_CONTRACT;
336
337 return m_pManifestFile->GetDisplayName(result, flags);
338 }
339#endif // DACCESS_COMPILE
340
341 void GetCodeBase(SString &result)
342 {
343 WRAPPER_NO_CONTRACT;
344
345 return m_pManifestFile->GetCodeBase(result);
346 }
347
348 OBJECTREF GetExposedObject();
349
350 DebuggerAssemblyControlFlags GetDebuggerInfoBits(void)
351 {
352 LIMITED_METHOD_CONTRACT;
353
354 return m_debuggerFlags;
355 }
356
357 void SetDebuggerInfoBits(DebuggerAssemblyControlFlags flags)
358 {
359 LIMITED_METHOD_CONTRACT;
360
361 m_debuggerFlags = flags;
362 }
363
364 void SetCopiedPDBs()
365 {
366 LIMITED_METHOD_CONTRACT;
367
368 m_debuggerFlags = (DebuggerAssemblyControlFlags) (m_debuggerFlags | DACF_PDBS_COPIED);
369 }
370
371 ULONG HashIdentity()
372 {
373 return GetManifestFile()->HashIdentity();
374 }
375
376 BOOL IsDisabledPrivateReflection();
377
378 //****************************************************************************************
379 //
380 // Uses the given token to load a module or another assembly. Returns the module in
381 // which the implementation resides.
382
383 mdFile GetManifestFileToken(IMDInternalImport *pImport, mdFile kFile);
384 mdFile GetManifestFileToken(LPCSTR name);
385
386 // On failure:
387 // if loadFlag == Loader::Load => throw
388 // if loadFlag != Loader::Load => return NULL
389 Module *FindModuleByExportedType(mdExportedType mdType,
390 Loader::LoadFlag loadFlag,
391 mdTypeDef mdNested,
392 mdTypeDef *pCL);
393
394 static Module * FindModuleByTypeRef(Module * pModule,
395 mdTypeRef typeRef,
396 Loader::LoadFlag loadFlag,
397 BOOL * pfNoResolutionScope);
398
399 Module *FindModuleByName(LPCSTR moduleName);
400
401 //****************************************************************************************
402 //
403 INT32 ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThreads);
404
405 //****************************************************************************************
406
407 Assembly();
408 ~Assembly();
409#ifdef FEATURE_PREJIT
410 void DeleteNativeCodeRanges();
411#endif
412
413 BOOL GetResource(LPCSTR szName, DWORD *cbResource,
414 PBYTE *pbInMemoryResource, Assembly **pAssemblyRef,
415 LPCSTR *szFileName, DWORD *dwLocation,
416 BOOL fSkipRaiseResolveEvent = FALSE);
417
418 //****************************************************************************************
419#ifdef DACCESS_COMPILE
420 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
421#endif
422
423 FORCEINLINE BOOL IsDynamic() { LIMITED_METHOD_CONTRACT; return m_isDynamic; }
424 FORCEINLINE BOOL IsCollectible() { LIMITED_METHOD_DAC_CONTRACT; return m_isCollectible; }
425
426 DWORD GetNextModuleIndex() { LIMITED_METHOD_CONTRACT; return m_nextAvailableModuleIndex++; }
427
428 void AddType(Module* pModule,
429 mdTypeDef cl);
430 void AddExportedType(mdExportedType cl);
431 mdAssemblyRef AddAssemblyRef(Assembly *refedAssembly, IMetaDataAssemblyEmit *pAssemEmitter = NULL, BOOL fUsePublicKeyToken = TRUE);
432
433 //****************************************************************************************
434
435 DomainAssembly *GetDomainAssembly(AppDomain *pDomain);
436 void SetDomainAssembly(DomainAssembly *pAssembly);
437
438 // Verison of GetDomainAssembly that uses the current AppDomain (N/A in DAC builds)
439#ifndef DACCESS_COMPILE
440 DomainAssembly *GetDomainAssembly() { WRAPPER_NO_CONTRACT; return GetDomainAssembly(GetAppDomain()); }
441#endif
442
443 // FindDomainAssembly will return NULL if the assembly is not in the given domain
444 DomainAssembly *FindDomainAssembly(AppDomain *pDomain);
445
446#if defined(FEATURE_COLLECTIBLE_TYPES) && !defined(DACCESS_COMPILE)
447 OBJECTHANDLE GetLoaderAllocatorObjectHandle() { WRAPPER_NO_CONTRACT; return GetLoaderAllocator()->GetLoaderAllocatorObjectHandle(); }
448#endif // FEATURE_COLLECTIBLE_TYPES
449
450 BOOL IsSIMDVectorAssembly() { LIMITED_METHOD_DAC_CONTRACT; return m_fIsSIMDVectorAssembly; }
451
452#ifdef FEATURE_PREJIT
453 BOOL IsInstrumented();
454 BOOL IsInstrumentedHelper();
455#endif // FEATURE_PREJIT
456
457#ifdef FEATURE_COMINTEROP
458 static ITypeLib * const InvalidTypeLib;
459
460 // Get any cached ITypeLib* for the assembly.
461 ITypeLib *GetTypeLib();
462
463 // Try to set the ITypeLib*, if one is not already cached.
464 bool TrySetTypeLib(_In_ ITypeLib *pTlb);
465#endif // FEATURE_COMINTEROP
466
467#ifndef DACCESS_COMPILE
468
469 void DECLSPEC_NORETURN ThrowTypeLoadException(LPCUTF8 pszFullName, UINT resIDWhy);
470
471 void DECLSPEC_NORETURN ThrowTypeLoadException(LPCUTF8 pszNameSpace, LPCUTF8 pTypeName,
472 UINT resIDWhy);
473
474 void DECLSPEC_NORETURN ThrowTypeLoadException(NameHandle *pName, UINT resIDWhy);
475
476 void DECLSPEC_NORETURN ThrowTypeLoadException(IMDInternalImport *pInternalImport,
477 mdToken token,
478 UINT resIDWhy);
479
480 void DECLSPEC_NORETURN ThrowTypeLoadException(IMDInternalImport *pInternalImport,
481 mdToken token,
482 LPCUTF8 pszFieldOrMethodName,
483 UINT resIDWhy);
484
485 void DECLSPEC_NORETURN ThrowTypeLoadException(LPCUTF8 pszNameSpace,
486 LPCUTF8 pszTypeName,
487 LPCUTF8 pszMethodName,
488 UINT resIDWhy);
489
490 void DECLSPEC_NORETURN ThrowBadImageException(LPCUTF8 pszNameSpace,
491 LPCUTF8 pszTypeName,
492 UINT resIDWhy);
493
494#endif // #ifndef DACCESS_COMPILE
495
496 //****************************************************************************************
497 //
498
499 static BOOL FileNotFound(HRESULT hr);
500
501 //****************************************************************************************
502 // Is the given assembly a friend of this assembly?
503 bool GrantsFriendAccessTo(Assembly *pAccessingAssembly, FieldDesc *pFD);
504 bool GrantsFriendAccessTo(Assembly *pAccessingAssembly, MethodDesc *pMD);
505 bool GrantsFriendAccessTo(Assembly *pAccessingAssembly, MethodTable *pMT);
506 bool IgnoresAccessChecksTo(Assembly *pAccessedAssembly);
507
508#ifdef FEATURE_COMINTEROP
509 bool IsImportedFromTypeLib()
510 {
511 WRAPPER_NO_CONTRACT;
512 return ((GetInteropAttributeMask() & INTEROP_ATTRIBUTE_IMPORTED_FROM_TYPELIB) != 0);
513 }
514
515 bool IsPIAOrImportedFromTypeLib()
516 {
517 WRAPPER_NO_CONTRACT;
518 return ((GetInteropAttributeMask() & (INTEROP_ATTRIBUTE_IMPORTED_FROM_TYPELIB | INTEROP_ATTRIBUTE_PRIMARY_INTEROP_ASSEMBLY)) != 0);
519 }
520
521 bool IsPIA()
522 {
523 WRAPPER_NO_CONTRACT;
524 return ((GetInteropAttributeMask() & INTEROP_ATTRIBUTE_PRIMARY_INTEROP_ASSEMBLY) != 0);
525 }
526
527 // Does this assembly contain windows metadata
528 bool IsWinMD();
529
530 // Does this assembly contain windows metadata with managed implementation
531 bool IsManagedWinMD();
532
533 // Returns the IWinMDImport interface of the manifest module metadata or NULL if this assembly is not a .winmd
534 IWinMDImport *GetManifestWinMDImport();
535#endif
536
537
538protected:
539#ifdef FEATURE_COMINTEROP
540 enum WinMDStatus
541 {
542 WinMDStatus_Unknown,
543 WinMDStatus_IsPureWinMD,
544 WinMDStatus_IsManagedWinMD,
545 WinMDStatus_IsNotWinMD
546 };
547
548 // Determine if the assembly is a pure Windows Metadata file, contians managed implementation, or is not
549 // Windows Metadata at all.
550 WinMDStatus GetWinMDStatus();
551
552 enum InteropAttributeStatus {
553 INTEROP_ATTRIBUTE_UNSET = 0,
554 INTEROP_ATTRIBUTE_CACHED = 1,
555 INTEROP_ATTRIBUTE_IMPORTED_FROM_TYPELIB = 2,
556 INTEROP_ATTRIBUTE_PRIMARY_INTEROP_ASSEMBLY = 4,
557 };
558
559 InteropAttributeStatus GetInteropAttributeMask()
560 {
561 LIMITED_METHOD_CONTRACT;
562
563 if (m_InteropAttributeStatus & INTEROP_ATTRIBUTE_CACHED)
564 return m_InteropAttributeStatus;
565
566 int mask = INTEROP_ATTRIBUTE_UNSET;
567
568 if (!IsWinMD()) // ignore classic COM interop CAs in .winmd
569 {
570 if (this->GetManifestImport()->GetCustomAttributeByName(TokenFromRid(1, mdtAssembly), INTEROP_IMPORTEDFROMTYPELIB_TYPE, 0, 0) == S_OK)
571 mask |= INTEROP_ATTRIBUTE_IMPORTED_FROM_TYPELIB;
572 if (this->GetManifestImport()->GetCustomAttributeByName(TokenFromRid(1, mdtAssembly), INTEROP_PRIMARYINTEROPASSEMBLY_TYPE, 0, 0) == S_OK)
573 mask |= INTEROP_ATTRIBUTE_PRIMARY_INTEROP_ASSEMBLY;
574 }
575
576 if (!IsDynamic())
577 {
578 mask |= INTEROP_ATTRIBUTE_CACHED;
579 m_InteropAttributeStatus = static_cast<InteropAttributeStatus>(mask);
580 }
581
582 return static_cast<InteropAttributeStatus>(mask);
583 }
584#endif // FEATURE_INTEROP
585
586private:
587
588 //****************************************************************************************
589
590 void CacheManifestExportedTypes(AllocMemTracker *pamTracker);
591 void CacheManifestFiles();
592
593 void CacheFriendAssemblyInfo();
594
595
596 PTR_BaseDomain m_pDomain; // Parent Domain
597 PTR_ClassLoader m_pClassLoader; // Single Loader
598
599
600
601 PTR_MethodDesc m_pEntryPoint; // Method containing the entry point
602 PTR_Module m_pManifest;
603 PTR_PEAssembly m_pManifestFile;
604
605 FriendAssemblyDescriptor *m_pFriendAssemblyDescriptor;
606
607 BOOL m_isDynamic;
608#ifdef FEATURE_COLLECTIBLE_TYPES
609 BOOL m_isCollectible;
610#endif // FEATURE_COLLECTIBLE_TYPES
611 DWORD m_nextAvailableModuleIndex;
612 PTR_LoaderAllocator m_pLoaderAllocator;
613 DWORD m_isDisabledPrivateReflection;
614
615#ifdef FEATURE_COMINTEROP
616 // If a TypeLib is ever required for this module, cache the pointer here.
617 ITypeLib *m_pITypeLib;
618 InteropAttributeStatus m_InteropAttributeStatus;
619
620 WinMDStatus m_winMDStatus;
621 IWinMDImport *m_pManifestWinMDImport;
622#endif // FEATURE_COMINTEROP
623
624 DebuggerAssemblyControlFlags m_debuggerFlags;
625
626 BOOL m_fTerminated;
627
628 BOOL m_fIsSIMDVectorAssembly;
629
630#ifdef FEATURE_PREJIT
631 enum IsInstrumentedStatus {
632 IS_INSTRUMENTED_UNSET = 0,
633 IS_INSTRUMENTED_FALSE = 1,
634 IS_INSTRUMENTED_TRUE = 2,
635 };
636 IsInstrumentedStatus m_isInstrumentedStatus;
637#endif // FEATURE_PREJIT
638
639};
640
641typedef Assembly::ModuleIterator ModuleIterator;
642
643#ifndef DACCESS_COMPILE
644
645//---------------------------------------------------------------------------------------
646//
647// FriendSecurityDescriptor contains information on which assemblies are friends of an assembly, as well as
648// which individual internals are visible to those friend assemblies.
649//
650
651class FriendAssemblyDescriptor
652{
653public:
654 ~FriendAssemblyDescriptor();
655
656 static
657 FriendAssemblyDescriptor *CreateFriendAssemblyDescriptor(PEAssembly *pAssembly);
658
659 //---------------------------------------------------------------------------------------
660 //
661 // Checks to see if an assembly has friend access to a particular member.
662 //
663 // Arguments:
664 // pAccessingAssembly - the assembly requesting friend access
665 // pMember - the member that is attempting to be accessed
666 //
667 // Return Value:
668 // true if friend access is allowed, false otherwise
669 //
670 // Notes:
671 // Template type T should be either FieldDesc, MethodDesc, or MethodTable.
672 //
673
674 template <class T>
675 bool GrantsFriendAccessTo(Assembly *pAccessingAssembly, T *pMember)
676 {
677 CONTRACTL
678 {
679 THROWS;
680 GC_TRIGGERS;
681 PRECONDITION(CheckPointer(pAccessingAssembly));
682 PRECONDITION(CheckPointer(pMember));
683 }
684 CONTRACTL_END;
685
686 return IsAssemblyOnList(pAccessingAssembly, m_alFullAccessFriendAssemblies);
687 }
688
689
690 bool IgnoresAccessChecksTo(Assembly *pAccessedAssembly)
691 {
692 return IsAssemblyOnList(pAccessedAssembly, m_subjectAssemblies);
693 }
694
695private:
696 typedef AssemblySpec FriendAssemblyName_t;
697 typedef NewHolder<AssemblySpec> FriendAssemblyNameHolder;
698
699 ArrayList m_alFullAccessFriendAssemblies; // Friend assemblies which have access to all internals
700 ArrayList m_subjectAssemblies; // Subject assemblies which we will not perform access checks against
701
702 FriendAssemblyDescriptor();
703
704 void AddFriendAssembly(FriendAssemblyName_t *pFriendAssembly);
705 void AddSubjectAssembly(FriendAssemblyName_t *pSubjectAssembly);
706
707 static
708 bool IsAssemblyOnList(Assembly *pAssembly, const ArrayList &alAssemblyNames)
709 {
710 return IsAssemblyOnList(pAssembly->GetManifestFile(), alAssemblyNames);
711 }
712
713 static
714 bool IsAssemblyOnList(PEAssembly *pAssembly, const ArrayList &alAssemblyNames);
715};
716
717#endif // !DACCESS_COMPILE
718
719
720#endif
721