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)]
AssemblyBuilderData( InternalAssemblyBuilder assembly, String strAssemblyName, AssemblyBuilderAccess access, String dir)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)]
AddModule(ModuleBuilder dynModule)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
AddResWriter(ResWriterData resData)68         internal void AddResWriter(ResWriterData resData)
69         {
70             m_resWriterList.Add(resData);
71         }
72 
73 
74         // Helper to track CAs to persist onto disk
AddCustomAttribute(CustomAttributeBuilder customBuilder)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
AddCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)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
FillUnmanagedVersionInfo()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
CheckResNameConflict(String strNewResName)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)]
CheckNameConflict(String strNewModuleName)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
CheckTypeNameConflict(String strTypeName, TypeBuilder enclosingType)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         //
CheckFileNameConflict(String strFileName)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         //
FindModuleWithFileName(String strFileName)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         //
FindModuleWithName(String strName)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
AddPublicComType(Type type)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
AddPermissionRequests( PermissionSet required, PermissionSet optional, PermissionSet refused)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 
EnsurePublicComTypeCapacity()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
ResWriterData( IResourceWriter resWriter, Stream memoryStream, String strName, String strFileName, String strFullFileName, ResourceAttributes attribute)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     {
NativeVersionInfo()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 }
598