Merge pull request #3386 from alexanderkyte/nunit_lite_return_status
[mono.git] / mcs / class / referencesource / System.Web / Util / Misc.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="FileChangesMonitor.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 namespace System.Web.Util {
8     using System;
9     using System.Diagnostics.CodeAnalysis;
10     using System.Globalization;
11     using System.Runtime.InteropServices;
12     using System.Security.Permissions;
13     using System.Text;
14     using System.Web.Hosting;
15     using Microsoft.Win32;
16
17     internal sealed class Misc {
18
19         const string APPLICATION_ID  = "\r\n\r\nApplication ID: ";
20         const string PROCESS_ID      = "\r\n\r\nProcess ID: ";
21         const string EXCEPTION       = "\r\n\r\nException: ";
22         const string INNER_EXCEPTION = "\r\n\r\nInnerException: ";
23         const string MESSAGE         = "\r\n\r\nMessage: ";
24         const string STACK_TRACE     = "\r\n\r\nStackTrace: ";
25
26         static StringComparer s_caseInsensitiveInvariantKeyComparer;
27
28         internal static StringComparer CaseInsensitiveInvariantKeyComparer {
29             get {
30                 if (s_caseInsensitiveInvariantKeyComparer == null) {
31                     s_caseInsensitiveInvariantKeyComparer = StringComparer.Create(CultureInfo.InvariantCulture, true);
32                 }
33
34                 return s_caseInsensitiveInvariantKeyComparer;
35             }
36         }
37
38         [SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Int32.ToString(System.IFormatProvider)",
39             Justification = "This is the proper culture for writing to the event log.")]
40         internal static void WriteUnhandledExceptionToEventLog(AppDomain appDomain, Exception exception) {
41             if (appDomain == null || exception == null) {
42                 return;
43             }
44
45             ProcessImpersonationContext imperContext = null;
46             try {
47                 imperContext = new ProcessImpersonationContext();
48                 String appId = appDomain.GetData(".appId") as String;
49                 if (appId == null) {
50                     appId = appDomain.FriendlyName;
51                 }
52                 string pid = SafeNativeMethods.GetCurrentProcessId().ToString(CultureInfo.InstalledUICulture);
53                 string description = SR.Resources.GetString(SR.Unhandled_Exception, CultureInfo.InstalledUICulture);
54                 Misc.ReportUnhandledException(exception, new string[5] {description, APPLICATION_ID, appId, PROCESS_ID, pid});
55             }
56             catch {
57                 // ignore exceptions so that WriteErrorToEventLog never throws
58             }
59             finally {
60                 if (imperContext != null) {
61                     imperContext.Undo();
62                 }
63             }
64         }
65
66         internal static void ReportUnhandledException(Exception e, String[] strings) {
67             UnsafeNativeMethods.ReportUnhandledException(FormatExceptionMessage(e, strings));
68         }
69
70         internal static String FormatExceptionMessage(Exception e, String[] strings) {
71             StringBuilder sb = new StringBuilder(4096);
72             for (int i = 0; i < strings.Length; i++) {
73                 sb.Append(strings[i]);
74             }
75             for (Exception current = e; current != null; current = current.InnerException) {
76                 if (current == e) 
77                     sb.Append(EXCEPTION);
78                 else
79                     sb.Append(INNER_EXCEPTION);
80                 sb.Append(current.GetType().FullName);
81                 sb.Append(MESSAGE);
82                 sb.Append(current.Message);
83                 sb.Append(STACK_TRACE);
84                 sb.Append(current.StackTrace);                    
85             }
86
87             return sb.ToString();
88         }
89
90         internal unsafe static void CopyMemory(IntPtr src, int srcOffset, byte[] dest, int destOffset, int size) {
91             // 
92             System.Runtime.InteropServices.Marshal.Copy(new IntPtr(src.ToInt64()+srcOffset), dest, destOffset, size);
93         }
94
95         internal unsafe static void CopyMemory(byte[] src, int srcOffset, IntPtr dest, int destOffset, int size) {
96             // 
97             System.Runtime.InteropServices.Marshal.Copy(src, srcOffset, new IntPtr(dest.ToInt64()+destOffset), size);
98         }
99
100         internal unsafe static void CopyMemory(IntPtr src, int srcOffset, IntPtr dest, int destOffset, int size) {
101             byte *s = ((byte*)src) + srcOffset;
102             byte *d = ((byte*)dest) + destOffset;
103             StringUtil.memcpyimpl(s, d, size);
104         }
105
106         internal static void ThrowIfFailedHr(int hresult) {
107             // SUCCEEDED >= 0
108             // FAILED < 0
109             if (hresult < 0) {
110                 Marshal.ThrowExceptionForHR(hresult);
111             }
112         }
113
114         internal static IProcessHostSupportFunctions CreateLocalSupportFunctions(IProcessHostSupportFunctions proxyFunctions) {
115             IProcessHostSupportFunctions localFunctions = null;
116
117             // get the underlying COM object
118             IntPtr pUnk = Marshal.GetIUnknownForObject(proxyFunctions);
119
120             // this object isn't a COM object
121             if (IntPtr.Zero == pUnk) {
122                 return null;
123             }
124             
125             IntPtr ppv = IntPtr.Zero;
126             try {
127                 // QI it for the interface
128                 Guid g = typeof(IProcessHostSupportFunctions).GUID;
129
130                 int hresult = Marshal.QueryInterface(pUnk, ref g, out ppv);
131                 if (hresult < 0)  {
132                     Marshal.ThrowExceptionForHR(hresult);
133                 }
134
135                 // create a RCW we can hold onto in this domain
136                 // this bumps the ref count so we can drop our refs on the raw interfaces
137                 localFunctions = (IProcessHostSupportFunctions)Marshal.GetObjectForIUnknown(ppv);
138             }
139             finally {
140                 // drop our explicit refs and keep the managed instance
141                 if (IntPtr.Zero != ppv) {
142                     Marshal.Release(ppv);
143                 }
144                 if (IntPtr.Zero != pUnk) {
145                     Marshal.Release(pUnk);
146                 }
147             }
148
149             return localFunctions;
150         }
151
152
153         // Open ASP.NET's reg key, or one of its subkeys
154         internal static RegistryKey OpenAspNetRegKey(string subKey) {
155             String ver = VersionInfo.SystemWebVersion;
156
157             // Zero out minor version number VSWhidbey 602541
158             // Eg. 2.0.50727.42 becomes 2.0.50727.0
159             if (!string.IsNullOrEmpty(ver)) {
160                 int pos = ver.LastIndexOf('.');
161                 if (pos > -1) {
162                     ver = ver.Substring(0, pos + 1) + "0";
163                 }
164             }
165  
166             // The main ASP.NET reg key
167             string key = @"Software\Microsoft\ASP.NET\" + ver;
168
169             // If we're asked for a subkey, append it
170             if (subKey != null)
171                 key += @"\" + subKey;
172
173             // Open and return the key
174             return Registry.LocalMachine.OpenSubKey(key);
175         }
176
177         // Get an ASP.NET registry value, from the main key or a subkey
178         // The Registry class does a full demand, so we'll turn it into a LinkDemand
179         [RegistryPermission(SecurityAction.LinkDemand, Unrestricted = true)]
180         [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
181         internal static object GetAspNetRegValue(string subKey, string valueName, object defaultValue) {
182             try {
183                 using (RegistryKey regKey = OpenAspNetRegKey(subKey)) {
184
185                     // Return the default value if the key doesn't exist
186                     if (regKey == null)
187                         return defaultValue;
188
189                     return regKey.GetValue(valueName, defaultValue);
190                 }
191             }
192             catch {
193                 // Return the default value if anything goes wrong
194                 return defaultValue;
195             }
196         }
197
198     }
199 }
200
201