Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / reflection / emit / assemblybuilderdata.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 ////////////////////////////////////////////////////////////////////////////////
7 ////////////////////////////////////////////////////////////////////////////////
8 // <OWNER>Microsoft</OWNER>
9 // 
10
11 namespace System.Reflection.Emit {
12     using System;
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;
19 #if !FEATURE_CORECLR
20     using ResourceWriter = System.Resources.ResourceWriter;
21 #else // FEATURE_CORECLR
22     using IResourceWriter = System.Resources.IResourceWriter;
23 #endif // !FEATURE_CORECLR
24     using System.IO;
25     using System.Runtime.Versioning;
26     using System.Diagnostics.SymbolStore;
27     using System.Diagnostics.Contracts;
28
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
33     {
34         [SecurityCritical]
35         [ResourceExposure(ResourceScope.Machine)]
36         [ResourceConsumption(ResourceScope.Machine)]
37         internal AssemblyBuilderData(
38             InternalAssemblyBuilder assembly, 
39             String                  strAssemblyName, 
40             AssemblyBuilderAccess   access,
41             String                  dir)
42         {
43             m_assembly = assembly;
44             m_strAssemblyName = strAssemblyName;
45             m_access = access;
46             m_moduleBuilderList = new List<ModuleBuilder>();
47             m_resWriterList = new List<ResWriterData>();
48
49             //Init to null/0 done for you by the CLR.  FXCop has spoken
50
51             if (dir == null && access != AssemblyBuilderAccess.Run)
52                 m_strDir = Environment.CurrentDirectory;
53             else
54                 m_strDir = dir;
55
56             m_peFileKind = PEFileKinds.Dll;
57          }
58     
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)
63         {
64             m_moduleBuilderList.Add(dynModule);
65         }
66     
67         // Helper to add a resource information into the tracking list
68         internal void AddResWriter(ResWriterData resData)
69         {
70             m_resWriterList.Add(resData);
71         }
72
73
74         // Helper to track CAs to persist onto disk
75         internal void AddCustomAttribute(CustomAttributeBuilder customBuilder)
76         {
77
78             // make sure we have room for this CA
79             if (m_CABuilders == null)
80             {
81                 m_CABuilders = new CustomAttributeBuilder[m_iInitialSize];
82             }
83             if (m_iCABuilder == m_CABuilders.Length)
84             {
85                 CustomAttributeBuilder[]  tempCABuilders = new CustomAttributeBuilder[m_iCABuilder * 2];
86                 Array.Copy(m_CABuilders, tempCABuilders, m_iCABuilder);
87                 m_CABuilders = tempCABuilders;            
88             }
89             m_CABuilders[m_iCABuilder] = customBuilder;
90             
91             m_iCABuilder++;
92         }
93
94         // Helper to track CAs to persist onto disk
95         internal void AddCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
96         {
97
98             // make sure we have room for this CA
99             if (m_CABytes == null)
100             {
101                 m_CABytes = new byte[m_iInitialSize][];
102                 m_CACons = new ConstructorInfo[m_iInitialSize];                
103             }
104             if (m_iCAs == m_CABytes.Length)
105             {
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++)
110                 {
111                     temp[i] = m_CABytes[i];
112                     tempCon[i] = m_CACons[i];
113                 }
114                 m_CABytes = temp;
115                 m_CACons = tempCon;
116             }
117
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;
122             m_iCAs++;
123         }
124
125 #if !FEATURE_PAL        
126         // Helper to calculate unmanaged version info from Assembly's custom attributes.
127         // If DefineUnmanagedVersionInfo is called, the parameter provided will override
128         // the CA's value.
129         //                      
130         [System.Security.SecurityCritical]  // auto-generated
131         internal void FillUnmanagedVersionInfo()
132         {
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. 
136             //
137             CultureInfo locale = m_assembly.GetLocale();
138 #if FEATURE_USE_LCID            
139             if (locale != null)
140                 m_nativeVersion.m_lcid = locale.LCID;
141 #endif            
142                                                     
143             for (int i = 0; i < m_iCABuilder; i++)
144             {
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)
148                     continue;
149
150                 if (conType.Equals(typeof(System.Reflection.AssemblyCopyrightAttribute)))
151                 {
152                         // assert that we should only have one argument for this CA and the type should
153                         // be a string.
154                         // 
155                     if (m_CABuilders[i].m_constructorArgs.Length != 1)
156                     {
157                         throw new ArgumentException(Environment.GetResourceString(
158                             "Argument_BadCAForUnmngRSC",
159                             m_CABuilders[i].m_con.ReflectedType.Name));
160                     }
161                     if (m_OverrideUnmanagedVersionInfo == false)
162                     {
163                         m_nativeVersion.m_strCopyright = m_CABuilders[i].m_constructorArgs[0].ToString();
164                     }
165                 }
166                 else if (conType.Equals(typeof(System.Reflection.AssemblyTrademarkAttribute))) 
167                 {
168                         // assert that we should only have one argument for this CA and the type should
169                         // be a string.
170                         // 
171                     if (m_CABuilders[i].m_constructorArgs.Length != 1)
172                     {
173                         throw new ArgumentException(Environment.GetResourceString(
174                             "Argument_BadCAForUnmngRSC",
175                             m_CABuilders[i].m_con.ReflectedType.Name));
176                     }
177                     if (m_OverrideUnmanagedVersionInfo == false)
178                     {
179                         m_nativeVersion.m_strTrademark = m_CABuilders[i].m_constructorArgs[0].ToString();
180                     }
181                 }
182                 else if (conType.Equals(typeof(System.Reflection.AssemblyProductAttribute))) 
183                 {
184                     if (m_OverrideUnmanagedVersionInfo == false)
185                     {
186                         // assert that we should only have one argument for this CA and the type should
187                         // be a string.
188                         // 
189                         m_nativeVersion.m_strProduct = m_CABuilders[i].m_constructorArgs[0].ToString();
190                     }
191                 }
192                 else if (conType.Equals(typeof(System.Reflection.AssemblyCompanyAttribute))) 
193                 {
194                     if (m_CABuilders[i].m_constructorArgs.Length != 1)
195                     {
196                         throw new ArgumentException(Environment.GetResourceString(
197                             "Argument_BadCAForUnmngRSC",
198                             m_CABuilders[i].m_con.ReflectedType.Name));
199                     }
200                     if (m_OverrideUnmanagedVersionInfo == false)
201                     {
202                         // assert that we should only have one argument for this CA and the type should
203                         // be a string.
204                         // 
205                         m_nativeVersion.m_strCompany = m_CABuilders[i].m_constructorArgs[0].ToString();
206                     }
207                 }
208                 else if (conType.Equals(typeof(System.Reflection.AssemblyDescriptionAttribute))) 
209                 {
210                     if (m_CABuilders[i].m_constructorArgs.Length != 1)
211                     {
212                         throw new ArgumentException(Environment.GetResourceString(
213                             "Argument_BadCAForUnmngRSC",
214                             m_CABuilders[i].m_con.ReflectedType.Name));
215                     }
216                     m_nativeVersion.m_strDescription = m_CABuilders[i].m_constructorArgs[0].ToString();
217                 }
218                 else if (conType.Equals(typeof(System.Reflection.AssemblyTitleAttribute))) 
219                 {
220                     if (m_CABuilders[i].m_constructorArgs.Length != 1)
221                     {
222                         throw new ArgumentException(Environment.GetResourceString(
223                             "Argument_BadCAForUnmngRSC",
224                             m_CABuilders[i].m_con.ReflectedType.Name));
225                     }
226                     m_nativeVersion.m_strTitle = m_CABuilders[i].m_constructorArgs[0].ToString();
227                 }
228                 else if (conType.Equals(typeof(System.Reflection.AssemblyInformationalVersionAttribute))) 
229                 {
230                     if (m_CABuilders[i].m_constructorArgs.Length != 1)
231                     {
232                         throw new ArgumentException(Environment.GetResourceString(
233                             "Argument_BadCAForUnmngRSC",
234                             m_CABuilders[i].m_con.ReflectedType.Name));
235                     }
236                     if (m_OverrideUnmanagedVersionInfo == false)
237                     {
238                         m_nativeVersion.m_strProductVersion = m_CABuilders[i].m_constructorArgs[0].ToString();
239                     }
240                 }
241                 else if (conType.Equals(typeof(System.Reflection.AssemblyCultureAttribute))) 
242                 {
243                     // retrieve the LCID
244                     if (m_CABuilders[i].m_constructorArgs.Length != 1)
245                     {
246                         throw new ArgumentException(Environment.GetResourceString(
247                             "Argument_BadCAForUnmngRSC",
248                             m_CABuilders[i].m_con.ReflectedType.Name));
249                     }
250                     // CultureInfo attribute overrides the lcid from AssemblyName.                                      
251                     CultureInfo culture = new CultureInfo(m_CABuilders[i].m_constructorArgs[0].ToString());
252 #if FEATURE_USE_LCID                    
253                     m_nativeVersion.m_lcid = culture.LCID;
254 #endif
255                 }
256                 else if (conType.Equals(typeof(System.Reflection.AssemblyFileVersionAttribute))) 
257                 {
258                     if (m_CABuilders[i].m_constructorArgs.Length != 1)
259                     {
260                         throw new ArgumentException(Environment.GetResourceString(
261                             "Argument_BadCAForUnmngRSC",
262                             m_CABuilders[i].m_con.ReflectedType.Name));
263                     }
264                     if (m_OverrideUnmanagedVersionInfo == false)
265                     {
266                         m_nativeVersion.m_strFileVersion = m_CABuilders[i].m_constructorArgs[0].ToString();
267                     }
268                 }
269             }
270         }
271 #endif //!FEATURE_PAL
272         
273         // Helper to ensure the resource name is unique underneath assemblyBuilder
274         internal void CheckResNameConflict(String strNewResName)
275         {
276             int         size = m_resWriterList.Count;
277             int         i;
278             for (i = 0; i < size; i++) 
279             {
280                 ResWriterData resWriter = m_resWriterList[i];
281                 if (resWriter.m_strName.Equals(strNewResName))
282                 {
283                     // Cannot have two resources with the same name
284                     throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateResourceName"));
285                 }
286             }        
287         }
288
289     
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)
294         {
295             int         size = m_moduleBuilderList.Count;
296             int         i;
297             for (i = 0; i < size; i++) 
298             {
299                 ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
300                 if (moduleBuilder.m_moduleData.m_strModuleName.Equals(strNewModuleName))
301                 {
302                     // Cannot have two dynamic modules with the same name
303                     throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateModuleName"));
304                 }
305             }
306
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 
309             // with this:
310             //  if (m_assembly.GetModule(strNewModuleName) != null)
311             //  {
312             //      // Cannot have two dynamic modules with the same name
313             //      throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateModuleName"));
314             //  }
315         }
316     
317         // Helper to ensure the type name is unique underneath assemblyBuilder
318         internal void CheckTypeNameConflict(String strTypeName, TypeBuilder enclosingType)
319         {
320             BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.CheckTypeNameConflict( " + strTypeName + " )"); 
321             for (int i = 0; i < m_moduleBuilderList.Count; i++) 
322             {
323                 ModuleBuilder curModule = m_moduleBuilderList[i];
324                 curModule.CheckTypeNameConflict(strTypeName, enclosingType);
325             }
326
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)
332             //      {
333             //          // Cannot have two types with the same name
334             //          throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateTypeName"));
335             //      }
336         }
337         
338
339         // Helper to ensure the file name is unique underneath assemblyBuilder. This includes 
340         // modules and resources.
341         //  
342         //  
343         //  
344         internal void CheckFileNameConflict(String strFileName)
345         {
346             int         size = m_moduleBuilderList.Count;
347             int         i;
348             for (i = 0; i < size; i++) 
349             {
350                 ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
351                 if (moduleBuilder.m_moduleData.m_strFileName != null)
352                 {
353                     if (String.Compare(moduleBuilder.m_moduleData.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0)
354                     {
355                         // Cannot have two dynamic module with the same name
356                         throw new ArgumentException(Environment.GetResourceString("Argument_DuplicatedFileName"));
357                     }
358                 }
359             }    
360             size = m_resWriterList.Count;
361             for (i = 0; i < size; i++) 
362             {
363                 ResWriterData resWriter = m_resWriterList[i];
364                 if (resWriter.m_strFileName != null)
365                 {
366                     if (String.Compare(resWriter.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0)
367                     {
368                         // Cannot have two dynamic module with the same name
369                         throw new ArgumentException(Environment.GetResourceString("Argument_DuplicatedFileName"));
370                     }
371                 }
372             }    
373
374         }
375     
376         // Helper to look up which module that assembly is supposed to be stored at
377         //  
378         // 
379         //  
380         internal ModuleBuilder FindModuleWithFileName(String strFileName)
381         {
382             int         size = m_moduleBuilderList.Count;
383             int         i;
384             for (i = 0; i < size; i++) 
385             {
386                 ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
387                 if (moduleBuilder.m_moduleData.m_strFileName != null)
388                 {
389                     if (String.Compare(moduleBuilder.m_moduleData.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0)
390                     {
391                         return moduleBuilder;
392                     }
393                 }
394             } 
395             return null;       
396         }
397
398         // Helper to look up module by name.
399         //  
400         // 
401         //  
402         internal ModuleBuilder FindModuleWithName(String strName)
403         {
404             int         size = m_moduleBuilderList.Count;
405             int         i;
406             for (i = 0; i < size; i++) 
407             {
408                 ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
409                 if (moduleBuilder.m_moduleData.m_strModuleName != null)
410                 {
411                     if (String.Compare(moduleBuilder.m_moduleData.m_strModuleName, strName, StringComparison.OrdinalIgnoreCase) == 0)
412                         return moduleBuilder;
413                 }
414             } 
415             return null;       
416         }
417
418         
419         // add type to public COMType tracking list
420         internal void AddPublicComType(Type type)
421         {
422             BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.AddPublicComType( " + type.FullName + " )"); 
423             if (m_isSaved == true)
424             {
425                 // assembly has been saved before!
426                 throw new InvalidOperationException(Environment.GetResourceString(
427                     "InvalidOperation_CannotAlterAssembly"));
428             }        
429             EnsurePublicComTypeCapacity();
430             m_publicComTypeList[m_iPublicComTypeCount] = type;
431             m_iPublicComTypeCount++;
432         }
433         
434         // add security permission requests
435         internal void AddPermissionRequests(
436             PermissionSet       required,
437             PermissionSet       optional,
438             PermissionSet       refused)
439         {
440             BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.AddPermissionRequests");
441             if (m_isSaved == true)
442             {
443                 // assembly has been saved before!
444                 throw new InvalidOperationException(Environment.GetResourceString(
445                     "InvalidOperation_CannotAlterAssembly"));
446             }        
447             m_RequiredPset = required;
448             m_OptionalPset = optional;
449             m_RefusedPset = refused;
450         }
451         
452         private void EnsurePublicComTypeCapacity()
453         {
454             if (m_publicComTypeList == null)
455             {
456                 m_publicComTypeList = new Type[m_iInitialSize];
457             }
458             if (m_iPublicComTypeCount == m_publicComTypeList.Length)
459             {
460                 Type[]  tempTypeList = new Type[m_iPublicComTypeCount * 2];
461                 Array.Copy(m_publicComTypeList, tempTypeList, m_iPublicComTypeCount);
462                 m_publicComTypeList = tempTypeList;            
463             }
464         }
465          
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;
471         
472         internal Type[]                 m_publicComTypeList;
473         internal int                    m_iPublicComTypeCount;
474         
475         internal bool                   m_isSaved;    
476         internal const int              m_iInitialSize = 16;
477         internal String                 m_strDir;
478
479         // hard coding the assembly def token
480         internal const int              m_tkAssembly = 0x20000001;
481     
482         // Security permission requests
483         internal PermissionSet          m_RequiredPset;
484         internal PermissionSet          m_OptionalPset;
485         internal PermissionSet          m_RefusedPset;
486         
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;
492         internal int                    m_iCAs;
493         internal PEFileKinds            m_peFileKind;           // assembly file kind
494         internal MethodInfo             m_entryPointMethod;
495         internal Assembly               m_ISymWrapperAssembly;
496
497 #if !FEATURE_CORECLR
498         internal ModuleBuilder          m_entryPointModule;
499 #endif //!FEATURE_CORECLR
500                                   
501 #if !FEATURE_PAL
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
509
510     }
511
512     
513     /**********************************************
514     *
515     * Internal structure to track the list of ResourceWriter for
516     * AssemblyBuilder & ModuleBuilder.
517     *
518     **********************************************/
519     internal class ResWriterData 
520     {
521 #if FEATURE_CORECLR
522         internal ResWriterData(
523             IResourceWriter  resWriter,
524             Stream          memoryStream,
525             String          strName,
526             String          strFileName,
527             String          strFullFileName,
528             ResourceAttributes attribute)
529         {
530             m_resWriter = resWriter;
531             m_memoryStream = memoryStream;
532             m_strName = strName;
533             m_strFileName = strFileName;
534             m_strFullFileName = strFullFileName;
535             m_nextResWriter = null;
536             m_attribute = attribute;
537         }
538 #else
539         internal ResWriterData(
540             ResourceWriter  resWriter,
541             Stream          memoryStream,
542             String          strName,
543             String          strFileName,
544             String          strFullFileName,
545             ResourceAttributes attribute)
546         {
547             m_resWriter = resWriter;
548             m_memoryStream = memoryStream;
549             m_strName = strName;
550             m_strFileName = strFileName;
551             m_strFullFileName = strFullFileName;
552             m_nextResWriter = null;
553             m_attribute = attribute;
554         }
555 #endif
556 #if !FEATURE_CORECLR
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;
567     }
568
569 #if !FEATURE_PAL
570     internal class NativeVersionInfo
571     {
572         internal NativeVersionInfo()
573         {
574             m_strDescription = null;
575             m_strCompany = null;
576             m_strTitle = null;
577             m_strCopyright = null;
578             m_strTrademark = null;
579             m_strProduct = null;
580             m_strProductVersion = null;
581             m_strFileVersion = null;
582             m_lcid = -1;
583         }
584         
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;
593         internal int        m_lcid;
594     }
595 #endif //!FEATURE_PAL
596
597 }