Making sure mono_marshal_free is used instead of g_free in mono_string_builder_to_utf8
[mono.git] / mcs / class / referencesource / System / compmod / system / componentmodel / design / DesigntimeLicenseContext.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="DesigntimeLicenseContext.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 namespace System.ComponentModel.Design {
8     using System.Runtime.Remoting;
9     using System.Diagnostics;
10     using System;
11     using Microsoft.Win32;
12     using System.Net;
13     using System.IO;
14     using System.Reflection;
15     using System.Collections;
16     using System.ComponentModel;
17     using System.Globalization;
18     using System.Security;
19     using System.Security.Permissions;
20
21     /// <devdoc>
22     ///    <para>
23     ///       Provides design-time support for licensing.
24     ///    </para>
25     /// </devdoc>
26     [HostProtection(SharedState = true)]
27     [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.InheritanceDemand, Name = "FullTrust")]
28     [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
29     public class DesigntimeLicenseContext : LicenseContext {
30         internal Hashtable savedLicenseKeys = new Hashtable();
31
32         /// <devdoc>
33         ///    <para>
34         ///       Gets or sets the license usage mode.
35         ///    </para>
36         /// </devdoc>
37         public override LicenseUsageMode UsageMode { 
38             get {
39                 return LicenseUsageMode.Designtime;
40             }
41         }
42         /// <devdoc>
43         ///    <para>
44         ///       Gets a saved license key.
45         ///    </para>
46         /// </devdoc>
47         public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly) {
48             return null;
49         }
50         /// <devdoc>
51         ///    <para>
52         ///       Sets a saved license key.
53         ///    </para>
54         /// </devdoc>
55         public override void SetSavedLicenseKey(Type type, string key) {
56             savedLicenseKeys[type.AssemblyQualifiedName] = key;
57         }
58     }
59
60     [HostProtection(SharedState = true)]
61     internal class RuntimeLicenseContext : LicenseContext
62     {
63         private static TraceSwitch RuntimeLicenseContextSwitch = new TraceSwitch("RuntimeLicenseContextTrace", "RuntimeLicenseContext tracing");
64         const int ReadBlock = 400;
65
66         internal Hashtable savedLicenseKeys;
67
68         /// <devdoc>
69         ///     This method takes a file URL and converts it to a local path.  The trick here is that
70         ///     if there is a '#' in the path, everything after this is treated as a fragment.  So
71         ///     we need to append the fragment to the end of the path.
72         /// </devdoc>
73         private string GetLocalPath(string fileName) {
74             System.Diagnostics.Debug.Assert(fileName != null && fileName.Length > 0, "Cannot get local path, fileName is not valid");
75
76             Uri uri = new Uri(fileName);
77             return uri.LocalPath + uri.Fragment;
78         }
79
80         public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly) {
81
82             if (savedLicenseKeys == null || savedLicenseKeys[type.AssemblyQualifiedName]==null) {
83                 Debug.WriteLineIf(RuntimeLicenseContextSwitch.TraceVerbose, "savedLicenseKey is null or doesnt contain our type");
84                 if (savedLicenseKeys == null) {
85                     savedLicenseKeys = new Hashtable();
86                 }
87                 
88                 Uri licenseFile = null;
89
90                 if (resourceAssembly == null) {
91                     Debug.WriteLineIf(RuntimeLicenseContextSwitch.TraceVerbose,"resourceAssembly is null");
92                     string rawFile = (string)AppDomain.CurrentDomain.SetupInformation.LicenseFile;
93                     Debug.WriteLineIf(RuntimeLicenseContextSwitch.TraceVerbose,"rawfile: " + rawFile);
94                     string codeBase;
95                     
96 #if !DISABLE_CAS_USE
97                     // FileIOPermission is required for ApplicationBase in URL-hosted domains
98                     FileIOPermission perm = new FileIOPermission(PermissionState.Unrestricted);
99                     perm.Assert();
100                     try {
101                         codeBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
102                     }
103                     finally {
104                         CodeAccessPermission.RevertAssert();
105                     }
106 #else
107                     codeBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
108 #endif
109                     if (rawFile != null && codeBase != null) {
110                         licenseFile = new Uri(new Uri(codeBase), rawFile);
111                     }
112                 }
113
114                 if (licenseFile == null) {
115                     if(resourceAssembly == null) {
116                         resourceAssembly = Assembly.GetEntryAssembly();
117                     }
118
119                     if (resourceAssembly == null) {
120                         Debug.WriteLineIf(RuntimeLicenseContextSwitch.TraceVerbose,"resourceAssembly is null");
121                         // If Assembly.EntryAssembly returns null, then we will 
122                         // try everything!
123                         // 
124                         foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) {
125
126                             // Though, I could not repro this, we seem to be hitting an AssemblyBuilder
127                             // when walking through all the assemblies in the current app domain. This throws an 
128                             // exception on Assembly.CodeBase and we bail out. Catching exceptions here is not a 
129                             // bad thing.
130                             if (asm.IsDynamic)
131                                 continue;
132
133                             // file://fullpath/foo.exe
134                             //
135                             string fileName;
136 #if !DISABLE_CAS_USE
137                             FileIOPermission perm = new FileIOPermission(PermissionState.Unrestricted);
138                             perm.Assert();
139                             try
140                             {
141                                 fileName = GetLocalPath(asm.EscapedCodeBase);
142                                 fileName = new FileInfo(fileName).Name;
143                             }
144                             finally
145                             {
146                                 CodeAccessPermission.RevertAssert();
147                             }
148 #else
149                             fileName = GetLocalPath(asm.EscapedCodeBase);
150                             fileName = new FileInfo(fileName).Name;
151 #endif
152
153                             Stream s = asm.GetManifestResourceStream(fileName + ".licenses");
154                             if (s == null) {
155                                 //Since the casing may be different depending on how the assembly was loaded, 
156                                 //we'll do a case insensitive lookup for this manifest resource stream...
157                                 s = CaseInsensitiveManifestResourceStreamLookup(asm, fileName + ".licenses");
158                             }
159                             
160                             if (s != null) {
161                                 DesigntimeLicenseContextSerializer.Deserialize(s, fileName.ToUpper(CultureInfo.InvariantCulture), this);
162                                 break;
163                             }
164                         }
165                     }
166                     else if(!resourceAssembly.IsDynamic) { // EscapedCodeBase won't be supported by emitted assemblies anyway
167                         Debug.WriteLineIf(RuntimeLicenseContextSwitch.TraceVerbose,"resourceAssembly is not null");
168                         string fileName;
169                         FileIOPermission perm = new FileIOPermission(PermissionState.Unrestricted);
170                         perm.Assert();
171                         try
172                         {
173                             fileName = GetLocalPath(resourceAssembly.EscapedCodeBase);
174                         }
175                         finally
176                         {
177                             CodeAccessPermission.RevertAssert();
178                         }
179                         fileName = Path.GetFileName(fileName); // we don't want to use FileInfo here... it requests FileIOPermission that we
180                         // might now have... see VSWhidbey 527758
181                         string licResourceName = fileName + ".licenses";
182                         // first try the filename
183                         Stream s = resourceAssembly.GetManifestResourceStream(licResourceName);
184                         if (s == null) {
185                             string resolvedName = null;
186                             CompareInfo comparer = CultureInfo.InvariantCulture.CompareInfo;
187                             string shortAssemblyName = resourceAssembly.GetName().Name;
188                             //  if the assembly has been renamed, we try our best to find a good match in the available resources
189                             // by looking at the assembly name (which doesn't change even after a file rename) + ".exe.licenses" or + ".dll.licenses"
190                             foreach(String existingName in resourceAssembly.GetManifestResourceNames()) {
191                                 if (comparer.Compare(existingName, licResourceName, CompareOptions.IgnoreCase) == 0 ||
192                                  comparer.Compare(existingName, shortAssemblyName + ".exe.licenses", CompareOptions.IgnoreCase) == 0 || 
193                                  comparer.Compare(existingName, shortAssemblyName + ".dll.licenses", CompareOptions.IgnoreCase) == 0) {
194                                     resolvedName = existingName;
195                                     break;
196                                 }
197                             }
198                             if (resolvedName != null) {
199                                 s = resourceAssembly.GetManifestResourceStream(resolvedName);
200                             }
201                         }
202                         if (s != null) {
203                             DesigntimeLicenseContextSerializer.Deserialize(s, fileName.ToUpper(CultureInfo.InvariantCulture), this);
204                         }
205                     }
206                 }
207
208
209                 if (licenseFile != null) {
210                     Debug.WriteLineIf(RuntimeLicenseContextSwitch.TraceVerbose,"licenseFile: " + licenseFile.ToString());
211                     Debug.WriteLineIf(RuntimeLicenseContextSwitch.TraceVerbose,"opening licenses file over URI " + licenseFile.ToString());
212                     Stream s = OpenRead(licenseFile);
213                     if (s != null) {
214                         string[] segments = licenseFile.Segments;
215                         string licFileName = segments[segments.Length - 1];
216                         string key = licFileName.Substring(0, licFileName.LastIndexOf("."));
217                         DesigntimeLicenseContextSerializer.Deserialize(s, key.ToUpper(CultureInfo.InvariantCulture), this);
218                     }
219                 }
220
221             }
222             Debug.WriteLineIf(RuntimeLicenseContextSwitch.TraceVerbose,"returning : " + (string)savedLicenseKeys[type.AssemblyQualifiedName]);
223             return(string)savedLicenseKeys[type.AssemblyQualifiedName];
224         }
225
226         /**
227         * Looks up a .licenses file in the assembly manifest using 
228         * case-insensitive lookup rules.  We do this because the name
229         * we are attempting to locate could have different casing 
230         * depending on how the assembly was loaded.
231         **/
232         private Stream CaseInsensitiveManifestResourceStreamLookup(Assembly satellite, string name)
233         {
234             CompareInfo comparer = CultureInfo.InvariantCulture.CompareInfo;
235             
236             //loop through the resource names in the assembly
237             // we try to handle the case where the assembly file name has been renamed
238             // by trying to guess the original file name based on the assembly name...
239             string assemblyShortName = satellite.GetName().Name;
240             foreach(string existingName in satellite.GetManifestResourceNames()) {
241                 if (comparer.Compare(existingName, name, CompareOptions.IgnoreCase) == 0 ||
242                     comparer.Compare(existingName, assemblyShortName + ".exe.licenses") == 0 ||
243                     comparer.Compare(existingName, assemblyShortName + ".dll.licenses") == 0) {
244                     name = existingName;
245                     break;
246                 }
247             }
248
249             //finally, attempt to return our stream based on the 
250             //case insensitive match we found
251             //
252             return satellite.GetManifestResourceStream(name);
253         }
254
255         static Stream OpenRead(Uri resourceUri) {
256             Stream result = null;
257 #if !DISABLE_CAS_USE
258             PermissionSet perms = new PermissionSet(PermissionState.Unrestricted);
259
260             perms.Assert();
261 #endif
262             try {
263                 WebClient webClient = new WebClient();
264                 webClient.Credentials = CredentialCache.DefaultCredentials;
265                 result = webClient.OpenRead(resourceUri.ToString());
266             }
267             catch (Exception e) {
268                 Debug.Fail(e.ToString());
269             }
270 #if !DISABLE_CAS_USE
271             finally {
272                 CodeAccessPermission.RevertAssert();
273             }
274 #endif
275             return result;
276         }
277     }
278 }
279
280