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 | // DomainFile.h |
6 | // |
7 | |
8 | // -------------------------------------------------------------------------------- |
9 | |
10 | |
11 | #ifndef _DOMAINFILE_H_ |
12 | #define _DOMAINFILE_H_ |
13 | |
14 | // -------------------------------------------------------------------------------- |
15 | // Required headers |
16 | // -------------------------------------------------------------------------------- |
17 | |
18 | // -------------------------------------------------------------------------------- |
19 | // Forward class declarations |
20 | // -------------------------------------------------------------------------------- |
21 | class AppDomain; |
22 | class DomainAssembly; |
23 | class DomainModule; |
24 | class Assembly; |
25 | class Module; |
26 | class DynamicMethodTable; |
27 | |
28 | enum FileLoadLevel |
29 | { |
30 | // These states are tracked by FileLoadLock |
31 | |
32 | // Note: This enum must match the static array fileLoadLevelName[] |
33 | // which contains the printable names of the enum values |
34 | |
35 | // Note that semantics here are description is the LAST step done, not what is |
36 | // currently being done. |
37 | |
38 | FILE_LOAD_CREATE, |
39 | FILE_LOAD_BEGIN, |
40 | FILE_LOAD_FIND_NATIVE_IMAGE, |
41 | FILE_LOAD_VERIFY_NATIVE_IMAGE_DEPENDENCIES, |
42 | FILE_LOAD_ALLOCATE, |
43 | FILE_LOAD_ADD_DEPENDENCIES, |
44 | FILE_LOAD_PRE_LOADLIBRARY, |
45 | FILE_LOAD_LOADLIBRARY, |
46 | FILE_LOAD_POST_LOADLIBRARY, |
47 | FILE_LOAD_EAGER_FIXUPS, |
48 | FILE_LOAD_VTABLE_FIXUPS, |
49 | FILE_LOAD_DELIVER_EVENTS, |
50 | FILE_LOADED, // Loaded by not yet active |
51 | FILE_LOAD_VERIFY_EXECUTION, |
52 | FILE_ACTIVE // Fully active (constructors run & security checked) |
53 | }; |
54 | |
55 | |
56 | enum NotificationStatus |
57 | { |
58 | NOT_NOTIFIED=0, |
59 | PROFILER_NOTIFIED=1, |
60 | DEBUGGER_NEEDNOTIFICATION=2, |
61 | DEBUGGER_NOTIFIED=4 |
62 | }; |
63 | |
64 | // -------------------------------------------------------------------------------- |
65 | // DomainFile represents a file loaded (or being loaded) into an app domain. It |
66 | // is guranteed to be unique per file per app domain. |
67 | // -------------------------------------------------------------------------------- |
68 | |
69 | class DomainFile |
70 | { |
71 | VPTR_BASE_VTABLE_CLASS(DomainFile); |
72 | |
73 | public: |
74 | |
75 | // ------------------------------------------------------------ |
76 | // Public API |
77 | // ------------------------------------------------------------ |
78 | |
79 | #ifndef DACCESS_COMPILE |
80 | virtual ~DomainFile(); |
81 | DomainFile() {LIMITED_METHOD_CONTRACT;}; |
82 | #endif |
83 | |
84 | virtual LoaderAllocator *GetLoaderAllocator(); |
85 | |
86 | PTR_AppDomain GetAppDomain() |
87 | { |
88 | LIMITED_METHOD_CONTRACT; |
89 | SUPPORTS_DAC; |
90 | return m_pDomain; |
91 | } |
92 | |
93 | PEFile *GetFile() |
94 | { |
95 | LIMITED_METHOD_DAC_CONTRACT; |
96 | return m_pFile; |
97 | } |
98 | |
99 | PEFile *GetOriginalFile() |
100 | { |
101 | LIMITED_METHOD_DAC_CONTRACT; |
102 | return m_pOriginalFile!= NULL ? m_pOriginalFile : m_pFile; |
103 | } |
104 | |
105 | |
106 | IMDInternalImport *GetMDImport() |
107 | { |
108 | WRAPPER_NO_CONTRACT; |
109 | return m_pFile->GetPersistentMDImport(); |
110 | } |
111 | |
112 | OBJECTREF GetExposedModuleObjectIfExists() |
113 | { |
114 | LIMITED_METHOD_CONTRACT; |
115 | |
116 | OBJECTREF objRet = NULL; |
117 | GET_LOADERHANDLE_VALUE_FAST(GetLoaderAllocator(), m_hExposedModuleObject, &objRet); |
118 | return objRet; |
119 | } |
120 | |
121 | OBJECTREF GetExposedModuleObject(); |
122 | |
123 | BOOL IsSystem() |
124 | { |
125 | WRAPPER_NO_CONTRACT; |
126 | return GetFile()->IsSystem(); |
127 | } |
128 | |
129 | LPCUTF8 GetSimpleName() |
130 | { |
131 | WRAPPER_NO_CONTRACT; |
132 | return GetFile()->GetSimpleName(); |
133 | } |
134 | |
135 | #ifdef LOGGING |
136 | LPCWSTR GetDebugName() |
137 | { |
138 | WRAPPER_NO_CONTRACT; |
139 | return GetFile()->GetDebugName(); |
140 | } |
141 | #endif |
142 | |
143 | |
144 | void ReleaseFiles() DAC_EMPTY(); |
145 | |
146 | virtual BOOL IsAssembly() = 0; |
147 | |
148 | DomainAssembly *GetDomainAssembly(); |
149 | |
150 | // ------------------------------------------------------------ |
151 | // Loading state checks |
152 | // ------------------------------------------------------------ |
153 | |
154 | // Return the File's load level. Note that this is the last level actually successfully completed. |
155 | // Note that this is subtly different than the FileLoadLock's level, which is the last level |
156 | // which was triggered (but potentially skipped if error or inappropriate.) |
157 | FileLoadLevel GetLoadLevel() { LIMITED_METHOD_DAC_CONTRACT; return m_level; } |
158 | |
159 | // Error means that a permanent x-appdomain load error has occurred. |
160 | BOOL IsError() |
161 | { |
162 | LIMITED_METHOD_DAC_CONTRACT; |
163 | DACCOP_IGNORE(FieldAccess, "No marshalling required" ); |
164 | return m_pError != NULL; |
165 | } |
166 | |
167 | // Loading means that the load is still being tracked by a FileLoadLock. |
168 | BOOL IsLoading() { LIMITED_METHOD_CONTRACT; return m_loading; } |
169 | |
170 | // Loaded means that the file can be used passively. This includes loading types, reflection, and |
171 | // jitting. |
172 | BOOL IsLoaded() { LIMITED_METHOD_DAC_CONTRACT; return m_level >= FILE_LOAD_DELIVER_EVENTS; } |
173 | |
174 | // Active means that the file can be used actively in the current app domain. Note that a shared file |
175 | // may conditionally not be able to be made active on a per app domain basis. |
176 | BOOL IsActive() { LIMITED_METHOD_CONTRACT; return m_level >= FILE_ACTIVE; } |
177 | |
178 | // Checks if the load has reached the point where profilers may be notified |
179 | // about the file. It's important that IF a profiler is notified, THEN this returns |
180 | // TRUE, otherwise there can be profiler-attach races where the profiler doesn't see |
181 | // the file via either enumeration or notification. As a result, this begins |
182 | // returning TRUE just before the profiler is actually notified. See |
183 | // code:ProfilerFunctionEnum::Init#ProfilerEnumAssemblies |
184 | BOOL IsAvailableToProfilers() |
185 | { |
186 | LIMITED_METHOD_DAC_CONTRACT; |
187 | return IsProfilerNotified(); // despite the name, this function returns TRUE just before we notify the profiler |
188 | } |
189 | |
190 | // CheckLoaded is appropriate for asserts that the assembly can be passively used. |
191 | CHECK CheckLoaded(); |
192 | |
193 | // CheckActivated is appropriate for asserts that the assembly can be actively used. Note that |
194 | // it is slightly different from IsActive in that it deals with reentrancy cases properly. |
195 | CHECK CheckActivated(); |
196 | |
197 | // Ensure that an assembly has reached at least the IsLoaded state. Throw if not. |
198 | void EnsureLoaded() |
199 | { |
200 | WRAPPER_NO_CONTRACT; |
201 | return EnsureLoadLevel(FILE_LOADED); |
202 | } |
203 | |
204 | // Ensure that an assembly has reached at least the IsActive state. Throw if not. |
205 | void EnsureActive() |
206 | { |
207 | WRAPPER_NO_CONTRACT; |
208 | return EnsureLoadLevel(FILE_ACTIVE); |
209 | } |
210 | |
211 | // Ensure that an assembly has reached at least the Allocated state. Throw if not. |
212 | void EnsureAllocated() |
213 | { |
214 | WRAPPER_NO_CONTRACT; |
215 | return EnsureLoadLevel(FILE_LOAD_ALLOCATE); |
216 | } |
217 | |
218 | |
219 | void EnsureLibraryLoaded() |
220 | { |
221 | WRAPPER_NO_CONTRACT; |
222 | return EnsureLoadLevel(FILE_LOAD_LOADLIBRARY); |
223 | } |
224 | |
225 | // This wraps EnsureActive, suppressing non-transient exceptions |
226 | BOOL TryEnsureActive(); |
227 | |
228 | // EnsureLoadLevel is a generic routine used to ensure that the file is not in a delay loaded |
229 | // state (unless it needs to be.) This should be used when a particular level of loading |
230 | // is required for an operation. Note that deadlocks are tolerated so the level may be one |
231 | void EnsureLoadLevel(FileLoadLevel targetLevel) DAC_EMPTY(); |
232 | |
233 | // AttemptLoadLevel is a generic routine used to try to further load the file to a given level. |
234 | // No guarantee is made about the load level resulting however. |
235 | void AttemptLoadLevel(FileLoadLevel targetLevel) DAC_EMPTY(); |
236 | |
237 | // CheckLoadLevel is an assert predicate used to verify the load level of an assembly. |
238 | // deadlockOK indicates that the level is allowed to be one short if we are restricted |
239 | // by loader reentrancy. |
240 | CHECK CheckLoadLevel(FileLoadLevel requiredLevel, BOOL deadlockOK = TRUE) DAC_EMPTY_RET(CHECK::OK()); |
241 | |
242 | // RequireLoadLevel throws an exception if the domain file isn't loaded enough. Note |
243 | // that this is intolerant of deadlock related failures so is only really appropriate for |
244 | // checks inside the main loading loop. |
245 | void RequireLoadLevel(FileLoadLevel targetLevel) DAC_EMPTY(); |
246 | |
247 | // Throws if a load error has occurred |
248 | void ThrowIfError(FileLoadLevel targetLevel) DAC_EMPTY(); |
249 | |
250 | // Checks that a load error has not occurred before the given level |
251 | CHECK CheckNoError(FileLoadLevel targetLevel) DAC_EMPTY_RET(CHECK::OK()); |
252 | |
253 | // IsNotified means that the profiler API notification has been delivered |
254 | BOOL IsProfilerNotified() { LIMITED_METHOD_CONTRACT; return m_notifyflags & PROFILER_NOTIFIED; } |
255 | BOOL IsDebuggerNotified() { LIMITED_METHOD_CONTRACT; return m_notifyflags & DEBUGGER_NOTIFIED; } |
256 | BOOL ShouldNotifyDebugger() { LIMITED_METHOD_CONTRACT; return m_notifyflags & DEBUGGER_NEEDNOTIFICATION; } |
257 | |
258 | |
259 | // ------------------------------------------------------------ |
260 | // Other public APIs |
261 | // ------------------------------------------------------------ |
262 | |
263 | #ifndef DACCESS_COMPILE |
264 | BOOL Equals(DomainFile *pFile) { WRAPPER_NO_CONTRACT; return GetFile()->Equals(pFile->GetFile()); } |
265 | BOOL Equals(PEFile *pFile) { WRAPPER_NO_CONTRACT; return GetFile()->Equals(pFile); } |
266 | #endif // DACCESS_COMPILE |
267 | |
268 | Module* GetCurrentModule(); |
269 | Module* GetLoadedModule(); |
270 | Module* GetModule(); |
271 | |
272 | #ifdef FEATURE_PREJIT |
273 | BOOL IsZapRequired(); // Are we absolutely required to use a native image? |
274 | #endif |
275 | // The format string is intentionally unicode to avoid globalization bugs |
276 | #ifdef FEATURE_PREJIT |
277 | void ExternalLog(DWORD level, const WCHAR *fmt, ...); |
278 | void ExternalLog(DWORD level, const char *msg); |
279 | #endif |
280 | #ifdef DACCESS_COMPILE |
281 | virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); |
282 | #endif |
283 | |
284 | #ifndef DACCESS_COMPILE |
285 | // light code gen. Keep the list of MethodTables needed for creating dynamic methods |
286 | DynamicMethodTable* GetDynamicMethodTable(); |
287 | #endif |
288 | |
289 | protected: |
290 | // ------------------------------------------------------------ |
291 | // Loader API |
292 | // ------------------------------------------------------------ |
293 | |
294 | friend class AppDomain; |
295 | friend class Assembly; |
296 | friend class Module; |
297 | friend class FileLoadLock; |
298 | |
299 | DomainFile(AppDomain *pDomain, PEFile *pFile); |
300 | |
301 | BOOL DoIncrementalLoad(FileLoadLevel targetLevel); |
302 | void ClearLoading() { LIMITED_METHOD_CONTRACT; m_loading = FALSE; } |
303 | void SetLoadLevel(FileLoadLevel level) { LIMITED_METHOD_CONTRACT; m_level = level; } |
304 | |
305 | #ifndef DACCESS_COMPILE |
306 | virtual void Begin() = 0; |
307 | virtual void Allocate() = 0; |
308 | void AddDependencies(); |
309 | void PreLoadLibrary(); |
310 | void LoadLibrary(); |
311 | void PostLoadLibrary(); |
312 | void EagerFixups(); |
313 | void VtableFixups(); |
314 | virtual void DeliverSyncEvents() = 0; |
315 | virtual void DeliverAsyncEvents() = 0; |
316 | void FinishLoad(); |
317 | void VerifyExecution(); |
318 | void Activate(); |
319 | #endif |
320 | |
321 | // This should be used to permanently set the load to fail. Do not use with transient conditions |
322 | void SetError(Exception *ex); |
323 | |
324 | #ifdef FEATURE_PREJIT |
325 | |
326 | #ifndef DACCESS_COMPILE |
327 | virtual void FindNativeImage() = 0; |
328 | #endif |
329 | void VerifyNativeImageDependencies(bool verifyOnly = FALSE); |
330 | |
331 | // Are we absolutely required to use a native image? |
332 | void CheckZapRequired(); |
333 | |
334 | void ClearNativeImageStress(); |
335 | |
336 | #endif // FEATURE_PREJIT |
337 | |
338 | void SetProfilerNotified() { LIMITED_METHOD_CONTRACT; m_notifyflags|= PROFILER_NOTIFIED; } |
339 | void SetDebuggerNotified() { LIMITED_METHOD_CONTRACT; m_notifyflags|=DEBUGGER_NOTIFIED; } |
340 | void SetShouldNotifyDebugger() { LIMITED_METHOD_CONTRACT; m_notifyflags|=DEBUGGER_NEEDNOTIFICATION; } |
341 | #ifndef DACCESS_COMPILE |
342 | void UpdatePEFileWorker(PTR_PEFile pFile); |
343 | #endif |
344 | |
345 | // ------------------------------------------------------------ |
346 | // Instance data |
347 | // ------------------------------------------------------------ |
348 | |
349 | PTR_AppDomain m_pDomain; |
350 | PTR_PEFile m_pFile; |
351 | PTR_PEFile m_pOriginalFile; // keep file alive just in case someone is sitill using it. If this is not NULL then m_pFile contains reused file from the shared assembly |
352 | PTR_Module m_pModule; |
353 | FileLoadLevel m_level; |
354 | LOADERHANDLE m_hExposedModuleObject; |
355 | |
356 | class ExInfo |
357 | { |
358 | enum |
359 | { |
360 | ExType_ClrEx, |
361 | ExType_HR |
362 | } |
363 | m_type; |
364 | union |
365 | { |
366 | Exception *m_pEx; |
367 | HRESULT m_hr; |
368 | }; |
369 | |
370 | public: |
371 | void Throw() |
372 | { |
373 | CONTRACTL |
374 | { |
375 | THROWS; |
376 | GC_TRIGGERS; |
377 | MODE_ANY; |
378 | } |
379 | CONTRACTL_END; |
380 | if (m_type==ExType_ClrEx) |
381 | { |
382 | PAL_CPP_THROW(Exception *, m_pEx->DomainBoundClone()); |
383 | } |
384 | if (m_type==ExType_HR) |
385 | ThrowHR(m_hr); |
386 | _ASSERTE(!"Bad exception type" ); |
387 | ThrowHR(E_UNEXPECTED); |
388 | }; |
389 | ExInfo(Exception* pEx) |
390 | { |
391 | LIMITED_METHOD_CONTRACT; |
392 | m_type=ExType_ClrEx; |
393 | m_pEx=pEx; |
394 | }; |
395 | |
396 | void ConvertToHResult() |
397 | { |
398 | LIMITED_METHOD_CONTRACT; |
399 | if(m_type==ExType_HR) |
400 | return; |
401 | _ASSERTE(m_type==ExType_ClrEx); |
402 | HRESULT hr=m_pEx->GetHR(); |
403 | delete m_pEx; |
404 | m_hr=hr; |
405 | m_type=ExType_HR; |
406 | }; |
407 | ~ExInfo() |
408 | { |
409 | LIMITED_METHOD_CONTRACT; |
410 | if (m_type==ExType_ClrEx) |
411 | delete m_pEx; |
412 | } |
413 | }* m_pError; |
414 | |
415 | void ReleaseManagedData() |
416 | { |
417 | if (m_pError) |
418 | m_pError->ConvertToHResult(); |
419 | }; |
420 | |
421 | #ifdef FEATURE_PREJIT |
422 | // Lock-free enumeration of DomainFiles in an AppDomain. |
423 | public: |
424 | DomainFile *FindNextDomainFileWithNativeImage(); |
425 | private: |
426 | void InsertIntoDomainFileWithNativeImageList(); |
427 | #endif // FEATURE_PREJIT |
428 | |
429 | DWORD m_notifyflags; |
430 | BOOL m_loading; |
431 | // m_pDynamicMethodTable is used by the light code generation to allow method |
432 | // generation on the fly. They are lazily created when/if a dynamic method is requested |
433 | // for this specific module |
434 | DynamicMethodTable *m_pDynamicMethodTable; |
435 | class UMThunkHash *m_pUMThunkHash; |
436 | BOOL m_bDisableActivationCheck; |
437 | |
438 | // This value is to make it easier to diagnose Assembly Loader "rejected native image" crashes. |
439 | // See Dev11 bug 358184 for more details |
440 | public: |
441 | DWORD m_dwReasonForRejectingNativeImage; // See code:g_dwLoaderReasonForNotSharing in Assembly.cpp for a similar variable. |
442 | private: |
443 | |
444 | #ifdef FEATURE_PREJIT |
445 | // This value is to allow lock-free enumeration of all native images in an AppDomain |
446 | Volatile<DomainFile *> m_pNextDomainFileWithNativeImage; |
447 | #endif |
448 | }; |
449 | |
450 | // These will sometimes result in a crash with error code 0x80131506 COR_E_EXECUTIONENGINE |
451 | // "An internal error happened in the Common Language Runtime's Execution Engine" |
452 | // Cause: Incorrectly committed to using native image for <path to assembly> |
453 | enum ReasonForRejectingNativeImage |
454 | { |
455 | ReasonForRejectingNativeImage_NoNiForManifestModule = 0x101, |
456 | ReasonForRejectingNativeImage_DependencyNotNative = 0x102, |
457 | ReasonForRejectingNativeImage_MscorlibNotNative = 0x103, |
458 | ReasonForRejectingNativeImage_FailedSecurityCheck = 0x104, |
459 | ReasonForRejectingNativeImage_DependencyIdentityMismatch = 0x105, |
460 | ReasonForRejectingNativeImage_CannotShareNiAssemblyNotDomainNeutral = 0x106, |
461 | ReasonForRejectingNativeImage_NiAlreadyUsedInAnotherSharedAssembly = 0x107, |
462 | }; |
463 | |
464 | //--------------------------------------------------------------------------------------- |
465 | // One of these values is specified when requesting a module iterator to customize which |
466 | // modules should appear in the enumeration |
467 | enum ModuleIterationOption |
468 | { |
469 | // include only modules that are already loaded (m_level >= FILE_LOAD_DELIVER_EVENTS) |
470 | kModIterIncludeLoaded = 1, |
471 | |
472 | // include all modules, even those that are still in the process of loading (all m_level values) |
473 | kModIterIncludeLoading = 2, |
474 | |
475 | // include only modules loaded just enough that profilers are notified of them. |
476 | // (m_level >= FILE_LOAD_LOADLIBRARY). See comment at code:DomainFile::IsAvailableToProfilers |
477 | kModIterIncludeAvailableToProfilers = 3, |
478 | }; |
479 | |
480 | // -------------------------------------------------------------------------------- |
481 | // DomainAssembly is a subclass of DomainFile which specifically represents a assembly. |
482 | // -------------------------------------------------------------------------------- |
483 | |
484 | class DomainAssembly : public DomainFile |
485 | { |
486 | VPTR_VTABLE_CLASS(DomainAssembly, DomainFile); |
487 | |
488 | public: |
489 | // ------------------------------------------------------------ |
490 | // Public API |
491 | // ------------------------------------------------------------ |
492 | |
493 | PEAssembly *GetFile() |
494 | { |
495 | LIMITED_METHOD_CONTRACT; |
496 | return PTR_PEAssembly(m_pFile); |
497 | } |
498 | |
499 | LoaderAllocator *GetLoaderAllocator() |
500 | { |
501 | LIMITED_METHOD_CONTRACT; |
502 | return m_pLoaderAllocator; |
503 | } |
504 | |
505 | #ifndef DACCESS_COMPILE |
506 | void ReleaseFiles(); |
507 | #endif // DACCESS_COMPILE |
508 | |
509 | // Finds only loaded hmods |
510 | DomainFile *FindIJWModule(HMODULE hMod); |
511 | |
512 | void SetAssembly(Assembly* pAssembly); |
513 | |
514 | BOOL IsAssembly() |
515 | { |
516 | LIMITED_METHOD_DAC_CONTRACT; |
517 | return TRUE; |
518 | } |
519 | |
520 | OBJECTREF GetExposedAssemblyObjectIfExists() |
521 | { |
522 | LIMITED_METHOD_CONTRACT; |
523 | |
524 | OBJECTREF objRet = NULL; |
525 | GET_LOADERHANDLE_VALUE_FAST(GetLoaderAllocator(), m_hExposedAssemblyObject, &objRet); |
526 | return objRet; |
527 | } |
528 | |
529 | // Returns managed representation of the assembly (Assembly or AssemblyBuilder). |
530 | // Returns NULL if the managed scout was already collected (see code:LoaderAllocator#AssemblyPhases). |
531 | OBJECTREF GetExposedAssemblyObject(); |
532 | |
533 | Assembly* GetCurrentAssembly(); |
534 | Assembly* GetLoadedAssembly(); |
535 | Assembly* GetAssembly(); |
536 | |
537 | #ifdef DACCESS_COMPILE |
538 | virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); |
539 | #endif |
540 | |
541 | // ------------------------------------------------------------ |
542 | // Modules |
543 | // ------------------------------------------------------------ |
544 | class ModuleIterator |
545 | { |
546 | ArrayList::Iterator m_i; |
547 | ModuleIterationOption m_moduleIterationOption; |
548 | |
549 | public: |
550 | BOOL Next() |
551 | { |
552 | WRAPPER_NO_CONTRACT; |
553 | while (m_i.Next()) |
554 | { |
555 | if (m_i.GetElement() == NULL) |
556 | { |
557 | continue; |
558 | } |
559 | if (GetDomainFile()->IsError()) |
560 | { |
561 | continue; |
562 | } |
563 | if (m_moduleIterationOption == kModIterIncludeLoading) |
564 | return TRUE; |
565 | if ((m_moduleIterationOption == kModIterIncludeLoaded) && |
566 | GetDomainFile()->IsLoaded()) |
567 | return TRUE; |
568 | if ((m_moduleIterationOption == kModIterIncludeAvailableToProfilers) && |
569 | GetDomainFile()->IsAvailableToProfilers()) |
570 | return TRUE; |
571 | } |
572 | return FALSE; |
573 | } |
574 | Module *GetModule() |
575 | { |
576 | WRAPPER_NO_CONTRACT; |
577 | return GetDomainFile()->GetModule(); |
578 | } |
579 | Module *GetLoadedModule() |
580 | { |
581 | WRAPPER_NO_CONTRACT; |
582 | return GetDomainFile()->GetLoadedModule(); |
583 | } |
584 | DomainFile *GetDomainFile() |
585 | { |
586 | WRAPPER_NO_CONTRACT; |
587 | return dac_cast<PTR_DomainFile>(m_i.GetElement()); |
588 | } |
589 | SIZE_T GetIndex() |
590 | { |
591 | WRAPPER_NO_CONTRACT; |
592 | return m_i.GetIndex(); |
593 | } |
594 | |
595 | private: |
596 | friend class DomainAssembly; |
597 | // Cannot have constructor so this iterator can be used inside a union |
598 | static ModuleIterator Create(DomainAssembly * pDomainAssembly, ModuleIterationOption moduleIterationOption) |
599 | { |
600 | WRAPPER_NO_CONTRACT; |
601 | ModuleIterator i; |
602 | |
603 | i.m_i = pDomainAssembly->m_Modules.Iterate(); |
604 | i.m_moduleIterationOption = moduleIterationOption; |
605 | |
606 | return i; |
607 | } |
608 | }; |
609 | friend class ModuleIterator; |
610 | |
611 | ModuleIterator IterateModules(ModuleIterationOption moduleIterationOption) |
612 | { |
613 | WRAPPER_NO_CONTRACT; |
614 | return ModuleIterator::Create(this, moduleIterationOption); |
615 | } |
616 | |
617 | DomainFile *LookupDomainFile(DWORD index) |
618 | { |
619 | WRAPPER_NO_CONTRACT; |
620 | if (index >= m_Modules.GetCount()) |
621 | return NULL; |
622 | else |
623 | return dac_cast<PTR_DomainFile>(m_Modules.Get(index)); |
624 | } |
625 | |
626 | Module *LookupModule(DWORD index) |
627 | { |
628 | WRAPPER_NO_CONTRACT; |
629 | DomainFile *pModule = LookupDomainFile(index); |
630 | if (pModule == NULL) |
631 | return NULL; |
632 | else |
633 | return pModule->GetModule(); |
634 | } |
635 | |
636 | |
637 | // ------------------------------------------------------------ |
638 | // Resource access |
639 | // ------------------------------------------------------------ |
640 | |
641 | BOOL GetResource(LPCSTR szName, DWORD *cbResource, |
642 | PBYTE *pbInMemoryResource, DomainAssembly** pAssemblyRef, |
643 | LPCSTR *szFileName, DWORD *dwLocation, |
644 | BOOL fSkipRaiseResolveEvent); |
645 | |
646 | #ifdef FEATURE_PREJIT |
647 | // ------------------------------------------------------------ |
648 | // Prejitting API |
649 | // ------------------------------------------------------------ |
650 | |
651 | void GetCurrentVersionInfo(CORCOMPILE_VERSION_INFO *pZapVersionInfo); |
652 | |
653 | void GetOptimizedIdentitySignature(CORCOMPILE_ASSEMBLY_SIGNATURE *pSignature); |
654 | BOOL CheckZapDependencyIdentities(PEImage *pNativeImage); |
655 | |
656 | #endif // FEATURE_PREJIT |
657 | |
658 | // ------------------------------------------------------------ |
659 | // Debugger control API |
660 | // ------------------------------------------------------------ |
661 | |
662 | DebuggerAssemblyControlFlags GetDebuggerInfoBits(void) |
663 | { |
664 | LIMITED_METHOD_CONTRACT; |
665 | return m_debuggerFlags; |
666 | } |
667 | |
668 | void SetDebuggerInfoBits(DebuggerAssemblyControlFlags newBits) |
669 | { |
670 | LIMITED_METHOD_CONTRACT; |
671 | m_debuggerFlags = newBits; |
672 | } |
673 | |
674 | void SetupDebuggingConfig(void); |
675 | DWORD ComputeDebuggingConfig(void); |
676 | |
677 | bool GetDebuggingOverrides(DWORD *pdwFlags); |
678 | |
679 | HRESULT GetDebuggingCustomAttributes(DWORD *pdwFlags); |
680 | |
681 | BOOL IsVisibleToDebugger(); |
682 | BOOL NotifyDebuggerLoad(int flags, BOOL attaching); |
683 | void NotifyDebuggerUnload(); |
684 | |
685 | inline BOOL IsCollectible(); |
686 | // |
687 | // GC API |
688 | // |
689 | void EnumStaticGCRefs(promote_func* fn, ScanContext* sc); |
690 | |
691 | |
692 | private: |
693 | |
694 | // ------------------------------------------------------------ |
695 | // Loader API |
696 | // ------------------------------------------------------------ |
697 | |
698 | friend class AppDomain; |
699 | friend class Assembly; |
700 | friend class AssemblyNameNative; |
701 | |
702 | #ifndef DACCESS_COMPILE |
703 | public: |
704 | ~DomainAssembly(); |
705 | private: |
706 | DomainAssembly(AppDomain *pDomain, PEFile *pFile, LoaderAllocator *pLoaderAllocator); |
707 | #endif |
708 | |
709 | // ------------------------------------------------------------ |
710 | // Internal routines |
711 | // ------------------------------------------------------------ |
712 | |
713 | void SetSecurityError(Exception *ex); |
714 | |
715 | #ifndef DACCESS_COMPILE |
716 | void Begin(); |
717 | void Allocate(); |
718 | void LoadSharers(); |
719 | void DeliverSyncEvents(); |
720 | void DeliverAsyncEvents(); |
721 | #endif |
722 | |
723 | void UpdatePEFile(PTR_PEFile pFile); |
724 | |
725 | #ifdef FEATURE_PREJIT |
726 | #ifndef DACCESS_COMPILE |
727 | void FindNativeImage(); |
728 | #endif |
729 | #endif // FEATURE_PREJIT |
730 | |
731 | BOOL IsInstrumented(); |
732 | |
733 | public: |
734 | ULONG HashIdentity(); |
735 | |
736 | // ------------------------------------------------------------ |
737 | // Instance data |
738 | // ------------------------------------------------------------ |
739 | |
740 | private: |
741 | LOADERHANDLE m_hExposedAssemblyObject; |
742 | PTR_Assembly m_pAssembly; |
743 | DebuggerAssemblyControlFlags m_debuggerFlags; |
744 | ArrayList m_Modules; |
745 | BOOL m_fDebuggerUnloadStarted; |
746 | BOOL m_fCollectible; |
747 | Volatile<bool> m_fHostAssemblyPublished; |
748 | PTR_LoaderAllocator m_pLoaderAllocator; |
749 | DomainAssembly* m_NextDomainAssemblyInSameALC; |
750 | |
751 | public: |
752 | DomainAssembly* GetNextDomainAssemblyInSameALC() |
753 | { |
754 | return m_NextDomainAssemblyInSameALC; |
755 | } |
756 | |
757 | void SetNextDomainAssemblyInSameALC(DomainAssembly* domainAssembly) |
758 | { |
759 | _ASSERTE(m_NextDomainAssemblyInSameALC == NULL); |
760 | m_NextDomainAssemblyInSameALC = domainAssembly; |
761 | } |
762 | |
763 | // Indicates if the assembly can be cached in a binding cache such as AssemblySpecBindingCache. |
764 | inline bool CanUseWithBindingCache() |
765 | { STATIC_CONTRACT_WRAPPER; return GetFile()->CanUseWithBindingCache(); } |
766 | }; |
767 | |
768 | typedef DomainAssembly::ModuleIterator DomainModuleIterator; |
769 | |
770 | // -------------------------------------------------------------------------------- |
771 | // DomainModule is a subclass of DomainFile which specifically represents a module. |
772 | // -------------------------------------------------------------------------------- |
773 | #endif // _DOMAINFILE_H_ |
774 | |