~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/reflect/Fusion.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2010-2012 Jeroen Frijters
 
3
  Copyright (C) 2011 Marek Safar
 
4
 
 
5
  This software is provided 'as-is', without any express or implied
 
6
  warranty.  In no event will the authors be held liable for any damages
 
7
  arising from the use of this software.
 
8
 
 
9
  Permission is granted to anyone to use this software for any purpose,
 
10
  including commercial applications, and to alter it and redistribute it
 
11
  freely, subject to the following restrictions:
 
12
 
 
13
  1. The origin of this software must not be misrepresented; you must not
 
14
     claim that you wrote the original software. If you use this software
 
15
     in a product, an acknowledgment in the product documentation would be
 
16
     appreciated but is not required.
 
17
  2. Altered source versions must be plainly marked as such, and must not be
 
18
     misrepresented as being the original software.
 
19
  3. This notice may not be removed or altered from any source distribution.
 
20
 
 
21
  Jeroen Frijters
 
22
  jeroen@frijters.net
 
23
  
 
24
*/
 
25
 
 
26
using System;
 
27
using System.Runtime.InteropServices;
 
28
using System.Text;
 
29
 
 
30
namespace IKVM.Reflection
 
31
{
 
32
        struct ParsedAssemblyName
 
33
        {
 
34
                internal string Name;
 
35
                internal Version Version;
 
36
                internal string Culture;
 
37
                internal string PublicKeyToken;
 
38
                internal bool? Retargetable;
 
39
                internal ProcessorArchitecture ProcessorArchitecture;
 
40
                internal bool HasPublicKey;
 
41
                internal bool WindowsRuntime;
 
42
        }
 
43
 
 
44
        enum ParseAssemblyResult
 
45
        {
 
46
                OK,
 
47
                GenericError,
 
48
                DuplicateKey,
 
49
        }
 
50
 
 
51
        static class Fusion
 
52
        {
 
53
                internal static bool CompareAssemblyIdentityNative(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result)
 
54
                {
 
55
                        bool equivalent;
 
56
                        Marshal.ThrowExceptionForHR(CompareAssemblyIdentity(assemblyIdentity1, unified1, assemblyIdentity2, unified2, out equivalent, out result));
 
57
                        return equivalent;
 
58
                }
 
59
 
 
60
                [DllImport("fusion", CharSet = CharSet.Unicode)]
 
61
                private static extern int CompareAssemblyIdentity(string pwzAssemblyIdentity1, bool fUnified1, string pwzAssemblyIdentity2, bool fUnified2, out bool pfEquivalent, out AssemblyComparisonResult pResult);
 
62
 
 
63
                // internal for use by mcs
 
64
                internal static bool CompareAssemblyIdentityPure(string assemblyIdentity1, bool unified1, string assemblyIdentity2, bool unified2, out AssemblyComparisonResult result)
 
65
                {
 
66
                        ParsedAssemblyName name1;
 
67
                        ParsedAssemblyName name2;
 
68
 
 
69
                        ParseAssemblyResult r = ParseAssemblyName(assemblyIdentity1, out name1);
 
70
                        if (r != ParseAssemblyResult.OK || (r = ParseAssemblyName(assemblyIdentity2, out name2)) != ParseAssemblyResult.OK)
 
71
                        {
 
72
                                result = AssemblyComparisonResult.NonEquivalent;
 
73
                                switch (r)
 
74
                                {
 
75
                                        case ParseAssemblyResult.DuplicateKey:
 
76
                                                throw new System.IO.FileLoadException();
 
77
                                        case ParseAssemblyResult.GenericError:
 
78
                                        default:
 
79
                                                throw new ArgumentException();
 
80
                                }
 
81
                        }
 
82
 
 
83
                        bool partial = IsPartial(name1);
 
84
 
 
85
                        if ((partial && unified1) || IsPartial(name2))
 
86
                        {
 
87
                                result = AssemblyComparisonResult.NonEquivalent;
 
88
                                throw new ArgumentException();
 
89
                        }
 
90
                        if (!name1.Name.Equals(name2.Name, StringComparison.InvariantCultureIgnoreCase))
 
91
                        {
 
92
                                result = AssemblyComparisonResult.NonEquivalent;
 
93
                                return false;
 
94
                        }
 
95
                        if (name1.Name.Equals("mscorlib", StringComparison.InvariantCultureIgnoreCase))
 
96
                        {
 
97
                                result = AssemblyComparisonResult.EquivalentFullMatch;
 
98
                                return true;
 
99
                        }
 
100
                        if (partial && name1.Culture == null)
 
101
                        {
 
102
                        }
 
103
                        else if (!name1.Culture.Equals(name2.Culture, StringComparison.InvariantCultureIgnoreCase))
 
104
                        {
 
105
                                result = AssemblyComparisonResult.NonEquivalent;
 
106
                                return false;
 
107
                        }
 
108
                        if (IsStrongNamed(name2))
 
109
                        {
 
110
                                if (partial && name1.PublicKeyToken == null)
 
111
                                {
 
112
                                }
 
113
                                else if (name1.PublicKeyToken != name2.PublicKeyToken)
 
114
                                {
 
115
                                        result = AssemblyComparisonResult.NonEquivalent;
 
116
                                        return false;
 
117
                                }
 
118
                                if (partial && name1.Version == null)
 
119
                                {
 
120
                                        result = AssemblyComparisonResult.EquivalentPartialMatch;
 
121
                                        return true;
 
122
                                }
 
123
                                else if (IsFrameworkAssembly(name2))
 
124
                                {
 
125
                                        result = partial ? AssemblyComparisonResult.EquivalentPartialFXUnified : AssemblyComparisonResult.EquivalentFXUnified;
 
126
                                        return true;
 
127
                                }
 
128
                                else if (name1.Version.Revision == -1 || name2.Version.Revision == -1)
 
129
                                {
 
130
                                        result = AssemblyComparisonResult.NonEquivalent;
 
131
                                        throw new ArgumentException();
 
132
                                }
 
133
                                else if (name1.Version < name2.Version)
 
134
                                {
 
135
                                        if (unified2)
 
136
                                        {
 
137
                                                result = partial ? AssemblyComparisonResult.EquivalentPartialUnified : AssemblyComparisonResult.EquivalentUnified;
 
138
                                                return true;
 
139
                                        }
 
140
                                        else
 
141
                                        {
 
142
                                                result = partial ? AssemblyComparisonResult.NonEquivalentPartialVersion : AssemblyComparisonResult.NonEquivalentVersion;
 
143
                                                return false;
 
144
                                        }
 
145
                                }
 
146
                                else if (name1.Version > name2.Version)
 
147
                                {
 
148
                                        if (unified1)
 
149
                                        {
 
150
                                                result = partial ? AssemblyComparisonResult.EquivalentPartialUnified : AssemblyComparisonResult.EquivalentUnified;
 
151
                                                return true;
 
152
                                        }
 
153
                                        else
 
154
                                        {
 
155
                                                result = partial ? AssemblyComparisonResult.NonEquivalentPartialVersion : AssemblyComparisonResult.NonEquivalentVersion;
 
156
                                                return false;
 
157
                                        }
 
158
                                }
 
159
                                else
 
160
                                {
 
161
                                        result = partial ? AssemblyComparisonResult.EquivalentPartialMatch : AssemblyComparisonResult.EquivalentFullMatch;
 
162
                                        return true;
 
163
                                }
 
164
                        }
 
165
                        else if (IsStrongNamed(name1))
 
166
                        {
 
167
                                result = AssemblyComparisonResult.NonEquivalent;
 
168
                                return false;
 
169
                        }
 
170
                        else
 
171
                        {
 
172
                                result = partial ? AssemblyComparisonResult.EquivalentPartialWeakNamed : AssemblyComparisonResult.EquivalentWeakNamed;
 
173
                                return true;
 
174
                        }
 
175
                }
 
176
 
 
177
                static bool IsFrameworkAssembly(ParsedAssemblyName name)
 
178
                {
 
179
                        // A list of FX assemblies which require some form of remapping
 
180
                        // When 4.0 + 1 version  is release, assemblies introduced in v4.0
 
181
                        // will have to be added
 
182
                        switch (name.Name)
 
183
                        {
 
184
                                case "System":
 
185
                                case "System.Core":
 
186
                                case "System.Data":
 
187
                                case "System.Data.DataSetExtensions":
 
188
                                case "System.Data.Linq":
 
189
                                case "System.Data.OracleClient":
 
190
                                case "System.Data.Services":
 
191
                                case "System.Data.Services.Client":
 
192
                                case "System.IdentityModel":
 
193
                                case "System.IdentityModel.Selectors":
 
194
                                case "System.Runtime.Remoting":
 
195
                                case "System.Runtime.Serialization":
 
196
                                case "System.ServiceModel":
 
197
                                case "System.Transactions":
 
198
                                case "System.Windows.Forms":
 
199
                                case "System.Xml":
 
200
                                case "System.Xml.Linq":
 
201
                                        return name.PublicKeyToken == "b77a5c561934e089";
 
202
 
 
203
                                case "System.Configuration":
 
204
                                case "System.Configuration.Install":
 
205
                                case "System.Design":
 
206
                                case "System.DirectoryServices":
 
207
                                case "System.Drawing":
 
208
                                case "System.Drawing.Design":
 
209
                                case "System.EnterpriseServices":
 
210
                                case "System.Management":
 
211
                                case "System.Messaging":
 
212
                                case "System.Runtime.Serialization.Formatters.Soap":
 
213
                                case "System.Security":
 
214
                                case "System.ServiceProcess":
 
215
                                case "System.Web":
 
216
                                case "System.Web.Mobile":
 
217
                                case "System.Web.Services":
 
218
                                        return name.PublicKeyToken == "b03f5f7f11d50a3a";
 
219
 
 
220
                                case "System.ComponentModel.DataAnnotations":
 
221
                                case "System.ServiceModel.Web":
 
222
                                case "System.Web.Abstractions":
 
223
                                case "System.Web.Extensions":
 
224
                                case "System.Web.Extensions.Design":
 
225
                                case "System.Web.DynamicData":
 
226
                                case "System.Web.Routing":
 
227
                                        return name.PublicKeyToken == "31bf3856ad364e35";
 
228
                        }
 
229
 
 
230
                        return false;
 
231
                }
 
232
 
 
233
                internal static ParseAssemblyResult ParseAssemblySimpleName(string fullName, out int pos, out string simpleName)
 
234
                {
 
235
                        StringBuilder sb = new StringBuilder();
 
236
                        pos = 0;
 
237
                        simpleName = null;
 
238
                        while (pos < fullName.Length && char.IsWhiteSpace(fullName[pos]))
 
239
                        {
 
240
                                pos++;
 
241
                        }
 
242
                        char quoteOrComma = ',';
 
243
                        if (pos < fullName.Length && (fullName[pos] == '\"' || fullName[pos] == '\''))
 
244
                        {
 
245
                                quoteOrComma = fullName[pos++];
 
246
                        }
 
247
                        while (pos < fullName.Length)
 
248
                        {
 
249
                                char ch = fullName[pos++];
 
250
                                if (ch == '\\')
 
251
                                {
 
252
                                        if (pos == fullName.Length)
 
253
                                        {
 
254
                                                return ParseAssemblyResult.GenericError;
 
255
                                        }
 
256
                                        ch = fullName[pos++];
 
257
                                        if (ch == '\\')
 
258
                                        {
 
259
                                                return ParseAssemblyResult.GenericError;
 
260
                                        }
 
261
                                }
 
262
                                else if (ch == quoteOrComma)
 
263
                                {
 
264
                                        if (ch != ',')
 
265
                                        {
 
266
                                                while (pos != fullName.Length)
 
267
                                                {
 
268
                                                        ch = fullName[pos++];
 
269
                                                        if (ch == ',')
 
270
                                                        {
 
271
                                                                break;
 
272
                                                        }
 
273
                                                        if (!char.IsWhiteSpace(ch))
 
274
                                                        {
 
275
                                                                return ParseAssemblyResult.GenericError;
 
276
                                                        }
 
277
                                                }
 
278
                                        }
 
279
                                        break;
 
280
                                }
 
281
                                else if (ch == '=' || (quoteOrComma == ',' && (ch == '\'' || ch == '"')))
 
282
                                {
 
283
                                        return ParseAssemblyResult.GenericError;
 
284
                                }
 
285
                                sb.Append(ch);
 
286
                        }
 
287
                        simpleName = sb.ToString().Trim();
 
288
                        if (simpleName.Length == 0)
 
289
                        {
 
290
                                return ParseAssemblyResult.GenericError;
 
291
                        }
 
292
                        if (pos == fullName.Length && fullName[fullName.Length - 1] == ',')
 
293
                        {
 
294
                                return ParseAssemblyResult.GenericError;
 
295
                        }
 
296
                        return ParseAssemblyResult.OK;
 
297
                }
 
298
 
 
299
                internal static ParseAssemblyResult ParseAssemblyName(string fullName, out ParsedAssemblyName parsedName)
 
300
                {
 
301
                        parsedName = new ParsedAssemblyName();
 
302
                        int pos;
 
303
                        ParseAssemblyResult res = ParseAssemblySimpleName(fullName, out pos, out parsedName.Name);
 
304
                        if (res != ParseAssemblyResult.OK || pos == fullName.Length)
 
305
                        {
 
306
                                return res;
 
307
                        }
 
308
                        else
 
309
                        {
 
310
                                System.Collections.Generic.Dictionary<string, string> unknownAttributes = null;
 
311
                                bool hasProcessorArchitecture = false;
 
312
                                bool hasContentType = false;
 
313
                                string[] parts = fullName.Substring(pos).Split(',');
 
314
                                for (int i = 0; i < parts.Length; i++)
 
315
                                {
 
316
                                        string[] kv = parts[i].Split('=');
 
317
                                        if (kv.Length != 2)
 
318
                                        {
 
319
                                                return ParseAssemblyResult.GenericError;
 
320
                                        }
 
321
                                        switch (kv[0].Trim().ToLowerInvariant())
 
322
                                        {
 
323
                                                case "version":
 
324
                                                        if (parsedName.Version != null)
 
325
                                                        {
 
326
                                                                return ParseAssemblyResult.DuplicateKey;
 
327
                                                        }
 
328
                                                        if (!ParseVersion(kv[1].Trim(), out parsedName.Version))
 
329
                                                        {
 
330
                                                                return ParseAssemblyResult.GenericError;
 
331
                                                        }
 
332
                                                        break;
 
333
                                                case "culture":
 
334
                                                        if (parsedName.Culture != null)
 
335
                                                        {
 
336
                                                                return ParseAssemblyResult.DuplicateKey;
 
337
                                                        }
 
338
                                                        if (!ParseCulture(kv[1].Trim(), out parsedName.Culture))
 
339
                                                        {
 
340
                                                                return ParseAssemblyResult.GenericError;
 
341
                                                        }
 
342
                                                        break;
 
343
                                                case "publickeytoken":
 
344
                                                        if (parsedName.PublicKeyToken != null)
 
345
                                                        {
 
346
                                                                return ParseAssemblyResult.DuplicateKey;
 
347
                                                        }
 
348
                                                        if (!ParsePublicKeyToken(kv[1].Trim(), out parsedName.PublicKeyToken))
 
349
                                                        {
 
350
                                                                return ParseAssemblyResult.GenericError;
 
351
                                                        }
 
352
                                                        break;
 
353
                                                case "publickey":
 
354
                                                        if (parsedName.PublicKeyToken != null)
 
355
                                                        {
 
356
                                                                return ParseAssemblyResult.DuplicateKey;
 
357
                                                        }
 
358
                                                        if (!ParsePublicKey(kv[1].Trim(), out parsedName.PublicKeyToken))
 
359
                                                        {
 
360
                                                                return ParseAssemblyResult.GenericError;
 
361
                                                        }
 
362
                                                        parsedName.HasPublicKey = true;
 
363
                                                        break;
 
364
                                                case "retargetable":
 
365
                                                        if (parsedName.Retargetable.HasValue)
 
366
                                                        {
 
367
                                                                return ParseAssemblyResult.DuplicateKey;
 
368
                                                        }
 
369
                                                        switch (kv[1].Trim().ToLowerInvariant())
 
370
                                                        {
 
371
                                                                case "yes":
 
372
                                                                        parsedName.Retargetable = true;
 
373
                                                                        break;
 
374
                                                                case "no":
 
375
                                                                        parsedName.Retargetable = false;
 
376
                                                                        break;
 
377
                                                                default:
 
378
                                                                        return ParseAssemblyResult.GenericError;
 
379
                                                        }
 
380
                                                        break;
 
381
                                                case "processorarchitecture":
 
382
                                                        if (hasProcessorArchitecture)
 
383
                                                        {
 
384
                                                                return ParseAssemblyResult.DuplicateKey;
 
385
                                                        }
 
386
                                                        hasProcessorArchitecture = true;
 
387
                                                        switch (kv[1].Trim().ToLowerInvariant())
 
388
                                                        {
 
389
                                                                case "none":
 
390
                                                                        parsedName.ProcessorArchitecture = ProcessorArchitecture.None;
 
391
                                                                        break;
 
392
                                                                case "msil":
 
393
                                                                        parsedName.ProcessorArchitecture = ProcessorArchitecture.MSIL;
 
394
                                                                        break;
 
395
                                                                case "x86":
 
396
                                                                        parsedName.ProcessorArchitecture = ProcessorArchitecture.X86;
 
397
                                                                        break;
 
398
                                                                case "ia64":
 
399
                                                                        parsedName.ProcessorArchitecture = ProcessorArchitecture.IA64;
 
400
                                                                        break;
 
401
                                                                case "amd64":
 
402
                                                                        parsedName.ProcessorArchitecture = ProcessorArchitecture.Amd64;
 
403
                                                                        break;
 
404
                                                                case "arm":
 
405
                                                                        parsedName.ProcessorArchitecture = ProcessorArchitecture.Arm;
 
406
                                                                        break;
 
407
                                                                default:
 
408
                                                                        return ParseAssemblyResult.GenericError;
 
409
                                                        }
 
410
                                                        break;
 
411
                                                case "contenttype":
 
412
                                                        if (hasContentType)
 
413
                                                        {
 
414
                                                                return ParseAssemblyResult.DuplicateKey;
 
415
                                                        }
 
416
                                                        hasContentType = true;
 
417
                                                        if (kv[1].Trim().ToLowerInvariant() != "windowsruntime")
 
418
                                                        {
 
419
                                                                return ParseAssemblyResult.GenericError;
 
420
                                                        }
 
421
                                                        parsedName.WindowsRuntime = true;
 
422
                                                        break;
 
423
                                                default:
 
424
                                                        if (kv[1].Trim() == "")
 
425
                                                        {
 
426
                                                                return ParseAssemblyResult.GenericError;
 
427
                                                        }
 
428
                                                        if (unknownAttributes == null)
 
429
                                                        {
 
430
                                                                unknownAttributes = new System.Collections.Generic.Dictionary<string, string>();
 
431
                                                        }
 
432
                                                        if (unknownAttributes.ContainsKey(kv[0].Trim().ToLowerInvariant()))
 
433
                                                        {
 
434
                                                                return ParseAssemblyResult.DuplicateKey;
 
435
                                                        }
 
436
                                                        unknownAttributes.Add(kv[0].Trim().ToLowerInvariant(), null);
 
437
                                                        break;
 
438
                                        }
 
439
                                }
 
440
                        }
 
441
                        return ParseAssemblyResult.OK;
 
442
                }
 
443
 
 
444
                private static bool ParseVersion(string str, out Version version)
 
445
                {
 
446
                        string[] parts = str.Split('.');
 
447
                        if (parts.Length < 2 || parts.Length > 4)
 
448
                        {
 
449
                                version = null;
 
450
                                ushort dummy;
 
451
                                // if the version consists of a single integer, it is invalid, but not invalid enough to fail the parse of the whole assembly name
 
452
                                return parts.Length == 1 && ushort.TryParse(parts[0], System.Globalization.NumberStyles.Integer, null, out dummy);
 
453
                        }
 
454
                        if (parts[0] == "" || parts[1] == "")
 
455
                        {
 
456
                                // this is a strange scenario, the version is invalid, but not invalid enough to fail the parse of the whole assembly name
 
457
                                version = null;
 
458
                                return true;
 
459
                        }
 
460
                        ushort major, minor, build = 65535, revision = 65535;
 
461
                        if (ushort.TryParse(parts[0], System.Globalization.NumberStyles.Integer, null, out major)
 
462
                                && ushort.TryParse(parts[1], System.Globalization.NumberStyles.Integer, null, out minor)
 
463
                                && (parts.Length <= 2 || parts[2] == "" || ushort.TryParse(parts[2], System.Globalization.NumberStyles.Integer, null, out build))
 
464
                                && (parts.Length <= 3 || parts[3] == "" || (parts[2] != "" && ushort.TryParse(parts[3], System.Globalization.NumberStyles.Integer, null, out revision))))
 
465
                        {
 
466
                                if (parts.Length == 4 && parts[3] != "" && parts[2] != "")
 
467
                                {
 
468
                                        version = new Version(major, minor, build, revision);
 
469
                                }
 
470
                                else if (parts.Length == 3 && parts[2] != "")
 
471
                                {
 
472
                                        version = new Version(major, minor, build);
 
473
                                }
 
474
                                else
 
475
                                {
 
476
                                        version = new Version(major, minor);
 
477
                                }
 
478
                                return true;
 
479
                        }
 
480
                        version = null;
 
481
                        return false;
 
482
                }
 
483
 
 
484
                private static bool ParseCulture(string str, out string culture)
 
485
                {
 
486
                        if (str == null)
 
487
                        {
 
488
                                culture = null;
 
489
                                return false;
 
490
                        }
 
491
                        culture = str;
 
492
                        return true;
 
493
                }
 
494
 
 
495
                private static bool ParsePublicKeyToken(string str, out string publicKeyToken)
 
496
                {
 
497
                        if (str == null)
 
498
                        {
 
499
                                publicKeyToken = null;
 
500
                                return false;
 
501
                        }
 
502
                        publicKeyToken = str.ToLowerInvariant();
 
503
                        return true;
 
504
                }
 
505
 
 
506
                private static bool ParsePublicKey(string str, out string publicKeyToken)
 
507
                {
 
508
                        if (str == null)
 
509
                        {
 
510
                                publicKeyToken = null;
 
511
                                return false;
 
512
                        }
 
513
                        publicKeyToken = AssemblyName.ComputePublicKeyToken(str);
 
514
                        return true;
 
515
                }
 
516
 
 
517
                private static bool IsPartial(ParsedAssemblyName name)
 
518
                {
 
519
                        return name.Version == null || name.Culture == null || name.PublicKeyToken == null;
 
520
                }
 
521
 
 
522
                private static bool IsStrongNamed(ParsedAssemblyName name)
 
523
                {
 
524
                        return name.PublicKeyToken != null && name.PublicKeyToken != "null";
 
525
                }
 
526
        }
 
527
}