1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 //
8 
9 namespace System.Reflection.Emit
10 {
11     using System.Text;
12     using System;
13     using System.Diagnostics.Contracts;
14     using System.Reflection;
15     using System.Runtime.CompilerServices;
16     using System.Runtime.InteropServices;
17     using System.Runtime.Versioning;
18     using System.Security.Permissions;
19 
20     [ClassInterface(ClassInterfaceType.None)]
21     [ComDefaultInterface(typeof(_SignatureHelper))]
22 [System.Runtime.InteropServices.ComVisible(true)]
23     public sealed class SignatureHelper : _SignatureHelper
24     {
25         #region Consts Fields
26         private const int NO_SIZE_IN_SIG = -1;
27         #endregion
28 
29         #region Static Members
30         [System.Security.SecuritySafeCritical]  // auto-generated
GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes)31         public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes)
32         {
33             return GetMethodSigHelper(mod, CallingConventions.Standard, returnType, null, null, parameterTypes, null, null);
34         }
35 
36         [System.Security.SecurityCritical]  // auto-generated
GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType, int cGenericParam)37         internal static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType, int cGenericParam)
38         {
39             return GetMethodSigHelper(mod, callingConvention, cGenericParam, returnType, null, null, null, null, null);
40         }
41 
42         [System.Security.SecuritySafeCritical]  // auto-generated
GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType)43         public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType)
44         {
45             return GetMethodSigHelper(mod, callingConvention, returnType, null, null, null, null, null);
46         }
47 
GetMethodSpecSigHelper(Module scope, Type[] inst)48         internal static SignatureHelper GetMethodSpecSigHelper(Module scope, Type[] inst)
49         {
50             SignatureHelper sigHelp = new SignatureHelper(scope, MdSigCallingConvention.GenericInst);
51             sigHelp.AddData(inst.Length);
52             foreach(Type t in inst)
53                 sigHelp.AddArgument(t);
54             return sigHelp;
55         }
56 
57         [System.Security.SecurityCritical]  // auto-generated
GetMethodSigHelper( Module scope, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)58         internal static SignatureHelper GetMethodSigHelper(
59             Module scope, CallingConventions callingConvention,
60             Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
61             Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
62         {
63             return GetMethodSigHelper(scope, callingConvention, 0, returnType, requiredReturnTypeCustomModifiers,
64                 optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
65         }
66 
67         [System.Security.SecurityCritical]  // auto-generated
GetMethodSigHelper( Module scope, CallingConventions callingConvention, int cGenericParam, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)68         internal static SignatureHelper GetMethodSigHelper(
69             Module scope, CallingConventions callingConvention, int cGenericParam,
70             Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
71             Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
72         {
73             SignatureHelper sigHelp;
74             MdSigCallingConvention intCall;
75 
76             if (returnType == null)
77             {
78                 returnType = typeof(void);
79             }
80 
81             intCall = MdSigCallingConvention.Default;
82 
83             if ((callingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
84                 intCall = MdSigCallingConvention.Vararg;
85 
86             if (cGenericParam > 0)
87             {
88                 intCall |= MdSigCallingConvention.Generic;
89             }
90 
91             if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis)
92                 intCall |= MdSigCallingConvention.HasThis;
93 
94             sigHelp = new SignatureHelper(scope, intCall, cGenericParam, returnType,
95                                             requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers);
96             sigHelp.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
97 
98             return sigHelp;
99         }
100 
101         [System.Security.SecuritySafeCritical]  // auto-generated
GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType)102         public static SignatureHelper GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType)
103         {
104             SignatureHelper sigHelp;
105             MdSigCallingConvention intCall;
106 
107             if (returnType == null)
108                 returnType = typeof(void);
109 
110             if (unmanagedCallConv == CallingConvention.Cdecl)
111             {
112                 intCall = MdSigCallingConvention.C;
113             }
114             else if (unmanagedCallConv == CallingConvention.StdCall || unmanagedCallConv == CallingConvention.Winapi)
115             {
116                 intCall = MdSigCallingConvention.StdCall;
117             }
118             else if (unmanagedCallConv == CallingConvention.ThisCall)
119             {
120                 intCall = MdSigCallingConvention.ThisCall;
121             }
122             else if (unmanagedCallConv == CallingConvention.FastCall)
123             {
124                 intCall = MdSigCallingConvention.FastCall;
125             }
126             else
127             {
128                 throw new ArgumentException(Environment.GetResourceString("Argument_UnknownUnmanagedCallConv"), "unmanagedCallConv");
129             }
130 
131             sigHelp = new SignatureHelper(mod, intCall, returnType, null, null);
132 
133             return sigHelp;
134         }
135 
GetLocalVarSigHelper()136         public static SignatureHelper GetLocalVarSigHelper()
137         {
138             return GetLocalVarSigHelper(null);
139         }
140 
GetMethodSigHelper(CallingConventions callingConvention, Type returnType)141         public static SignatureHelper GetMethodSigHelper(CallingConventions callingConvention, Type returnType)
142         {
143             return GetMethodSigHelper(null, callingConvention, returnType);
144         }
145 
GetMethodSigHelper(CallingConvention unmanagedCallingConvention, Type returnType)146         public static SignatureHelper GetMethodSigHelper(CallingConvention unmanagedCallingConvention, Type returnType)
147         {
148             return GetMethodSigHelper(null, unmanagedCallingConvention, returnType);
149         }
150 
GetLocalVarSigHelper(Module mod)151         public static SignatureHelper GetLocalVarSigHelper(Module mod)
152         {
153             return new SignatureHelper(mod, MdSigCallingConvention.LocalSig);
154         }
155 
GetFieldSigHelper(Module mod)156         public static SignatureHelper GetFieldSigHelper(Module mod)
157         {
158             return new SignatureHelper(mod, MdSigCallingConvention.Field);
159         }
160 
GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes)161         public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes)
162         {
163             return GetPropertySigHelper(mod, returnType, null, null, parameterTypes, null, null);
164         }
165 
GetPropertySigHelper(Module mod, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)166         public static SignatureHelper GetPropertySigHelper(Module mod,
167             Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
168             Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
169         {
170             return GetPropertySigHelper(mod, (CallingConventions)0, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers,
171                 parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
172         }
173         [System.Security.SecuritySafeCritical]  // auto-generated
GetPropertySigHelper(Module mod, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)174         public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention,
175             Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
176             Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
177         {
178             SignatureHelper sigHelp;
179 
180             if (returnType == null)
181             {
182                 returnType = typeof(void);
183             }
184 
185             MdSigCallingConvention intCall = MdSigCallingConvention.Property;
186 
187             if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis)
188                 intCall |= MdSigCallingConvention.HasThis;
189 
190             sigHelp = new SignatureHelper(mod, intCall,
191                 returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers);
192             sigHelp.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
193 
194             return sigHelp;
195         }
196 
197         [System.Security.SecurityCritical]  // auto-generated
GetTypeSigToken(Module mod, Type type)198         internal static SignatureHelper GetTypeSigToken(Module mod, Type type)
199         {
200             if (mod == null)
201                 throw new ArgumentNullException("module");
202 
203             if (type == null)
204                 throw new ArgumentNullException("type");
205 
206             return new SignatureHelper(mod, type);
207         }
208         #endregion
209 
210         #region Private Data Members
211         private byte[] m_signature;
212         private int m_currSig; // index into m_signature buffer for next available byte
213         private int m_sizeLoc; // index into m_signature buffer to put m_argCount (will be NO_SIZE_IN_SIG if no arg count is needed)
214         private ModuleBuilder m_module;
215         private bool m_sigDone;
216         private int m_argCount; // tracking number of arguments in the signature
217         #endregion
218 
219         #region Constructor
SignatureHelper(Module mod, MdSigCallingConvention callingConvention)220         private SignatureHelper(Module mod, MdSigCallingConvention callingConvention)
221         {
222             // Use this constructor to instantiate a local var sig  or Field where return type is not applied.
223             Init(mod, callingConvention);
224         }
225 
226         [System.Security.SecurityCritical]  // auto-generated
SignatureHelper(Module mod, MdSigCallingConvention callingConvention, int cGenericParameters, Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)227         private SignatureHelper(Module mod, MdSigCallingConvention callingConvention, int cGenericParameters,
228             Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
229         {
230             // Use this constructor to instantiate a any signatures that will require a return type.
231             Init(mod, callingConvention, cGenericParameters);
232 
233             if (callingConvention == MdSigCallingConvention.Field)
234                 throw new ArgumentException(Environment.GetResourceString("Argument_BadFieldSig"));
235 
236             AddOneArgTypeHelper(returnType, requiredCustomModifiers, optionalCustomModifiers);
237         }
238 
239         [System.Security.SecurityCritical]  // auto-generated
SignatureHelper(Module mod, MdSigCallingConvention callingConvention, Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)240         private SignatureHelper(Module mod, MdSigCallingConvention callingConvention,
241             Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
242             : this(mod, callingConvention, 0, returnType, requiredCustomModifiers, optionalCustomModifiers)
243         {
244         }
245 
246         [System.Security.SecurityCritical]  // auto-generated
SignatureHelper(Module mod, Type type)247         private SignatureHelper(Module mod, Type type)
248         {
249             Init(mod);
250 
251             AddOneArgTypeHelper(type);
252         }
253 
Init(Module mod)254         private void Init(Module mod)
255         {
256             m_signature = new byte[32];
257             m_currSig = 0;
258             m_module = mod as ModuleBuilder;
259             m_argCount = 0;
260             m_sigDone = false;
261             m_sizeLoc = NO_SIZE_IN_SIG;
262 
263             if (m_module == null && mod != null)
264                 throw new ArgumentException(Environment.GetResourceString("NotSupported_MustBeModuleBuilder"));
265         }
266 
Init(Module mod, MdSigCallingConvention callingConvention)267         private void Init(Module mod, MdSigCallingConvention callingConvention)
268         {
269             Init(mod, callingConvention, 0);
270         }
271 
Init(Module mod, MdSigCallingConvention callingConvention, int cGenericParam)272         private void Init(Module mod, MdSigCallingConvention callingConvention, int cGenericParam)
273         {
274             Init(mod);
275 
276             AddData((byte)callingConvention);
277 
278             if (callingConvention == MdSigCallingConvention.Field ||
279                 callingConvention == MdSigCallingConvention.GenericInst)
280             {
281                 m_sizeLoc = NO_SIZE_IN_SIG;
282             }
283             else
284             {
285                 if (cGenericParam > 0)
286                     AddData(cGenericParam);
287 
288                 m_sizeLoc = m_currSig++;
289             }
290         }
291 
292         #endregion
293 
294         #region Private Members
295         [System.Security.SecurityCritical]  // auto-generated
AddOneArgTypeHelper(Type argument, bool pinned)296         private void AddOneArgTypeHelper(Type argument, bool pinned)
297         {
298             if (pinned)
299                 AddElementType(CorElementType.Pinned);
300 
301             AddOneArgTypeHelper(argument);
302         }
303 
304         [System.Security.SecurityCritical]  // auto-generated
AddOneArgTypeHelper(Type clsArgument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)305         private void AddOneArgTypeHelper(Type clsArgument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
306         {
307             // This function will not increase the argument count. It only fills in bytes
308             // in the signature based on clsArgument. This helper is called for return type.
309 
310             Contract.Requires(clsArgument != null);
311             Contract.Requires((optionalCustomModifiers == null && requiredCustomModifiers == null) || !clsArgument.ContainsGenericParameters);
312 
313             if (optionalCustomModifiers != null)
314             {
315                 for (int i = 0; i < optionalCustomModifiers.Length; i++)
316                 {
317                     Type t = optionalCustomModifiers[i];
318 
319                     if (t == null)
320                         throw new ArgumentNullException("optionalCustomModifiers");
321 
322                     if (t.HasElementType)
323                         throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), "optionalCustomModifiers");
324 
325                     if (t.ContainsGenericParameters)
326                         throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "optionalCustomModifiers");
327 
328                     AddElementType(CorElementType.CModOpt);
329 
330                     int token = m_module.GetTypeToken(t).Token;
331                     Contract.Assert(!MetadataToken.IsNullToken(token));
332                     AddToken(token);
333                 }
334             }
335 
336             if (requiredCustomModifiers != null)
337             {
338                 for (int i = 0; i < requiredCustomModifiers.Length; i++)
339                 {
340                     Type t = requiredCustomModifiers[i];
341 
342                     if (t == null)
343                         throw new ArgumentNullException("requiredCustomModifiers");
344 
345                     if (t.HasElementType)
346                         throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), "requiredCustomModifiers");
347 
348                     if (t.ContainsGenericParameters)
349                         throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "requiredCustomModifiers");
350 
351                     AddElementType(CorElementType.CModReqd);
352 
353                     int token = m_module.GetTypeToken(t).Token;
354                     Contract.Assert(!MetadataToken.IsNullToken(token));
355                     AddToken(token);
356                 }
357             }
358 
359             AddOneArgTypeHelper(clsArgument);
360         }
361 
362         [System.Security.SecurityCritical]  // auto-generated
AddOneArgTypeHelper(Type clsArgument)363         private void AddOneArgTypeHelper(Type clsArgument) { AddOneArgTypeHelperWorker(clsArgument, false); }
364         [System.Security.SecurityCritical]  // auto-generated
AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst)365         private void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst)
366         {
367             if (clsArgument.IsGenericParameter)
368             {
369                 if (clsArgument.DeclaringMethod != null)
370                     AddElementType(CorElementType.MVar);
371                 else
372                     AddElementType(CorElementType.Var);
373 
374                 AddData(clsArgument.GenericParameterPosition);
375             }
376             else if (clsArgument.IsGenericType && (!clsArgument.IsGenericTypeDefinition || !lastWasGenericInst))
377             {
378                 AddElementType(CorElementType.GenericInst);
379 
380                 AddOneArgTypeHelperWorker(clsArgument.GetGenericTypeDefinition(), true);
381 
382                 Type[] args = clsArgument.GetGenericArguments();
383 
384                 AddData(args.Length);
385 
386                 foreach (Type t in args)
387                     AddOneArgTypeHelper(t);
388             }
389             else if (clsArgument is TypeBuilder)
390             {
391                 TypeBuilder clsBuilder = (TypeBuilder)clsArgument;
392                 TypeToken tkType;
393 
394                 if (clsBuilder.Module.Equals(m_module))
395                 {
396                     tkType = clsBuilder.TypeToken;
397                 }
398                 else
399                 {
400                     tkType = m_module.GetTypeToken(clsArgument);
401                 }
402 
403                 if (clsArgument.IsValueType)
404                 {
405                     InternalAddTypeToken(tkType, CorElementType.ValueType);
406                 }
407                 else
408                 {
409                     InternalAddTypeToken(tkType, CorElementType.Class);
410                 }
411             }
412             else if (clsArgument is EnumBuilder)
413             {
414                 TypeBuilder clsBuilder = ((EnumBuilder)clsArgument).m_typeBuilder;
415                 TypeToken tkType;
416 
417                 if (clsBuilder.Module.Equals(m_module))
418                 {
419                     tkType = clsBuilder.TypeToken;
420                 }
421                 else
422                 {
423                     tkType = m_module.GetTypeToken(clsArgument);
424                 }
425 
426                 if (clsArgument.IsValueType)
427                 {
428                     InternalAddTypeToken(tkType, CorElementType.ValueType);
429                 }
430                 else
431                 {
432                     InternalAddTypeToken(tkType, CorElementType.Class);
433                 }
434             }
435             else if (clsArgument.IsByRef)
436             {
437                 AddElementType(CorElementType.ByRef);
438                 clsArgument = clsArgument.GetElementType();
439                 AddOneArgTypeHelper(clsArgument);
440             }
441             else if (clsArgument.IsPointer)
442             {
443                 AddElementType(CorElementType.Ptr);
444                 AddOneArgTypeHelper(clsArgument.GetElementType());
445             }
446             else if (clsArgument.IsArray)
447             {
448                 if (clsArgument.IsSzArray)
449                 {
450                     AddElementType(CorElementType.SzArray);
451 
452                     AddOneArgTypeHelper(clsArgument.GetElementType());
453                 }
454                 else
455                 {
456                     AddElementType(CorElementType.Array);
457 
458                     AddOneArgTypeHelper(clsArgument.GetElementType());
459 
460                     // put the rank information
461                     int rank = clsArgument.GetArrayRank();
462                     AddData(rank);     // rank
463                     AddData(0);     // upper bounds
464                     AddData(rank);  // lower bound
465                     for (int i = 0; i < rank; i++)
466                         AddData(0);
467                 }
468             }
469             else
470             {
471                 CorElementType type = CorElementType.Max;
472 
473                 if (clsArgument is RuntimeType)
474                 {
475                     type = RuntimeTypeHandle.GetCorElementType((RuntimeType)clsArgument);
476 
477                     //GetCorElementType returns CorElementType.Class for both object and string
478                     if (type == CorElementType.Class)
479                     {
480                         if (clsArgument == typeof(object))
481                             type = CorElementType.Object;
482                         else if (clsArgument == typeof(string))
483                             type = CorElementType.String;
484                     }
485                 }
486 
487                 if (IsSimpleType(type))
488                 {
489                     AddElementType(type);
490                 }
491                 else if (m_module == null)
492                 {
493                     InternalAddRuntimeType(clsArgument);
494                 }
495                 else if (clsArgument.IsValueType)
496                 {
497                     InternalAddTypeToken(m_module.GetTypeToken(clsArgument), CorElementType.ValueType);
498                 }
499                 else
500                 {
501                     InternalAddTypeToken(m_module.GetTypeToken(clsArgument), CorElementType.Class);
502                 }
503             }
504         }
505 
AddData(int data)506         private void AddData(int data)
507         {
508             // A managed representation of CorSigCompressData;
509 
510             if (m_currSig + 4 > m_signature.Length)
511             {
512                 m_signature = ExpandArray(m_signature);
513             }
514 
515             if (data <= 0x7F)
516             {
517                 m_signature[m_currSig++] = (byte)(data & 0xFF);
518             }
519             else if (data <= 0x3FFF)
520             {
521                 m_signature[m_currSig++] = (byte)((data >>8) | 0x80);
522                 m_signature[m_currSig++] = (byte)(data & 0xFF);
523             }
524             else if (data <= 0x1FFFFFFF)
525             {
526                 m_signature[m_currSig++] = (byte)((data >>24) | 0xC0);
527                 m_signature[m_currSig++] = (byte)((data >>16) & 0xFF);
528                 m_signature[m_currSig++] = (byte)((data >>8) & 0xFF);
529                 m_signature[m_currSig++] = (byte)((data) & 0xFF);
530             }
531             else
532             {
533                 throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger"));
534             }
535 
536         }
537 
AddData(uint data)538         private void AddData(uint data)
539         {
540             if (m_currSig + 4 > m_signature.Length)
541             {
542                 m_signature = ExpandArray(m_signature);
543             }
544 
545             m_signature[m_currSig++] = (byte)((data)     & 0xFF);
546             m_signature[m_currSig++] = (byte)((data>>8)  & 0xFF);
547             m_signature[m_currSig++] = (byte)((data>>16) & 0xFF);
548             m_signature[m_currSig++] = (byte)((data>>24) & 0xFF);
549         }
550 
AddData(ulong data)551         private void AddData(ulong data)
552         {
553             if (m_currSig + 8 > m_signature.Length)
554             {
555                 m_signature = ExpandArray(m_signature);
556             }
557 
558             m_signature[m_currSig++] = (byte)((data)     & 0xFF);
559             m_signature[m_currSig++] = (byte)((data>>8)  & 0xFF);
560             m_signature[m_currSig++] = (byte)((data>>16) & 0xFF);
561             m_signature[m_currSig++] = (byte)((data>>24) & 0xFF);
562             m_signature[m_currSig++] = (byte)((data>>32) & 0xFF);
563             m_signature[m_currSig++] = (byte)((data>>40) & 0xFF);
564             m_signature[m_currSig++] = (byte)((data>>48) & 0xFF);
565             m_signature[m_currSig++] = (byte)((data>>56) & 0xFF);
566         }
567 
AddElementType(CorElementType cvt)568         private void AddElementType(CorElementType cvt)
569         {
570             // Adds an element to the signature.  A managed represenation of CorSigCompressElement
571             if (m_currSig + 1 > m_signature.Length)
572                 m_signature = ExpandArray(m_signature);
573 
574             m_signature[m_currSig++] = (byte)cvt;
575         }
576 
AddToken(int token)577         private void AddToken(int token)
578         {
579             // A managed represenation of CompressToken
580             // Pulls the token appart to get a rid, adds some appropriate bits
581             // to the token and then adds this to the signature.
582 
583             int rid =  (token & 0x00FFFFFF); //This is RidFromToken;
584             MetadataTokenType type = (MetadataTokenType)(token & unchecked((int)0xFF000000)); //This is TypeFromToken;
585 
586             if (rid > 0x3FFFFFF)
587             {
588                 // token is too big to be compressed
589                 throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger"));
590             }
591 
592             rid = (rid << 2);
593 
594             // TypeDef is encoded with low bits 00
595             // TypeRef is encoded with low bits 01
596             // TypeSpec is encoded with low bits 10
597             if (type == MetadataTokenType.TypeRef)
598             {
599                 //if type is mdtTypeRef
600                 rid|=0x1;
601             }
602             else if (type == MetadataTokenType.TypeSpec)
603             {
604                 //if type is mdtTypeSpec
605                 rid|=0x2;
606             }
607 
608             AddData(rid);
609         }
610 
InternalAddTypeToken(TypeToken clsToken, CorElementType CorType)611         private void InternalAddTypeToken(TypeToken clsToken, CorElementType CorType)
612         {
613             // Add a type token into signature. CorType will be either CorElementType.Class or CorElementType.ValueType
614             AddElementType(CorType);
615             AddToken(clsToken.Token);
616         }
617 
618         [System.Security.SecurityCritical]  // auto-generated
InternalAddRuntimeType(Type type)619         private unsafe void InternalAddRuntimeType(Type type)
620         {
621             // Add a runtime type into the signature.
622 
623             AddElementType(CorElementType.Internal);
624 
625             IntPtr handle = type.GetTypeHandleInternal().Value;
626 
627             // Internal types must have their pointer written into the signature directly (we don't
628             // want to convert to little-endian format on big-endian machines because the value is
629             // going to be extracted and used directly as a pointer (and only within this process)).
630 
631             if (m_currSig + sizeof(void*) > m_signature.Length)
632                 m_signature = ExpandArray(m_signature);
633 
634             byte *phandle = (byte*)&handle;
635             for (int i = 0; i < sizeof(void*); i++)
636                 m_signature[m_currSig++] = phandle[i];
637         }
638 
ExpandArray(byte[] inArray)639         private byte[] ExpandArray(byte[] inArray)
640         {
641             // Expand the signature buffer size
642             return ExpandArray(inArray, inArray.Length * 2);
643         }
644 
ExpandArray(byte[] inArray, int requiredLength)645         private byte[] ExpandArray(byte[] inArray, int requiredLength)
646         {
647             // Expand the signature buffer size
648 
649             if (requiredLength < inArray.Length)
650                 requiredLength = inArray.Length*2;
651 
652             byte[] outArray = new byte[requiredLength];
653             Array.Copy(inArray, outArray, inArray.Length);
654             return outArray;
655         }
656 
IncrementArgCounts()657         private void IncrementArgCounts()
658         {
659             if (m_sizeLoc == NO_SIZE_IN_SIG)
660             {
661                 //We don't have a size if this is a field.
662                 return;
663             }
664 
665             m_argCount++;
666         }
667 
SetNumberOfSignatureElements(bool forceCopy)668         private void SetNumberOfSignatureElements(bool forceCopy)
669         {
670             // For most signatures, this will set the number of elements in a byte which we have reserved for it.
671             // However, if we have a field signature, we don't set the length and return.
672             // If we have a signature with more than 128 arguments, we can't just set the number of elements,
673             // we actually have to allocate more space (e.g. shift everything in the array one or more spaces to the
674             // right.  We do this by making a copy of the array and leaving the correct number of blanks.  This new
675             // array is now set to be m_signature and we use the AddData method to set the number of elements properly.
676             // The forceCopy argument can be used to force SetNumberOfSignatureElements to make a copy of
677             // the array.  This is useful for GetSignature which promises to trim the array to be the correct size anyway.
678 
679             byte[] temp;
680             int newSigSize;
681             int currSigHolder = m_currSig;
682 
683             if (m_sizeLoc == NO_SIZE_IN_SIG)
684                 return;
685 
686             //If we have fewer than 128 arguments and we haven't been told to copy the
687             //array, we can just set the appropriate bit and return.
688             if (m_argCount < 0x80 && !forceCopy)
689             {
690                 m_signature[m_sizeLoc] = (byte)m_argCount;
691                 return;
692             }
693 
694             //We need to have more bytes for the size.  Figure out how many bytes here.
695             //Since we need to copy anyway, we're just going to take the cost of doing a
696             //new allocation.
697             if (m_argCount < 0x80)
698             {
699                 newSigSize = 1;
700             }
701             else if (m_argCount < 0x4000)
702             {
703                 newSigSize = 2;
704             }
705             else
706             {
707                 newSigSize = 4;
708             }
709 
710             //Allocate the new array.
711             temp = new byte[m_currSig + newSigSize - 1];
712 
713             //Copy the calling convention.  The calling convention is always just one byte
714             //so we just copy that byte.  Then copy the rest of the array, shifting everything
715             //to make room for the new number of elements.
716             temp[0] = m_signature[0];
717             Array.Copy(m_signature, m_sizeLoc + 1, temp, m_sizeLoc + newSigSize, currSigHolder - (m_sizeLoc + 1));
718             m_signature = temp;
719 
720             //Use the AddData method to add the number of elements appropriately compressed.
721             m_currSig = m_sizeLoc;
722             AddData(m_argCount);
723             m_currSig = currSigHolder + (newSigSize - 1);
724         }
725 
726         #endregion
727 
728         #region Internal Members
729         internal int ArgumentCount
730         {
731             get
732             {
733                 return m_argCount;
734             }
735         }
736 
IsSimpleType(CorElementType type)737         internal static bool IsSimpleType(CorElementType type)
738         {
739             if (type <= CorElementType.String)
740                 return true;
741 
742             if (type == CorElementType.TypedByRef || type == CorElementType.I || type == CorElementType.U || type == CorElementType.Object)
743                 return true;
744 
745             return false;
746         }
747 
InternalGetSignature(out int length)748         internal byte[] InternalGetSignature(out int length)
749         {
750             // An internal method to return the signature.  Does not trim the
751             // array, but passes out the length of the array in an out parameter.
752             // This is the actual array -- not a copy -- so the callee must agree
753             // to not copy it.
754             //
755             // param length : an out param indicating the length of the array.
756             // return : A reference to the internal ubyte array.
757 
758             if (!m_sigDone)
759             {
760                 m_sigDone = true;
761 
762                 // If we have more than 128 variables, we can't just set the length, we need
763                 // to compress it.  Unfortunately, this means that we need to copy the entire
764                 // array.  Bummer, eh?
765                 SetNumberOfSignatureElements(false);
766             }
767 
768             length = m_currSig;
769             return m_signature;
770         }
771 
772 
773 
774 
InternalGetSignatureArray()775         internal byte[] InternalGetSignatureArray()
776         {
777             int argCount = m_argCount;
778             int currSigLength = m_currSig;
779             int newSigSize = currSigLength;
780 
781             //Allocate the new array.
782             if (argCount < 0x7F)
783                 newSigSize += 1;
784             else if (argCount < 0x3FFF)
785                 newSigSize += 2;
786             else
787                 newSigSize += 4;
788             byte[] temp = new byte[newSigSize];
789 
790             // copy the sig
791             int sigCopyIndex = 0;
792             // calling convention
793             temp[sigCopyIndex++] = m_signature[0];
794             // arg size
795             if (argCount <= 0x7F)
796                 temp[sigCopyIndex++] = (byte)(argCount & 0xFF);
797             else if (argCount <= 0x3FFF)
798             {
799                 temp[sigCopyIndex++] = (byte)((argCount >>8) | 0x80);
800                 temp[sigCopyIndex++] = (byte)(argCount & 0xFF);
801             }
802             else if (argCount <= 0x1FFFFFFF)
803             {
804                 temp[sigCopyIndex++] = (byte)((argCount >>24) | 0xC0);
805                 temp[sigCopyIndex++] = (byte)((argCount >>16) & 0xFF);
806                 temp[sigCopyIndex++] = (byte)((argCount >>8) & 0xFF);
807                 temp[sigCopyIndex++] = (byte)((argCount) & 0xFF);
808             }
809             else
810                 throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger"));
811             // copy the sig part of the sig
812             Array.Copy(m_signature, 2, temp, sigCopyIndex, currSigLength - 2);
813             // mark the end of sig
814             temp[newSigSize - 1] = (byte)CorElementType.End;
815 
816             return temp;
817         }
818 
819         #endregion
820 
821         #region Public Methods
AddArgument(Type clsArgument)822         public void AddArgument(Type clsArgument)
823         {
824             AddArgument(clsArgument, null, null);
825         }
826 
827         [System.Security.SecuritySafeCritical]  // auto-generated
AddArgument(Type argument, bool pinned)828         public void AddArgument(Type argument, bool pinned)
829         {
830             if (argument == null)
831                 throw new ArgumentNullException("argument");
832 
833             IncrementArgCounts();
834             AddOneArgTypeHelper(argument, pinned);
835         }
836 
AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)837         public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
838         {
839             if (requiredCustomModifiers != null && (arguments == null || requiredCustomModifiers.Length != arguments.Length))
840                 throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "requiredCustomModifiers", "arguments"));
841 
842             if (optionalCustomModifiers != null && (arguments == null || optionalCustomModifiers.Length != arguments.Length))
843                 throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "optionalCustomModifiers", "arguments"));
844 
845             if (arguments != null)
846             {
847                 for (int i =0; i < arguments.Length; i++)
848                 {
849                     AddArgument(arguments[i],
850                         requiredCustomModifiers == null ? null : requiredCustomModifiers[i],
851                         optionalCustomModifiers == null ? null : optionalCustomModifiers[i]);
852                 }
853             }
854         }
855 
856         [System.Security.SecuritySafeCritical]  // auto-generated
AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)857         public void AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
858         {
859             if (m_sigDone)
860                 throw new ArgumentException(Environment.GetResourceString("Argument_SigIsFinalized"));
861 
862             if (argument == null)
863                 throw new ArgumentNullException("argument");
864 
865             IncrementArgCounts();
866 
867             // Add an argument to the signature. Takes a Type and determines whether it
868             // is one of the primitive types of which we have special knowledge or a more
869             // general class.  In the former case, we only add the appropriate short cut encoding,
870             // otherwise we will calculate proper description for the type.
871             AddOneArgTypeHelper(argument, requiredCustomModifiers, optionalCustomModifiers);
872         }
873 
AddSentinel()874         public void AddSentinel()
875         {
876             AddElementType(CorElementType.Sentinel);
877         }
878 
Equals(Object obj)879         public override bool Equals(Object obj)
880         {
881             if (!(obj is SignatureHelper))
882             {
883                 return false;
884             }
885 
886             SignatureHelper temp = (SignatureHelper)obj;
887 
888             if ( !temp.m_module.Equals(m_module) || temp.m_currSig!=m_currSig || temp.m_sizeLoc!=m_sizeLoc || temp.m_sigDone !=m_sigDone )
889             {
890                 return false;
891             }
892 
893             for (int i=0; i<m_currSig; i++)
894             {
895                 if (m_signature[i]!=temp.m_signature[i])
896                     return false;
897             }
898             return true;
899         }
900 
GetHashCode()901         public override int GetHashCode()
902         {
903             // Start the hash code with the hash code of the module and the values of the member variables.
904             int HashCode = m_module.GetHashCode() + m_currSig + m_sizeLoc;
905 
906             // Add one if the sig is done.
907             if (m_sigDone)
908                 HashCode += 1;
909 
910             // Then add the hash code of all the arguments.
911             for (int i=0; i < m_currSig; i++)
912                 HashCode += m_signature[i].GetHashCode();
913 
914             return HashCode;
915         }
916 
GetSignature()917         public byte[] GetSignature()
918         {
919             return GetSignature(false);
920         }
921 
GetSignature(bool appendEndOfSig)922         internal byte[] GetSignature(bool appendEndOfSig)
923         {
924             // Chops the internal signature to the appropriate length.  Adds the
925             // end token to the signature and marks the signature as finished so that
926             // no further tokens can be added. Return the full signature in a trimmed array.
927             if (!m_sigDone)
928             {
929                 if (appendEndOfSig)
930                     AddElementType(CorElementType.End);
931                 SetNumberOfSignatureElements(true);
932                 m_sigDone = true;
933             }
934 
935             // This case will only happen if the user got the signature through
936             // InternalGetSignature first and then called GetSignature.
937             if (m_signature.Length > m_currSig)
938             {
939                 byte[] temp = new byte[m_currSig];
940                 Array.Copy(m_signature, temp, m_currSig);
941                 m_signature = temp;
942             }
943 
944             return m_signature;
945         }
946 
ToString()947         public override String ToString()
948         {
949             StringBuilder sb = new StringBuilder();
950             sb.Append("Length: " + m_currSig + Environment.NewLine);
951 
952             if (m_sizeLoc != -1)
953             {
954                 sb.Append("Arguments: " + m_signature[m_sizeLoc] + Environment.NewLine);
955             }
956             else
957             {
958                 sb.Append("Field Signature" + Environment.NewLine);
959             }
960 
961             sb.Append("Signature: " + Environment.NewLine);
962             for (int i=0; i<=m_currSig; i++)
963             {
964                 sb.Append(m_signature[i] + "  ");
965             }
966 
967             sb.Append(Environment.NewLine);
968             return sb.ToString();
969         }
970 
971         #endregion
972 
973 #if !FEATURE_CORECLR
_SignatureHelper.GetTypeInfoCount(out uint pcTInfo)974         void _SignatureHelper.GetTypeInfoCount(out uint pcTInfo)
975         {
976             throw new NotImplementedException();
977         }
978 
_SignatureHelper.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)979         void _SignatureHelper.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
980         {
981             throw new NotImplementedException();
982         }
983 
_SignatureHelper.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)984         void _SignatureHelper.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
985         {
986             throw new NotImplementedException();
987         }
988 
_SignatureHelper.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)989         void _SignatureHelper.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
990         {
991             throw new NotImplementedException();
992         }
993 #endif
994 
995     }
996 }
997 
998 
999 
1000 
1001 
1002 
1003 
1004 
1005 
1006 
1007 
1008 
1009 
1010 
1011 
1012 
1013 
1014 
1015 
1016 
1017 
1018 
1019 
1020 
1021 
1022