3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 ////////////////////////////////////////////////////////////////////////////////
7 ////////////////////////////////////////////////////////////////////////////////
8 // <OWNER>Microsoft</OWNER>
11 namespace System.Reflection.Emit {
13 using IList = System.Collections.IList;
14 using System.Collections.Generic;
15 using System.Reflection;
16 using System.Security;
17 using System.Diagnostics;
18 using CultureInfo = System.Globalization.CultureInfo;
20 using ResourceWriter = System.Resources.ResourceWriter;
21 #else // FEATURE_CORECLR
22 using IResourceWriter = System.Resources.IResourceWriter;
23 #endif // !FEATURE_CORECLR
25 using System.Runtime.Versioning;
26 using System.Diagnostics.SymbolStore;
27 using System.Diagnostics.Contracts;
29 // This is a package private class. This class hold all of the managed
30 // data member for AssemblyBuilder. Note that what ever data members added to
31 // this class cannot be accessed from the EE.
32 internal class AssemblyBuilderData
35 [ResourceExposure(ResourceScope.Machine)]
36 [ResourceConsumption(ResourceScope.Machine)]
37 internal AssemblyBuilderData(
38 InternalAssemblyBuilder assembly,
39 String strAssemblyName,
40 AssemblyBuilderAccess access,
43 m_assembly = assembly;
44 m_strAssemblyName = strAssemblyName;
46 m_moduleBuilderList = new List<ModuleBuilder>();
47 m_resWriterList = new List<ResWriterData>();
49 //Init to null/0 done for you by the CLR. FXCop has spoken
51 if (dir == null && access != AssemblyBuilderAccess.Run)
52 m_strDir = Environment.CurrentDirectory;
56 m_peFileKind = PEFileKinds.Dll;
59 // Helper to add a dynamic module into the tracking list
60 [ResourceExposure(ResourceScope.None)]
61 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
62 internal void AddModule(ModuleBuilder dynModule)
64 m_moduleBuilderList.Add(dynModule);
67 // Helper to add a resource information into the tracking list
68 internal void AddResWriter(ResWriterData resData)
70 m_resWriterList.Add(resData);
74 // Helper to track CAs to persist onto disk
75 internal void AddCustomAttribute(CustomAttributeBuilder customBuilder)
78 // make sure we have room for this CA
79 if (m_CABuilders == null)
81 m_CABuilders = new CustomAttributeBuilder[m_iInitialSize];
83 if (m_iCABuilder == m_CABuilders.Length)
85 CustomAttributeBuilder[] tempCABuilders = new CustomAttributeBuilder[m_iCABuilder * 2];
86 Array.Copy(m_CABuilders, tempCABuilders, m_iCABuilder);
87 m_CABuilders = tempCABuilders;
89 m_CABuilders[m_iCABuilder] = customBuilder;
94 // Helper to track CAs to persist onto disk
95 internal void AddCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
98 // make sure we have room for this CA
99 if (m_CABytes == null)
101 m_CABytes = new byte[m_iInitialSize][];
102 m_CACons = new ConstructorInfo[m_iInitialSize];
104 if (m_iCAs == m_CABytes.Length)
106 // enlarge the arrays
107 byte[][] temp = new byte[m_iCAs * 2][];
108 ConstructorInfo[] tempCon = new ConstructorInfo[m_iCAs * 2];
109 for (int i=0; i < m_iCAs; i++)
111 temp[i] = m_CABytes[i];
112 tempCon[i] = m_CACons[i];
118 byte[] attrs = new byte[binaryAttribute.Length];
119 Array.Copy(binaryAttribute, attrs, binaryAttribute.Length);
120 m_CABytes[m_iCAs] = attrs;
121 m_CACons[m_iCAs] = con;
126 // Helper to calculate unmanaged version info from Assembly's custom attributes.
127 // If DefineUnmanagedVersionInfo is called, the parameter provided will override
130 [System.Security.SecurityCritical] // auto-generated
131 internal void FillUnmanagedVersionInfo()
133 // Get the lcid set on the assembly name as default if available
134 // Note that if LCID is not avaible from neither AssemblyName or AssemblyCultureAttribute,
135 // it is default to -1 which is treated as language neutral.
137 CultureInfo locale = m_assembly.GetLocale();
140 m_nativeVersion.m_lcid = locale.LCID;
143 for (int i = 0; i < m_iCABuilder; i++)
145 // check for known attributes
146 Type conType = m_CABuilders[i].m_con.DeclaringType;
147 if (m_CABuilders[i].m_constructorArgs.Length == 0 || m_CABuilders[i].m_constructorArgs[0] == null)
150 if (conType.Equals(typeof(System.Reflection.AssemblyCopyrightAttribute)))
152 // assert that we should only have one argument for this CA and the type should
155 if (m_CABuilders[i].m_constructorArgs.Length != 1)
157 throw new ArgumentException(Environment.GetResourceString(
158 "Argument_BadCAForUnmngRSC",
159 m_CABuilders[i].m_con.ReflectedType.Name));
161 if (m_OverrideUnmanagedVersionInfo == false)
163 m_nativeVersion.m_strCopyright = m_CABuilders[i].m_constructorArgs[0].ToString();
166 else if (conType.Equals(typeof(System.Reflection.AssemblyTrademarkAttribute)))
168 // assert that we should only have one argument for this CA and the type should
171 if (m_CABuilders[i].m_constructorArgs.Length != 1)
173 throw new ArgumentException(Environment.GetResourceString(
174 "Argument_BadCAForUnmngRSC",
175 m_CABuilders[i].m_con.ReflectedType.Name));
177 if (m_OverrideUnmanagedVersionInfo == false)
179 m_nativeVersion.m_strTrademark = m_CABuilders[i].m_constructorArgs[0].ToString();
182 else if (conType.Equals(typeof(System.Reflection.AssemblyProductAttribute)))
184 if (m_OverrideUnmanagedVersionInfo == false)
186 // assert that we should only have one argument for this CA and the type should
189 m_nativeVersion.m_strProduct = m_CABuilders[i].m_constructorArgs[0].ToString();
192 else if (conType.Equals(typeof(System.Reflection.AssemblyCompanyAttribute)))
194 if (m_CABuilders[i].m_constructorArgs.Length != 1)
196 throw new ArgumentException(Environment.GetResourceString(
197 "Argument_BadCAForUnmngRSC",
198 m_CABuilders[i].m_con.ReflectedType.Name));
200 if (m_OverrideUnmanagedVersionInfo == false)
202 // assert that we should only have one argument for this CA and the type should
205 m_nativeVersion.m_strCompany = m_CABuilders[i].m_constructorArgs[0].ToString();
208 else if (conType.Equals(typeof(System.Reflection.AssemblyDescriptionAttribute)))
210 if (m_CABuilders[i].m_constructorArgs.Length != 1)
212 throw new ArgumentException(Environment.GetResourceString(
213 "Argument_BadCAForUnmngRSC",
214 m_CABuilders[i].m_con.ReflectedType.Name));
216 m_nativeVersion.m_strDescription = m_CABuilders[i].m_constructorArgs[0].ToString();
218 else if (conType.Equals(typeof(System.Reflection.AssemblyTitleAttribute)))
220 if (m_CABuilders[i].m_constructorArgs.Length != 1)
222 throw new ArgumentException(Environment.GetResourceString(
223 "Argument_BadCAForUnmngRSC",
224 m_CABuilders[i].m_con.ReflectedType.Name));
226 m_nativeVersion.m_strTitle = m_CABuilders[i].m_constructorArgs[0].ToString();
228 else if (conType.Equals(typeof(System.Reflection.AssemblyInformationalVersionAttribute)))
230 if (m_CABuilders[i].m_constructorArgs.Length != 1)
232 throw new ArgumentException(Environment.GetResourceString(
233 "Argument_BadCAForUnmngRSC",
234 m_CABuilders[i].m_con.ReflectedType.Name));
236 if (m_OverrideUnmanagedVersionInfo == false)
238 m_nativeVersion.m_strProductVersion = m_CABuilders[i].m_constructorArgs[0].ToString();
241 else if (conType.Equals(typeof(System.Reflection.AssemblyCultureAttribute)))
244 if (m_CABuilders[i].m_constructorArgs.Length != 1)
246 throw new ArgumentException(Environment.GetResourceString(
247 "Argument_BadCAForUnmngRSC",
248 m_CABuilders[i].m_con.ReflectedType.Name));
250 // CultureInfo attribute overrides the lcid from AssemblyName.
251 CultureInfo culture = new CultureInfo(m_CABuilders[i].m_constructorArgs[0].ToString());
253 m_nativeVersion.m_lcid = culture.LCID;
256 else if (conType.Equals(typeof(System.Reflection.AssemblyFileVersionAttribute)))
258 if (m_CABuilders[i].m_constructorArgs.Length != 1)
260 throw new ArgumentException(Environment.GetResourceString(
261 "Argument_BadCAForUnmngRSC",
262 m_CABuilders[i].m_con.ReflectedType.Name));
264 if (m_OverrideUnmanagedVersionInfo == false)
266 m_nativeVersion.m_strFileVersion = m_CABuilders[i].m_constructorArgs[0].ToString();
271 #endif //!FEATURE_PAL
273 // Helper to ensure the resource name is unique underneath assemblyBuilder
274 internal void CheckResNameConflict(String strNewResName)
276 int size = m_resWriterList.Count;
278 for (i = 0; i < size; i++)
280 ResWriterData resWriter = m_resWriterList[i];
281 if (resWriter.m_strName.Equals(strNewResName))
283 // Cannot have two resources with the same name
284 throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateResourceName"));
290 // Helper to ensure the module name is unique underneath assemblyBuilder
291 [ResourceExposure(ResourceScope.None)]
292 [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly, ResourceScope.Machine | ResourceScope.Assembly)]
293 internal void CheckNameConflict(String strNewModuleName)
295 int size = m_moduleBuilderList.Count;
297 for (i = 0; i < size; i++)
299 ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
300 if (moduleBuilder.m_moduleData.m_strModuleName.Equals(strNewModuleName))
302 // Cannot have two dynamic modules with the same name
303 throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateModuleName"));
307 // Right now dynamic modules can only be added to dynamic assemblies in which
308 // all modules are dynamic. Otherwise we would also need to check the static modules
310 // if (m_assembly.GetModule(strNewModuleName) != null)
312 // // Cannot have two dynamic modules with the same name
313 // throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateModuleName"));
317 // Helper to ensure the type name is unique underneath assemblyBuilder
318 internal void CheckTypeNameConflict(String strTypeName, TypeBuilder enclosingType)
320 BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.CheckTypeNameConflict( " + strTypeName + " )");
321 for (int i = 0; i < m_moduleBuilderList.Count; i++)
323 ModuleBuilder curModule = m_moduleBuilderList[i];
324 curModule.CheckTypeNameConflict(strTypeName, enclosingType);
327 // Right now dynamic modules can only be added to dynamic assemblies in which
328 // all modules are dynamic. Otherwise we would also need to check loaded types.
329 // We only need to make this test for non-nested types since any
330 // duplicates in nested types will be caught at the top level.
331 // if (enclosingType == null && m_assembly.GetType(strTypeName, false, false) != null)
333 // // Cannot have two types with the same name
334 // throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateTypeName"));
339 // Helper to ensure the file name is unique underneath assemblyBuilder. This includes
340 // modules and resources.
344 internal void CheckFileNameConflict(String strFileName)
346 int size = m_moduleBuilderList.Count;
348 for (i = 0; i < size; i++)
350 ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
351 if (moduleBuilder.m_moduleData.m_strFileName != null)
353 if (String.Compare(moduleBuilder.m_moduleData.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0)
355 // Cannot have two dynamic module with the same name
356 throw new ArgumentException(Environment.GetResourceString("Argument_DuplicatedFileName"));
360 size = m_resWriterList.Count;
361 for (i = 0; i < size; i++)
363 ResWriterData resWriter = m_resWriterList[i];
364 if (resWriter.m_strFileName != null)
366 if (String.Compare(resWriter.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0)
368 // Cannot have two dynamic module with the same name
369 throw new ArgumentException(Environment.GetResourceString("Argument_DuplicatedFileName"));
376 // Helper to look up which module that assembly is supposed to be stored at
380 internal ModuleBuilder FindModuleWithFileName(String strFileName)
382 int size = m_moduleBuilderList.Count;
384 for (i = 0; i < size; i++)
386 ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
387 if (moduleBuilder.m_moduleData.m_strFileName != null)
389 if (String.Compare(moduleBuilder.m_moduleData.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0)
391 return moduleBuilder;
398 // Helper to look up module by name.
402 internal ModuleBuilder FindModuleWithName(String strName)
404 int size = m_moduleBuilderList.Count;
406 for (i = 0; i < size; i++)
408 ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
409 if (moduleBuilder.m_moduleData.m_strModuleName != null)
411 if (String.Compare(moduleBuilder.m_moduleData.m_strModuleName, strName, StringComparison.OrdinalIgnoreCase) == 0)
412 return moduleBuilder;
419 // add type to public COMType tracking list
420 internal void AddPublicComType(Type type)
422 BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.AddPublicComType( " + type.FullName + " )");
423 if (m_isSaved == true)
425 // assembly has been saved before!
426 throw new InvalidOperationException(Environment.GetResourceString(
427 "InvalidOperation_CannotAlterAssembly"));
429 EnsurePublicComTypeCapacity();
430 m_publicComTypeList[m_iPublicComTypeCount] = type;
431 m_iPublicComTypeCount++;
434 // add security permission requests
435 internal void AddPermissionRequests(
436 PermissionSet required,
437 PermissionSet optional,
438 PermissionSet refused)
440 BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.AddPermissionRequests");
441 if (m_isSaved == true)
443 // assembly has been saved before!
444 throw new InvalidOperationException(Environment.GetResourceString(
445 "InvalidOperation_CannotAlterAssembly"));
447 m_RequiredPset = required;
448 m_OptionalPset = optional;
449 m_RefusedPset = refused;
452 private void EnsurePublicComTypeCapacity()
454 if (m_publicComTypeList == null)
456 m_publicComTypeList = new Type[m_iInitialSize];
458 if (m_iPublicComTypeCount == m_publicComTypeList.Length)
460 Type[] tempTypeList = new Type[m_iPublicComTypeCount * 2];
461 Array.Copy(m_publicComTypeList, tempTypeList, m_iPublicComTypeCount);
462 m_publicComTypeList = tempTypeList;
466 internal List<ModuleBuilder> m_moduleBuilderList;
467 internal List<ResWriterData> m_resWriterList;
468 internal String m_strAssemblyName;
469 internal AssemblyBuilderAccess m_access;
470 private InternalAssemblyBuilder m_assembly;
472 internal Type[] m_publicComTypeList;
473 internal int m_iPublicComTypeCount;
475 internal bool m_isSaved;
476 internal const int m_iInitialSize = 16;
477 internal String m_strDir;
479 // hard coding the assembly def token
480 internal const int m_tkAssembly = 0x20000001;
482 // Security permission requests
483 internal PermissionSet m_RequiredPset;
484 internal PermissionSet m_OptionalPset;
485 internal PermissionSet m_RefusedPset;
487 // tracking AssemblyDef's CAs for persistence to disk
488 internal CustomAttributeBuilder[] m_CABuilders;
489 internal int m_iCABuilder;
490 internal byte[][] m_CABytes;
491 internal ConstructorInfo[] m_CACons;
493 internal PEFileKinds m_peFileKind; // assembly file kind
494 internal MethodInfo m_entryPointMethod;
495 internal Assembly m_ISymWrapperAssembly;
498 internal ModuleBuilder m_entryPointModule;
499 #endif //!FEATURE_CORECLR
502 // For unmanaged resources
503 internal String m_strResourceFileName;
504 internal byte[] m_resourceBytes;
505 internal NativeVersionInfo m_nativeVersion;
506 internal bool m_hasUnmanagedVersionInfo;
507 internal bool m_OverrideUnmanagedVersionInfo;
508 #endif // !FEATURE_PAL
513 /**********************************************
515 * Internal structure to track the list of ResourceWriter for
516 * AssemblyBuilder & ModuleBuilder.
518 **********************************************/
519 internal class ResWriterData
522 internal ResWriterData(
523 IResourceWriter resWriter,
527 String strFullFileName,
528 ResourceAttributes attribute)
530 m_resWriter = resWriter;
531 m_memoryStream = memoryStream;
533 m_strFileName = strFileName;
534 m_strFullFileName = strFullFileName;
535 m_nextResWriter = null;
536 m_attribute = attribute;
539 internal ResWriterData(
540 ResourceWriter resWriter,
544 String strFullFileName,
545 ResourceAttributes attribute)
547 m_resWriter = resWriter;
548 m_memoryStream = memoryStream;
550 m_strFileName = strFileName;
551 m_strFullFileName = strFullFileName;
552 m_nextResWriter = null;
553 m_attribute = attribute;
557 internal ResourceWriter m_resWriter;
558 #else // FEATURE_CORECLR
559 internal IResourceWriter m_resWriter;
560 #endif // !FEATURE_CORECLR
561 internal String m_strName;
562 internal String m_strFileName;
563 internal String m_strFullFileName;
564 internal Stream m_memoryStream;
565 internal ResWriterData m_nextResWriter;
566 internal ResourceAttributes m_attribute;
570 internal class NativeVersionInfo
572 internal NativeVersionInfo()
574 m_strDescription = null;
577 m_strCopyright = null;
578 m_strTrademark = null;
580 m_strProductVersion = null;
581 m_strFileVersion = null;
585 internal String m_strDescription;
586 internal String m_strCompany;
587 internal String m_strTitle;
588 internal String m_strCopyright;
589 internal String m_strTrademark;
590 internal String m_strProduct;
591 internal String m_strProductVersion;
592 internal String m_strFileVersion;
595 #endif //!FEATURE_PAL